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));
            }
        }
Пример #2
0
        public OtherInfo(
            IEntropyProvider entropyProvider,
            string otherInfoPattern,
            int otherInfoLength,
            KeyAgreementRole thisPartyKeyAgreementRole,
            PartyOtherInfo thisPartyOtherInfo,
            PartyOtherInfo otherPartyOtherInfo
            )
        {
            _thisPartyKeyAgreementRole = thisPartyKeyAgreementRole;
            _thisPartyOtherInfo        = thisPartyOtherInfo;
            _otherPartyOtherInfo       = otherPartyOtherInfo;

            // split the pattern into pieces
            var pieces = otherInfoPattern.Split("||".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

            foreach (var piece in pieces)
            {
                var workingPiece = piece.Replace("||", "");
                _otherInfo = _otherInfo.ConcatenateBits(ConcatenatePieceOntoOtherInfo(workingPiece));
            }

            // Add entropy to hit otherInfoLength
            _otherInfo = _otherInfo.ConcatenateBits(entropyProvider.GetEntropy(otherInfoLength - _otherInfo.BitLength));

            _otherInfo = _otherInfo.GetMostSignificantBits(otherInfoLength);
        }
Пример #3
0
        public override SymmetricCipherResult ProcessPayload(IModeBlockCipherParameters param)
        {
            CheckPayloadRequirements(param.Payload);
            var key = param.Key.ToBytes();

            var engineParam = new EngineInitParameters(param.Direction, key, param.UseInverseCipherMode);

            _engine.Init(engineParam);

            var numberOfBlocks = GetNumberOfBlocks(param.Payload.BitLength);
            var outBuffer      = GetOutputBuffer(param.Payload.BitLength);

            if (param.Direction == BlockCipherDirections.Encrypt)
            {
                Encrypt(param, numberOfBlocks, outBuffer);
            }
            else
            {
                Decrypt(param, numberOfBlocks, outBuffer);
            }

            var output = new BitString(outBuffer);

            return(new SymmetricCipherResult(output.GetMostSignificantBits(param.Payload.BitLength)));
        }
Пример #4
0
        public KdfResult DeriveKey(IAns942Parameters param)
        {
            if (!(param is ConcatAns942Parameters concatParams))
            {
                return(new KdfResult("Unable to parse concat parameters"));
            }

            if (concatParams.KeyLen <= 0 || concatParams.KeyLen > 65536)
            {
                return(new KdfResult($"KeyLen must be between [1, 65536]. Value given was: {concatParams.KeyLen}"));
            }

            var d       = (int)System.Math.Ceiling(concatParams.KeyLen / (decimal)_sha.HashFunction.OutputLen);
            var counter = BitString.To32BitString(1);
            var h       = new BitString(0);

            for (var i = 1; i <= d; i++)
            {
                // H[i] = Hash(ZZ || counter || otherInfo)
                var hashInput = concatParams.Zz.ConcatenateBits(counter).ConcatenateBits(concatParams.OtherInfo);
                h = h.ConcatenateBits(_sha.HashMessage(hashInput).Digest);

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

            return(new KdfResult(h.GetMostSignificantBits(concatParams.KeyLen)));
        }
Пример #5
0
        private (BitString output, string error) Prf(BitString secret, string label, BitString seed, int outputLength)
        {
            int lengthToGenerate = outputLength.CeilingDivide(_shaHmac.OutputLength * _md5Hmac.OutputLength) * (_shaHmac.OutputLength * _md5Hmac.OutputLength);

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

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

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

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

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

            var xorResult = md5Out.XOR(shaOut);

            return(xorResult.GetMostSignificantBits(outputLength), "");
        }
        public byte[] HandleFinalFullPayloadBlockDecryption(BitString payload, IBlockCipherEngine engine, int numberOfBlocks, int originalPayloadBitLength)
        {
            // When payload is not a multiple of the block size
            if (numberOfBlocks > 1 && payload.BitLength % engine.BlockSizeBits != 0)
            {
                var numberOfBitsToAdd = engine.BlockSizeBits - payload.BitLength % engine.BlockSizeBits;

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

                engine.ProcessSingleBlock(lastBlock, decryptedLastBlockBuffer, 0);

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

                return(paddedPayload.ToBytes());
            }

            return(payload.ToBytes());
        }
Пример #7
0
        private HashResult Md5Process(BitString message)
        {
            var lastIndex = _fullMessage.Length - 1;
            var spaceRemainingInLastBlock = SizeOfChunk - _fullMessage[lastIndex].BitLength;

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

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

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

                // Figure out how many bits are left in the message and try to process them
                var trimmedMessage = message.GetLeastSignificantBits(message.BitLength - spaceRemainingInLastBlock);
                return(Md5Process(trimmedMessage));
            }
        }
Пример #8
0
        public KdfResult DeriveKey(IAns942Parameters param)
        {
            if (!(param is DerAns942Parameters derParams))
            {
                return(new KdfResult("Unable to parse der parameters"));
            }

            if (derParams.KeyLen <= 0 || derParams.KeyLen > 65536)
            {
                return(new KdfResult($"KeyLen must be between [1, 65536]. Value given was: {derParams.KeyLen}"));
            }

            var d       = (int)System.Math.Ceiling(derParams.KeyLen / (decimal)_sha.HashFunction.OutputLen);
            var h       = new BitString(0);
            var counter = BitString.To32BitString(0);

            for (var i = 1; i <= d; i++)
            {
                // Increment Counter
                counter = counter.BitStringAddition(BitString.One());

                // Prepare ANS.1/DER encoded OtherInfo
                var derEncodedOtherInfo = DerEncode(derParams, counter);
                var str = derEncodedOtherInfo.ToHex();
                // H[i] = Hash(ZZ || otherInfo)
                h = h.ConcatenateBits(_sha.HashMessage(derParams.Zz.ConcatenateBits(derEncodedOtherInfo)).Digest);
            }

            return(new KdfResult(h.GetMostSignificantBits(derParams.KeyLen)));
        }
Пример #9
0
        protected override BitString Wrap(BitString K, BitString S, bool wrapWithInverseCipher)
        {
            // 0. Pre-conditions
            var n = S.BitLength / 32;

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

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

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

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

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

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

            // 3. Output the results:
            // a) Let C1 = A^s
            // b) For i=2,...,n: Ci = Ri^s
            // c) Return C1 || C2 || ... || Cn
            return(A.ConcatenateBits(R2n));
        }
        // Question: Is it a hard restriction that the hash within HMAC is the same used within the signature process?
        public BigInteger GetNonce(BigInteger privateD, BigInteger hashedMessage, BigInteger orderN)
        {
            // 1.3
            var seedMaterial = new BitString(privateD).PadToModulusMsb(32).ConcatenateBits(new BitString(hashedMessage).PadToModulusMsb(32));

            // 1.4
            var key = BitString.Zeroes(_hmac.OutputLength);

            // 1.5
            var v = _01bits.GetMostSignificantBits(_hmac.OutputLength);

            // 1.6
            key = _hmac.Generate(key, v.ConcatenateBits(BitString.ConcatenateBits(BitString.Zeroes(8), seedMaterial))).Mac;

            // 1.7
            v = _hmac.Generate(key, v).Mac;

            // 1.8
            key = _hmac.Generate(key, v.ConcatenateBits(BitString.ConcatenateBits(new BitString("01"), seedMaterial))).Mac;

            // 1.9
            v = _hmac.Generate(key, v).Mac;

            // 2
            var nlen = orderN.ExactBitLength();

            // 3
            BigInteger k = 0;

            while (k == 0 || k >= orderN)
            {
                // 4.1
                var tmp = new BitString(0);

                // 4.2
                while (tmp.BitLength < nlen)
                {
                    v   = _hmac.Generate(key, v).Mac;
                    tmp = tmp.ConcatenateBits(v);
                }

                // 4.3
                k = tmp.GetMostSignificantBits(nlen).ToPositiveBigInteger();

                // 4.4
                if (k > 0 && k < orderN)
                {
                    return(k);
                }

                // 4.5
                key = _hmac.Generate(key, v.ConcatenateBits(BitString.Zeroes(8))).Mac;

                // 4.6
                v = _hmac.Generate(key, v).Mac;
            }

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

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

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


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

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

            // 3. Output the results:
            // 3.a) Let S1 = A0
            // 3.b) For i=2,...,n: Si = Ri0
            // 3.c) Return S1 || S2 || ... || Sn
            return(A.ConcatenateBits(R2n));
        }
Пример #12
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));
        }
Пример #13
0
 private static void AllTransform(List <AlgoArrayResponse> results)
 {
     // CFB1 - PT is always "0" (hex), CT is the most significant bit of the normal KAT.
     results.ForEach(fe =>
     {
         fe.PlainText  = new BitString("00", 1);
         fe.CipherText = BitString.GetMostSignificantBits(1, fe.CipherText);
     });
 }
Пример #14
0
        public void ShouldEncryptDecryptToSameValue(string label, BitString iv, BitString pt, BitString key, BitString ct)
        {
            var encryptResult = _subjectCs3
                                .ProcessPayload(new ModeBlockCipherParameters(BlockCipherDirections.Encrypt, iv.GetDeepCopy(), key, pt)).Result;

            var decryptResult = _subjectCs3
                                .ProcessPayload(new ModeBlockCipherParameters(BlockCipherDirections.Decrypt, iv.GetDeepCopy(), key, encryptResult)).Result;

            Assert.AreEqual(pt.GetMostSignificantBits(pt.BitLength).ToHex(), decryptResult.GetMostSignificantBits(pt.BitLength).ToHex());
        }
Пример #15
0
        protected override BitString Wrap(BitString K, BitString S, bool wrapWithInverseCipher)
        {
            // 0. Pre-conditions
            var n = S.BitLength / 64;

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

            var keyLen = K.BitLength;

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

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

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

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

            // 3. Output the results:
            // a) Let C1 = A^s
            // b) For i=2,...,n: Ci = Ri^s
            // c) Return C1 || C2 || ... || Cn
            return(A.ConcatenateBits(R2n));
        }
Пример #16
0
        private MCTResult <AlgoArrayResponse> Encrypt(IModeBlockCipherParameters param)
        {
            List <AlgoArrayResponse> responses = new List <AlgoArrayResponse>();

            int i = 0;
            int j = 0;

            try
            {
                for (i = 0; i < 100; i++)
                {
                    AlgoArrayResponse iIterationResponse = new AlgoArrayResponse()
                    {
                        IV        = param.Iv,
                        Key       = param.Key,
                        PlainText = param.Payload
                    };

                    BitString jCipherText            = null;
                    BitString previousCipherText     = null;
                    BitString copyPreviousCipherText = null;
                    var       ivCopiedBytes          = iIterationResponse.IV.ToBytes();
                    param.Iv = new BitString(ivCopiedBytes);
                    for (j = 0; j < 1000; j++)
                    {
                        var jResult = _algo.ProcessPayload(param);
                        jCipherText = jResult.Result;

                        if (j == 0)
                        {
                            previousCipherText = iIterationResponse.IV.ConcatenateBits(jCipherText.GetMostSignificantBits(param.Payload.BitLength - param.Iv.BitLength));
                        }

                        param.Payload          = previousCipherText;
                        copyPreviousCipherText = previousCipherText;
                        previousCipherText     = jCipherText;
                    }

                    iIterationResponse.CipherText = jCipherText;
                    responses.Add(iIterationResponse);

                    param.Key = _keyMaker.MixKeys(param.Key, previousCipherText, copyPreviousCipherText);
                    param.Iv  = previousCipherText.GetMostSignificantBits(param.Iv.BitLength);
                }
            }
            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));
        }
Пример #17
0
        protected override BitString WrapInverse(BitString K, BitString C, bool wrappedWithInverseCipher)
        {
            // 0. Pre-conditions
            var n = C.BitLength / 64;

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

            var aesKeyLength = K.BitLength;

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

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

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

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

            // 3. Output the results:
            // 3.a) Let S1 = A0
            // 3.b) For i=2,...,n: Si = Ri0
            // 3.c) Return S1 || S2 || ... || Sn
            return(A.ConcatenateBits(R2n));
        }
Пример #18
0
        private void Update(BitString seedMaterial)
        {
            BitString v   = V.GetDeepCopy();
            BitString key = Key.GetDeepCopy();

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

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

                BitString outputBlock = BlockEncrypt(key, v);

                temp = temp.ConcatenateBits(outputBlock);
            }

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

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

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

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

            // 7. Return new values of Key and V
            Key = key.GetDeepCopy();
            V   = v.GetDeepCopy();
        }
Пример #19
0
        public KdfResult Kdf(KdfParameterIkeV1 param, BitString fixedInfo = null)
        {
            var hashFunction = ShaAttributes.GetHashFunctionFromEnum(param.HashFunction);

            var kdf = _ikeV1Factory.GetIkeV1Instance(AuthenticationMethods.Dsa, hashFunction);

            var result = kdf.GenerateIke(param.InitiatorEphemeralData, param.ResponderEphemeralData, param.Z,
                                         param.AdditionalInitiatorNonce, param.AdditionalResponderNonce, null);

            var dkm = new BitString(0)
                      .ConcatenateBits(result.SKeyIdD)
                      .ConcatenateBits(result.SKeyIdA)
                      .ConcatenateBits(result.SKeyIdE);

            return(new KdfResult(dkm.GetMostSignificantBits(param.L)));
        }
Пример #20
0
        public KdfResult DeriveKey(BitString z, BitString sharedInfo, int keyLength)
        {
            var numBlocks = keyLength.CeilingDivide(_hash.HashFunction.OutputLen);

            var keyData = new BitString(0);

            for (var i = 1; i <= numBlocks; i++)
            {
                var counter   = BitString.To32BitString(i);
                var hashInput = z.ConcatenateBits(counter).ConcatenateBits(sharedInfo);

                keyData = keyData.ConcatenateBits(_hash.HashMessage(hashInput).Digest);
            }

            return(new KdfResult(keyData.GetMostSignificantBits(keyLength)));
        }
Пример #21
0
        private BitString GenerateKeyingMaterial(BitString key, BitString fixedData, int dkmLength)
        {
            var iterations = dkmLength.CeilingDivide(_hmac.OutputLength);

            var keyingMaterial = new BitString(0);
            var temp           = new BitString(0);

            for (var i = 0; i < iterations; i++)
            {
                var valueI = temp.ConcatenateBits(fixedData).ConcatenateBits(BitString.To32BitString(i + 1).GetLeastSignificantBits(8));
                temp           = _hmac.Generate(key, valueI).Mac;
                keyingMaterial = keyingMaterial.ConcatenateBits(temp);
            }

            return(keyingMaterial.GetMostSignificantBits(dkmLength));
        }
Пример #22
0
        public override SymmetricCipherResult Decrypt(BitString key, BitString cipherText, bool wrappedWithInverseCipher)
        {
            // 1. Let ICV1 = 0xA6A6A6A6A6A6A6A6
            // 2. Let S = W^-1(C)
            BitString s = WrapInverse(key, cipherText, wrappedWithInverseCipher);

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

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

            return(new SymmetricCipherResult(p));
        }
Пример #23
0
        private BitString Prf(BitString secret, string label, BitString seed, int outputLength)
        {
            var labelBytes = new BitString(Encoding.ASCII.GetBytes(label));
            var prfSeed    = labelBytes.ConcatenateBits(seed);
            var numBlocks  = outputLength.CeilingDivide(_hmac.OutputLength);

            var A      = prfSeed.GetDeepCopy();
            var output = new BitString(0);

            for (var i = 0; i < numBlocks; i++)
            {
                A      = _hmac.Generate(secret, A).Mac;
                output = output.ConcatenateBits(_hmac.Generate(secret, A.ConcatenateBits(prfSeed)).Mac);
            }

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

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

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

            var bitsToAppend = new BitString(lsp1, s);

            //ThisLogger.Debug($"BitsToAppendLength: {bitsToAppend.Length}");
            return(X.GetMostSignificantBits(X.BitLength - s).ConcatenateBits(bitsToAppend));
        }
Пример #25
0
        public BitString Expand(BitString pseudoRandomKey, BitString otherInfo, int keyLengthBytes)
        {
            // keyLength comes in as bytes
            var keyLengthBits = keyLengthBytes * 8;
            var n             = keyLengthBits.CeilingDivide(_hmac.OutputLength);
            var t             = new BitString(0);
            var counter       = new BitString("00");
            var result        = new BitString(0);

            for (short i = 1; i <= n; i++)
            {
                counter = counter.BitStringAddition(BitString.One());
                t       = _hmac.Generate(pseudoRandomKey, t.ConcatenateBits(otherInfo).ConcatenateBits(counter)).Mac;
                result  = result.ConcatenateBits(t);
            }

            return(result.GetMostSignificantBits(keyLengthBits));
        }
Пример #26
0
        private BitString Kdf(int length, BitString key, BitString salt, BitString kdr, BitString index, BitString label)
        {
            var keyId = label.ConcatenateBits(Divide(index, kdr));
            var m     = length.CeilingDivide(128); // guaranteed to be either 1 or 2

            // Left pad keyId with 0s so it is the same length as salt
            keyId = BitString.Zeroes(salt.BitLength - keyId.BitLength).ConcatenateBits(keyId);
            var x = keyId.XOR(salt);

            var derivedKey = new BitString(0);

            for (short i = 0; i < m; i++)
            {
                var inBlock = x.ConcatenateBits(BitString.To16BitString(i));
                var param   = new ModeBlockCipherParameters(BlockCipherDirections.Encrypt, key, inBlock);
                derivedKey = derivedKey.ConcatenateBits(_aesEcb.ProcessPayload(param).Result);
            }

            return(derivedKey.GetMostSignificantBits(length));
        }
Пример #27
0
        public void Update(byte[] input, int bitLength)
        {
            if (bitLength % 8 == 0 && _cachedBits.BitLength == 0)
            {
                BlockUpdate(input, 0, bitLength / 8);
                return;
            }

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

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

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

            _cachedBits = numberOfCompletedBytes * 8 == _cachedBits.BitLength ? new BitString(0) : _cachedBits.GetLeastSignificantBits(_cachedBits.BitLength - numberOfCompletedBytes * 8);
        }
Пример #28
0
        protected override DrbgResult GenerateAlgorithm(int requestedNumberOfBits, BitString additionalInput)
        {
            // 1
            if (ReseedCounter > Attributes.MaxNumberOfRequestsBetweenReseeds)
            {
                return(new DrbgResult(DrbgStatus.ReseedRequired));
            }

            // 2
            if (additionalInput.BitLength != 0)
            {
                Update(additionalInput);
            }

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

            // 4
            while (temp.BitLength < requestedNumberOfBits)
            {
                // 4.1
                V = _hmac.Generate(Key, V).Mac;

                // 4.2
                temp = temp.ConcatenateBits(V);
            }

            // 5
            var returnedBits = temp.GetMostSignificantBits(requestedNumberOfBits);

            // 6
            Update(additionalInput);

            // 7
            ReseedCounter++;

            // 8
            return(new DrbgResult(returnedBits));
        }
        public void TransformCiphertext(byte[] outBuffer, IBlockCipherEngine engine, int numberOfBlocks, int originalPayloadBitLength)
        {
            if (numberOfBlocks == 1 || originalPayloadBitLength % engine.BlockSizeBits == 0)
            {
                return;
            }

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

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

            Array.Copy(newPayloadBytes, 0, outBuffer, 0, newPayloadBytes.Length);
        }
Пример #30
0
        // [TestCase(5)]
        // [TestCase(6)]
        // [TestCase(7)]
        public void TestMultipleBitLengthsOfZz(int bitsToDrop)
        {
            var zz = new BitString("51020F0B4423F066FFA2B9CA5FA536603F307A52048D7FBE4FA2D0A8F5B6ACF116BE68A28F6D21C37A4A76F082A5CE0D240FB84D6E3291C9B49E6865E76AB166934C701DB25A7FF77DE8849657244CB818B813B72D404D86DC1B0CFF64AFABFEE0CE24DF6DD6C537B6E58DBBC96DD4B18DDD0583699234B82BDDF4778236DD0B944E042BE5DA951E4B7D4962086964D0929F3641AB403CE4FA0AB9F2E500A5004786153E3E7740C41EA0C396773EC2D5D0E98837372491B97C42A336AEA3CF1F13C090CB3F45BA1AC67D763D09B9279D4158A6B41FB8C0E8515473F882174184EDDD5FAECC043E779DA7F0080CE31DE03B255DE038ACEC636F6CDF7DCD47B2C6757310179952B29F48DF510C2C204520C2313034DDB7080DE4F9018EA37756FEA41C285213E0216B5A3BA730AAC15C60EB72E5143656E2ADD533F7CACE1CCAE0100BDD789130A3B755669BC064DD31ECB3CFAB6E5766FA7194C982B79776D1F5FC1C1DECBE102096E14C7B30C8876757EB9F419002C6FC2DE88B98B1C784F3C0976447DC352D8BF56FBE255394E2FD3D7B5A4C9B4770");

            zz = zz.GetMostSignificantBits(zz.BitLength - bitsToDrop);
            var otherInfo = new BitString("82852BF64C6CF56399CC0E5F7ADAE2DF286B51E0D1A274BE949AF3D72A29CBB21F8AC17574BB12550804F4A8AA498082");

            var hashFunction = new HashFunction(ModeValues.SHA1, DigestSizes.d160);
            var sha          = _factory.GetShaInstance(hashFunction);
            var subject      = new AnsiX942Concat(sha);

            var param = new ConcatAns942Parameters
            {
                Zz        = zz,
                KeyLen    = 384,
                OtherInfo = otherInfo
            };

            var result = subject.DeriveKey(param);

            Assert.True(result.Success);
            Assert.AreEqual(new BitString("DD8469A101758AA949516B0AE4B8F6B56438A0A119575D3265163C6BBBEA2CB58629F387A1AA163D5AE164C5206E1DB5").ToHex(), result.DerivedKey.ToHex());
        }