Last active
September 3, 2018 02:24
-
-
Save lifecube/4f456383006eb3dc13f50a2ff6d83318 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import org.slf4j.Logger; | |
| import org.slf4j.LoggerFactory; | |
| import javax.crypto.*; | |
| import javax.crypto.spec.GCMParameterSpec; | |
| import javax.crypto.spec.SecretKeySpec; | |
| import java.io.UnsupportedEncodingException; | |
| import java.security.*; | |
| import java.security.spec.InvalidKeySpecException; | |
| import java.security.spec.PKCS8EncodedKeySpec; | |
| import java.security.spec.X509EncodedKeySpec; | |
| import java.util.Base64; | |
| /** | |
| * require Java 8 or above | |
| **/ | |
| public class CryptUtil { | |
| public static final Logger log = LoggerFactory.getLogger(CryptUtil.class); | |
| //GCM related settings | |
| public static final int GCM_KEY_SIZE = 128; // in bits. 16 bytes | |
| public static final int GCM_NONCE_SIZE = 8; // in bytes. 8 bytes | |
| public static final int GCM_TAG_SIZE = 128; // in bits. 16 bytes | |
| public static final String GCM_KEY_GEN_NAME = "AES"; | |
| public static final String GCM_CIPHER_ALIAS = "AES/GCM/NoPadding"; | |
| //RSA related settings | |
| public static final String RSA_KEY_FAC_NAME = "RSA"; | |
| public static final String RSA_CIPHER_ALIAS = "RSA/ECB/PKCS1PADDING"; | |
| private CryptUtil() { | |
| } | |
| public static String sha512(String input) { | |
| MessageDigest objSHA; | |
| try { | |
| objSHA = MessageDigest.getInstance("SHA-512"); | |
| byte[] bytes = objSHA.digest(input.getBytes("UTF-8")); | |
| StringBuilder sb = new StringBuilder(); | |
| for (int i = 0; i < bytes.length; i++) { | |
| String h = Integer.toHexString(0xFF & bytes[i]); | |
| while (h.length() < 2) | |
| h = "0" + h; | |
| sb.append(h); | |
| } | |
| return sb.toString(); | |
| } catch (NoSuchAlgorithmException ex) { | |
| log.error("NoSuchAlgorithmException ex:", ex); | |
| } catch (UnsupportedEncodingException ex) { | |
| log.error("UnsupportedEncodingException ex:", ex); | |
| } | |
| return ""; | |
| } | |
| public static byte[] generateGCMNonce() throws NoSuchAlgorithmException { | |
| byte[] nonce = new byte[GCM_NONCE_SIZE]; | |
| SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); | |
| secureRandom.nextBytes(nonce); | |
| return nonce; | |
| } | |
| public static SecretKey generateGCMKey() throws NoSuchAlgorithmException { | |
| KeyGenerator generator = getGCMKeyGenerator(); | |
| return generator.generateKey(); | |
| } | |
| public static SecretKey getGCMKey(byte[] encodedKey) { | |
| return new SecretKeySpec(encodedKey, 0, encodedKey.length, GCM_KEY_GEN_NAME); | |
| } | |
| private static KeyGenerator getGCMKeyGenerator() throws NoSuchAlgorithmException { | |
| KeyGenerator aesKeyGenerator = KeyGenerator.getInstance(GCM_KEY_GEN_NAME); | |
| SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); | |
| aesKeyGenerator.init(GCM_KEY_SIZE, random); | |
| return aesKeyGenerator; | |
| } | |
| public static byte[] gcmEncrypt(SecretKey key, byte[] nonce, byte[] data, byte[] aad) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { | |
| //in case you don't want to provide the aad, the empty array will assign | |
| if (aad == null) { | |
| aad = new byte[0]; | |
| } | |
| Cipher cipher = Cipher.getInstance(GCM_CIPHER_ALIAS); | |
| GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_SIZE, nonce); | |
| cipher.init(Cipher.ENCRYPT_MODE, key, spec); | |
| cipher.updateAAD(aad); | |
| return cipher.doFinal(data); | |
| } | |
| public static byte[] gcmDecrypt(SecretKey key, byte[] nonce, byte[] data, byte[] aad) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { | |
| if (aad == null) { | |
| aad = new byte[0]; | |
| } | |
| Cipher cipher = Cipher.getInstance(GCM_CIPHER_ALIAS); | |
| GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_SIZE, nonce); | |
| cipher.init(Cipher.DECRYPT_MODE, key, spec); | |
| cipher.updateAAD(aad); | |
| return cipher.doFinal(data); | |
| } | |
| public static KeyFactory getRSAKeyFactory() throws NoSuchAlgorithmException { | |
| return KeyFactory.getInstance(RSA_KEY_FAC_NAME); | |
| } | |
| //ACCEPT PEM content public key | |
| public static PublicKey getRSAPublicKey(String pubKey) throws InvalidKeySpecException, NoSuchAlgorithmException { | |
| //since DER is binary based, it's more convenient for bank to send the string based key data to lms. No encoding required. | |
| pubKey = pubKey.replaceAll("(-+BEGIN PUBLIC KEY-+|-+END PUBLIC KEY-+|\\r?\\n)", ""); | |
| byte[] keyBytes = Base64.getDecoder().decode(pubKey); | |
| X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); | |
| KeyFactory keyFactory = getRSAKeyFactory(); | |
| return keyFactory.generatePublic(spec); | |
| } | |
| public static PrivateKey getRSAPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException { | |
| privateKey = privateKey.replaceAll("(-+BEGIN PRIVATE KEY-+|-+END PRIVATE KEY-+|\\r?\\n)", ""); | |
| byte[] keyBytes = Base64.getDecoder().decode(privateKey); | |
| PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); | |
| KeyFactory keyFactory = getRSAKeyFactory(); | |
| return keyFactory.generatePrivate(keySpec); | |
| } | |
| public static byte[] rsaEncrypt(PublicKey key, byte[] data) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { | |
| Cipher cipher = Cipher.getInstance(RSA_CIPHER_ALIAS); | |
| cipher.init(Cipher.ENCRYPT_MODE, key); | |
| return cipher.doFinal(data); | |
| } | |
| public static byte[] rsaDecrypt(PrivateKey privateKey, byte[] data) throws Exception { | |
| Cipher cipher = Cipher.getInstance(RSA_CIPHER_ALIAS); | |
| cipher.init(Cipher.DECRYPT_MODE, privateKey); | |
| return cipher.doFinal(data); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment