private static secp256k1_context secp256k1_context_create(Secp256K1Options flags) { var ret = new secp256k1_context { illegal_callback = IllegalCallback, error_callback = ErrorCallback }; if ((flags & Secp256K1Options.FlagsTypeMask) != Secp256K1Options.FlagsTypeContext) { ret.illegal_callback?.Invoke(null, new secp256k1_callback("Invalid flags")); return(null); } ECMult.secp256k1_ecmult_context_init(ret.ecmult_ctx); ECMultGen.secp256k1_ecmult_gen_context_init(ret.ecmult_gen_ctx); if (flags.HasFlag(Secp256K1Options.FlagsBitContextSign)) { ECMultGen.secp256k1_ecmult_gen_context_build(ret.ecmult_gen_ctx, ret.error_callback); } if (flags.HasFlag(Secp256K1Options.FlagsBitContextVerify)) { ECMult.secp256k1_ecmult_context_build(ret.ecmult_ctx, ret.error_callback); } return(ret); }
private static bool secp256k1_ecdsa_sig_sign(secp256k1_ecmult_gen_context ctx, secp256k1_scalar sigr, secp256k1_scalar sigs, secp256k1_scalar seckey, secp256k1_scalar message, secp256k1_scalar nonce, out byte recid) { var b = new byte[32]; secp256k1_gej rp; secp256k1_ge r = new secp256k1_ge(); secp256k1_scalar n = new secp256k1_scalar(); bool overflow = false; ECMultGen.secp256k1_ecmult_gen(ctx, out rp, nonce); Group.secp256k1_ge_set_gej(r, rp); Field.secp256k1_fe_normalize(r.x); Field.secp256k1_fe_normalize(r.y); Field.secp256k1_fe_get_b32(b, r.x); Scalar.secp256k1_scalar_set_b32(sigr, b, ref overflow); /* These two conditions should be checked before calling */ Util.VERIFY_CHECK(!Scalar.secp256k1_scalar_is_zero(sigr)); Util.VERIFY_CHECK(!overflow); // The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log // of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria. recid = (byte)((overflow ? 2 : 0) | (Field.secp256k1_fe_is_odd(r.y) ? 1 : 0)); Scalar.secp256k1_scalar_mul(n, sigr, seckey); Scalar.secp256k1_scalar_add(n, n, message); Scalar.secp256k1_scalar_inverse(sigs, nonce); Scalar.secp256k1_scalar_mul(sigs, sigs, n); Scalar.secp256k1_scalar_clear(n); Group.secp256k1_gej_clear(rp); Group.secp256k1_ge_clear(r); if (Scalar.secp256k1_scalar_is_zero(sigs)) { return(false); } if (Scalar.secp256k1_scalar_is_high(sigs)) { Scalar.secp256k1_scalar_negate(sigs, sigs); recid ^= 1; } return(true); }
private static bool secp256k1_ecdsa_sign_recoverable(secp256k1_context ctx, secp256k1_ecdsa_recoverable_signature signature, byte[] msg32, byte[] seckey, secp256k1_nonce_function noncefp, byte[] noncedata) { if (ctx == null || msg32 == null || signature == null || seckey == null) { throw new NullReferenceException(); } if (!ECMultGen.secp256k1_ecmult_gen_context_is_built(ctx.ecmult_gen_ctx)) { throw new ArithmeticException(); } if (noncefp == null) { noncefp = Secp256k1.secp256k1_nonce_function_default; } secp256k1_scalar r, s; secp256k1_scalar sec, non, msg; byte recid = 1; bool ret = false; var overflow = false; sec = new secp256k1_scalar(); Scalar.secp256k1_scalar_set_b32(sec, seckey, ref overflow); r = new secp256k1_scalar(); s = new secp256k1_scalar(); /* Fail if the secret key is invalid. */ if (!overflow && !Scalar.secp256k1_scalar_is_zero(sec)) { var nonce32 = new byte[32]; uint count = 0; msg = new secp256k1_scalar(); Scalar.secp256k1_scalar_set_b32(msg, msg32); non = new secp256k1_scalar(); while (true) { ret = noncefp(nonce32, msg32, seckey, null, noncedata, count); if (!ret) { break; } Scalar.secp256k1_scalar_set_b32(non, nonce32, ref overflow); if (!Scalar.secp256k1_scalar_is_zero(non) && !overflow) { if (secp256k1_ecdsa_sig_sign(ctx.ecmult_gen_ctx, r, s, sec, msg, non, out recid)) { break; } } count++; } Util.MemSet(nonce32, 0, 32); //memset(nonce32, 0, 32); Scalar.secp256k1_scalar_clear(msg); Scalar.secp256k1_scalar_clear(non); Scalar.secp256k1_scalar_clear(sec); } if (ret) { secp256k1_ecdsa_recoverable_signature_save(signature, r, s, recid); } else { Util.MemSet(signature.data, 0, secp256k1_ecdsa_recoverable_signature.Size); //memset(signature, 0, sizeof(* signature)); } return(ret); }