mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* ext/openssl/ossl_pkcs5.c: add note on timing attacks and general
documentation. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33495 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
67db3f8177
commit
98490d1f71
2 changed files with 100 additions and 7 deletions
|
@ -1,3 +1,8 @@
|
|||
Thu Oct 20 22:38:53 2011 Martin Bosslet <Martin.Bosslet@googlemail.com>
|
||||
|
||||
* ext/openssl/ossl_pkcs5.c: add note on timing attacks and general
|
||||
documentation.
|
||||
|
||||
Thu Oct 20 21:19:15 2011 Naohisa Goto <ngotogenome@gmail.com>
|
||||
|
||||
* vm_eval.c (check_funcall): set array elements one-by-one to fix
|
||||
|
@ -9,7 +14,7 @@ Thu Oct 20 13:09:35 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
|||
* include/ruby/defines.h (flush_register_windows): use software
|
||||
trap on Debian Sparc 32-bit userspace. [Bug #5244]
|
||||
|
||||
Thu Oct 20 14:28:22 2011 Martin Bosslet <Martin.Bosslet@googlemail.com>
|
||||
Thu Oct 20 12:28:22 2011 Martin Bosslet <Martin.Bosslet@googlemail.com>
|
||||
|
||||
* test/openssl/test_pkcs5.rb: add RFC 6070 tests for PBKDF2 with
|
||||
HMAC-SHA1
|
||||
|
|
|
@ -14,12 +14,12 @@ VALUE ePKCS5;
|
|||
*
|
||||
* === Parameters
|
||||
* * +pass+ - string
|
||||
* * +salt+ - string
|
||||
* * +iter+ - integer - should be greater than 1000. 2000 is better.
|
||||
* * +salt+ - string - should be at least 8 bytes long.
|
||||
* * +iter+ - integer - should be greater than 1000. 20000 is better.
|
||||
* * +keylen+ - integer
|
||||
* * +digest+ - a string or OpenSSL::Digest object.
|
||||
*
|
||||
* Available in OpenSSL 0.9.9?.
|
||||
* Available in OpenSSL 0.9.4.
|
||||
*
|
||||
* Digests other than SHA1 may not be supported by other cryptography libraries.
|
||||
*/
|
||||
|
@ -56,11 +56,11 @@ ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE key
|
|||
*
|
||||
* === Parameters
|
||||
* * +pass+ - string
|
||||
* * +salt+ - string
|
||||
* * +iter+ - integer - should be greater than 1000. 2000 is better.
|
||||
* * +salt+ - string - should be at least 8 bytes long.
|
||||
* * +iter+ - integer - should be greater than 1000. 20000 is better.
|
||||
* * +keylen+ - integer
|
||||
*
|
||||
* This method is available almost any version OpenSSL.
|
||||
* This method is available in almost any version of OpenSSL.
|
||||
*
|
||||
* Conforms to rfc2898.
|
||||
*/
|
||||
|
@ -93,7 +93,95 @@ Init_ossl_pkcs5()
|
|||
* Password-based Encryption
|
||||
*
|
||||
*/
|
||||
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
|
||||
#endif
|
||||
|
||||
/* Document-class: OpenSSL::PKCS5
|
||||
*
|
||||
* Provides password-based encryption functionality based on PKCS#5.
|
||||
* Typically used for securely deriving arbitrary length symmetric keys
|
||||
* to be used with an OpenSSL::Cipher from passwords. Another use case
|
||||
* is for storing passwords: Due to the ability to tweak the effort of
|
||||
* computation by increasing the iteration count, computation can be
|
||||
* slowed down artificially in order to render possible attacks infeasible.
|
||||
*
|
||||
* PKCS5 offers support for PBKDF2 with an OpenSSL::Digest::SHA1-based
|
||||
* HMAC, or an arbitrary Digest if the underlying version of OpenSSL
|
||||
* already supports it (>= 0.9.4).
|
||||
*
|
||||
* === Parameters
|
||||
* ==== Password
|
||||
* Typically an arbitrary String that represents the password to be used
|
||||
* for deriving a key.
|
||||
* ==== Salt
|
||||
* Prevents attacks based on dictionaries of common passwords. It is a
|
||||
* public value that can be safely stored along with the password (e.g.
|
||||
* if PBKDF2 is used for password storage). For maximum security, a fresh,
|
||||
* random salt should be generated for each stored password. According
|
||||
* to PKCS#5, a salt should be at least 8 bytes long.
|
||||
* ==== Iteration Count
|
||||
* Allows to tweak the length that the actual computation will take. The
|
||||
* larger the iteration count, the longer it will take.
|
||||
* ==== Key Length
|
||||
* Specifies the length in bytes of the output that will be generated.
|
||||
* Typically, the key length should be larger than or equal to the output
|
||||
* length of the underlying digest function, otherwise an attacker could
|
||||
* simply try to brute-force the key. According to PKCS#5, security is
|
||||
* limited by the output length of the underlying digest function, i.e.
|
||||
* security is not improved if a key length strictly larger than the
|
||||
* digest output length is chosen. Therefore, when using PKCS5 for
|
||||
* password storage, it suffices to store values equal to the digest
|
||||
* output length, nothing is gained by storing larger values.
|
||||
*
|
||||
* == Examples
|
||||
* === Generating a 128 bit key for a Cipher (e.g. AES)
|
||||
* pass = "secret"
|
||||
* salt = OpenSSL::Random.random_bytes(16)
|
||||
* iter = 20000
|
||||
* key_len = 16
|
||||
* key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, key_len)
|
||||
*
|
||||
* === Storing Passwords
|
||||
* pass = "secret"
|
||||
* salt = OpenSSL::Random.random_bytes(16) #store this with the generated value
|
||||
* iter = 20000
|
||||
* digest = OpenSSL::Digest::SHA256.new
|
||||
* len = digest.digest_length
|
||||
* #the final value to be stored
|
||||
* value = OpenSSL::PKCS5.pbkdf2_hmac(pass, salt, iter, len, digest)
|
||||
*
|
||||
* === Important Note on Checking Passwords
|
||||
* When comparing passwords provided by the user with previously stored
|
||||
* values, a common mistake made is comparing the two values using "==".
|
||||
* Typically, "==" short-circuits on evaluation, and is therefore
|
||||
* vulnerable to timing attacks. The proper way is to use a method that
|
||||
* always takes the same amount of time when comparing two values, thus
|
||||
* not leaking any information to potential attackers. To compare two
|
||||
* values, the following could be used:
|
||||
* def eql_time_cmp(a, b)
|
||||
* unless a.length == b.length
|
||||
* return false
|
||||
* end
|
||||
* cmp = b.bytes.to_a
|
||||
* result = 0
|
||||
* a.bytes.each_with_index {|c,i|
|
||||
* result |= c ^ cmp[i]
|
||||
* }
|
||||
* result == 0
|
||||
* end
|
||||
* Please note that the premature return in case of differing lengths
|
||||
* typically does not leak valuable information - when using PKCS#5, the
|
||||
* length of the values to be compared is of fixed size.
|
||||
*/
|
||||
|
||||
mPKCS5 = rb_define_module_under(mOSSL, "PKCS5");
|
||||
/* Document-class: OpenSSL::PKCS5::PKCS5Error
|
||||
*
|
||||
* Generic Exception class that is raised if an error occurs during a
|
||||
* computation.
|
||||
*/
|
||||
ePKCS5 = rb_define_class_under(mPKCS5, "PKCS5Error", eOSSLError);
|
||||
|
||||
rb_define_module_function(mPKCS5, "pbkdf2_hmac", ossl_pkcs5_pbkdf2_hmac, 5);
|
||||
|
|
Loading…
Reference in a new issue