Commit:    b5b8ea1050837fba5a6cee55e41b4574ed64158e
Author:    Scott MacVicar <scott...@php.net>         Mon, 11 Jun 2012 00:16:30 
-0700
Parents:   a18cede1c5094d5255daeb99cd6debe09938399d
Branches:  PHP-5.4

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=b5b8ea1050837fba5a6cee55e41b4574ed64158e

Log:
Add PBKDF2 support via openssl()

Summary:
No easy way to put these in the hash extension since we don't really support 
optional
parameters to certain algorithms. Implemented in openssl for now since it has 
it already
and is pretty stable.

Only SHA1 is confirmed to work as an algorithm but openssl has a parameter so 
it can be
changed in the future.

Will backport to 5.4 potentially with Stas' approval.

Test Plan:
Ran newly added tests which came from RFC 6070

Changed paths:
  M  ext/openssl/openssl.c
  M  ext/openssl/php_openssl.h
  A  ext/openssl/tests/openssl_pkcs5_pbkdf2_hmac.phpt


Diff:
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 7187a96..28f7618 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -242,6 +242,16 @@ ZEND_BEGIN_ARG_INFO(arginfo_openssl_pkey_get_details, 0)
     ZEND_ARG_INFO(0, key)
 ZEND_END_ARG_INFO()
 
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_pkcs5_pbkdf2_hmac, 0, 0, 4)
+    ZEND_ARG_INFO(0, password)
+    ZEND_ARG_INFO(0, salt)
+    ZEND_ARG_INFO(0, key_length)
+    ZEND_ARG_INFO(0, iterations)
+    ZEND_ARG_INFO(0, digest_algorithm)
+ZEND_END_ARG_INFO()
+#endif
+
 ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_pkcs7_verify, 0, 0, 2)
     ZEND_ARG_INFO(0, filename)
     ZEND_ARG_INFO(0, flags)
@@ -428,6 +438,10 @@ const zend_function_entry openssl_functions[] = {
        PHP_FE(openssl_seal,                            arginfo_openssl_seal)
        PHP_FE(openssl_open,                            arginfo_openssl_open)
 
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+       PHP_FE(openssl_pkcs5_pbkdf2_hmac,       
arginfo_openssl_pkcs5_pbkdf2_hmac)
+#endif
+
 /* for S/MIME handling */
        PHP_FE(openssl_pkcs7_verify,            arginfo_openssl_pkcs7_verify)
        PHP_FE(openssl_pkcs7_decrypt,           arginfo_openssl_pkcs7_decrypt)
@@ -3317,6 +3331,57 @@ PHP_FUNCTION(openssl_pkey_get_details)
 
 /* }}} */
 
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+
+/* {{{ proto string openssl_pkcs5_pbkdf2_hmac(string password, string salt, 
long key_length, long iterations [, string digest_method = "sha1"])
+   Generates a PKCS5 v2 PBKDF2 string, defaults to sha1 */
+PHP_FUNCTION(openssl_pkcs5_pbkdf2_hmac)
+{
+       long key_length = 0, iterations = 0;
+       char *password; int password_len;
+       char *salt; int salt_len;
+       char *method; int method_len = 0;
+       unsigned char *out_buffer;
+
+       const EVP_MD *digest;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssll|s",
+                               &password, &password_len,
+                               &salt, &salt_len,
+                               &key_length, &iterations,
+                               &method, &method_len) == FAILURE) {
+               return;
+       }
+
+       if (key_length <= 0) {
+               RETURN_FALSE;
+       }
+
+       if (method_len) {
+               digest = EVP_get_digestbyname(method);
+       } else {
+               digest = EVP_sha1();
+       }
+
+       if (!digest) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature 
algorithm");
+               RETURN_FALSE;
+       }
+
+       out_buffer = emalloc(key_length + 1);
+       out_buffer[key_length] = '\0';
+
+       if (PKCS5_PBKDF2_HMAC(password, password_len, (unsigned char *)salt, 
salt_len, iterations, digest, key_length, out_buffer) == 1) {
+               RETVAL_STRINGL((char *)out_buffer, key_length, 0);
+       } else {
+               efree(out_buffer);
+               RETURN_FALSE;
+       }
+}
+/* }}} */
+
+#endif
+
 /* {{{ PKCS7 S/MIME functions */
 
 /* {{{ proto bool openssl_pkcs7_verify(string filename, long flags [, string 
signerscerts [, array cainfo [, string extracerts [, string content]]]])
diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h
index fc118db..0dbe7d2 100644
--- a/ext/openssl/php_openssl.h
+++ b/ext/openssl/php_openssl.h
@@ -52,6 +52,8 @@ PHP_FUNCTION(openssl_private_decrypt);
 PHP_FUNCTION(openssl_public_encrypt);
 PHP_FUNCTION(openssl_public_decrypt);
 
+PHP_FUNCTION(openssl_pkcs5_pbkdf2_hmac);
+
 PHP_FUNCTION(openssl_pkcs7_verify);
 PHP_FUNCTION(openssl_pkcs7_decrypt);
 PHP_FUNCTION(openssl_pkcs7_sign);
diff --git a/ext/openssl/tests/openssl_pkcs5_pbkdf2_hmac.phpt 
b/ext/openssl/tests/openssl_pkcs5_pbkdf2_hmac.phpt
new file mode 100644
index 0000000..af1fcb1
--- /dev/null
+++ b/ext/openssl/tests/openssl_pkcs5_pbkdf2_hmac.phpt
@@ -0,0 +1,26 @@
+--TEST--
+openssl_pkcs5_pbkdf2_hmac() tests
+--SKIPIF--
+<?php if (!extension_loaded("openssl") || 
!function_exists("openssl_pkcs5_pbkdf2_hmac")) print "skip"; ?>
+--FILE--
+<?php
+// official test vectors
+var_dump(bin2hex(openssl_pkcs5_pbkdf2_hmac('password', 'salt', 20, 1)));
+var_dump(bin2hex(openssl_pkcs5_pbkdf2_hmac('password', 'salt', 20, 2)));
+var_dump(bin2hex(openssl_pkcs5_pbkdf2_hmac('password', 'salt', 20, 4096)));
+
+/* really slow but should be:
+string(40) "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984"
+var_dump(bin2hex(openssl_pkcs5_pbkdf2_hmac('password', 'salt', 20, 16777216)));
+*/
+
+var_dump(bin2hex(openssl_pkcs5_pbkdf2_hmac('passwordPASSWORDpassword', 
'saltSALTsaltSALTsaltSALTsaltSALTsalt', 25, 4096)));
+var_dump(bin2hex(openssl_pkcs5_pbkdf2_hmac("pass\0word", "sa\0lt", 16, 4096)));
+
+?>
+--EXPECTF--
+string(40) "0c60c80f961f0e71f3a9b524af6012062fe037a6"
+string(40) "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"
+string(40) "4b007901b765489abead49d926f721d065a429c1"
+string(50) "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"
+string(32) "56fa6aa75548099dcc37d7f03425e0c3"


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to