Esempio n. 1
0
        public void ShouldCorrectlyConvert168BitKeyTo192BitKey(string keyHex, string expectedHex)
        {
            var k        = new BitString(keyHex);
            var expected = new BitString(expectedHex);

            var result = _subject.Convert168BitKeyTo192BitKey_public(k);

            var expectedArr = new BitString[3];

            expectedArr[0] = expected.MSBSubstring(0, 64);
            expectedArr[1] = expected.MSBSubstring(64, 64);
            expectedArr[2] = expected.MSBSubstring(64 * 2, 64);

            var resultArr = new BitString[3];

            resultArr[0] = result.MSBSubstring(0, 64);
            resultArr[1] = result.MSBSubstring(64, 64);
            resultArr[2] = result.MSBSubstring(64 * 2, 64);

            for (var i = 0; i < 3; i++)
            {
                Assert.AreEqual(expectedArr[i], resultArr[i], $"{i}");
            }

            Assert.AreEqual(expected, result, "whole");
        }
        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));
        }
Esempio n. 3
0
        // Computes Kc as described in rfc 8554
        public BitString Algorithm4b(BitString sig, BitString msg, BitString pubType, BitString I, BitString q)
        {
            // 1. If the signature is not at least four bytes long, return INVALID.
            if (sig.BitLength < 32)
            {
                return(null);
            }

            // 2. Parse sigtype, C, and y from the signature as follows:
            // a. sigtype = strTou32(first 4 bytes of signature)
            var sigType = sig.MSBSubstring(0, 32);

            // b. If sigtype is not equal to pubtype, return INVALID.
            if (!pubType.Equals(sigType))
            {
                return(null);
            }

            // c. Set n and p according to the pubtype and Table 1; if the signature is not exactly 4 + n * (p + 1)
            //    bytes long, return INVALID.
            var p = LmotsModeMapping.GetPFromCode(sigType);
            var n = LmotsModeMapping.GetNFromCode(sigType);

            if (sig.BitLength != (4 + (n * (p + 1))) * 8)
            {
                return(null);
            }

            // d. C = next n bytes of signature
            var C = sig.MSBSubstring(32, n * 8);

            // e. y[0] = next n bytes of signature
            //    y[1] = next n bytes of signature
            //    ...
            //    y[p - 1] = next n bytes of signature
            var y = sig.MSBSubstring((n * 8) + 32, p * n * 8);

            // 3. Compute the string Kc as described in rfc 8554
            var Q = _sha256.HashMessage(I
                                        .ConcatenateBits(q)
                                        .ConcatenateBits(D_MESG)
                                        .ConcatenateBits(C)
                                        .ConcatenateBits(msg)).Digest;
            var cksmQ  = CheckSum(Q);
            var QcksmQ = Q.ConcatenateBits(cksmQ);

            var z = LmsDllLoader.GenZ(_p, _n, _w, y.ToBytes(), QcksmQ.ToBytes(), I.ToBytes(), q.ToBytes());

            var concatenated = I.ConcatenateBits(q).ConcatenateBits(D_PBLC);

            concatenated = concatenated.ConcatenateBits(new BitString(z));

            var Kc = _sha256.HashMessage(concatenated).Digest;

            // 4. Return Kc.
            return(Kc);
        }
Esempio n. 4
0
 public static BitString SubString(BitString X, int start, int end)
 {
     if (start >= end || start >= X.BitLength)
     {
         return(new BitString(0));
     }
     else if (end <= X.BitLength)
     {
         return(X.MSBSubstring(start, end - start));
     }
     else
     {
         return(X.MSBSubstring(start, X.BitLength - start));
     }
 }
Esempio n. 5
0
        public LmotsVerificationResult VerifyLmotsSignature(BitString sig, BitString publicKey, BitString msg)
        {
            // 1. If the public key is not at least four bytes long, return INVALID.
            if (publicKey.BitLength < 32)
            {
                return(new LmotsVerificationResult("Validation failed. Public key wrong length."));
            }

            // 2.  Parse pubtype, I, q, and K from the public key as follows:
            // a. pubtype = strTou32(first 4 bytes of public key)
            var pubType = publicKey.MSBSubstring(0, 32);

            // b. Set n according to the pubkey and Table 1; if the public key is not exactly 24 + n bytes long, return INVALID.
            var n = LmotsModeMapping.GetNFromCode(pubType);

            if (publicKey.BitLength != (n + 24) * 8)
            {
                return(new LmotsVerificationResult("Validation failed. Public key wrong length."));
            }

            // c. I = next 16 bytes of public key
            var I = publicKey.MSBSubstring(32, 128);

            // d. q = strTou32(next 4 bytes of public key)
            var q = publicKey.MSBSubstring(160, 32);

            // e. K = next n bytes of public key
            var K = publicKey.MSBSubstring(192, n * 8);

            // 3. Compute the public key candidate Kc from the signature, message, pubtype, and the identifiers I and q
            //    obtained from the public key, using Algorithm 4b.If Algorithm 4b returns INVALID, then return INVALID.
            var Kc = Algorithm4b(sig, msg, pubType, I, q);

            if (Kc == null)
            {
                return(new LmotsVerificationResult("Validation failed. Computing Kc failed."));
            }

            // 4. If Kc is equal to K, return VALID; otherwise, return INVALID.
            if (K.Equals(Kc))
            {
                return(new LmotsVerificationResult());
            }
            else
            {
                return(new LmotsVerificationResult("Validation failed. Signature does not match."));
            }
        }
Esempio n. 6
0
        // Public for use in HashConditioningComponent
        public DrbgResult Hash_Df(BitString data, int bitsToReturn)
        {
            // 0
            if (bitsToReturn > 255 * HashAttributes.OutputLength)
            {
                throw new ArgumentException("Requesting too many bits to return");
            }

            // 1
            var temp = new BitString(0);

            // 2
            var len = bitsToReturn.CeilingDivide(HashAttributes.OutputLength);

            // 3
            var counter = new BitString("01");

            // 4
            for (var i = 0; i < len; i++)
            {
                // 4.1
                var dataToHash = counter.ConcatenateBits(BitString.To32BitString(bitsToReturn)).ConcatenateBits(data);
                temp = temp.ConcatenateBits(_sha.HashMessage(dataToHash).Digest);

                // 4.2
                counter = counter.BitStringAddition(BitString.One());
            }

            // 5
            var requestedBits = temp.MSBSubstring(0, bitsToReturn);

            // 6
            return(new DrbgResult(requestedBits));
        }
Esempio n. 7
0
        public FfcVerificationResult Verify(FfcDomainParameters domainParameters, FfcKeyPair keyPair, BitString message, FfcSignature signature, bool skipHash = false)
        {
            // 1
            if (signature.R < 0 || signature.R > domainParameters.Q)
            {
                return(new FfcVerificationResult("Invalid r provided"));
            }

            if (signature.S < 0 || signature.S > domainParameters.Q)
            {
                return(new FfcVerificationResult("Invalid s provided"));
            }

            // 2
            var w    = signature.S.ModularInverse(domainParameters.Q);
            var zLen = System.Math.Min(Sha.HashFunction.OutputLen, new BitString(domainParameters.Q).BitLength);
            var z    = BitString.MSBSubstring(Sha.HashMessage(message).Digest, 0, zLen).ToPositiveBigInteger();
            var u1   = (z * w) % domainParameters.Q;
            var u2   = (signature.R * w) % domainParameters.Q;

            // (g^u1 * y^u2) mod p == [(g^u1 mod p) * (y^u2 mod p)] mod p
            var v = ((BigInteger.ModPow(domainParameters.G, u1, domainParameters.P) * BigInteger.ModPow(keyPair.PublicKeyY, u2, domainParameters.P)) % domainParameters.P) % domainParameters.Q;

            // 3
            if (v != signature.R)
            {
                return(new FfcVerificationResult("Invalid v, does not match provided r"));
            }

            return(new FfcVerificationResult());
        }
Esempio n. 8
0
        private BitString HashGen(BitString v, int bitsToReturn)
        {
            // 1
            var m = bitsToReturn / HashAttributes.OutputLength + (bitsToReturn % HashAttributes.OutputLength != 0 ? 1 : 0);

            // 2
            var data = v.GetDeepCopy();

            // 3
            var W = new BitString(0);

            // 4
            for (var i = 0; i < m; i++)
            {
                // 4.1
                var w = _sha.HashMessage(data).Digest;

                // 4.2
                W = W.ConcatenateBits(w);

                // 4.3
                data = data.BitStringAddition(BitString.One()).GetLeastSignificantBits(HashAttributes.SeedLength);
            }

            // 5
            var returnedBits = W.MSBSubstring(0, bitsToReturn);

            // 6
            return(returnedBits);
        }
Esempio n. 9
0
        // As described on page 8 of RFC 8554
        private BigInteger Coef(BitString S, int i, int w)
        {
            var resultlhs = new BitString(new BigInteger((1 << w) - 1));

            var resultrhs = new BitString(S.MSBSubstring(i * w / 8 * 8, 8).ToPositiveBigInteger() >> (8 - (w * (i % (8 / w)) + w)));

            return(resultlhs.AND(resultrhs).ToPositiveBigInteger());
        }
Esempio n. 10
0
        public KdfResult DeriveKey(BitString kI, BitString fixedData, int len, BitString iv = null, int breakLocation = 0)
        {
            // 1
            var n = len.CeilingDivide(Mac.OutputLength);

            // 2
            if (n > NumberTheory.Pow2(_counterLength) - 1)
            {
                return(new KdfResult("Counter length too long for operation"));
            }

            // 3
            var result = new BitString(0);

            // 4
            if (_counterLocation == CounterLocations.MiddleFixedData)
            {
                if (breakLocation < 1 || breakLocation > fixedData.BitLength - 1)
                {
                    return(new KdfResult("Invalid break location"));
                }
            }

            for (var i = 1; i <= n; i++)
            {
                var counterBits = BitString.To32BitString(i).GetLeastSignificantBits(_counterLength);
                var data        = new BitString(0);

                switch (_counterLocation)
                {
                case CounterLocations.BeforeFixedData:
                    data = data.ConcatenateBits(counterBits).ConcatenateBits(fixedData);
                    break;

                case CounterLocations.AfterFixedData:
                    data = data.ConcatenateBits(fixedData).ConcatenateBits(counterBits);
                    break;

                case CounterLocations.MiddleFixedData:
                    var firstPart  = fixedData.GetMostSignificantBits(breakLocation);
                    var secondPart = fixedData.MSBSubstring(breakLocation, fixedData.BitLength - breakLocation);
                    data = data.ConcatenateBits(firstPart).ConcatenateBits(counterBits).ConcatenateBits(secondPart);
                    break;

                default:
                    return(new KdfResult("Invalid Counter location"));
                }

                var kTemp = PseudoRandomFunction(kI, data);

                result = result.ConcatenateBits(kTemp);
            }

            // 5
            var kOut = result.GetMostSignificantBits(len);

            return(new KdfResult(kOut));
        }
Esempio n. 11
0
        /*
         * INPUT: The initial Msg of 256 bits long
         *        LmsParams
         *        SEED
         *        RootI
         *
         * {
         *     lmsKeyPair = GenerateLmsKeyPair(SEED, RootI, Params);
         *     Output0 = Msg;
         *     for (j=0; j<100; j++) {
         *         for (i=1; i<(isSample ? 101 : 1001); i++) {
         *             M[i] = leftmost bits indexed from 96 to 352;
         *             if (lmsKeyPair is expired) {
         *                 lmsKeyPair = GenerateLmsKeyPair(M[i], 128 left most bits of M[i], Params);
         *             }
         *             Output[i] = LmsSignature(M[i],lmsKeyPair);
         *             lmsKeyPair = UpdateLmsKeyPair(lmsKeyPair);
         *         }
         *         Output[j] = Output[1000];
         *         OUTPUT: Output[j]
         *     }
         * }
         */
        #endregion MonteCarloAlgorithm Pseudocode

        public async Task <MCTResult <AlgoArrayResponse> > MCTHashAsync(LmsType[] lmsTypes, LmotsType[] lmotsTypes,
                                                                        BitString seed, BitString rootI, BitString message, bool isSample)
        {
            var hss = _hssFactory.GetInstance(lmsTypes.Length, lmsTypes, lmotsTypes, EntropyProviderTypes.Testable, seed, rootI);

            var keyPair = await hss.GenerateHssKeyPairAsync();

            if (isSample)
            {
                NUM_OF_RESPONSES = 3;
            }

            var responses = new List <AlgoArrayResponse>();
            var i         = 0;
            var j         = 0;

            var innerMessage = message.GetDeepCopy();

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

                    for (j = 0; j < (isSample ? 100 : 1000); j++)
                    {
                        if (keyPair.Expired)
                        {
                            hss = _hssFactory.GetInstance(lmsTypes.Length, lmsTypes, lmotsTypes,
                                                          EntropyProviderTypes.Testable, innerMessage, innerMessage.MSBSubstring(0, 128));
                            keyPair = await hss.GenerateHssKeyPairAsync();
                        }

                        innerSignature = (await hss.GenerateHssSignatureAsync(innerMessage, keyPair)).Signature;

                        keyPair = await hss.UpdateKeyPairOneStepAsync(keyPair);

                        innerMessage = innerSignature.MSBSubstring(96, 256);
                    }

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

            return(new MCTResult <AlgoArrayResponse>(responses));
        }
Esempio n. 12
0
        public BitString Mask(BitString seed, int maskLen)
        {
            var T          = new BitString(0);
            var iterations = maskLen.CeilingDivide(_sha.HashFunction.OutputLen) - 1;

            for (var i = 0; i <= iterations; i++)
            {
                var dig = _sha.HashMessage(BitString.ConcatenateBits(seed, BitString.To32BitString(i))).Digest;
                T = BitString.ConcatenateBits(T, dig);
            }

            return(T.MSBSubstring(0, maskLen));
        }
Esempio n. 13
0
        private Common.Symmetric.MCTResult <AlgoArrayResponse> Encrypt(IModeBlockCipherParameters param)
        {
            var responses = new List <AlgoArrayResponse> {
                new AlgoArrayResponse {
                    IV        = param.Iv,
                    Keys      = param.Key,
                    PlainText = param.Payload
                }
            };
            int numberOfOutputsToSave     = 192 / Shift;
            var indexAtWhichToStartSaving = NUMBER_OF_ITERATIONS - numberOfOutputsToSave;

            for (var i = 0; i < NumberOfCases; i++)
            {
                Debug.WriteLineIf((i + 1) % 10 == 0, $"Running MCT Encryption round {i + 1} out of {NumberOfCases}");
                var       lastResponse     = responses.Last();
                var       tempText         = lastResponse.PlainText.GetDeepCopy();
                var       tempIv           = lastResponse.IV.GetDeepCopy();
                BitString prevTempIv       = null;
                var       lastCipherTexts  = new List <BitString>();
                BitString output           = null;
                var       keysForThisRound = responses[i].Keys;
                for (var j = 0; j < NUMBER_OF_ITERATIONS; j++)
                {
                    prevTempIv = tempIv.GetDeepCopy();
                    output     = _algo.ProcessPayload(new ModeBlockCipherParameters(
                                                          BlockCipherDirections.Encrypt,
                                                          tempIv,
                                                          keysForThisRound,
                                                          tempText
                                                          )).Result;
                    tempText = prevTempIv.MSBSubstring(0, Shift);

                    if (j >= indexAtWhichToStartSaving)
                    {
                        lastCipherTexts.Insert(0, output.GetDeepCopy());
                    }
                }
                lastResponse.CipherText = output;
                responses.Add(new AlgoArrayResponse()
                {
                    Keys      = _keyMaker.MixKeys(new TDESKeys(lastResponse.Keys.GetDeepCopy()), lastCipherTexts).ToOddParityBitString(),
                    PlainText = prevTempIv.GetDeepCopy().MSBSubstring(0, Shift),
                    IV        = tempIv.GetDeepCopy()
                });
            }
            responses.RemoveAt(responses.Count() - 1);
            return(new Common.Symmetric.MCTResult <AlgoArrayResponse>(responses));
        }
Esempio n. 14
0
        public BitString PolyVal(BitString H, BitString X)
        {
            var invX = new BitString(0);

            for (var i = 0; i < X.BitLength / 128; i++)
            {
                invX = invX.ConcatenateBits(LittleEndianify(X.MSBSubstring(128 * i, 128)));
            }

            var reversedH = LittleEndianify(H);
            var invH      = MulXGHash(reversedH);
            var gHash     = _gcmInternals.GHash(invH, invX);

            return(LittleEndianify(gHash));
        }
Esempio n. 15
0
        /// <summary>
        /// Sponge function for Keccak. Gathers content for sponge and performs hash
        /// </summary>
        /// <param name="message">Raw BitString message</param>
        /// <param name="digestSize">Digest Size</param>
        /// <param name="capacity">Capacity of the sponge function</param>
        /// <returns>Message digest</returns>
        public static BitString Sponge(BitString message, int digestSize, int capacity)
        {
            // Define properties
            // All possible rates are divisible by 8
            var rate = _b - capacity;

            // Pad the message
            var paddedMessage = PadMessage(message, rate);

            // Split up padded message into rate chunks
            var n = paddedMessage.BitLength / rate;
            var P = new BitString[n];

            for (var i = 0; i < n; i++)
            {
                P[i] = BitString.MSBSubstring(paddedMessage, i * rate, rate);
            }

            // Build sponge
            var sponge = new BitString(_b);

            for (var i = 0; i < n; i++)
            {
                var P_i = ConvertEndianness(P[i]);

                var spongeContent = BitString.XOR(sponge, BitString.ConcatenateBits(P_i, new BitString(capacity)));
                sponge = Keccak_p(spongeContent);
            }

            // Truncate output
            var Z = new BitString(0);

            while (true)
            {
                Z = BitString.ConcatenateBits(Z, BitString.MSBSubstring(sponge, 0, rate));
                if (digestSize <= Z.BitLength)
                {
                    return(LittleEndianSubstring(Z, 0, digestSize));
                }

                sponge = Keccak_p(sponge);
            }
        }
Esempio n. 16
0
        public FfcSignatureResult Sign(FfcDomainParameters domainParameters, FfcKeyPair keyPair, BitString message, bool skipHash = false)
        {
            BigInteger r, s;

            do
            {
                var k    = _entropyProvider.GetEntropy(1, domainParameters.Q - 1);
                var kInv = k.ModularInverse(domainParameters.Q);

                r = BigInteger.ModPow(domainParameters.G, k, domainParameters.P) % domainParameters.Q;

                var zLen = System.Math.Min(Sha.HashFunction.OutputLen, new BitString(domainParameters.Q).BitLength);
                var z    = BitString.MSBSubstring(Sha.HashMessage(message).Digest, 0, zLen).ToPositiveBigInteger();

                s = (kInv * (z + keyPair.PrivateKeyX * r)) % domainParameters.Q;
            } while (r == 0 || s == 0);

            return(new FfcSignatureResult(new FfcSignature(r, s)));
        }
Esempio n. 17
0
        public KeccakState(BitString content, int b)        // b is always 1600 but keep it flexible for future
        {
            Width  = b / GridSize;
            L      = (int)System.Math.Log(Width, 2);
            _state = new ulong[RowSize, ColSize];


            // done for better speed when using b as 1600
            if (b == 1600)
            {
                _offsets = new int[5, 5] {
                    { 0, 36, 3, 41, 18 },
                    { 1, 44, 10, 45, 2 },
                    { 62, 6, 43, 15, 61 },
                    { 28, 55, 25, 21, 56 },
                    { 27, 20, 39, 8, 14 }
                };
            }
            else
            {
                _offsets = new int[5, 5];

                int x = 1, y = 0;

                for (var t = 0; t < 24; t++)
                {
                    _offsets[x, y] = ((t + 1) * (t + 2) / 2) % Width;
                    var newX = (0 * x + 1 * y) % 5;
                    var newY = (2 * x + 3 * y) % 5;
                    x = newX;
                    y = newY;
                }
            }

            for (var x = 0; x < RowSize; x++)
            {
                for (var y = 0; y < ColSize; y++)
                {
                    _state[x, y] = BitStringToLong(content.MSBSubstring((x + RowSize * y) * Width, Width));
                }
            }
        }
Esempio n. 18
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));
        }
        public static BitString[] TriPartitionBitString(BitString bitString)
        {
            //string needs to be evenly splittable into three parts, and be on the byte boundary. 3 * 8 = 24
            if (bitString.BitLength % (PARTITIONS * BITS_IN_BYTE) != 0)
            {
                throw new Exception($"Can't tripartition a bitstring of size {bitString.BitLength}");
            }

            var retVal = new BitString[PARTITIONS];

            for (var i = 0; i < PARTITIONS; i++)
            {
                retVal[i] = new BitString(0);
            }

            for (var i = 0; i < bitString.BitLength / BLOCK_SIZE_BITS; i++)
            {
                var ptIndex = i % PARTITIONS;
                retVal[ptIndex] = retVal[ptIndex].ConcatenateBits(bitString.MSBSubstring(i * BLOCK_SIZE_BITS, BLOCK_SIZE_BITS));
            }

            return(retVal);
        }
Esempio n. 20
0
        public BitString AesCtr(BitString key, BitString initialCounterBlock, BitString input)
        {
            var ecb        = _factory.GetStandardCipher(_engine, BlockCipherModesOfOperation.Ecb);
            var block      = initialCounterBlock.GetDeepCopy();
            var output     = new BitString(0);
            var iterations = (int)System.Math.Ceiling(input.BitLength / 128.0);

            for (var i = 0; i < iterations; i++)
            {
                var inputBlock = (i * 128 + 128 <= input.BitLength) ? input.MSBSubstring(i * 128, 128) : input.MSBSubstring(i * 128, input.BitLength % 128);

                if (block.BitLength != 128)
                {
                    throw new Exception($"\nBlock length is not a mulitple of 128.\nInput: {input.ToHex()}\nKey: {key.ToHex()}\nInitialCtr: {initialCounterBlock.ToHex()}");
                }

                var keyStreamBlock = ecb.ProcessPayload
                                     (
                    new ModeBlockCipherParameters
                    (
                        BlockCipherDirections.Encrypt,
                        key,
                        block
                    )
                                     );

                var beginOfBlock = block.MSBSubstring(0, 32);
                var endOfBlock   = block.MSBSubstring(32, 96);
                block = beginOfBlock.BitStringAddition(new BitString("01000000")).ConcatenateBits(endOfBlock).Substring(0, 128);

                var inputXor = inputBlock.GetDeepCopy().ConcatenateBits(BitString.Zeroes(keyStreamBlock.Result.BitLength - inputBlock.BitLength));
                var xor      = keyStreamBlock.Result.XOR(inputXor).MSBSubstring(0, inputBlock.BitLength);
                output = output.ConcatenateBits(xor);
            }

            return(output);
        }
Esempio n. 21
0
        public HssVerificationResult VerifyHssSignature(BitString msg, BitString publicKey, BitString signature)
        {
            // 1. The signature S is parsed into its components as follows:
            // a. Nspk = strTou32(first four bytes of S)
            //    if Nspk+1 is not equal to the number of levels L in pub return INVALID
            var Nspk           = (int)signature.MSBSubstring(0, 32).ToPositiveBigInteger();
            var lengthInPublic = (int)publicKey.MSBSubstring(0, 32).ToPositiveBigInteger();

            if (Nspk + 1 != lengthInPublic)
            {
                return(new HssVerificationResult("Validation failed. L values do not match."));
            }

            // b. for (i = 0; i<Nspk; i = i + 1) {
            //        siglist[i] = next LMS signature parsed from S
            //        publist[i] = next LMS public key parsed from S
            //    }
            var siglist   = new BitString[Nspk + 1];
            var publist   = new BitString[Nspk + 1];
            var currIndex = 32;

            for (int i = 0; i < Nspk; i++)
            {
                // assume sig and pub have same LMS mode
                var otsCode = signature.MSBSubstring(currIndex + 32, 32);
                var n       = LmotsModeMapping.GetNFromCode(otsCode);
                var p       = LmotsModeMapping.GetPFromCode(otsCode);
                var sigtype = signature.MSBSubstring((8 + n * (p + 1)) * 8 + currIndex, 32);
                var m       = LmsModeMapping.GetMFromCode(sigtype);
                var h       = LmsModeMapping.GetHFromCode(sigtype);
                var siglen  = (12 + n * (p + 1) + m * h) * 8;
                var publen  = 192 + (m * 8);
                siglist[i] = signature.MSBSubstring(currIndex, siglen);
                currIndex += siglen;
                publist[i] = signature.MSBSubstring(currIndex, publen);
                currIndex += publen;
            }

            // c. siglist[Nspk] = next LMS signature parsed from S
            var otsCodeLast = signature.MSBSubstring(currIndex + 32, 32);
            var nLast       = LmotsModeMapping.GetNFromCode(otsCodeLast);
            var pLast       = LmotsModeMapping.GetPFromCode(otsCodeLast);
            var sigtypeLast = signature.MSBSubstring((8 + nLast * (pLast + 1)) * 8 + currIndex, 32);
            var mLast       = LmsModeMapping.GetMFromCode(sigtypeLast);
            var hLast       = LmsModeMapping.GetHFromCode(sigtypeLast);
            var siglenLast  = (12 + nLast * (pLast + 1) + mLast * hLast) * 8;

            siglist[Nspk] = signature.MSBSubstring(currIndex, siglenLast);

            // 2. Verify each part of the signature
            var key = publicKey.MSBSubstring(32, publicKey.BitLength - 32);

            for (int i = 0; i < Nspk; i++)
            {
                var result = _lms[i].VerifyLmsSignature(publist[i], key, siglist[i]);
                if (!result.Success)
                {
                    return(new HssVerificationResult("LMS Validation failed: " + result.ErrorMessage));
                }
                key = publist[i];
            }

            // 3. return lms_verify(message, key, siglist[Nspk])
            var finalResult = _lms[Nspk].VerifyLmsSignature(msg, key, siglist[Nspk]);

            if (finalResult.Success)
            {
                return(new HssVerificationResult());
            }
            else
            {
                return(new HssVerificationResult("Validation failed. Final check failed: " + finalResult.ErrorMessage));
            }
        }
Esempio n. 22
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"));
            }
        }
Esempio n. 23
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));
        }
Esempio n. 24
0
        public LmsVerificationResult VerifyLmsSignature(BitString msg, BitString publicKey, BitString signature)
        {
            // 1. If the public key is not at least eight bytes long, return INVALID.
            if (publicKey.BitLength < 64)
            {
                return(new LmsVerificationResult("Validation failed. Public key wrong length."));
            }

            // 2. Parse pubtype, I, and T[1] from the public key as follows:
            // a. pubtype = strTou32(first 4 bytes of public key)
            var pubType = publicKey.MSBSubstring(0, 32);

            // b. ots_typecode = strTou32(next 4 bytes of public key)
            var ots_typecode = publicKey.MSBSubstring(32, 32);

            // c. Set m according to pubtype, based on Table 2.
            var m = LmsModeMapping.GetMFromCode(pubType);

            // d. If the public key is not exactly 24 + m bytes long, return INVALID.
            if (publicKey.BitLength != (24 + m) * 8)
            {
                return(new LmsVerificationResult("Validation failed. Public key wrong length."));
            }

            // e. I = next 16 bytes of the public key
            var I = publicKey.MSBSubstring(64, 128);

            // f. T[1] = next m bytes of the public key
            var root = publicKey.MSBSubstring(192, m * 8);

            // 3. Compute the LMS Public Key Candidate Tc from the signature, message, identifier,
            //    pubtype, and ots_typecode, using Algorithm 6a.

            // Algorithm 6a:

            // 1. If the signature is not at least eight bytes long, return INVALID.
            if (signature.BitLength < 64)
            {
                return(new LmsVerificationResult("Validation failed. Signature wrong length."));
            }

            // 2.  Parse sigtype, q, lmots_signature, and path from the signature as follows:
            // a. q = strTou32(first 4 bytes of signature)
            var q = signature.MSBSubstring(0, 32);

            // b. otssigtype = strTou32(next 4 bytes of signature)
            var otssigtype = signature.MSBSubstring(32, 32);

            // c. If otssigtype is not the OTS typecode from the public key, return INVALID.
            if (!otssigtype.Equals(ots_typecode))
            {
                return(new LmsVerificationResult("Validation failed. OTS Code incongruent."));
            }

            // d. Set n, p according to otssigtype and Table 1; if the signature is not
            //    at least 12 + n* (p + 1) bytes long, return INVALID.
            var n = LmotsModeMapping.GetNFromCode(otssigtype);
            var p = LmotsModeMapping.GetPFromCode(otssigtype);

            if (signature.BitLength < (12 + n * (p - 1)) * 8)
            {
                return(new LmsVerificationResult("Validation failed. Signature wrong length."));
            }

            // e. lmots_signature = bytes 4 through 7 + n* (p + 1) of signature
            var lmots_signature = signature.MSBSubstring(32, (4 + n * (p + 1)) * 8);

            // f. sigtype = strTou32(bytes 8 + n* (p + 1)) through 11 + n* (p + 1) of signature)
            var sigtype = signature.MSBSubstring((8 + n * (p + 1)) * 8, 32);

            // g. If sigtype is not the LM typecode from the public key, return INVALID.
            if (!sigtype.Equals(pubType))
            {
                return(new LmsVerificationResult("Verification failed. Type mismatch."));
            }

            // h. Set m, h according to sigtype and Table 2.
            // m already set from above
            var h = LmsModeMapping.GetHFromCode(sigtype);

            // i. If q >= 2^h or the signature is not exactly 12 + n* (p + 1) + m* h bytes long, return INVALID.
            if (q.ToPositiveBigInteger() >= (1 << h) || signature.BitLength != (12 + n * (p + 1) + m * h) * 8)
            {
                return(new LmsVerificationResult("Verification failed. Signature wrong length."));
            }

            // j. Set path as follows:
            //    path[0] = next m bytes of signature
            //    path[1] = next m bytes of signature
            //    ...
            //    path[h-1] = next m bytes of signature
            var path = new BitString[h];

            for (int i = 0; i < h; i++)
            {
                path[i] = signature.MSBSubstring(((12 + n * (p + 1)) * 8) + (i * m * 8), m * 8);
            }

            // 3.  Kc = candidate public key computed by applying Algorithm 4b to the signature lmots_signature,
            //     the message, and the identifiers I, q
            var Kc = _lmots.Algorithm4b(lmots_signature, msg, otssigtype, I, q);

            if (Kc == null)
            {
                return(new LmsVerificationResult("Verification failed. Algorithm 4b failed."));
            }

            // 4. Compute the candidate LMS root value Tc as described in rfc 8554
            var node_num = (1 << h) + q.ToPositiveBigInteger();

            var tmp = _sha256.HashMessage(I
                                          .ConcatenateBits(new BitString(node_num, 32))
                                          .ConcatenateBits(D_LEAF)
                                          .ConcatenateBits(Kc)).Digest;

            for (int i = 0; node_num > 1; node_num /= 2)
            {
                if (node_num % 2 == 1)
                {
                    tmp = _sha256.HashMessage(I
                                              .ConcatenateBits(new BitString(node_num / 2, 32))
                                              .ConcatenateBits(D_INTR)
                                              .ConcatenateBits(path[i])
                                              .ConcatenateBits(tmp)).Digest;
                }
                else
                {
                    tmp = _sha256.HashMessage(I
                                              .ConcatenateBits(new BitString(node_num / 2, 32))
                                              .ConcatenateBits(D_INTR)
                                              .ConcatenateBits(tmp)
                                              .ConcatenateBits(path[i])).Digest;
                }
                i++;
            }

            // 5. Return Tc
            var Tc = tmp;

            // END Algorithm 6a

            // 4. If Tc is equal to T[1], return VALID; otherwise, return INVALID.
            if (Tc.Equals(root))
            {
                return(new LmsVerificationResult());
            }
            else
            {
                return(new LmsVerificationResult("Verification failed. Signature invalid."));
            }
        }
Esempio n. 25
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));
        }
Esempio n. 26
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"));
            }
        }
Esempio n. 27
0
        public SharedSecretResponse Decrypt(KeyPair rsaKeyPair, BitString ciphertext, BitString additionalInput)
        {
            if (additionalInput == null)
            {
                additionalInput = new BitString(0);
            }

            // 1. Initializations:
            // a. nLen = the byte length of n. For this Recommendation, nLen ≥ 256.
            var nLenBits = rsaKeyPair.PubKey.N.ExactBitLength().ValueToMod(BitString.BITSINBYTE);
            var nLen     = nLenBits.CeilingDivide(BitString.BITSINBYTE);

            var hLenBits = _sha.HashFunction.OutputLen;
            var HLen     = hLenBits.CeilingDivide(BitString.BITSINBYTE);

            // b. DecryptErrorFlag = False.

            // 2. Check for erroneous input:
            // a. If the length of the ciphertext C is not nLen bytes, output an indication of erroneous
            // input, and exit without further processing.
            if (ciphertext.BitLength != nLenBits)
            {
                throw new DecryptionFailedException("Ciphertext bit length did not match nLen.");
            }

            // b. Convert the ciphertext byte string C to a ciphertext integer c
            // (see Appendix B.2):
            // c = BS2I(C).
            var c = ciphertext.ToPositiveBigInteger();

            // c. If the ciphertext integer c is not such that 1 < c < (n – 1), output an indication of
            // erroneous input, and exit without further processing.
            if (c <= 1 || c >= rsaKeyPair.PubKey.N - 1)
            {
                throw new DecryptionFailedException("Ciphertext integer c is not such that 1 < c < (n - 1).");
            }

            // 3. RSA decryption:
            // a. Apply RSADP (see Section 7.1.2) to the ciphertext integer c using the private key
            // (n, d) to produce an integer em:
            // em = RSADP((n, d), c).24
            var em = _rsa.Decrypt(c, rsaKeyPair.PrivKey, rsaKeyPair.PubKey).PlainText;

            // b. Convert the integer em to an encoded message EM, a byte string of nLen bytes (see
            // Appendix B.1):
            // EM = I2BS(em, nLen).
            var EM = new BitString(em).PadToModulusMsb(nLenBits);

            // 4. OAEP decoding:
            // a. Apply the selected hash function (see Section 5.1) to compute:
            // HA = H(A).
            // HA is a byte string of HLen bytes.
            var HA = _sha.HashMessage(additionalInput).Digest;

            // b. Separate the encoded message EM into a single byte Y, a byte string
            // maskedMGFSeed′ of HLen bytes, and a byte string maskedDB′ of nLen – HLen – 1
            // bytes as follows:
            // EM = Y || maskedMGFSeed′ || maskedDB′.
            var Y             = EM.MSBSubstring(0, BitString.BITSINBYTE);
            var maskedMGFSeed = EM.MSBSubstring(BitString.BITSINBYTE, hLenBits);
            var maskedDB      = EM.MSBSubstring(BitString.BITSINBYTE + hLenBits, (nLen - HLen - 1) * BitString.BITSINBYTE);

            // c. Apply the mask-generation function specified in Section 7.2.2.2 to compute:
            // mgfSeedMask′ = MGF(maskedDB′, HLen).
            var mgfSeedMask = _mgf.Generate(maskedDB, hLenBits);

            // d. Let mgfSeed′ = maskedMGFSeed′ ⊕ mgfSeedMask′.
            var mgfSeed = maskedMGFSeed.XOR(mgfSeedMask);

            // e. Apply the mask-generation function specified in Section 7.2.2.2 to compute:
            // dbMask′= MGF(mgfSeed′, nLen – HLen – 1).
            var dbMask = _mgf.Generate(mgfSeed, (nLen - HLen - 1) * BitString.BITSINBYTE);

            // f. Let DB′ = maskedDB′ ⊕ dbMask′.
            var DB = maskedDB.XOR(dbMask);

            // g. Separate DB′ into a byte string HA′ of HLen bytes and a byte string X of nLen –
            // 2HLen – 1 bytes as follows:
            // DB′ = HA′ || X.
            var HA2 = DB.MSBSubstring(0, hLenBits);
            var X   = DB.MSBSubstring(hLenBits, (nLen - 2 * HLen - 1) * BitString.BITSINBYTE);

            // 5. Check for RSA-OAEP decryption errors:
            // a. DecryptErrorFlag = False.
            // b. If Y is not the 00 byte (i.e., the bit string 00000000), then DecryptErrorFlag = True.
            if (Y.ToPositiveBigInteger() != BigInteger.Zero)
            {
                throw new DecryptionFailedException("Y did not equal zero.");
            }

            // c. If HA′ does not equal HA, then DecryptErrorFlag = True.
            if (!HA.Equals(HA2))
            {
                throw new DecryptionFailedException("HA` did not equal HA.");
            }

            // d. If X does not have the form PS || 00000001 || K, where PS consists of zero or more
            // consecutive 00 bytes, then DecryptErrorFlag = True.
            var kStartByte = 0;

            for (var i = 0; i < X.BitLength.CeilingDivide(8); i++)
            {
                if (X[i] == 0x00)
                {
                    continue;
                }
                if (X[i] == 0x01)
                {
                    kStartByte = i + 1;
                    break;
                }

                throw new DecryptionFailedException("X did not have the form PS || 00000001 || K, where PS consists of zero or more consecutive 00 bytes");
            }

            var K = X.MSBSubstring(kStartByte * BitString.BITSINBYTE, X.BitLength - kStartByte * BitString.BITSINBYTE);

            return(new SharedSecretResponse(K));
        }
Esempio n. 28
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));
        }
Esempio n. 29
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));
        }
Esempio n. 30
0
        public MCTResult <AlgoArrayResponse> Encrypt(IModeBlockCipherParameters param)
        {
            var ivs       = TdesPartitionHelpers.SetupIvs(param.Iv);
            var responses = new List <AlgoArrayResponse> {
                new AlgoArrayResponse {
                    IV        = ivs[0],
                    Keys      = param.Key,
                    PlainText = param.Payload
                }
            };
            var numberOfOutputsToSave     = 192 / Shift;
            var indexAtWhichToStartSaving = NUMBER_OF_ITERATIONS - numberOfOutputsToSave;

            for (var i = 0; i < NumberOfCases; i++)
            {
                ivs = TdesPartitionHelpers.SetupIvs(responses[i].IV.GetDeepCopy());
                var       tempText         = responses[i].PlainText.GetDeepCopy();
                BitString prevTempIv       = null;
                var       tempIv           = responses[i].IV.GetDeepCopy();
                var       keysForThisRound = responses[i].Keys;
                BitString output           = null;
                var       holdouts         = new BitString[3];
                var       lastCipherTexts  = new List <BitString>();
                for (var j = 0; j < NUMBER_OF_ITERATIONS; j++)
                {
                    switch (j)
                    {
                    case 0:
                        tempIv = ivs[0].GetDeepCopy();
                        break;

                    case 1:
                        tempIv = ivs[1].GetDeepCopy();
                        break;

                    case 2:
                        tempIv = ivs[2].GetDeepCopy();
                        break;

                    default:
                        tempIv = prevTempIv.MSBSubstring(Shift, 64 - Shift).ConcatenateBits(holdouts[2]);
                        break;
                    }
                    prevTempIv = tempIv.GetDeepCopy();

                    output = _algo.ProcessPayload(new ModeBlockCipherParameters(
                                                      BlockCipherDirections.Encrypt, tempIv, keysForThisRound, tempText)
                                                  ).Result;

                    holdouts[2] = holdouts[1];
                    holdouts[1] = holdouts[0];
                    holdouts[0] = output;

                    tempText = prevTempIv.MSBSubstring(0, Shift);

                    if (j >= indexAtWhichToStartSaving)
                    {
                        lastCipherTexts.Insert(0, output.GetDeepCopy());
                    }
                }
                responses[i].CipherText = output;

                var newIv  = prevTempIv.MSBSubstring(Shift, 64 - Shift).ConcatenateBits(output);
                var newIvs = TdesPartitionHelpers.SetupIvs(newIv);

                responses.Add(new AlgoArrayResponse()
                {
                    Keys = _keyMaker.MixKeys(new TDESKeys(responses[i].Keys.GetDeepCopy()), lastCipherTexts.ToList())
                           .ToOddParityBitString(),
                    PlainText = prevTempIv.GetDeepCopy().MSBSubstring(0, Shift),
                    IV        = newIvs[0]
                });
            }
            responses.RemoveAt(responses.Count - 1);
            return(new MCTResult <AlgoArrayResponse>(responses));
        }