Skip to content

Instantly share code, notes, and snippets.

@balzss
Last active October 30, 2022 05:23
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save balzss/a287b7ef1e7b6abcf069d522dcc53ffc to your computer and use it in GitHub Desktop.
Save balzss/a287b7ef1e7b6abcf069d522dcc53ffc to your computer and use it in GitHub Desktop.
Utility library for RSA cryptography on 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.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
public class CryptoUtil {
private final static String CRYPTO_METHOD = "RSA";
private final static int CRYPTO_BITS = 2048;
public static Map<String, String> generateKeyPair()
throws NoSuchAlgorithmException,
NoSuchPaddingException,
InvalidKeyException,
IllegalBlockSizeException,
BadPaddingException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(CRYPTO_METHOD);
kpg.initialize(CRYPTO_BITS);
KeyPair kp = kpg.genKeyPair();
PublicKey publicKey = kp.getPublic();
PrivateKey privateKey = kp.getPrivate();
Map map = new HashMap<String, String>();
map.put("privateKey", Base64.encodeToString(privateKey.getEncoded(), Base64.DEFAULT));
map.put("publicKey", Base64.encodeToString(publicKey.getEncoded(), Base64.DEFAULT));
return map;
}
public static String encrypt(String plain, String pubk)
throws NoSuchAlgorithmException,
NoSuchPaddingException,
InvalidKeyException,
IllegalBlockSizeException,
BadPaddingException,
InvalidKeySpecException {
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, stringToPublicKey(pubk));
byte[] encryptedBytes = cipher.doFinal(plain.getBytes(StandardCharsets.UTF_8));
return Base64.encodeToString(encryptedBytes, Base64.DEFAULT);
}
public static String decrypt(String result, String privk)
throws NoSuchPaddingException,
NoSuchAlgorithmException,
BadPaddingException,
IllegalBlockSizeException,
InvalidKeySpecException,
InvalidKeyException {
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, stringToPrivateKey(privk));
byte[] decryptedBytes = cipher.doFinal(Base64.decode(result, Base64.DEFAULT));
return new String(decryptedBytes);
}
private static PublicKey stringToPublicKey(String publicKeyString)
throws InvalidKeySpecException,
NoSuchAlgorithmException {
byte[] keyBytes = Base64.decode(publicKeyString, Base64.DEFAULT);
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(CRYPTO_METHOD);
return keyFactory.generatePublic(spec);
}
private static PrivateKey stringToPrivateKey(String privateKeyString)
throws InvalidKeySpecException,
NoSuchAlgorithmException {
byte [] pkcs8EncodedBytes = Base64.decode(privateKeyString, Base64.DEFAULT);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);
KeyFactory kf = KeyFactory.getInstance(CRYPTO_METHOD);
return kf.generatePrivate(keySpec);
}
}
Map keyPair = CryptoUtil.generateKeyPair();
String publicKey = (String)keyPair.get("publicKey");
String privateKey = (String)keyPair.get("privateKey");
String encryptedMessage = CryptoUtil.encrypt("Test message...", publicKey);
String decryptedMessage = CryptoUtil.decrypt(encryptedMessage, privateKey);
@dicarlomagnus
Copy link

dicarlomagnus commented Apr 6, 2021

Hello, This is helpful but what to do if we need BEGIN END part too along with the key. The encryption method gives an error in parsing the Public key. Any solution for this?

Yeah, I had the same problem, I just replaced those words with a blank space like this:

fun clearPem(publicKey: String): String {
      return publicKey.replace("-----BEGIN PUBLIC KEY-----", "")
          .replace("-----END PUBLIC KEY-----", "").replace(Regex("\\s+"), "")
          .replace(Regex("[ \\t\\n]+"), "")

  }

@S-Ambika
Copy link

S-Ambika commented Apr 7, 2021

Thank you for the reply but what I mean is I want BEGIN - END part along with the key as it will be required at the decryption end. I do not want to replace it. What I know is we can use RSAPublicKeySpec instead of X509EncodedKeySpec for this kind of key but for this, we need modulus and exponent & I do not know how to get them and then how to decrypt the whole encoded data.

@luongchung
Copy link

Thank you so much !!!!

@Aji2
Copy link

Aji2 commented Oct 30, 2022

thanks for saving my hours

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment