[前][次][番号順一覧][スレッド一覧]

ruby-changes:23945

From: emboss <ko1@a...>
Date: Sun, 10 Jun 2012 03:16:34 +0900 (JST)
Subject: [ruby-changes:23945] emboss:r35996 (trunk): * ext/openssl/ossl.c: Fix error in example. Patch by David Albert.

emboss	2012-06-10 03:16:18 +0900 (Sun, 10 Jun 2012)

  New Revision: 35996

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=35996

  Log:
    * ext/openssl/ossl.c: Fix error in example. Patch by David Albert.
      
      Add/extend existing documentation. Examples now also cover RSA 
      signatures and PBKDF2.
      [ruby-core: 45154][ruby-trunk - Bug #6475]

  Modified files:
    trunk/ChangeLog
    trunk/ext/openssl/ossl.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 35995)
+++ ChangeLog	(revision 35996)
@@ -1,3 +1,12 @@
+Sun Jun 10 03:09:41 2012  Martin Bosslet  <Martin.Bosslet@g...>
+
+	* ext/openssl/ossl.c: Fix error in example. Patch by David Albert.
+	  
+	  Add/extend existing documentation. Examples now also cover RSA 
+	  signatures and PBKDF2.
+	  [ruby-core: 45154][ruby-trunk - Bug #6475]
+
+
 Sun Jun 10 01:41:45 2012  Martin Bosslet  <Martin.Bosslet@g...>
 
 	* ext/openssl/ossl_ssl.c: Introduce SSLContext#renegotiation_cb and
Index: ext/openssl/ossl.c
===================================================================
--- ext/openssl/ossl.c	(revision 35995)
+++ ext/openssl/ossl.c	(revision 35996)
@@ -455,7 +455,7 @@
  * ahold of the key may use it unless it is encrypted.  In order to securely
  * export a key you may export it with a pass phrase.
  *
- *   cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC'
+ *   cipher = OpenSSL::Cipher.new 'AES-128-CBC'
  *   pass_phrase = 'my secure pass phrase goes here'
  *
  *   key_secure = key.export cipher, pass_phrase
@@ -489,35 +489,126 @@
  *
  * == RSA Encryption
  *
- * RSA provides ecryption and decryption using the public and private keys.
+ * RSA provides encryption and decryption using the public and private keys.
  * You can use a variety of padding methods depending upon the intended use of
  * encrypted data.
  *
+ * === Encryption & Decryption
+ *
+ * Asymmetric public/private key encryption is slow and victim to attack in
+ * cases where it is used without padding or directly to encrypt larger chunks
+ * of data. Typical use cases for RSA encryption involve "wrapping" a symmetric 
+ * key with the public key of the recipient who would "unwrap" that symmetric
+ * key again using their private key.  
+ * The following illustrates a simplified example of such a key transport
+ * scheme. It shouldn't be used in practice, though, standardized protocols
+ * should always be preferred.
+ *
+ *   wrapped_key = key.public_encrypt key
+ *
+ * A symmetric key encrypted with the public key can only be decrypted with
+ * the corresponding private key of the recipient.
+ *
+ *   original_key = key.private_decrypt wrapped_key
+ *
+ * By default PKCS#1 padding will be used, but it is also possible to use
+ * other forms of padding, see PKey::RSA for further details.
+ *
+ * === Signatures
+ *
+ * Using "private_encrypt" to encrypt some data with the private key is
+ * equivalent to applying a digital signature to the data. A verifying
+ * party may validate the signature by comparing the result of decrypting
+ * the signature with "public_decrypt" to the original data. However, 
+ * OpenSSL::PKey already has methods "sign" and "verify" that handle
+ * digital signatures in a standardized way - "private_encrypt" and
+ * "public_decrypt" shouldn't be used in practice.
+ *
+ * To sign a document, a cryptographically secure hash of the document is
+ * computed first, which is then signed using the private key.
+ *
+ *   digest = OpenSSL::Digest::SHA256.new
+ *   signature = key.sign digest, document
+ *
+ * To validate the signature, again a hash of the document is computed and
+ * the signature is decrypted using the public key. The result is then
+ * compared to the hash just computed, if they are equal the signature was
+ * valid.
+ *
+ *   digest = OpenSSL::Digest::SHA256.new
+ *   if key.verify digest, signature, document
+ *     puts 'Valid'
+ *   else
+ *     puts 'Invalid'
+ *   end
+ *
+ * == PBKDF2 Password-based Encryption
+ * 
+ * If supported by the underlying OpenSSL version used, Password-based
+ * Encryption should use the features of PKCS5. If not supported or if
+ * required by legacy applications, the older, less secure methods specified
+ * in RFC 2898 are also supported (see below).
+ * 
+ * PKCS5 supports PBKDF2 as it was specified in PKCS#5 
+ * v2.0[http://www.rsa.com/rsalabs/node.asp?id=2127]. It still uses a
+ * password, a salt, and additionally a number of iterations that will
+ * slow the key derivation process down. The slower this is, the more work
+ * it requires being able to brute-force the resulting key.
+ *
  * === Encryption
+ *   
+ * The strategy is to first instantiate a Cipher for encryption, and
+ * then to generate a random IV plus a key derived from the password
+ * using PBKDF2. PKCS #5 v2.0 recommends at least 8 bytes for the salt,
+ * the number of iterations largely depends on the hardware being used.
  *
- * Documents encrypted with the public key can only be decrypted with the
- * private key.
+ *   cipher = OpenSSL::Cipher.new 'AES-128-CBC'
+ *   cipher.encrypt
+ *   iv = cipher.random_iv
  *
- *   public_encrypted = key.public_encrypt 'top secret document'
+ *   pwd = 'some hopefully not to easily guessable password'
+ *   salt = OpenSSL::Random.random_bytes 16
+ *   iter = 20000
+ *   key_len = cipher.key_len
+ *   digest = OpenSSL::Digest::SHA256.new
  *
- * Documents encrypted with the private key can only be decrypted with the
- * public key.
+ *   key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
+ *   cipher.key = key
  *
- *   private_encrypted = key.private_encrypt 'public release document'
+ *   Now encrypt the data:
  *
+ *   encrypted = cipher.update document
+ *   encrypted << cipher.final
+ *
  * === Decryption
  *
- * Use the opposite key type do decrypt the document
+ * Use the same steps as before to derive the symmetric AES key, this time
+ * setting the Cipher up for decryption.
  *
- *   top_secret = key.public_decrypt public_encrypted
+ *   cipher = OpenSSL::Cipher.new 'AES-128-CBC'
+ *   cipher.decrypt
+ *   cipher.iv = iv # the one generated with #random_iv
  *
- *   public_release = key.private_decrypt private_encrypted
+ *   pwd = 'some hopefully not to easily guessable password'
+ *   salt = ... # the one generated above
+ *   iter = 20000
+ *   key_len = cipher.key_len
+ *   digest = OpenSSL::Digest::SHA256.new
  *
+ *   key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
+ *   cipher.key = key
+ *
+ *   Now decrypt the data:
+ *
+ *   decrypted = cipher.update encrypted
+ *   decrypted << cipher.final
+ *
  * == PKCS #5 Password-based Encryption
  *
  * PKCS #5 is a password-based encryption standard documented at
  * RFC2898[http://www.ietf.org/rfc/rfc2898.txt].  It allows a short password or
- * passphrase to be used to create a secure encryption key.
+ * passphrase to be used to create a secure encryption key. If possible, PBKDF2
+ * as described above should be used if the circumstances allow it.
  *
  * PKCS #5 uses a Cipher, a pass phrase and a salt to generate an encryption
  * key.
@@ -529,7 +620,7 @@
  *
  * First set up the cipher for encryption
  *
- *   encrypter = OpenSSL::Cipher::Cipher.new 'AES-128-CBC'
+ *   encrypter = OpenSSL::Cipher.new 'AES-128-CBC'
  *   encrypter.encrypt
  *   encrypter.pkcs5_keyivgen pass_phrase, salt
  *
@@ -542,7 +633,7 @@
  *
  * Use a new Cipher instance set up for decryption
  *
- *   decrypter = OpenSSL::Cipher::Cipher.new 'AES-128-CBC'
+ *   decrypter = OpenSSL::Cipher.new 'AES-128-CBC'
  *   decrypter.decrypt
  *   decrypter.pkcs5_keyivgen pass_phrase, salt
  *

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]