How to encrypt decrypt with RSA keys in java - java

I need to replace the encrypt and decrypt step from Unix to java code with the rsaprivatekey.pem and rsapublickey.pem keys generated with openssl
I generate the keys
openssl genrsa -out /tmp/rsaprivatekey.pem -des3 1024
openssl rsa -in /tmp/rsaprivatekey.pem -pubout -out /tmp/rsapublickey.pem
i use the keys in unix (i need do it in java)
echo "Text to encript"| openssl rsautl -encrypt -inkey /tmp/rsapublickey.pem -pubin -out out.enc
openssl rsautl -decrypt -inkey /tmp/rsaprivatekey.pem -in out.enc
This was my attempt to do it
public static void main(String[] args) {
Base64 base64 = new Base64();
String TextStream = "this is the input text";
byte[] Cipher;
System.out.println("input:\n" + TextStream);
Cipher = encrypt(TextStream);
System.out.println("cipher:\n" + base64.encodeAsString(Cipher));
System.out.println("decrypt:\n" + decrypt(Cipher));
}
private static byte[] encrypt(String Buffer) {
try {
Cipher rsa;
rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.ENCRYPT_MODE, getPrivateKey(PRIVATE_PATH));
return rsa.doFinal(Buffer.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String decrypt(byte[] buffer) {
try {
Cipher rsa;
rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.DECRYPT_MODE, getPrivateKey(PUBLIC_PATH));
byte[] utf8 = rsa.doFinal(buffer);
return new String(utf8, "UTF8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static PrivateKey getPrivateKey(String filename) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
public static PublicKey getPublicKey(String filename) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
but it not works, the PKCS8EncodedKeySpec/X509EncodedKeySpec are not correct... but i do not know what to put

Solution:
Thanks to #Sanjeev, using the bouncy castle API, I was able to encrypt/decrypt with the keys generated by openssl
public static void main(String[] args) throws IOException {
Security.addProvider(new BouncyCastleProvider());
KeyPair keyPair = readKeyPair(new File(PRIVATE_PATH), "pass");
// if the private key is not encripted, pass can be anything.
Key publickey = readPublicKey(new File(PUBLIC_PATH), "pass");
Base64 base64 = new Base64();
String text = "this is the input text";
byte[] encripted;
System.out.println("input:\n" + text);
encripted = encrypt(keyPair.getPublic(), text);
System.out.println("cipher:\n" + base64.encodeAsString(encripted));
System.out.println("decrypt:\n" + decrypt(keyPair.getPrivate(), encripted));
}
private static byte[] encrypt(Key pubkey, String text) {
try {
Cipher rsa;
rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.ENCRYPT_MODE, pubkey);
return rsa.doFinal(text.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String decrypt(Key decryptionKey, byte[] buffer) {
try {
Cipher rsa;
rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.DECRYPT_MODE, decryptionKey);
byte[] utf8 = rsa.doFinal(buffer);
return new String(utf8, "UTF8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static KeyPair readKeyPair(File privateKey, String keyPassword) throws IOException {
FileReader fileReader = new FileReader(privateKey);
PEMReader r = new PEMReader(fileReader, new DefaultPasswordFinder(keyPassword.toCharArray()));
try {
return (KeyPair) r.readObject();
} catch (IOException ex) {
throw ex;
} finally {
r.close();
fileReader.close();
}
}
private static Key readPublicKey(File privateKey, String keyPassword) throws IOException {
FileReader fileReader = new FileReader(privateKey);
PEMReader r = new PEMReader(fileReader, new DefaultPasswordFinder(keyPassword.toCharArray()));
try {
return (RSAPublicKey) r.readObject();
} catch (IOException ex) {
throw ex;
} finally {
r.close();
fileReader.close();
}
}

I think you're having problems reading PEM files. The JPA doesn't directly support the PEM format. You have two options, either convert them to DER encoded files (you can use openSSL to do this) or the you can use the bouncy castle API to read (or write) PEM files. the class you'd be interested in is called PEMReader (and maybe also PEMWriter). Here is the Javadoc on the bouncycastle website.

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);

How to read public/private key files for encryption when they are Base64?

I'm trying to learn RSA public/private key-pair encryption in Java.
I have the code below working. It generates a private & public key pair, writes the keys to disk, encrypts the string with the public key from disk, the decrypts with the private key from disk, and then it outputs the decrypted string.
All works great.
The next thing is, I want the key files to be the readable "-----BEGIN RSA PRIVATE KEY-----" type of key files ... so I wrote the method saveKeysToDiskBase64.
The problem is, when I write the files using saveKeysToDiskBase64, the methods that read the key files fail. That is loadPrivateKey and loadPublicKey can't read the Base64 files.
What am I missing?
public class EncryptionTest1 {
public void execute() throws Exception {
String filename = "test1";
KeyPair keyPair = EncryptionUtil.generateKeyPair();
EncryptionUtil.saveKeysToDisk(filename, keyPair);
// EncryptionUtil.saveKeysToDiskBase64(filename, keyPair);
String pvtKeyFilename = filename+".key";
String pubKeyFilename = filename+".pub";
PrivateKey privateKey = EncryptionUtil.loadPrivateKey(pvtKeyFilename);
byte[] bPrivateKey = privateKey.getEncoded();
PublicKey publicKey = EncryptionUtil.loadPublicKey(pubKeyFilename);
byte[] bPublicKey = publicKey.getEncoded();
String sOriginal = "hi this is plain text";
byte[] encryptedData = EncryptionUtil.encrypt(bPublicKey, sOriginal.getBytes());
byte[] decryptedData = EncryptionUtil.decrypt(bPrivateKey, encryptedData);
String sEncrypted = new String(encryptedData);
String sDecrypted = new String(decryptedData);
System.out.println("sOriginal = "+sOriginal);
System.out.println("sEncrypted = "+sEncrypted);
System.out.println("sDecryptedData = "+sDecrypted);
}
public static void main(String[] args) {
try {
new EncryptionTest1().execute();
} catch (Exception x) {
x.printStackTrace();
}
}
}
...
public class EncryptionUtil {
private static final String ALGORITHM = "RSA";
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
// 2048 is keysize
keyGen.initialize(2048, random);
KeyPair generateKeyPair = keyGen.generateKeyPair();
return generateKeyPair;
}
public static void saveKeysToDisk(String name, KeyPair keyPair) {
try {
String privateFileName = name+".key";
FileOutputStream out1 = new FileOutputStream(privateFileName);
out1.write(keyPair.getPrivate().getEncoded());
out1.close();
String publicFileName = name+".pub";
FileOutputStream out2 = new FileOutputStream(publicFileName);
out2.write(keyPair.getPublic().getEncoded());
out2.close();
} catch (Exception x) {
x.printStackTrace();
}
}
public static void saveKeysToDiskBase64(String name, KeyPair keyPair) {
try {
Base64.Encoder encoder = Base64.getEncoder();
String privateFileName = name+".key";
Writer out = new FileWriter(privateFileName);
out.write("-----BEGIN RSA PRIVATE KEY-----\n");
out.write(encoder.encodeToString(keyPair.getPrivate().getEncoded()));
out.write("\n-----END RSA PRIVATE KEY-----\n");
out.close();
String publicFileName = name+".pub";
Writer out2 = new FileWriter(publicFileName);
out2.write("-----BEGIN RSA PUBLIC KEY-----\n");
out2.write(encoder.encodeToString(keyPair.getPublic().getEncoded()));
out2.write("\n-----END RSA PUBLIC KEY-----\n");
out2.close();
} catch (Exception x) {
x.printStackTrace();
}
}
public static PrivateKey loadPrivateKey(String keyFile) {
PrivateKey pvt = null;
try {
/* Read all bytes from the private key file */
Path path = Paths.get(keyFile);
byte[] bytes = Files.readAllBytes(path);
/* Generate private key. */
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
pvt = kf.generatePrivate(ks);
} catch (Exception x) {
x.printStackTrace();
}
return pvt;
}
public static PublicKey loadPublicKey(String keyFile) {
PublicKey pub = null;
try {
/* Read all the public key bytes */
Path path = Paths.get(keyFile);
byte[] bytes = Files.readAllBytes(path);
/* Generate public key. */
X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
pub = kf.generatePublic(ks);
} catch (Exception x) {
x.printStackTrace();
}
return pub;
}
public static byte[] encrypt(byte[] publicKey, byte[] inputData) throws Exception {
PublicKey key = KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(publicKey));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedBytes = cipher.doFinal(inputData);
return encryptedBytes;
}
public static byte[] decrypt(byte[] privateKey, byte[] inputData) throws Exception {
PrivateKey key = KeyFactory.getInstance(ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(privateKey));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedBytes = cipher.doFinal(inputData);
return decryptedBytes;
}
}
Great thanks to #President James K. Polk who gave me the correct answer in a comment.
Here is the Base64 related code that that worked for me ...
private static String PRIVATE_HEADER = "-----BEGIN PRIVATE KEY-----\n";
private static String PRIVATE_FOOTER = "\n-----END PRIVATE KEY-----\n";
private static String PUBLIC_HEADER = "-----BEGIN PUBLIC KEY-----\n";
private static String PUBLIC_FOOTER = "\n-----END PUBLIC KEY-----\n";
public static void saveKeysToDiskBase64(String name, KeyPair keyPair) {
try {
Base64.Encoder encoder = Base64.getEncoder();
String privateFileName = name+".key";
Writer out = new FileWriter(privateFileName);
out.write(PRIVATE_HEADER);
out.write(encoder.encodeToString(keyPair.getPrivate().getEncoded()));
out.write(PRIVATE_FOOTER);
out.close();
String publicFileName = name+".pub";
Writer out2 = new FileWriter(publicFileName);
out2.write(PUBLIC_HEADER);
out2.write(encoder.encodeToString(keyPair.getPublic().getEncoded()));
out2.write(PUBLIC_FOOTER);
out2.close();
} catch (Exception x) {
x.printStackTrace();
}
}
public static PrivateKey loadPrivateKeyBase64(String keyFile) {
PrivateKey pvt = null;
try {
/* Read all bytes from the private key file */
Path path = Paths.get(keyFile);
byte[] bytes = Files.readAllBytes(path);
String s = new String(bytes);
s = s.replace(PRIVATE_HEADER, "");
s = s.replace(PRIVATE_FOOTER, "");
bytes = Base64.getDecoder().decode(s.getBytes());
/* Generate private key. */
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
pvt = kf.generatePrivate(ks);
} catch (Exception x) {
x.printStackTrace();
}
return pvt;
}
public static PublicKey loadPublicKeyBase64(String keyFile) {
PublicKey pub = null;
try {
/* Read all the public key bytes */
Path path = Paths.get(keyFile);
byte[] bytes = Files.readAllBytes(path);
String s = new String(bytes);
s = s.replace(PUBLIC_HEADER, "");
s = s.replace(PUBLIC_FOOTER, "");
bytes = Base64.getDecoder().decode(s.getBytes());
/* Generate public key. */
X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
pub = kf.generatePublic(ks);
} catch (Exception x) {
x.printStackTrace();
}
return pub;
}

How to convert java OpenSSLRSAPrivateCrtKey to PKCS1 format

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()));

javax.crypto.BadPaddingException: Decryption error

Here is the error I have got when run my Encode & Decode Class.
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:365)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:391)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at RSAEncDecDemo.decryptData(RSAEncDecDemo.java:64)
at RSAEncDecDemo.main(RSAEncDecDemo.java:47)
java.lang.NullPointerException
at java.lang.String.<init>(String.java:556)
at RSAEncDecDemo.decryptData(RSAEncDecDemo.java:70)
at RSAEncDecDemo.main(RSAEncDecDemo.java:47)
Here is the source code of RSAEncDecDemo.java class file.
public class RSAEncDecDemo {
private static final String PUBLIC_KEY_FILE = "lk.public.key";
private static final String PRIVATE_KEY_FILE = "lk.private.key";
#SuppressWarnings("restriction")
public static void main(String[] args) throws IOException {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
writeStringkey(PUBLIC_KEY_FILE,new BASE64Encoder().encode(publicKey.getEncoded()));
writeStringkey(PRIVATE_KEY_FILE,new BASE64Encoder().encode(privateKey.getEncoded()));
String demoString = "123346";
RSAEncDecDemo rsa = new RSAEncDecDemo();
String decrypted = rsa.decryptData(demoString);
String msisdn = decrypted.substring(0,decrypted.indexOf("|"));
} catch (Exception e) {
e.printStackTrace();
}
}
private String decryptData(String strData) throws IOException {
byte[] data = DatatypeConverter.parseHexBinary(strData);
byte[] descryptedData = null;
try {
PrivateKey privateKey = readPrivateKeyFromFile(PRIVATE_KEY_FILE);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
descryptedData = cipher.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
}
return new String(descryptedData);
}
#SuppressWarnings("restriction")
public PrivateKey readPrivateKeyFromFile(String fileName)throws IOException, NoSuchAlgorithmException,InvalidKeySpecException {
String publicK = readStringKey(fileName);
byte[] keyBytes = new BASE64Decoder().decodeBuffer(publicK);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory fact = KeyFactory.getInstance("RSA");
return fact.generatePrivate(keySpec);
}
public PrivateKey readPrivateKeyFromFileold(String fileName)throws IOException {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream(new File(fileName));
ois = new ObjectInputStream(fis);
BigInteger modulus = (BigInteger) ois.readObject();
BigInteger exponent = (BigInteger) ois.readObject();
RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey privateKey = fact.generatePrivate(rsaPrivateKeySpec);
return privateKey;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ois != null) {
ois.close();
if (fis != null) {
fis.close();
}
}
}
return null;
}
public static void writeStringkey(String fileName, String data) {
try {
FileWriter out = new FileWriter(new File(fileName));
out.write(data);
out.close();
} catch (IOException e) {
}
}
public static String readStringKey(String fileName) {
BufferedReader reader = null;
StringBuffer fileData = null;
try {
fileData = new StringBuffer(2048);
reader = new BufferedReader(new FileReader(fileName));
char[] buf = new char[1024];
int numRead = 0;
while ((numRead = reader.read(buf)) != -1) {
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
buf = new char[1024];
}
reader.close();
} catch (Exception e) {
} finally {
if (reader != null) {
reader = null;
}
}
return fileData.toString();
}
}
Where is mistaken point.? Decryption part is give that error.
Whole class uploaded here
LINK TO SOURCE CODE
-Thanks
In principle a ciphertext should be indistinguishable from random. That said, ciphers do place constraints on the domain (size and possible values). In the case of RSA PKCS#1 - which is the default mode for "RSA" within the Oracle provider - the output must be precisely the key size (in bytes). Furthermore, the value must be smaller than the modulus.
Now assume that you've just shown us a demo value (because the exception doesn't match the input) and the size of the ciphertext is correct. In that case you would get an unpadding exception when either:
the private key doesn't match the public key used;
the wrong padding mode (e.g. OAEP) was used to create the ciphertext;
the ciphertext was altered (e.g. due to an invalid conversion to a string).
You would have to try until you find the culprit, without the required information we cannot test this for you.

Decrypted string not the same as pre encrypted string

I have the following pieces of code:
Globals
public static PublicKey pubKey;
public static PrivateKey privKey;
public static Cipher cip;
Main
public static void main(String[] args) throws Exception {
//Generate the keys
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair kp = kpg.genKeyPair();
Key publicKey = kp.getPublic();
Key privateKey = kp.getPrivate();
KeyFactory fact = KeyFactory.getInstance("RSA");
cip = Cipher.getInstance("RSA/ECB/NoPadding");
// Store Public Key.
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
publicKey.getEncoded());
FileOutputStream fos = new FileOutputStream("public.key");
fos.write(x509EncodedKeySpec.getEncoded());
fos.close();
// Store Private Key.
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
privateKey.getEncoded());
fos = new FileOutputStream("private.key");
fos.write(pkcs8EncodedKeySpec.getEncoded());
fos.close();
//Get the public and private keys out of their files
getPubAndPrivateKey();
//Check if the keys gotten out of the files are the same as the generated files (this returns truetrue)
System.out.print(publicKey.equals(pubKey));
System.out.print(privateKey.equals(privKey));
byte[] text = "This is my super secret secret".getBytes();
encryptToFile("encrypted.txt", text );
decryptToFile("encrypted.txt", "decrypted.txt");
}
Getting the keys from the files
private static void getPubAndPrivateKey() throws IOException, Exception {
// Read Public Key.
File filePublicKey = new File("public.key");
FileInputStream fis = new FileInputStream("public.key");
byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
fis.read(encodedPublicKey);
fis.close();
// Read Private Key.
File filePrivateKey = new File("private.key");
fis = new FileInputStream("private.key");
byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
fis.read(encodedPrivateKey);
fis.close();
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
encodedPublicKey);
pubKey = keyFactory.generatePublic(publicKeySpec);
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
encodedPrivateKey);
privKey = keyFactory.generatePrivate(privateKeySpec);
}
Encrypting
public static void encryptToFile(String fileName, byte[] data)
throws IOException {
try {
cip.init(Cipher.ENCRYPT_MODE, privKey);
byte[] cipherData = cip.doFinal(data);
String encryptedData = cipherData.toString();
BufferedWriter out = new BufferedWriter(new FileWriter(fileName));
out.write(encryptedData);
out.close();
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
}
}
Decrypting
private static void decryptToFile(String string, String string2)
throws Exception {
try {
File encryptedFile = new File("encrypted.txt");
byte[] encrypted = getContents(encryptedFile).getBytes();
cip = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cip.init(Cipher.DECRYPT_MODE, pubKey);
byte[] cipherData = cip.doFinal(encrypted);
String decryptedData = cipherData.toString();
BufferedWriter out = new BufferedWriter(new FileWriter(
"decrypted.txt"));
out.write(decryptedData);
out.close();
} catch (Exception e) {
throw e;
}
}
Things I already checked
The data used in the decryption is the same as in the encrypted file
The generated keys are the same as the ones gotten from the file
The encryption and decryption both don't give errors
Results
Original string:
My super secret secret
The encryption results in:
[B#1747b17
The decryption results in:
[B#91a4fb
If you print out a byte array via toString() method you are getting a value that is totally independent of the content.
Therefore the values [B#1747b17 [B#91a4fb are just garbage that does not tell you anything.
If you want to print the content of a byte array convert it to Base64 or hex-string.
System.out.println(new sun.misc.BASE64Encoder().encode(myByteArray));
A hex string can be generated by using org.apache.commons.codec.binary.Hex from Apache Commons Codec library.
I agree with the above answer.
I would like to add that in your case, you can simply use FileOutputStream, write the bytes to a file -
For example:
public static void encryptToFile(String fileName, byte[] data)
throws IOException {
FileOutputStream out = null;
try {
cip.init(Cipher.ENCRYPT_MODE, privKey);
byte[] cipherData = cip.doFinal(data);
out = new FileOutputStream(fileName);
out.write(cipherData);
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ex) {
}
}
}
}

Categories

Resources