加密算法种类:
- 对称加密
对称加密,意味着加密和解密使用同一个秘钥,安全级别相对于非对称加密要低. - 非对称加密
非对称加密,意味着加密和解密使用不同的秘钥,安全级别相对于对称加密要高. - hash算法
hash算法是一种单向算法,不可还原成加密之前的元字符.
常用的加密算法
常见的对称加密算法
DES、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6和AES
常见的非对称加密算法
RSA、ECC、Diffie-Hellman、El Gamal、DSA
常见的Hash算法
MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1
非对称加密算法-RSA实现
依赖的POM:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
实现代码:
import com.bruce.tool.common.exception.ExceptionUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RSA {
private static final String KEY_ALGORITHM = "RSA";
private static final String RSA_SIGNATURE_ALGORITHM = "SHA1withRSA";
/**
* 初始化密钥
*/
public static KeyPair init() {
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
return keyPairGen.generateKeyPair();
} catch (Exception e) {
ExceptionUtils.printStackTrace(e);
}
return null;
}
/**
* 取得公钥
*/
public static String publicKey(KeyPair keyPair) {
if(Objects.isNull(keyPair) ){ return null; }
return Base64.encode(keyPair.getPublic().getEncoded());
}
/**
* 取得私钥
*/
public static String privateKey(KeyPair keyPair) {
if(Objects.isNull(keyPair)){ return null; }
return Base64.encode(keyPair.getPrivate().getEncoded());
}
/**
* 用公钥加密
* @param data 元数据字节码
* @param base64PublicKey base64编码过的公钥(publicKey)
* @return 加密结果
*/
public static byte[] encrypt(byte[] data, String base64PublicKey) {
try {
// 对公钥解密
byte[] keyBytes = Base64.decode(base64PublicKey);
// 取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
} catch (Exception e) {
ExceptionUtils.printStackTrace(e);
}
return new byte[0];
}
/**
* 用私钥解密
* @param data 元数据字节码
* @param base64PrivateKey base64编码过的私钥(privateKey)
* @return 解码结果
*/
public static byte[] decrypt(byte[] data, String base64PrivateKey) {
try {
// 对密钥解密
byte[] keyBytes = Base64.decode(base64PrivateKey);
// 取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
} catch (Exception e) {
ExceptionUtils.printStackTrace(e);
}
return new byte[0];
}
/**
* 签名-私钥签名
* @param data 元数据字节码
* @param base64PrivateKey base64编码过的私钥
* @return 签名结果
*/
public static byte[] sign(byte[] data, String base64PrivateKey){
try {
// Base64 --> Key
byte[] bytes = Base64.decode(base64PrivateKey);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
// Sign
Signature signature = Signature.getInstance(RSA_SIGNATURE_ALGORITHM);
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
} catch (Exception e) {
ExceptionUtils.printStackTrace(e);
}
return new byte[0];
}
/**
* 验签-公钥验签
*
* @param data 需要验签的字符串
* @param base64PublicKey base64编码之后的公钥
* @param sign 需要验证的签名
* @return
*/
public static boolean verify(byte[] data, String base64PublicKey, String sign) {
try {
// Base64 --> Key
byte[] bytes = Base64.decode(base64PublicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicKey = keyFactory.generatePublic(keySpec);
// verify
Signature signature = Signature.getInstance(RSA_SIGNATURE_ALGORITHM);
signature.initVerify(publicKey);
signature.update(data);
return signature.verify(Base64.decode(sign));
} catch (Exception e) {
ExceptionUtils.printStackTrace(e);
}
return false;
}
}
测试类:
import com.bruce.tool.common.util.LogUtils;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.security.KeyPair;
@Slf4j
public class RSATest {
/**生成签名**/
@Test
public void createKeys() {
KeyPair keyPair = RSA.init();
LogUtils.info(log,RSA.publicKey(keyPair));
LogUtils.info(log,RSA.privateKey(keyPair));
}
/**签名和验签**/
@Test
public void signAndVerify() {
KeyPair keyPair = RSA.init();
String publicKey = RSA.publicKey(keyPair));
String privateKey = RSA.privateKey(keyPair));
String payload = "a=1&b=2&c=3";
byte[] sign = RSA.sign(payload.getBytes(),privateKey);
LogUtils.info(log,Base64.encode(sign));
boolean verify = RSA.verify(payload.getBytes(),publicKey,Base64.encode(sign));
LogUtils.info(log,verify);
}
/**加密解密**/
@Test
public void encryptAndDecrypt() {
KeyPair keyPair = RSA.init();
String publicKey = RSA.publicKey(keyPair));
String privateKey = RSA.privateKey(keyPair));
String payload = "123456";
byte[] encrypts = RSA.encrypt(payload.getBytes(),publicKey);
LogUtils.info(log,Base64.encode(encrypts));
byte[] decrypts = RSA.decrypt(Base64.decode(Base64.encode(encrypts)),privateKey);
LogUtils.info(log,new String(decrypts));
}
}
补充说明
-
在做计算算法概念确定的时候,最初给加密算法想当然的给列了如下的种类:
1.不可逆加密(不可解密) 不可逆,意味着加密之后,不能被解密. 2.可逆加密(可解密) A.对称加密 对称加密,意味着加密和解密使用同一个秘钥,安全级别相对于非对称加密要低. B.非对称加密 非对称加密,意味着加密和解密使用不同的秘钥,安全级别相对于对称加密要高.
在想说明一下MD5的时候,觉着不太精确,怕误导大家,于是,到CSDN首页查了一下,发现一篇文章MD5到底是不是加密算法,于是修改了关于算法的种类说明.
-
关于加密算法,还有许多知识点,在此并没有细说,因为这片文章的目的是"开箱即用".
-
文章里边使用到lombok,使用ide的童鞋,请安装对应的lombok插件.
-
文章里边使用到ExceptionUtils以及LogUtils是我自己封装的工具类,大家用的时候,可以替换成自己的.
参考文献
1.百度百科-算法种类说明
2.百度百科-RSA算法说明
3.博客园-常用加密算法概述