ecdsa_adaptor: add nonce function and tags

This commit adds a nonce function that will be used by default
for ECDSA adaptor signatures.

This nonce function is similar to secp256k1_nonce_function_hardened
except it uses the compressed 33-byte encoding for the pubkey argument.
We need 33 bytes instead of 32 because, unlike with BIP-340, an ECDSA
X-coordinate alone is not sufficient to disambiguate the Y-coordinate.
This commit is contained in:
Jesse Posner 2021-03-05 00:00:13 -08:00
parent 654cd633f5
commit d8f336564f
3 changed files with 113 additions and 0 deletions

View File

@ -12,6 +12,40 @@ extern "C" {
* and https://github.com/LLFourn/one-time-VES/blob/master/main.pdf). * and https://github.com/LLFourn/one-time-VES/blob/master/main.pdf).
*/ */
/** A pointer to a function to deterministically generate a nonce.
*
* Same as secp256k1_nonce_function_hardened with the exception of using the
* compressed 33-byte encoding for the pubkey argument.
*
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to
* return an error.
* Out: nonce32: pointer to a 32-byte array to be filled by the function
* In: msg32: the 32-byte message hash being verified
* key32: pointer to a 32-byte secret key
* pk33: the 33-byte serialized pubkey corresponding to key32
* algo: pointer to an array describing the signature algorithm
* algolen: the length of the algo array
* data: arbitrary data pointer that is passed through
*
* Except for test cases, this function should compute some cryptographic hash of
* the message, the key, the pubkey, the algorithm description, and data.
*/
typedef int (*secp256k1_nonce_function_hardened_ecdsa_adaptor)(
unsigned char *nonce32,
const unsigned char *msg32,
const unsigned char *key32,
const unsigned char *pk33,
const unsigned char *algo,
size_t algolen,
void *data
);
/** A modified BIP-340 nonce generation function. If a data pointer is passed, it is
* assumed to be a pointer to 32 bytes of auxiliary random data as defined in BIP-340.
* The hash will be tagged with algo after removing all terminating null bytes.
*/
SECP256K1_API extern const secp256k1_nonce_function_hardened_ecdsa_adaptor secp256k1_nonce_function_ecdsa_adaptor;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1 +1,2 @@
include_HEADERS += include/secp256k1_ecdsa_adaptor.h include_HEADERS += include/secp256k1_ecdsa_adaptor.h
noinst_HEADERS += src/modules/ecdsa_adaptor/main_impl.h

View File

@ -9,4 +9,82 @@
#include "include/secp256k1_ecdsa_adaptor.h" #include "include/secp256k1_ecdsa_adaptor.h"
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("ECDSAadaptor/non")||SHA256("ECDSAadaptor/non"). */
static void secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged(secp256k1_sha256 *sha) {
secp256k1_sha256_initialize(sha);
sha->s[0] = 0x791dae43ul;
sha->s[1] = 0xe52d3b44ul;
sha->s[2] = 0x37f9edeaul;
sha->s[3] = 0x9bfd2ab1ul;
sha->s[4] = 0xcfb0f44dul;
sha->s[5] = 0xccf1d880ul;
sha->s[6] = 0xd18f2c13ul;
sha->s[7] = 0xa37b9024ul;
sha->bytes = 64;
}
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("ECDSAadaptor/aux")||SHA256("ECDSAadaptor/aux"). */
static void secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged_aux(secp256k1_sha256 *sha) {
secp256k1_sha256_initialize(sha);
sha->s[0] = 0xd14c7bd9ul;
sha->s[1] = 0x095d35e6ul;
sha->s[2] = 0xb8490a88ul;
sha->s[3] = 0xfb00ef74ul;
sha->s[4] = 0x0baa488ful;
sha->s[5] = 0x69366693ul;
sha->s[6] = 0x1c81c5baul;
sha->s[7] = 0xc33b296aul;
sha->bytes = 64;
}
/* algo argument for nonce_function_ecdsa_adaptor to derive the nonce using a tagged hash function. */
static const unsigned char ecdsa_adaptor_algo[16] = "ECDSAadaptor/non";
/* Modified BIP-340 nonce function */
static int nonce_function_ecdsa_adaptor(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *pk33, const unsigned char *algo, size_t algolen, void *data) {
secp256k1_sha256 sha;
unsigned char masked_key[32];
int i;
if (algo == NULL) {
return 0;
}
if (data != NULL) {
secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged_aux(&sha);
secp256k1_sha256_write(&sha, data, 32);
secp256k1_sha256_finalize(&sha, masked_key);
for (i = 0; i < 32; i++) {
masked_key[i] ^= key32[i];
}
}
/* Tag the hash with algo which is important to avoid nonce reuse across
* algorithims. An optimized tagging implementation is used if the default
* tag is provided. */
if (algolen == sizeof(ecdsa_adaptor_algo)
&& secp256k1_memcmp_var(algo, ecdsa_adaptor_algo, algolen) == 0) {
secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged(&sha);
} else {
secp256k1_sha256_initialize_tagged(&sha, algo, algolen);
}
/* Hash (masked-)key||pk||msg using the tagged hash as per BIP-340 */
if (data != NULL) {
secp256k1_sha256_write(&sha, masked_key, 32);
} else {
secp256k1_sha256_write(&sha, key32, 32);
}
secp256k1_sha256_write(&sha, pk33, 33);
secp256k1_sha256_write(&sha, msg32, 32);
secp256k1_sha256_finalize(&sha, nonce32);
return 1;
}
const secp256k1_nonce_function_hardened_ecdsa_adaptor secp256k1_nonce_function_ecdsa_adaptor = nonce_function_ecdsa_adaptor;
#endif #endif