Skip to content

Commit 040e0cc

Browse files
Thomas Kerinafk11
Thomas Kerin
authored andcommittedFeb 13, 2018
add secp256k1_ec_privkey_negate function and tests
1 parent 0eb676b commit 040e0cc

7 files changed

+153
-0
lines changed
 

‎secp256k1/php_secp256k1.h

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ PHP_FUNCTION(secp256k1_ecdsa_signature_serialize_der);
4242
PHP_FUNCTION(secp256k1_ecdsa_signature_normalize);
4343

4444
PHP_FUNCTION(secp256k1_ec_seckey_verify);
45+
PHP_FUNCTION(secp256k1_ec_privkey_negate);
4546
PHP_FUNCTION(secp256k1_ec_pubkey_create);
4647
PHP_FUNCTION(secp256k1_ec_pubkey_combine);
4748
PHP_FUNCTION(secp256k1_ec_pubkey_parse);

‎secp256k1/secp256k1.c

+45
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ ZEND_BEGIN_ARG_INFO(arginfo_secp256k1_ec_pubkey_create, 0)
133133
ZEND_ARG_INFO(0, secretKey)
134134
ZEND_END_ARG_INFO();
135135

136+
ZEND_BEGIN_ARG_INFO(arginfo_secp256k1_ec_privkey_negate, 0)
137+
ZEND_ARG_INFO(0, context)
138+
ZEND_ARG_INFO(1, secKey)
139+
ZEND_END_ARG_INFO();
140+
136141
ZEND_BEGIN_ARG_INFO(arginfo_secp256k1_ec_privkey_tweak_add, 0)
137142
ZEND_ARG_INFO(0, context)
138143
ZEND_ARG_INFO(1, seckey)
@@ -185,6 +190,7 @@ const zend_function_entry secp256k1_functions[] = {
185190
PHP_FE(secp256k1_ec_seckey_verify, arginfo_secp256k1_ec_seckey_verify)
186191

187192
PHP_FE(secp256k1_ec_pubkey_create, arginfo_secp256k1_ec_pubkey_create)
193+
PHP_FE(secp256k1_ec_privkey_negate, arginfo_secp256k1_ec_privkey_negate)
188194
PHP_FE(secp256k1_ec_pubkey_parse, arginfo_secp256k1_ec_pubkey_parse)
189195
PHP_FE(secp256k1_ec_pubkey_combine, arginfo_secp256k1_ec_pubkey_combine)
190196
PHP_FE(secp256k1_ec_pubkey_serialize, arginfo_secp256k1_ec_pubkey_serialize)
@@ -747,6 +753,45 @@ PHP_FUNCTION(secp256k1_ec_pubkey_create)
747753
}
748754
/* }}} */
749755

756+
/** Negates a private key in place.
757+
* Returns: 1 always
758+
* Args: ctx: pointer to a context object
759+
* In/Out: pubkey: pointer to the public key to be negated (cannot be NULL)
760+
*/
761+
PHP_FUNCTION(secp256k1_ec_privkey_negate)
762+
{
763+
zval *zCtx, *zPrivKey;
764+
secp256k1_context *ctx;
765+
unsigned char *newseckey;
766+
int result;
767+
768+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz/", &zCtx, &zPrivKey) == FAILURE) {
769+
RETURN_FALSE;
770+
}
771+
772+
if ((ctx = (secp256k1_context *)zend_fetch_resource2_ex(zCtx, SECP256K1_CTX_RES_NAME, le_secp256k1_ctx, -1)) == NULL) {
773+
RETURN_FALSE;
774+
}
775+
776+
if (Z_TYPE_P(zPrivKey) != IS_STRING) {
777+
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "secp256k1_ec_privkey_negate(): Parameter 2 should be string");
778+
return;
779+
}
780+
781+
if (Z_STRLEN_P(zPrivKey) != SECRETKEY_LENGTH) {
782+
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "secp256k1_ec_privkey_negate(): Parameter 2 should be 32 bytes");
783+
return;
784+
}
785+
786+
newseckey = (unsigned char *) emalloc(SECRETKEY_LENGTH);
787+
memcpy(newseckey, Z_STRVAL_P(zPrivKey), SECRETKEY_LENGTH);
788+
result = secp256k1_ec_privkey_negate(ctx, newseckey);
789+
zval_dtor(zPrivKey);
790+
ZVAL_STRINGL(zPrivKey, newseckey, SECRETKEY_LENGTH);
791+
792+
RETURN_LONG(result);
793+
}
794+
750795
/* Parse a variable length public key into a public key resource */
751796
/** {{{ proto int secp256k1_ec_pubkey_parse(resource secp256k1_context, string publicKey)
752797
* In: ctx: a secp256k1_context resource
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
secp256k1_ec_privkey_negate works
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("secp256k1")) print "skip extension not loaded";
6+
?>
7+
--FILE--
8+
<?php
9+
$ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
10+
11+
$privKey = pack("H*", "0000000000000000000000000000000000000000000000000000000000000001");
12+
$result = secp256k1_ec_privkey_negate($ctx, $privKey);
13+
echo $result . PHP_EOL;
14+
echo unpack("H*", $privKey)[1] . PHP_EOL;
15+
16+
$result = secp256k1_ec_privkey_negate($ctx, $privKey);
17+
echo $result . PHP_EOL;
18+
echo unpack("H*", $privKey)[1] . PHP_EOL;
19+
20+
?>
21+
--EXPECT--
22+
1
23+
fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140
24+
1
25+
0000000000000000000000000000000000000000000000000000000000000001
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
secp256k1_ec_privkey_negate returns false if context is wrong resource type
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("secp256k1")) print "skip extension not loaded";
6+
?>
7+
--FILE--
8+
<?php
9+
10+
set_error_handler(function($code, $str) { echo $str . PHP_EOL; });
11+
12+
$keyTweak = str_repeat("A", 32);
13+
$context = tmpfile();
14+
$result = secp256k1_ec_privkey_negate($context, $keyTweak);
15+
echo gettype($result) . PHP_EOL;
16+
echo ($result ? "true" : "false") . PHP_EOL;
17+
18+
?>
19+
--EXPECT--
20+
secp256k1_ec_privkey_negate(): supplied resource is not a valid secp256k1_context resource
21+
boolean
22+
false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
secp256k1_ec_privkey_negate returns false if parameter parsing fails
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("secp256k1")) print "skip extension not loaded";
6+
?>
7+
--FILE--
8+
<?php
9+
10+
set_error_handler(function($code, $str) { echo $str . PHP_EOL; });
11+
12+
$ctx1 = secp256k1_ec_privkey_negate();
13+
echo gettype($ctx1) . PHP_EOL;
14+
echo ($ctx1 ? "true" : "false") . PHP_EOL;
15+
16+
?>
17+
--EXPECT--
18+
secp256k1_ec_privkey_negate() expects exactly 2 parameters, 0 given
19+
boolean
20+
false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
secp256k1_ec_privkey_negate throws exception if privKey is not a string
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("secp256k1")) print "skip extension not loaded";
6+
?>
7+
--FILE--
8+
<?php
9+
$ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
10+
11+
$privKey = 1;
12+
try {
13+
secp256k1_ec_privkey_negate($ctx, $privKey);
14+
} catch (\Exception $e) {
15+
echo $e->getMessage() . PHP_EOL;
16+
}
17+
18+
?>
19+
--EXPECT--
20+
secp256k1_ec_privkey_negate(): Parameter 2 should be string
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
secp256k1_ec_privkey_negate throws exception if privKey is not 32 bytes
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("secp256k1")) print "skip extension not loaded";
6+
?>
7+
--FILE--
8+
<?php
9+
$ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
10+
11+
$privKey = "1234abcd";
12+
try {
13+
secp256k1_ec_privkey_negate($ctx, $privKey);
14+
} catch (\Exception $e) {
15+
echo $e->getMessage() . PHP_EOL;
16+
}
17+
18+
?>
19+
--EXPECT--
20+
secp256k1_ec_privkey_negate(): Parameter 2 should be 32 bytes

0 commit comments

Comments
 (0)
Please sign in to comment.