RSA加密算法介绍及Java工具类
Posted 格子衫111
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RSA加密算法介绍及Java工具类相关的知识,希望对你有一定的参考价值。
一、RSA加密算法介绍
当今重要的三类加密算法:非对称加密、对称加密以及哈希算法(HASH严格说不是加密算法,但由于其不可逆性,已成为加密算法中的一个重要构成部分)。
1976年以前,所有的加密方法都是同一种模式:加密和解密使用同样规则(简称"密钥"),这被称为"对称加密算法",使用相同的密钥,两次连续的对等加密运算后会恢复原始文字,也有很大的安全隐患。
1976年,两位美国计算机学家Whitfield Diffie 和 Martin Hellman,提出了一种崭新构思,可以在不直接传递密钥的情况下,完成解密。这被称为"Diffie-Hellman密钥交换算法"。也正是因为这个算法的产生,人类终于可以实现非对称加密了:A给B发送信息
1.B要先生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
2.A获取B的公钥,然后用它对信息加密。
3.B得到加密后的信息,用私钥解密。
理论上如果公钥加密的信息只有私钥解得开,那么只要私钥不泄漏,通信就是安全的。
1977年,三位数学家Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字命名,叫做RSA算法。从那时直到现在,RSA算法一直是最广为使用的"非对称加密算法"。毫不夸张地说,只要有计算机网络的地方,就有RSA算法。这种算法非常可靠,密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长RSA密钥是232个十进制位,也就是768个二进制位,因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全,当然量子计算机除外。
总结:
RSA加密算法是一种非对称加密算法,所谓非对称,就是指该算法加密和解密使用不同的密钥,即使用加密密钥进行加密、解密密钥进行解密。在RAS算法中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。
二、公钥私钥介绍
-
公钥与私钥是成对出现的;
-
私钥文件中包含了公钥数据,所以可以基于私钥导出公钥;
-
密钥越长,越难破解,所以2048位密钥比1024位密钥要更安全;
-
公钥和私钥都是密钥,被公开的那个就是公钥,没有被公开的那个就是私钥。
-
公钥和私钥都可以用于加解密操作,用公钥加密的数据只能由对应的私钥解密,反之亦然。
tips:
1、私钥用于签名、公钥用于验签
签名和加密作用不同,签名并不是为了保密,而是为了保证这个签名是由特定的某个人签名的,而不是被其它人伪造的签名,所以私钥的私有性就适合用在签名用途上。
私钥签名后,只能由对应的公钥解密,公钥又是公开的(很多人可持有),所以这些人拿着公钥来解密,解密成功后就能判断出是持有私钥的人做的签名,验证了身份合法性。
2、公钥用于加密、私钥用于解密,这才能起到加密作用
因为公钥是公开的,很多人可以持有公钥。若用私钥加密,那所有持有公钥的人都可以进行解密,这是不安全的!
若用公钥加密,那只能由私钥解密,而私钥是私有不公开的,只能由特定的私钥持有人解密,保证的数据的安全性
虽然公钥和私钥都可以加解密,但是用法一般如下:
公钥加密、私钥解密、私钥签名、公钥验签。
三、Java工具类
下面介绍两种工具类:
1、公钥在客户端,私钥在服务端。公钥用于加密,私钥用于解密。
pom引包
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
java工具类
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RSAUtils
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* 获取密钥对
*
* @return 密钥对
*/
public static KeyPair getKeyPair() throws Exception
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(1024);
return generator.generateKeyPair();
/**
* 获取私钥
*
* @param privateKey 私钥字符串
* @return
*/
public static PrivateKey getPrivateKey(String privateKey) throws Exception
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
return keyFactory.generatePrivate(keySpec);
/**
* 获取公钥
*
* @param publicKey 公钥字符串
* @return
*/
public static PublicKey getPublicKey(String publicKey) throws Exception
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
return keyFactory.generatePublic(keySpec);
/**
* RSA加密
*
* @param data 待加密数据
* @param publicKey 公钥
* @return
*/
public static String encrypt(String data, PublicKey publicKey) throws Exception
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int inputLen = data.getBytes().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.getBytes(), offset, MAX_ENCRYPT_BLOCK);
else
cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_ENCRYPT_BLOCK;
byte[] encryptedData = out.toByteArray();
out.close();
// 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
// 加密后的字符串
return new String(Base64.encodeBase64String(encryptedData));
/**
* RSA解密
*
* @param data 待解密数据
* @param privateKey 私钥
* @return
*/
public static String decrypt(String data, PrivateKey privateKey) throws Exception
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] dataBytes = Base64.decodeBase64(data);
int inputLen = dataBytes.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(dataBytes, offset, MAX_DECRYPT_BLOCK);
else
cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_DECRYPT_BLOCK;
byte[] decryptedData = out.toByteArray();
out.close();
// 解密后的内容
return new String(decryptedData, "UTF-8");
/**
* 签名
*
* @param data 待签名数据
* @param privateKey 私钥
* @return 签名
*/
public static String sign(String data, PrivateKey privateKey) throws Exception
byte[] keyBytes = privateKey.getEncoded();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(key);
signature.update(data.getBytes());
return new String(Base64.encodeBase64(signature.sign()));
/**
* 验签
*
* @param srcData 原始字符串
* @param publicKey 公钥
* @param sign 签名
* @return 是否验签通过
*/
public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception
byte[] keyBytes = publicKey.getEncoded();
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey key = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(key);
signature.update(srcData.getBytes());
return signature.verify(Base64.decodeBase64(sign.getBytes()));
public static void main(String[] args)
try
// 生成密钥对
KeyPair keyPair = getKeyPair();
// String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIb3B054H+Yw87yezuwaV0M+TXthoBmWtKHKer5M9u1/t/0/5ZwBDEaWnwowPyhkHWsZk7EPaL8Lgsl0h4/DUgJrH50y6ZvYmVgulxD3EDe46hywzBO62hT2wxEbARmN+8j//1xkTYXVxu7sbNV5d+4SxASe29OBqrukYys+NKuJAgMBAAECgYBh7vCDVRE4lH7YeJgHpNl7NsM8a0ukJcIuwGEuo2RuU8XrYyk2eWAx/GutFfNOWM8r/uQ3j8nfDvg5PHB9tipT9xxCnFgwOeMB2+/ofOXeicKI7UFyW1LWbEYOKe3QQmzWa3vXCn2LsVnBAHcbdHlz134wKr7VJc+t1QeU03EKgQJBAO0zmzFyDIk2iBJOxR5bRWMBmK6I7S9E364X3lEwOkK/WtTF+9H0E6tojxoGAnuLDI+K+Zf0xu5d5YARlWmlYXkCQQCRqTmQGjo9BGGpr2u0oF04yNek3G9e9ysXwQktDPmgnn4GsSrrp3mcb+Z1/2xfmW2fWwCcWiCSFwAo3YSb9KaRAkAB7dqEQ24wq33d0EAwKAPfc0LfoIN1T/UVwGHxfRfsNQwzEM0kfvyt9zK6vnPEt3PJsxKmlroLdD4KlZoGeu7ZAkAmD8cn3YKcURnIAjutrj3NycV3odZERWfwRBPGvt4311JtIzxo6ZFAjIj3CnBiJrBbdKcbM/3QzsvO4dt1+R7RAkEAgMDvRc3Um1mQqt3xoxT3VYUEh8LQxF72x+dsXrPzoggFLvCXSlA7WQJpyDqHK8x2HSXvazB82Ei1uro58sd0Hw==";
// String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCG9wdOeB/mMPO8ns7sGldDPk17YaAZlrShynq+TPbtf7f9P+WcAQxGlp8KMD8oZB1rGZOxD2i/C4LJdIePw1ICax+dMumb2JlYLpcQ9xA3uOocsMwTutoU9sMRGwEZjfvI//9cZE2F1cbu7GzVeXfuEsQEntvTgaq7pGMrPjSriQIDAQAB";
System.out.println("私钥:" + privateKey);
System.out.println("公钥:" + publicKey);
// RSA加密
String data = "test";
String encryptData = encrypt(data, getPublicKey(publicKey));
System.out.println("加密后内容:" + encryptData);
// RSA解密
String decryptData = decrypt(encryptData, getPrivateKey(privateKey));
System.out.println("解密后内容:" + decryptData);
// RSA签名
String sign = sign(data, getPrivateKey(privateKey));
// RSA验签
boolean result = verify(data, getPublicKey(publicKey), sign);
System.out.print("验签结果:" + result);
catch (Exception e)
e.printStackTrace();
System.out.print("加解密异常");
2、AB两个平台对接,双方相互交换公钥,自己保存私钥。
A加密:先用A的私钥加密,再用B的公钥加密;
B解密:先用B的私钥解密,再用A的公钥解密
package com.zwt.demo.util;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
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;
/**
* RSA工具类
*/
public class RSAUtil
/**
* 加密算法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";
/**
* 初始化密钥对生成器时,指定密钥大小的整数值(安全漏洞,长度至少为2048)
*/
private static final int KEY_PAIR_INIT_SIZE = 2048;
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 245;
/**
* RSA最大解密密文大小,
* RSA 位数 如果采用1024 上面最大加密和最大解密则须填写: 117 128
* RSA 位数 如果采用2048 上面最大加密和最大解密则须填写: 245 256
*/
private static final int MAX_DECRYPT_BLOCK = 256;
/**
* 生成密钥对(公钥和私钥)
*/
public static Map<String, Object> genKeyPair() throws Exception
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(KEY_PAIR_INIT_SIZE);
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 keyMap 密钥对
* @return
*/
public static String getPrivateKey(Map<String, Object> keyMap)
Key key = (Key) keyMap.get(PRIVATE_KEY);
return Base64.encodeBase64String(key.getEncoded());
/**
* 获取公钥
*
* @param keyMap 密钥对
* @return
*/
public static String getPublicKey(Map<String, Object> keyMap)
Key key = (Key) keyMap.get(PUBLIC_KEY);
return Base64.encodeBase64String(key.getEncoded());
/**
* 私钥解密
*
* @param encryptedData 已加密数据
* @param privateKey 私钥(BASE64编码)
*/
private static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception
byte[] keyBytes = Base64.decodeBase64(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);
return encryptData(encryptedData, cipher, MAX_DECRYPT_BLOCK);
/**
* 公钥解密
*
* @param encryptedData 已加密数据
* @param publicKey 公钥(BASE64编码)
*/
private static byte以上是关于RSA加密算法介绍及Java工具类的主要内容,如果未能解决你的问题,请参考以下文章