1. 程式人生 > >Java使用非對稱數據加密RSA加密解密

Java使用非對稱數據加密RSA加密解密

ner tco init git turn comm [] 4類 fse

  emmmmmm就是呢,我今天研究了一下非對稱數據加密RSA的使用,算法什麽的暫時不研究,加密算法還有很多,以後再研究吧,就醬(>人<;)。非對稱加密算法需要兩個密鑰:公開密鑰(publicKey)和私有密鑰(privateKey);如果用公有密鑰加密,對應的就是要私有密鑰才能解密;反過來就是私鑰加密,公鑰解密。

  然後就來實現一下RSA加密的工具類吧

  註意:RSA加密明文最大長度是117字節,解密要求密文最大長度為128字節,所以再加密和解密的時候要分段進行,就是每117字節就加密,然後再把這一節節拼起來。

  1 public class RSAUtil {
  2 
  3     public
static String KEY_PAIRGENO = "RSA"; 4 public static String PUBLIC_KEY = "PUBLIC_KEY"; 5 public static String PRIVATE_KEY = "PRIVATE_KEY"; 6 public static final String CHARSET = "UTF-8"; 7 8 public static HashMap<String, String> keyMap = new HashMap<>(2); 9 10
public static void init() throws Exception { 11 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_PAIRGENO); 12 keyPairGen.initialize(1024); 13 KeyPair keyPair = keyPairGen.generateKeyPair(); 14 String publicKey = getPublicKeyStr(keyPair.getPublic());
15 String privateKey = getPrivateKeyStr(keyPair.getPrivate()); 16 17 keyMap.put(PUBLIC_KEY, publicKey); 18 keyMap.put(PRIVATE_KEY,privateKey); 19 } 20 21 22 private static String getPrivateKeyStr(PrivateKey privateKey) throws Exception { 23 return Base64.encodeBase64URLSafeString(privateKey.getEncoded()); 24 } 25 26 private static String getPublicKeyStr(PublicKey publicKey) throws Exception { 27 return Base64.encodeBase64URLSafeString(publicKey.getEncoded()); 28 } 29 30 /** 31 * 把字符串公鑰轉為 RSAPublicKey 公鑰 32 */ 33 public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException { 34 //通過X509編碼的Key指令獲得公鑰對象 35 KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIRGENO); 36 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey)); 37 RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec); 38 return key; 39 } 40 41 /** 42 * 把字符串私鑰轉為 RSAPrivateKey 私鑰 43 */ 44 public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException { 45 //通過PKCS#8編碼的Key指令獲得私鑰對象 46 KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIRGENO); 47 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)); 48 RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec); 49 return key; 50 } 51 52 /** 53 * 公鑰加密, 加密明文最大長度是117字節 54 */ 55 public static String encryptByPublicKey(String msg, RSAPublicKey publicKey) throws Exception{ 56 Cipher cipher = Cipher.getInstance(KEY_PAIRGENO); 57 cipher.init(Cipher.ENCRYPT_MODE,publicKey); 58 int keySize = publicKey.getModulus().bitLength();//1024 59 byte[] data = msg.getBytes(CHARSET); 60 byte[] encryptedData = rsaSplitCode(cipher, data, Cipher.ENCRYPT_MODE, keySize); 61 String mi= Base64.encodeBase64URLSafeString(encryptedData); 62 return mi; 63 64 65 } 66 67 /* 68 * 私鑰解密,解密要求密文最大長度為128字節 69 * */ 70 public static String decryptByPrivateKey(String rsaMsg, RSAPrivateKey privateKey) throws Exception{ 71 Cipher cipher = Cipher.getInstance(KEY_PAIRGENO); 72 cipher.init(Cipher.DECRYPT_MODE, privateKey); 73 int keySize = privateKey.getModulus().bitLength();//長度是1024 74 byte[] data = Base64.decodeBase64(rsaMsg); 75 byte[] decryptedData = rsaSplitCode(cipher, data, Cipher.DECRYPT_MODE, keySize); 76 String ming = new String(decryptedData, CHARSET); 77 return ming; 78 } 79 80 /*私鑰加密*/ 81 public static String encryptByPrivate(String msg, RSAPrivateKey privateKey) throws Exception{ 82 Cipher ciper = Cipher.getInstance(KEY_PAIRGENO); 83 ciper.init(Cipher.ENCRYPT_MODE,privateKey); 84 int keySize = privateKey.getModulus().bitLength(); 85 byte[] data = msg.getBytes(CHARSET); 86 byte[] encryptedData = rsaSplitCode(ciper, data, Cipher.ENCRYPT_MODE,keySize); 87 String mi = Base64.encodeBase64URLSafeString(encryptedData); 88 return mi; 89 } 90 91 /*公鑰解密*/ 92 public static String decrytByPublic(String msg, RSAPublicKey publicKey) throws Exception{ 93 Cipher ciper = Cipher.getInstance(KEY_PAIRGENO); 94 ciper.init(Cipher.DECRYPT_MODE, publicKey); 95 int keySize = publicKey.getModulus().bitLength(); 96 byte[] data = Base64.decodeBase64(msg); 97 byte[] decryptedData = rsaSplitCode(ciper, data, Cipher.DECRYPT_MODE,keySize); 98 String ming = new String(decryptedData,CHARSET); 99 return ming; 100 } 101 102 103 104 private static byte[] rsaSplitCode(Cipher cipher, byte[] data,int opmode ,int keySize){ 105 int maxBlock = 0; 106 if(opmode == Cipher.DECRYPT_MODE) 107 maxBlock = keySize / 8;//解密要求最大長度是128 108 else 109 maxBlock = keySize / 8 -11; //加密要求最大長度是117 110 111 int inputLen = data.length; 112 ByteArrayOutputStream out = new ByteArrayOutputStream(); 113 int offSet = 0; 114 byte[] cache; 115 int i = 0; 116 // 對數據分段解密 117 try { 118 while (inputLen - offSet > 0) { 119 if (inputLen - offSet > maxBlock) { 120 cache = cipher.doFinal(data, offSet, maxBlock); 121 } else { 122 cache = cipher.doFinal(data, offSet, inputLen - offSet); 123 } 124 out.write(cache, 0, cache.length); 125 i++; 126 offSet = i * maxBlock; 127 } 128 byte[] bytes = out.toByteArray(); 129 out.close(); 130 return bytes; 131 } catch (Exception e) { 132 throw new RuntimeException("加解密閥值為["+maxBlock+"]的數據時發生異常", e); 133 } 134 } 135 136 137 138 139 140 public static void main(String[] args) throws Exception { 141 init(); 142 String msg = "我是冬竹"; 143 System.out.println("公鑰加密-私鑰解密:"); 144 String mi = encryptByPublicKey(msg, getPublicKey(keyMap.get(PUBLIC_KEY))); 145 System.out.println("密文:" + mi); 146 147 String ming = decryptByPrivateKey(mi , getPrivateKey(keyMap.get(PRIVATE_KEY))); 148 System.out.println("明文:" + ming); 149 150 System.out.println("私鑰加密-公鑰解密:"); 151 String mi2 = encryptByPrivate(msg, getPrivateKey(keyMap.get(PRIVATE_KEY))); 152 System.out.println("密文:" + mi2); 153 154 String ming2 = decrytByPublic(mi2 , getPublicKey(keyMap.get(PUBLIC_KEY))); 155 System.out.println("明文:" + ming); 156 } 157 158 }

  

  這這這好長啊........

  說一下這個過程:

    1. keyPair.getPublic() 獲得的字節數組 用encodeBase64URLSafeString() 編碼成字符串,也就是我們有時候用的那種很多字母的那種公鑰(私鑰)

    2. 用decodeBase64() 把公鑰解碼成字節數組,然後通過X509編碼的Key指令獲得公鑰對象 RSAPublicKey

 加密字符串的過程:

    1. msg.getBytes() 獲得字符數組, 然後用rsaSplitCode() 方法加密,再用encodeBase64URLSafeString編碼成字符串(密文)

 解密字符串的過程:

    1. decodeBase64() 把密文解碼成字符數組,再用new String()方法轉為字符串

然後我用的Base64類是commons-net-3.1.jar 裏的,這個是我的maven倉庫裏(maven真的太方便了(●ˇ?ˇ●))

放上這個:https://github.com/MoisAbby/XZUtils, 以後會把我攢的好用的東西都放上來

Java使用非對稱數據加密RSA加密解密