流程分析: java
甲方構建密鑰對兒,將公鑰公佈給乙方,將私鑰保留。算法
甲方使用私鑰加密數據,而後用私鑰對加密後的數據簽名,發送給乙方簽名以及加密後的數據;乙方使用公鑰、簽名來驗證待解密數據是否有效,若是有效使用公鑰對數據解密。安全
乙方使用公鑰加密數據,向甲方發送通過加密後的數據;甲方得到加密數據,經過私鑰解密。ide
按如上步驟給出序列圖,以下: 編碼
package com.rsa; import java.security.MessageDigest; import javax.crypto.KeyGenerator; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; /** * 基礎加密組件 * * @author 樑棟 * @version 1.0 * @since 1.0 */ @SuppressWarnings("restriction") public abstract class Coder { public static final String KEY_SHA = "SHA"; public static final String KEY_MD5 = "MD5"; /** * MAC算法可選如下多種算法 * * <pre> * HmacMD5 * HmacSHA1 * HmacSHA256 * HmacSHA384 * HmacSHA512 * </pre> */ public static final String KEY_MAC = "HmacMD5"; /** * BASE64解密 * * @param key * @return * @throws Exception */ public static byte[] decryptBASE64(String key) throws Exception { return (new BASE64Decoder()).decodeBuffer(key); } /** * BASE64加密 * * @param key * @return * @throws Exception */ public static String encryptBASE64(byte[] key) throws Exception { return (new BASE64Encoder()).encodeBuffer(key); } /** * MD5加密 * * @param data * @return * @throws Exception */ public static byte[] encryptMD5(byte[] data) throws Exception { MessageDigest md5 = MessageDigest.getInstance(KEY_MD5); md5.update(data); return md5.digest(); } /** * SHA加密 * * @param data * @return * @throws Exception */ public static byte[] encryptSHA(byte[] data) throws Exception { MessageDigest sha = MessageDigest.getInstance(KEY_SHA); sha.update(data); return sha.digest(); } /** * 初始化HMAC密鑰 * * @return * @throws Exception */ public static String initMacKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC); SecretKey secretKey = keyGenerator.generateKey(); return encryptBASE64(secretKey.getEncoded()); } /** * HMAC加密 * * @param data * @param key * @return * @throws Exception */ public static byte[] encryptHMAC(byte[] data, String key) throws Exception { SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC); Mac mac = Mac.getInstance(secretKey.getAlgorithm()); mac.init(secretKey); return mac.doFinal(data); } }
package com.rsa; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; 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 javax.crypto.Cipher; /** * RSA安全編碼組件 * * @author 樑棟 * @version 1.0 * @since 1.0 */ public abstract class RSACoder extends Coder { public static final String KEY_ALGORITHM = "RSA"; public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; private static final String PUBLIC_KEY = "RSAPublicKey"; private static final String PRIVATE_KEY = "RSAPrivateKey"; /** * 用私鑰對信息生成數字簽名 * * @param data * 加密數據 * @param privateKey * 私鑰 * * @return * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { // 解密由base64編碼的私鑰 byte[] keyBytes = decryptBASE64(privateKey); // 構造PKCS8EncodedKeySpec對象 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); // KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 取私鑰匙對象 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); // 用私鑰對信息生成數字簽名 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(priKey); signature.update(data); return encryptBASE64(signature.sign()); } /** * 校驗數字簽名 * * @param data * 加密數據 * @param publicKey * 公鑰 * @param sign * 數字簽名 * * @return 校驗成功返回true 失敗返回false * @throws Exception * */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { // 解密由base64編碼的公鑰 byte[] keyBytes = decryptBASE64(publicKey); // 構造X509EncodedKeySpec對象 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); // KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 取公鑰匙對象 PublicKey pubKey = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(pubKey); signature.update(data); // 驗證簽名是否正常 return signature.verify(decryptBASE64(sign)); } /** * 解密<br> * 用私鑰解密 * * @param data * @param key * @return * @throws Exception */ public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception { // 對密鑰解密 byte[] keyBytes = decryptBASE64(key); // 取得私鑰 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec); // 對數據解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(data); } /** * 解密<br> * 用私鑰解密 * * @param data * @param key * @return * @throws Exception */ public static byte[] decryptByPublicKey(byte[] data, String key) throws Exception { // 對密鑰解密 byte[] keyBytes = decryptBASE64(key); // 取得公鑰 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicKey = keyFactory.generatePublic(x509KeySpec); // 對數據解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(data); } /** * 加密<br> * 用公鑰加密 * * @param data * @param key * @return * @throws Exception */ public static byte[] encryptByPublicKey(byte[] data, String key) throws Exception { // 對公鑰解密 byte[] keyBytes = decryptBASE64(key); // 取得公鑰 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicKey = keyFactory.generatePublic(x509KeySpec); // 對數據加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data); } /** * 加密<br> * 用私鑰加密 * * @param data * @param key * @return * @throws Exception */ public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception { // 對密鑰解密 byte[] keyBytes = decryptBASE64(key); // 取得私鑰 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec); // 對數據加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateKey); return cipher.doFinal(data); } /** * 取得私鑰 * * @param keyMap * @return * @throws Exception */ public static String getPrivateKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PRIVATE_KEY); return encryptBASE64(key.getEncoded()); } /** * 取得公鑰 * * @param keyMap * @return * @throws Exception */ public static String getPublicKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PUBLIC_KEY); return encryptBASE64(key.getEncoded()); } /** * 初始化密鑰 * * @return * @throws Exception */ public static Map<String, Object> initKey() throws Exception { KeyPairGenerator keyPairGen = KeyPairGenerator .getInstance(KEY_ALGORITHM); keyPairGen.initialize(1024); KeyPair keyPair = keyPairGen.generateKeyPair(); // 公鑰 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 私鑰 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); Map<String, Object> keyMap = new HashMap<String, Object>(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } }
package com.rsa; import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; import java.util.Map; /** * * @author 樑棟 * @version 1.0 * @since 1.0 */ public class RSACoderTest { private String publicKey; private String privateKey; @Before public void setUp() throws Exception { Map<String, Object> keyMap = RSACoder.initKey(); publicKey = RSACoder.getPublicKey(keyMap); privateKey = RSACoder.getPrivateKey(keyMap); System.err.println("公鑰: \n\r" + publicKey); System.err.println("私鑰: \n\r" + privateKey); } @Test public void test() throws Exception { System.err.println("公鑰加密——私鑰解密"); String inputStr = "abc"; byte[] data = inputStr.getBytes(); byte[] encodedData = RSACoder.encryptByPublicKey(data, publicKey); byte[] decodedData = RSACoder.decryptByPrivateKey(encodedData, privateKey); String outputStr = new String(decodedData); System.err.println("加密前: " + inputStr + "\n\r" + "解密後: " + outputStr); assertEquals(inputStr, outputStr); } @Test public void testSign() throws Exception { System.err.println("私鑰加密——公鑰解密"); String inputStr = "sign"; byte[] data = inputStr.getBytes(); byte[] encodedData = RSACoder.encryptByPrivateKey(data, privateKey); byte[] decodedData = RSACoder .decryptByPublicKey(encodedData, publicKey); String outputStr = new String(decodedData); System.err.println("加密前: " + inputStr + "\n\r" + "解密後: " + outputStr); assertEquals(inputStr, outputStr); System.err.println("私鑰簽名——公鑰驗證簽名"); // 產生簽名 String sign = RSACoder.sign(encodedData, privateKey); System.err.println("簽名:\r" + sign); // 驗證簽名 boolean status = RSACoder.verify(encodedData, publicKey, sign); System.err.println("狀態:\r" + status); assertTrue(status); } }