I'm learning how to use the BouncyCastle c# cipher library for doing encryption. I'm not looking to send messages so I'm not thinking about security etc. I have written my c# code in Visual Studio.
Here is the problem. I have encrypted the text "Hello World!", using Twofish in CFB mode. The key is 1234567812345678. I've used phpfiddle http://phpfiddle.org/ online tool.
$algo = 'twofish';
$mode = 'cfb';
$cipher = mcrypt_module_open($algo,'',$mode,'');
$key = hex2bin('31323334353637383132333435363738'); //1234567812345678
$iv = hex2bin('00000000000000000000000000000000');
mcrypt_generic_init($cipher, $key, $iv);
$plaintext = utf8_encode('Hello World!');
$encrypted = mcrypt_encrypt($algo, $key, $plaintext, $mode, $iv);
printf("<br>Encrypted text: %s<br><br>",base64_encode($encrypted));
$decrypted = mcrypt_decrypt($algo, $key, $encrypted, $mode, $iv);
printf("<br>Decrypted text: %s (%s)<br><br>",$decrypted,bin2hex($decrypted));
mcrypt_generic_deinit($cipher);
mcrypt_module_close($cipher);
The result is as follows
cfdJ+M6MAzG4WJMb (Base64)
I have then created a c# version to decrypt the same text
// ASCII encoding and Zero padding
encoding = Encoding.ASCII
padding = IBlockCipherPadding.zeroBytePadding
// Set up the engine and cipher types
baseCipher = new TwofishEngine();
blockSize = baseCipher.GetBlockSize();
modeCipher = new CfbBlockCipher(baseCipher, blockSize);
cipher = padding == null ? new PaddedBufferedBlockCipher(modeCipher) : new PaddedBufferedBlockCipher(modeCipher, padding);
// convert the strings to byte array and create a dummy 000000.. iv
byte[] iv = new byte[blockSize]; // i.e. 16 bytes of zero
keyBytes = _encoding.GetBytes(key); //1234567812345678
inputBytes = Convert.FromBase64String(inp);
// initiate the cipher with iv parameters
cipher.Init(true, new ParametersWithIV(new KeyParameter(keyBytes), iv));
// do the decryption
console.write(_encoding.GetString(cipher.DoFinal(inputBytes)) + "\n";)
But this gives me garbage out. I get HIl1oVW�rEdIp�
Close (H.l.o.W.r.d.) but every other letter is wrong!
ECB mode works fine so it must be something to do with the initialization vector.
Are there some differences between PHP and c# that I havn't learnt yet?
Where is my c# code incorrect in that case?
OK. So I solved it finally. A basic error in my understanding of cipher block modes. CFB and OFB are Stream Ciphers not Padded Buffered block ciphers.
Therefore the cipher setup should have been
(The cipher.doFinal was changed too but not shown here)
It now works fine.