I am trying to encrypt an ISO-0 pinblock using the codenameone BouncyCastle lib. The methods I use to achieve this is as follows:
private static byte[] performEncrypt(byte[] key, String plainText, boolean padding) {
byte[] ptBytes = plainText.getBytes();
BufferedBlockCipher cipher;
if (padding) {
cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new DESedeEngine()));
} else {
cipher = new BufferedBlockCipher(new CBCBlockCipher(new DESedeEngine()));
}
cipher.init(true, new KeyParameter(key));
byte[] rv = new byte[cipher.getOutputSize(ptBytes.length)];
int oLen = cipher.processBytes(ptBytes, 0, ptBytes.length, rv, 0);
try {
cipher.doFinal(rv, oLen);
} catch (CryptoException ce) {
LoggingUtil.error(TAG, ce, "Unexpected Exception");
}
return rv;
}
private static String createIso0PinBlock(String pin, String number) {
...
}
private static String getPaddedData(String data, byte padCharacter) {
String paddedData = ByteUtil.pad(data, (char) padCharacter, 8).toString();
return paddedData;
}
public static String createPinBlockAndEncrypt(String pin, String number) {
LoggingUtil.debug("SecurityUtil", "CREAT PIN BLOCK AND ENCRYPT.. PIN: " + pin + " NUMBER: " + number);
String pb = createIso0PinBlock(pin, number.substring(0, number.length() - 1));
LoggingUtil.debug("SecurityUtil", "PINBLOCK: " + pb);
String padded = getPaddedData(pb, (byte) 0x00);
LoggingUtil.debug("SecurityUtil", "PADDED: " + padded);
byte[] encrypted = performEncrypt(Hex.decode(KEY.getBytes()), new String(ByteUtil.hex2byte(padded)), false);
return ByteUtil.byte2hex(encrypted);
}
In ByteUtil
:
public static StringBuilder pad(String data, char padCharacter, int multiplier) {
StringBuilder text = new StringBuilder();
text.append(data);
while (text.length() % multiplier != 0) {
text.append(padCharacter);
}
return text;
}
To give example Log outputs:
[SecurityUtil] CREAT PIN BLOCK AND ENCRYPT.. PIN: 2255 NUMBER: 6284734104205417486
[SecurityUtil] PINBLOCK: 042214FBDFABE8B7
[SecurityUtil] PADDED: 042214FBDFABE8B7
When I run this through a public static void main
method, it works as expected, however, when I build this for Android via Codenameone, I get the following error in logcat:
org.bouncycastle.crypto.DataLengthException: data not block size aligned
org.bouncycastle.crypto.BufferedBlockCipher.doFinal(BufferedBlockCipher.java:275)
Despite the padded pinblock being 16 in length (a multiple of 8).
Any help regarding this issue would be appreciated.
Encryption works on binary data, and your pinblock is binary, so keep it that way.
When calling performEncrypt(..)
you convert your hex encoded pinblock to a string with new String(ByteUtil.hex2byte(padded))
, and inside performEncrypt(...)
you convert it to a byte array with byte[] ptBytes = plainText.getBytes();
. The problem with this is that not all byte sequences can be mapped correctly back and forth through a string, and you might end up with different data and even different length etc. take a look here
Change your signature of you performEncrypt(..)
to:
private static byte[] performEncrypt(byte[] key, byte[] plainText, boolean padding) {
and avoid converting through a string altogether.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With