コード例 #1
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);
        }