Example #1
0
        public static byte[] SignRaw(ECPrivateKey sk, IDigest rfc6979Hash,
                                     byte[] hash, int hashOff, int hashLen)
        {
            ECCurve curve = sk.Curve;

            byte[]  q  = curve.SubgroupOrder;
            RFC6979 rf = new RFC6979(rfc6979Hash, q, sk.X,
                                     hash, hashOff, hashLen, rfc6979Hash != null);
            ModInt mh = rf.GetHashMod();
            ModInt mx = mh.Dup();

            mx.Decode(sk.X);

            /*
             * Compute DSA signature. We use a loop to enumerate
             * candidates for k until a proper one is found (it
             * is VERY improbable that we may have to loop).
             */
            ModInt mr = mh.Dup();
            ModInt ms = mh.Dup();
            ModInt mk = mh.Dup();

            byte[] k = new byte[q.Length];
            for (;;)
            {
                rf.NextK(k);
                MutableECPoint G = curve.MakeGenerator();
                if (G.MulSpecCT(k) == 0)
                {
                    /*
                     * We may get an error here only if the
                     * curve is invalid (generator does not
                     * produce the expected subgroup).
                     */
                    throw new CryptoException(
                              "Invalid EC private key / curve");
                }
                mr.DecodeReduce(G.X);
                if (mr.IsZero)
                {
                    continue;
                }
                ms.Set(mx);
                ms.ToMonty();
                ms.MontyMul(mr);
                ms.Add(mh);
                mk.Decode(k);
                mk.Invert();
                ms.ToMonty();
                ms.MontyMul(mk);

                byte[] sig = new byte[q.Length << 1];
                mr.Encode(sig, 0, q.Length);
                ms.Encode(sig, q.Length, q.Length);
                return(sig);
            }
        }
        internal override void Set(MutableECPoint Q)
        {
            MutableECPointPrime R = SameCurve(Q);

            mx.Set(R.mx);
            my.Set(R.my);
            mz.Set(R.mz);
            affine = R.affine;
        }
        internal override void Set(MutableECPoint Q, uint ctl)
        {
            MutableECPointPrime R = SameCurve(Q);

            mx.CondCopy(R.mx, ctl);
            my.CondCopy(R.my, ctl);
            mz.CondCopy(R.mz, ctl);
            affine ^= ctl & (affine ^ R.affine);
        }
Example #4
0
        MutableECPointCurve25519 SameCurve(MutableECPoint Q)
        {
            MutableECPointCurve25519 R = Q as MutableECPointCurve25519;

            if (R == null)
            {
                throw new CryptoException("Mixed curves");
            }
            return(R);
        }
Example #5
0
        /*
         * Multiply the provided (encoded) point G by a scalar x. Scalar
         * encoding is big-endian. The scalar value shall be non-zero and
         * lower than the subgroup order (exception: some curves allow
         * larger ranges).
         *
         * The result is written in the provided D[] array, using either
         * compressed or uncompressed format (for some curves, output is
         * always compressed). The array shall have the appropriate length.
         * Returned value is -1 on success, 0 on error. If 0 is returned
         * then the array contents are indeterminate.
         *
         * G and D need not be distinct arrays.
         */
        public uint Mul(byte[] G, byte[] x, byte[] D, bool compressed)
        {
            MutableECPoint P    = MakeZero();
            uint           good = P.DecodeCT(G);

            good &= ~P.IsInfinityCT;
            good &= P.MulSpecCT(x);
            good &= P.Encode(D, compressed);
            return(good);
        }
        MutableECPointPrime SameCurve(MutableECPoint Q)
        {
            MutableECPointPrime R = Q as MutableECPointPrime;

            if (R == null || !curve.Equals(R.curve))
            {
                throw new CryptoException("Mixed curves");
            }
            return(R);
        }
        internal override uint EqCT(MutableECPoint Q)
        {
            MutableECPointPrime R = SameCurve(Q);

            if (affine != 0)
            {
                if (R.affine != 0)
                {
                    return(mx.EqCT(R.mx)
                           & my.EqCT(R.my)
                           & mz.EqCT(R.mz));
                }
                else
                {
                    return(EqCTMixed(R, this));
                }
            }
            else if (R.affine != 0)
            {
                return(EqCTMixed(this, R));
            }

            /*
             * Both points are in Jacobian coordinates.
             * If Z1 and Z2 are non-zero, then equality is
             * achieved if and only if both following equations
             * are true:
             *     X1*(Z2^2) = X2*(Z1^2)
             *     Y1*(Z2^3) = Y2*(Z1^3)
             * If Z1 or Z2 is zero, then equality is achieved
             * if and only if both are zero.
             */
            mt1.Set(mz);
            mt1.MontySquare();
            mt2.Set(R.mz);
            mt2.MontySquare();
            mt3.Set(mx);
            mt3.MontyMul(mt2);
            mt4.Set(R.mx);
            mt4.MontyMul(mt1);
            uint r = mt3.EqCT(mt4);

            mt1.MontyMul(mz);
            mt2.MontyMul(R.mz);
            mt3.Set(my);
            mt3.MontyMul(mt2);
            mt4.Set(R.my);
            mt4.MontyMul(mt1);
            r &= mt3.EqCT(mt4);
            uint z1z = mz.IsZeroCT;
            uint z2z = R.mz.IsZeroCT;

            return((r & ~(z1z | z2z)) ^ (z1z & z2z));
        }
Example #8
0
        /*
         * CheckValid() runs the validity tests on the curve, and
         * verifies that provided point is part of a subgroup with
         * the advertised subgroup order.
         */
        public void CheckValid()
        {
            curve.CheckValid();
            MutableECPoint P = iPub.Dup();

            if (P.MulSpecCT(curve.SubgroupOrder) == 0 ||
                !P.IsInfinity)
            {
                throw new CryptoException(
                          "Public key point not on the defined subgroup");
            }
        }
Example #9
0
 /*
  * Create a new instance with the provided elements. The
  * constructor verifies that the provided point is part of
  * the curve.
  */
 public ECPublicKey(ECCurve curve, byte[] Pub)
 {
     this.curve = curve;
     this.pub   = Pub;
     iPub       = curve.Decode(Pub);
     if (iPub.IsInfinity)
     {
         throw new CryptoException(
                   "Public key point is infinity");
     }
     hashCode = curve.GetHashCode()
                ^ (int)BigInt.HashInt(iPub.X)
                ^ (int)BigInt.HashInt(iPub.Y);
 }
Example #10
0
        internal override uint AddCT(MutableECPoint Q)
        {
            MutableECPointPrime P2 = SameCurve(Q);

            if (P2.affine != 0)
            {
                ms4.Set(P2.mx);
                ms5.Set(P2.my);
                ms6.Set(P2.mz);
                ms4.ToMonty();
                ms5.ToMonty();
                ms6.SetMonty(~ms6.IsZeroCT);
                return(AddCTInner(ms4, ms5, ms6, true));
            }
            else
            {
                return(AddCTInner(P2.mx, P2.my, P2.mz, false));
            }
        }
Example #11
0
        /*
         * Given points A and B, and scalar x and y, return x*A+y*B. This
         * is used for ECDSA. Scalars use big-endian encoding and must be
         * non-zero and lower than the subgroup order.
         *
         * The result is written in the provided D[] array, using either
         * compressed or uncompressed format (for some curves, output is
         * always compressed). The array shall have the appropriate length.
         * Returned value is -1 on success, 0 on error. If 0 is returned
         * then the array contents are indeterminate.
         *
         * Not all curves support this operation; if the curve does not,
         * then an exception is thrown.
         *
         * A, B and D need not be distinct arrays.
         */
        public uint MulAdd(byte[] A, byte[] x, byte[] B, byte[] y,
                           byte[] D, bool compressed)
        {
            MutableECPoint P = MakeZero();
            MutableECPoint Q = MakeZero();

            /*
             * Decode both points.
             */
            uint good = P.DecodeCT(A);

            good &= Q.DecodeCT(B);
            good &= ~P.IsInfinityCT & ~Q.IsInfinityCT;

            /*
             * Perform both point multiplications.
             */
            good &= P.MulSpecCT(x);
            good &= Q.MulSpecCT(y);
            good &= ~P.IsInfinityCT & ~Q.IsInfinityCT;

            /*
             * Perform addition. The AddCT() function may fail if
             * P = Q, in which case we must compute 2Q and use that
             * value instead.
             */
            uint z = P.AddCT(Q);

            Q.DoubleCT();
            P.Set(Q, ~z);

            /*
             * Encode the result. The Encode() function will report
             * an error if the addition result is infinity.
             */
            good &= P.Encode(D, compressed);
            return(good);
        }
Example #12
0
 /*
  * Set this instance to the same contents as the provided point,
  * but only if ctl == 0xFFFFFFFFF. If ctl == 0x00000000, then
  * this instance is unmodified. The operand Q must be part of
  * the same curve.
  */
 internal abstract void Set(MutableECPoint Q, uint ctl);
Example #13
0
        internal override void Set(MutableECPoint Q)
        {
            MutableECPointCurve25519 R = SameCurve(Q);

            x.Set(R.x);
        }
Example #14
0
 internal override void SetMux(uint ctl,
                               MutableECPoint P1, MutableECPoint P2)
 {
     SetMuxInner(ctl, SameCurve(P1), SameCurve(P2));
 }
Example #15
0
        internal override void Set(MutableECPoint Q, uint ctl)
        {
            MutableECPointCurve25519 R = SameCurve(Q);

            x.CondCopy(R.x, ctl);
        }
Example #16
0
 internal override uint AddCT(MutableECPoint Q)
 {
     throw new CryptoException("Not implemented for Curve25519");
 }
Example #17
0
 internal bool Eq(MutableECPoint Q)
 {
     return(EqCT(Q) != 0);
 }
Example #18
0
 /*
  * Compare this point to another. This method throws an
  * exception if the provided point is not on the same curve as
  * this instance. It otherwise returns 0xFFFFFFFF if both points
  * are equal, 0x00000000 otherwise. This method is constant-time
  * (its execution time may depend on whether this and/or the
  * other point is normalized or not, but not on the actual
  * values).
  */
 internal abstract uint EqCT(MutableECPoint Q);
Example #19
0
 /*
  * AddCT() computes P+Q (P is this instance, Q is the operand).
  * It may assume that P != Q. If P = Q and the method could not
  * compute the correct result, then it shall set this instance to
  * 0 (infinity) and return 0x00000000. In all other cases, it must
  * compute the correct point and return 0xFFFFFFFF. In particular,
  * it should properly handle cases where P = 0 or Q = 0. This
  * function is allowed to handle doubling cases as well, if it
  * can.
  *
  * This method may be more efficient if the operand is
  * normalized. Execution time and memory access may depend on
  * whether this instance or the other operand is normalized,
  * but not on the actual point values (including if the points
  * do not fulfill the properties above).
  */
 internal abstract uint AddCT(MutableECPoint Q);
Example #20
0
        internal override uint EqCT(MutableECPoint Q)
        {
            MutableECPointCurve25519 R = SameCurve(Q);

            return(x.EqCT(R.x));
        }
Example #21
0
 /*
  * Set this instance to the same contents as the provided point.
  * The operand Q must be part of the same curve.
  */
 internal abstract void Set(MutableECPoint Q);
Example #22
0
 /*
  * Set this instance to the same contents as point P1 if
  * ctl == 0xFFFFFFFF, or point P2 if ctl == 0x00000000.
  * Both operands must use the same curve as this instance.
  */
 internal abstract void SetMux(uint ctl,
                               MutableECPoint P1, MutableECPoint P2);
Example #23
0
        public static bool VerifyRaw(ECPublicKey pk,
                                     byte[] hash, int hashOff, int hashLen,
                                     byte[] sig, int sigOff, int sigLen)
        {
            try {
                /*
                 * Get the curve.
                 */
                ECCurve curve = pk.Curve;

                /*
                 * Get r and s from signature. This also verifies
                 * that they do not exceed the subgroup order.
                 */
                if (sigLen == 0 || (sigLen & 1) != 0)
                {
                    return(false);
                }
                int    tlen = sigLen >> 1;
                ModInt oneQ = new ModInt(curve.SubgroupOrder);
                oneQ.Set(1);
                ModInt r = oneQ.Dup();
                ModInt s = oneQ.Dup();
                r.Decode(sig, sigOff, tlen);
                s.Decode(sig, sigOff + tlen, tlen);

                /*
                 * If either r or s was too large, it got set to
                 * zero. We also don't want real zeros.
                 */
                if (r.IsZero || s.IsZero)
                {
                    return(false);
                }

                /*
                 * Convert the hash value to an integer modulo q.
                 * As per FIPS 186-4, if the hash value is larger
                 * than q, then we keep the qlen leftmost bits of
                 * the hash value.
                 */
                int    qBitLength = oneQ.ModBitLength;
                int    hBitLength = hashLen << 3;
                byte[] hv;
                if (hBitLength <= qBitLength)
                {
                    hv = new byte[hashLen];
                    Array.Copy(hash, hashOff, hv, 0, hashLen);
                }
                else
                {
                    int qlen = (qBitLength + 7) >> 3;
                    hv = new byte[qlen];
                    Array.Copy(hash, hashOff, hv, 0, qlen);
                    int rs = (8 - (qBitLength & 7)) & 7;
                    BigInt.RShift(hv, rs);
                }
                ModInt z = oneQ.Dup();
                z.DecodeReduce(hv);

                /*
                 * Apply the verification algorithm:
                 *   w = 1/s mod q
                 *   u = z*w mod q
                 *   v = r*w mod q
                 *   T = u*G + v*Pub
                 *   test whether T.x mod q == r.
                 */
                /*
                 * w = 1/s mod q
                 */
                ModInt w = s.Dup();
                w.Invert();

                /*
                 * u = z*w mod q
                 */
                w.ToMonty();
                ModInt u = w.Dup();
                u.MontyMul(z);

                /*
                 * v = r*w mod q
                 */
                ModInt v = w.Dup();
                v.MontyMul(r);

                /*
                 * Compute u*G
                 */
                MutableECPoint T    = curve.MakeGenerator();
                uint           good = T.MulSpecCT(u.Encode());

                /*
                 * Compute v*iPub
                 */
                MutableECPoint M = pk.iPub.Dup();
                good &= M.MulSpecCT(v.Encode());

                /*
                 * Compute T = u*G+v*iPub
                 */
                uint nd = T.AddCT(M);
                M.DoubleCT();
                T.Set(M, ~nd);
                good &= ~T.IsInfinityCT;

                /*
                 * Get T.x, reduced modulo q.
                 * Signature is valid if and only if we get
                 * the same value as r (and we did not encounter
                 * an error previously).
                 */
                s.DecodeReduce(T.X);
                return((good & r.EqCT(s)) != 0);
            } catch (CryptoException) {
                /*
                 * Exceptions may occur if the key or signature
                 * have invalid values (non invertible, out of
                 * range...). Any such occurrence means that the
                 * signature is not valid.
                 */
                return(false);
            }
        }