emmmmmm 就是呢, 我今天研究了一下非对称数据加密 RSA 的使用, 算法什么的暂时不研究, 加密算法还有很多, 以后再研究吧, 就酱 (>人<;) 非对称加密算法需要两个密钥: 公开密钥 (publicKey) 和私有密钥(privateKey); 如果用公有密钥加密, 对应的就是要私有密钥才能解密; 反过来就是私钥加密, 公钥解密
然后就来实现一下 RSA 加密的工具类吧
注意: RSA 加密明文最大长度是 117 字节, 解密要求密文最大长度为 128 字节, 所以再加密和解密的时候要分段进行, 就是每 117 字节就加密, 然后再把这一节节拼起来
- public class RSAUtil {
- public static String KEY_PAIRGENO = "RSA";
- public static String PUBLIC_KEY = "PUBLIC_KEY";
- public static String PRIVATE_KEY = "PRIVATE_KEY";
- public static final String CHARSET = "UTF-8";
- public static HashMap < String,
- String > keyMap = new HashMap < >(2);
- public static void init() throws Exception {
- KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_PAIRGENO);
- keyPairGen.initialize(1024);
- KeyPair keyPair = keyPairGen.generateKeyPair();
- String publicKey = getPublicKeyStr(keyPair.getPublic());
- String privateKey = getPrivateKeyStr(keyPair.getPrivate());
- keyMap.put(PUBLIC_KEY, publicKey);
- keyMap.put(PRIVATE_KEY, privateKey);
- }
- private static String getPrivateKeyStr(PrivateKey privateKey) throws Exception {
- return Base64.encodeBase64URLSafeString(privateKey.getEncoded());
- }
- private static String getPublicKeyStr(PublicKey publicKey) throws Exception {
- return Base64.encodeBase64URLSafeString(publicKey.getEncoded());
- }
- /**
- * 把字符串公钥转为 RSAPublicKey 公钥
- */
- public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException,
- InvalidKeySpecException {
- // 通过 X509 编码的 Key 指令获得公钥对象
- KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIRGENO);
- X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
- RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
- return key;
- }
- /**
- * 把字符串私钥转为 RSAPrivateKey 私钥
- */
- public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException,
- InvalidKeySpecException {
- // 通过 PKCS#8 编码的 Key 指令获得私钥对象
- KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIRGENO);
- PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
- RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
- return key;
- }
- /**
- * 公钥加密, 加密明文最大长度是 117 字节
- */
- public static String encryptByPublicKey(String msg, RSAPublicKey publicKey) throws Exception {
- Cipher cipher = Cipher.getInstance(KEY_PAIRGENO);
- cipher.init(Cipher.ENCRYPT_MODE, publicKey);
- int keySize = publicKey.getModulus().bitLength(); //1024
- byte[] data = msg.getBytes(CHARSET);
- byte[] encryptedData = rsaSplitCode(cipher, data, Cipher.ENCRYPT_MODE, keySize);
- String mi = Base64.encodeBase64URLSafeString(encryptedData);
- return mi;
- }
- /*
- * 私钥解密, 解密要求密文最大长度为 128 字节
- * */
- public static String decryptByPrivateKey(String rsaMsg, RSAPrivateKey privateKey) throws Exception {
- Cipher cipher = Cipher.getInstance(KEY_PAIRGENO);
- cipher.init(Cipher.DECRYPT_MODE, privateKey);
- int keySize = privateKey.getModulus().bitLength(); // 长度是 1024
- byte[] data = Base64.decodeBase64(rsaMsg);
- byte[] decryptedData = rsaSplitCode(cipher, data, Cipher.DECRYPT_MODE, keySize);
- String ming = new String(decryptedData, CHARSET);
- return ming;
- }
- /* 私钥加密 */
- public static String encryptByPrivate(String msg, RSAPrivateKey privateKey) throws Exception {
- Cipher ciper = Cipher.getInstance(KEY_PAIRGENO);
- ciper.init(Cipher.ENCRYPT_MODE, privateKey);
- int keySize = privateKey.getModulus().bitLength();
- byte[] data = msg.getBytes(CHARSET);
- byte[] encryptedData = rsaSplitCode(ciper, data, Cipher.ENCRYPT_MODE, keySize);
- String mi = Base64.encodeBase64URLSafeString(encryptedData);
- return mi;
- }
- /* 公钥解密 */
- public static String decrytByPublic(String msg, RSAPublicKey publicKey) throws Exception {
- Cipher ciper = Cipher.getInstance(KEY_PAIRGENO);
- ciper.init(Cipher.DECRYPT_MODE, publicKey);
- int keySize = publicKey.getModulus().bitLength();
- byte[] data = Base64.decodeBase64(msg);
- byte[] decryptedData = rsaSplitCode(ciper, data, Cipher.DECRYPT_MODE, keySize);
- String ming = new String(decryptedData, CHARSET);
- return ming;
- }
- private static byte[] rsaSplitCode(Cipher cipher, byte[] data, int opmode, int keySize) {
- int maxBlock = 0;
- if (opmode == Cipher.DECRYPT_MODE) maxBlock = keySize / 8; // 解密要求最大长度是 128
- else maxBlock = keySize / 8 - 11; // 加密要求最大长度是 117
- int inputLen = data.length;
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- int offSet = 0;
- byte[] cache;
- int i = 0;
- // 对数据分段解密
- try {
- while (inputLen - offSet > 0) {
- if (inputLen - offSet > maxBlock) {
- cache = cipher.doFinal(data, offSet, maxBlock);
- } else {
- cache = cipher.doFinal(data, offSet, inputLen - offSet);
- }
- out.write(cache, 0, cache.length);
- i++;
- offSet = i * maxBlock;
- }
- byte[] bytes = out.toByteArray();
- out.close();
- return bytes;
- } catch(Exception e) {
- throw new RuntimeException("加解密阀值为 [" + maxBlock + "] 的数据时发生异常", e);
- }
- }
- public static void main(String[] args) throws Exception {
- init();
- String msg = "我是冬竹";
- System.out.println("公钥加密 - 私钥解密:");
- String mi = encryptByPublicKey(msg, getPublicKey(keyMap.get(PUBLIC_KEY)));
- System.out.println("密文:" + mi);
- String ming = decryptByPrivateKey(mi, getPrivateKey(keyMap.get(PRIVATE_KEY)));
- System.out.println("明文:" + ming);
- System.out.println("私钥加密 - 公钥解密:");
- String mi2 = encryptByPrivate(msg, getPrivateKey(keyMap.get(PRIVATE_KEY)));
- System.out.println("密文:" + mi2);
- String ming2 = decrytByPublic(mi2, getPublicKey(keyMap.get(PUBLIC_KEY)));
- System.out.println("明文:" + ming);
- }
- }
这这这好长啊........
说一下这个过程:
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 真的太方便了(ˇ?ˇ))
来源: http://www.bubuko.com/infodetail-2495907.html