版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xybelieve1990/article/details/83088697
加密举例
比如有两个用户Alice和Bob,Alice想把一段明文通过双钥加密的技术发送给Bob,Bob有一对公钥和私钥,那么加密解密的过程如下:
- Bob将他的公开密钥传送给Alice。
- Alice用Bob的公开密钥加密她的消息,然后传送给Bob。
- Bob用他的私人密钥解密Alice的消息。
上面的过程可以用下图表示,Alice使用Bob的公钥进行加密,Bob用自己的私钥进行解密。
例子和图出自《网络安全基础 应用与标准第二版》
RSA算法
RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
编码实现
package encrypt;
import org.apache.tomcat.util.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.*;
import java.security.*;
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加解密及签名校验
* RSA签名算法:MD2withRSA、MD5withRSA、SHA1withRSA,为jdk实现
* 1.秘钥长度为64的倍数,在512~65536之间,默认长度1024,签名长度和秘钥长度相同
* 签名算法:SHA256withRSA,为BC实现,秘钥默认长度为2048
*/
public class RsaSecurity {
//非对称加密算法
public static final String KEY_ALGORITHM = "RSA";
//签名算法
public static final String SIGN_ALGORITHM = "SHA256withRSA";
/**
* 秘钥长度,必须是64的倍数,在512~65536之间
*/
private static final int KEY_SIZE = 512;
//公钥
private static final String PUBLIC_KEY = "PUBLIC_KEY";
//私钥
private static final String PRIVATE_KEY = "PRIVATE_KEY";
private static final String PUBLIC_PATH = "/Users/public.key";
private static final String PRIVATE_PATH = "/Users/private.key";
public static void main(String[] args) throws Exception{
/**
* 加解密验证
*/
//初始化秘钥对
Map<String, Object> keyMap = RsaSecurity.initKey();
//私钥
byte[] privateKey = RsaSecurity.getPrivateKey(keyMap);
//公钥
byte[] publicKey = RsaSecurity.getPublicKey(keyMap);
System.out.println("私钥:" + Base64.encodeBase64String(privateKey));
System.out.println("公钥:" + Base64.encodeBase64String(publicKey));
String source = "Burning by Maria Arredondo";
byte[] encryptData = RsaSecurity.encryptByPrivateKey(source.getBytes(), privateKey);
System.out.println("私钥加密后数据:" + new String(encryptData));
byte[] decryptData = RsaSecurity.decryptByPublicKey(encryptData, publicKey);
System.out.println("公钥解密后数据:" + new String(decryptData));
/**
* 签名验证
*/
String privateKeyStr = readKeyFromFile(PRIVATE_PATH);
String publicKeyStr = readKeyFromFile(PUBLIC_PATH);
String signSource = "Love Mail";
String sign = signByPrivateKey(signSource, privateKeyStr);
System.out.println("私钥签名值:" + sign);
System.out.println("公钥签名校验结果:" + verifySignByPublic(signSource, publicKeyStr, sign));
}
/**
* 初始化秘钥对
* @return 秘钥map
* @throws Exception
*/
public static Map<String, Object> initKey() throws Exception{
//实例化秘钥生成器
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
//初始化秘钥生成器
keyPairGenerator.initialize(KEY_SIZE);
//生成秘钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
//公钥
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
//私钥
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
//保存公钥
RsaSecurity.saveKeyForFile(PUBLIC_PATH, Base64.encodeBase64String(rsaPublicKey.getEncoded()));
//保存私钥
RsaSecurity.saveKeyForFile(PRIVATE_PATH, Base64.encodeBase64String(rsaPrivateKey.getEncoded()));
//将秘钥存储在map中
Map<String, Object> keyMap = new HashMap<>();
keyMap.put(PUBLIC_KEY, rsaPublicKey);
keyMap.put(PRIVATE_KEY, rsaPrivateKey);
return keyMap;
}
/**
* 私钥加密
* @param data 待加密数据
* @param key 秘钥
* @return byte[] 加密数据
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception{
//取得私钥
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
//实例化秘钥工厂
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成私钥
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//私钥加密数据
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 公钥解密
* @param data 待解密数据
* @param key 秘钥
* @return byte[] 解密数据
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception{
//取得公钥(材料转换)
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
//实例化秘钥工厂
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成公钥
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
//解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 私钥签名
* @param content 待签名数据
* @param rsaPrivateKey 签名秘钥
* @return 签名值
* @throws Exception
*/
public static String signByPrivateKey(String content, String rsaPrivateKey) throws Exception{
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(rsaPrivateKey));
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//获取秘钥
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//实例化签名
Signature signature = Signature.getInstance(SIGN_ALGORITHM);
//初始化签名
signature.initSign(privateKey);
signature.update(content.getBytes());
byte[] sign = signature.sign();
return Base64.encodeBase64String(sign);
}
/**
* 公钥验签
* @param content 报文数据
* @param rsaPublicKey 签名秘钥
* @param sign 签名值
* @return 验签是否通过
* @throws Exception
*/
public static boolean verifySignByPublic(String content, String rsaPublicKey, String sign) throws Exception{
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(rsaPublicKey));
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//获取公钥
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
//实例化签名
Signature signature = Signature.getInstance(SIGN_ALGORITHM);
//初始化验签
signature.initVerify(publicKey);
signature.update(content.getBytes());
return signature.verify(Base64.decodeBase64(sign));
}
/**
* 获取公钥
* @param keyMap
* @return
*/
public static byte[] getPublicKey(Map<String, Object> keyMap){
Key key = (Key) keyMap.get(PUBLIC_KEY);
return key.getEncoded();
}
/**
* 获取私钥
* @param keyMap
* @return
*/
public static byte[] getPrivateKey(Map<String, Object> keyMap){
Key key = (Key) keyMap.get(PRIVATE_KEY);
return key.getEncoded();
}
/**
* 生成文件保存秘钥
* @param filePath
* @param keyStr
*/
public static void saveKeyForFile(String filePath, String keyStr){
try{
File file = new File(filePath);
if(!file.exists()){
file.mkdir();
}
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
bw.write(keyStr);
bw.flush();
bw.close();
}catch(IOException e){
e.printStackTrace();
}
}
/**
* 从文件中读取秘钥
* @param filePath
* @return
*/
public static String readKeyFromFile(String filePath){
try {
BufferedReader br = new BufferedReader(new FileReader(new File(filePath)));
String readLine = null;
StringBuilder sb = new StringBuilder();
while((readLine=br.readLine()) != null){
sb.append(readLine);
}
br.close();
return sb.toString();
}catch (IOException e){
e.printStackTrace();
}
return null;
}
}