mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35996 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
14ba7fab58
commit
21f1af2ec2
2 changed files with 114 additions and 14 deletions
|
@ -1,3 +1,12 @@
|
|||
Sun Jun 10 03:09:41 2012 Martin Bosslet <Martin.Bosslet@googlemail.com>
|
||||
|
||||
* 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@googlemail.com>
|
||||
|
||||
* ext/openssl/ossl_ssl.c: Introduce SSLContext#renegotiation_cb and
|
||||
|
|
|
@ -455,7 +455,7 @@ ossl_debug_set(VALUE self, VALUE val)
|
|||
* 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 @@ ossl_debug_set(VALUE self, VALUE val)
|
|||
*
|
||||
* == 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 @@ ossl_debug_set(VALUE self, VALUE val)
|
|||
*
|
||||
* 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 @@ ossl_debug_set(VALUE self, VALUE val)
|
|||
*
|
||||
* 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
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue