mirror of
https://github.com/php/php-src.git
synced 2024-09-22 18:37:25 +00:00
Add parameter to openssl_(en|de)crypt
This commit is contained in:
parent
962e95df52
commit
340d57b13a
@ -99,6 +99,7 @@ PHP_FUNCTION(openssl_get_cipher_methods);
|
||||
PHP_FUNCTION(openssl_digest);
|
||||
PHP_FUNCTION(openssl_encrypt);
|
||||
PHP_FUNCTION(openssl_decrypt);
|
||||
PHP_FUNCTION(openssl_cipher_iv_length);
|
||||
|
||||
PHP_FUNCTION(openssl_dh_compute_key);
|
||||
PHP_FUNCTION(openssl_random_pseudo_bytes);
|
||||
@ -347,6 +348,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_encrypt, 0, 0, 3)
|
||||
ZEND_ARG_INFO(0, method)
|
||||
ZEND_ARG_INFO(0, password)
|
||||
ZEND_ARG_INFO(0, raw_output)
|
||||
ZEND_ARG_INFO(0, iv)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_decrypt, 0, 0, 3)
|
||||
@ -354,6 +356,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_decrypt, 0, 0, 3)
|
||||
ZEND_ARG_INFO(0, method)
|
||||
ZEND_ARG_INFO(0, password)
|
||||
ZEND_ARG_INFO(0, raw_input)
|
||||
ZEND_ARG_INFO(0, iv)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_openssl_cipher_iv_length, 0)
|
||||
ZEND_ARG_INFO(0, method)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_openssl_dh_compute_key, 0)
|
||||
@ -408,6 +415,7 @@ const zend_function_entry openssl_functions[] = {
|
||||
PHP_FE(openssl_digest, arginfo_openssl_digest)
|
||||
PHP_FE(openssl_encrypt, arginfo_openssl_encrypt)
|
||||
PHP_FE(openssl_decrypt, arginfo_openssl_decrypt)
|
||||
PHP_FE(openssl_cipher_iv_length, arginfo_openssl_cipher_iv_length)
|
||||
PHP_FE(openssl_sign, arginfo_openssl_sign)
|
||||
PHP_FE(openssl_verify, arginfo_openssl_verify)
|
||||
PHP_FE(openssl_seal, arginfo_openssl_seal)
|
||||
@ -4585,19 +4593,54 @@ PHP_FUNCTION(openssl_digest)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string openssl_encrypt(string data, string method, string password [, bool raw_output=false])
|
||||
static zend_bool php_openssl_validate_iv(char **piv, int *piv_len, int iv_required_len)
|
||||
{
|
||||
char *iv_new;
|
||||
|
||||
/* Best case scenario, user behaved */
|
||||
if (*piv_len == iv_required_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
iv_new = ecalloc(1, iv_required_len + 1);
|
||||
|
||||
if (*piv_len <= 0) {
|
||||
/* BC behavior */
|
||||
*piv_len = iv_required_len;
|
||||
*piv = iv_new;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*piv_len < iv_required_len) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "IV passed is only %d bytes long, cipher expects an IV of precisely %d bytes, padding with \\0", *piv_len, iv_required_len);
|
||||
memcpy(iv_new, *piv, *piv_len);
|
||||
*piv_len = iv_required_len;
|
||||
*piv = iv_new;
|
||||
return 1;
|
||||
}
|
||||
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "IV passed is %d bytes long which is longer than the %d expected by selected cipher, truncating", *piv_len, iv_required_len);
|
||||
memcpy(iv_new, *piv, iv_required_len);
|
||||
*piv_len = iv_required_len;
|
||||
*piv = iv_new;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/* {{{ proto string openssl_encrypt(string data, string method, string password [, bool raw_output=false [, string $iv='']])
|
||||
Encrypts given data with given method and key, returns raw or base64 encoded string */
|
||||
PHP_FUNCTION(openssl_encrypt)
|
||||
{
|
||||
zend_bool raw_output = 0;
|
||||
char *data, *method, *password;
|
||||
int data_len, method_len, password_len;
|
||||
char *data, *method, *password, *iv = "";
|
||||
int data_len, method_len, password_len, iv_len = 0;
|
||||
const EVP_CIPHER *cipher_type;
|
||||
EVP_CIPHER_CTX cipher_ctx;
|
||||
int i, outlen, keylen, ivlen;
|
||||
unsigned char *outbuf, *key, *iv;
|
||||
int i, outlen, keylen;
|
||||
unsigned char *outbuf, *key;
|
||||
zend_bool free_iv;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|b", &data, &data_len, &method, &method_len, &password, &password_len, &raw_output) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|bs", &data, &data_len, &method, &method_len, &password, &password_len, &raw_output, &iv, &iv_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
cipher_type = EVP_get_cipherbyname(method);
|
||||
@ -4615,14 +4658,15 @@ PHP_FUNCTION(openssl_encrypt)
|
||||
key = (unsigned char*)password;
|
||||
}
|
||||
|
||||
ivlen = EVP_CIPHER_iv_length(cipher_type);
|
||||
iv = emalloc(ivlen);
|
||||
memset(iv, 0, ivlen);
|
||||
if (iv_len <= 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Using an empty Initialization Vector (iv) is potentially insecure and not recommended");
|
||||
}
|
||||
free_iv = php_openssl_validate_iv(&iv, &iv_len, EVP_CIPHER_iv_length(cipher_type));
|
||||
|
||||
outlen = data_len + EVP_CIPHER_block_size(cipher_type);
|
||||
outbuf = emalloc(outlen + 1);
|
||||
|
||||
EVP_EncryptInit(&cipher_ctx, cipher_type, key, iv);
|
||||
EVP_EncryptInit(&cipher_ctx, cipher_type, key, (unsigned char *)iv);
|
||||
EVP_EncryptUpdate(&cipher_ctx, outbuf, &i, (unsigned char *)data, data_len);
|
||||
outlen = i;
|
||||
if (EVP_EncryptFinal(&cipher_ctx, (unsigned char *)outbuf + i, &i)) {
|
||||
@ -4645,25 +4689,28 @@ PHP_FUNCTION(openssl_encrypt)
|
||||
if (key != (unsigned char*)password) {
|
||||
efree(key);
|
||||
}
|
||||
if (free_iv) {
|
||||
efree(iv);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string openssl_decrypt(string data, string method, string password [, bool raw_input=false])
|
||||
/* {{{ proto string openssl_decrypt(string data, string method, string password [, bool raw_input=false [, string $iv = '']])
|
||||
Takes raw or base64 encoded string and dectupt it using given method and key */
|
||||
PHP_FUNCTION(openssl_decrypt)
|
||||
{
|
||||
zend_bool raw_input = 0;
|
||||
char *data, *method, *password;
|
||||
int data_len, method_len, password_len;
|
||||
char *data, *method, *password, *iv = "";
|
||||
int data_len, method_len, password_len, iv_len = 0;
|
||||
const EVP_CIPHER *cipher_type;
|
||||
EVP_CIPHER_CTX cipher_ctx;
|
||||
int i, outlen, keylen, ivlen;
|
||||
unsigned char *outbuf, *key, *iv;
|
||||
int i, outlen, keylen;
|
||||
unsigned char *outbuf, *key;
|
||||
int base64_str_len;
|
||||
char *base64_str = NULL;
|
||||
zend_bool free_iv;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|b", &data, &data_len, &method, &method_len, &password, &password_len, &raw_input) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|bs", &data, &data_len, &method, &method_len, &password, &password_len, &raw_input, &iv, &iv_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4693,14 +4740,12 @@ PHP_FUNCTION(openssl_decrypt)
|
||||
key = (unsigned char*)password;
|
||||
}
|
||||
|
||||
ivlen = EVP_CIPHER_iv_length(cipher_type);
|
||||
iv = emalloc(ivlen);
|
||||
memset(iv, 0, ivlen);
|
||||
free_iv = php_openssl_validate_iv(&iv, &iv_len, EVP_CIPHER_iv_length(cipher_type));
|
||||
|
||||
outlen = data_len + EVP_CIPHER_block_size(cipher_type);
|
||||
outbuf = emalloc(outlen + 1);
|
||||
|
||||
EVP_DecryptInit(&cipher_ctx, cipher_type, key, iv);
|
||||
EVP_DecryptInit(&cipher_ctx, cipher_type, key, (unsigned char *)iv);
|
||||
EVP_DecryptUpdate(&cipher_ctx, outbuf, &i, (unsigned char *)data, data_len);
|
||||
outlen = i;
|
||||
if (EVP_DecryptFinal(&cipher_ctx, (unsigned char *)outbuf + i, &i)) {
|
||||
@ -4714,13 +4759,42 @@ PHP_FUNCTION(openssl_decrypt)
|
||||
if (key != (unsigned char*)password) {
|
||||
efree(key);
|
||||
}
|
||||
if (free_iv) {
|
||||
efree(iv);
|
||||
}
|
||||
if (base64_str) {
|
||||
efree(base64_str);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int openssl_cipher_iv_length(string $method) */
|
||||
PHP_FUNCTION(openssl_cipher_iv_length)
|
||||
{
|
||||
char *method;
|
||||
int method_len, iv_len;
|
||||
const EVP_CIPHER *cipher_type;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!method_len) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown cipher algorithm");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
cipher_type = EVP_get_cipherbyname(method);
|
||||
if (!cipher_type) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown cipher algorithm");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETURN_LONG(EVP_CIPHER_iv_length(cipher_type));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto string openssl_dh_compute_key(string pub_key, resource dh_key)
|
||||
Computes shared sicret for public value of remote DH key and local DH key */
|
||||
PHP_FUNCTION(openssl_dh_compute_key)
|
||||
|
@ -8,11 +8,16 @@ $data = "openssl_encrypt() and openssl_decrypt() tests";
|
||||
$method = "AES-128-CBC";
|
||||
$password = "openssl";
|
||||
|
||||
$encrypted = openssl_encrypt($data, $method, $password);
|
||||
$output = openssl_decrypt($encrypted, $method, $password);
|
||||
$ivlen = openssl_cipher_iv_length($method);
|
||||
$iv = '';
|
||||
srand(time() + ((microtime(true) * 1000000) % 1000000));
|
||||
while(strlen($iv) < $ivlen) $iv .= chr(rand(0,255));
|
||||
|
||||
$encrypted = openssl_encrypt($data, $method, $password, false, $iv);
|
||||
$output = openssl_decrypt($encrypted, $method, $password, false, $iv);
|
||||
var_dump($output);
|
||||
$encrypted = openssl_encrypt($data, $method, $password, true);
|
||||
$output = openssl_decrypt($encrypted, $method, $password, true);
|
||||
$encrypted = openssl_encrypt($data, $method, $password, true, $iv);
|
||||
$output = openssl_decrypt($encrypted, $method, $password, true, $iv);
|
||||
var_dump($output);
|
||||
?>
|
||||
--EXPECT--
|
||||
|
@ -8,8 +8,11 @@ $data = "openssl_decrypt() tests";
|
||||
$method = "AES-128-CBC";
|
||||
$password = "openssl";
|
||||
$wrong = "wrong";
|
||||
$iv = str_repeat("\0", openssl_cipher_iv_length($method));
|
||||
|
||||
$encrypted = openssl_encrypt($data, $method, $password);
|
||||
var_dump($encrypted); /* Not passing $iv should be the same as all-NULL iv, but with a warning */
|
||||
var_dump(openssl_encrypt($data, $method, $password, false, $iv));
|
||||
var_dump(openssl_decrypt($encrypted, $method, $wrong));
|
||||
var_dump(openssl_decrypt($encrypted, $wrong, $password));
|
||||
var_dump(openssl_decrypt($wrong, $method, $password));
|
||||
@ -21,6 +24,10 @@ var_dump(openssl_decrypt($encrypted, array(), $password));
|
||||
var_dump(openssl_decrypt($encrypted, $method, array()));
|
||||
?>
|
||||
--EXPECTF--
|
||||
|
||||
Warning: openssl_encrypt(): Using an empty Initialization Vector (iv) is potentially insecure and not recommended in %s on line %d
|
||||
string(44) "yof6cPPH4mLee6TOc0YQSrh4dvywMqxGUyjp0lV6+aM="
|
||||
string(44) "yof6cPPH4mLee6TOc0YQSrh4dvywMqxGUyjp0lV6+aM="
|
||||
bool(false)
|
||||
|
||||
Warning: openssl_decrypt(): Unknown cipher algorithm in %s on line %d
|
||||
|
Loading…
Reference in New Issue
Block a user