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)); }
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)); }