KeyUtil.java
package org.ondc;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
*
* Utility Class to Generate Keypairs and Shared Key.
*
*/
public class KeyUtil {
private static Logger log = Logger.getLogger("ErrorLogger");
private KeyUtil() {
}
/**
* The Algorithm used to generate Key pairs. ("X25519").
*/
public static final String KEYPAIR_GENERATION_ALGORITHM = "X25519";
/**
*
* POJO class for storing private and public keys.
*
*/
public static class DHKeyPair {
/**
* The Public Key.
*/
private String publicKey;
/**
* The Private Key.
*/
private String privateKey;
/**
* Constructor
* @param keyPair Instance of java.security.KeyPair Class.
*/
public DHKeyPair(KeyPair keyPair) {
this.publicKey = keyToString(keyPair.getPublic());
this.privateKey = keyToString(keyPair.getPrivate());
}
/**
* Gets the Public Key.
* @return Public Key.
*/
public String getPublicKey() {
return publicKey;
}
/**
* Gets the Private Key.
* @return Private Key.
*/
public String getPrivateKey() {
return privateKey;
}
/**
* String Formatting.
*/
@Override
public String toString() {
return "DHKeyPair [publicKey=" + publicKey + ", privateKey=" + privateKey + "]";
}
}
/**
* Generate a Keypair.
* @return Generated Keypair.
*/
public static DHKeyPair generateKeyPair() {
DHKeyPair generatedKeyPair = null;
try {
KeyPair keyPair = KeyPairGenerator.getInstance(KEYPAIR_GENERATION_ALGORITHM).generateKeyPair();
generatedKeyPair = new DHKeyPair(keyPair);
} catch (Exception e) {
log.log(Level.SEVERE, e.getMessage(), e);
}
return generatedKeyPair;
}
/**
* Generates a SharedKey.
* @param privateKeyStr Private Key of one party.
* @param publicKeyStr Public Key of the other party.
* @return Shared key as base64 string.
*/
public static String generateSharedKey(String privateKeyStr, String publicKeyStr){
// Initialize the variables to store Shared Key and Key Agreement.
String sharedKey = null;
KeyAgreement ka;
try {
// De-serializing the private key and public key.
Key privateKey = privateKeyFromString(privateKeyStr);
Key publicKey = publicKeyFromString(publicKeyStr);
// Intializing a key agreement instance.
ka = KeyAgreement.getInstance(KEYPAIR_GENERATION_ALGORITHM, "BC");
ka.init(privateKey);
// Generate the Shared Key.
ka.doPhase(publicKey, true);
SecretKey sKey = ka.generateSecret("AES");
sharedKey = keyToString(sKey);
} catch (Exception e) {
log.log(Level.SEVERE, e.getMessage(), e);
}
// Return the Shared Key.
return sharedKey;
}
/**
* Encode a key to base64 string.
* @param key The key to encode.
* @return The Encoded Key.
*/
private static String keyToString(Key key) {
byte[] encodedKey = key.getEncoded();
return Base64.getEncoder().encodeToString(encodedKey);
}
/**
* Get the Public Key from base64 encoded string.
* @param publicKeyStr The base64 encoded Public Key string.
* @return The Decoded Public Key.
* @throws NoSuchAlgorithmException Thrown when invalid keypair generation algorithm is configured.
* @throws InvalidKeySpecException Thrown if the public key is invalid.
*/
private static PublicKey publicKeyFromString(String publicKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] encodedKey = Base64.getDecoder().decode(publicKeyStr);
KeyFactory keyFactory = KeyFactory.getInstance(KEYPAIR_GENERATION_ALGORITHM);
return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
}
/**
* Get the Private Key from base64 encoded string.
* @param privateKeyStr The base64 encoded Private Key string.
* @return The Decoded Private Key.
* @throws NoSuchAlgorithmException Thrown when invalid keypair generation algorithm is configured.
* @throws InvalidKeySpecException Thrown if the private key is invalid.
*/
private static PrivateKey privateKeyFromString(String privateKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] encodedKey = Base64.getDecoder().decode(privateKeyStr);
KeyFactory keyFactory = KeyFactory.getInstance(KEYPAIR_GENERATION_ALGORITHM);
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
}
/**
* Get the Shared Key from base64 encoded string.
* @param sharedKeyString The base64 encoded Shared Key String.
* @return The Decoded Shared Key.
*/
protected static SecretKey sharedKeyFromString(String sharedKeyString) {
byte[] decodedKey = Base64.getDecoder().decode(sharedKeyString);
return new SecretKeySpec(decodedKey, KEYPAIR_GENERATION_ALGORITHM);
}
}