September 15, 2016

Public-Key Cryptography (Asymmetric Cryptography)

Introduction

In Public-Key Cryptography you have two keys: a public key and a private key.

As the names indicates the public key is for everyone eyes and the private is to be hidden and is personal.

Encryption with the PRIVATE key, also called Signature

Encryption with you private key, is not very secret, since one can decrypt it with the public key. And since it is public, anyone can do that. So what good is that? Verification. When you can successfully decrypt it, you can be sure of, that this data has not been tampered and can only be originated from the person that holds the private key.

This encrypted is called Signature.

Encryption with the PUBLIC key

This is what you usually call encryption, since it can only be decrypted with the private key.

Example

Generate a public and private key.

$ keytool -genkeypair -alias mykey -keyalg RSA -keysize 2048 -keystore mykey.jks

Java code

package se.magnuskkarlsson.example.security;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

public class PublicKeyCryptography {

    public KeyStore loadKeyStore(InputStream input, String password)
            throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {

        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(input, password.toCharArray());
        return keyStore;
    }

    public KeyPair getKeyPair(KeyStore keyStore, String alias, String password)
            throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException {

        PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
        PublicKey publicKey = keyStore.getCertificate(alias).getPublicKey();
        return new KeyPair(publicKey, privateKey);
    }

    public byte[] generateSignature(PrivateKey privateKey, String data) throws NoSuchAlgorithmException,
            NoSuchProviderException, InvalidKeyException, SignatureException, UnsupportedEncodingException {

        Signature signature = Signature.getInstance("SHA1withRSA");
        signature.initSign(privateKey);
        signature.update(data.getBytes("UTF-8"));
        return signature.sign();
    }

    public boolean verifySignature(PublicKey publicKey, String data, byte[] signedData) throws NoSuchAlgorithmException,
            NoSuchProviderException, InvalidKeyException, SignatureException, UnsupportedEncodingException {

        Signature signature = Signature.getInstance("SHA1withRSA");
        signature.initVerify(publicKey);
        signature.update(data.getBytes("UTF-8"));
        return signature.verify(signedData);
    }

    public byte[] encrypt(PublicKey publicKey, String data) throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException {

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        cipher.update(data.getBytes("UTF-8"));
        return cipher.doFinal();
    }

    public byte[] decrypt(PrivateKey privateKey, byte[] encryptedData) throws NoSuchAlgorithmException,
            NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        cipher.update(encryptedData);
        return cipher.doFinal();
    }

    public static void main(String[] args) throws Exception {
        PublicKeyCryptography crypt = new PublicKeyCryptography();
        InputStream input = PublicKeyCryptography.class.getClassLoader().getResourceAsStream("mykey.jks");
        KeyStore keyStore = crypt.loadKeyStore(input, "changeit");
        KeyPair keyPair = crypt.getKeyPair(keyStore, "mykey", "changeit");

        byte[] signedData = crypt.generateSignature(keyPair.getPrivate(), "hello world");
        System.out.println("Signature : ");
        System.out.println(new sun.misc.BASE64Encoder().encode(signedData));
        boolean verifies = crypt.verifySignature(keyPair.getPublic(), "hello world", signedData);
        System.out.println("Verifies : " + verifies);
        System.out.println();

        byte[] encryptedData = crypt.encrypt(keyPair.getPublic(), "hello world");
        System.out.println("Encrypted Data : ");
        System.out.println(new sun.misc.BASE64Encoder().encode(encryptedData));
        byte[] descryptedData = crypt.decrypt(keyPair.getPrivate(), encryptedData);
        System.out.println("Decrypted Data : " + new String(descryptedData, "UTF-8"));
    }

}

No comments: