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) {
}
}
}
}
Related
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);
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;
}
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.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I want to encrypt test.txt file I am using this java class for encryption and decryption.In My directory I have three files private.txt for save private key and public.txt for public key and test.txt is for encryption.
package EncryptionDecryption;
import java.io.BufferedInputStream;
public class EncryptionUtil {
/**
* String to hold name of the encryption algorithm.
*/
public static final String ALGORITHM = "RSA";
/**
* String to hold the name of the private key file.
*/
public static final String PRIVATE_KEY_FILE = "private.txt";
/**
* String to hold name of the public key file.
*/
public static final String PUBLIC_KEY_FILE = "public.txt";
public static void generateKey() {
try {
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
keyGen.initialize(1024);
final KeyPair key = keyGen.generateKeyPair();
File privateKeyFile = new File(PRIVATE_KEY_FILE);
File publicKeyFile = new File(PUBLIC_KEY_FILE);
// Create files to store public and private key
if (privateKeyFile.getParentFile() != null) {
privateKeyFile.getParentFile().mkdirs();
}
privateKeyFile.createNewFile();
if (publicKeyFile.getParentFile() != null) {
publicKeyFile.getParentFile().mkdirs();
}
publicKeyFile.createNewFile();
// Saving the Public key in a file
ObjectOutputStream publicKeyOS = new ObjectOutputStream(
new FileOutputStream(publicKeyFile));
publicKeyOS.writeObject(key.getPublic());
System.out.println("public"+key.getPublic().getEncoded());
publicKeyOS.close();
// Saving the Private key in a file
ObjectOutputStream privateKeyOS = new ObjectOutputStream(
new FileOutputStream(privateKeyFile));
privateKeyOS.writeObject(key.getPrivate());
System.out.println("private"+key.getPrivate().getEncoded());
//System.out.println(key.getPrivate());
privateKeyOS.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean areKeysPresent() {
File privateKey = new File(PRIVATE_KEY_FILE);
File publicKey = new File(PUBLIC_KEY_FILE);
if (privateKey.exists() && publicKey.exists()) {
return true;
}
return false;
}
public static byte[] encrypt(byte[]bs, PublicKey key) {
byte[] cipherText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(ALGORITHM);
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(bs);
} catch (Exception e) {
e.printStackTrace();
}
return cipherText;
}
public static String decrypt(byte[] text, PrivateKey key) {
byte[] dectyptedText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(ALGORITHM);
// decrypt the text using the private key
cipher.init(Cipher.DECRYPT_MODE, key);
dectyptedText = cipher.doFinal(text);
} catch (Exception ex) {
ex.printStackTrace();
}
return new String(dectyptedText);
}
public static void main(String[] args)throws IOException {
System.out.println("Hai");
try {
// Check if the pair of keys are present else generate those.
generateKey();
File f=new File("test.txt");
byte[] contents = new byte[(int)f.length()];
BufferedInputStream bis = null;
try
{
bis = new BufferedInputStream(new FileInputStream(f));
DataInputStream dis = new DataInputStream(bis);
dis.readFully(contents);
}
finally
{
if(bis != null)
{
bis.close();
}
}
// final String originalText = "Text to be encrypted";
// Encrypt the string using the public key
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
final PublicKey publicKey = (PublicKey) inputStream.readObject();
final byte[] cipherText = encrypt(contents, publicKey);
inputStream.close();
// Decrypt the cipher text using the private key.
ObjectInputStream inputStream1 = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
final PrivateKey privateKey = (PrivateKey) inputStream1.readObject();
final String plainText = decrypt(cipherText, privateKey);
// Printing the Original, Encrypted and Decrypted Text
System.out.println("Original Text: " + contents.toString());
System.out.println("Encrypted Text: " +cipherText);
System.out.println("Decrypted Text: " + plainText);
inputStream.close();
inputStream1.close();
} catch (Exception e) {
e.printStackTrace();
}
finally
{
}
}
}
I got this error when debugging
I
public[B#f73c1
private[B#15b9e68
javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes
at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at EncryptionDecryption.EncryptionUtil.encrypt(EncryptionUtil.java:122)
at EncryptionDecryption.EncryptionUtil.main(EncryptionUtil.java:193)
java.lang.IllegalArgumentException: Null input buffer
at javax.crypto.Cipher.doFinal(DashoA13*..)
at EncryptionDecryption.EncryptionUtil.decrypt(EncryptionUtil.java:147)
at EncryptionDecryption.EncryptionUtil.main(EncryptionUtil.java:198)
java.lang.NullPointerException
at java.lang.String.<init>(String.java:593)
at EncryptionDecryption.EncryptionUtil.decrypt(EncryptionUtil.java:153)
at EncryptionDecryption.EncryptionUtil.main(EncryptionUtil.java:198)
There is a good basic example here on encrypting a String with. This example uses DES but I belive the principle is the same and so will hopefully help get you started.
The Stack Trace you have posted is very similar to the issue faced in this post. There is an accepted answer there if you have a look which may provide you with a fix also.
Good luck!
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.