不幸的是
SicBlockCipher
它本身不作为流密码实现,因此(实际上)不能直接使用此功能。
BufferedBlockCipher
创建时考虑了许多不同的操作模式。IT缓冲区
输入
,而对于计数器(ctr)模式,
锡克分组密码
实现时,您将需要缓冲加密的计数器块。
加密的计数器块组成密钥流,然后可以与明文进行异或以创建CipherStream(或确实,使用CipherText再次检索明文,加密是对计数器模式的解密)。
我看到的唯一方法是创建您自己的
IBlockCipher
并实现所述功能。
这里是作为流密码的计数器模式…
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Modes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SicStream
{
public class SicStreamCipher : IStreamCipher
{
private SicBlockCipher parent;
private int blockSize;
private byte[] zeroBlock;
private byte[] blockBuffer;
private int processed;
public SicStreamCipher(SicBlockCipher parent)
{
this.parent = parent;
this.blockSize = parent.GetBlockSize();
this.zeroBlock = new byte[blockSize];
this.blockBuffer = new byte[blockSize];
// indicates that no bytes are available: lazy generation of counter blocks (they may not be needed)
this.processed = blockSize;
}
public string AlgorithmName
{
get
{
return parent.AlgorithmName;
}
}
public void Init(bool forEncryption, ICipherParameters parameters)
{
parent.Init(forEncryption, parameters);
Array.Clear(blockBuffer, 0, blockBuffer.Length);
processed = blockSize;
}
public void ProcessBytes(byte[] input, int inOff, int length, byte[] output, int outOff)
{
int inputProcessed = 0;
while (inputProcessed < length)
{
// NOTE can be optimized further
// the number of available bytes can be pre-calculated; too much branching
if (processed == blockSize)
{
// lazilly create a new block of key stream
parent.ProcessBlock(zeroBlock, 0, blockBuffer, 0);
processed = 0;
}
output[outOff + inputProcessed] = (byte)(input[inOff + inputProcessed] ^ blockBuffer[processed]);
processed++;
inputProcessed++;
}
}
public void Reset()
{
parent.Reset();
Array.Clear(blockBuffer, 0, blockBuffer.Length);
this.processed = blockSize;
}
public byte ReturnByte(byte input)
{
if (processed == blockSize)
{
// lazily create a new block of key stream
parent.ProcessBlock(zeroBlock, 0, blockBuffer, 0);
processed = 0;
}
return (byte)(input ^ blockBuffer[processed++]);
}
}
}
…在这里,它被包装起来,这样它就可以在代码中使用分组密码的操作模式…
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Modes;
namespace SicStream
{
/**
* A class that implements an online Sic (segmented integer counter mode, or just counter (CTR) mode for short).
* This class buffers one encrypted counter (representing the key stream) at a time.
* The encryption of the counter is only performed when required, so that no key stream blocks are generated while they are not required.
*/
public class StreamingSicBlockCipher : BufferedCipherBase
{
private SicStreamCipher parent;
private int blockSize;
public StreamingSicBlockCipher(SicBlockCipher parent)
{
this.parent = new SicStreamCipher(parent);
this.blockSize = parent.GetBlockSize();
}
public override string AlgorithmName
{
get
{
return parent.AlgorithmName;
}
}
public override byte[] DoFinal()
{
// returns no bytes at all, as there is no input
return new byte[0];
}
public override byte[] DoFinal(byte[] input, int inOff, int length)
{
byte[] result = ProcessBytes(input, inOff, length);
Reset();
return result;
}
public override int GetBlockSize()
{
return blockSize;
}
public override int GetOutputSize(int inputLen)
{
return inputLen;
}
public override int GetUpdateOutputSize(int inputLen)
{
return inputLen;
}
public override void Init(bool forEncryption, ICipherParameters parameters)
{
parent.Init(forEncryption, parameters);
}
public override byte[] ProcessByte(byte input)
{
return new byte[] { parent.ReturnByte(input) };
}
public override byte[] ProcessBytes(byte[] input, int inOff, int length)
{
byte[] result = new byte[length];
parent.ProcessBytes(input, inOff, length, result, 0);
return result;
}
public override void Reset()
{
parent.Reset();
}
}
}
请注意,最后一个代码效率较低,因为需要创建其他数组。