package testRSA;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;import it.sauronsoftware.base64.Base64;/** * <p> * BASE64編碼解碼工具包 * </p> * <p> * 依賴javabase64-1.3.1.jar * </p> * * @author IceWee * @date 2012-5-19 * @version 1.0 */public class Base64Utils { /** * 檔案讀取緩衝區大小 */ private static final int CACHE_SIZE = 1024; /** * <p> * BASE64字串解碼為位元據 * </p> * * @param base64 * @return * @throws Exception */ public static byte[] decode(String base64) throws Exception { return Base64.decode(base64.getBytes()); } /** * <p> * 位元據編碼為BASE64字串 * </p> * * @param bytes * @return * @throws Exception */ public static String encode(byte[] bytes) throws Exception { return new String(Base64.encode(bytes)); } /** * <p> * 將檔案編碼為BASE64字串 * </p> * <p> * 大檔案慎用,可能會導致記憶體溢出 * </p> * * @param filePath 檔案絕對路徑 * @return * @throws Exception */ public static String encodeFile(String filePath) throws Exception { byte[] bytes = fileToByte(filePath); return encode(bytes); } /** * <p> * BASE64字串轉迴文件 * </p> * * @param filePath 檔案絕對路徑 * @param base64 編碼字串 * @throws Exception */ public static void decodeToFile(String filePath, String base64) throws Exception { byte[] bytes = decode(base64); byteArrayToFile(bytes, filePath); } /** * <p> * 檔案轉換為位元組 * </p> * * @param filePath 檔案路徑 * @return * @throws Exception */ public static byte[] fileToByte(String filePath) throws Exception { byte[] data = new byte[0]; File file = new File(filePath); if (file.exists()) { FileInputStream in = new FileInputStream(file); ByteArrayOutputStream out = new ByteArrayOutputStream(2048); byte[] cache = new byte[CACHE_SIZE]; int nRead = 0; while ((nRead = in.read(cache)) != -1) { out.write(cache, 0, nRead); out.flush(); } out.close(); in.close(); data = out.toByteArray(); } return data; } /** * <p> * 位元據寫檔案 * </p> * * @param bytes 位元據 * @param filePath 檔案組建目錄 */ public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception { InputStream in = new ByteArrayInputStream(bytes); File destFile = new File(filePath); if (!destFile.getParentFile().exists()) { destFile.getParentFile().mkdirs(); } destFile.createNewFile(); OutputStream out = new FileOutputStream(destFile); byte[] cache = new byte[CACHE_SIZE]; int nRead = 0; while ((nRead = in.read(cache)) != -1) { out.write(cache, 0, nRead); out.flush(); } out.close(); in.close(); } }
--------------------------------------------------無情分割線------------------------------------------------------------------------------------------
package testRSA;import java.util.Map;public class RSATester { static String publicKey; static String privateKey; /**明文*/ private final static String sourceString = "七裡我是七裡我是中國人,好不,好不好,你說呢,可以行呀中國人,好不,好不好,你說呢,可以行呀"; //測試公開金鑰 private static String public_aa="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAQqyzkY8i3VhvQrt4a2jwzlJrhiATa8Sh1R9vvQWdwfvF34cZzHsnJjXkkAUm5dvS6mG5LU1FfpMuv7ZobbLtXITzyEILde6pyaXFeTBPrO0XDP5hhJqSzh1IOGbamzY0rJeSEXxiks4hBBv2S+tObV/Y9n88myiqLe5Cqsdp9wIDAQAB"; //測試私密金鑰 private static String private_bb="MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIBCrLORjyLdWG9Cu3hraPDOUmuGIBNrxKHVH2+9BZ3B+8XfhxnMeycmNeSQBSbl29LqYbktTUV+ky6/tmhtsu1chPPIQgt17qnJpcV5ME+s7RcM/mGEmpLOHUg4ZtqbNjSsl5IRfGKSziEEG/ZL605tX9j2fzybKKot7kKqx2n3AgMBAAECgYB5mDxIRN/RKs0zNa2rPREQ8lk67L4uC0YwMm+KLEZNyGDbt81KDQxYEiaXmF36AYKEk4Wv253dG2GHuWLB3/X3LPDqz/JaokVdvIioR2c/QchAsOqPTzL6jBeBPj03edvTssyZ5sVadie8tPrzue9/xIsNoR4Bz1SBrXu2xDox6QJBAM6GHrJD5AGL4R/edxCqz59DjGLruK9Oi0XhbwuuZEMCGRdwEiaxujMvUq9TKHWXiv5jyJfXwCo6MRin91WR1r0CQQCe/L6PhnbojvheZlCHrmy4fjbn2RCNEQTnMdneMpX3vcgzfSzDaJOVmZPuS/rfctxZVlCa3KjCCwCI5cdZzbjDAkAbH3Qil1X3egZr6AydDMHNudJTH4AWzerul4e88f9K6ZigAmDv4gGBPWLPkc1LfEaN2E782iHrqc7O3ShXfZrFAkAmiIN3LdPsEZrI5mtmNzRKkuyjzMxiJFnX3xE69W+7l9fKAvCye8opXAuqmee3+JLHZFAs+IY+YYRDqc1jSqUZAkEAkoMHKd1Kt9Z+EoJMSIl3kgGqha+pImdlskneCYkOd9RGxNGGmnRuwgSEotFTBa3+6JfkwL3PSPx07kOI0UnT5w=="; static { try { Map<String, Object> keyMap = RSAUtils.genKeyPair(); publicKey = RSAUtils.getPublicKey(keyMap); privateKey = RSAUtils.getPrivateKey(keyMap); System.err.println("公開金鑰: " + publicKey); System.err.println("私密金鑰: " + privateKey); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { test(); System.out.println(); System.out.println(); System.out.println(); testSign(); } static void test() throws Exception { System.out.println("加密前文字: " + sourceString); //加密 // @��#��ߜ�v��ݮ�I[�M{87ޏs�Ep��`A�7Q��GTW�Tj7��↧��Pj�p7I1�>o����BjT/hA)J�+�q#, byte[] data = sourceString.getBytes(); byte[] encodedData = RSAUtils.encryptByPublicKey(data, public_aa); System.out.println("加密後文字後: " + new String(encodedData)); //解密 //測試解密 byte[] decodedData = RSAUtils.decryptByPrivateKey(encodedData, private_bb); String target = new String(decodedData); System.out.println("解密後文字: " + target); } static void testSign() throws Exception { System.out.println("原文字:" + sourceString); byte[] data = sourceString.getBytes(); byte[] encodedData = RSAUtils.encryptByPrivateKey(data, private_bb); System.out.println("加密後: " + new String(encodedData)); byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, public_aa); String target = new String(decodedData); System.out.println("解密後: " + target); String sign = RSAUtils.sign(encodedData, private_bb); System.out.println("簽名: " + sign); //改變結果測試------------------------------------------ String strCode=new String(encodedData); strCode+="ddwerwef"; encodedData=strCode.getBytes(); //改變結果測試--------------------------------------------- boolean status = RSAUtils.verify(encodedData, public_aa, sign); System.out.println("驗證結果: " + status); } }
//----------------------------------------------無情分割線------------------------------------------------------------------------------------------
package testRSA;import java.io.ByteArrayOutputStream;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;/** * <p> * RSA公開金鑰/私密金鑰/簽名工具包 * </p> * <p> * 羅納德·李維斯特(Ron [R]ivest)、阿迪·薩莫爾(Adi [S]hamir)和倫納德·阿德曼(Leonard [A]dleman) * </p> * <p> * 字串格式的密鑰在未在特殊說明情況下都為BASE64編碼格式<br/> * 由於非對稱式加密速度極其緩慢,一般檔案不使用它來加密而是使用對稱式加密,<br/> * 非對稱式加密演算法可以用來對對稱式加密的祕密金鑰加密,這樣保證密鑰的安全也就保證了資料的安全 * </p> * * @author IceWee * @date 2012-4-26 * @version 1.0 */public class RSAUtils { /** * 密碼編譯演算法RSA */ public static final String KEY_ALGORITHM = "RSA"; /** * 簽名演算法 */ public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; /** * 擷取公開金鑰的key */ private static final String PUBLIC_KEY = "RSAPublicKey"; /** * 擷取私密金鑰的key */ private static final String PRIVATE_KEY = "RSAPrivateKey"; /** * RSA最大加密明文大小 */ private static final int MAX_ENCRYPT_BLOCK = 117; /** * RSA最大解密密文大小 */ private static final int MAX_DECRYPT_BLOCK = 128; /** * 產生金鑰組(公開金鑰和私密金鑰) * @throws Exception */ public static Map<String, Object> genKeyPair() 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; } /** * 用私密金鑰對資訊產生數位簽章 * @param data 已加密資料 * @param privateKey 私密金鑰(BASE64編碼) * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(privateK); signature.update(data); return Base64Utils.encode(signature.sign()); } /** * 校正數位簽章 * @param data 已加密資料 * @param publicKey 公開金鑰(BASE64編碼) * @param sign 數位簽章 * @return * @throws Exception * */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey publicK = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(publicK); signature.update(data); return signature.verify(Base64Utils.decode(sign)); } /** * 私密金鑰解密 * @param encryptedData 已加密資料 * @param privateKey 私密金鑰(BASE64編碼) * @throws Exception */ public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對資料分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } /** * 公開金鑰解密 * @param encryptedData 已加密資料 * @param publicKey 公開金鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對資料分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } /** * 公開金鑰加密 * @param data 來源資料 * @param publicKey 公開金鑰(BASE64編碼) * @throws Exception */ public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); // 對資料加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對資料分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } /** * <p> * 私密金鑰加密 * </p> * * @param data 來源資料 * @param privateKey 私密金鑰(BASE64編碼) * @return * @throws Exception */ public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對資料分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } /** * 擷取私密金鑰 * @param keyMap 金鑰組 * @return * @throws Exception */ public static String getPrivateKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PRIVATE_KEY); return Base64Utils.encode(key.getEncoded()); } /** * 擷取公開金鑰 * @param keyMap 金鑰組 * @throws Exception */ public static String getPublicKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PUBLIC_KEY); return Base64Utils.encode(key.getEncoded()); }}