Encrypting and decrypting with public and private RSA keys in JAVA - java

I am trying to do a simple encrypt/decrypt with asymmetric keys in JAVA using RSA keys and i have some troubles. This is my code :
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.RandomAccessFile;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
public class AsymmetricCipherTestFiles
{
public static void main(String[] unused) throws Exception
{
// 1. Generating keys
System.out.println("Generating keys ...");
PublicKey publicKey;
PrivateKey privateKey;
// generateKeys(512);
// 2. read them from file
System.out.println("Read from file");
publicKey = readPublicKeyFromFile("public.key");
privateKey = readPrivateKeyFromFileTest("private.key");
System.exit(0);
// 3. encrypt data
System.out.println("Encrypt data");
byte[] dataBytes = "some string to encrypt".getBytes();
byte[] encBytes = encrypt(dataBytes, publicKey, "RSA");
printByteArray(encBytes);
// 4. decrypt data
byte[] decBytes = decrypt(encBytes, privateKey, "RSA");
printByteArray(decBytes);
// String decryptedThing = convert(decBytes);
}
public static void generateKeys(int keySize) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException
{
// Create key
// System.out.println("Generating keys");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(keySize);
KeyPair kp = kpg.genKeyPair();
/*
Key publicKey = kp.getPublic();
Key privateKey = kp.getPrivate();
*/
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(),RSAPublicKeySpec.class);
RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(),RSAPrivateKeySpec.class);
saveKeyToFile("bin/public.key", pub.getModulus(), pub.getPublicExponent());
saveKeyToFile("bin/private.key", priv.getModulus(),priv.getPrivateExponent());
// System.out.println("Keys generated");
}
private static byte[] encrypt(byte[] inpBytes, PublicKey key,String xform) throws Exception
{
Cipher cipher = Cipher.getInstance(xform);
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(inpBytes);
}
private static byte[] decrypt(byte[] inpBytes, PrivateKey key,String xform) throws Exception
{
Cipher cipher = Cipher.getInstance(xform);
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(inpBytes);
}
public static String convert(byte[] data)
{
StringBuilder sb = new StringBuilder(data.length);
for (int i = 0; i < data.length; ++ i)
{
if (data[i] < 0) throw new IllegalArgumentException();
sb.append((char) data[i]);
}
return sb.toString();
}
public static PublicKey readPublicKeyFromFile(String keyFileName) throws IOException
{
InputStream in = (InputStream) AsymmetricCipherTestFiles.class.getResourceAsStream(keyFileName);
ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream( in ));
try
{
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);
return pubKey;
}
catch (Exception e)
{
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
}
}
public static PrivateKey readPrivateKeyFromFile(String keyFileName) throws IOException
{
InputStream in = (InputStream) AsymmetricCipherTestFiles.class.getResourceAsStream(keyFileName);
ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream( in ));
try
{
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
byte[] byteArray = new byte[512];
byteArray = m.toByteArray();
KeySpec keySpec = new PKCS8EncodedKeySpec(byteArray);
// RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey privateKey = fact.generatePrivate(keySpec);
return privateKey;
}
catch (Exception e)
{
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
}
}
public static PrivateKey readPrivateKeyFromFileTest(String filename) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException
{
RandomAccessFile raf = new RandomAccessFile(filename, "r");
byte[] buf = new byte[(int)raf.length()];
raf.readFully(buf);
raf.close();
PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(buf);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privKey = kf.generatePrivate(kspec);
return privKey;
}
public static void saveKeyToFile(String fileName,BigInteger mod, BigInteger exp) throws IOException
{
ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(fileName)));
try
{
oout.writeObject(mod);
oout.writeObject(exp);
}
catch (Exception e)
{
throw new IOException("Unexpected error", e);
}
finally
{
oout.close();
}
}
public static void printByteArray(byte[] byteArray)
{
int increment = 0;
for(byte b : byteArray)
{
System.out.println("B["+increment+"] = "+b);
increment++;
}
}
}
When i run it it gives me this error :
Generating keys ...
Read from file
Exception in thread "main" java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : DerInputStream.getLength(): lengthTag=109, too big.
at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(Unknown Source)
at java.security.KeyFactory.generatePrivate(Unknown Source)
at AsymmetricCipherTestFiles.readPrivateKeyFromFileTest(AsymmetricCipherTestFiles.java:160)
at AsymmetricCipherTestFiles.main(AsymmetricCipherTestFiles.java:40)
Caused by: java.security.InvalidKeyException: IOException : DerInputStream.getLength(): lengthTag=109, too big.
at sun.security.pkcs.PKCS8Key.decode(Unknown Source)
at sun.security.pkcs.PKCS8Key.decode(Unknown Source)
at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(Unknown Source)
at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(Unknown Source)
at sun.security.rsa.RSAKeyFactory.generatePrivate(Unknown Source)
... 4 more
The thing is that at generating/reading/encrypting with public key everything works smoothly, the error occurs when reading private key and trying to get it into an PrivateKey object.
What i am doing wrong and how i may solve this?
Thanks.

You're saving the key with two writeObject() calls but retreiving it with a single readFully() call. You need to either:
save the key with write(byte[]), supplying the result of getEncoded(), and read it with readFully(), or
save it with writeObject() and read it with readObject().
Not a mixture of the two.

Related

RSA -OAEP encryption and decryption of Symmetric Key file

I am trying to encrypt and decrypt a symmetric key file (256 and 128) using RSAES - OAEP but I am getting error while encrypting :
File Sizes to encrypt: 256 and 128
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import java.util.Arrays;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
public static void main(String[] args) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.generateKeyPair();
String inputPath = "/home/roxane/Music/test_09";
String inFile = "/home/roxane/Downloads/s_key";
String encfile = "/home/roxane/Music/s_key.enc";
// get key pair
PublicKey pub = kp.getPublic();
PrivateKey PrivateKey = kp.getPrivate();
// Write Key Pair
try (FileOutputStream out = new FileOutputStream(inputPath + ".key")) {
out.write(kp.getPrivate().getEncoded());
}
try (FileOutputStream out = new FileOutputStream(inputPath + ".pub")) {
out.write(kp.getPublic().getEncoded());
}
//restore kEys
byte[] pubbytes = Files.readAllBytes(Paths.get(inputPath + ".pub"));
X509EncodedKeySpec ks = new X509EncodedKeySpec(pubbytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pub1 = kf.generatePublic(ks);
byte[] privbytes = Files.readAllBytes(Paths.get(inputPath + ".key"));
PKCS8EncodedKeySpec ks1 = new PKCS8EncodedKeySpec(privbytes);
KeyFactory kf1 = KeyFactory.getInstance("RSA");
PrivateKey pvt = kf1.generatePrivate(ks1);
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-512ANDMGF1PADDING");
cipher.init(Cipher.ENCRYPT_MODE, pvt);
try (FileInputStream in = new FileInputStream(inFile);
FileOutputStream out = new FileOutputStream(encfile)) {
processFile(cipher, in, out);
}
}
static private void processFile(Cipher ci,InputStream in,OutputStream out)
throws javax.crypto.IllegalBlockSizeException,
javax.crypto.BadPaddingException,
java.io.IOException
{
byte[] ibuf = new byte[1024];
int len;
while ((len = in.read(ibuf)) != -1) {
byte[] obuf = ci.update(ibuf, 0, len);
if ( obuf != null ) out.write(obuf);
}
byte[] obuf = ci.doFinal();
if ( obuf != null ) out.write(obuf);
}
Error: Exception in thread "main" java.security.InvalidKeyException: OAEP cannot be used to sign or verify signatures
Requesting help in the code encrytption and decryption of the files compatible with openssl. I am open to use bouncycastle if required

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

InvalidKeyException DER input not a bit string

import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;
public class DJExampleDecryptCode
{
public static void main(String[] args)
{
try
{
String encryptedText = "q3sEN1NZZyseoFy9H3WIwNf9jpGrDTTqh/AticRV2pnb1KZ5lieuK5jw3JgctgYUnTE03xnMcOL50UGKZ4dbYEt5XGCZyNVgh1qVGF7Vgnvi5PKndnpKLcoSUJCcbu/lyLI2P+Zd7ZH0/tRKRn1zqrPAWUH3VjtUt7qkIcdIYyaoHP5I7eiZRk6FL9ugUQJnz8WFgM4mcRJ5Zs/NLdaXKeHMO4nPQBTOLNaPdNxW2MM+qlv0HN/fs4rPMRGUw0xXhjWsmSNqadASfn7UX4fL79CmGyKfm8ol4njZakZbsfes/zstc5Su0swycfFSkjXAjPjvMGdBs5/HSLXYAvQPoA==";
String TextToEncrypt = "Test";
String decryptedString = decrypt(encryptedText);
String encryptedString = encrypt(TextToEncrypt);
//Printing
System.out.println("Decrypted Text: " + decryptedString);
System.out.println("Encrypted Text: " + encryptedString);
}
catch (Exception e)
{
e.printStackTrace();
}
}
//public static String decrypt(String text, String privateKeyString) throws GeneralSecurityException
public static String decrypt(String text) throws GeneralSecurityException
{
String DJPrivateKey = ".....";
PrivateKey privateKey = stringToPrivateKey(DJPrivateKey);
byte[] dectyptedText = null;
try
{
final Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
dectyptedText = cipher.doFinal(base64Decode(text));
}
catch (Exception ex)
{
ex.printStackTrace();
}
return new String(dectyptedText);
}
public static String encrypt(String data) throws GeneralSecurityException
{
String PCMSPublicKey = "MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIV/0v/U5+6pgCAggAMBQGCCqGSIb3DQMHBAhSuqMZCoVAxgSCBMhKaVDCjOS9q0jEc+nUCEKQD73pHte/9nMdTkHbFGpu+1amzpY0YLhgqVTQhDp43amH6IvM3KfmM+9M5i0bXBksa+5la2kVl8Ntw6fzc1xFtcSMLb8CFkk0gV3l6kcKEo1rN2TiH3jGQz43DFHUJbnITWwY3SFCsWPZF2oegTAMSEKhOJ6h9bad3KoqNmqji6hdk9ONhQBarDrZGL9l+8GWnx9TyVxAVltBxzv0DRlqXlKhVkfV2XqkiECcilFHeoaI+cV6W1z8S9kFPdnm93QjCu88l1lG1a5ox4tu4dPHj4u7uVZKuEBkpr7HpF0uL+o+JEflNjUl/BYlS3++l6lfRpOp6mb2VVt1zQgoKVR1wZZeSoEqhJ/r75Krybq4TdXXqs4IdPZmSwIPTVM8n5ZvzUz/F+K46rYIQchz3GPCpKEPI/9+OhqUKtXe2KpPsZtD7hJ7+r1g99MwzEjyET6l7lLuIE2SpKS0wxZB5qb0+92+SfyPwQWIM5tfv1Gs7M8A2MFz9GclXsaGpt+mx0DQPiMkpdoB9e5GbO1PGlP3MWhUmQ6wwIUVVjGryJuvLFL+4psDeUzkdKilG9nPDVSWHLlCx1C3k8hcuJUy1bTihrFprcOEjuzGzmhp3IUQc+5Z4dydM/2AmYFCNmjySRKYZVRBPfPrcVfDo8P1lzlYeXLcWubMlwxyRfv/WjzJkyMlDSiYEEnkcYJrCgeocsU8qJ+yq1QAsTs361Svi2tQ7lJZjp1FtIdvMr+U32eW1Pri+vn4LWdPcPzxbrLHN/daV+l3Ttw493x0R7WMDnhcS8yhd8NlWoh43IzmQDCn33Lek7WS3HmSzTAg6bfxmYZf9Ogn86DR/q2c2ZKwbs3nloHdfkKklOOqgRPic7nP8khsd+pjTULZUDmKa3d0OW8Ps5fTY/GzWrJBLVEoM8bN0w3CUsHixSQOh1pMwJUiyAT/cJPZfru1gtUeNkSJ5u/atc6HaPc6sfrhLF6RWyhIYKyqoM2dyLFC3hi+N0ZLBZwp/tnIou24dtwlJnLvKCinzO0pUTJC2yOwsnfL57h+ikdd3xS9fMWwpiSdNps086japrp12GU9VyBZX8b9QEip/Hxw778OK1x853+WYM978wNPrFwIfWtQpvNZMi8Mt0WXDvfHiG8JK9PKDoS25iV8SrwZScfBTMIi95j419BuhcVca1fi0keEEKaqMzBus4Mgz421Qcy0xv2u81w90qoMyXBwadRODtrJBQIovHBCKVRkxEm64Rr3fCWGjralnKcjxDKa77qakFlFOyNJsplnlC0mc229E19JXlxpcdDlivscE727KLLYu8rPUEWMZY/PA0D9JH+u+52A81ur0vuCnTLF1V0WG8ECJwgVTbIfByPoi+MKuvmW1pvixwBXiIh7as95gVl47HAXmCYOj0bnD0yO/pFSLoiAURl0j2R/c/NtKjz5TQ9F3O3U83UojatwtIyc7xN6Bs+iwTPaBOJrI6Sbgc5yDJPFczhPQDSpFZVtTUSeq1UA7N7mogwQLAqawGBHQJ9JIapMl6uC7Y2nN9O4lYRtbQLBKpZ3xzIk9LrDyT3F/w+c3l/lVUz0X6lz746zNutl/6f6XKI5oeis7/b5rMHHYYE=";
PublicKey publicKey = stringToPublicKey(PCMSPublicKey);
byte[] enctyptedText = null;
try
{
final Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
enctyptedText = cipher.doFinal(base64Decode(data));
}
catch (Exception ex)
{
ex.printStackTrace();
}
return new String(enctyptedText);
}
public static byte[] base64Decode(String encodedString)
{
Base64 myBase64 = new Base64();
return myBase64.decode(encodedString);
}
public static PrivateKey stringToPrivateKey(String privateKeyString) throws GeneralSecurityException
{
byte[] clear = base64Decode(privateKeyString);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(clear);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey priv = fact.generatePrivate(keySpec);
Arrays.fill(clear, (byte) 0);
return priv;
}
public static PublicKey stringToPublicKey(String publicKeyString) throws GeneralSecurityException
{
byte[] clear = base64Decode(publicKeyString);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(clear);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pub = fact.generatePublic(keySpec);
Arrays.fill(clear, (byte) 0);
return pub;
}
}
I have the above java code that does encryption and decryption. The decryption works fine, which uses the private key, but when I ran the encryption part using the public key I hard-coded, I got the below errors,
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DER input not a bit string
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:205)
at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
at DJExampleDecryptCode.stringToPublicKey(DJExampleDecryptCode.java:109)
at DJExampleDecryptCode.encrypt(DJExampleDecryptCode.java:64)
at DJExampleDecryptCode.main(DJExampleDecryptCode.java:26)
Caused by: java.security.InvalidKeyException: IOException: DER input not a bit string
at sun.security.x509.X509Key.decode(X509Key.java:397)
at sun.security.x509.X509Key.decode(X509Key.java:403)
at sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:83)
can anyone give me some suggestions? thanks a lot

ECKeyAgreement in Generating public and private key using ecc

I am working on a concept of encryption and decryption using ecc.
I already generated public and private key. While I am encrypting the text I am getting this error:
java.security.InvalidKeyException: ECKeyAgreement requires ECPrivateKey
at
org.bouncycastle.jce.provider.JCEECDHKeyAgreement.engineInit(JCEECDHKeyAgreement.java:121)
at javax.crypto.KeyAgreement.init(KeyAgreement.java:462)
at javax.crypto.KeyAgreement.init(KeyAgreement.java:436)
at rbl2015.encryec.main(encryec.java:67)
This is my encryption Java file:
import java.io.File;
import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.ECParameterSpec;
import java.security.spec.EllipticCurve;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Scanner;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class encryec
{
KeyPairGenerator kpg;
EllipticCurve curve;
ECParameterSpec ecSpec;
KeyPair aKeyPair;
static KeyAgreement aKeyAgree;
KeyPair bKeyPair;
KeyAgreement bKeyAgree;
KeyFactory keyFac;
static String msg;
public static void main(String args[])
{
Security.addProvider(new BouncyCastleProvider());
Scanner ss=new Scanner(System.in);
try{
String path = "D:\\rp";
File filePublicKey = new File(path+"\\public.key");
FileInputStream fis = new FileInputStream(path+"\\public.key");
byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
fis.read(encodedPublicKey);
fis.close();
// Read Private Key.
File filePrivateKey = new File(path+"\\private.key");
fis = new FileInputStream(path+"\\private.key");
byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
fis.read(encodedPrivateKey);
fis.close();
KeyFactory keyFactory = KeyFactory.getInstance("ECDH");
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
encodedPublicKey);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
aKeyAgree = KeyAgreement.getInstance("ECDH", "BC");
aKeyAgree.init(privateKey); // exception line
aKeyAgree.doPhase(publicKey, true);
byte[] aBys = aKeyAgree.generateSecret();
KeySpec aKeySpec = new DESKeySpec(aBys);
SecretKeyFactory aFactory = SecretKeyFactory.getInstance("DES");
Key aSecretKey = aFactory.generateSecret(aKeySpec);
Cipher aCipher = Cipher.getInstance(aSecretKey.getAlgorithm());
aCipher.init(Cipher.ENCRYPT_MODE, aSecretKey);
byte[] encText = aCipher.doFinal("Its Rahul".getBytes());
System.out.println(Base64.encodeBase64String(encText));
System.out.println(encText);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
I don't know what I am missing. I tried everything that I can to get the ECPrivateKey.
This is the code for generating the public and private key:
import java.io.*;
import java.security.*;
import java.security.spec.*;
public class Rahul {
public static void main(String args[]) {
Rahul rahul = new Rahul();
try {
String path = "D:\\rp";
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
keyGen.initialize(1024);
KeyPair generatedKeyPair = keyGen.genKeyPair();
System.out.println("Generated Key Pair");
rahul.dumpKeyPair(generatedKeyPair);
rahul.SaveKeyPair(path, generatedKeyPair);
KeyPair loadedKeyPair = rahul.LoadKeyPair(path, "DSA");
System.out.println("Loaded Key Pair");
rahul.dumpKeyPair(loadedKeyPair);
} catch (Exception e) {
e.printStackTrace();
return;
}
}
private void dumpKeyPair(KeyPair keyPair) {
PublicKey pub = keyPair.getPublic();
System.out.println("Public Key: " + getHexString(pub.getEncoded()));
PrivateKey priv = keyPair.getPrivate();
System.out.println("Private Key: " + getHexString(priv.getEncoded()));
}
private String getHexString(byte[] b) {
String result = "";
for (int i = 0; i < b.length; i++) {
result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
}
return result;
}
public void SaveKeyPair(String path, KeyPair keyPair) throws IOException {
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
// Store Public Key.
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
publicKey.getEncoded());
FileOutputStream fos = new FileOutputStream(path + "/public.key");
fos.write(x509EncodedKeySpec.getEncoded());
fos.close();
// Store Private Key.
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
privateKey.getEncoded());
fos = new FileOutputStream(path + "/private.key");
fos.write(pkcs8EncodedKeySpec.getEncoded());
fos.close();
}
public KeyPair LoadKeyPair(String path, String algorithm)
throws IOException, NoSuchAlgorithmException,
InvalidKeySpecException {
// Read Public Key.
File filePublicKey = new File(path + "/public.key");
FileInputStream fis = new FileInputStream(path + "/public.key");
byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
fis.read(encodedPublicKey);
fis.close();
// Read Private Key.
File filePrivateKey = new File(path + "/private.key");
fis = new FileInputStream(path + "/private.key");
byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
fis.read(encodedPrivateKey);
fis.close();
// Generate KeyPair.
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
encodedPublicKey);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
encodedPrivateKey);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
return new KeyPair(publicKey, privateKey);
}
}
You should try and create an EC(DH) key pair instead of a DSA key pair. Although the general method of operation is identical (both ECDSA and DSA are based on the Diffie-Hellman problem) the key types are certainly not.

How to sign string with private key

How can I get the signature of a string using SHA1withRSA if I already have the Private Key as byte[] or String?
I guess what you say is you know the key pair before hand and want to sign/verify with that.
Please see the following code.
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import sun.misc.BASE64Encoder;
public class MainClass {
public static void main(String[] args) throws Exception {
KeyPair keyPair = getKeyPair();
byte[] data = "test".getBytes("UTF8");
Signature sig = Signature.getInstance("SHA1WithRSA");
sig.initSign(keyPair.getPrivate());
sig.update(data);
byte[] signatureBytes = sig.sign();
System.out.println("Signature:" + new BASE64Encoder().encode(signatureBytes));
sig.initVerify(keyPair.getPublic());
sig.update(data);
System.out.println(sig.verify(signatureBytes));
}
private static KeyPair getKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
return kpg.genKeyPair();
}
}
Here you need to change the method getKeyPair() to supply your known key pair. You may load it from a java key store [JKS].
You can't just have an arbitrary byte array either as your public key or private key. They should be generated in relation.
public static String sign(String plainText, PrivateKey privateKey) throws Exception {
Signature privateSignature = Signature.getInstance("SHA256withRSA");
privateSignature.initSign(privateKey);
privateSignature.update(plainText.getBytes(UTF_8));
byte[] signature = privateSignature.sign();
return Base64.getEncoder().encodeToString(signature);
}
public static boolean verify(String plainText, String signature, PublicKey publicKey) throws Exception {
Signature publicSignature = Signature.getInstance("SHA256withRSA");
publicSignature.initVerify(publicKey);
publicSignature.update(plainText.getBytes(UTF_8));
byte[] signatureBytes = Base64.getDecoder().decode(signature);
return publicSignature.verify(signatureBytes);
}
I use bouncy-castle to sign data and verify it.
you should add maven dependency:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.56</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.56</version>
</dependency>
Load RSA private or public key from a disk file into a Java object
First, we need to be able to load RSA private or public key from a disk file into a Java object of a proper class from Bouncy Castle
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.commons.lang3.Validate;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
public class KeyUtil {
public static AsymmetricKeyParameter loadPublicKey(InputStream is) {
SubjectPublicKeyInfo spki = (SubjectPublicKeyInfo) readPemObject(is);
try {
return PublicKeyFactory.createKey(spki);
} catch (IOException ex) {
throw new RuntimeException("Cannot create public key object based on input data", ex);
}
}
public static AsymmetricKeyParameter loadPrivateKey(InputStream is) {
PEMKeyPair keyPair = (PEMKeyPair) readPemObject(is);
PrivateKeyInfo pki = keyPair.getPrivateKeyInfo();
try {
return PrivateKeyFactory.createKey(pki);
} catch (IOException ex) {
throw new RuntimeException("Cannot create private key object based on input data", ex);
}
}
private static Object readPemObject(InputStream is) {
try {
Validate.notNull(is, "Input data stream cannot be null");
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
PEMParser pemParser = new PEMParser(isr);
Object obj = pemParser.readObject();
if (obj == null) {
throw new Exception("No PEM object found");
}
return obj;
} catch (Throwable ex) {
throw new RuntimeException("Cannot read PEM object from input data", ex);
}
}
}
Creation of an RSA digital signature
// GIVEN: InputStream prvKeyInpStream
AsymmetricKeyParameter privKey = KeyUtil.loadPrivateKey(prvKeyInpStream);
// GIVEN: byte[] messageBytes = ...
RSADigestSigner signer = new RSADigestSigner(new SHA512Digest());
signer.init(true, privKey);
signer.update(messageBytes, 0, messageBytes.length);
try {
byte[] signature = signer.generateSignature();
} catch (Exception ex) {
throw new RuntimeException("Cannot generate RSA signature. " + ex.getMessage(), ex);
}
Verification of an RSA digital signature
// GIVEN: InputStream pubKeyInpStream
AsymmetricKeyParameter publKey = KeyUtil.loadPublicKey(pubKeyInpStream);
// GIVEN: byte[] messageBytes
RSADigestSigner signer = new RSADigestSigner(new SHA512Digest());
signer.init(false, publKey);
signer.update(messageBytes, 0, messageBytes.length);
// GIVEN: byte[] signature - see code sample above
boolean isValidSignature = signer.verifySignature(signature);
public static String sign(String samlResponseString, String keystoreFile, String keyStorePassword, String privateKeyPassword, String alias)
throws NoSuchAlgorithmException, UnsupportedEncodingException,
InvalidKeyException, SignatureException {
PrivateKey pkey=getPrivateKey( keystoreFile, keyStorePassword, privateKeyPassword, alias);
String signedString = null;
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(pkey);
signature.update(samlResponseString.getBytes());
byte[] signatureBytes = signature.sign();
byte[] encryptedByteValue = Base64.encodeBase64(signatureBytes);
signedString = new String(encryptedByteValue, "UTF-8");
System.out.println(signedString);
return signedString;
}
You first must create a public key from array of bytes
byte publicKeyBytes[] = .... your public key in bytes ...
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes));
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
and after using the publicKey to encrypt
String data = "... data to be encrypted ....";
String alg = "RSA/ECB/PKCS1Padding";
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte encryptedBytes[] = cipher.doFinal(data.getBytes());
Now only who have the privateKey can read your data
#rczajka: a publicKey is a key. You can use it to sign somethig that only the owner (that have the privateKey) can read.

Categories

Resources