RSA Encryption disparity between Android and Java environments - java

Firstly, apologies for the amount of code I'm about to post. I'm trying to use the RSA public key from my Java application to encrypt a message in an Android app, and then send the ciphertext back to a Java environment for decryption, but upon attempting to decrypt I always get this error:
javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:382)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
...
The ciphertext does contain the correct number of bytes (512), so it's confusing to see a "bad padding" exception. Other similar posts on SO have suggested using "RSA/ECB/PKCS1Padding" as the algorithm, but this does not work.
Annoyingly, encryption and decryption in the Android environment (using Base64.URL_SAFE as the 'base64Type') works just fine, I just can't seem to get the initial encryption working with the public key produced via Java.
I have extracted the bare minimum code into examples, as shown below:
Android Code
private void exampleMethod(){
String messageString = "Why does this not work in Android?";
String serverPubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoApIBIna77xq4j+M2RmyIhsB++41NHcY4KIPfX4VP4ADnkO+7ejbs4le/twrPtYGESVPF9czSMB5bzmTBZtq0jC8oT/6wiDIBlSuzo4fBrGociBIuaOjyG/j3ZhpcWpWPXuzER+ehuQ+8hZkMuJdK9IodqPR+5jmCef4rXoKObwS02LYQ1co5dEmtZVQRmmeYaVnWibd/s1d4KKGvSzXap3YBTf8peH5UGIQrLOTqvX0bo34xFxmj5U0H3xudnnwuVAlQlj9KiHPPABuwNtm1buRKJb5HZhSCveyT/2YAOmQqGrVN/nALtlZyTDZNs//Vp1zb9exSuG0t5xFc+pn4QIDAQAB";
String encryptedMessageString = getUrlEncodedCipherText(messageString, serverPubKey, Base64.NO_WRAP);
/**
* CipherText is ALWAYS the same and does not decrypt: DA_-RpCki-mjF6tSwiP2IhuW2UfPzZC7A9oVTTNptjT73HtROiQZvUC0Z2veJ5VwVx4toolvLErQmKKoQlqELSD756bu8ohEQwgJ4Xsu-3tXv-uEi5a9a_u19WnNLIF7tayDUhFeD2RzNvW895y1v-D30TvQRskNCFJfnjaytr_vmcVv8HrXURCmG6AMltaqdN72zh8p6VkKcjXSLiCApH957GXSqJCRzxbaQwf8X5EJfn8CQrPDGbE3gdhc2_hFwXQNIdxPxrOLtVbaFp9i_4GRWXJ6E2jHttV2bDv_uSVIz3OBzh7EkJiCnl3c904sH8QZae8c3SQyrTxVL7EpIA,,
*/
}
public static String getUrlEncodedCipherText(String plainText, String pubKey, int base64Type){
try {
final PublicKey publicKey = loadPublicKey(pubKey, base64Type);
final byte[] cipherBytes = encrypt(plainText, publicKey);
String cipherText = base64Encode(cipherBytes, base64Type);
String urlEncodedCipherText = urlEncode(cipherText);
return urlEncodedCipherText;
}
catch (Exception e){
e.printStackTrace();
return null;
}
}
public static final String ALGORITHM = "RSA";
public static PublicKey loadPublicKey(String stored, int base64Type) throws GeneralSecurityException {
String pubKey = stored.replace(BEGIN_PUBLIC_KEY, "");
pubKey = pubKey.replace(END_PUBLIC_KEY, "");
byte[] data = Base64.decode(pubKey, base64Type);
X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
KeyFactory fact = KeyFactory.getInstance(ALGORITHM);
PublicKey pub = fact.generatePublic(spec);
return pub;
}
public static byte[] encrypt(String text, PublicKey key) {
byte[] cipherText = null;
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(text.getBytes());
}
catch (Exception e) {
e.printStackTrace();
}
return cipherText;
}
public static String base64Encode(byte[] cipherBytes, int base64Type){
byte[] base64Cipher = Base64.encode(cipherBytes, base64Type);
return new String(base64Cipher);
}
public static String urlEncode(String text){
return text.replace("+", "-").replace("/", "_").replace("=", ",");
}
Java Code
private void exampleMethod(){
String pubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoApIBIna77xq4j+M2RmyIhsB++41NHcY4KIPfX4VP4ADnkO+7ejbs4le/twrPtYGESVPF9czSMB5bzmTBZtq0jC8oT/6wiDIBlSuzo4fBrGociBIuaOjyG/j3ZhpcWpWPXuzER+ehuQ+8hZkMuJdK9IodqPR+5jmCef4rXoKObwS02LYQ1co5dEmtZVQRmmeYaVnWibd/s1d4KKGvSzXap3YBTf8peH5UGIQrLOTqvX0bo34xFxmj5U0H3xudnnwuVAlQlj9KiHPPABuwNtm1buRKJb5HZhSCveyT/2YAOmQqGrVN/nALtlZyTDZNs//Vp1zb9exSuG0t5xFc+pn4QIDAQAB";
String privKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCgCkgEidrvvGriP4zZGbIiGwH77jU0dxjgog99fhU/gAOeQ77t6NuziV7+3Cs+1gYRJU8X1zNIwHlvOZMFm2rSMLyhP/rCIMgGVK7Ojh8GsahyIEi5o6PIb+PdmGlxalY9e7MRH56G5D7yFmQy4l0r0ih2o9H7mOYJ5/itego5vBLTYthDVyjl0Sa1lVBGaZ5hpWdaJt3+zV3gooa9LNdqndgFN/yl4flQYhCss5Oq9fRujfjEXGaPlTQffG52efC5UCVCWP0qIc88AG7A22bVu5EolvkdmFIK97JP/ZgA6ZCoatU3+cAu2VnJMNk2z/9WnXNv17FK4bS3nEVz6mfhAgMBAAECggEBAIax4IchV0jqdbLR9cNK4yfdP0A/7jun+SImg48FLPDy1xi+v9UQZMioV3F88FDEZPrNQdI45wrWI94+wMS5V6BsMHYumOgGGxNo9m8WInrJz5GuJkdHuLMbqNZ6TlSMQOUiVUWWLSAuveOWgOJqriwRhsjDfBmbSBESUbP/wNdxX42RJudKJbVUV07urjFc3VAUrX+Sbj9KMZRe10pOzes7WKq9NMyQuitLcwCPzs2pQoXW1LdZYrVSi6MOqE1WHSL6VAgPx3cHYl7yznhspLmvDgnKTwnVbRo3BBwkxNbpvZXzgJBLEPLUtLqwNLKkU0aSF9MT5TABx4tfCaRQIiECgYEA70980I9mK74tjXlFrMKaLGigjHBss+Q/b7cRAtlQAhVOn0FCqz4Fc4iBri0iPekVIZ09lRehacEstTR8JBImMW2mqGyMwBbPaqQOf6xZ0pIoYb0ODAIjUNTWoBEr72+ko5HjaoQbxeb2QGUhMe/t3M1CMsrETEQTdA+qNP5C61UCgYEAqzOL7sSsNfTYbAF156qPPqx1IyXNqu0wbKa/zufCxGlFJDkaYoYIECKdLbpI2fqJsENqpZHgOnT0+LbqhFn07NIe1zT/zf0rh7w5fqxqy3Srs4+Mj6HwTIC7QpeXjiHxQuVrfi2W2ZatjQi8froxtEj3mpYKHsl0Ia89JSczQl0CgYAqHPXdCe8z8XK4u8esIE7bU8o1DK/EdH1JXpDqzG1NAIzmb6iY1ABHlZUknqKw/GyQjshAjXkFUE5a0RKrkloQRriWWQvn3dvAa4B1rVHdQYVDte5b5KBsYBgo8PynVSFG+6xmmTr996gMKv/NduiH+8MThyVGOpCl0v/j9X63RQKBgEmOhir6eXtdTbdqETyOPamR82o8jddIvauRIYxGa5p0GG7t0fZO3BwCo0HIbhCp4orHDIVC3fJ/2dkazjw7Yk52ISYZ8WaRxig1qQZSEjiEUll97ciwrUxRayO7ejRpRP2XEM5PzCaE5OBZxpM0cLKjPy8+E+8SY0Etx7m01ANJAoGBALUubgeKx1fut80YHLDmxOiTg9olFJi83Lj1TPQ0fRCXdJX6pHCSypBScoXuJYVwuIavHhTf8DPQ6OONq/V3DXKsGLydK/2E5yg+bz3qYfYslb3vDkZovNJDmfoyR0XakWbUTotntUQqodLk8Q9klHKp6oy+MkGY57R5OhIZBGPa";
String message = "Why does this not work in Android?";
String encryptedMessage = getUrlEncodedCipherText(message, pubKey);
try {
byte[] base64Decoded = Base64.decodeBase64(encryptedMessage.getBytes(Charset.forName("UTF-8")));
String decryptedMessage = decrypt(base64Decoded, loadPrivateKey(privKey));
System.out.println("decryptedMessage: " + decryptedMessage);
/**
* This works! Ciphertext always comes out different, as expected, and decodes successfully.
*/
}
catch (Exception e){
e.printStackTrace();
}
}
public static String getUrlEncodedCipherText(String plainText, String pubKey){
try {
final PublicKey publicKey = loadPublicKey(pubKey);
final byte[] cipherBytes = encrypt(plainText, publicKey);
String cipherText = base64Encode(cipherBytes);
String urlEncodedCipherText = urlEncode(cipherText);
return urlEncodedCipherText;
}
catch (Exception e){
e.printStackTrace();
return null;
}
}
public static final String ALGORITHM = "RSA";
public static PublicKey loadPublicKey(String stored) throws GeneralSecurityException {
String pubKey = stored.replace(BEGIN_PUBLIC_KEY, "");
pubKey = pubKey.replace(END_PUBLIC_KEY, "");
byte[] data = Base64.decodeBase64(pubKey);
X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
KeyFactory fact = KeyFactory.getInstance(ALGORITHM);
PublicKey pub = fact.generatePublic(spec);
return pub;
}
public static byte[] encrypt(String text, PublicKey key) {
byte[] cipherText = null;
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(text.getBytes());
}
catch (Exception e) {
e.printStackTrace();
}
return cipherText;
}
public static String decrypt(byte[] encrypted, PrivateKey key) {
byte[] decryptedText = null;
try {
final Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
decryptedText = cipher.doFinal(encrypted);
}
catch (Exception e) {
e.printStackTrace();
return null;
}
return new String(decryptedText);
}
public static String base64Encode(byte[] cipherBytes){
byte[] base64Cipher = Base64.encodeBase64(cipherBytes);
return new String(base64Cipher);
}
public static String urlEncode(String text){
return text.replace("+", "-").replace("/", "_").replace("=", ",");
}
I'm aware that the problem has to be to do with difference in the way Android and Java interpret the RSA algorithm, and/or differences with the Base64 encode/decode, but I'm stumped. Any assistance greatly appreciated.

Solved it! The issue was that I was using the same ALGORITHM String for Cipher, KeyFactory etc. I split this into two different Strings, and the full solution for my problem is...
Android Code
private void exampleMethod(){
String messageString = "This actually works in Java AND Android!";
String serverPubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjS7T3WJ+VLucnUP5WYryeg+hhOjZZl5VxwvJAgo4GrXaXdernTPtmXnOSUlbhd928QRCip7D3rLwJNvGIwhPa6coA+YQnj+aHQC02AvCJP/9jpeNmm5MASZfYFXrdmOrMhAPpDZ4rUk1mqtvpwBkYmW3VbMtG336wT1bAIKPHCZuI2n6glupJvs8gK0NuIoAPRlxiQmQD7NCcRx1Et4JmqOMIRC+HqdGv9GGqC/0PB0Fv6LXi8GdzJQPMdoRLR0rvVykNeIzmcimejoIVjI78XUZeB1hF7p55h6W4C4Xm/PrnzKuXw4lBVehZtRhyIvNO62G/eNEZ3tup1/m+vkzHQIDAQAB";
String encryptedMessageString = getUrlEncodedCipherText(messageString, serverPubKey, Base64.NO_WRAP);
System.out.println("encryptedMessageString: " + encryptedMessageString);
/**
* This works! Ciphertext always comes out different, as expected, and decodes successfully when fed into Java application.
*/
}
public static String getUrlEncodedCipherText(String plainText, String pubKey, int base64Type){
try {
final PublicKey publicKey = loadPublicKey(pubKey, base64Type);
final byte[] cipherBytes = encrypt(plainText, publicKey);
String cipherText = base64Encode(cipherBytes, base64Type);
String urlEncodedCipherText = urlEncode(cipherText);
return urlEncodedCipherText;
}
catch (Exception e){
e.printStackTrace();
return null;
}
}
public static final String ALGORITHM = "RSA";
public static final String CIPHER_ALGORITHM = "RSA/ECB/PKCS1Padding";
public static PublicKey loadPublicKey(String stored, int base64Type) throws GeneralSecurityException {
String pubKey = stored.replace(BEGIN_PUBLIC_KEY, "");
pubKey = pubKey.replace(END_PUBLIC_KEY, "");
byte[] data = Base64.decode(pubKey, base64Type);
X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
KeyFactory fact = KeyFactory.getInstance(ALGORITHM);
PublicKey pub = fact.generatePublic(spec);
return pub;
}
public static byte[] encrypt(String text, PublicKey key) {
byte[] cipherText = null;
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(text.getBytes());
}
catch (Exception e) {
e.printStackTrace();
}
return cipherText;
}
public static String base64Encode(byte[] cipherBytes, int base64Type){
byte[] base64Cipher = Base64.encode(cipherBytes, base64Type);
return new String(base64Cipher);
}
public static String urlEncode(String text){
return text.replace("+", "-").replace("/", "_").replace("=", ",");
}
Java Code
private void exampleMethod(){
String pubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjS7T3WJ+VLucnUP5WYryeg+hhOjZZl5VxwvJAgo4GrXaXdernTPtmXnOSUlbhd928QRCip7D3rLwJNvGIwhPa6coA+YQnj+aHQC02AvCJP/9jpeNmm5MASZfYFXrdmOrMhAPpDZ4rUk1mqtvpwBkYmW3VbMtG336wT1bAIKPHCZuI2n6glupJvs8gK0NuIoAPRlxiQmQD7NCcRx1Et4JmqOMIRC+HqdGv9GGqC/0PB0Fv6LXi8GdzJQPMdoRLR0rvVykNeIzmcimejoIVjI78XUZeB1hF7p55h6W4C4Xm/PrnzKuXw4lBVehZtRhyIvNO62G/eNEZ3tup1/m+vkzHQIDAQAB";
String privKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCNLtPdYn5Uu5ydQ/lZivJ6D6GE6NlmXlXHC8kCCjgatdpd16udM+2Zec5JSVuF33bxBEKKnsPesvAk28YjCE9rpygD5hCeP5odALTYC8Ik//2Ol42abkwBJl9gVet2Y6syEA+kNnitSTWaq2+nAGRiZbdVsy0bffrBPVsAgo8cJm4jafqCW6km+zyArQ24igA9GXGJCZAPs0JxHHUS3gmao4whEL4ep0a/0YaoL/Q8HQW/oteLwZ3MlA8x2hEtHSu9XKQ14jOZyKZ6OghWMjvxdRl4HWEXunnmHpbgLheb8+ufMq5fDiUFV6Fm1GHIi807rYb940Rne26nX+b6+TMdAgMBAAECggEAOHrlUwmWFHvBmcCZvlKx0lbyfONSJXvTwP9b+K7x5u2dYDFpfEhL4zwxZGwuaw4M3TqhDCeboDnhjD1HtLgcXarPfU/KkiRLmRKxRkTd9ENcwnCqu38odMVPHpEA06nn0O1P9Je+C0TgZvHyhtLHVf3vLB+0Ce2KJUhQYZHZgp7dBt0jgsGlEvQTtc1q3UtElNYbcPdLhg16Dcvw93+C+CWizUxHKl2VAxYBz5fGBxa+Cc6xbj4OGd0mvK9Z+71cX8sgp+WIdSV3a2SZrwYq8XxdtJJfdOwPc6LE56Ul9y3fE/biG8DM8ysu7g4C2K1tjKBTq1Rzz4NBCaGwkWQwGQKBgQDCX5nOiHYi0OYoE3WEVYVuEaf/YljurMiU4xYsy3bXzI42S+iKfVHz+/tvTrXSE0n6AdJnDHyP7mncFZodaurYR90S9VW3P+aOGoysmOmBRWW30xyIZ1g5+PJ9xPzoBfyc/AGHO5w5roY7Gg5myUC+UbucFU+9/JHUVoGV8yFz+wKBgQC58f8iY37sXf/sguv0YHpUV1suPWT90kxC25eRQz0lHWIIw4gfGXI7Tf2vtx7hUPK1z3X9lPiTsqmZIRKPrvykD8djmpfZEOzZlLxxhHUZMZppx19xSsgHaespCZir68aytBWn7FOVpehJP7MWaJurg03V8Cv0NSPU5JhN/j8xxwKBgQCkb6I78oAWtilvz/6EJKGL244HZJkd2bibFH4HCV4R9HB/CLrCpoB1a0BsCueQwFa+FVp9aTfbv/N4iCHoLzJcJHeneTu5mmqe32ERBw/MF/yUhhnGX79o0+25brQSSjZKTHuyf0CMH9RZHZL/a9TE7XpM8k6SyKBKRaC9TYGIjwKBgDZG10x4coIYZi3pgWqSBuM7pJf4v9P/YNdbNgDm+aAt1YHtYXyCdv+solJ6R39Jm69KYYylwXGLg0n5h2t9jq1tFayTYaOw9xIEAoW4Pl4eRo597fQp+f2AA261KGV2q0danb+okjVqekV3XJU778S+zSeXtZzRLiZkm7iYcGXdAoGAUEbRAsopG+blDBmuC5Fhr7Grof9lw/zRgfl516n9oujOmDY8Sl4F7jHkgKzOL1CpvMbRswr6G3tmpJMYGNy0HVX4n4QAiIvEraLUtLlh7LotUiU8zzjniK7HPANoOsQxEi6iUR6jWRf0LKgckE9aaUJjvljj1Hr4PbFpny2gjD4=";
String message = "This actually works in Java AND Android!";
String encryptedMessage = getUrlEncodedCipherText(message, pubKey);
try {
byte[] base64Decoded = Base64.decodeBase64(encryptedMessage.getBytes(Charset.forName("UTF-8")));
String decryptedMessage = decrypt(base64Decoded, loadPrivateKey(privKey));
System.out.println("decryptedMessage: " + decryptedMessage);
/**
* This works! Ciphertext always comes out different, as expected, and decodes successfully.
*/
}
catch (Exception e){
e.printStackTrace();
}
}
public static String getUrlEncodedCipherText(String plainText, String pubKey){
try {
final PublicKey publicKey = loadPublicKey(pubKey);
final byte[] cipherBytes = encrypt(plainText, publicKey);
String cipherText = base64Encode(cipherBytes);
String urlEncodedCipherText = urlEncode(cipherText);
return urlEncodedCipherText;
}
catch (Exception e){
e.printStackTrace();
return null;
}
}
public static final String ALGORITHM = "RSA";
public static final String CIPHER_ALGORITHM = "RSA/ECB/PKCS1Padding";
public static PublicKey loadPublicKey(String stored) throws GeneralSecurityException {
String pubKey = stored.replace(BEGIN_PUBLIC_KEY, "");
pubKey = pubKey.replace(END_PUBLIC_KEY, "");
byte[] data = Base64.decodeBase64(pubKey);
X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
KeyFactory fact = KeyFactory.getInstance(ALGORITHM);
PublicKey pub = fact.generatePublic(spec);
return pub;
}
public static byte[] encrypt(String text, PublicKey key) {
byte[] cipherText = null;
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(text.getBytes());
}
catch (Exception e) {
e.printStackTrace();
}
return cipherText;
}
public static String decrypt(byte[] encrypted, PrivateKey key) {
byte[] decryptedText = null;
try {
final Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
decryptedText = cipher.doFinal(encrypted);
}
catch (Exception e) {
e.printStackTrace();
return null;
}
return new String(decryptedText);
}
public static String base64Encode(byte[] cipherBytes){
byte[] base64Cipher = Base64.encodeBase64(cipherBytes);
return new String(base64Cipher);
}
public static String urlEncode(String text){
return text.replace("+", "-").replace("/", "_").replace("=", ",");
}

Related

BadPaddingException when trying to decrypt a text in Base64 encrypted in AES in ECB

i'm trying to do the 7° challeng of cryptopals and i have to decrypt a file Base64 that was encrypted with the AES in ECB mode. So, i found this code that work with the tutoria stirngs, but when i try with the given data in exercise it give me back the error:
Error while decrypting: javax.crypto.BadPaddingException: Given final
block not properly padded. Such issues can arise if a bad key is used
during decryption.
Process finished with exit code 0
this is the code:
public class ES7 {
private static SecretKeySpec secretKey;
private static byte[] key;
public static void main(String[] args) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, IOException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
String file = readBase64("C:\\Users\\Huawei\\OneDrive\\Desktop\\Lavoro\\Esercizi\\src\\ES7.txt");
String res = decrypt(file,"YELLOW SUBMARINE"); --> this gave error of key
// final String secretKey = "ssshhhhhhhhhhh!!!!";
// String encryptedString= "Tg2Nn7wUZOQ6Xc+1lenkZTQ9ZDf9a2/RBRiqJBCIX6o=";
// String decryptedString = decrypt(encryptedString, secretKey) ; --> this work
}
public static void setKey(final String myKey) {
MessageDigest sha = null;
try {
key = myKey.getBytes("UTF-8");
sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16);
secretKey = new SecretKeySpec(key, "AES");
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public static String decrypt(final String strToDecrypt, final String secret) {
try {
setKey(secret);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)));
} catch (Exception e) {
System.out.println("Error while decrypting: " + e.toString());
}
return null;
}
private static String readBase64(String file) {
String filetext = "";
String line;
try
{
BufferedReader input = new BufferedReader(new FileReader(new File(file)));
while ((line = input.readLine()) != null)
{
filetext += line;
}
input.close();
} catch (IOException e){
e.printStackTrace();
}
return filetext;
}
}

Reconstruct private key

I am generating Asymmetric public key and private using the code below.
public static KeyPair generateRSAKkeyPair()
throws Exception {
SecureRandom secureRandom = new SecureRandom();
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(
2048, secureRandom);
return keyPairGenerator
.generateKeyPair();
}
public static byte[] do_RSAEncryption(
String plainText,
PublicKey publicKey)
throws Exception {
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(
Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(
plainText.getBytes());
}
public static String do_RSADecryption(
byte[] cipherText,
PrivateKey privateKey)
throws Exception {
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.DECRYPT_MODE,
privateKey);
byte[] result = cipher.doFinal(cipherText);
return new String(result);
}
public static PublicKey getKey(String key) {
try {
byte[] byteKey = Base64.getDecoder().decode(key.getBytes());
X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(byteKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(X509publicKey);
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static PrivateKey getPrivateKey(String key) {
try {
byte[] byteKey = Base64.getDecoder().decode(key.getBytes());
X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(byteKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(X509publicKey);
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
This works as expected.
String plainText = "This is the PlainText. I want to Encrypt using RSA.";
byte[] cipherText = do_RSAEncryption(plainText, keypair.getPublic());
String decryptedText = do_RSADecryption(cipherText, keypair.getPrivate());
Now, I am storing the generated the generated public key and private key in a string and trying to encrypt and decrypt and it is failing.
String base64EncodedEncryptionKey = DatatypeConverter.printBase64Binary(keypair.getPublic().getEncoded()));
String base64EccodedDecryptionKey = DatatypeConverter.printBase64Binary(keypair.getPrivate().getEncoded()));
PublicKey pubKey = getKey(base64EncodedEncryptionKey);
byte[] cipherText1 = do_RSAEncryption(plainText, pubKey);
System.out.println("Encrypted Text ===> "+ DatatypeConverter.printHexBinary(cipherText1));
PrivateKey privateKey = getPrivateKey(base64EccodedDecryptionKey);
String decryptedText1 = do_RSADecryption(cipherText1,privateKey);
System.out.println("DecryptedText ====>>> "+decryptedText1);
Error:-
java.security.spec.InvalidKeySpecException: Only RSAPrivate(Crt)KeySpec and PKCS8EncodedKeySpec supported for RSA private keys
at java.base/sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:389)
at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:247)
at java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:390)
at com.apple.ist.alloy.memsqlloader.service.Asymmetric.getPrivateKey(Asymmetric.java:96)
at com.apple.ist.alloy.memsqlloader.service.Asymmetric.main(Asymmetric.java:135)
Exception in thread "main" java.security.InvalidKeyException: No installed provider supports this key: (null)
at java.base/javax.crypto.Cipher.chooseProvider(Cipher.java:930)
at java.base/javax.crypto.Cipher.init(Cipher.java:1286)
at java.base/javax.crypto.Cipher.init(Cipher.java:1223)
at com.apple.ist.alloy.memsqlloader.service.Asymmetric.do_RSADecryption(Asymmetric.java:68)
at com.apple.ist.alloy.memsqlloader.service.Asymmetric.main(Asymmetric.java:137)
Private keys are encoded with PKCS8EncodedKeySpec. You should replace X509EncodedKeySpec with that.

AES Encryption and Decryption (JAVA)

I want to check my result of encryption and decryption with this website
https://8gwifi.org/CipherFunctions.jsp How do I input in the secret key on the website?
This is my java code.
public static void main(String[] args) throws Exception {
final String secretKey = "PASSWORD";
String originalString = "Java Web Developer";
String encryptedString = AESUtils.encrypt(originalString, secretKey) ;
String decryptedString = AESUtils.decrypt(encryptedString, secretKey) ;
System.out.println("Original : " + originalString); //Original : Java Web Developer
System.out.println("Encryption : " + encryptedString); //Encryption : 43Ak2VHK368eandGGYWX2WvbcimGGAEsPdCSjEatjR0=
System.out.println("Decryption : " + decryptedString); //Decryption : Java Web Developer
}
public class AESUtils {
private static SecretKeySpec secretKey;
private static byte[] key;
public static void setKey(String myKey)
{
MessageDigest sha = null;
try {
key = myKey.getBytes("UTF-8");
sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16);
secretKey = new SecretKeySpec(key, "AES");
byte encoded[] = secretKey.getEncoded();
/*
* Encodes the specified byte array into a String using Base64 encoding
* scheme
*/
String encodedKey = Base64.getEncoder().encodeToString(encoded);
System.out.println("SecretKey: " + encodedKey); //SecretKey: ESu3kTBHkd3PaS4p/VzxSQ==
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public static String encrypt(String strToEncrypt, String secret)
{
try
{
setKey(secret);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
}
catch (Exception e)
{
System.out.println("Error while encrypting: " + e.toString());
}
return null;
}
public static String decrypt(String strToDecrypt, String secret)
{
try
{
setKey(secret);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)));
}
catch (Exception e)
{
System.out.println("Error while decrypting: " + e.toString());
}
return null;
}
}
I tried inputting the secret key with "ESu3kTBHkd3PaS4p/VzxSQ==", But the result of encryption does not match the result of encryption from the java program.
My Java program retured encryption to be 43Ak2VHK368eandGGYWX2WvbcimGGAEsPdCSjEatjR0=

How do I encrypt a message and then I decryot it on another device with javax.crypto.cipher using AES

I have a problem with my code. I want to encrypt a message using a key made from passphrase. Then I want to send it (or use it somewhere, whatever) in String form (the encrypted one), and after that I want to decrypt it only by knowing the passphrase.
I wrote the code below, but I receive either IllegalBlockSizeException or BadPaddingException. I thought that badding would be took care by padding.
Here is my code:
Constructor and initialization:
public class AES_Cipher {
private String keyString;
private byte[] byteKey;
private SecretKey key;
Cipher c;
public AES_Cipher(String keyString){
this.keyString = keyString.toString();
}
public void init() throws InitializtionFailedException{
try{
c = Cipher.getInstance("AES/ECB/PKCS5Padding");
byteKey = keyString.getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
byteKey = sha.digest(byteKey);
byteKey = Arrays.copyOf(byteKey, 16);
key = new SecretKeySpec(byteKey, "AES");
}catch(NoSuchAlgorithmException e){
throw new InitializtionFailedException();
}
}
Encrypt:
public String encrypt(String text) throws EncryptionException{
try{
c.init(Cipher.ENCRYPT_MODE, key);
byte[] tmp = c.doFinal( text.getBytes("UTF-8"));
return new String(tmp, "UTF-8");
}catch(IllegalBlockSizeException e){
throw new EncryptionException();
}
}
Decrypt:
public String decrypt(String text) throws DecryptionException{
try{
//byte[] decordedValue = new BASE64Decoder().decodeBuffer(text);
// tried too use it but with poor outcome
//c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, key);
byte[] tmp1 = text.getBytes("UTF-8");
//byte[] tmp = c.doFinal("aaaaaaaaaaaaaaaa".getBytes());
//this returns BadPaddingException
byte[] tmp = c.doFinal(text.getBytes());
return new String(tmp, "UTF-8");
}catch(IllegalBlockSizeException e){
throw new DecryptionException();
}
}
Of course there are some more exceptions.
Also, I would like to later use this code on android, and It doesn't need to be AES if there is some other Ciphers that are maybe less effective but less troublesome. But not simple XOR if that's not too much too ask.
Thank you in advance.
Ok. Seems to work now thanks to Artjom B.
Constructor and inicialization:
public class AES_Cipher {
private String keyString;
private byte[] byteKey;
private SecretKey key;
Cipher c;
public AES_Cipher(String keyString){
this.keyString = keyString.toString();
}
public void init() throws InitializtionFailedException{
try{
c = Cipher.getInstance("AES/ECB/PKCS5Padding");
byteKey = keyString.getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
byteKey = sha.digest(byteKey);
byteKey = Arrays.copyOf(byteKey, 16);
key = new SecretKeySpec(byteKey, "AES");
}catch(NoSuchAlgorithmException e){
throw new InitializtionFailedException();
}
}
Encryption:
public String encrypt(String text) throws EncryptionException{
try{
c.init(Cipher.ENCRYPT_MODE, key);
byte[] textByte = text.getBytes("UTF-8");
byte[] tmp = c.doFinal(textByte);
String return1 = Base64.encodeToString(tmp, Base64.DEFAULT);
return return1;
} // of course there is some exceptions catched down there
Decryption:
public String decrypt(String text) throws DecryptionException{
try{
c.init(Cipher.DECRYPT_MODE, key);
byte[] textByte = Base64.decode(text, Base64.DEFAULT);
byte[] tmp = c.doFinal(textByte);
return new String(tmp, "UTF-8");
}catch(IllegalBlockSizeException e){
Log.d("Exception", "IllegalBlockSizeException");
throw new DecryptionException();
} // wrote DecryptionException myself.
// also there is more Exceptions below
}

AES encryption returning different values on different machines

My AES encryption program is returning different encrypted values on different machines. Can anyone please help on finding out what needs to be done to ensure the same encrypted value is returned on any machine the program is run..
private static SecretKeySpec secret;
private static String seed;
private static String text;
private static String salt = "Salt123";
private static int pswdIterations = 65536;
private static int keySize = 256;
/**
*
* #param mySeed
*/
public static void setSeed(String mySeed) {
try {
byte[] saltBytes = salt.getBytes("UTF-8");
PBEKeySpec spec = new PBEKeySpec(mySeed.toCharArray(), saltBytes,
pswdIterations, keySize);
SecretKeyFactory factory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
SecretKey secretKey = factory.generateSecret(spec);
secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
}
public static String getEncryptedStringFor(String text) {
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] encryptedData = cipher.doFinal(text.getBytes("UTF-8"));
return new String(Base64.encodeBase64(encryptedData));
} catch (Exception e) {
System.out.println("Error while encrypting: " + e.toString());
}
return null;
}
public static String getDecryptedStringFor(String text) {
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secret);
return (new String(cipher.doFinal(Base64
.decodeBase64(text.getBytes("UTF-8")))));
} catch (Exception e) {
System.out.println("Error while decrypting: " + e.toString());
}
return null;
}
Some sample values
seed : seed123
text : #text!
Encrypted value : RoVE3KsjzN0nNxCNsNpRPg==
seed : seed!!
text : #text123!
Encrypted value :X6pfUKCVXXrAEyqKko/kFQ==
The only thing I can see in the code is the following line:
return (new String(cipher.doFinal(Base64.decodeBase64(text.getBytes("UTF-8")))));
Now it looks like this is actually returning a String after decoding with UTF-8. But it doesn't: it uses the platform default:
return (new String(
cipher.doFinal(
Base64.decodeBase64(
text.getBytes("UTF-8")
)
)
));
Of course, the first ( is superfluous anyway, so try this:
byte[] ciphertext = Base64.decodeBase64(text.getBytes("UTF-8"));
byte[] plaintext = cipher.doFinal(ciphertext);
return new String(plaintext, "UTF-8");
Note that you can also use import static java.nio.charsets.StandardCharsets.UTF_8 nowadays, which lets you do away with the exception as well. I wish they would do the same for StandardCiphers.AES_CBC_PKCS7PADDING :)

Categories