1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Improve openssl ext to generate EC keys with custom EC parameters

This change extends supported parameter when generating EC keys.

Specifically following parameters are now supported: p, a, b, order,
generator, seed, cofactory, g_x, g_y, x, y and d.

Those parameters can be passed to ec field in openssl_pkey_new options.

It also fixes some issues openssl_pkey_get_details related to SM2
support.

Closes GH-9991
This commit is contained in:
Eno
2023-05-13 01:15:24 +08:00
committed by Jakub Zelenka
parent b0a2727749
commit 0dadd6616a
5 changed files with 504 additions and 130 deletions

3
NEWS
View File

@@ -10,6 +10,9 @@ PHP NEWS
. Fixed line number of JMP instruction over else block. (ilutov)
. Fixed use-of-uninitialized-value with ??= on assert. (ilutov)
- OpenSSL
. Added support for additional EC parameters in openssl_pkey_new. (Eno-CN)
06 Jul 2023, PHP 8.3.0alpha3
- Core:

View File

@@ -97,6 +97,14 @@
#if !defined(OPENSSL_NO_EC) && defined(EVP_PKEY_EC)
#define HAVE_EVP_PKEY_EC 1
/* the OPENSSL_EC_EXPLICIT_CURVE value was added
* in OpenSSL 1.1.0; previous versions should
* use 0 instead.
*/
#ifndef OPENSSL_EC_EXPLICIT_CURVE
#define OPENSSL_EC_EXPLICIT_CURVE 0x000
#endif
#endif
ZEND_DECLARE_MODULE_GLOBALS(openssl)
@@ -4264,158 +4272,290 @@ cleanup:
#ifdef HAVE_EVP_PKEY_EC
#if PHP_OPENSSL_API_VERSION < 0x30000
static bool php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, bool *is_private) {
BIGNUM *p = NULL, *a = NULL, *b = NULL, *order = NULL, *g_x = NULL, *g_y = NULL , *cofactor = NULL;
BIGNUM *x = NULL, *y = NULL, *d = NULL;
EC_POINT *point_g = NULL;
EC_POINT *point_q = NULL;
EC_GROUP *group = NULL;
EC_POINT *pnt = NULL;
BIGNUM *d = NULL;
zval *bn;
zval *x;
zval *y;
BN_CTX *bctx = BN_CTX_new();
*is_private = false;
if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1)) != NULL &&
Z_TYPE_P(bn) == IS_STRING) {
int nid = OBJ_sn2nid(Z_STRVAL_P(bn));
if (nid != NID_undef) {
group = EC_GROUP_new_by_curve_name(nid);
if (!group) {
php_openssl_store_errors();
zval *curve_name_zv = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1);
if (curve_name_zv && Z_TYPE_P(curve_name_zv) == IS_STRING && Z_STRLEN_P(curve_name_zv) > 0) {
int nid = OBJ_sn2nid(Z_STRVAL_P(curve_name_zv));
if (nid == NID_undef) {
php_error_docref(NULL, E_WARNING, "Unknown elliptic curve (short) name %s", Z_STRVAL_P(curve_name_zv));
goto clean_exit;
}
if (!(group = EC_GROUP_new_by_curve_name(nid))) {
goto clean_exit;
}
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
} else {
OPENSSL_PKEY_SET_BN(data, p);
OPENSSL_PKEY_SET_BN(data, a);
OPENSSL_PKEY_SET_BN(data, b);
OPENSSL_PKEY_SET_BN(data, order);
if (!(p && a && b && order)) {
if (!p && !a && !b && !order) {
php_error_docref(NULL, E_WARNING, "Missing params: curve_name");
} else {
php_error_docref(
NULL, E_WARNING, "Missing params: curve_name or p, a, b, order");
}
goto clean_exit;
}
if (!(group = EC_GROUP_new_curve_GFp(p, a, b, bctx))) {
goto clean_exit;
}
if (!(point_g = EC_POINT_new(group))) {
goto clean_exit;
}
zval *generator_zv = zend_hash_str_find(Z_ARRVAL_P(data), "generator", sizeof("generator") - 1);
if (generator_zv && Z_TYPE_P(generator_zv) == IS_STRING && Z_STRLEN_P(generator_zv) > 0) {
if (!(EC_POINT_oct2point(group, point_g, (unsigned char *)Z_STRVAL_P(generator_zv), Z_STRLEN_P(generator_zv), bctx))) {
goto clean_exit;
}
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
if (!EC_KEY_set_group(eckey, group)) {
php_openssl_store_errors();
} else {
OPENSSL_PKEY_SET_BN(data, g_x);
OPENSSL_PKEY_SET_BN(data, g_y);
if (!g_x || !g_y) {
php_error_docref(
NULL, E_WARNING, "Missing params: generator or g_x and g_y");
goto clean_exit;
}
if (!EC_POINT_set_affine_coordinates_GFp(group, point_g, g_x, g_y, bctx)) {
goto clean_exit;
}
}
zval *seed_zv = zend_hash_str_find(Z_ARRVAL_P(data), "seed", sizeof("seed") - 1);
if (seed_zv && Z_TYPE_P(seed_zv) == IS_STRING && Z_STRLEN_P(seed_zv) > 0) {
if (!EC_GROUP_set_seed(group, (unsigned char *)Z_STRVAL_P(seed_zv), Z_STRLEN_P(seed_zv))) {
goto clean_exit;
}
}
/*
* OpenSSL uses 0 cofactor as a marker for "unknown cofactor".
* So accept cofactor == NULL or cofactor >= 0.
* Internally, the lib will check the cofactor value.
*/
OPENSSL_PKEY_SET_BN(data, cofactor);
if (!EC_GROUP_set_generator(group, point_g, order, cofactor)) {
goto clean_exit;
}
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE);
}
if (group == NULL) {
php_error_docref(NULL, E_WARNING, "Unknown curve name");
EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
if (!EC_KEY_set_group(eckey, group)) {
goto clean_exit;
}
// The public key 'pnt' can be calculated from 'd' or is defined by 'x' and 'y'
if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "d", sizeof("d") - 1)) != NULL &&
Z_TYPE_P(bn) == IS_STRING) {
OPENSSL_PKEY_SET_BN(data, d);
OPENSSL_PKEY_SET_BN(data, x);
OPENSSL_PKEY_SET_BN(data, y);
if (d) {
*is_private = true;
d = BN_bin2bn((unsigned char*) Z_STRVAL_P(bn), Z_STRLEN_P(bn), NULL);
if (!EC_KEY_set_private_key(eckey, d)) {
php_openssl_store_errors();
goto clean_exit;
}
// Calculate the public key by multiplying the Point Q with the public key
// P = d * Q
pnt = EC_POINT_new(group);
if (!pnt || !EC_POINT_mul(group, pnt, d, NULL, NULL, NULL)) {
php_openssl_store_errors();
goto clean_exit;
}
BN_free(d);
} else if ((x = zend_hash_str_find(Z_ARRVAL_P(data), "x", sizeof("x") - 1)) != NULL &&
Z_TYPE_P(x) == IS_STRING &&
(y = zend_hash_str_find(Z_ARRVAL_P(data), "y", sizeof("y") - 1)) != NULL &&
Z_TYPE_P(y) == IS_STRING) {
pnt = EC_POINT_new(group);
if (pnt == NULL) {
php_openssl_store_errors();
point_q = EC_POINT_new(group);
if (!point_q || !EC_POINT_mul(group, point_q, d, NULL, NULL, bctx)) {
goto clean_exit;
}
if (!EC_POINT_set_affine_coordinates_GFp(
group, pnt, BN_bin2bn((unsigned char*) Z_STRVAL_P(x), Z_STRLEN_P(x), NULL),
BN_bin2bn((unsigned char*) Z_STRVAL_P(y), Z_STRLEN_P(y), NULL), NULL)) {
php_openssl_store_errors();
} else if (x && y) {
/* OpenSSL does not allow setting EC_PUB_X/EC_PUB_Y, so convert to encoded format. */
point_q = EC_POINT_new(group);
if (!point_q || !EC_POINT_set_affine_coordinates_GFp(group, point_q, x, y, bctx)) {
goto clean_exit;
}
}
if (pnt != NULL) {
if (!EC_KEY_set_public_key(eckey, pnt)) {
php_openssl_store_errors();
if (point_q != NULL) {
if (!EC_KEY_set_public_key(eckey, point_q)) {
goto clean_exit;
}
EC_POINT_free(pnt);
pnt = NULL;
}
if (!EC_KEY_check_key(eckey)) {
*is_private = true;
PHP_OPENSSL_RAND_ADD_TIME();
EC_KEY_generate_key(eckey);
php_openssl_store_errors();
}
if (EC_KEY_check_key(eckey)) {
EC_GROUP_free(group);
return true;
} else {
php_openssl_store_errors();
}
clean_exit:
BN_free(d);
EC_POINT_free(pnt);
php_openssl_store_errors();
BN_CTX_free(bctx);
EC_GROUP_free(group);
return false;
EC_POINT_free(point_g);
EC_POINT_free(point_q);
BN_free(p);
BN_free(a);
BN_free(b);
BN_free(order);
BN_free(g_x);
BN_free(g_y);
BN_free(cofactor);
BN_free(d);
BN_free(x);
BN_free(y);
return EC_KEY_check_key(eckey);
}
#endif
static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
#if PHP_OPENSSL_API_VERSION >= 0x30000
BIGNUM *d = NULL, *x = NULL, *y = NULL;
int nid = NID_undef;
BIGNUM *p = NULL, *a = NULL, *b = NULL, *order = NULL, *g_x = NULL, *g_y = NULL, *cofactor = NULL;
BIGNUM *x = NULL, *y = NULL, *d = NULL;
EC_POINT *point_g = NULL;
EC_POINT *point_q = NULL;
unsigned char *point_g_buf = NULL;
unsigned char *point_q_buf = NULL;
EC_GROUP *group = NULL;
EC_POINT *pnt = NULL;
unsigned char *pnt_oct = NULL;
EVP_PKEY *param_key = NULL, *pkey = NULL;
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
BN_CTX *bctx = BN_CTX_new();
OSSL_PARAM *params = NULL;
OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
zval *curve_name_zv = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1);
OPENSSL_PKEY_SET_BN(data, d);
OPENSSL_PKEY_SET_BN(data, x);
OPENSSL_PKEY_SET_BN(data, y);
*is_private = false;
if (!ctx || !bld || !curve_name_zv || Z_TYPE_P(curve_name_zv) != IS_STRING) {
goto cleanup;
}
int nid = OBJ_sn2nid(Z_STRVAL_P(curve_name_zv));
group = EC_GROUP_new_by_curve_name(nid);
if (!group) {
php_error_docref(NULL, E_WARNING, "Unknown curve name");
goto cleanup;
}
OSSL_PARAM_BLD_push_utf8_string(
bld, OSSL_PKEY_PARAM_GROUP_NAME, Z_STRVAL_P(curve_name_zv), Z_STRLEN_P(curve_name_zv));
if (d) {
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, d);
pnt = EC_POINT_new(group);
if (!pnt || !EC_POINT_mul(group, pnt, d, NULL, NULL, NULL)) {
goto cleanup;
}
} else if (x && y) {
/* OpenSSL does not allow setting EC_PUB_X/EC_PUB_Y, so convert to encoded format. */
pnt = EC_POINT_new(group);
if (!pnt || !EC_POINT_set_affine_coordinates(group, pnt, x, y, NULL)) {
goto cleanup;
}
}
if (pnt) {
size_t pnt_oct_len =
EC_POINT_point2buf(group, pnt, POINT_CONVERSION_COMPRESSED, &pnt_oct, NULL);
if (!pnt_oct_len) {
zval *curve_name_zv = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1);
if (curve_name_zv && Z_TYPE_P(curve_name_zv) == IS_STRING && Z_STRLEN_P(curve_name_zv) > 0) {
nid = OBJ_sn2nid(Z_STRVAL_P(curve_name_zv));
if (nid == NID_undef) {
php_error_docref(NULL, E_WARNING, "Unknown elliptic curve (short) name %s", Z_STRVAL_P(curve_name_zv));
goto cleanup;
}
OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, pnt_oct, pnt_oct_len);
if (!(group = EC_GROUP_new_by_curve_name(nid))) {
goto cleanup;
}
if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, Z_STRVAL_P(curve_name_zv), Z_STRLEN_P(curve_name_zv))) {
goto cleanup;
}
} else {
OPENSSL_PKEY_SET_BN(data, p);
OPENSSL_PKEY_SET_BN(data, a);
OPENSSL_PKEY_SET_BN(data, b);
OPENSSL_PKEY_SET_BN(data, order);
if (!(p && a && b && order)) {
if (!p && !a && !b && !order) {
php_error_docref(NULL, E_WARNING, "Missing params: curve_name");
} else {
php_error_docref(NULL, E_WARNING, "Missing params: curve_name or p, a, b, order");
}
goto cleanup;
}
if (!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_P, p) ||
!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_A, a) ||
!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_B, b) ||
!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_ORDER, order) ||
!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_FIELD_TYPE, SN_X9_62_prime_field, 0)) {
goto cleanup;
}
if (!(group = EC_GROUP_new_curve_GFp(p, a, b, bctx))) {
goto cleanup;
}
if (!(point_g = EC_POINT_new(group))) {
goto cleanup;
}
zval *generator_zv = zend_hash_str_find(Z_ARRVAL_P(data), "generator", sizeof("generator") - 1);
if (generator_zv && Z_TYPE_P(generator_zv) == IS_STRING && Z_STRLEN_P(generator_zv) > 0) {
if (!EC_POINT_oct2point(group, point_g, (unsigned char *)Z_STRVAL_P(generator_zv), Z_STRLEN_P(generator_zv), bctx) ||
!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_GENERATOR, Z_STRVAL_P(generator_zv), Z_STRLEN_P(generator_zv))) {
goto cleanup;
}
} else {
OPENSSL_PKEY_SET_BN(data, g_x);
OPENSSL_PKEY_SET_BN(data, g_y);
if (!g_x || !g_y) {
php_error_docref(
NULL, E_WARNING, "Missing params: generator or g_x and g_y");
goto cleanup;
}
if (!EC_POINT_set_affine_coordinates(group, point_g, g_x, g_y, bctx)) {
goto cleanup;
}
size_t point_g_buf_len =
EC_POINT_point2buf(group, point_g, POINT_CONVERSION_COMPRESSED, &point_g_buf, bctx);
if (!point_g_buf_len) {
goto cleanup;
}
if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_GENERATOR, point_g_buf, point_g_buf_len)) {
goto cleanup;
}
}
zval *seed_zv = zend_hash_str_find(Z_ARRVAL_P(data), "seed", sizeof("seed") - 1);
if (seed_zv && Z_TYPE_P(seed_zv) == IS_STRING && Z_STRLEN_P(seed_zv) > 0) {
if (!EC_GROUP_set_seed(group, (unsigned char *)Z_STRVAL_P(seed_zv), Z_STRLEN_P(seed_zv)) ||
!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_SEED, Z_STRVAL_P(seed_zv), Z_STRLEN_P(seed_zv))) {
goto cleanup;
}
}
OPENSSL_PKEY_SET_BN(data, cofactor);
if (!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_COFACTOR, cofactor) ||
!EC_GROUP_set_generator(group, point_g, order, cofactor)) {
goto cleanup;
}
nid = EC_GROUP_check_named_curve(group, 0, bctx);
}
/* custom params not supported with SM2, SKIP */
if (nid != NID_sm2) {
OPENSSL_PKEY_SET_BN(data, d);
OPENSSL_PKEY_SET_BN(data, x);
OPENSSL_PKEY_SET_BN(data, y);
if (d) {
point_q = EC_POINT_new(group);
if (!point_q || !EC_POINT_mul(group, point_q, d, NULL, NULL, bctx) ||
!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, d)) {
goto cleanup;
}
} else if (x && y) {
/* OpenSSL does not allow setting EC_PUB_X/EC_PUB_Y, so convert to encoded format. */
point_q = EC_POINT_new(group);
if (!point_q || !EC_POINT_set_affine_coordinates(group, point_q, x, y, bctx)) {
goto cleanup;
}
}
if (point_q) {
size_t point_q_buf_len =
EC_POINT_point2buf(group, point_q, POINT_CONVERSION_COMPRESSED, &point_q_buf, bctx);
if (!point_q_buf_len ||
!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, point_q_buf, point_q_buf_len)) {
goto cleanup;
}
}
}
params = OSSL_PARAM_BLD_to_param(bld);
@@ -4423,21 +4563,25 @@ static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
goto cleanup;
}
if (EVP_PKEY_fromdata_init(ctx) <= 0 ||
if (d || (x && y)) {
if (EVP_PKEY_fromdata_init(ctx) <= 0 ||
EVP_PKEY_fromdata(ctx, &param_key, EVP_PKEY_KEYPAIR, params) <= 0) {
goto cleanup;
goto cleanup;
}
EVP_PKEY_CTX_free(ctx);
ctx = EVP_PKEY_CTX_new(param_key, NULL);
}
EVP_PKEY_CTX_free(ctx);
ctx = EVP_PKEY_CTX_new(param_key, NULL);
if (EVP_PKEY_check(ctx)) {
if (EVP_PKEY_check(ctx) || EVP_PKEY_public_check_quick(ctx)) {
*is_private = d != NULL;
EVP_PKEY_up_ref(param_key);
pkey = param_key;
} else {
*is_private = true;
PHP_OPENSSL_RAND_ADD_TIME();
if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) {
if (EVP_PKEY_keygen_init(ctx) != 1 ||
EVP_PKEY_CTX_set_params(ctx, params) != 1 ||
EVP_PKEY_generate(ctx, &pkey) != 1) {
goto cleanup;
}
}
@@ -4446,11 +4590,21 @@ cleanup:
php_openssl_store_errors();
EVP_PKEY_free(param_key);
EVP_PKEY_CTX_free(ctx);
BN_CTX_free(bctx);
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(bld);
EC_POINT_free(pnt);
EC_GROUP_free(group);
OPENSSL_free(pnt_oct);
EC_POINT_free(point_g);
EC_POINT_free(point_q);
OPENSSL_free(point_g_buf);
OPENSSL_free(point_q_buf);
BN_free(p);
BN_free(a);
BN_free(b);
BN_free(order);
BN_free(g_x);
BN_free(g_y);
BN_free(cofactor);
BN_free(d);
BN_free(x);
BN_free(y);
@@ -4796,7 +4950,21 @@ PHP_FUNCTION(openssl_pkey_get_details)
*/
#if PHP_OPENSSL_API_VERSION >= 0x30000
zval ary;
switch (EVP_PKEY_base_id(pkey)) {
int base_id = 0;
if (EVP_PKEY_id(pkey) != EVP_PKEY_KEYMGMT) {
base_id = EVP_PKEY_base_id(pkey);
} else {
const char *type_name = EVP_PKEY_get0_type_name(pkey);
if (type_name) {
int nid = OBJ_txt2nid(type_name);
if (nid != NID_undef) {
base_id = EVP_PKEY_type(nid);
}
}
}
switch (base_id) {
case EVP_PKEY_RSA:
ktype = OPENSSL_KEYTYPE_RSA;
array_init(&ary);
@@ -4859,7 +5027,9 @@ PHP_FUNCTION(openssl_pkey_get_details)
break;
}
#endif
EMPTY_SWITCH_DEFAULT_CASE();
default:
ktype = -1;
break;
}
#else
switch (EVP_PKEY_base_id(pkey)) {
@@ -4955,24 +5125,22 @@ PHP_FUNCTION(openssl_pkey_get_details)
ec_group = EC_KEY_get0_group(ec_key);
// Curve nid (numerical identifier) used for ASN1 mapping
nid = EC_GROUP_get_curve_name(ec_group);
if (nid == NID_undef) {
break;
}
array_init(&ec);
// Short object name
crv_sn = (char*) OBJ_nid2sn(nid);
if (crv_sn != NULL) {
add_assoc_string(&ec, "curve_name", crv_sn);
}
/** Curve nid (numerical identifier) used for ASN1 mapping */
nid = EC_GROUP_get_curve_name(ec_group);
if (nid != NID_undef) {
crv_sn = (char*) OBJ_nid2sn(nid);
if (crv_sn != NULL) {
add_assoc_string(&ec, "curve_name", crv_sn);
}
obj = OBJ_nid2obj(nid);
if (obj != NULL) {
int oir_len = OBJ_obj2txt(oir_buf, sizeof(oir_buf), obj, 1);
add_assoc_stringl(&ec, "curve_oid", (char*) oir_buf, oir_len);
ASN1_OBJECT_free(obj);
obj = OBJ_nid2obj(nid);
if (obj != NULL) {
int oir_len = OBJ_obj2txt(oir_buf, sizeof(oir_buf), obj, 1);
add_assoc_stringl(&ec, "curve_oid", (char*) oir_buf, oir_len);
ASN1_OBJECT_free(obj);
}
}
pub = EC_KEY_get0_public_key(ec_key);

View File

@@ -74,7 +74,8 @@ var_dump($csr);
$pubkey1 = openssl_pkey_get_details(openssl_csr_get_public_key($csr));
var_dump(isset($pubkey1["ec"]["priv_key"]));
unset($d1["ec"]["priv_key"]);
var_dump(array_diff($d1["ec"], $pubkey1["ec"]));
$diff = array_diff($d1["ec"], $pubkey1["ec"]);
var_dump(isset($diff["d"]) && is_string($diff["d"]) && strlen($diff["d"]) > 0);
$x509 = openssl_csr_sign($csr, null, $key1, 365, $args);
var_dump($x509);
@@ -121,10 +122,7 @@ Testing openssl_csr_new with existing ecc key
object(OpenSSLCertificateSigningRequest)#%d (0) {
}
bool(false)
array(1) {
["d"]=>
string(%d) "%a"
}
bool(true)
object(OpenSSLCertificate)#%d (0) {
}
Testing openssl_x509_check_private_key

View File

@@ -0,0 +1,113 @@
--TEST--
openssl_*() with OPENSSL_KEYTYPE_EC for ec custom params
--EXTENSIONS--
openssl
--SKIPIF--
<?php
if (!defined("OPENSSL_KEYTYPE_EC")) die("skip EC disabled");
?>
--FILE--
<?php
// EC - generate keypair with curve_name
echo "Testing openssl_pkey_new with ec curve_name\n";
$curve_name = openssl_get_curve_names()[0];
$ec = openssl_pkey_new(array(
'ec'=> array(
'curve_name' => $curve_name,
)
));
var_dump($ec);
$details = openssl_pkey_get_details($ec);
$ec_details = $details['ec'];
var_dump($ec_details['curve_name'] === $curve_name);
// EC - generate keypair from priv_key "d" with explicit parameters (OSCCA WAPIP192v1 Elliptic curve)
echo "Testing openssl_pkey_new with ec explicit parameters\n";
$d = hex2bin('8D0AC65AAEA0D6B96254C65817D4A143A9E7A03876F1A37D');
$x = hex2bin('98E07AAD50C31F9189EBE6B8B5C70E5DEE59D7A8BC344CC6');
$y = hex2bin('6109D3D96E52D0867B9D05D72D07BE5876A3D973E0E96792');
$p = hex2bin('BDB6F4FE3E8B1D9E0DA8C0D46F4C318CEFE4AFE3B6B8551F');
$a = hex2bin('BB8E5E8FBC115E139FE6A814FE48AAA6F0ADA1AA5DF91985');
$b = hex2bin('1854BEBDC31B21B7AEFC80AB0ECD10D5B1B3308E6DBF11C1');
$g_x = hex2bin('4AD5F7048DE709AD51236DE65E4D4B482C836DC6E4106640');
$g_y = hex2bin('02BB3A02D4AAADACAE24817A4CA3A1B014B5270432DB27D2');
$order = hex2bin('BDB6F4FE3E8B1D9E0DA8C0D40FC962195DFAE76F56564677');
$ec = openssl_pkey_new(array(
'ec'=> array(
'p' => $p,
'a' => $a,
'b' => $b,
'order' => $order,
'g_x' => $g_x,
'g_y' => $g_y,
'd' => $d,
)
));
$details = openssl_pkey_get_details($ec);
$ec_details = $details['ec'];
var_dump($ec_details['x'] === $x);
var_dump($ec_details['y'] === $y);
var_dump($ec_details['d'] === $d);
echo "Testing openssl_pkey_new with ec missing params \n";
// EC - invalid curve_name
$ec = openssl_pkey_new(array(
'ec'=> array(
'curve_name' => 'invalid_curve_name',
)
));
var_dump($ec);
// EC - missing all params
$ec = openssl_pkey_new(array(
'ec'=> array()
));
var_dump($ec);
// EC - missing "p" param
$ec = openssl_pkey_new(array(
'ec'=> array(
'a' => $a,
'b' => $b,
'order' => $order
)
));
var_dump($ec);
// EC - missing "generator" or "g_x" and "g_y" param
$ec = openssl_pkey_new(array(
'ec'=> array(
'p' => $p,
'a' => $a,
'b' => $b,
'order' => $order
)
));
var_dump($ec);
?>
--EXPECTF--
Testing openssl_pkey_new with ec curve_name
object(OpenSSLAsymmetricKey)#%d (0) {
}
bool(true)
Testing openssl_pkey_new with ec explicit parameters
bool(true)
bool(true)
bool(true)
Testing openssl_pkey_new with ec missing params
Warning: openssl_pkey_new(): Unknown elliptic curve (short) name invalid_curve_name in %s on line %d
bool(false)
Warning: openssl_pkey_new(): Missing params: curve_name in %s on line %d
bool(false)
Warning: openssl_pkey_new(): Missing params: curve_name or p, a, b, order in %s on line %d
bool(false)
Warning: openssl_pkey_new(): Missing params: generator or g_x and g_y in %s on line %d
bool(false)

View File

@@ -0,0 +1,92 @@
--TEST--
openssl_*() with OPENSSL_KEYTYPE_EC for SM2
--EXTENSIONS--
openssl
--SKIPIF--
<?php
if (!defined("OPENSSL_KEYTYPE_EC")) die("skip EC disabled");
if (!in_array('SM2', openssl_get_curve_names())) die("skip SM2 disabled");
?>
--FILE--
<?php
// EC - generate SM2 keypair with curve_name
echo "Testing openssl_pkey_new with ec curve_name SM2\n";
$ec = openssl_pkey_new(array(
'ec'=> array(
'curve_name' => 'SM2',
)
));
var_dump($ec);
$details = openssl_pkey_get_details($ec);
var_dump($details["bits"]);
var_dump(strlen($details["key"]));
var_dump($details["ec"]["curve_name"]);
var_dump($details["type"] == OPENSSL_KEYTYPE_EC);
// EC - generate SM2 keypair with curve_name
echo "Testing openssl_pkey_get_public from SM2 pem pubkey\n";
$public_key = openssl_pkey_get_public($details["key"]);
var_dump($public_key);
$details_public_key = openssl_pkey_get_details($public_key);
var_dump(strlen($details["key"]));
var_dump($details_public_key["ec"]["curve_name"]);
var_dump($details["type"] == OPENSSL_KEYTYPE_EC);
var_dump($details_public_key["ec"]["x"] === $details["ec"]["x"]);
var_dump($details_public_key["ec"]["y"] === $details["ec"]["y"]);
// EC - generate keypair with explicit parameters (SM2 curve)
echo "Testing openssl_pkey_new with ec explicit parameters (SM2 curve)\n";
$p = hex2bin('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF');
$a = hex2bin('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC');
$b = hex2bin('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93');
$g_x = hex2bin('32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7');
$g_y = hex2bin('BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0');
$order = hex2bin('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123');
$ec = openssl_pkey_new(array(
'ec'=> array(
'p' => $p,
'a' => $a,
'b' => $b,
'order' => $order,
'g_x' => $g_x,
'g_y' => $g_y
)
));
$details = openssl_pkey_get_details($ec);
var_dump($details['bits']);
var_dump(strlen($details['key']));
var_dump($details['type'] == OPENSSL_KEYTYPE_EC);
$public_key = openssl_pkey_get_public($details["key"]);
$details_public_key = openssl_pkey_get_details($public_key);
var_dump(strlen($details["key"]));
var_dump($details["type"] == OPENSSL_KEYTYPE_EC);
var_dump($details_public_key["ec"]["x"] === $details["ec"]["x"]);
var_dump($details_public_key["ec"]["y"] === $details["ec"]["y"]);
?>
--EXPECTF--
Testing openssl_pkey_new with ec curve_name SM2
object(OpenSSLAsymmetricKey)#%d (0) {
}
int(256)
int(178)
string(3) "SM2"
bool(true)
Testing openssl_pkey_get_public from SM2 pem pubkey
object(OpenSSLAsymmetricKey)#%d (0) {
}
int(178)
string(3) "SM2"
bool(true)
bool(true)
bool(true)
Testing openssl_pkey_new with ec explicit parameters (SM2 curve)
int(256)
int(475)
bool(true)
int(475)
bool(true)
bool(true)
bool(true)