Search code examples
c#encodingbouncycastle

Encoding type and key problem in Bouncy castle AES Encryption


I am using Bouncy Castle crypto libraries. I have a 13 character key something like string key = "wergt543jusft"; Text to be encrypted is: string plain = "435625241526373";

I convert it into 128 bit key using the following method.

public string getKeyMessageDigest(string key)
{
    byte[] ByteData = Encoding.ASCII.GetBytes(key);

    //MD5 creating MD5 object.
    MD5 oMd5 = MD5.Create();
    byte[] HashData = oMd5.ComputeHash(ByteData);

    //convert byte array to hex format
    StringBuilder oSb = new StringBuilder();
    for (int x = 0; x < HashData.Length; x++)
    {
        //hexadecimal string value
        oSb.Append(HashData[x].ToString("x2"));
    }
    return Convert.ToString(oSb);
}

Then, I create an object of AESEncryption class which I have defined

AESEncryption aes = new AESEncryption(Encoding.ASCII, new Pkcs7Padding());

Class AESEncryption has two methods:

public string Encrypt(string plain, string key)
{
    string hashKey = getKeyMessageDigest(key);
    BCEngine bcEngine = new BCEngine(new AesEngine(), _encoding);
    bcEngine.SetPadding(_padding);
    return bcEngine.Encrypt(plain, hashKey);
}

public string Decrypt(string plain, string key)
{
    string hashKey = getKeyMessageDigest(key);
    BCEngine bcEngine = new BCEngine(new AesEngine(), _encoding);
    bcEngine.SetPadding(_padding);
    return bcEngine.Decrypt(plain, hashKey);
}

Everything works fine.

But, when I change the encoding type to anything other than ASCII, I get error "Key length not 128/192/256 bits.". I made the following chnages in my code to change the Encoding type:

public string getKeyMessageDigest(string key)
{
    byte[] ByteData = Encoding.UTF32.GetBytes(key);
    //MD5 creating MD5 object.
    MD5 oMd5 = MD5.Create();
    byte[] HashData = oMd5.ComputeHash(ByteData);

    //convert byte array to hex format
    StringBuilder oSb = new StringBuilder();
    for (int x = 0; x < HashData.Length; x++)
    {
        //hexadecimal string value
        oSb.Append(HashData[x].ToString("x2"));
    }
    return Convert.ToString(oSb);
}

AND

AESEncryption aes = new AESEncryption(Encoding.UTF32, new Pkcs7Padding());

Rest of the code remains the same. Can anyone please guide?

Thanks in advance...

I am following the link: http://elian.co.uk/post/2009/07/29/Bouncy-Castle-CSharp.aspx

My aim is to generate the encrypted string for the variable plian = "435625241526373" using all encoding types such as: ASCII,BigEndianUnicode,Unicode,UTF32 UTF7,UTF8

[Edit from comments] The exception is thrown inside this method:

private byte[] BouncyCastleCrypto(bool forEncrypt, byte[] input, string key)
{ 
    try 
    { 
        cipher = _padding == null ?
            new PaddedBufferedBlockCipher(_blockCipher) : 
            new PaddedBufferedBlockCipher(_blockCipher, _padding);

        byte[] keyByte = _encoding.GetBytes(key);
        _cipher.Init(forEncrypt, new KeyParameter(keyByte));
        return _cipher.DoFinal(input);

    }
    catch (Org.BouncyCastle.Crypto.CryptoException ex)
    {
        throw new CryptoException(ex.Message); 
    } 
} 

Solution

  • You need to make sure that your key is 128/192/256 bits long. Just as you used getKeyMessageDigest inside Encrypt and Decrypt methods, you can use it inside the try/catch clause to create a 128-bit hash value of your key:

    private byte[] BouncyCastleCrypto(bool forEncrypt, byte[] input, string key)
    { 
        try 
        { 
            cipher = _padding == null ?
                new PaddedBufferedBlockCipher(_blockCipher) : 
                new PaddedBufferedBlockCipher(_blockCipher, _padding);
    
            // this line will make sure keyByte is 16 bytes long
            byte[] keyByte = getKeyMessageDigest(key);
    
            _cipher.Init(forEncrypt, new KeyParameter(keyByte));
    
            return _cipher.DoFinal(input);          
        }
        catch (Org.BouncyCastle.Crypto.CryptoException ex)
        {
            throw new CryptoException(ex.Message); 
        } 
    } 
    

    Additionally, you don't need to worry about changing the encoding inside getKeyMessageDigest, encoding is passed around just to ensure correct encoding for the actual data, not the key.

    MD5 hash always contains 16 bytes, regardless of the input size. So, the only problem is if you use Encoding.GetBytes to get the key, since this method returns different array lengths for different encodings.