Esempio n. 1
0
        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));
        }
Esempio n. 2
0
        internal override uint EqCT(MutableECPoint Q)
        {
            MutableECPointCurve25519 R = SameCurve(Q);

            return(x.EqCT(R.x));
        }
Esempio n. 3
0
        internal override uint DecodeCT(byte[] enc)
        {
            /*
             * Format (specified in IEEE P1363, annex E):
             *
             *   0x00             point at infinity
             *   0x02+b <X>       compressed, b = lsb of Y
             *   0x04 <X> <Y>     uncompressed
             *   0x06+b <X> <Y>   uncompressed, b = lsb of Y
             *
             * Coordinates X and Y are in unsigned big-endian
             * notation with exactly the length of the modulus.
             *
             * We want constant-time decoding, up to the encoded
             * length. This means that the four following situations
             * can be differentiated:
             * -- Point is zero (length = 1)
             * -- Point is compressed (length = 1 + flen)
             * -- Point is uncompressed or hybrid (length = 1 + 2*flen)
             * -- Length is neither 1, 1+flen or 1+2*flen.
             */

            int  flen = curve.flen;
            uint good = 0xFFFFFFFF;

            if (enc.Length == 1)
            {
                /*
                 * 1-byte encoding is point at infinity; the
                 * byte shall have value 0.
                 */
                int z = enc[0];
                good &= ~(uint)((z | -z) >> 31);
                SetZero();
            }
            else if (enc.Length == 1 + flen)
            {
                /*
                 * Compressed encoding. Leading byte is 0x02 or
                 * 0x03.
                 */
                int z = (enc[0] & 0xFE) - 0x02;
                good &= ~(uint)((z | -z) >> 31);
                uint lsbValue = (uint)(enc[0] & 1);
                good &= mx.Decode(enc, 1, flen);
                RebuildY2();
                if (curve.pMod4 == 3)
                {
                    good &= my.SqrtBlum();
                }
                else
                {
                    /*
                     * Square roots modulo a non-Blum prime
                     * are a bit more complex. We do not
                     * support them yet (TODO).
                     */
                    good = 0x00000000;
                }

                /*
                 * Adjust Y depending on LSB.
                 */
                mt1.Set(my);
                mt1.Negate();
                uint dn = (uint)-(int)(my.GetLSB() ^ lsbValue);
                my.CondCopy(mt1, dn);

                /*
                 * A corner case: LSB adjustment works only if
                 * Y != 0. If Y is 0 and requested LSB is 1,
                 * then the decoding fails. Note that this case
                 * cannot happen with usual prime curves, because
                 * they have a prime order, implying that there is
                 * no valid point such that Y = 0 (that would be
                 * a point of order 2).
                 */
                good &= ~(uint)-(int)(my.GetLSB() ^ lsbValue);

                mz.Set(1);
            }
            else if (enc.Length == 1 + (flen << 1))
            {
                /*
                 * Uncompressed or hybrid. Leading byte is either
                 * 0x04, 0x06 or 0x07. We verify that the X and
                 * Y coordinates fulfill the curve equation.
                 */
                int fb = enc[0];
                int z  = (fb & 0xFC) - 0x04;
                good &= ~(uint)((z | -z) >> 31);
                z     = fb - 0x05;
                good &= (uint)((z | -z) >> 31);
                good &= mx.Decode(enc, 1, flen);
                RebuildY2();
                mt1.Set(my);
                mt1.FromMonty();
                good &= my.Decode(enc, 1 + flen, flen);
                mt2.Set(my);
                mt2.MontySquare();
                good &= mt1.EqCT(mt2);

                /*
                 * We must check the LSB for hybrid encoding.
                 * The check fails if the encoding is marked as
                 * hybrid AND the LSB does not match.
                 */
                int lm = (fb >> 1) & ((int)my.GetLSB() ^ fb) & 1;
                good &= ~(uint)-lm;

                mz.Set(1);
            }
            else
            {
                good = 0x00000000;
            }

            /*
             * If decoding failed, then we force the value to 0.
             * Otherwise, we got a value. Either way, this uses
             * affine coordinates.
             */
            mx.CondCopy(curve.mp, ~good);
            my.CondCopy(curve.mp, ~good);
            mz.CondCopy(curve.mp, ~good);
            affine = 0xFFFFFFFF;
            return(good);
        }
Esempio n. 4
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);
            }
        }