Android中的RSA加密
阿新 • • 發佈:2018-11-13
RSA公鑰加密演算法,一種非對稱加密方式,是伺服器與客戶端之間通訊中最常用的加密方式。非對稱加密金鑰有兩個,分別為公開金鑰(publickey)和私有金鑰(privatekey),公開金鑰與私有金鑰是一對。如果用公開金鑰對資料加密,只有用對應的私有金鑰才能解密;如果用私有金鑰對資料進行加密,那麼只有對應的公開金鑰才能解密。
一般情況下都是採用公鑰加密資料,因為公鑰是向外公開大家都可以知道,但密文只有私鑰能夠解開。使用私鑰加密適合用於簽名,使用公鑰解密驗證私鑰身份。
程式碼;
測試程式碼:package com.test; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; public class RSA { private static final String ALGORITHM = "RSA"; /** * 公鑰加密 * * @param src * 明文 * @param key * 金鑰 * @return */ public static String RSAPublicEncrypt(String src, String key) { try { PublicKey pubkey = getPublicKeyFromX509(ALGORITHM, key); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, pubkey); byte bytes[] = src.getBytes("UTF-8"); byte[] encrypted = blockCipher(cipher, bytes, Cipher.ENCRYPT_MODE); return bytes2Hex(encrypted); } catch (Exception e) { return null; } } /** * 私鑰解密 * * @param src * 密文 * @param key * 金鑰 * @return */ public static String RSAPrivateDncrypt(String src, String key) { try { PrivateKey prikey = getEncodedKeySpecPKCS8(ALGORITHM, key); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, prikey); byte bytes[] = toByte(src); byte[] decrypted = blockCipher(cipher, bytes, Cipher.DECRYPT_MODE); return new String(decrypted, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 私鑰加密 * * @param src * 明文 * @param key * 金鑰 * @return */ public static String RSAPrivateEncrypt(String src, String key) { try { PrivateKey prikey = getEncodedKeySpecPKCS8(ALGORITHM, key); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, prikey); byte bytes[] = src.getBytes("UTF-8"); byte[] encrypted = blockCipher(cipher, bytes, Cipher.ENCRYPT_MODE); return bytes2Hex(encrypted); } catch (Exception e) { return null; } } /** * 公鑰解密 * * @param src * 密文 * @param key * 金鑰 * @return */ public static String RSAPublicDncrypt(String src, String key) { try { PublicKey pubkey = getPublicKeyFromX509(ALGORITHM, key); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, pubkey); byte bytes[] = toByte(src); byte[] decrypted = blockCipher(cipher, bytes, Cipher.DECRYPT_MODE); return new String(decrypted, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 得到公鑰 */ private static PublicKey getPublicKeyFromX509(String algorithm, String bysKey) throws NoSuchAlgorithmException, Exception { byte[] decodedKey = toByte(bysKey); X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodedKey); KeyFactory keyFactory = KeyFactory.getInstance(algorithm); return keyFactory.generatePublic(x509); } /** * 得到私鑰 */ private static PrivateKey getEncodedKeySpecPKCS8(String algorithm, String bysKey) throws NoSuchAlgorithmException, Exception { byte[] decodedKey = toByte(bysKey); PKCS8EncodedKeySpec PKCS8 = new PKCS8EncodedKeySpec(decodedKey); KeyFactory keyFactory = KeyFactory.getInstance(algorithm); return keyFactory.generatePrivate(PKCS8); } private static byte[] blockCipher(Cipher cipher, byte[] bytes, int mode) throws IllegalBlockSizeException, BadPaddingException { byte[] scrambled = new byte[0]; byte[] toReturn = new byte[0]; // 如果我們使用長100位元組塊加密。解密需要128長度 int length = (mode == Cipher.ENCRYPT_MODE) ? 100 : 128; byte[] buffer = null; if (bytes.length <= length) { return cipher.doFinal(bytes); } else { buffer = new byte[length]; } for (int i = 0; i < bytes.length; i++) { if ((i > 0) && (i % length == 0)) { scrambled = cipher.doFinal(buffer); toReturn = append(toReturn, scrambled); int newlength = length; if (i + length > bytes.length) { newlength = bytes.length - i; } buffer = new byte[newlength]; } buffer[i % length] = bytes[i]; } scrambled = cipher.doFinal(buffer); toReturn = append(toReturn, scrambled); return toReturn; } private static byte[] append(byte[] prefix, byte[] suffix) { byte[] toReturn = new byte[prefix.length + suffix.length]; for (int i = 0; i < prefix.length; i++) { toReturn[i] = prefix[i]; } for (int i = 0; i < suffix.length; i++) { toReturn[i + prefix.length] = suffix[i]; } return toReturn; } /** * 隨機生成金鑰對 */ public static Map<String, String> genKeyPair() { KeyPairGenerator keyPairGen = null; try { keyPairGen = KeyPairGenerator.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } // 第一個引數為祕鑰長度,當需要2048加密只需修改祕鑰長度即可 keyPairGen.initialize(1024, new SecureRandom()); KeyPair keyPair = keyPairGen.generateKeyPair(); Map<String, String> key = new HashMap<String, String>(); key.put("PrivateKey", bytes2Hex((keyPair.getPrivate().getEncoded()))); key.put("PublicKey", bytes2Hex(keyPair.getPublic().getEncoded())); return key; } /** * Byte[]轉16進位制 * * @param bts * @return */ private static String bytes2Hex(byte[] bts) { String des = ""; String tmp = null; for (int i = 0; i < bts.length; i++) { tmp = (Integer.toHexString(bts[i] & 0xFF)); if (tmp.length() == 1) { des += "0"; } des += tmp; } return des; } /** * 將16進位制轉換為byte陣列 * * @param hexString * 16進位制字串 * @return byte陣列 */ public static byte[] toByte(String hexString) { int len = hexString.length() / 2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue(); return result; } }
static Map<String, String> keyMap; public static void main(String[] args) { keyMap = RSA.genKeyPair(); String privateKey = keyMap.get("PrivateKey"); String publicKey = keyMap.get("PublicKey"); System.out.println("公鑰===" + publicKey); System.out.println("私鑰===" + privateKey); String str = RSA.RSAPublicEncrypt("123456", publicKey); System.out.println("公鑰加密後的資料:" + str); str = RSA.RSAPrivateDncrypt(str, privateKey); System.out.println("私鑰解密後的資料:" + str); str = RSA.RSAPrivateEncrypt(str, privateKey); System.out.println("私鑰加密後的資料:" + str); str = RSA.RSAPublicDncrypt(str, publicKey); System.out.println("公鑰解密後的資料:" + str); }