'Android javax.crypto.IllegalBlockSizeException
I have an issue with this helper class where I get an exception while I tried to decrypt. I tried a few solutions on the internet and they seem not working.
This is the code I have for the moment. I see that this snippet is a bit old but would like to know other options to update the code as well.
UPDATE: I was able to narrow down the issue. I was getting the error while I'm trying to encrypt/decrypt the value "Bku>?u{Wpn/}H2h&". But the issue is first time encrypt/decrypt works and the second time after logging out and logging in again apps get the above error.
public class KeyStoreHelper {
public static final String TAG = "KeyStoreHelper";
/**
* Creates a public and private key and stores it using the Android Key
* Store, so that only this application will be able to access the keys.
*/
public static void createKeys(Context context, String alias) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidAlgorithmParameterException {
if (!isSigningKey(alias)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
createKeysM(alias, false);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
createKeysJBMR2(context, alias);
}
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
static void createKeysJBMR2(Context context, String alias) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidAlgorithmParameterException {
Calendar start = new GregorianCalendar();
Calendar end = new GregorianCalendar();
end.add(Calendar.YEAR, 30);
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
// You'll use the alias later to retrieve the key. It's a key
// for the key!
.setAlias(alias)
.setSubject(new X500Principal("CN=" + alias))
.setSerialNumber(BigInteger.valueOf(Math.abs(alias.hashCode())))
// Date range of validity for the generated pair.
.setStartDate(start.getTime()).setEndDate(end.getTime())
.build();
KeyPairGenerator kpGenerator = KeyPairGenerator.getInstance(
SecurityConstants.TYPE_RSA,
SecurityConstants.KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
kpGenerator.initialize(spec);
KeyPair kp = kpGenerator.generateKeyPair();
Log.d(TAG, "Public Key is: " + kp.getPublic().toString());
}
@TargetApi(Build.VERSION_CODES.M)
static void createKeysM(String alias, boolean requireAuth) {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA, SecurityConstants.KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setAlgorithmParameterSpec(new RSAKeyGenParameterSpec(1024, F4))
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
.setDigests(KeyProperties.DIGEST_SHA256,
KeyProperties.DIGEST_SHA384,
KeyProperties.DIGEST_SHA512)
// Only permit the private key to be used if the user authenticated
// within the last five minutes.
.setUserAuthenticationRequired(requireAuth)
.build());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
Log.d(TAG, "Public Key is: " + keyPair.getPublic().toString());
} catch (NoSuchProviderException | NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
}
}
/**
* JBMR2+ If Key with the default alias exists, returns true, else false.
* on pre-JBMR2 returns true always.
*/
public static boolean isSigningKey(String alias) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
try {
KeyStore keyStore = KeyStore.getInstance(SecurityConstants.KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
keyStore.load(null);
return keyStore.containsAlias(alias);
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
return false;
}
} else {
return false;
}
}
private static KeyStore.PrivateKeyEntry getPrivateKeyEntry(String alias) {
try {
KeyStore ks = KeyStore
.getInstance(SecurityConstants.KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
ks.load(null);
KeyStore.Entry entry = ks.getEntry(alias, null);
if (entry == null) {
Log.w(TAG, "No key found under alias: " + alias);
Log.w(TAG, "Exiting signData()...");
return null;
}
if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
Log.w(TAG, "Not an instance of a PrivateKeyEntry");
Log.w(TAG, "Exiting signData()...");
return null;
}
return (KeyStore.PrivateKeyEntry) entry;
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
return null;
}
}
public static String encrypt(Context context, String alias, String plaintext) {
try {
PublicKey publicKey = getPrivateKeyEntry(alias).getCertificate().getPublicKey();
Cipher cipher = getCipher();
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.encodeToString(cipher.doFinal(plaintext.getBytes()), Base64.NO_WRAP);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static String decrypt(String alias, String ciphertext) {
try {
PrivateKey privateKey = getPrivateKeyEntry(alias).getPrivateKey();
Cipher cipher = getCipher();
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(cipher.doFinal(Base64.decode(ciphertext, Base64.NO_WRAP)));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static Cipher getCipher() throws NoSuchPaddingException, NoSuchAlgorithmException {
return Cipher.getInstance(
String.format("%s/%s/%s",
SecurityConstants.TYPE_RSA,
SecurityConstants.BLOCKING_MODE,
SecurityConstants.PADDING_TYPE));
}
public interface SecurityConstants {
String KEYSTORE_PROVIDER_ANDROID_KEYSTORE = "AndroidKeyStore";
String TYPE_RSA = "RSA";
String PADDING_TYPE = "PKCS1Padding";
String BLOCKING_MODE = "NONE";
//RSA/ECB/OAEPWithSHA-256AndMGF1Padding
String SIGNATURE_SHA256withRSA = "SHA256withRSA";
String SIGNATURE_SHA512withRSA = "SHA512withRSA";
}
}
The exception I'm getting while decrypting.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: uk.com.app.tk, PID: 24191
java.lang.RuntimeException: javax.crypto.IllegalBlockSizeException
at uk.com.app.tk.Util.KeyStoreHelper.decrypt(KeyStoreHelper.java:182)
at uk.com.app.tk.api.opal.SecureSettings.retrieveSetting(SecureSettings.java:28)
at uk.com.app.tk.api.opal.Settings.getAppInstId(Settings.java:149)
at uk.com.app.tk.opal.PaymentActivity.processCard(PaymentActivity.java:442)
at uk.com.app.tk.opal.PaymentActivity.access$000(PaymentActivity.java:65)
at uk.com.app.tk.opal.PaymentActivity$2.onClick(PaymentActivity.java:224)
at android.view.View.performClick(View.java:8160)
at android.view.View.performClickInternal(View.java:8137)
at android.view.View.access$3700(View.java:888)
at android.view.View$PerformClick.run(View.java:30236)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8595)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
Caused by: javax.crypto.IllegalBlockSizeException
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:519)
at javax.crypto.Cipher.doFinal(Cipher.java:2055)
at uk.com.app.tk.Util.KeyStoreHelper.decrypt(AndroidKeyStoreHelper.java:180)
at uk.com.app.tk.api.opal.SecureSettings.retrieveSetting(SecureSettings.java:28)
at uk.com.app.tk.api.opal.OpalSettings.getAppInstId(OpalSettings.java:149)
at
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|