public BitString MixKeys(BitString currentKey, BitString lastOutput, BitString secondToLastOutput)
        {
            switch (currentKey.BitLength)
            {
            case 128:
                return(currentKey.XOR(lastOutput.GetMostSignificantBits(128)));

            case 192:
                var mostSignificant16KeyBitStringXor =
                    currentKey.GetMostSignificantBits(64).XOR(  // XOR 64 most significant key bits w/
                        secondToLastOutput.Substring(0, 64)     // the 64 least significant bits of the previous cipher text
                        );
                var leastSignificant128KeyBitStringXor = currentKey.GetLeastSignificantBits(128).XOR(lastOutput.GetMostSignificantBits(128));

                return(mostSignificant16KeyBitStringXor.ConcatenateBits(leastSignificant128KeyBitStringXor));

            case 256:
                var mostSignificantFirst16BitStringXor = currentKey.GetMostSignificantBits(128).XOR(secondToLastOutput.GetMostSignificantBits(128));
                var leastSignificant16BitStringXor     = currentKey.GetLeastSignificantBits(128).XOR(lastOutput.GetMostSignificantBits(128));

                return(mostSignificantFirst16BitStringXor.ConcatenateBits(leastSignificant16BitStringXor));

            default:
                throw new ArgumentException(nameof(currentKey));
            }
        }
        public byte[] HandleFinalFullPayloadBlockDecryption(BitString payload, IBlockCipherEngine engine, int numberOfBlocks, int originalPayloadBitLength)
        {
            // When payload is not a multiple of the block size
            if (numberOfBlocks > 1 && payload.BitLength % engine.BlockSizeBits != 0)
            {
                var numberOfBitsToAdd = engine.BlockSizeBits - payload.BitLength % engine.BlockSizeBits;

                // Decrypt the last full payload block (in this case the last block)
                var decryptedLastBlockBuffer = new byte[engine.BlockSizeBytes];
                var lastBlock = payload.GetLeastSignificantBits(engine.BlockSizeBits).ToBytes();

                engine.ProcessSingleBlock(lastBlock, decryptedLastBlockBuffer, 0);

                var paddedPayload = payload
                                    // The original payload minus the final full block
                                    .GetMostSignificantBits(payload.BitLength - engine.BlockSizeBits)
                                    // Add the least significant bits of the decrypted last block to pad to a multiple of the block size
                                    .ConcatenateBits(new BitString(decryptedLastBlockBuffer).GetLeastSignificantBits(numberOfBitsToAdd))
                                    // Add the last block back onto the payload
                                    .ConcatenateBits(payload.GetLeastSignificantBits(engine.BlockSizeBits));

                return(paddedPayload.ToBytes());
            }

            return(payload.ToBytes());
        }
Пример #3
0
        /// <summary>
        /// Returns the EXACT number of bits needed to represent the <see cref="BigInteger"/> value. The MSbit is always a 1
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static BitString ExactBitString(this BigInteger value)
        {
            var bs     = new BitString(value);
            var length = value.ExactBitLength();

            return(bs.GetLeastSignificantBits(length));
        }
Пример #4
0
        private (BitString output, string error) Prf(BitString secret, string label, BitString seed, int outputLength)
        {
            int lengthToGenerate = outputLength.CeilingDivide(_shaHmac.OutputLength * _md5Hmac.OutputLength) * (_shaHmac.OutputLength * _md5Hmac.OutputLength);

            if (secret.BitLength % 8 != 0)
            {
                return(null, "Invalid secret, must be whole byte");
            }

            var secretBytes   = secret.BitLength / 8;
            var halfSecretLen = secretBytes.CeilingDivide(2) * 8;

            var firstHalf  = secret.GetMostSignificantBits(halfSecretLen);
            var secondHalf = secret.GetLeastSignificantBits(halfSecretLen);

            var labelBytes = new BitString(Encoding.ASCII.GetBytes(label));
            var md5Out     = HmacPrf(_md5Hmac, firstHalf, labelBytes.ConcatenateBits(seed), lengthToGenerate);
            var shaOut     = HmacPrf(_shaHmac, secondHalf, labelBytes.ConcatenateBits(seed), lengthToGenerate);

            if (md5Out.BitLength != shaOut.BitLength)
            {
                return(null, "Invalid PRF output, lenghts must be equal");
            }

            var xorResult = md5Out.XOR(shaOut);

            return(xorResult.GetMostSignificantBits(outputLength), "");
        }
Пример #5
0
        private HashResult Md5Process(BitString message)
        {
            var lastIndex = _fullMessage.Length - 1;
            var spaceRemainingInLastBlock = SizeOfChunk - _fullMessage[lastIndex].BitLength;

            if (message.BitLength <= spaceRemainingInLastBlock)
            {
                // Message doesn't fill the block entirely, so add it and return success
                _fullMessage[lastIndex] = _fullMessage[lastIndex].ConcatenateBits(message);
                return(new HashResult(new BitString(0)));
            }
            else
            {
                // Fill out the last partial block
                _fullMessage[lastIndex] = _fullMessage[lastIndex].ConcatenateBits(message.GetMostSignificantBits(spaceRemainingInLastBlock));

                // Add an empty block to the end (which is always needed for padding information anyways)
                _fullMessage = _fullMessage.Append(new BitString(0)).ToArray();

                // Try to compress the last full block, if it fails, eject and fail
                var result = Md5Compress(_fullMessage[lastIndex]);
                if (!result.Success)
                {
                    return(result);
                }

                // Figure out how many bits are left in the message and try to process them
                var trimmedMessage = message.GetLeastSignificantBits(message.BitLength - spaceRemainingInLastBlock);
                return(Md5Process(trimmedMessage));
            }
        }
Пример #6
0
        protected override BitString Wrap(BitString K, BitString S, bool wrapWithInverseCipher)
        {
            // 0. Pre-conditions
            var n = S.BitLength / 32;

            if ((n < 3) || (S.BitLength % 32 != 0))
            {
                throw new ArgumentException($"Invalid {nameof(S)} length.");
            }

            var keylen = K.BitLength;
            var K2     = K.GetDeepCopy();
            //if (keylen == 192)
            //{
            //    // Convert to 168 bits because TDES Block encrypt takes 168 bits
            //    K2 = to168BitKey(K);
            //    keylen = K2.BitLength;
            //}
            //else
            //{
            //    K2 = K;
            //}
            //if (keylen != 168)
            //{
            //    throw new ArgumentException($"Invalid {nameof(keylen)}");
            //}

            // 1. Initialize variables
            // 1.a) Let s = 6(n-1)
            int s = 6 * (n - 1);
            // 1.b) Let S1,S2,...,Sn be the semi-blocks s.t. S=S1 || S2 || ... || Sn
            // 1.c) Let A0 = S1
            BitString A = S.GetMostSignificantBits(32);
            // 1.d) For i=2,...,n: let Ri0 = Si
            BitString R2n = S.GetLeastSignificantBits(S.BitLength - 32);

            // 2. Calculate the intermediate values.  For t = 1,...,s update variables
            //    as follows:
            for (int t = 1; t <= s; ++t)
            {
                // a) A^t = MSB32(CIPH_K(A^t-1 || R2^t-1)) xor [t]32
                BitString R2 = R2n.GetMostSignificantBits(32);

                //BitString t32 = to_bitstring32((unsigned long long)t);
                BitString t32 = BitString.To64BitString(t).GetLeastSignificantBits(32);

                var       param   = new ModeBlockCipherParameters(BlockCipherDirections.Encrypt, K2, A.ConcatenateBits(R2), wrapWithInverseCipher);
                BitString block_t = Cipher.ProcessPayload(param).Result;
                A = block_t.GetMostSignificantBits(32).XOR(t32);
                // b) For i=2,...,n: Ri^t = Ri+1^t-1
                // c) Rn^t = LSB32(CIPH_K(CIPH_K(A^t-1 || R2^t-1)))
                R2n = R2n.GetLeastSignificantBits(R2n.BitLength - 32).ConcatenateBits(block_t.GetLeastSignificantBits(32));
            }

            // 3. Output the results:
            // a) Let C1 = A^s
            // b) For i=2,...,n: Ci = Ri^s
            // c) Return C1 || C2 || ... || Cn
            return(A.ConcatenateBits(R2n));
        }
Пример #7
0
        public BitString GetNextIV()
        {
            var currentIV = _iv.GetLeastSignificantBits(_blockSize).GetDeepCopy();

            _iv = _iv.BitStringAddition(BitString.One());

            return(currentIV);
        }
Пример #8
0
        protected override BitString WrapInverse(BitString K, BitString C, bool wrappedWithInverseCipher)
        {
            // 0. Pre-conditions
            int n = C.BitLength / 32;

            if ((n < 3) || (C.BitLength % 32 != 0))
            {
                throw new ArgumentException($"Invalid {nameof(C)} length.");
            }
            int keyLength = K.BitLength;
            var K2        = K.GetDeepCopy();
            //if (keyLength == 192)
            //{
            //    // Convert to 168 bits because TDES Block encrypt takes 168 bits
            //    K2 = to168BitKey(K);
            //    keyLength = K2.BitLength;
            //}
            //else
            //{
            //    K2 = K;
            //}
            //if (keyLength != 168)
            //{
            //    throw new ArgumentException($"Invalid {nameof(keyLength)}");
            //}

            // 1. Initialize variables
            // 1.a) Let s = 6(n-1)
            int s = 6 * (n - 1);
            // 1.b) Let C1,C2,...,Cn be the semi-blocks s.t. C=C1 || C2 || ... || Cn
            // 1.c) Let As = C1
            BitString A = C.GetMostSignificantBits(32);
            // 1.d) For i=2,...,n: let Ri0 = Ci
            BitString R2n = C.GetLeastSignificantBits(C.BitLength - 32);


            // 2. Calculate the intermediate values.  For t = s, s-1, ..., 1,
            //    update the variables as follows:
            for (int t = s; t >= 1; --t)
            {
                // a) A^t-1 = MSB(CIPH^-1K((A^t xor [t]32) || Rn^t))
                BitString t32 = BitString.To64BitString(t).GetLeastSignificantBits(32);
                BitString Rn  = R2n.GetLeastSignificantBits(32);

                var       param   = new ModeBlockCipherParameters(BlockCipherDirections.Decrypt, K2, A.XOR(t32).ConcatenateBits(Rn), wrappedWithInverseCipher);
                BitString block_t = Cipher.ProcessPayload(param).Result;
                A = block_t.GetMostSignificantBits(32);
                // b) R2^t-1 = LSB(CIPH^-1K((A^t xor [t]32) || Rn^t))
                // c) For i=2,...,n-1, Ri+1^t-1 = Ri^t
                R2n = block_t.GetLeastSignificantBits(32).ConcatenateBits(R2n.GetMostSignificantBits(R2n.BitLength - 32));
            }

            // 3. Output the results:
            // 3.a) Let S1 = A0
            // 3.b) For i=2,...,n: Si = Ri0
            // 3.c) Return S1 || S2 || ... || Sn
            return(A.ConcatenateBits(R2n));
        }
Пример #9
0
        protected override BitString Wrap(BitString K, BitString S, bool wrapWithInverseCipher)
        {
            // 0. Pre-conditions
            var n = S.BitLength / 64;

            if ((n < 3) || (S.BitLength % 64 != 0))
            {
                throw new ArgumentException($"Invalid {nameof(S)} length.");
            }

            var keyLen = K.BitLength;

            if ((keyLen != 128) && (keyLen != 192) && (keyLen != 256))
            {
                throw new ArgumentException($"Invalid {nameof(keyLen)}");
            }

            // 1. Initialize variables
            // 1.a) Let s = 6(n-1)
            var s = 6 * (n - 1);
            // 1.b) Let S1,S2,...,Sn be the semi-blocks s.t. S=S1 || S2 || ... || Sn
            // 1.c) Let A0 = S1
            var A = S.GetMostSignificantBits(64);
            // 1.d) For i=2,...,n: let Ri0 = Si
            var R2n = S.GetLeastSignificantBits(S.BitLength - 64);

            // 2. Calculate the intermediate values.  For t = 1,...,s update variables
            //    as follows:
            for (var t = 1; t <= s; ++t)
            {
                // a) A^t = MSB64(CIPH_K(A^t-1 || R2^t-1)) xor [t]64
                var R2      = R2n.GetMostSignificantBits(64);
                var t64     = BitString.To64BitString(t);
                var block_t = Cipher.ProcessPayload(
                    new ModeBlockCipherParameters(
                        BlockCipherDirections.Encrypt,
                        K,
                        A.ConcatenateBits(R2),
                        wrapWithInverseCipher
                        )).Result;

                A = block_t.GetMostSignificantBits(64).XOR(t64);
                // b) For i=2,...,n: Ri^t = Ri+1^t-1
                // c) Rn^t = LSB64(CIPH_K(CIPH_K(A^t-1 || R2^t-1)))
                R2n = R2n
                      .GetLeastSignificantBits(R2n.BitLength - 64)
                      .ConcatenateBits(block_t.GetLeastSignificantBits(64));
            }

            // 3. Output the results:
            // a) Let C1 = A^s
            // b) For i=2,...,n: Ci = Ri^s
            // c) Return C1 || C2 || ... || Cn
            return(A.ConcatenateBits(R2n));
        }
Пример #10
0
        protected override BitString WrapInverse(BitString K, BitString C, bool wrappedWithInverseCipher)
        {
            // 0. Pre-conditions
            var n = C.BitLength / 64;

            if ((n < 3) || (C.BitLength % 64 != 0))
            {
                throw new ArgumentException($"Invalid {nameof(C)} length.");
            }

            var aesKeyLength = K.BitLength;

            if ((aesKeyLength != 128) && (aesKeyLength != 192) && (aesKeyLength != 256))
            {
                throw new ArgumentException($"Invalid {nameof(aesKeyLength)}");
            }

            // 1. Initialize variables
            // 1.a) Let s = 6(n-1)
            var s = 6 * (n - 1);
            // 1.b) Let C1,C2,...,Cn be the semi-blocks s.t. C=C1 || C2 || ... || Cn
            // 1.c) Let As = C1
            var A = C.GetMostSignificantBits(64);
            // 1.d) For i=2,...,n: let Ri0 = Ci
            var R2n = C.GetLeastSignificantBits(C.BitLength - 64);

            // 2. Calculate the intermediate values.  For t = s, s-1, ..., 1,
            //    update the variables as follows:
            for (var t = s; t >= 1; --t)
            {
                // a) A^t-1 = MSB(CIPH^-1K((A^t xor [t]64) || Rn^t))
                var t64     = BitString.To64BitString(t);
                var Rn      = R2n.GetLeastSignificantBits(64);
                var block_t = Cipher.ProcessPayload(
                    new ModeBlockCipherParameters(
                        BlockCipherDirections.Decrypt,
                        K,
                        A.XOR(t64).ConcatenateBits(Rn),
                        wrappedWithInverseCipher
                        )).Result;

                A = block_t.GetMostSignificantBits(64);
                // b) R2^t-1 = LSB(CIPH^-1K((A^t xor [t]64) || Rn^t))
                // c) For i=2,...,n-1, Ri+1^t-1 = Ri^t
                R2n = block_t.GetLeastSignificantBits(64).ConcatenateBits(R2n.GetMostSignificantBits(R2n.BitLength - 64));
            }

            // 3. Output the results:
            // 3.a) Let S1 = A0
            // 3.b) For i=2,...,n: Si = Ri0
            // 3.c) Return S1 || S2 || ... || Sn
            return(A.ConcatenateBits(R2n));
        }
Пример #11
0
        public override SymmetricCipherResult Decrypt(BitString key, BitString cipherText, bool wrappedWithInverseCipher)
        {
            // 1. Let ICV1 = 0xA6A6A6A6A6A6A6A6
            // 2. Let S = W^-1(C)
            BitString s = WrapInverse(key, cipherText, wrappedWithInverseCipher);

            // 3. If MSB64(S) != ICV1 then return FAIL and stop.
            if (!s.GetMostSignificantBits(64).Equals(Icv1))
            {
                return(new SymmetricCipherResult("Authentication failure."));
            }

            // 4. Return P = LSB64(n-1)(S)
            BitString p = s.GetLeastSignificantBits((s.BitLength) - 64);

            return(new SymmetricCipherResult(p));
        }
Пример #12
0
        // NIST SP 800-38D
        // Recommendation for Block Cipher Modes of Operation: Galois/Counter
        // Mode (GCM) and GMAC
        // Section 6: Mathematical Components of GCM

        // Section 6.2: Incrementing Function
        // increment the rightmost s bits of X modulo 2^s
        // leave the leftmost len(X) - s bits unchanged
        public virtual BitString inc_s(int s, BitString X)
        {
            // inc_s(X) = MSB_len(X)-s || [int(LSB_s(X)) + 1 mod 2^s]_s
            if (X.BitLength < s)
            {
                return(null);
            }
            BigInteger lsp1 = X.GetLeastSignificantBits(s).ToPositiveBigInteger() + new BigInteger(1);

            //ThisLogger.Debug($"lsp1: {lsp1}");
            lsp1 = lsp1 % (new BigInteger(1) << s);
            //ThisLogger.Debug($"lsp2: {lsp1}");

            var bitsToAppend = new BitString(lsp1, s);

            //ThisLogger.Debug($"BitsToAppendLength: {bitsToAppend.Length}");
            return(X.GetMostSignificantBits(X.BitLength - s).ConcatenateBits(bitsToAppend));
        }
Пример #13
0
        public BitString GetNextIV()
        {
            if (_iv.BitLength < _blockSize)
            {
                _iv = BitString.Zeroes(_blockSize - _iv.BitLength).ConcatenateBits(_iv);
            }

            var currentIV = _iv.GetLeastSignificantBits(_blockSize).GetDeepCopy();

            // Avoid throwing an exception by subtracting from 000...0
            if (currentIV.Equals(BitString.Zeroes(_blockSize)))
            {
                _iv = BitString.Ones(_blockSize);
            }
            else
            {
                _iv = _iv.BitStringSubtraction(BitString.One());
            }

            return(currentIV);
        }
Пример #14
0
        protected override DrbgResult GenerateAlgorithm(int requestedNumberOfBits, BitString additionalInput)
        {
            // 1
            if (ReseedCounter > Attributes.MaxNumberOfRequestsBetweenReseeds)
            {
                return(new DrbgResult(DrbgStatus.ReseedRequired));
            }

            // 2
            if (additionalInput.BitLength != 0)
            {
                // 2.1
                var dataToHash = new BitString("02")
                                 .ConcatenateBits(V)
                                 .ConcatenateBits(additionalInput);

                var w = _sha.HashMessage(dataToHash).Digest;

                // 2.2
                V = V.BitStringAddition(w).GetLeastSignificantBits(HashAttributes.SeedLength);
            }

            // 3
            var returnedBits = HashGen(V, requestedNumberOfBits);

            // 4
            var H = _sha.HashMessage(new BitString("03").ConcatenateBits(V)).Digest;

            // 5
            V = V.BitStringAddition(H);
            V = V.BitStringAddition(C);
            V = V.BitStringAddition(BitString.To32BitString(ReseedCounter));
            V = V.GetLeastSignificantBits(HashAttributes.SeedLength);

            // 6
            ReseedCounter++;

            // 7
            return(new DrbgResult(returnedBits));
        }
Пример #15
0
        public void ShouldReturnCorrectOtherInfoCavsTests(
            KeyAgreementRole iutRole,
            OtherPartySharedInformation <FfcDomainParameters, FfcKeyPair> uPartySharedInformation,
            OtherPartySharedInformation <FfcDomainParameters, FfcKeyPair> vPartySharedInformation,
            int otherInfoLength,
            BitString expectedOtherInfo
            )
        {
            string otherInfoPattern = "uPartyInfo||vPartyInfo";

            TestableEntropyProvider entropyProvider = new TestableEntropyProvider();

            // u/v party info comprised of ID, and dkmNonce, find the bitlength of both parties contributed information
            // to determine which bits are the "random" bits to inject into the TestableEntropyProvider.
            var composedBitLength = uPartySharedInformation.PartyId.BitLength +
                                    uPartySharedInformation.DkmNonce.BitLength +
                                    vPartySharedInformation.PartyId.BitLength;

            var entropyBits = expectedOtherInfo.GetLeastSignificantBits(expectedOtherInfo.BitLength - composedBitLength);

            entropyProvider.AddEntropy(entropyBits);

            var uPartyOtherInfo = new PartyOtherInfo(uPartySharedInformation.PartyId, uPartySharedInformation.DkmNonce);
            var vPartyOtherInfo = new PartyOtherInfo(vPartySharedInformation.PartyId, vPartySharedInformation.DkmNonce);

            _subject = new OtherInfo(
                entropyProvider,
                otherInfoPattern,
                otherInfoLength,
                KeyAgreementRole.InitiatorPartyU,
                uPartyOtherInfo,
                vPartyOtherInfo
                );

            var result = _subject.GetOtherInfo();

            Assert.AreEqual(expectedOtherInfo.ToHex(), result.ToHex());
        }
        public void TransformCiphertext(byte[] outBuffer, IBlockCipherEngine engine, int numberOfBlocks, int originalPayloadBitLength)
        {
            if (numberOfBlocks == 1 || originalPayloadBitLength % engine.BlockSizeBits == 0)
            {
                return;
            }

            var bitsToAddForPadding     = numberOfBlocks * engine.BlockSizeBits - originalPayloadBitLength;
            var blockBitsWithoutPadding = engine.BlockSizeBits - bitsToAddForPadding;

            var newPayload            = new BitString(outBuffer);
            var newPayloadUpToPadding = newPayload
                                        // all the blocks up to the second to last block, which should only include the "non padded" bits
                                        .GetMostSignificantBits(engine.BlockSizeBits * (numberOfBlocks - 2) + blockBitsWithoutPadding);
            var finalBlock      = newPayload.GetLeastSignificantBits(engine.BlockSizeBits);
            var newPayloadBytes = newPayloadUpToPadding
                                  .ConcatenateBits(finalBlock)
                                  // Adding zero bits in the LSB to not add significant bits when converting to a byte array.
                                  .ConcatenateBits(BitString.Zeroes(bitsToAddForPadding))
                                  .ToBytes();

            Array.Copy(newPayloadBytes, 0, outBuffer, 0, newPayloadBytes.Length);
        }
Пример #17
0
        private void Update(BitString seedMaterial)
        {
            BitString v   = V.GetDeepCopy();
            BitString key = Key.GetDeepCopy();

            // 1. temp = Null
            BitString temp = new BitString(0);

            // 2. While (len(temp)<seedlen) do:
            while (temp.BitLength < CounterAttributes.SeedLength)
            {
                v = v
                    .BitStringAddition(BitString.One())
                    .ConcatenateBits(new BitString(CounterAttributes.OutputLength - v.BitLength)); // Add zeroes to bitstring to make it the length of the OutputLength

                BitString outputBlock = BlockEncrypt(key, v);

                temp = temp.ConcatenateBits(outputBlock);
            }

            // 3. temp = Leftmost seedlen bits of temp
            temp = temp.GetMostSignificantBits(CounterAttributes.SeedLength);

            // 4. temp = temp xor provided_data
            Debug.Assert(temp.BitLength == seedMaterial.BitLength);
            temp = temp.XOR(seedMaterial);

            // 5. Key = Leftmost keylen bits of temp
            key = temp.GetMostSignificantBits(CounterAttributes.KeyLength);

            // 6. V = Rightmost outlen bits of temp
            v = temp.GetLeastSignificantBits(CounterAttributes.OutputLength);

            // 7. Return new values of Key and V
            Key = key.GetDeepCopy();
            V   = v.GetDeepCopy();
        }
Пример #18
0
        private BitString Divide(BitString a, BitString b)
        {
            if (b.Equals(BitString.Zeroes(b.BitLength)))
            {
                return(BitString.Zeroes(a.BitLength));
            }

            var aBigInt = a.ToPositiveBigInteger();
            var bBigInt = b.ToPositiveBigInteger();

            var result = new BitString(aBigInt / bBigInt);

            // Ensure result is the same number of bits as a
            if (result.BitLength > a.BitLength)
            {
                result = result.GetLeastSignificantBits(a.BitLength);
            }
            else if (result.BitLength < a.BitLength)
            {
                result = BitString.Zeroes(a.BitLength - result.BitLength).ConcatenateBits(result);
            }

            return(result);
        }
Пример #19
0
        /*
         *  INPUT: The initial Msg is the length of the digest size
         *
         *  MCT(Msg, MaxOutLen, MinOutLen, OutLenIncrement, MaxBlockSize, MinBlockSize)
         *  {
         *    Range = (MaxOutLen – MinOutLen + 1);
         *    OutputLen = MaxOutLen;
         *    BlockRange = (MaxBlockSize – MinBlockSize + 1);
         *    BlockSize = MinBlockSize;
         *    Customization = "";
         *
         *    Output[0] = Msg;
         *    for (j = 0; j < 100; j++)
         *    {
         *      for (i = 1; i < 1001; i++)
         *      {
         *        InnerMsg = Left(Output[i-1] || ZeroBits(128), 128);
         *        Output[i] = ParallelHash(InnerMsg, OutputLen, BlockSize, FunctionName, Customization);
         *        Rightmost_Output_bits = Right(Output[i], 16);
         *        OutputLen = MinOutLen + (floor((Rightmost_Output_bits % Range) / OutLenIncrement) * OutLenIncrement);
         *        BlockSize = MinBlockSize + Right(Rightmost_Output_bits, 8) % BlockRange;
         *        Customization = BitsToString(InnerMsg || Rightmost_Output_bits);
         *      }
         *
         *      OutputJ[j] = Output[1000];
         *    }
         *
         *    return OutputJ;
         *  }
         */
        #endregion MonteCarloAlgorithm Pseudocode

        public MctResult <AlgoArrayResponseWithCustomization> MCTHash(HashFunction function, BitString message, MathDomain outputLength, MathDomain blockSizeDomain, bool hexCustomization, bool isSample)
        {
            _hexCustomization = hexCustomization;
            if (isSample)
            {
                NUM_OF_RESPONSES = 3;
            }

            var responses    = new List <AlgoArrayResponseWithCustomization>();
            var i            = 0;
            var j            = 0;
            var min          = outputLength.GetDomainMinMax().Minimum;
            var max          = outputLength.GetDomainMinMax().Maximum;
            var increment    = outputLength.GetDomainMinMax().Increment;
            var minBlockSize = blockSizeDomain.GetDomainMinMax().Minimum;
            var maxBlockSize = blockSizeDomain.GetDomainMinMax().Maximum;

            var outputLen      = max;
            var blockSize      = minBlockSize;
            var blockSizeRange = (maxBlockSize - minBlockSize) + 1;
            var customization  = "";
            var range          = (max - min) + 1;
            var innerMessage   = message.GetDeepCopy();

            try
            {
                for (i = 0; i < NUM_OF_RESPONSES; i++)
                {
                    var innerDigest       = new BitString(0);
                    var iterationResponse = new AlgoArrayResponseWithCustomization()
                    {
                    };
                    iterationResponse.Message       = innerMessage;
                    iterationResponse.Customization = customization;
                    iterationResponse.BlockSize     = blockSize;

                    for (j = 0; j < 1000; j++)
                    {
                        // Might not have 128 bits to pull from so we pad with 0
                        innerMessage = BitString.ConcatenateBits(innerMessage, BitString.Zeroes(128))
                                       .GetMostSignificantBits(128);

                        function.DigestLength = outputLen;

                        var innerResult = _iParallelHash.HashMessage(function, innerMessage, blockSize, customization);
                        innerDigest = innerResult.Digest.GetDeepCopy();

                        // Will always have 16 bits to pull from
                        var rightmostBitString = innerDigest.GetLeastSignificantBits(16);

                        var rightmostBits = rightmostBitString.Bits;

                        outputLen     = min + (int)System.Math.Floor((double)(rightmostBits.ToInt() % range) / increment) * increment;
                        blockSize     = minBlockSize + rightmostBitString.GetLeastSignificantBits(8).Bits.ToInt() % blockSizeRange;
                        customization = GetStringFromBytes(BitString.ConcatenateBits(innerMessage, rightmostBitString).ToBytes());

                        innerMessage = innerDigest.GetDeepCopy();
                    }

                    iterationResponse.Digest = innerDigest.GetDeepCopy();
                    responses.Add(iterationResponse);
                }
            }
            catch (Exception ex)
            {
                ThisLogger.Debug($"i count {i}, j count {j}");
                ThisLogger.Error(ex);
                return(new MctResult <AlgoArrayResponseWithCustomization>($"{ex.Message}; {outputLen}"));
            }

            return(new MctResult <AlgoArrayResponseWithCustomization>(responses));
        }
Пример #20
0
        public void Update(byte[] input, int bitLength)
        {
            if (bitLength % 8 == 0 && _cachedBits.BitLength == 0)
            {
                BlockUpdate(input, 0, bitLength / 8);
                return;
            }

            var inputBits = new BitString(input).GetMostSignificantBits(bitLength);

            _cachedBits = BitString.ConcatenateBits(_cachedBits, inputBits);
            var numberOfCompletedBytes = _cachedBits.BitLength / 8;

            if (numberOfCompletedBytes > 0)
            {
                var completedBytes = _cachedBits.GetMostSignificantBits(numberOfCompletedBytes * 8);
                BlockUpdate(completedBytes.ToBytes(), 0, completedBytes.BitLength / 8);
            }

            _cachedBits = numberOfCompletedBytes * 8 == _cachedBits.BitLength ? new BitString(0) : _cachedBits.GetLeastSignificantBits(_cachedBits.BitLength - numberOfCompletedBytes * 8);
        }
Пример #21
0
        public VerifyResult VerifyPadding(int nlen, BitString message, BigInteger embededMessage, PublicKey pubKey)
        {
            // 1. Signature Opening
            BigInteger irPrime;

            if (embededMessage % 16 == 12)
            {
                irPrime = embededMessage;
            }
            else if ((pubKey.N - embededMessage) % 16 == 12)
            {
                irPrime = pubKey.N - embededMessage;
            }
            else
            {
                return(new VerifyResult("Reject signature, failing modulo check"));
            }

            if (irPrime < NumberTheory.Pow2(nlen - 2) || irPrime > NumberTheory.Pow2(nlen - 1) - 1)
            {
                return(new VerifyResult("irPrime not within required range"));
            }

            // 2. Encapsulated Hash Verification
            var bsIrPrime = new BitString(irPrime, nlen);

            if (bsIrPrime.BitLength != nlen)
            {
                return(new VerifyResult("Bad bitlength for irPrime"));
            }

            if (!bsIrPrime.GetMostSignificantBits(4).Equals(Header))
            {
                return(new VerifyResult("Header not found within first 4 bits"));
            }

            if (!bsIrPrime.GetLeastSignificantBits(8).Equals(Tail))
            {
                return(new VerifyResult("Tail not found within last 8 bits"));
            }

            // check nibbles for Bs and A
            var expectedPaddingLen = nlen - Header.BitLength - Sha.HashFunction.OutputLen - GetTrailer().BitLength;
            var expectedPadding    = GetPadding(expectedPaddingLen);
            var padding            = bsIrPrime.MSBSubstring(4, expectedPaddingLen);

            if (!padding.Equals(expectedPadding))
            {
                return(new VerifyResult("Improper padding, must be 'B's followed by 'A'"));
            }

            var beginOfHashIndex = expectedPaddingLen + 4;

            // 3. Hash Recovery
            var hashDigest = bsIrPrime.MSBSubstring(beginOfHashIndex, Sha.HashFunction.OutputLen);

            // 4. Message Hashing and Comparison
            var expectedHash = Sha.HashMessage(message).Digest;

            // check trailer for accuracy, including hash function
            var expectedTrailer = GetTrailer();
            var trailer         = bsIrPrime.GetLeastSignificantBits(expectedTrailer.BitLength);

            if (!expectedTrailer.Equals(trailer))
            {
                return(new VerifyResult("Trailer hash functions do not match, bad signature"));
            }

            if (expectedHash.Equals(hashDigest))
            {
                return(new VerifyResult());
            }
            else
            {
                return(new VerifyResult("Hashes do not match, bad signature"));
            }
        }