Search code examples
c#encryptionbouncycastleblowfishcbc-mode

Encrypt data with CBC Blowfish Encryption not working


I'm trying to encrypt with bounycastle using CBC blowfish encryption. It is a requirement I cannot change so I need to figure out how this works. I am rather new with encryption altogether so any help would be really appreciated as I have a deadline to meet.

Here is what I have so far:

public void Test() {
    var value = "My Test Value";
    var key = "some key"; //56 characters long
    var iv = Encoding.GetBytes("some iv");
    var encryptedValue = CbcBlowfishEncrypt(encryptedText, key, iv);
}

private string CbcBlowfishEncrypt(string strValue, string key, byte[] iv)
{
    byte[] inputBytes = Encoding.UTF8.GetBytes(strValue);
    BlowfishEngine engine = new BlowfishEngine();
    CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC
    PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher); //Default scheme is PKCS5/PKCS7
    KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(key));
    ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 8);

    cipher.Init(true, keyParamWithIV);
    byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)];
    int length = cipher.ProcessBytes(inputBytes, outputBytes, 0);
    cipher.DoFinal(outputBytes, length);
    var result = BitConverter.ToString(outputBytes).Replace("-", "");
    return result;
}

public static byte[] StringToByteArray(string hex)
{
    return Enumerable.Range(0, hex.Length)
        .Where(x => x % 2 == 0)
        .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
        .ToArray();
}

Here is the error I get:

'initialisation vector must be the same length as block size'

As I've mentioned above, I am rather new to this with a deadline for a client and doing my best to read up on a lot of this and understand it, but I've really hit a wall here and not sure where to go from here. This is probably an obvious thing for some of you so please have some mercy :)

Edit: One thing to mention is that I tried changing 16 to 8 for ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16); and it seems to let it through. But what I'm confused on that is my byte is 16 bytes long, not 8. Is this because each character takes up 2 bytes and that value represents characters, not bytes?


Solution

  • Nobody officially posted an answer, so I just wanted to close of the question to help anyone else trying to do the same. Below is the code I used to encrypt and decrypt the value:

    function Run()
    {
        var key = "enter your key";
        var value = "Enter your test value";
        var iv = StringToByteArray("enter your 16 char hex value");
    
        var encryptedValue = CbcBlowfishEncrypt(value, key, iv);
        var decryptedValue = CbcBlowfishDecrypt(encryptedValue, key, iv);
    }
    
    private string CbcBlowfishEncrypt(string strValue, string key, byte[] iv)
    {
        byte[] inputBytes = Encoding.UTF8.GetBytes(strValue);
        BlowfishEngine engine = new BlowfishEngine();
        CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher);
        KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(key));
        ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 8);
    
        cipher.Init(true, keyParamWithIV);
        byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)];
        int length = cipher.ProcessBytes(inputBytes, outputBytes, 0);
        cipher.DoFinal(outputBytes, length); //Do the final block
        var c = BitConverter.ToString(outputBytes);
        string encryptedInput = Convert.ToBase64String(outputBytes);
        var result = BitConverter.ToString(outputBytes).Replace("-", "");
        return result;
    }
    
    private string CbcBlowfishDecrypt(string strValue, string key, byte[] iv)
    {
        BlowfishEngine engine = new BlowfishEngine();
        CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher);
        StringBuilder result = new StringBuilder();
        KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(key));
        ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 8);
    
        cipher.Init(false, keyParamWithIV);
        byte[] out1 = Hex.Decode(strValue);
        byte[] out2 = new byte[cipher.GetOutputSize(out1.Length)];
        int len2 = cipher.ProcessBytes(out1, 0, out1.Length, out2, 0);
        cipher.DoFinal(out2, len2);
        return Encoding.UTF8.GetString(out2);
    }
    
    public static byte[] StringToByteArray(string hex)
    {
        return Enumerable.Range(0, hex.Length)
            .Where(x => x % 2 == 0)
            .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
            .ToArray();
    }