-
-
Save awesometic/f1f52acf5904189f687724e42c461413 to your computer and use it in GitHub Desktop.
/** | |
* Created by Awesometic | |
* It's encrypt returns Base64 encoded, and also decrypt for Base64 encoded cipher | |
* references: http://stackoverflow.com/questions/12471999/rsa-encryption-decryption-in-android | |
*/ | |
import android.util.Base64; | |
import java.nio.charset.StandardCharsets; | |
import java.security.InvalidKeyException; | |
import java.security.KeyFactory; | |
import java.security.KeyPair; | |
import java.security.KeyPairGenerator; | |
import java.security.NoSuchAlgorithmException; | |
import java.security.PrivateKey; | |
import java.security.PublicKey; | |
import java.security.spec.InvalidKeySpecException; | |
import java.security.spec.X509EncodedKeySpec; | |
import javax.crypto.BadPaddingException; | |
import javax.crypto.Cipher; | |
import javax.crypto.IllegalBlockSizeException; | |
import javax.crypto.NoSuchPaddingException; | |
public class RSACipher { | |
KeyPairGenerator kpg; | |
KeyPair kp; | |
PublicKey publicKey; | |
PrivateKey privateKey; | |
byte[] encryptedBytes, decryptedBytes; | |
Cipher cipher, cipher1; | |
String encrypted, decrypted; | |
private final static String CRYPTO_METHOD = "RSA"; | |
private final static int CRYPTO_BITS = 2048; | |
public RSACipher() | |
throws NoSuchAlgorithmException, | |
NoSuchPaddingException, | |
InvalidKeyException, | |
IllegalBlockSizeException, | |
BadPaddingException { | |
generateKeyPair(); | |
} | |
private void generateKeyPair() | |
throws NoSuchAlgorithmException, | |
NoSuchPaddingException, | |
InvalidKeyException, | |
IllegalBlockSizeException, | |
BadPaddingException { | |
kpg = KeyPairGenerator.getInstance(CRYPTO_METHOD); | |
kpg.initialize(CRYPTO_BITS); | |
kp = kpg.genKeyPair(); | |
publicKey = kp.getPublic(); | |
privateKey = kp.getPrivate(); | |
} | |
/** | |
* Encrypt plain text to RSA encrypted and Base64 encoded string | |
* | |
* @param args | |
* args[0] should be plain text that will be encrypted | |
* If args[1] is be, it should be RSA public key to be used as encrypt public key | |
* @return a encrypted string that Base64 encoded | |
* @throws NoSuchAlgorithmException | |
* @throws NoSuchPaddingException | |
* @throws InvalidKeyException | |
* @throws IllegalBlockSizeException | |
* @throws BadPaddingException | |
*/ | |
public String encrypt(Object... args) | |
throws NoSuchAlgorithmException, | |
NoSuchPaddingException, | |
InvalidKeyException, | |
IllegalBlockSizeException, | |
BadPaddingException { | |
String plain = (String) args[0]; | |
PublicKey rsaPublicKey; | |
if (args.length == 1) { | |
rsaPublicKey = this.publicKey; | |
} else { | |
rsaPublicKey = (PublicKey) args[1]; | |
} | |
cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding"); | |
cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey); | |
encryptedBytes = cipher.doFinal(plain.getBytes(StandardCharsets.UTF_8)); | |
return Base64.encodeToString(encryptedBytes, Base64.DEFAULT); | |
} | |
public String decrypt(String result) | |
throws NoSuchAlgorithmException, | |
NoSuchPaddingException, | |
InvalidKeyException, | |
IllegalBlockSizeException, | |
BadPaddingException { | |
cipher1 = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding"); | |
cipher1.init(Cipher.DECRYPT_MODE, privateKey); | |
decryptedBytes = cipher1.doFinal(Base64.decode(result, Base64.DEFAULT)); | |
decrypted = new String(decryptedBytes); | |
return decrypted; | |
} | |
public String getPublicKey(String option) | |
throws NoSuchAlgorithmException, | |
NoSuchPaddingException, | |
InvalidKeyException, | |
IllegalBlockSizeException, | |
BadPaddingException { | |
switch (option) { | |
case "pkcs1-pem": | |
String pkcs1pem = "-----BEGIN RSA PUBLIC KEY-----\n"; | |
pkcs1pem += Base64.encodeToString(publicKey.getEncoded(), Base64.DEFAULT); | |
pkcs1pem += "-----END RSA PUBLIC KEY-----"; | |
return pkcs1pem; | |
case "pkcs8-pem": | |
String pkcs8pem = "-----BEGIN PUBLIC KEY-----\n"; | |
pkcs8pem += Base64.encodeToString(publicKey.getEncoded(), Base64.DEFAULT); | |
pkcs8pem += "-----END PUBLIC KEY-----"; | |
return pkcs8pem; | |
case "base64": | |
return Base64.encodeToString(publicKey.getEncoded(), Base64.DEFAULT); | |
default: | |
return null; | |
} | |
} | |
public static PublicKey stringToPublicKey(String publicKeyString) | |
throws NoSuchAlgorithmException, | |
NoSuchPaddingException, | |
InvalidKeyException, | |
IllegalBlockSizeException, | |
BadPaddingException { | |
try { | |
if (publicKeyString.contains("-----BEGIN PUBLIC KEY-----") || publicKeyString.contains("-----END PUBLIC KEY-----")) | |
publicKeyString = publicKeyString.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", ""); | |
byte[] keyBytes = Base64.decode(publicKeyString, Base64.DEFAULT); | |
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); | |
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); | |
return keyFactory.generatePublic(spec); | |
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) { | |
e.printStackTrace(); | |
return null; | |
} | |
} | |
} |
when i run below :
String result = null;
String g = null;
try {
result = new Pgp().encrypt("slkdfjlks");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
try {
g = new Pgp().decrypt(result);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
i get this error :
javax.crypto.BadPaddingException: data hash wrong
and exception is because of this line in decrypt function
decryptedBytes = cipher1.doFinal(Base64.decode(result, Base64.DEFAULT));
public String decrypt(String result)
throws NoSuchAlgorithmException,
NoSuchPaddingException,
InvalidKeyException,
IllegalBlockSizeException,
BadPaddingException {
cipher1 = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
cipher1.init(Cipher.DECRYPT_MODE, privateKey);
decryptedBytes = cipher1.doFinal(Base64.decode(result, Base64.DEFAULT));
decrypted = new String(decryptedBytes);
return decrypted;
}
when i run below :
String result = null; String g = null; try { result = new Pgp().encrypt("slkdfjlks"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } try { g = new Pgp().decrypt(result); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); }
i get this error :
javax.crypto.BadPaddingException: data hash wrong
and exception is because of this line in decrypt function
decryptedBytes = cipher1.doFinal(Base64.decode(result, Base64.DEFAULT));
public String decrypt(String result) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { cipher1 = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding"); cipher1.init(Cipher.DECRYPT_MODE, privateKey); decryptedBytes = cipher1.doFinal(Base64.decode(result, Base64.DEFAULT)); decrypted = new String(decryptedBytes); return decrypted; }
If you are using a hardcoded private string then you must check that
start/begin is same as pkcs8Pem = pkcs8Pem.replace("-----BEGIN PRIVATE KEY-----", "");
and end/completes with the pkcs8Pem = pkcs8Pem.replace("-----END PRIVATE KEY-----", "");
i get this error on decryption :
com.android.org.bouncycastle.jcajce.provider.util.BadBlockException: unable to decrypt block
at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.getOutput(CipherSpi.java:553)
at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineDoFinal(CipherSpi.java:498)
at javax.crypto.Cipher.doFinal(Cipher.java:2056)
at com.example.magicchatapp.utils.security.RSACipher.decrypt(RSACipher.java:106)
at com.example.magicchatapp.presentation.fragment.SingleChatThreadFragment
Excellent coding .
you can use below code for creating PRIVATE KEY from a string: