Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - Encrypt String with existing public key file

I've been researching this for the past 4-5 hours now and can't seem to find an answer that actually works despite finding 'answers' that used everything from a few methods to an entire ~100 line class. I can't imagine that there isn't some simple function to do such a trivial thing :P

I have a pre-existing set of public / private keys (actually, two sets - one generated by ssh-keygen and another by openssl so .. whatever format works is cool).

All I am after is a simple java equivalent to what I write in python like -

key_object = someModule.KeyObject(nameOfPublicKeyFile)

def encrypt (SomePlainText) :
  return someOtherModule.encrypt(key_object, SomePlainText)

Any help would be awesome!

like image 835
user2877564 Avatar asked Jun 21 '14 03:06

user2877564


People also ask

Can you encrypt something with a public key?

Public key cryptography is a method of encrypting or signing data with two different keys and making one of the keys, the public key, available for anyone to use. The other key is known as the private key. Data encrypted with the public key can only be decrypted with the private key.

Can you encrypt and decrypt with the same public key?

Sign of the Times And you can obtain this easily because your recipient can share their public key with anyone, since public keys are only used to encrypt messages, not decrypt them. But there's more! We know that if you encrypt a message with a certain public key, it can only be decrypted by the matching private key.


1 Answers

These openssl commands in the shell create an RSA key pair and write the public and private keys to DER formatted files.

Here, the private key file is not password-protected (-nocrypt) to keep things simple.

$ openssl genrsa -out keypair.pem 2048
Generating RSA private key, 2048 bit long modulus
............+++
................................+++
e is 65537 (0x10001)
$ openssl rsa -in keypair.pem -outform DER -pubout -out public.der
writing RSA key
$ openssl pkcs8 -topk8 -nocrypt -in keypair.pem -outform DER -out private.der

Now that you have the DER files, you can read them in Java and use KeySpec and KeyFactory to create PublicKey and PrivateKey objects.

public byte[] readFileBytes(String filename) throws IOException
{
    Path path = Paths.get(filename);
    return Files.readAllBytes(path);        
}

public PublicKey readPublicKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException
{
    X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(readFileBytes(filename));
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    return keyFactory.generatePublic(publicSpec);       
}

public PrivateKey readPrivateKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException
{
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(readFileBytes(filename));
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    return keyFactory.generatePrivate(keySpec);     
}

With the public and private keys, you can encrypt and decrypt small amounts of data (that fit within your RSA modulus.) I recommend OAEP padding.

public byte[] encrypt(PublicKey key, byte[] plaintext) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");   
    cipher.init(Cipher.ENCRYPT_MODE, key);  
    return cipher.doFinal(plaintext);
}

public byte[] decrypt(PrivateKey key, byte[] ciphertext) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");   
    cipher.init(Cipher.DECRYPT_MODE, key);  
    return cipher.doFinal(ciphertext);
}

Here it is tied together with a simple encryption and decryption:

public void Hello()
{
    try
    {
        PublicKey publicKey = readPublicKey("public.der");
        PrivateKey privateKey = readPrivateKey("private.der");
        byte[] message = "Hello World".getBytes("UTF8");
        byte[] secret = encrypt(publicKey, message);
        byte[] recovered_message = decrypt(privateKey, secret);
        System.out.println(new String(recovered_message, "UTF8"));
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}
like image 105
Jim Flood Avatar answered Sep 29 '22 17:09

Jim Flood