示例#1
0
        /// Compute `a - b` (mod l)
        public static UnpackedScalar sub(UnpackedScalar a, UnpackedScalar b)
        {
            var difference   = UnpackedScalar.zero();
            var differencesp = difference.value.Span;
            var mask         = ((ulong)1 << 52) - 1;


            var asp = a.value.Span;
            var bsp = b.value.Span;

            // a - b
            ulong borrow = 0;

            for (int i = 0; i < 5; i++)
            {
                borrow          = asp[i] - (bsp[i] + (borrow >> 63));
                differencesp[i] = borrow & mask;
            }


            // conditionally add l if the difference is negative
            var   underflow_mask = ((borrow >> 63) ^ 1) - (1);
            ulong carry          = 0;

            for (int i = 0; i < 5; i++)
            {
                carry           = (carry >> 52) + differencesp[i] + (Constant.L.value.Span[i] & underflow_mask);
                differencesp[i] = carry & mask;
            }

            return(difference);
        }
示例#2
0
        /// Unpack a 32 byte / 256 bit scalar into 5 52-bit limbs.
        public static UnpackedScalar from_bytes(byte[] bytes)
        {
            var words = new ulong[4];

            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 8; j++)
                {
                    words[i] |= ((ulong)bytes[(i * 8) + j]) << (j * 8);
                }
            }

            var mask     = (((ulong)1) << 52) - 1;
            var top_mask = (((ulong)1) << 48) - 1;
            var s        = UnpackedScalar.zero();
            var ss       = s.value.Span;

            ss[0] = words[0] & mask;
            ss[1] = ((words[0] >> 52) | (words[1] << 12)) & mask;
            ss[2] = ((words[1] >> 40) | (words[2] << 24)) & mask;
            ss[3] = ((words[2] >> 28) | (words[3] << 36)) & mask;
            ss[4] = (words[3] >> 16) & top_mask;

            return(s);
        }
示例#3
0
        /// Compute `a + b` (mod l)
        public static UnpackedScalar add(UnpackedScalar a, UnpackedScalar b)
        {
            var sum  = UnpackedScalar.zero();
            var sums = sum.value.Span;
            var mask = ((ulong)1 << 52) - 1;

            var asp = a.value.Span;
            var bsp = b.value.Span;

            // a + b
            ulong carry = 0;

            for (int i = 0; i < 5; i++)
            {
                carry   = asp[i] + bsp[i] + (carry >> 52);
                sums[i] = carry & mask;
            }


            // subtract l if the sum is >= l
            return(UnpackedScalar.sub(sum, Constant.L));
        }
示例#4
0
        /// Reduce a 64 byte / 512 bit scalar mod l
        public static UnpackedScalar from_bytes_wide(byte[] bytes)
        {
            var words = new ulong[8];

            for (int i = 0; i < 8; i++)
            {
                for (int j = 0; j < 8; j++)
                {
                    words[i] |= ((ulong)bytes[(i * 8) + j]) << (j * 8);
                }
            }



            var mask = (((ulong)1) << 52) - 1;
            var lo   = UnpackedScalar.zero();
            var hi   = UnpackedScalar.zero();

            var los = lo.value.Span;
            var his = hi.value.Span;


            los[0] = words[0] & mask;
            los[1] = ((words[0] >> 52) | (words[1] << 12)) & mask;
            los[2] = ((words[1] >> 40) | (words[2] << 24)) & mask;
            los[3] = ((words[2] >> 28) | (words[3] << 36)) & mask;
            los[4] = ((words[3] >> 16) | (words[4] << 48)) & mask;
            his[0] = (words[4] >> 4) & mask;
            his[1] = ((words[4] >> 56) | (words[5] << 8)) & mask;
            his[2] = ((words[5] >> 44) | (words[6] << 20)) & mask;
            his[3] = ((words[6] >> 32) | (words[7] << 32)) & mask;
            his[4] = words[7] >> 20;

            lo = UnpackedScalar.montgomery_mul(lo, Constant.R);  // (lo * R) / R = lo
            hi = UnpackedScalar.montgomery_mul(hi, Constant.RR); // (hi * R^2) / R = hi * R

            return(UnpackedScalar.add(hi, lo));
        }