예제 #1
0
        public static bool TrySignAdaptor(this ECPrivKey key, ReadOnlySpan <byte> msg32, ECPubKey adaptor, out SecpECDSAAdaptorSignature?adaptorSignature, out SecpECDSAAdaptorProof?proof)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (adaptor == null)
            {
                throw new ArgumentNullException(nameof(adaptor));
            }
            if (msg32.Length < 32)
            {
                throw new ArgumentException(paramName: nameof(msg32), message: "msg32 should be at least 32 bytes");
            }
            var    adaptor_ge = adaptor.Q;
            var    seckey32   = key.sec;
            SHA256 sha        = new SHA256();

            sha.Write(msg32.Slice(0, 32));
            Span <byte> buf33 = stackalloc byte[33];

            Internals.secp256k1_dleq_serialize_point(buf33, adaptor_ge);
            sha.Write(buf33);
            sha.GetHash(buf33);
            Span <byte> nonce32 = stackalloc byte[32];

            nonce_function_dleq(buf33, key.sec, "ECDSAAdaptorNon", nonce32);
            var k = new Scalar(nonce32);

            if (k.IsZero)
            {
                adaptorSignature = default;
                proof            = default;
                return(false);
            }
            var rpj = key.ctx.EcMultGenContext.MultGen(k);
            /* 2. R = k*Y; */
            var rj = adaptor_ge.MultConst(k, 256);

            /* 4. [sic] proof = DLEQ_prove((G,R'),(Y, R)) */
            if (!key.ctx.EcMultGenContext.secp256k1_dleq_proof("ECDSAAdaptorSig", k, adaptor_ge, out var dleq_proof_s, out var dleq_proof_e))
            {
                adaptorSignature = default;
                proof            = default;
                return(false);
            }

            /* 5. s' = k⁻¹(H(m) + x_coord(R)x) */
            var r   = rj.ToGroupElement();
            var msg = new Scalar(msg32);

            if (!secp256k1_ecdsa_adaptor_sign_helper(msg, k, r, key.sec, out var sp))
            {
                k = default;
                adaptorSignature = default;
                proof            = default;
                return(false);
            }

            /* 6. return (R, R', s', proof) */
            var rp = rpj.ToGroupElement();

            proof            = new SecpECDSAAdaptorProof(rp, dleq_proof_s, dleq_proof_e);
            adaptorSignature = new SecpECDSAAdaptorSignature(r, sp);
            k = default;
            return(true);
        }
예제 #2
0
        public static bool SigVerify(this ECPubKey pubKey, SecpECDSAAdaptorSignature sig, SecpECDSAAdaptorProof proof, ReadOnlySpan <byte> msg32, ECPubKey adaptor)
        {
            if (pubKey == null)
            {
                throw new ArgumentNullException(nameof(pubKey));
            }
            if (adaptor == null)
            {
                throw new ArgumentNullException(nameof(adaptor));
            }
            if (msg32.Length < 32)
            {
                throw new ArgumentException(paramName: nameof(msg32), message: "msg32 should be at least 32 bytes");
            }
            if (sig == null)
            {
                throw new ArgumentNullException(nameof(sig));
            }
            var adaptor_ge = adaptor.Q;

            if (!secp256k1_dleq_verify(pubKey.ctx.EcMultContext, "ECDSAAdaptorSig", proof.s, proof.e, proof.rp, adaptor_ge, sig.r))
            {
                return(false);
            }

            /* 2. return x_coord(R') == x_coord(s'⁻¹(H(m) * G + x_coord(R) * X)) */
            var q   = pubKey.Q;
            var msg = new Scalar(msg32);

            if (!pubKey.ctx.secp256k1_ecdsa_adaptor_sig_verify_helper(sig.r.x.ToScalar(), sig.sp, q, msg, out var rhs))
            {
                return(false);
            }
            var lhs = proof.rp.ToGroupElementJacobian();

            rhs = rhs.Negate();
            lhs = lhs.AddVariable(rhs, out _);
            return(lhs.IsInfinity);
        }