I need to convert a JCE based code to a Bouncy Castle based code. I'm completely new to Bouncy Castle and couldn't find a easy-to-understand introduction to this topic in general or my issue specifically. This is the JCE based class:
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import com.sun.crypto.provider.SunJCE;
public class JCEBlowfishEncrypterDecrypter {
private static final String ALGORITHM = "Blowfish";
public static SecretKeySpec key;
public static String crypt(String msg, String k) throws Exception {
SecretKeySpec key = init(k);
return Hex.byte2hex(intCrypt(msg, key));
}
public static String decrypt(String msg, String k) throws Exception {
SecretKeySpec key = init(k);
return new String(intDecrypt(Hex.hex2byte(msg), key));
}
private static byte[] intCrypt(String msg, SecretKeySpec key) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(1, key);
return cipher.doFinal(msg.getBytes());
}
private static byte[] intDecrypt(byte encrypted[], SecretKeySpec key) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(2, key);
return cipher.doFinal(encrypted);
}
private static SecretKeySpec init(String myKey) throws NoSuchAlgorithmException {
SunJCE sunJce = new SunJCE();
Security.addProvider(sunJce);
byte raw[] = myKey.getBytes();
return new SecretKeySpec(raw, ALGORITHM);
}
}
... And this is the Bouncy Castle based class:
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.engines.BlowfishEngine;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
public class BouncyCastleBlowfishEncrypterDecrypter {
public static String crypt(String msg, String key) throws Exception {
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new BlowfishEngine(), new PKCS7Padding());
cipher.init(true, new KeyParameter(key.getBytes()));
byte[] inputAsBytes = msg.getBytes();
byte[] encryptedAsBytes = new byte[cipher.getOutputSize(inputAsBytes.length)];
int numberOfBytesCopiedOnEncryptedAsBytes = cipher.processBytes(inputAsBytes, 0, inputAsBytes.length,
encryptedAsBytes, 0);
cipher.doFinal(encryptedAsBytes, numberOfBytesCopiedOnEncryptedAsBytes);
return Hex.byte2hex(encryptedAsBytes);
}
public static String decrypt(String msg, String key) throws Exception {
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new BlowfishEngine(), new PKCS7Padding());
cipher.init(false, new KeyParameter(key.getBytes()));
byte[] outputConvertedAsBytes = Hex.hex2byte(msg);
byte[] decryptedAsBytes = new byte[cipher.getOutputSize(outputConvertedAsBytes.length)];
int numberOfBytesCopiedOnDecryptedAsBytes = cipher.processBytes(outputConvertedAsBytes, 0,
outputConvertedAsBytes.length, decryptedAsBytes, 0);
cipher.doFinal(decryptedAsBytes, numberOfBytesCopiedOnDecryptedAsBytes);
return new String(decryptedAsBytes);
}
}
... And this is the main method:
public static void main(String[] args) throws Exception {
String encrypted = JCEBlowfishEncrypterDecrypter.crypt("Test", "mmTSQOFzSL9xAwXGLMEe1Q==");
String decrypted = JCEBlowfishEncrypterDecrypter.decrypt(encrypted, "mmTSQOFzSL9xAwXGLMEe1Q==");
System.out.println("--------------");
System.out.println("encrypted -> " + encrypted);
System.out.println("decrypted -> " + decrypted);
encrypted = BouncyCastleBlowfishEncrypterDecrypter.crypt("Test",
"mmTSQOFzSL9xAwXGLMEe1Q==");
decrypted = BouncyCastleBlowfishEncrypterDecrypter.decrypt(encrypted,
"mmTSQOFzSL9xAwXGLMEe1Q==");
System.out.println("--------------");
System.out.println("encrypted -> " + encrypted);
System.out.println("decrypted -> " + decrypted);
}
... But I get some strange additional characters when decrypting: What's wrong?

In the meantime, you have changed your original post, so I refer you to the original post and list all necessary changes:
BufferedBlockCiphermust be replaced byPaddedBufferedBlockCipherandPKCS7Paddingmust be specified.cipher.getOutputSize()returns the size including the padding, which is why the bufferdecryptedAsBytesafter unpadding is larger than the decrypted data. The actual size of the decrypted data (i.e. without padding) can be determined via the return values ofcipher.processBytes()andcipher.doFinal()and used during decoding in conjunction with a suitableStringoverload.Sample implementation:
Further issues:
In the code, the encoding is missing in many
getBytes()andnew String()calls. This should be specified, as otherwise the platform-dependent default encoding is used intransparently.Possibly, the Base64 decoding of the key is missing in the code (
mmTSQOFzSL9xAwXGLMEe1Q==is UTF-8 encoded 24 bytes long and Base64 decoded 16 bytes long; technically both are possible, as Blowfish allows key sizes between 4 and 56 bytes; usually the raw key is applied).This is probably a legacy application, so the mode and algorithm cannot be changed. But for the sake of completeness: ECB is an insecure mode, better use a mode with IV (e.g. CBC) or even better authenticated encryption. The current standard AES is considered more secure than Blowfish.
Note that Base64 is more efficient than hex encoding.