4

I am trying to use to implement AES CTR encryption using the Bouncy castle cryptography library in C#. .NET provides RijndaelManaged Crypto Library but it does not support CTR mode for AES hence the selection of Bouncycastle.

I haven't been able to code it properly The problem seems to be with IV.

    public string BytesToHex(byte[] bytes)
    {
        char[] c = new char[bytes.Length * 2];

        byte b;

        for (int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)
        {
            b = ((byte)(bytes[bx] >> 4));
            c[cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);

            b = ((byte)(bytes[bx] & 0x0F));
            c[++cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);
        }

        return new string(c);
    }

    public byte[] HexToBytes(string str)
    {
        if (str.Length == 0 || str.Length % 2 != 0)
            return new byte[0];

        byte[] buffer = new byte[str.Length / 2];
        char c;
        for (int bx = 0, sx = 0; bx < buffer.Length; ++bx, ++sx)
        {
            // Convert first half of byte
            c = str[sx];
            buffer[bx] = (byte)((c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0')) << 4);

            // Convert second half of byte
            c = str[++sx];
            buffer[bx] |= (byte)(c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0'));
        }

        return buffer;
    }
   private static byte[] cipherData(PaddedBufferedBlockCipher cipher, byte[] data)
    {
        int minSize = cipher.GetOutputSize(data.Length);
        byte[] outBuf = new byte[minSize];
        int length1 = cipher.ProcessBytes(data, 0, data.Length, outBuf, 0);
        int length2 = cipher.DoFinal(outBuf, length1);
        int actualLength = length1 + length2;
        byte[] result = new byte[actualLength];
        Array.Copy(outBuf,result,actualLength);

        //System.arraycopy(outBuf, 0, result, 0, result.length);
        return result;
    }
    private static byte[] decryptCTR(byte[] cipher, byte[] key, byte[] iv)
    {
        //Org.BouncyCastle.Crypto.Modes.SicBlockCipher

      PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new SicBlockCipher(new AesEngine()));

      ParametersWithIV   ivAndKey = new ParametersWithIV(new KeyParameter(key), iv);
      aes.Init(false, ivAndKey);

      return cipherData(aes, cipher);
    }
    private static byte[] encryptCTR(byte[] plain, byte[] key, byte[] iv)
    {
        PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new SicBlockCipher(
                new AesEngine()));

        ParametersWithIV ivAndKey = new ParametersWithIV(new KeyParameter(key), iv);
        aes.Init(true, ivAndKey);
        return cipherData(aes, plain);
    }

And I am trying to decrypt a given cipher text using the following method

   private void btnDecryptDirectly_Click(object sender, EventArgs e)
    {
        String encodedMsgHex =  "770b80259ec33beb2561358a9f2dc617e46218c0a53cbeca695ae45faa8952aa0e311bde9d4e01726d3184c34451";
        String key = "36f18357be4dbd77f050515c73fcf9f2";
        byte [] keyBytes = HexToBytes(key);

        byte[] cipher = HexToBytes(encodedMsgHex);

        txtDecryptedText = BytesToHex(decryptCTR(cipher, keyBytes, IV));

        rtbDecrypted.Text = txtDecryptedText;
    }

Every time I run this I get error the

last block incomplete in decryption

Error.

Can any one please help me out.

Khurram Majeed
  • 2,291
  • 8
  • 37
  • 59
  • 3
    owlstead is correct about not needing the padding. I would advise to use CipherUtilities.GetCipher("AES/CTR/NoPadding") to get the cipher object, at least until you have things basically working. You might also find the Org.BouncyCastle.Utilities.Encoders.Hex class useful. – Peter Dettman Dec 05 '12 at 06:05
  • Try this https://stackoverflow.com/questions/51286633/java-bc-sicblockcipher-direct-output-equivalent-in-c-sharp – Sentinel Jul 13 '18 at 09:49

2 Answers2

4

You don't need to use PaddedBufferedBlockCipher at all. Counter mode encryption is a streaming mode for a block cipher. Streaming ciphers don't need padding.

You can use BufferedBlockCipher to access the streaming mode as SicBlockCipher only lets you encrypt one block at a time.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • 1
    The C# implementation of SicBlockCipher seems to only offer ProcessBlock, no processbytes. – Sentinel Jul 11 '18 at 12:47
  • @Sentinel Thanks, fixed. – Maarten Bodewes Jul 11 '18 at 12:50
  • Quick q from me though on that, as I am stuck trying to understand how a bit of java code works for a c# port.... the SicBlockCipher in Java seems to allow processing a single byte directly to an output buffer, but BufferedBlockCipher doesn't seem to do the same without a call to DoFinal. Is my understanding correct? I can put this into a SO question if you want. – Sentinel Jul 11 '18 at 12:54
  • Please create a question, it seems very useful to others as well! – Maarten Bodewes Jul 11 '18 at 13:00
  • OK added here https://stackoverflow.com/questions/51286633/java-bc-sicblockcipher-direct-output-equivalent-in-c-sharp Any help much thanks in advance. – Sentinel Jul 11 '18 at 13:25
1

If you need just CTR mode, you can easily code it by yourself - it just writing IV, IV + 1, IV + 2, IV +3 ... to buffer (up to input data size), encrypting this buffer, and xoring with buffer you need to encrypt or decrypt. This can be achieved with builtin Rijndael Managed.

Nickolay Olshevsky
  • 13,706
  • 1
  • 34
  • 48