How to convert java OpenSSLRSAPrivateCrtKey to PKCS1 format - java

CipherText
i5SvmG2TbtZfkWdwJ5qeaYzvLlQknY3uMvZxSEwhBdRcXKHjgzrRk6XLDCEG9ZtZDGDA7iB3tFhLPMisfqGZvSSrcBfiV8b71+qzWVDNW9EedVShk6kaeEN6rw4UgVi6P5PvrDMn6pmYmLWCjtuFWrmboCvvYgI+FJurhlbsQESkA5oDYirjS8L0wnsQB/TnnQ5UPY2xfOBdY2MJpUSTyIjJPhI40GST8YWjXEMkJeDV/1zuKuK55RHCDF5AdTMEvgvvRnGhN2Fzh+rsDziHqVS9d8FmrtjdU445F6ki0d8DkaeFfrofptxGIncqfuukKSXpSp4cPLvM3LxtRvp+Aw==
Code to decrypt
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp2 = kpg.generateKeyPair();
generatedPub = kp2.getPublic();
generatedPvt = kp2.getPrivate();
public String rsaDecrypt(String encrypted) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, generatedPvt);
byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted.getBytes()));
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
Error
javax.crypto.BadPaddingException: error:04000089:RSA routines:OPENSSL_internal:PKCS_DECODING_ERROR
Also, if I try printing the private key as :
generatedPvt.toString()
I get the following :
OpenSSLRSAPrivateCrtKey{modulus=c7544bf521bbdd7db52dd28bd3c6f694214dc2356b905edd2730b631d11be9aea703692c2db690e6725da65737b5ec511c13668d1735bfbbc2519e0d33a67b41b289bae6ea71903af91e4f12c6e8660614ef12cd439293a0a38f564fd8f19a3e38f9e2defa269d0bcf0f53159bba1b4fd539ad934fb691e860113be53901de5a10d0c0e3ceaec3715841bc6e56b7738336e8df95a989b61175b06d70d349dcb4a031acf5b25647a1d77f6e6e11efc66e98bb321430f148a63c103a0a59e94b147a4fb49a9ecb0b23603a6ceed6e6e298650667cd61de71455bd4f95767444d89bcf485cc47a297b5306a60a14f77a3fbc19552c5fddfa5cfa2e68020e245ad91,publicExponent=10001}
While I was expecting the PKCS#8 formatted key to be printed. How do i get the key printed in the PKCS#8 format ?
And why am i getting the padding error as shown above ?

byte[] original = cipher.doFinal(encrypted.getBytes());
remove Base64.decodeBase64 from both encrypt and decrypt methods
if you want to convert key to string then use
String keyString= Base64.encodeBase64String(key.getEncoded());
RSA Implementation
public static void main(String[] args) {
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp2 = kpg.generateKeyPair();
PublicKey publicKey = kp2.getPublic();
PrivateKey privateKey = kp2.getPrivate();
NewClass nc = new NewClass();
byte[] encrypt=nc.rsaEncrypt("hi",publicKey);
byte[] decrypt=nc.rsaDecrypt(encrypt,privateKey);
String decryptString = new String(decrypt);
System.out.println("decryptString = " + decryptString);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(NewClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
public byte[] rsaDecrypt(byte[] encrypted,PrivateKey privateKey) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] original = cipher.doFinal(encrypted);
return original;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public byte[] rsaEncrypt(String message,PublicKey publicKey) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] original = cipher.doFinal(message.getBytes());
return original;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
When encoding and decoding is done along with encrypt and decrypt the order must be
Encryption
cipher.doFinal(Base64.encodeBase64(message.getBytes()));
Decryption
Base64.decodeBase64(cipher.doFinal(cipher.getBytes()));

Related

Unable to decrypt using RSA encryption through stored keys in files

I am trying to encrypt and decrypt a message within java using RSA encryption. We have stored our keys as bytes in their own respective files, and load the contents of these files to be used as the keys in our encryption/ decryption methods. However, when I compile the code, I receive error:
javax.crypto.IllegalBlockSizeException: Data must be longer than 256
bytes.
Our generateKeys and encryption/ decryption methods read:
import java.security.*;
import java.security.spec.*;
import java.util.Base64;
import java.util.Scanner;
import java.io.*;
import java.nio.file.*;
import javax.crypto.Cipher;
public class Encryption {
static File filepath = new File("..\\..\\..\\");
public static void generateKeyPair() throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
KeyPair pair = generator.generateKeyPair();
PublicKey publicKey = pair.getPublic();
PrivateKey privateKey = pair.getPrivate();
DataOutputStream dos = null;
try {
dos = new DataOutputStream(new FileOutputStream(filepath.getAbsolutePath()
+ "rsaPublicKey"));
dos.write(publicKey.getEncoded());
dos.flush();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
try {
dos = new DataOutputStream(new FileOutputStream(filepath.getAbsolutePath()
+ "rsaPrivateKey"));
dos.write(privateKey.getEncoded());
dos.flush();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (dos != null)
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static KeyPair getKeyPair() throws Exception {
byte[] keyBytesPublic = Files.readAllBytes(Paths.get(filepath + "rsaPublicKey"));
byte[] keyBytesPrivate = Files.readAllBytes(Paths.get(filepath + "rsaPrivateKey"));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(keyBytesPublic);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(keyBytesPrivate);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
KeyPair keys = new KeyPair(publicKey, privateKey);
return keys;
}
public static byte[] Encrypt (String plainText, PublicKey publicKey) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] cipherText = cipher.doFinal(plainText.getBytes());
return cipherText;
}
public static String Decrypt (byte[] cipherTextArray, PrivateKey privateKey) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedTextArray = cipher.doFinal(cipherTextArray);
return new String(decryptedTextArray);
}
}
We then call these methods, where we receive our error:
KeyPair pair = Encryption.getKeyPair();
PublicKey publicKey = pair.getPublic();
PrivateKey privateKey = pair.getPrivate();
// plugin.getLogger().info(chatMessage);
ids = chatMessage.substring(chatMessage.length() - 9, chatMessage.length() - 1);
plugin.getLogger().info(ids);
chatMessage = chatMessage.substring(0, chatMessage.length() - 10);
chatMessage = Encryption.Decrypt(chatMessage.getBytes(), privateKey);
server.broadcastMessage(chatMessage);
byte[] ctArray = Encryption.Encrypt("Sent message successfully.", publicKey);
encrypted_return = Base64.getEncoder().encodeToString(ctArray);
send(encrypted_return);

Im getting a RSA bad padding exception

I cannot seem to find a awnser to why my program wont work
I have already checked the keys and they are the same
here is my error
javax.crypto.BadPaddingException: Decryption error null 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:363) at
com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389) at
javax.crypto.Cipher.doFinal(Cipher.java:2165) at
com.thatmadhacker.finlaybot.client.FinlayBot.rsadecrypt(FinlayBot.java:234)
at
com.thatmadhacker.finlaybot.client.MainThread.run(MainThread.java:16)
at java.lang.Thread.run(Thread.java:745)
here is mv key generator code
KeyPairGenerator kpg = null;
try {
kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.genKeyPair();
publicKey = kp.getPublic();
privateKey = kp.getPrivate();
KeyFactory fact = KeyFactory.getInstance("RSA");
pub = fact.getKeySpec(kp.getPublic(),
RSAPublicKeySpec.class);
priv = fact.getKeySpec(kp.getPrivate(),
RSAPrivateKeySpec.class);
saveToFile("public.key", pub.getModulus(),
pub.getPublicExponent());
saveToFile("private.key", priv.getModulus(),
priv.getPrivateExponent());
} catch (Exception e1) {
e1.printStackTrace();
}
here are my decryption and encryption methods
public static String rsadecrypt(byte[] text) {
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance("RSA");
// decrypt the text using the private key
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] dectyptedText = cipher.doFinal(text);
return new String(dectyptedText);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static byte[] rsaencrypt(String text) {
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance("RSA");
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, clientKey);
byte[] cipherText = cipher.doFinal(text.getBytes());
return cipherText;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
and then here is my server thread that performing a key exchange
Scanner in = new Scanner(s.getInputStream());
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
java.io.PrintWriter unEncryptOut = new java.io.PrintWriter(s.getOutputStream(), true);
unEncryptOut.println(FinlayBot.pub.getModulus());
unEncryptOut.println(FinlayBot.pub.getPublicExponent());
unEncryptOut.flush();
BigInteger modulus = new BigInteger(in.nextLine());
BigInteger exponent = new BigInteger(in.nextLine());
RSAPublicKeySpec pub = new RSAPublicKeySpec(modulus,exponent);
try {
FinlayBot.clientKey = KeyFactory.getInstance("RSA").generatePublic(pub);
//System.out.println(modulus +" "+exponent);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
and the client
System.out.println("Waiting For KeyPair!");
pubKeyModulus = new BigInteger(in.nextLine().trim());
pubKeyExponent = new BigInteger(in.nextLine().trim());
//System.out.println(pubKeyModulus+" "+pubKeyExponent);
System.out.println("Recieved KeyPair!");
RSAPublicKeySpec pub = new RSAPublicKeySpec(pubKeyModulus, pubKeyExponent);
try {
serverPublicKey = KeyFactory.getInstance("RSA").generatePublic(pub);
System.out.println(pub.getModulus()+" "+pub.getPublicExponent());
writer.println(pub.getModulus());
writer.println(pub.getPublicExponent());
writer.flush();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}

Decryption returns an empty string when encrypting text in Android

I'm trying to save few text fields securely. For that I'm trying to encrypt and decrypt the content. This is the code:
public class SecureStorage {
public String getPassword() {
if(!isRooted()) {
String password = pref.getPassword("");
System.out.println("pass getPass: " + password);
return password.isEmpty() ? password : new String(decrypt(Base64.decode(password, Base64.DEFAULT)));
} else
return "";
}
public void setPassword(String passwordStr) {
if(!isRooted()) {
byte[] password = encrypt(passwordStr.getBytes());
pref.setPassword(password == null ? "" : Base64.encodeToString(password, Base64.DEFAULT));
}
}
private SecretKey generateKey() {
// Generate a 256-bit key
final int outputKeyLength = 256;
try {
SecureRandom secureRandom = new SecureRandom();
// Do *not* seed secureRandom! Automatically seeded from system entropy.
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(outputKeyLength, secureRandom);
return keyGenerator.generateKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
private byte[] getRawKey(byte[] key) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG", "Crypto");
secureRandom.setSeed(key);
keyGenerator.init(128, secureRandom); // 192 and 256 bits may not be available
SecretKey secretKey = keyGenerator.generateKey();
byte[] rawKey = secretKey.getEncoded();
return rawKey;
}
/** The method that encrypts the string.
#param toEncrypt The string to be encrypted.
#return The encrypted string in bytes. */
//****************************************
private byte[] encrypt(byte[] toEncrypt) {
byte[] encryptedByte = new String().getBytes();
try {
SecretKeySpec secretKeySpec = new SecretKeySpec(getRawKey(Utils.generateUID().getBytes()), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
encryptedByte = cipher.doFinal(toEncrypt);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return encryptedByte;
}
//**************************************
/** The method that decrypts the string.
#param encryptedByte The string to be encrypted.
#return The decrypted string in bytes. */
//****************************************
private byte[] decrypt(byte[] encryptedByte) {
byte[] decryptedByte = new String().getBytes();
try {
SecretKeySpec secretKeySpec = new SecretKeySpec(getRawKey(Utils.generateUID().getBytes()), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
decryptedByte = cipher.doFinal(encryptedByte);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return decryptedByte;
}
}
I'm able to encrypt the Text.
I'm using SharedPreferences to store the encrypted text and getting the sharedprefs to decrypt the text and give it to a TextView. But in the getPassword() I'm getting the SharedPreference value and trying to decrypt if there is any value in the SharedPrefs. I'm getting the SharedPrefs into a string (password) and trying to decrypt it, but I'm unable to! I'm getting an empty String!
CBC mode needs an initialization vector (IV) in order to operate. The IV is there to randomize the ciphertext and prevent an attacker from determining whether previous plaintexts had the same prefix as the current one.
Since you're not generating any IV, it will be generated for you. A wrong IV only affects the first block (first 16 bytes for AES). If your plaintext is shorter than a block, then this will lead to completely different decryption and then the padding cannot be removed with a probability of roughly 255/256.
The IV is not supposed to be secret. It is common to prepend it to the ciphertext and slice it off before decryption.
public byte[] encrypt(byte[] toEncrypt) throws Exception {
try {
SecretKeySpec secretKeySpec = new SecretKeySpec(getRawKey(Utils.generateUID().getBytes()), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] iv = cipher.getIV();
byte[] ct = cipher.doFinal(toEncrypt);
byte[] result = new byte[ct.length + iv.length];
System.arraycopy(iv, 0, result, 0, iv.length);
System.arraycopy(ct, 0, result, iv.length, ct.length);
return result;
} catch(...) {...}
return new byte[0];
}
public byte[] decrypt(byte[] encryptedByte) throws Exception {
try {
SecretKeySpec secretKeySpec = new SecretKeySpec(getRawKey(Utils.generateUID().getBytes()), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[cipher.getBlockSize()];
byte[] ct = new byte[encryptedByte.length - cipher.getBlockSize()];
System.arraycopy(encryptedByte, 0, iv, 0, cipher.getBlockSize());
System.arraycopy(encryptedByte, cipher.getBlockSize(), ct, 0, ct.length);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
return cipher.doFinal(ct);
} catch (...) {...}
return new byte[0];
}
The problem with this might be that the ciphertext is bigger than anticipated (16 bytes additionally for the IV). If you can make sure that an attacker doesn't get any useful information from determining that previous plaintexts had the same prefix, then you could use a static IV. But be aware that this is usually not that great of an idea and should only be done if you really need that space.
private static final byte[] IV = new byte[16];
...
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(IV));
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(IV));

Decryption error on Android 4.4

I have algorithm of encryption\ decryption files:
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = new SecureRandom();
sr.setSeed(seed);
kgen.init(sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
It works great, but on Android 4.4 (api 19) I have strangely exception
javax.crypto.BadPaddingException: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
What is it?
Here what I got: http://www.logikdev.com/2010/11/01/encrypt-with-php-decrypt-with-java/
public class AES2 {
private static final String TRANSFORMATION = "AES/CFB8/NoPadding";
private static final String ALGO_MD5 = "MD5";
private static final String ALGO_AES = "AES";
/**
* See http://www.logikdev.com/2012/12/12/md5-generates-31-bytes-instead-of-32/ form more detail.
*
* #param input
* #return
* #throws NoSuchAlgorithmException
*/
private static String md5(String input) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance(ALGO_MD5);
byte[] messageDigest = md.digest(input.getBytes());
BigInteger number = new BigInteger(1, messageDigest);
return String.format("%032x", number);
}
public static String decrypt(String encryptedData, String initialVectorString, String secretKey) {
String decryptedData = null;
try {
String md5Key = md5(secretKey);
SecretKeySpec skeySpec = new SecretKeySpec(md5Key.getBytes(), ALGO_AES);
IvParameterSpec initialVector = new IvParameterSpec(initialVectorString.getBytes());
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, initialVector);
byte[] encryptedByteArray = Base64.decode(encryptedData.getBytes(), Base64.DEFAULT);
byte[] decryptedByteArray = cipher.doFinal(encryptedByteArray);
decryptedData = new String(decryptedByteArray);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return decryptedData;
}
}
So you have to create a initialVectorString (example: "fedcba9876543210"). Hope this help.

read public key invalid key format java

I have code:
public PublicKey read_public_key(String path)
throws IOException, NoSuchAlgorithmException,
InvalidKeySpecException {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
FileInputStream pubKeyStream = new FileInputStream(path);
byte[] pubKeyBytes = new byte[(int)path.length()];
pubKeyStream.read(pubKeyBytes);
pubKeyStream.close();
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(pubKeyBytes);
PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
return pubKey;
}
But I get invalid key format How do I get public key from .pub file? Later I need to:
private static byte[] encrypt(String text, PublicKey key) {
byte[] cipherText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(text.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return cipherText;
}

Categories

Resources