Exemple #1
0
        public override SymmetricCipherResult ProcessPayload(IModeBlockCipherParameters param)
        {
            CheckPayloadRequirements(param.Payload);
            var key = param.Key.ToBytes();
            var actualBitsToProcess = param.Payload.BitLength;

            param.Payload = BitString.PadToModulus(param.Payload, _engine.BlockSizeBits);

            // OFB always utilizes engine in encrypt mode
            var engineParam = new EngineInitParameters(BlockCipherDirections.Encrypt, key, param.UseInverseCipherMode);

            _engine.Init(engineParam);

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


            if (numberOfBlocks < PARTITIONS)
            {
                throw new ArgumentOutOfRangeException(nameof(param.Payload), $"Ofb-I mode requires a minimum of {PARTITIONS} blocks");
            }

            var ivs = SetupIvs(param.Iv);

            ProcessPayload(param, ivs, numberOfBlocks, outBuffer);

            return(new SymmetricCipherResult(
                       new BitString(outBuffer).GetMostSignificantBits(actualBitsToProcess)
                       ));
        }
        public void DecryptTestsCs2(string label, BitString key, BitString iv, BitString pt, BitString ct, BitString nextIv)
        {
            // transform the cs3 ct to cs3 again (to cancel the sample vector CS3)
            var ctBytes        = BitString.PadToModulus(ct, _engine.BlockSizeBits).ToBytes();
            var numberOfBlocks = GetNumberOfBlocks(pt.BitLength);
            var cs3Transformer = _csTransform.Get(CiphertextStealingMode.CS3);

            cs3Transformer.TransformCiphertext(ctBytes, _engine, numberOfBlocks, pt.BitLength);

            // apply a cs2 transform
            var cs2Transformer = _csTransform.Get(CiphertextStealingMode.CS2);

            cs2Transformer.TransformCiphertext(ctBytes, _engine, numberOfBlocks, pt.BitLength);
            ct = new BitString(ctBytes).GetMostSignificantBits(pt.BitLength);

            var param = new ModeBlockCipherParameters(
                BlockCipherDirections.Decrypt,
                iv,
                key,
                ct
                );
            var result = _subjectCs2.ProcessPayload(param);

            Assert.AreEqual(pt.ToHex(), result.Result.ToHex(), nameof(pt));
            Assert.AreEqual(nextIv.ToHex(), param.Iv.ToHex(), nameof(nextIv));
        }
Exemple #3
0
        public byte[] HandleFinalFullPayloadBlockDecryption(BitString payload, IBlockCipherEngine engine, int numberOfBlocks, int originalPayloadBitLength)
        {
            // Decrypt the last full payload block (when there is more than one block)
            if (numberOfBlocks > 1)
            {
                var originalPayloadPaddedToBlockSize = payload.PadToModulus(engine.BlockSizeBits).ToBytes();

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

                var decryptedSecondToLastBlockBuffer = new byte[engine.BlockSizeBytes];

                engine.ProcessSingleBlock(secondToLastBlock, decryptedSecondToLastBlockBuffer, 0);

                var decryptedBlock = new BitString(decryptedSecondToLastBlockBuffer);

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

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

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

            return(payload.ToBytes());
        }
        private void Encrypt(IModeBlockCipherParameters param, int numberOfBlocks, byte[] outBuffer)
        {
            var iv = param.Iv.GetDeepCopy().ToBytes();

            // Pad the last partial plaintext block with 0 until it reaches the block size.
            var paddedPayload = BitString.PadToModulus(param.Payload, _engine.BlockSizeBits).ToBytes();

            // Encrypt the whole padded plaintext using the standard CBC mode.
            // For each block
            for (int i = 0; i < numberOfBlocks; i++)
            {
                // XOR IV onto current block payload
                for (int j = 0; j < _engine.BlockSizeBytes; j++)
                {
                    paddedPayload[i * _engine.BlockSizeBytes + j] ^= iv[j];
                }

                _engine.ProcessSingleBlock(paddedPayload, outBuffer, i);

                // Update Iv with current block's outBuffer values
                Array.Copy(outBuffer, i * _engine.BlockSizeBytes, iv, 0, _engine.BlockSizeBytes);
            }

            // Update the Param.Iv for the next call
            for (int i = 0; i < _engine.BlockSizeBytes; i++)
            {
                param.Iv[i] = iv[i];
            }

            _ciphertextStealingTransform.TransformCiphertext(outBuffer, _engine, numberOfBlocks, param.Payload.BitLength);
        }
        public override SymmetricCounterResult ProcessPayload(IModeBlockCipherParameters param)
        {
            CheckPayloadRequirements(param.Payload);
            var ivs = new List <BitString>();
            var key = param.Key.ToBytes();
            var actualBitsToProcess = param.Payload.BitLength;

            param.Payload = BitString.PadToModulus(param.Payload, _engine.BlockSizeBits);

            // CTR always utilizes engine in encrypt mode
            var engineParam = new EngineInitParameters(BlockCipherDirections.Encrypt, key, param.UseInverseCipherMode);

            _engine.Init(engineParam);

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

            ProcessPayload(param, numberOfBlocks, outBuffer, ivs);

            return(new SymmetricCounterResult(new BitString(outBuffer).GetMostSignificantBits(actualBitsToProcess), ivs));
        }
        public SymmetricCounterResult ExtractIvs(ICounterModeBlockCipherParameters parameters)
        {
            BitString plainText, cipherText;

            if (parameters.Direction == BlockCipherDirections.Encrypt)
            {
                plainText  = parameters.Payload;
                cipherText = parameters.Result;
            }
            else
            {
                plainText  = parameters.Result;
                cipherText = parameters.Payload;
            }

            plainText  = BitString.PadToModulus(plainText, _engine.BlockSizeBits);
            cipherText = BitString.PadToModulus(cipherText, _engine.BlockSizeBits);

            var numberOfBlocks = GetNumberOfBlocks(plainText.BitLength);
            var ivs            = new List <BitString>();
            var engineParam    = new EngineInitParameters(BlockCipherDirections.Decrypt, parameters.Key.ToBytes(), parameters.UseInverseCipherMode);

            _engine.Init(engineParam);

            for (var i = 0; i < numberOfBlocks; i++)
            {
                var blockPt = plainText.MSBSubstring(i * _engine.BlockSizeBits, _engine.BlockSizeBits);
                var blockCt = cipherText.MSBSubstring(i * _engine.BlockSizeBits, _engine.BlockSizeBits);

                var xor       = BitString.XOR(blockPt, blockCt).ToBytes();
                var outBuffer = GetOutputBuffer(blockPt.BitLength);
                _engine.ProcessSingleBlock(xor, outBuffer, 0);

                ivs.Add(new BitString(outBuffer));
            }

            return(new SymmetricCounterResult(parameters.Result, ivs));
        }