import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Base64; import org.springframework.util.Base64Utils; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.ShortBufferException; import java.io.ByteArrayOutputStream; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.regex.Pattern; /** * RSA安全編碼組件 * * @author wbw * @version 1.0 */ public class RSAUtils { /** * 非對稱加密密鑰算法 */ public static final String KEY_ALGORITHM_RSA = "RSA"; private static String RSA_JAVA = "RSA/None/PKCS1Padding"; /** * 公鑰 */ private static final String RSA_PUBLIC_KEY = "RSAPublicKey"; /** * 私鑰 */ private static final String RSA_PRIVATE_KEY = "RSAPrivateKey"; /** * RSA密鑰長度 * 默認1024位, * 密鑰長度必須是64的倍數, * 范圍在512至65536位之間。 */ private static final int KEY_SIZE = 1024; static{ Security.insertProviderAt(new BouncyCastleProvider(), 1); } /** * 私鑰解密 * * @param data * 待解密數據 * @param key * 私鑰 * @return byte[] 解密數據 * @throws Exception */ public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception { // 取得私鑰 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_RSA); // 生成私鑰 PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec); // 對數據解密 Cipher cipher = Cipher.getInstance(RSA_JAVA); cipher.init(Cipher.DECRYPT_MODE, privateKey); int blockSize = cipher.getBlockSize(); if(blockSize>0){ ByteArrayOutputStream bout = new ByteArrayOutputStream(64); int j = 0; while (data.length - j * blockSize > 0) { bout.write(cipher.doFinal(data, j * blockSize, blockSize)); j++; } return bout.toByteArray(); } return cipher.doFinal(data); } /** * 公鑰解密 * * @param data * 待解密數據 * @param key * 公鑰 * @return byte[] 解密數據 * @throws Exception */ public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception { // 取得公鑰 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_RSA); // 生成公鑰 PublicKey publicKey = keyFactory.generatePublic(x509KeySpec); // 對數據解密 Cipher cipher = Cipher.getInstance(RSA_JAVA); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(data); } /** * 公鑰加密 * * @param data * 待加密數據 * @param key * 公鑰 * @return byte[] 加密數據 * @throws Exception */ public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception { // 取得公鑰 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_RSA); PublicKey publicKey = keyFactory.generatePublic(x509KeySpec); // 對數據加密 Cipher cipher = Cipher.getInstance(RSA_JAVA); cipher.init(Cipher.ENCRYPT_MODE, publicKey); int blockSize = cipher.getBlockSize(); byte[] raw = getBytes(data, cipher, blockSize); if (raw != null) { return raw; } return cipher.doFinal(data); } private static byte[] getBytes(byte[] data, Cipher cipher, int blockSize) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { if(blockSize>0){ int outputSize = cipher.getOutputSize(data.length); int leavedSize = data.length % blockSize; int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize; byte[] raw = new byte[outputSize * blocksSize]; int i = 0,remainSize=0; while ((remainSize = data.length - i * blockSize) > 0) { int inputLen = remainSize > blockSize?blockSize:remainSize; cipher.doFinal(data, i * blockSize, inputLen, raw, i * outputSize); i++; } return raw; } return null; } /** * 私鑰加密 * * @param data * 待加密數據 * @param key * 私鑰 * @return byte[] 加密數據 * @throws Exception */ public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception { // 取得私鑰 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_RSA); // 生成私鑰 PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec); // 對數據加密 Cipher cipher = Cipher.getInstance(RSA_JAVA); cipher.init(Cipher.ENCRYPT_MODE, privateKey); int blockSize = cipher.getBlockSize(); byte[] raw = getBytes(data, cipher, blockSize); return cipher.doFinal(data); } /** * 取得私鑰 * * @param keyMap * 密鑰Map * @return key 私鑰 * @throws Exception */ public static Key getPrivateKey(Map<String, Key> keyMap) throws Exception { return keyMap.get(RSA_PRIVATE_KEY); } /** * 取得私鑰 * * @param keyMap * 密鑰Map * @return byte[] 私鑰 * @throws Exception */ public static byte[] getPrivateKeyByte(Map<String, Key> keyMap) throws Exception { return keyMap.get(RSA_PRIVATE_KEY).getEncoded(); } /** * 取得公鑰 * * @param keyMap * 密鑰Map * @return key 公鑰 * @throws Exception */ public static Key getPublicKey(Map<String, Key> keyMap) throws Exception { return keyMap.get(RSA_PUBLIC_KEY); } /** * 取得公鑰 * * @param keyMap * 密鑰Map * @return byte[] 公鑰 * @throws Exception */ public static byte[] getPublicKeyByte(Map<String, Key> keyMap) throws Exception { return keyMap.get(RSA_PUBLIC_KEY).getEncoded(); } /** * 初始化密鑰 * @param seed 種子 * @return Map 密鑰Map * @throws Exception */ public static Map<String,Key> initKey(byte[] seed)throws Exception{ // 實例化密鑰對生成器 KeyPairGenerator keyPairGen = KeyPairGenerator .getInstance(KEY_ALGORITHM_RSA); // 初始化密鑰對生成器 keyPairGen.initialize(KEY_SIZE, new SecureRandom(seed) ); // 生成密鑰對 KeyPair keyPair = keyPairGen.generateKeyPair(); // 公鑰 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 私鑰 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 封裝密鑰 Map<String, Key> keyMap = new HashMap<String, Key>(2); keyMap.put(RSA_PUBLIC_KEY, publicKey); keyMap.put(RSA_PRIVATE_KEY, privateKey); return keyMap; } /** * 初始化密鑰 * @param seed 種子 * @return Map 密鑰Map * @throws Exception */ public static Map<String,Key> initKey(String seed)throws Exception{ return initKey(seed.getBytes()); } /** * 初始化密鑰 * * @return Map 密鑰Map * @throws Exception */ public static Map<String, Key> initKey() throws Exception { return initKey(UUID.randomUUID().toString().getBytes()); } public static PublicKey getPublicRSAKey(String key) throws Exception { X509EncodedKeySpec x509 = new X509EncodedKeySpec(Base64.decode(key)); KeyFactory kf = KeyFactory.getInstance(KEY_ALGORITHM_RSA); return kf.generatePublic(x509); } public static PrivateKey getPrivateRSAKey(String key) throws Exception { PKCS8EncodedKeySpec pkgs8 = new PKCS8EncodedKeySpec(Base64.decode(key)); KeyFactory kf = KeyFactory.getInstance(KEY_ALGORITHM_RSA); return kf.generatePrivate(pkgs8); } }
調用
class RSAUtilsTest { private static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAHzDQssuIce0x5thZdTbS1N/iJtkpluE5X3sU0nvRIUAmkqVi9zCuJrRizpOCSGatkX21gQjwJRb7Fz/H38HuyeSv6myLHBbQU866eU3nJPpuQcYiWQMbcWv+y2Y9y0oOqjEZwv+ERj0mLYGO+SHftYwJ3T6yyeHXd3VcMBKkiQIDAQAB"; private static String PRIVATE_KEY= "MIICWwIBAAKBgQCAHzDQssuIce0x5thZdTbS1N/iJtkpluE5X3sU0nvRIUAmkqVi9zCuJrRizpOCSGatkX21gQjwJRb7Fz/H38HuyeSv6myLHBbQU866eU3nJPpuQcYiWQMbcWv+y2Y9y0oOqjEZwv+ERj0mLYGO+SHftYwJ3T6yyeHXd3VcMBKkiQIDAQABAoGAGk/Ng56kY/IZpzzkQ4Lp7mRfUh9uS7c7q7+rFDyhxvIQLZvCMU/YhHtYYk5QRto9k/mkGmlUf5TuYkSFCbQvLGGpc7WKOvEuoHzXcHAc1peQa5+7WKDjhs8R9W6T5g4cYnqknTWNh1nfVbM9GOBdDLFxBJgJVh/r2fvhpB1WL4ECQQCQf2yrKiiHJsEIuO67iVRy54HcEnZvV0nYVnhFNWfDLtMIm/6I7G6n0MZHGWCIs77EPAhiMtg9IioE3I0Q/neZAkEA4vzQE6VcG12MoYkmudgmpnO3YjPdST9Ui1sEhrxvqXNru+ykfwx3kWZt42yv5471FytVSPJwXwX63fnfNp7qcQJAbRaWLr68LBR45SHgsdpi1ACtTDzwBuzKRjY5xF4mQPenwLcsOajtfWojVuf0th+lJLcByUkDcVvKhzMOmMbT+QJAPc9GAfOHb1Q8FUi5qOW5MJ5WE4G4Algid4gjZWUuqt/pOFUqPgZxEMDpr4JLLCz7hIGiSajq/JUuSP/fzonboQJAbWcNpngj5xddtGn/PVE1Zv9iwJmfD+/9Y9nQ+0AO/FFK6ruFEjikefkrB8byBcGy6fU7ax7AjqsF5HdsE1BfaA=="; public static String rsaPublicEncryptAndPrivateKeyDecrypt(String rawText) { byte[] privateKey = Base64Utils.decodeFromString(PRIVATE_KEY); byte[] publicKey = Base64Utils.decodeFromString(PUBLIC_KEY); try { System.out.println("原數據為:"+rawText); byte[] encryptByPublicKey = RSAUtils.encryptByPublicKey(rawText.getBytes(), publicKey); String encryptByPublicKeyString = Base64Utils.encodeToString(encryptByPublicKey); System.out.println("公鑰加密后的數據為:"+encryptByPublicKeyString); byte[] decryptByPrivateKey = RSAUtils.decryptByPrivateKey( Base64Utils.decodeFromString(encryptByPublicKeyString), privateKey); String result=new String(decryptByPrivateKey); System.out.println("私鑰解密后的數據為:"+result); return result; } catch (Exception e) { System.out.println(e); } return null; } public static void main(String[] args) { System.out.println(rsaPublicEncryptAndPrivateKeyDecrypt("Hello world!")); } }
輸出
原數據為:Hello world! 公鑰加密后的數據為:fymr5G4ZWIy3ek9xJ+KAtNAKHVOjX9qPgPDF9wSofGaPsOuRMTz3LvvmpA8CCYJT/Y3TzXEQPWQjUwhcqH/AkDorf78oe1zbXE3m47Unua7yhsGNZdCE14j5JfXB5t6JZ3VOBycLMXgCw6Ol3m3lkaaa6xxAuH5sMN0haseERs8= 私鑰解密后的數據為:Hello world!
