public override SymmetricCipherResult Decrypt(BitString key, BitString cipherText, bool wrappedWithInverseCipher)
        {
            // 0. Check for valid bitlength ciphertext
            if (cipherText.BitLength < 128 || cipherText.BitLength % 64 != 0)
            {
                return(new SymmetricCipherResult("Invalid length for ciphertext"));
            }

            // 1. Let n = number of semi-blocks in C (number of half-blocks, where a block is 128-bits)
            var n = cipherText.BitLength / 64;

            // 2. Let ICV2 = 0xA65959A6
            // 3. Set S based on semi-blocks
            var S = new BitString(32);

            if (n == 2)
            {
                var aesResult = Cipher.ProcessPayload(new ModeBlockCipherParameters(BlockCipherDirections.Decrypt, key, cipherText, wrappedWithInverseCipher));
                if (!aesResult.Success)
                {
                    return(new SymmetricCipherResult(aesResult.ErrorMessage));
                }

                S = aesResult.Result;
            }
            else if (n > 2)
            {
                S = WrapInverse(key, cipherText, wrappedWithInverseCipher);
            }

            // 4. Check MSB(S, 32) to be equal to ICV2
            if (!S.MSBSubstring(0, 32).Equals(Icv2))
            {
                return(new SymmetricCipherResult("ICV2 not found as most significant bits of S"));
            }

            // 5. pLen = int(LSB(MSB(S, 64), 32))
            var pLen = (int)S.MSBSubstring(0, 64).Substring(0, 32).ToPositiveBigInteger();

            // 6. padLen = 8 * (n - 1) - pLen
            var padLen = 8 * (n - 1) - pLen;

            // 7. Make sure 0 < padLen < 7
            if (padLen < 0 || padLen > 7)
            {
                return(new SymmetricCipherResult("Invalid padLen"));
            }

            // 8. If the padding isn't 0s, then fail
            if (!S.Substring(0, 8 * padLen).Equals(BitString.Zeroes(8 * padLen)))
            {
                return(new SymmetricCipherResult("Padding is not all 0s"));
            }

            // 9. Return p = MSB(LSB(S, 64*(n-1)), 8*pLen)
            var p = S.Substring(0, 64 * (n - 1)).MSBSubstring(0, 8 * pLen);

            return(new SymmetricCipherResult(p));
        }
        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));
            }
        }
Beispiel #3
0
        public virtual BitString GHash(BitString h, BitString x)
        {
            //ThisLogger.Debug("GHash");
            if (h.BitLength != 128)
            {
                return(null);
            }
            if (x.BitLength % 128 != 0 || x.BitLength == 0)
            {
                ThisLogger.Debug(x.BitLength);
                return(null);
            }

            // Step 1: Let X1,...,Xm-1,Xm denote the unique sequence of blocks such that
            // X = X1 || X2 || ... || Xm-1 || Xm
            int m = x.BitLength / 128;

            // Step 2: Let Y0 be the "zero block" 0^128
            var y = BitString.Zeroes(128);

            // Step 3: For i = 1,...,m let Yi = (Yi-1 xor Xi) dot H
            for (int i = 0; i < m; ++i)
            {
                BitString xi     = x.Substring((m - i - 1) * 128, 128);
                BitString YxorXi = BitString.XOR(y, xi);
                y = BlockProduct(YxorXi, h);
            }

            return(y);
        }
Beispiel #4
0
        public byte[] HandleFinalFullPayloadBlockDecryption(BitString payload, IBlockCipherEngine engine, int numberOfBlocks, int originalPayloadBitLength)
        {
            // Decrypt the last full payload block (when there is more than one block)
            if (numberOfBlocks > 1)
            {
                var originalPayloadPaddedToBlockSize = payload.PadToModulus(engine.BlockSizeBits).ToBytes();

                // Decrypt the last full payload block (in this case the second to last block)
                var secondToLastBlock           = new byte[engine.BlockSizeBytes];
                var secondToLastBlockStartIndex = (numberOfBlocks - 2) * engine.BlockSizeBytes;
                Array.Copy(originalPayloadPaddedToBlockSize, secondToLastBlockStartIndex, secondToLastBlock, 0, engine.BlockSizeBytes);

                var decryptedSecondToLastBlockBuffer = new byte[engine.BlockSizeBytes];

                engine.ProcessSingleBlock(secondToLastBlock, decryptedSecondToLastBlockBuffer, 0);

                var decryptedBlock = new BitString(decryptedSecondToLastBlockBuffer);

                // Pad the payload to the nearest multiple of the block size using the last B−M bits of block cipher decryption of the second-to-last ciphertext block.
                var amountToPad = (engine.BlockSizeBits - payload.BitLength % engine.BlockSizeBits);
                if (amountToPad > 0)
                {
                    payload = payload.ConcatenateBits(BitString.Substring(decryptedBlock, 0, amountToPad));
                }

                var payloadBytes = payload.ToBytes();
                TransformText(payloadBytes, engine, numberOfBlocks, originalPayloadBitLength);

                payload = new BitString(payloadBytes);
                return(payload.ToBytes());
            }

            return(payload.ToBytes());
        }
        private BitString BCC(BitString key, BitString data)
        {
            // 1. chaining_value = 0^outlen
            // Comment: set the first chaining value to outlen zeros
            BitString chainingValue = new BitString(CounterAttributes.OutputLength);

            // 2. n = len(data)/outlen
            int n = data.BitLength / CounterAttributes.OutputLength;

            // 3. Starting with the leftmost bits of data, split the data into n
            // blocks of outlen bits each forming block_1 to block_n

            // 4. For i = 1 to n do:
            int iStart = data.BitLength - CounterAttributes.OutputLength;

            for (int i = 0; i < n; ++i, iStart -= CounterAttributes.OutputLength)
            {
                // 4.1 input_block = chaining_value xor block(i)
                BitString inputBlock = chainingValue.XOR(data.Substring(iStart, CounterAttributes.OutputLength));
                // 4.2 chaining_value = Block_Encrypt(Key, input_block)
                chainingValue = BlockEncrypt(key, inputBlock);
            }

            // 5. output_block = chaining_value;
            BitString outputBlock = chainingValue;

            // 6. Return output_block
            return(outputBlock);
        }
Beispiel #6
0
        public void Substring_ShouldReturnExpectedSubstring_WithEnumeration()
        {
            var bitString = new BitString("11110101");
            var other     = bitString.Substring(3, 4);

            Assert.AreEqual(4, other.Length);
            Assert.AreEqual("1010", other.ToBinString());
        }
Beispiel #7
0
        public void Substring_ShouldReturnExpectedSubstring_WithCopy()
        {
            var bitString = new BitString("111101011001011011100010");
            var other     = bitString.Substring(8, 8);

            Assert.AreEqual(8, other.Length);
            Assert.AreEqual("10010110", other.ToBinString());
        }
Beispiel #8
0
        protected virtual void Absorb(byte[] bytes, int length)
        {
            State.Clear();
            var message = new BitString(bytes, length);
            var rate    = State.Rate;

            message.Append(Suffix());
            message.Append(GetPadding(rate, message.Length));

            var       n      = message.Length / rate;
            var       zeroes = new BitString(Capacity);
            BitString chunk;

            for (var i = 0; i < n; i++)
            {
                chunk = message.Substring(rate * i, rate);
                chunk.Append(zeroes);
                State.BitString.Xor(chunk);
                Function();
            }
        }
        private BitString GetNextPayload(int j, BitString currentIv, List <BitString> previousOutputs)
        {
            switch (Shift)
            {
            case 1:
                if (j < 128)
                {
                    // Note, Bits are stored in the opposite direction on the BitString in comparison to where the MCT pseudo code expects them
                    return(currentIv
                           .Substring(currentIv.BitLength - 1 - j, Shift).GetDeepCopy());
                }
                else
                {
                    return(previousOutputs[j - _blockSizeBits / Shift].GetDeepCopy());
                }

            case 8:
                if (j < 16)
                {
                    return(new BitString(new byte[] { currentIv[j] }));
                }
                else
                {
                    return(previousOutputs[j - 16].GetDeepCopy());
                }

            case 128:
                if (j == 0)
                {
                    return(currentIv.GetDeepCopy());
                }
                else
                {
                    return(previousOutputs[previousOutputs.Count - 2].GetDeepCopy());
                }

            default:
                throw new ArgumentException(nameof(Shift));
            }
        }
Beispiel #10
0
        // Use this method when you need a Little Endian substring that is not a multiple of 8 bits in length
        // For the last byte, we would need to pull bits from the other end of the byte, rather than like reading an array in order
        // This only occurs once under SHAKE with variable output sizes
        private static BitString LittleEndianSubstring(BitString message, int startIdx, int length)
        {
            var lastFullByte = (length / 8) * 8;                                    // Integer division rounds down for us
            var firstBytes   = BitString.MSBSubstring(message, startIdx, lastFullByte);

            if (length == lastFullByte)
            {
                return(firstBytes);
            }

            var nextByte = BitString.MSBSubstring(message, startIdx + lastFullByte, 8);

            var bitsNeeded = length % 8;
            var lastBits   = new BitString(0);

            if (bitsNeeded != 0)
            {
                lastBits = BitString.Substring(nextByte, 0, bitsNeeded);
            }

            return(BitString.ConcatenateBits(firstBytes, lastBits));
        }
Beispiel #11
0
        public BitString MixKeys(TDESKeys keys, List <BitString> previousOutputs)
        {
            if (keys == null)
            {
                throw new ArgumentNullException(nameof(keys));
            }

            if (previousOutputs == null ||
                (previousOutputs.Count * previousOutputs[0].BitLength) < 192)
            {
                throw new ArgumentException("Need 192 bits of previous outputs", nameof(previousOutputs));
            }
            var outputBitString = new BitString(192);

            previousOutputs.Reverse();
            foreach (var previousOutput in previousOutputs)
            {
                outputBitString = outputBitString.ConcatenateBits(previousOutput);
            }
            var newKey1 = keys.KeysAsBitStrings[0].XOR(outputBitString.Substring(0, 64));
            var newKey2 = keys.KeysAsBitStrings[1].XOR(outputBitString.Substring(0, 64));
            var newKey3 = keys.KeysAsBitStrings[2].XOR(outputBitString.Substring(0, 64));

            if (keys.KeyOption == KeyOptionValues.ThreeKey)
            {
                newKey2 = keys.KeysAsBitStrings[1].XOR(outputBitString.Substring(64, 64));
                newKey3 = keys.KeysAsBitStrings[2].XOR(outputBitString.Substring(128, 64));
            }
            if (keys.KeyOption == KeyOptionValues.TwoKey)
            {
                newKey2 = keys.KeysAsBitStrings[1].XOR(outputBitString.Substring(64, 64));
            }
            byte[] outputArray = new byte[24];

            Array.Copy(newKey1.ToBytes(), outputArray, 8);
            Array.Copy(newKey2.ToBytes(), 0, outputArray, 8, 8);
            Array.Copy(newKey3.ToBytes(), 0, outputArray, 16, 8);
            return(new BitString(outputArray));
        }
Beispiel #12
0
        /*
         *  INPUT: The initial Single-Tuple of a random length between 0 and 65536 bits.
         *
         *  MCT(Tuple, MaxOutLen, MinOutLen, OutLenIncrement)
         *  {
         *    Range = (MaxOutLen – MinOutLen + 1);
         *    OutputLen = MaxOutLen;
         *    Customization = "";
         *
         *    T[0][0] = Tuple;
         *
         *    for (j = 0; j < 100; j++)
         *    {
         *      for (i = 1; i < 1001; i++)
         *      {
         *        workingBits = Left(T[i-1][0] || ZeroBits(288), 288);
         *        tupleSize = Left(workingBits, 3) % 4 + 1; // never more than 4 tuples to a round
         *        for (k = 0; k < tupleSize; k++)
         *        {
         *          T[i][k] = Substring of workingBits from (k * 288 / tupleSize) to ((k+1) * 288 / tupleSize - 1);
         *        }
         *        Output[i] = TupleHash(T[i], OutputLen, Customization);
         *        Rightmost_Output_bits = Right(Output[i], 16);
         *        OutputLen = MinOutLen + (floor((Rightmost_Output_bits % Range) / OutLenIncrement) * OutLenIncrement);
         *        Customization = BitsToString(T[i][0] || Rightmost_Output_bits);
         *      }
         *
         *      OutputJ[j] = Output[1000];
         *    }
         *
         *    return OutputJ;
         *  }
         */
        #endregion MonteCarloAlgorithm Pseudocode

        public MCTResultTuple <AlgoArrayResponse> MCTHash(HashFunction function, IEnumerable <BitString> tuple, MathDomain domain, bool hexCustomization, bool isSample)
        {
            _hexCustomization = hexCustomization;
            if (isSample)
            {
                NUM_OF_RESPONSES = 3;
            }

            var responses = new List <AlgoArrayResponse>();
            var i         = 0;
            var j         = 0;
            var min       = domain.GetDomainMinMax().Minimum;
            var max       = domain.GetDomainMinMax().Maximum;
            var increment = domain.GetDomainMinMax().Increment;
            var minBytes  = min / 8;
            var maxBytes  = max / 8;

            var outputLen     = max;
            var customization = "";
            var range         = (max - min) + 1;
            var innerTuple    = GetDeepCopy(tuple);

            try
            {
                for (i = 0; i < NUM_OF_RESPONSES; i++)
                {
                    var innerDigest       = new BitString(0);
                    var iterationResponse = new AlgoArrayResponse()
                    {
                    };
                    iterationResponse.Tuple         = innerTuple;
                    iterationResponse.Customization = customization;

                    for (j = 0; j < 1000; j++)
                    {
                        // Might not have 144 bits to pull from so we pad with 0
                        var innerBitString = BitString.ConcatenateBits(innerTuple.ElementAt(0), BitString.Zeroes(288))
                                             .GetMostSignificantBits(288);
                        var innerTupleSize = innerBitString.GetMostSignificantBits(3).Bits.ToInt() % 4 + 1;
                        innerTuple = new List <BitString>();
                        for (int k = 0; k < innerTupleSize; k++)
                        {
                            innerTuple.Add(BitString.MSBSubstring(innerBitString, k * 288 / innerTupleSize, 288 / innerTupleSize));
                        }

                        function.DigestLength = outputLen;

                        var innerResult = _iTupleHash.HashMessage(function, innerTuple, customization);
                        innerDigest = innerResult.Digest.GetDeepCopy();

                        // Will always have 16 bits to pull from
                        var rightmostBitString = BitString.Substring(innerDigest, 0, 16);
                        var rightmostBits      = rightmostBitString.Bits;

                        outputLen     = min + (int)System.Math.Floor((double)(rightmostBits.ToInt() % range) / increment) * increment;
                        customization = GetStringFromBytes(BitString.ConcatenateBits(innerTuple.ElementAt(0), rightmostBitString).ToBytes());

                        innerTuple = new List <BitString>();
                        innerTuple.Add(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 MCTResultTuple <AlgoArrayResponse>($"{ex.Message}; {outputLen}"));
            }

            return(new MCTResultTuple <AlgoArrayResponse>(responses));
        }
Beispiel #13
0
        /*
         *  INPUT: The initial Msg is the length of the digest size
         *
         *  MCT(Msg, MaxOutLen, MinOutLen, OutLenIncrement)
         *  {
         *    Range = (MaxOutLen – MinOutLen + 1);
         *    OutputLen = MaxOutLen;
         *    FunctionName = "";
         *    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] = CSHAKE(InnerMsg, OutputLen, FunctionName, Customization);
         *        Rightmost_Output_bits = Right(Output[i], 16);
         *        OutputLen = MinOutLen + (floor((Rightmost_Output_bits % Range) / OutLenIncrement) * OutLenIncrement);
         *        Customization = BitsToString(InnerMsg || Rightmost_Output_bits);
         *      }
         *
         *      OutputJ[j] = Output[1000];
         *    }
         *
         *    return OutputJ;
         *  }
         */
        #endregion MonteCarloAlgorithm Pseudocode

        public MctResult <AlgoArrayResponseWithCustomization> MCTHash(HashFunction function, BitString message, MathDomain domain, bool customizationHex, bool isSample)
        {
            _customizationHex = customizationHex;

            if (isSample)
            {
                NUM_OF_RESPONSES = 3;
            }

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

            //var outputLen = (int)System.Math.Floor((double)max / 8) * 8;
            var outputLen     = max;
            var customization = "";
            var functionName  = "";
            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;

                    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));
                        innerMessage          = BitString.MSBSubstring(innerMessage, 0, 128);
                        function.DigestLength = outputLen;

                        var innerResult = _iCSHAKE.HashMessage(function, innerMessage, customization, functionName);
                        innerDigest = innerResult.Digest.GetDeepCopy();

                        // Will always have 16 bits to pull from
                        var rightmostBitString = BitString.Substring(innerDigest, 0, 16);
                        var rightmostBits      = rightmostBitString.Bits;

                        //outputLen = min + (8 * rightmostBits.ToInt()) % range;
                        outputLen     = min + (int)System.Math.Floor((double)(rightmostBits.ToInt() % range) / increment) * increment;
                        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));
        }
Beispiel #14
0
        public virtual BitString GCTR(BitString icb, BitString x, BitString key)
        {
            // ICB must be 128 bits long
            // ThisLogger.Debug("GCTR");
            if (icb.BitLength != 128)
            {
                ThisLogger.Warn($"icbLen:{icb.BitLength}");
                return(null);
            }

            // Step 1: If X is the empty string, then return the empty string as Y
            if (x.BitLength == 0)
            {
                return(new BitString(0));
            }

            var ecb = _modeFactory.GetStandardCipher(
                _engineFactory.GetSymmetricCipherPrimitive(BlockCipherEngines.Aes),
                BlockCipherModesOfOperation.Ecb
                );

            // Step 2: Let n = ceil[ len(X)/128 ]
            int n = x.BitLength.CeilingDivide(128);

            // Step 3: Let X1,X2,...,Xn-1,Xn denote the unique sequence of bit
            // strings such that X = X1 || X2 || ... || Xn-1 || Xn*
            // X1, X2,...,Xn-1 are complete blocks
            // Xn* is either a complete block or a partial block

            // Step 4: Let CB1 = ICB
            // Step 5: For i = 2 to n, let CBi = inc32(CBi-1)
            // Step 6: For i = 1 to n-1, let Yi = Xi xor CIPH_K(CBi)

            BitString cbi = icb;
            BitString Y   = new BitString(0);
            int       sx  = x.BitLength - 128;

            for (int i = 1; i <= (n - 1); ++i, sx -= 128)
            {
                if (i > 1)
                {
                    cbi = inc_s(32, cbi);
                }
                BitString xi       = x.Substring(sx, 128);
                var       cbiParam = new ModeBlockCipherParameters(
                    BlockCipherDirections.Encrypt,
                    key,
                    cbi
                    );
                var       h  = ecb.ProcessPayload(cbiParam);
                BitString yi = BitString.XOR(xi, h.Result);
                Y = Y.ConcatenateBits(yi);    // This is part of Step 8
            }

            // Step 7: Let Yn* = Xn* xor MSB_len(Xn*) (CIPH_K(CBn))
            // i == n case:
            if (n > 1)
            {
                cbi = inc_s(32, cbi);
            }

            var xn        = x.Substring(0, 128 + sx);
            var cbiParam1 = new ModeBlockCipherParameters(
                BlockCipherDirections.Encrypt,
                key,
                cbi
                );
            var h1 = ecb.ProcessPayload(cbiParam1);

            var yn = xn.XOR(h1.Result.GetMostSignificantBits(xn.BitLength));

            Y = Y.ConcatenateBits(yn); // This is part of Step 8

            // Step 8: Let Y = Y1 || ... || Yn*

            // Step 9: Return Y
            return(Y);
        }
        // Public for BlockCipherConditioningComponent
        public DrbgResult BlockCipherDf(BitString seedMaterial, int numberOfBitsToReturn)
        {
            int maxNumberOfBits = 512;

            // Check that input string is a multiple of 8 bits
            if (seedMaterial.BitLength % 8 != 0)
            {
                ThisLogger.Debug($"{nameof(seedMaterial)} not mod 8");
                return(new DrbgResult(DrbgStatus.Error));
            }

            // 1. If (no_of_bits_to_return > max_number_of_bits) then return
            // and ERROR_FLAG
            if (numberOfBitsToReturn > maxNumberOfBits)
            {
                ThisLogger.Debug($"{nameof(seedMaterial)} gt {nameof(maxNumberOfBits)}");
                return(new DrbgResult(DrbgStatus.Error));
            }

            // 2. L = len(input_string)/8
            // Comment: L is the bitstring representation of the integer resulting
            // from len(input_string)/8. L shall be represented as a 32-bit integer.
            //BitString l = new BitString(new BigInteger(seedMaterial.BitLength / 8)).GetLeastSignificantBits(4 * 8);
            BitString l = new BitString(BitConverter.GetBytes(seedMaterial.BitLength / 8).Reverse().ToArray());

            // 3. N = no_of_bits_to_return/8
            // Comment: N is the bitstring representation of the integer resulting
            // from number_of_bits_to_return/8.  N shall be represented as a 32-bit
            // integer
            //BitString n = new BitString(new BigInteger(numberOfBitsToReturn / 8)).GetLeastSignificantBits(4 * 8);
            BitString n = new BitString(BitConverter.GetBytes(numberOfBitsToReturn / 8).Reverse().ToArray());

            // 3. S = L || N || input_string || 0x80
            // Comment: Prepend the string length and the requested length of the
            // output to the input_string
            // NOTE: SP800-90 has step 3 twice
            BitString s = l
                          .ConcatenateBits(n)
                          .ConcatenateBits(seedMaterial)
                          .ConcatenateBits(new BitString("80"));

            // 4. While (len(S) mod outlen) != 0, S = S || 0x00
            // Comment: Pad S with zeros if necessary
            while ((s.BitLength % CounterAttributes.OutputLength) != 0)
            {
                s = s
                    .ConcatenateBits(BitString.Zero());
            }

            // 5. temp = the Null string
            // Comment: compute the starting value
            BitString temp = new BitString(0);

            // 6. i = 0
            // Comment: i shall be represented as a 32-bit integer, i.e., len(i) = 32
            int i = 0;

            byte[] bt = new byte[32];
            for (int iterator = 0; iterator < 32; iterator++)
            {
                bt[iterator] = (byte)iterator;
            }

            // 7. Key = leftmost keylen bits of 0x000102030405
            BitString k = new BitString(bt).GetMostSignificantBits(CounterAttributes.KeyLength);

            // 8. While len(temp)< keylen + outlen, do:
            while (temp.BitLength < (CounterAttributes.KeyLength + CounterAttributes.OutputLength))
            {
                // 8.1 IV = i || 0^(outlen - len(i))
                BitString iv = new BitString(BitConverter.GetBytes(i).Reverse().ToArray())
                               .ConcatenateBits(new BitString(CounterAttributes.OutputLength - 32));
                // 8.2 temp = temp || BCC(Key, (IV || S))
                temp = temp
                       .ConcatenateBits(BCC(k, iv.ConcatenateBits(s)));

                i++;
            }

            // 9. Key = Leftmost keylen bits of temp
            k = temp.GetMostSignificantBits(CounterAttributes.KeyLength);

            // 10. X = Next outlen bits of temp
            int       istart = temp.BitLength - CounterAttributes.KeyLength - CounterAttributes.OutputLength;
            BitString x      = temp.Substring(istart, CounterAttributes.OutputLength);

            // 11. temp = the Null string
            temp = new BitString(0);

            // 12. While len(temp) < number_of_bits_to_return, do:
            while (temp.BitLength < numberOfBitsToReturn)
            {
                // 12.1 X = Block_Encrypt(Key, X)
                x = BlockEncrypt(k, x);
                // 12.2 temp = temp || X
                temp = temp.ConcatenateBits(x);
            }

            // 13. requested_bits = Leftmost no_of_bits_to_return of temp
            return(new DrbgResult(temp.GetMostSignificantBits(numberOfBitsToReturn)));
        }
Beispiel #16
0
        /*
         * INPUT: The initial Msg of 128 bits long
         *
         * Initial Outputlen = (floor(maxoutlen/8) )*8
         * //makes maxoutlen a multiple of 8 and remains within the range specified.
         *
         * {
         *     Output0 = Msg;
         *     for (j=0; j<100; j++) {
         *         for (i=1; i<1001; i++) {
         *             M[i] = 128 leftmost bits of Output[i-1];
         *             Output[i] = SHAKE(M[i],Outputlen);
         *             If (i == 1000){
         *                 Outputlen[j] = Outputlen;
         *             }
         *             Rightmost_Output_bits = rightmost 16 bits of Output[i];
         *             Range = (maxoutbytes – minoutbytes + 1);
         *             Outputlen = minoutbytes + (Rightmost_Output_bits mod Range);
         *         }
         *         Output[j] = Output[1000];
         *         OUTPUT: Outputlen[j], Output[j]
         *     }
         * }
         */
        #endregion MonteCarloAlgorithm Pseudocode

        public MctResult <AlgoArrayResponse> MctHash(BitString message, MathDomain domain, bool isSample = false)
        {
            if (isSample)
            {
                NUM_OF_RESPONSES = 3;
            }

            var responses = new List <AlgoArrayResponse>();
            var i         = 0;
            var j         = 0;
            var min       = domain.GetDomainMinMax().Minimum;
            var max       = domain.GetDomainMinMax().Maximum;
            var minBytes  = min / 8;
            var maxBytes  = max / 8;

            var outputLen = (int)System.Math.Floor((double)max / 8) * 8;
            var range     = (max - min) + 8;
            //var range = (max - min) + min;

            var innerMessage = message.GetDeepCopy();

            // Might not have 128 bits to pull from so we pad with 0
            innerMessage = BitString.ConcatenateBits(innerMessage, BitString.Zeroes(128));
            innerMessage = BitString.MSBSubstring(innerMessage, 0, 128);

            try
            {
                for (i = 0; i < NUM_OF_RESPONSES; i++)
                {
                    var innerDigest       = new BitString(0);
                    var iterationResponse = new AlgoArrayResponse()
                    {
                    };
                    iterationResponse.Message = innerMessage;

                    for (j = 0; j < 1000; j++)
                    {
                        var innerResult = _sha.HashMessage(innerMessage, outputLen);
                        innerDigest = innerResult.Digest.GetDeepCopy();

                        // Will always have 16 bits to pull from
                        var rightmostBits = BitString.Substring(innerDigest, 0, 16).Bits;

                        outputLen = min + (8 * GetIntFromBits(rightmostBits)) % range;

                        innerMessage = innerDigest.GetDeepCopy();
                        // Might not have 128 bits to pull from so we pad with 0
                        innerMessage = BitString.ConcatenateBits(innerMessage, BitString.Zeroes(128));
                        innerMessage = BitString.MSBSubstring(innerMessage, 0, 128);
                    }

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

            return(new MctResult <AlgoArrayResponse>(responses));
        }
Beispiel #17
0
        private VerifyResult EmsaPssVerify(BitString M, BitString EM, int emBits)
        {
            var mHash = Sha.HashMessage(M).Digest;

            if (EM.BitLength < mHash.BitLength / 8 + SaltLength + 2)
            {
                return(new VerifyResult("RSA PSS Verify: inconsistent result"));
            }

            if (!EM.Substring(0, 8).Equals(Bc))
            {
                return(new VerifyResult("RSA PSS Verify: 'BC' hex not found"));
            }

            // Bit values
            var maskedDB = EM.MSBSubstring(0, EM.BitLength - mHash.BitLength - 8);
            var H        = EM.MSBSubstring(maskedDB.BitLength, mHash.BitLength);

            if (!maskedDB.MSBSubstring(0, EM.BitLength - emBits).Equals(BitString.Zeroes(EM.BitLength - emBits)))
            {
                return(new VerifyResult("RSA PSS Verify: Leading 0s not found in maskedDB"));
            }

            var dbMask = Mask.Mask(H, EM.BitLength - mHash.BitLength - 8);
            var DB     = BitString.XOR(maskedDB, dbMask);

            for (var i = 0; i < EM.BitLength - emBits; i++)
            {
                DB.Set(DB.BitLength - i - 1, false);
            }

            var leftmostOctets = EM.BitLength - mHash.BitLength - SaltLength * 8 - 16;

            if (leftmostOctets != 0)
            {
                if (!DB.MSBSubstring(0, leftmostOctets).Equals(BitString.Zeroes(leftmostOctets)))
                {
                    return(new VerifyResult("RSA PSS Verify: DB incorrect, improper number of leading 0s"));
                }
            }

            if (!DB.MSBSubstring(leftmostOctets, 8).Equals(ZeroOne))
            {
                return(new VerifyResult("RSA PSS Verify: DB incorrect, '01' byte not found"));
            }

            var salt   = DB.Substring(0, SaltLength * 8);
            var MPrime = BitString.Zeroes(64);

            MPrime = BitString.ConcatenateBits(MPrime, mHash);
            MPrime = BitString.ConcatenateBits(MPrime, salt);

            var HPrime = Sha.HashMessage(MPrime).Digest;

            if (HPrime.Equals(H))
            {
                return(new VerifyResult());
            }
            else
            {
                return(new VerifyResult("RSA PSS Verify: Hashes do not match"));
            }
        }