aboutsummaryrefslogtreecommitdiff
path: root/src/modules/schnorr/main_impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/schnorr/main_impl.h')
-rw-r--r--src/modules/schnorr/main_impl.h164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/modules/schnorr/main_impl.h b/src/modules/schnorr/main_impl.h
new file mode 100644
index 0000000000..fa176a1767
--- /dev/null
+++ b/src/modules/schnorr/main_impl.h
@@ -0,0 +1,164 @@
+/**********************************************************************
+ * Copyright (c) 2014-2015 Pieter Wuille *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#ifndef SECP256K1_MODULE_SCHNORR_MAIN
+#define SECP256K1_MODULE_SCHNORR_MAIN
+
+#include "include/secp256k1_schnorr.h"
+#include "modules/schnorr/schnorr_impl.h"
+
+static void secp256k1_schnorr_msghash_sha256(unsigned char *h32, const unsigned char *r32, const unsigned char *msg32) {
+ secp256k1_sha256_t sha;
+ secp256k1_sha256_initialize(&sha);
+ secp256k1_sha256_write(&sha, r32, 32);
+ secp256k1_sha256_write(&sha, msg32, 32);
+ secp256k1_sha256_finalize(&sha, h32);
+}
+
+static const unsigned char secp256k1_schnorr_algo16[17] = "Schnorr+SHA256 ";
+
+int secp256k1_schnorr_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) {
+ secp256k1_scalar sec, non;
+ int ret = 0;
+ int overflow = 0;
+ unsigned int count = 0;
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
+ ARG_CHECK(msg32 != NULL);
+ ARG_CHECK(sig64 != NULL);
+ ARG_CHECK(seckey != NULL);
+ if (noncefp == NULL) {
+ noncefp = secp256k1_nonce_function_default;
+ }
+
+ secp256k1_scalar_set_b32(&sec, seckey, NULL);
+ while (1) {
+ unsigned char nonce32[32];
+ ret = noncefp(nonce32, msg32, seckey, secp256k1_schnorr_algo16, (void*)noncedata, count);
+ if (!ret) {
+ break;
+ }
+ secp256k1_scalar_set_b32(&non, nonce32, &overflow);
+ memset(nonce32, 0, 32);
+ if (!secp256k1_scalar_is_zero(&non) && !overflow) {
+ if (secp256k1_schnorr_sig_sign(&ctx->ecmult_gen_ctx, sig64, &sec, &non, NULL, secp256k1_schnorr_msghash_sha256, msg32)) {
+ break;
+ }
+ }
+ count++;
+ }
+ if (!ret) {
+ memset(sig64, 0, 64);
+ }
+ secp256k1_scalar_clear(&non);
+ secp256k1_scalar_clear(&sec);
+ return ret;
+}
+
+int secp256k1_schnorr_verify(const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msg32, const secp256k1_pubkey *pubkey) {
+ secp256k1_ge q;
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
+ ARG_CHECK(msg32 != NULL);
+ ARG_CHECK(sig64 != NULL);
+ ARG_CHECK(pubkey != NULL);
+
+ secp256k1_pubkey_load(ctx, &q, pubkey);
+ return secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64, &q, secp256k1_schnorr_msghash_sha256, msg32);
+}
+
+int secp256k1_schnorr_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *sig64, const unsigned char *msg32) {
+ secp256k1_ge q;
+
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
+ ARG_CHECK(msg32 != NULL);
+ ARG_CHECK(sig64 != NULL);
+ ARG_CHECK(pubkey != NULL);
+
+ if (secp256k1_schnorr_sig_recover(&ctx->ecmult_ctx, sig64, &q, secp256k1_schnorr_msghash_sha256, msg32)) {
+ secp256k1_pubkey_save(pubkey, &q);
+ return 1;
+ } else {
+ memset(pubkey, 0, sizeof(*pubkey));
+ return 0;
+ }
+}
+
+int secp256k1_schnorr_generate_nonce_pair(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, unsigned char *privnonce32, const unsigned char *sec32, const unsigned char *msg32, secp256k1_nonce_function noncefp, const void* noncedata) {
+ int count = 0;
+ int ret = 1;
+ secp256k1_gej Qj;
+ secp256k1_ge Q;
+ secp256k1_scalar sec;
+
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
+ ARG_CHECK(msg32 != NULL);
+ ARG_CHECK(sec32 != NULL);
+ ARG_CHECK(pubnonce != NULL);
+ ARG_CHECK(privnonce32 != NULL);
+
+ if (noncefp == NULL) {
+ noncefp = secp256k1_nonce_function_default;
+ }
+
+ do {
+ int overflow;
+ ret = noncefp(privnonce32, sec32, msg32, secp256k1_schnorr_algo16, (void*)noncedata, count++);
+ if (!ret) {
+ break;
+ }
+ secp256k1_scalar_set_b32(&sec, privnonce32, &overflow);
+ if (overflow || secp256k1_scalar_is_zero(&sec)) {
+ continue;
+ }
+ secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &sec);
+ secp256k1_ge_set_gej(&Q, &Qj);
+
+ secp256k1_pubkey_save(pubnonce, &Q);
+ break;
+ } while(1);
+
+ secp256k1_scalar_clear(&sec);
+ if (!ret) {
+ memset(pubnonce, 0, sizeof(*pubnonce));
+ }
+ return ret;
+}
+
+int secp256k1_schnorr_partial_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const unsigned char *sec32, const secp256k1_pubkey *pubnonce_others, const unsigned char *secnonce32) {
+ int overflow = 0;
+ secp256k1_scalar sec, non;
+ secp256k1_ge pubnon;
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
+ ARG_CHECK(msg32 != NULL);
+ ARG_CHECK(sig64 != NULL);
+ ARG_CHECK(sec32 != NULL);
+ ARG_CHECK(secnonce32 != NULL);
+ ARG_CHECK(pubnonce_others != NULL);
+
+ secp256k1_scalar_set_b32(&sec, sec32, &overflow);
+ if (overflow || secp256k1_scalar_is_zero(&sec)) {
+ return -1;
+ }
+ secp256k1_scalar_set_b32(&non, secnonce32, &overflow);
+ if (overflow || secp256k1_scalar_is_zero(&non)) {
+ return -1;
+ }
+ secp256k1_pubkey_load(ctx, &pubnon, pubnonce_others);
+ return secp256k1_schnorr_sig_sign(&ctx->ecmult_gen_ctx, sig64, &sec, &non, &pubnon, secp256k1_schnorr_msghash_sha256, msg32);
+}
+
+int secp256k1_schnorr_partial_combine(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char * const *sig64sin, size_t n) {
+ ARG_CHECK(sig64 != NULL);
+ ARG_CHECK(n >= 1);
+ ARG_CHECK(sig64sin != NULL);
+ return secp256k1_schnorr_sig_combine(sig64, n, sig64sin);
+}
+
+#endif