All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.netcode.security.encryption.RSAEncrypter Maven / Gradle / Ivy

package dev.netcode.security.encryption;

import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

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

/**
 * This class simplifies the process of RSA Encrypting data.
 * Using it you can generate RSA Keys and encrypt/decrypt data.
 */
public class RSAEncrypter {

	/**
	 * Generates a {@link KeyPair} with given size.
	 * The higher the size, the more secure the key can be considered.
	 * Size must be divisible by 2.
	 * @param size of the keys to be generated
	 * @return the generated {@link KeyPair}
	 */
	public static KeyPair generateKeyPair(int size) {
		KeyPairGenerator keygen = null;
		try {
			keygen = KeyPairGenerator.getInstance("RSA");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		keygen.initialize(size, new SecureRandom());
		return keygen.generateKeyPair();
	}
	
	/**
	 * Decrypts RSA encrypted data
	 * @param cipher data to be decrypted
	 * @param privateKey to be used to decrypt the data
	 * @return decrypted data as UTF-8 encoded String
	 * @throws InvalidKeyException in case the key format is not supported
	 * @throws BadPaddingException in case something failed while padding
	 * @throws IllegalBlockSizeException in case the blocksize is invalid
	 */
	public static String decrypt(byte[] cipher, PrivateKey privateKey) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException  {
		byte[] dec = {};
		Cipher c = null;
		try {
			c = Cipher.getInstance("RSA");
		} catch (NoSuchAlgorithmException |NoSuchPaddingException e) {
			// RSA exists so this should never be thrown
			e.printStackTrace();
		}
		c.init(Cipher.DECRYPT_MODE, privateKey);
		dec = c.doFinal(cipher);
		return new String(dec, StandardCharsets.UTF_8);
	}
	
	/**
	 * Encrypts a message using a RSA {@link PublicKey}
	 * @param message to be encrypted
	 * @param publicKey ised to encrypt the data
	 * @return byte array of encrypted data
	 * @throws InvalidKeyException in case the key format is not supported
	 * @throws BadPaddingException in case something failed while padding
	 * @throws IllegalBlockSizeException in case the blocksize is invalid
	 */
	public static byte[] encrypt(String message, PublicKey publicKey) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
		Cipher cipher = null;
		byte[] encrypted = null;
		try {
			cipher = Cipher.getInstance("RSA");
		} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
			// RSA exists so this should never be thrown
			e.printStackTrace();
		}
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		encrypted = cipher.doFinal(message.getBytes(StandardCharsets.UTF_8));
		return encrypted;
	}
	
	/**
	 * Generates a RSA signature for a given input. The signature can
	 * be used to make sure a message comes from a specific sender
	 * @param privateKey used to sign the data
	 * @param input data to be signed
	 * @return Signature as String
	 * @throws InvalidKeyException in case the key format is not supported
	 * @throws SignatureException in case something went wrong while creating the signature
	 */
	public static String sign(PrivateKey privateKey, String input) throws InvalidKeyException, SignatureException {
		Signature privateSignature = null;
		try {
			privateSignature = Signature.getInstance("SHA256withRSA");
		} catch (NoSuchAlgorithmException e) {
			// SHA256withRSA exists so this should never be thrown
			e.printStackTrace();
		}
	    privateSignature.initSign(privateKey);
	    privateSignature.update(input.getBytes(StandardCharsets.UTF_8));

	    byte[] signature = privateSignature.sign();
	    return Base64.getEncoder().encodeToString(signature);
	}
	
	/**
	 * Verifies that a given signature matches given data and a given public key.
	 * This process ensures that the data really comes from the sender 
	 * @param publicKey of the sender
	 * @param data original data 
	 * @param signature to be tested
	 * @return true if the signature matches the data and public key
	 */
	public static boolean verifySignature(PublicKey publicKey, String data, String signature) {
		try {
			Signature publicSignature = Signature.getInstance("SHA256withRSA");
		    publicSignature.initVerify(publicKey);
		    publicSignature.update(data.getBytes(StandardCharsets.UTF_8));
	
		    byte[] signatureBytes = Base64.getDecoder().decode(signature);
	
		    return publicSignature.verify(signatureBytes);
		} catch(Exception e) {
			return false;
		}
	}
	
	/**
	 * Generates a public key from byte array
	 * @param key byte array
	 * @return public key
	 * @throws InvalidKeySpecException in case the key format is not supported
	 */
	public static PublicKey generatePublicKeyFromString(byte[] key) throws InvalidKeySpecException{
        X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(key);
        KeyFactory kf;
		try {
			kf = KeyFactory.getInstance("RSA");
		} catch (NoSuchAlgorithmException e) {
			//should never be thrown
			e.printStackTrace();
			return null;
		}
		return kf.generatePublic(X509publicKey);
	}
	
	/**
	 * Generates a private key from byte array
	 * @param key byte array
	 * @return private key
	 * @throws InvalidKeySpecException in case the key format is not supported
	 */
	public static PrivateKey generatePrivateKeyFromString(byte[] key) throws InvalidKeySpecException{
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
        KeyFactory kf;
		try {
			kf = KeyFactory.getInstance("RSA");
		} catch (NoSuchAlgorithmException e) {
			// should never be thrown
			e.printStackTrace();
			return null;
		}
	    return kf.generatePrivate(pkcs8EncodedKeySpec);
	}
	
	/**
	 * Encodes a Key to a String representation.
	 * The key will be encoded to Base64
	 * @param key to transform
	 * @return String representation
	 */
	public static String keyToString(Key key) {
		if(key == null) {
			return "null";
		}
		return Base64.getEncoder().encodeToString(key.getEncoded());
	}
	
	/**
	 * Generates a fingerprint string of a public key.
	 * The key has to be X509 compatible.
	 * The fingerprint will be SHA-1 representation of the key
	 * @param key to get the fingerprint of
	 * @return the fingerprint
	 */
	public static String getFingerprint(PublicKey key) {
		try {
	        X509EncodedKeySpec pubkeyspec = new X509EncodedKeySpec(key.getEncoded());
	        return Base58.encode(MessageDigest.getInstance("SHA-1").digest(pubkeyspec.getEncoded()));
		} catch(Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy