C#Bouncy Castle:AES CTR为什么';它不是自动递增的

C#Bouncy Castle:AES CTR为什么';它不是自动递增的,c#,cryptography,aes,bouncycastle,C#,Cryptography,Aes,Bouncycastle,我正在尝试在c#中实现AES 128 CTR加密。我发现Bouncy Castle非常有用。这是我的密码: public class AESCrypto { private byte[] Key = new byte[16]; private byte[] IV = new byte[16]; private const int CHUNK_SIZE = 16; private IBufferedCipher cipher = CipherUtilities.GetCip

我正在尝试在c#中实现AES 128 CTR加密。我发现Bouncy Castle非常有用。这是我的密码:

public class AESCrypto
{
   private byte[] Key = new byte[16];
   private byte[] IV = new byte[16];
   private const int CHUNK_SIZE = 16;
   private IBufferedCipher cipher = CipherUtilities.GetCipher("AES/CTR/NoPadding");

   // Key and IV I get from client.
   public AESCrypto(byte[] key, byte[] iv, bool forEncryption) {
      Key = key;
      IV = iv;
      cipher.Init(forEncryption, new ParametersWithIV(new KeyParameter(Key), IV));
   }

   public byte[] PerformAES(byte[] incomingBytes)
   {
            int blockCount = incomingBytes.Length / CHUNK_SIZE; // Number of blocks
            int blockRemaining = incomingBytes.Length % CHUNK_SIZE; // Remaining bytes of the last block

            byte[] outcomingBytes = new byte[incomingBytes.Length];

            for (var i = 0; i < blockCount; i++)
            {
                // Why do I need to re-init it again?
                //cipher.Init(false, new ParametersWithIV(new KeyParameter(Key), IV));

                byte[] temp = new byte[CHUNK_SIZE];
                Array.Copy(incomingBytes, i * CHUNK_SIZE, temp, 0, CHUNK_SIZE);

                byte[] decryptedChunk = cipher.ProcessBytes(temp);
                Array.Copy(decryptedChunk, 0, outcomingBytes, i * CHUNK_SIZE, CHUNK_SIZE);
                //Increase(IV); Why do I need to increse iv by hand?
            }

            if (blockRemaining != 0)
            {
                // Why do I need to re-init it again?
                //cipher.Init(false, new ParametersWithIV(new KeyParameter(Key), IV));

                byte[] temp = new byte[blockRemaining];
                Array.Copy(incomingBytes, incomingBytes.Length - blockRemaining, temp, 0, blockRemaining);

                byte[] decryptedChunk = cipher.DoFinal(temp);
                Array.Copy(decryptedChunk, 0, outcomingBytes, incomingBytes.Length - blockRemaining, blockRemaining);
                //Increase(IV); Why do I need to increse iv by hand?
            }

            return outcomingBytes;
   }

   private void Increase(byte[] iv)
   {
            for (var i = 0; i < iv.Length; i++)
            {
                iv[i]++;
                if (iv[i] != 0)
                {
                    break;
                }
            }
    }
}
公共类AES加密
{
专用字节[]键=新字节[16];
专用字节[]IV=新字节[16];
私有常量int CHUNK_SIZE=16;
私有IBufferdCipher cipher=CipherUtilities.GetCipher(“AES/CTR/NoPadding”);
//我从客户那里拿到钥匙和IV。
公共AES加密(字节[]密钥,字节[]iv,布尔加密){
钥匙=钥匙;
IV=IV;
Init(forEncryption,新参数swithiv(newkeyparameter(Key),IV));
}
公共字节[]性能(字节[]输入字节)
{
int blockCount=incomingBytes.Length/CHUNK\u SIZE;//块数
int blockleveling=incomingBytes.Length%CHUNK\u SIZE;//最后一个块的剩余字节
byte[]outcomingBytes=新字节[incomingBytes.Length];
对于(变量i=0;i
乍一看,这段代码应该可以正常工作。但事实并非如此。注意注释掉的行: //Init(false,新参数swithiv(新的KeyParameter(Key),IV)); 和 //增加(四);为什么我需要手动增加iv? 只有在我取消注释它们时,我的代码才能正常工作

我想知道为什么我必须手动增加计数器?或者我在构造器的设置中出错了?我对Bouncy Castle不太熟悉


另外,我使用的是Nuget的BC 1.8.6.1版本。

问题是为什么首先要进行缓冲(或者说,为什么需要这段代码)。您使用的是缓冲密码,对吗?只需执行多个
ProcessBytes
并始终执行一个
DoFinal
,就可以了。别忘了一起讨论结果。尽管如此,我还是会投票支持你,因为这并不能解释原因。请注意,你没有在任何地方重置密码。每次加密都应该重新初始化密码。如果你把它当作一块地,这就不会发生。通常,只有键应该是字段。请注意,创建/初始化密码通常不会花费太多时间。我只使用了一次密码实例。所以,你是说,每次都需要重新初始化,而且这样做是正确的吗?是的,如果只是因为你想在每次运行时更新IV。通常情况下,IV(CTR模式下计数器的起点)是计数器值的前缀。在CTR模式的情况下,我会使用一个显式的nonce,然后用零填充其他最右边的字节(计数器是您实现的大端值)。当然,不需要包含零字节,您只需要存储nonce。您也可以在两侧使用计数器,但是更新nonce对于CTR来说是绝对重要的。如果没有它,你基本上就失去了所有的机密性。问题是为什么你首先要缓冲(或者说,为什么你需要这段代码)。您使用的是缓冲密码,对吗?只需执行多个
ProcessBytes
并始终执行一个
DoFinal
,就可以了。别忘了一起讨论结果。尽管如此,我还是会投票支持你,因为这并不能解释原因。请注意,你没有在任何地方重置密码。每次加密都应该重新初始化密码。如果你把它当作一块地,这就不会发生。通常,只有键应该是字段。请注意,创建/初始化密码通常不会花费太多时间。我只使用了一次密码实例。所以,你是说,每次都需要重新初始化,而且这样做是正确的吗?是的,如果只是因为你想在每次运行时更新IV。通常情况下,IV(CTR模式下计数器的起点)是计数器值的前缀。在CTR模式的情况下,我会使用一个显式的nonce,然后用零填充其他最右边的字节(计数器是您实现的大端值)。当然,不需要包含零字节,您只需要存储nonce。您也可以在两侧使用计数器,但是更新nonce对于CTR来说是绝对重要的。没有它,你基本上失去了所有的机密性。