public BigInteger Divide(BigInteger a, BigInteger b)
        {
            // Pulled from CAVS, EccMp.cpp, line 305
            // EccMPPoly::DivMod

            var aLen = a.ExactBitLength();
            var bLen = b.ExactBitLength();

            // If a has less bits than the divisor, no division necessary
            if (aLen < bLen)
            {
                return(0);
            }

            b <<= ((aLen - bLen) + 1);
            var quotientBs = new BitString(aLen - bLen + 1);

            for (var i = aLen; i >= bLen; i--)
            {
                b >>= 1;
                if (a.GetBit(i - 1))
                {
                    // Set Quotient bit
                    quotientBs.Set(i - bLen, true);
                    a ^= b;
                }
                else
                {
                    // Set Quotient bit
                    quotientBs.Set(i - bLen, false);
                }
            }

            return(quotientBs.ToPositiveBigInteger());
        }
Beispiel #2
0
        public static void BitGetSetTest()
        {
            const int n         = 250;
            var       bitArray  = new BitArray(n);
            var       bitString = new BitString(n);

            for (var i = 0; i < n; i++)
            {
                var value = RandomHelpers.Default.NextBoolean();
                bitArray.Set(i, value);
                bitString.Set(i, value);
                Assert.Equal(value, bitArray.Get(i));
                Assert.Equal(value, bitString.Get(i));
            }
        }
        public BigInteger Multiply(BigInteger a, BigInteger b)
        {
            // Pulled from CAVS, EccMp.cpp, line 222
            // EccMPPoly::operator*

            BigInteger shorter, longer;
            int        shortLen, longLen;
            int        aBitLen = a.ExactBitLength();
            int        bBitLen = b.ExactBitLength();

            if (aBitLen < bBitLen)
            {
                shorter  = a;
                shortLen = aBitLen;
                longer   = b;
                longLen  = bBitLen;
            }
            else
            {
                shorter  = b;
                shortLen = bBitLen;
                longer   = a;
                longLen  = aBitLen;
            }

            var shorterBits = new BitString(shorter).Bits;
            var longerBits  = new BitString(longer).Bits;
            var c           = new BitString(shortLen + longLen);

            for (var i = 0; i < shortLen; i++)
            {
                if (!shorterBits[i])
                {
                    continue;
                }

                for (var j = 0; j < longLen; j++)
                {
                    if (longerBits[j])
                    {
                        c.Set(i + j, !c.Bits[i + j]);
                    }
                }
            }

            return(Modulo(c.ToPositiveBigInteger()));
        }
        private BitString to168BitKey(BitString K)
        {
            var Kc = new BitString(168);

            int ikc = 0;

            for (int ik = 0; ik < K.BitLength; ++ik)
            {
                if (ik % 8 != 0)
                {
                    var b = K.Bits[ik];

                    Kc.Set(ikc++, b);
                }
            }

            return(Kc);
        }
Beispiel #5
0
        public virtual BitString Getj0(BitString h, BitString iv)
        {
            BitString j0 = null;

            //ThisLogger.Debug("Getj0");
            if (iv.BitLength == 96)
            {
                j0 = iv.ConcatenateBits(BitString.Zeroes(32));
                j0.Set(0, true);
            }
            //	If len(IV) != 96, then let s = 128 * ceil(len(IV)/128) - len(IV)
            //  and let J0 = GHASH_H(IV || 0^(s + 64) || [len(IV)]_64)
            else
            {
                int s = 128 * iv.BitLength.CeilingDivide(128) - iv.BitLength;
                var x = iv
                        .ConcatenateBits(BitString.Zeroes(s + 64))
                        .ConcatenateBits(BitString.To64BitString(iv.BitLength));
                j0 = GHash(h, x);
            }

            return(j0);
        }
Beispiel #6
0
        public MacResult Generate(BitString keyBits, BitString message, int macLength = 0)
        {
            // https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-38b.pdf

            //6.2 MAC Generation

            //Prerequisites:
            //    block cipher CIPH with block size b;
            //    key K;
            //    MAC length parameter Tlen

            //Input:
            //    message M of bit length Mlen.

            //Output:
            //    MAC T of bit length Tlen.

            //Suggested Notation:
            //    CMAC(K, M, Tlen) or, if Tlen is understood from the context, CMAC(K, M).

            //Steps:
            //    1. Apply the subkey generation process in Sec. 6.1 to K to produce K1 and K2.
            var subKeys = ComputeSubKey(keyBits);
            var K1      = subKeys.k1;
            var K2      = subKeys.k2;

            //    2. If Mlen = 0, let n = 1; else, let n = ceiling(Mlen / b).
            //var n = message.BitLength == 0 ? 1 : System.Math.Ceiling(
            //    message.BitLength / (double)Engine.BlockSizeBits
            //);
            var n = message.BitLength == 0 ? 1 : message.BitLength.CeilingDivide(Engine.BlockSizeBits);

            //    3. Let M1, M2, ... , Mn - 1, Mn* denote the unique sequence of bit strings
            //       such that M = M1 || M2 || ... || Mn - 1 || Mn*,
            //       where M1, M2,..., Mn-1 are complete blocks.2

            //    4. If Mn* is a complete block, let Mn = K1 XOR Mn*;


            //var numOfBlocks = (int)System.Math.Ceiling(message.BitLength / (double)_engine.BlockSizeBits);
            var numOfBlocks = message.BitLength.CeilingDivide(Engine.BlockSizeBits);

            var s1 = message.BitLength > Engine.BlockSizeBits ?
                     message.MSBSubstring(0, (numOfBlocks - 1) * Engine.BlockSizeBits) :
                     new BitString(0);

            var lastBlock = message.BitLength != 0
                ? message.MSBSubstring(s1.BitLength, message.BitLength - s1.BitLength) :
                            new BitString(0);

            if (message.BitLength % Engine.BlockSizeBits == 0 && message.BitLength != 0)
            {
                lastBlock = lastBlock.XOR(K1);
            }
            //       else, let Mn = K2 XOR (Mn* || 10^j), where j = nb - Mlen - 1.
            else
            {
                var padding = new BitString(Engine.BlockSizeBits - lastBlock.BitLength);
                padding.Set(padding.BitLength - 1, true);
                lastBlock = K2.XOR(lastBlock.ConcatenateBits(padding));
            }
            message = s1.ConcatenateBits(lastBlock).GetDeepCopy();
            //if this was an empty message, it would have been padded with another block
            if (message.BitLength % Engine.BlockSizeBits != 0)
            {
                throw new Exception("Message isn't composed of same sized blocks.");
            }
            numOfBlocks = message.BitLength / Engine.BlockSizeBits;
            BitString prevC = new BitString(Engine.BlockSizeBits);
            BitString currC = new BitString(Engine.BlockSizeBits);

            for (var i = 0; i < numOfBlocks; i++)
            {
                var block  = message.MSBSubstring(i * Engine.BlockSizeBits, Engine.BlockSizeBits);
                var param2 = new ModeBlockCipherParameters(
                    BlockCipherDirections.Encrypt, keyBits, prevC.XOR(block)
                    );
                currC = AlgoMode.ProcessPayload(param2).Result;
                prevC = currC.GetDeepCopy();
            }

            //    5. Let C0 = 0^b.
            //    6. For i = 1 to n, let Ci = CIPHK(Ci - 1 XOR Mi).
            //    7. Let T = MSBTlen(Cn).
            //    8. Return T.

            BitString mac;

            if (macLength != 0)
            {
                mac = currC.GetMostSignificantBits(macLength);
            }
            else
            {
                mac = currC.GetDeepCopy();
            }

            return(new MacResult(mac));
        }