I'm new to Android security concepts.
I have been reading some blogs to get to know about we can encrypt data using Public key and can decrypt it using respective Private key. Encryption seems to be doesn't have any problem, but when I try to decrypt it, it throws:
javax.crypto.BadPaddingException: error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02.
My code is as follows:
public String RSAEncrypt(final String plain, PublicKey publicKey ) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte [] encryptedBytes = cipher.doFinal(plain.getBytes());
String encrypted = bytesToString(encryptedBytes);
System.out.println("EEncrypted?????" + encrypted );
return encrypted;
}
public String RSADecrypt(String encryptedBytes,PrivateKey privateKey ) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException {
Cipher cipher1 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher1.init(Cipher.DECRYPT_MODE, privateKey);
byte [] decryptedBytes = cipher1.doFinal(stringToBytes(encryptedBytes));
String decrypted = new String(decryptedBytes);
System.out.println("DDecrypted?????" + decrypted);
return decrypted;
}
public String bytesToString(byte[] b) {
byte[] b2 = new byte[b.length + 1];
b2[0] = 1;
System.arraycopy(b, 0, b2, 1, b.length);
return new BigInteger(b2).toString(36);
}
public byte[] stringToBytes(String s) {
byte[] b2 = new BigInteger(s, 36).toByteArray();
return Arrays.copyOfRange(b2, 1, b2.length);
}
Stack trace is as follows:
07-28 11:27:35.119: I/System.out(22933): KEYSTORE : String to encrypt = > Hello
07-28 11:27:35.119: I/System.out(22933): KEYSTORE : [B#41bbf4d0
07-28 11:27:38.422: I/System.out(22933): KEYSTORE : String to Decrypt = > UJGAchuDhu3mqH5YPjmYqKBapJYMjJRk9g6HIy8bANooWorzwqgiEo+dOse6Nfq7i0yzw/Wt7TSdTNiYROxehkZvEx/mW5+Niw1CgZ2y9b/ijTeNTF+7aGPrqfDXJ38hUFdTPc6oNl2FVOIafncGOSK9po1JOAYeK0JiA2KrACfPLPjsLQSRzseThyYGxttRM7qbx/N0VTmlTeuNpLFld8Gtw3fHR8UoLGkH/OTFYPLZBVNE8t/oCCy8FpcCu9SGXxF8vh1R4rq15bfyyh9sBU9RuVtoLM0wDSbKixHhNOwwx2Z/A+SHDaQD9C+x3p1AnS9FYZm0Y07E+VYQWqzOpw
07-28 11:27:38.562: W/System.err(22933): javax.crypto.BadPaddingException: error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02
07-28 11:27:41.515: D/WifiNative-wlan0(773): doString: SIGNAL_POLL
07-28 11:27:41.515: W/WifiHW(773): QCOM Debug wifi_send_command "IFNAME=wlan0 SIGNAL_POLL"
07-28 11:27:41.525: D/wpa_supplicant(16189): nl80211: survey data missing!
07-2
07-28 11:27:56.612: W/WifiHW(773): QCOM Debug wifi_send_command "IFNAME=wlan0 SIGNAL_POLL"
07-28 11:27:56.612: D/wpa_supplicant(16189): nl80211: survey data missing!
07-28 11:27:56.622: I/wpa_supplicant(16189): environment dirty rate=0 [0][0][0]
07-28 11:27:56.622: D/WifiStateMachine(773): fetchRssiAndLinkSpeedNative RSSI = -62 abnormalRssiCnt = 0 newLinkSpeed = 58
07-28 11:27:56.622: D/WifiStateMachine(773): fetchRssiAndLinkSpeedNative mLinkspeedCount = 2, mLinkspeedSum: 116
I'm not sure where am going wrong.
A BadPaddingException occurs when the padding (bytes to fill up a too small encryption block) doesn't match a specified format (for example PKCS1, OAEP, ...). This can have a few causes:
You are using a different mode of RSA for en- and decryption.
The data (the byte[]) you get from encryption is not the same as the one you pass to decryption.
(You are using an incorrect KeyPair.)
Since you are initializing RSA with getInstance("RSA") for encryption and getInstance("RSA/ECB/PKCS1Padding") for decryption, it could be possible that ECB/PKCS1Padding is not the default on Android (even though it should be on Desktop-Java).
So try this in RSAEncrypt():
cipher.getInstance("RSA/ECB/PKCS1Padding");
If this does not work, make sure that you pass the exact same byte[] you get from cipher.doFinal() in encryption to cipher.doFinal() in decryption.
(Your code does work on my Desktop Java7 btw.)
you must break message to blocks.
can use below class.
// Note: RSA has block limitation, text size must < (SIZE/8) , otherwise you see [too much data for RSA block]
public class RSA
{
private RSAPublicKey internalPublicKey;
private RSAPrivateCrtKey internalPrivateKey;
private int SIZE = -1;
private String cipherAlgorithm = "RSA/None/PKCS1PADDING";
private String keyAlgorithm = "RSA";
private int b64State = Base64.NO_WRAP;
private static int b64State_static = Base64.NO_WRAP;
public RSA(int size)
{
SIZE = size;
init();
}
public RSA(int size, RSAPublicKey puk, RSAPrivateCrtKey prk)
{
if(puk == null)
throw new RuntimeException("Err: PublicKey is null.");
if(prk != null)
{
if(!puk.getModulus().equals(prk.getModulus()))
throw new RuntimeException("Err: PublicKey not matched by PrivateKey.");
}
SIZE = size;
internalPublicKey = puk;
internalPrivateKey = prk;
}
private void init()
{
try
{
//SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC");
KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyAlgorithm);
kpg.initialize(SIZE); //initialize(SIZE, new SecureRandom());
KeyPair kp = kpg.genKeyPair();
internalPublicKey = (RSAPublicKey) kp.getPublic();
internalPrivateKey = (RSAPrivateCrtKey) kp.getPrivate();
}
catch(Exception e)
{throw new RuntimeException("Err: init RSA. " + e.toString());}
}
public int getSize()
{
return SIZE;
}
public RSAPublicKey getPublicKey()
{
return internalPublicKey;
}
public RSAPrivateCrtKey getPrivateKey()
{
return internalPrivateKey;
}
public String getPublicModule()
{
String s = internalPublicKey.toString();
return s.substring(s.indexOf("modulus")+8, s.indexOf(",publicExponent"));
}
public BigInteger getPublicModuleInt()
{
return internalPublicKey.getModulus();
}
public String getPublicExponent()
{
String s = internalPublicKey.toString();
return s.substring(s.indexOf("publicExponent")+15, s.lastIndexOf("}"));
}
public BigInteger getPublicExponentInt()
{
return internalPublicKey.getPublicExponent();
}
public String getPrivateExponent()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("privateExponent")+16, s.indexOf(",primeP"));
}
public String getPrimP()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("primeP=")+7, s.indexOf(",primeQ"));
}
public String getPrimQ()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("primeQ=")+7, s.indexOf(",primeExponentP"));
}
public String getPrimExponentP()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("primeExponentP=")+15, s.indexOf(",primeExponentQ"));
}
public String getPrimExponentQ()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("primeExponentQ=")+15, s.indexOf(",crtCoefficient"));
}
public String getCrtCoefficient()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("crtCoefficient=")+15, s.lastIndexOf(","));
}
public byte[] getPublicKeyAsByte()
{
return internalPublicKey.getEncoded();
}
public byte[] getPrivateKeyAsByte()
{
return internalPrivateKey.getEncoded();
}
public void changeCipherAlgorithm(String algorithm)
{
cipherAlgorithm = algorithm;
}
public byte[] getEncrypt(byte[] plain)
{
try
{
Cipher cipher = Cipher.getInstance(cipherAlgorithm);
cipher.init(Cipher.ENCRYPT_MODE, internalPublicKey);
return cipher.doFinal(plain);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(byte[] plain), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public byte[] getEncrypt(String plain)
{
try
{
return getEncrypt(plain.getBytes("UTF-8"));
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(String x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public String getEncryptToB64(byte[] plain)
{
return Base64.encodeToString(getEncrypt(plain), b64State);
}
public byte[] getLargeEncrypt(byte[] plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
try
{
int n = byPadding ? (getSize()/8) -11: (getSize()/8);
int offset = 0;
while(offset < plain.length)
{
byte[] section = Arrays.copyOfRange(plain, offset, Math.min(offset+n, plain.length));
byte[] cache = getEncrypt(section);
out.write(cache, 0, cache.length);
offset += n;
}
return out.toByteArray();
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeEncrypt(String x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public byte[] getLargeEncrypt(String plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
return getLargeEncrypt(plain.getBytes(Charset.forName("UTF-8")), byPadding);
}
public String getLargeEncryptToB64(String plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
return Base64.encodeToString(getLargeEncrypt(plain, byPadding), Base64.NO_WRAP);
}
public String getLargeEncryptToB64Block(String plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
StringBuilder sb = new StringBuilder();
try
{
byte[] enc = plain.getBytes("UTF-8");
int n = byPadding ? (getSize()/8) -11: (getSize()/8);
int offset = 0;
while(offset < enc.length)
{
byte[] section = Arrays.copyOfRange(enc, offset, Math.min(offset+n, enc.length));
sb.append(getEncryptToB64(section));
offset += n;
}
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeEncryptToB64Block(String x), ", Constants.DEFAULT_ALERT_STATE);
}
return sb.toString();
}
public String getLargeDecryptFromB64Block(String enc)
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
try
{
int n = (getSize()/8)-11;
int x = getEncryptToB64(TextHelper.generateString(n).getBytes("UTF-8")).length();
String[] ex = TextHelper.splitFix(enc, x);
for(int i=0; i<ex.length; i++)
{
byte[] sec = Base64.decode(ex[i], Base64.NO_WRAP);
out.write(sec, 0, sec.length);
//sb.append(getDecryptFromB64(ex[i]));
}
return getLargeDecryptToString(out.toByteArray());//sb.toString()
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeDecryptFromB64Block(String x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public byte[] getLargeDecrypt(byte[] enc)
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
try
{
int n = (getSize()/8);
int offset = 0;
while(offset < enc.length)
{
byte[] section = Arrays.copyOfRange(enc, offset, Math.min(offset+n, enc.length));
byte[] cache = getDecrypt(section);
out.write(cache, 0, cache.length);
offset += n;
}
return out.toByteArray();
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeDecrypt(byte[] x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public String getLargeDecryptToString(byte[] enc)
{
return new String(getLargeDecrypt(enc), Charset.forName("UTF-8"));
}
public String getLargeDecryptFromB64(String encB64)
{
return getLargeDecryptToString(Base64.decode(encB64, Base64.NO_WRAP));
}
public byte[] getDecrypt(byte[] encryptedBytes)
{
try
{
Cipher cipher = Cipher.getInstance(cipherAlgorithm);
cipher.init(Cipher.DECRYPT_MODE, internalPrivateKey);
return cipher.doFinal(encryptedBytes);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getDecrypt(byte[] x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public String getDecryptFromB64(String encrypted)
{
try
{
byte[] b = Base64.decode(encrypted.getBytes("UTF-8"), b64State);
return getDecryptAsString(b);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getDecryptFromB64(String x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public String getDecryptAsString(byte[] encryptedBytes)
{
return new String(getDecrypt(encryptedBytes), Charset.forName("UTF-8"));
}
public static byte[] getEncrypt(byte[] plain, PublicKey pk, Cipher cipher)
{
try
{
cipher.init(Cipher.ENCRYPT_MODE, pk);
return cipher.doFinal(plain);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(byte[] x, PublicKey pk, Cipher cipher), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static byte[] getEncrypt(String plain, PublicKey pk, Cipher cipher)
{
try
{
return getEncrypt(plain.getBytes("UTF-8"), pk, cipher);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(String x, PublicKey pk, Cipher cipher), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static byte[] getDecrypt(byte[] encryptedBytes, PrivateKey pk, Cipher cipher)
{
try
{
cipher.init(Cipher.DECRYPT_MODE, pk);
return cipher.doFinal(encryptedBytes);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static String getDecryptAsString(byte[] encryptedBytes, PrivateKey pk, Cipher cipher)
{
try
{
return new String(getDecrypt(encryptedBytes, pk, cipher), "UTF-8");
}
catch(Exception e){}
return null;
}
public static byte[] getDecrypt(final byte[] encryptedBytes, byte[] privateKey, Cipher cipher)
{
try
{
KeyFactory keyFac = KeyFactory.getInstance("RSA");
KeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
PrivateKey pk = keyFac.generatePrivate(keySpec);
cipher.init(Cipher.DECRYPT_MODE, pk);
return cipher.doFinal(encryptedBytes);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static String getDecryptAsString(final byte[] encryptedBytes, byte[] privateKey, Cipher cipher)
{
return new String(getDecrypt(encryptedBytes, privateKey, cipher), Charset.forName("UTF-8"));
}
public static byte[] sign(byte[] forSign, PrivateKey byThisKey)
{
try
{
Signature privateSignature = Signature.getInstance("SHA1withRSA");//or SHA256withRSA
privateSignature.initSign(byThisKey);
privateSignature.update(forSign);
return privateSignature.sign();
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: sign(), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static String sign(String forSign, PrivateKey byThisKey)
{
return Base64.encodeToString(sign(forSign.getBytes(), byThisKey), b64State_static);
}
public static boolean verify(String plainText, String signature, PublicKey publicKey)
{
Signature publicSignature;
try
{
publicSignature = Signature.getInstance("SHA1withRSA");
publicSignature.initVerify(publicKey);
publicSignature.update(plainText.getBytes());
byte[] signatureBytes = Base64.decode(signature, b64State_static);
return publicSignature.verify(signatureBytes);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: verify(), ", Constants.DEFAULT_ALERT_STATE);
}
return false;
}
public static RSAPublicKey generatePublicKey(String modulus, String exponent)
{
try
{
BigInteger modBigInteger = new BigInteger(modulus, 16);
BigInteger exBigInteger = new BigInteger(exponent, 16);
RSAPublicKeySpec spec = new RSAPublicKeySpec(modBigInteger, exBigInteger);
KeyFactory factory = KeyFactory.getInstance("RSA");
return (RSAPublicKey) factory.generatePublic(spec);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static RSAPublicKey generatePublicKey(BigInteger modulus, BigInteger exponent)
{
try
{
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory factory = KeyFactory.getInstance("RSA");
return (RSAPublicKey) factory.generatePublic(spec);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static RSAPublicKey generatePublicKeyFromDotNet(String modulus, String exponent)
{
return generatePublicKey(RSA.parseDotNetBigInt(modulus), RSA.parseDotNetBigInt(exponent));
}
public static RSAPrivateCrtKey generatePrivateKeyFromDotNet(String modulus, String pubEx, String priEx, String p, String q, String dp, String dq,String invQ)
{
return generatePrivateKey(RSA.parseDotNetBigInt(modulus), RSA.parseDotNetBigInt(pubEx), RSA.parseDotNetBigInt(priEx), RSA.parseDotNetBigInt(p)
,RSA.parseDotNetBigInt(q),RSA.parseDotNetBigInt(dp), RSA.parseDotNetBigInt(dq), RSA.parseDotNetBigInt(invQ));
}
public static PublicKey generateBCPublicKey(String modulus, String exponent)
{
try
{
BigInteger modBigInteger = new BigInteger(modulus, 16);
BigInteger exBigInteger = new BigInteger(exponent, 16);
RSAPublicKeySpec spec = new RSAPublicKeySpec(modBigInteger, exBigInteger);
KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
return factory.generatePublic(spec);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getBCPublicKey(), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static RSAPrivateCrtKey generatePrivateKey(String modulus, String publicExpo, String privateExpo, String primP, String primQ, String ePrimP, String ePrimQ, String cof)
{
try
{
BigInteger module = new BigInteger(modulus, 16);
BigInteger expo1 = new BigInteger(publicExpo, 16);
BigInteger expo2 = new BigInteger(privateExpo, 16);
BigInteger prim_P = new BigInteger(primP, 16);
BigInteger prim_Q = new BigInteger(primQ, 16);
BigInteger prim_EP = new BigInteger(ePrimP, 16);
BigInteger prim_EQ = new BigInteger(ePrimQ, 16);
BigInteger coefficient = new BigInteger(cof, 16);
/*BigInteger module = new BigInteger(1, Base64.encode(modulus.getBytes(), b64State));*/
RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(module, expo1, expo2, prim_P, prim_Q, prim_EP, prim_EQ, coefficient);
KeyFactory factory = KeyFactory.getInstance("RSA");
return (RSAPrivateCrtKey) factory.generatePrivate(spec);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static RSAPrivateCrtKey generatePrivateKey(BigInteger modulus, BigInteger publicExpo, BigInteger privateExpo, BigInteger primP, BigInteger primQ, BigInteger ePrimP, BigInteger ePrimQ, BigInteger cof)
{
try
{
RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(modulus, publicExpo, privateExpo, primP, primQ, ePrimP, ePrimQ, cof);
KeyFactory factory = KeyFactory.getInstance("RSA");
return (RSAPrivateCrtKey) factory.generatePrivate(spec);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static PrivateKey generateBCPrivateKey(String modulus, String publicExpo, String privateExpo, String primP, String primQ, String ePrimP, String ePrimQ, String cof)
{
try
{
BigInteger module = new BigInteger(modulus, 16);
BigInteger expo1 = new BigInteger(publicExpo, 16);
BigInteger expo2 = new BigInteger(privateExpo, 16);
BigInteger prim_P = new BigInteger(primP, 16);
BigInteger prim_Q = new BigInteger(primQ, 16);
BigInteger prim_EP = new BigInteger(ePrimP, 16);
BigInteger prim_EQ = new BigInteger(ePrimQ, 16);
BigInteger coefficient = new BigInteger(cof, 16);
RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(module, expo1, expo2, prim_P, prim_Q, prim_EP, prim_EQ, coefficient);
KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
return factory.generatePrivate(spec);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static Cipher generateCipher(String alg,#Nullable String provider)
{
try
{
if(provider == null)
return Cipher.getInstance(alg);
else
return Cipher.getInstance(alg, provider);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: generateCipher(), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static BigInteger parseDotNetBigInt(String b64BigInt)
{
try
{
String modulusHex = Hex.encodeHex(Base64.decode(b64BigInt.getBytes("UTF-8"), Base64.NO_WRAP));
return new BigInteger(modulusHex, 16);
}
catch (Exception ex)
{
ThreadHelper.exceptionAlert(ex, Constants.TAG_FOR_LOG, "Err: parseDotNetBigInt(),", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static String privateKeyToXMLString(RSAPrivateCrtKey key)
{
try
{
Document xml = privateKeyToXML(key);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
StringWriter sw = new StringWriter();
transformer.transform(new DOMSource(xml), new StreamResult(sw));
return sw.getBuffer().toString();
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: privateKeyToXMLString(RSAPrivateCrtKey x),", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static String publicKeyToXMLString(RSAPublicKey key)
{
try
{
Document xml = publicKeyToXML(key);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
StringWriter sw = new StringWriter();
transformer.transform(new DOMSource(xml), new StreamResult(sw));
return sw.getBuffer().toString();
}
catch(Exception e){}
return null;
}
public static Document publicKeyToXML(RSAPublicKey key)
{
try
{
Document result = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element rsaKeyValue = result.createElement("RSAKeyValue");
result.appendChild(rsaKeyValue);
Element modulus = result.createElement("Modulus");
rsaKeyValue.appendChild(modulus);
byte[] modulusBytes = key.getModulus().toByteArray();
modulusBytes = stripLeadingZeros(modulusBytes);
modulus.appendChild(result.createTextNode(new String(Base64.encode(modulusBytes, b64State_static))));
Element exponent = result.createElement("Exponent");
rsaKeyValue.appendChild(exponent);
byte[] exponentBytes = key.getPublicExponent().toByteArray();
exponent.appendChild(result.createTextNode(new String(Base64.encode(exponentBytes, b64State_static))));
return result;
}
catch(Exception e){}
return null;
}
public static Document privateKeyToXML(RSAPrivateCrtKey key)
{
try
{
Document result = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element rsaKeyValue = result.createElement("RSAKeyValue");
result.appendChild(rsaKeyValue);
Element modulus = result.createElement("Modulus");
rsaKeyValue.appendChild(modulus);
Element exponent = result.createElement("Exponent");
rsaKeyValue.appendChild(exponent);
Element P = result.createElement("P");
rsaKeyValue.appendChild(P);
Element Q = result.createElement("Q");
rsaKeyValue.appendChild(Q);
Element DP = result.createElement("DP");
rsaKeyValue.appendChild(DP);
Element DQ = result.createElement("DQ");
rsaKeyValue.appendChild(DQ);
Element InverseQ = result.createElement("InverseQ");
rsaKeyValue.appendChild(InverseQ);
Element D = result.createElement("D");
rsaKeyValue.appendChild(D);
byte[] modulusBytes = key.getModulus().toByteArray();
modulusBytes = stripLeadingZeros(modulusBytes);
modulus.appendChild(result.createTextNode(new String(Base64.encode(modulusBytes, b64State_static))));
byte[] pubExponent = key.getPublicExponent().toByteArray();
exponent.appendChild(result.createTextNode(new String(Base64.encode(pubExponent, b64State_static))));
byte[] p = key.getPrimeP().toByteArray();
P.appendChild(result.createTextNode(new String(Base64.encode(p, b64State_static))));
byte[] q = key.getPrimeQ().toByteArray();
Q.appendChild(result.createTextNode(new String(Base64.encode(q, b64State_static))));
byte[] ep = key.getPrimeExponentP().toByteArray();
DP.appendChild(result.createTextNode(new String(Base64.encode(ep, b64State_static))));
byte[] eq = key.getPrimeExponentP().toByteArray();
DQ.appendChild(result.createTextNode(new String(Base64.encode(eq, b64State_static))));
byte[] cof = key.getCrtCoefficient().toByteArray();
InverseQ.appendChild(result.createTextNode(new String(Base64.encode(cof, b64State_static))));
byte[] priExponent = key.getPrivateExponent().toByteArray();
D.appendChild(result.createTextNode(new String(Base64.encode(priExponent, b64State_static))));
return result;
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static byte[] stripLeadingZeros(byte[] input)
{
while (input[0] == (byte) 0)
{
input = Arrays.copyOfRange(input, 1, input.length);
}
return input;
}
public static void saveKey(File file, PublicKey key)
{
try
{
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key.getEncoded());
FileOutputStream fos = new FileOutputStream(file);
fos.write(x509EncodedKeySpec.getEncoded());
fos.close();
}
catch(Exception e){}
}
public static void saveKey(File file, PrivateKey key)
{
try
{
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key.getEncoded());
FileOutputStream fos = new FileOutputStream(file);
fos.write(pkcs8EncodedKeySpec.getEncoded());
fos.close();
}
catch(Exception e){}
}
public PublicKey openPublicKey(String path, String algorithm)
{
try
{
File filePublicKey = new File(path);
FileInputStream fis = new FileInputStream(path);
byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
fis.read(encodedPublicKey);
fis.close();
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
return keyFactory.generatePublic(publicKeySpec);
}
catch(Exception e){}
return null;
}
public PrivateKey openPrivateKey(String path, String algorithm)
{
try
{
File filePrivateKey = new File(path);
FileInputStream fis = new FileInputStream(path);
byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
fis.read(encodedPrivateKey);
fis.close();
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);//RSA
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
return keyFactory.generatePrivate(privateKeySpec);
}
catch(Exception e){}
return null;
}
public static RSAPublicKey fetchPublicKeyFromXML(Document xml)
{
try
{
Element root = XMLMaster.getRoot(xml);
String mud = XMLMaster.getTextContent(root, "Modulus", 0);
String pubE = XMLMaster.getNodeValue(root, "Exponent", 0);
return generatePublicKeyFromDotNet(mud, pubE);
}
catch (Throwable e)
{
//throw new RuntimeException("Err: can not fetch PublicKey. " + e.toString());
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: can not fetch PublicKey. ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static RSAPrivateCrtKey fetchPrivateKeyFromXML(Document xml)
{
try
{
Element root = XMLMaster.getRoot(xml);
String mud = XMLMaster.getTextContent(root, "Modulus", 0);
String pubE = XMLMaster.getNodeValue(root, "Exponent", 0);
String priE = XMLMaster.getNodeValue(root, "D", 0);
String p = XMLMaster.getNodeValue(root, "P", 0);
String Q = XMLMaster.getNodeValue(root, "Q", 0);
String EP = XMLMaster.getNodeValue(root, "DP", 0);
String EQ = XMLMaster.getNodeValue(root, "DQ", 0);
String cof = XMLMaster.getNodeValue(root, "InverseQ", 0);
return generatePrivateKeyFromDotNet(mud, pubE, priE, p, Q, EP, EQ, cof);
}
catch (Throwable e)
{
throw new RuntimeException("Err: can not fetch PrivateKey. " + e.toString());
}
}
public static PrivateKey loadPrivateKey(String privateKeyB64)
{
try
{
byte[] buffer = Base64.decode(privateKeyB64, Base64.NO_WRAP);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(keySpec);
//Class c = Reflector.getClassByAddressName("com.android.org.conscrypt.OpenSSLRSAPrivateKey");
//RSAPrivateKeySpec privSpec = new RSAPrivateKeySpec(modules, d);
}
catch (Throwable e)
{
throw new RuntimeException("Err: can not load PrivateKey. " + e.toString());
}
}
public String convertCaseToString(BigInteger num)
{
return num.toString(16);
} // Use: convertCaseToString(rsa.getPublicModule())
}
Because you are working with encrypted data, it is unlikely you can convert that directly to a String (each byte may not correspond to a character store-able in a String) - therefore I'd expect bytesToString(encryptedBytes) to usually fail. Try converting the encrypted data to Base64 first then that will always be store-able in a String. You then simply do the reverse to decrypt:-
// to encrypt and get a String object
byte[] encode = Base64.encode(encryptedBytes, Base64.NO_PADDING|Base64.NO_WRAP);
String encryptedDataStr = new String(encode);
Then you can do stuff (like store) the encryptedDataStr or whaterver. Then later...
// to decrypt
byte[] encryptedBytes = Base64.decode(encryptedDataStr, Base64.NO_PADDING|Base64.NO_WRAP);
byte [] decryptedBytes = cipher1.doFinal(encryptedBytes);
Good luck!