package com.crypto;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class CipherTests {
String originalText = "我是要加密的原文本内容!!!!!";
@BeforeEach
void before() {
System.out.println("加密前的原文: " + originalText);
}
/**
* 对称加密 AES/DES
*
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
* @throws InvalidAlgorithmParameterException
*/
@Test
void symmetry() throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
//对称密钥算法
String algorithm = "AES";//DES
String algorithmKey = "1234567812345678";//DES长度为8
Key aesSecretKey = new SecretKeySpec(algorithmKey.getBytes(), algorithm);
//密码器 "AES/CBC/PKCS5Padding" 官网描述:https://docs.oracle.com/en/java/javase/17/docs/api/java.base/javax/crypto/Cipher.html
//AES:算法; CBC/ECB:模式; PKCS5Padding/NoPadding:填充 对齐8位
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//CBC模式初始向量 必须长度为16
String iv = "8765432187654321";
//IV length: must be 16 bytes long
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
//初始化密码器 Cipher.ENCRYPT_MODE:加密
cipher.init(Cipher.ENCRYPT_MODE, aesSecretKey, ivParameterSpec);
//执行加密
byte[] cipherBytes = cipher.doFinal(originalText.getBytes());
//打印加密字符串
printBase64CipherText(cipherBytes);
//初始化密码器 Cipher.DECRYPT_MODE:解密
cipher.init(Cipher.DECRYPT_MODE, aesSecretKey, ivParameterSpec);
byte[] decryptOriginal = cipher.doFinal(cipherBytes);
System.out.println(algorithm + "解密后的原文: " + new String(decryptOriginal));
}
/**
* Base64.encode后的公钥
*/
String publicKeyEncodeStr = null;
/**
* 公钥对象
*/
PublicKey publicKey = null;
/**
* Base64.encode后的私钥
*/
String privateKeyEncodeStr = null;
/**
* 私钥对象
*/
PrivateKey privateKey = null;
/**
* 非对称加密 RSA
*
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeySpecException
* @throws InvalidKeyException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
*/
@Test
void asymmetrical() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
//非对称加密算法
String algorithm = "RSA";
//生成密钥对
keyPairGenerator(algorithm);
//从Base64.encode的字符串还原密钥对
keyStrToKey(algorithm);
//密码器
Cipher cipher = Cipher.getInstance(algorithm);
//公钥加密
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] cipherBytes = cipher.doFinal(originalText.getBytes());
//打印加密字符串
printBase64CipherText(cipherBytes);
//初始化 私钥解密
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptOriginal = cipher.doFinal(cipherBytes);
System.out.println(algorithm + "解密后的原文: " + new String(decryptOriginal));
}
/**
* 数字签名 SHA3-512withRSA
*
* 签名流程
* 1.使用散列算法(SHA、MD5)对原文进行数字摘要
* 2.使用私钥对数字摘要进行加密
* 校验流程
* 1.使用相同散列算法对原文进行数字摘要
* 2.将对方加密后的数字摘要使用公钥解密
* 3.比较摘要是否相等
*
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws InvalidKeyException
* @throws SignatureException
*/
@Test
void signature() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
//非对称加密算法
String algorithm = "RSA";
//生成密钥对
keyPairGenerator(algorithm);
//从Base64.encode的字符串还原密钥对
keyStrToKey(algorithm);
//签名算法
String hashAlgorithm = "SHA3-512withRSA";
Signature signature = Signature.getInstance(hashAlgorithm);
//初始化 私钥进行签名
signature.initSign(privateKey);
//要签名的原文
signature.update(originalText.getBytes());
//执行签名
byte[] signByte = signature.sign();
//打印签名字符串
printBase64CipherText(signByte);
//校验签名
//初始化 公钥进行检验
signature.initVerify(publicKey);
//传入原文
signature.update(originalText.getBytes());
//传入签名
boolean verify = signature.verify(signByte);
System.out.println("签名是否正确: " + verify);
}
/**
* 打印Base64.encode后的加密字符串
*
* @param cipherBytes
*/
private void printBase64CipherText(byte[] cipherBytes) {
byte[] cipherEncodeBytes = Base64.getEncoder().encode(cipherBytes);
String cipherEncodeText = new String(cipherEncodeBytes);
System.out.println("Base64.encode后的加密字符串 " + cipherEncodeText);
}
/**
* 生成密钥对
* Key -> String
*
* @param algorithm 密钥对算法
* @throws NoSuchAlgorithmException
*/
private void keyPairGenerator(String algorithm) throws NoSuchAlgorithmException {
//生成公/私密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
KeyPair keyPair = keyPairGenerator.genKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
//对密钥对进行Base64编码
Base64.Encoder encoder = Base64.getEncoder();
publicKeyEncodeStr = new String(encoder.encode(publicKey.getEncoded()));
privateKeyEncodeStr = new String(encoder.encode(privateKey.getEncoded()));
System.out.println("Base64.encode后的公钥字符串 " + publicKeyEncodeStr);
System.out.println("Base64.encode后的私钥字符串 " + privateKeyEncodeStr);
}
/**
* 从Base64.encode的密钥字符串获取密钥对象
* String -> Key
*
* @param algorithm
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
private void keyStrToKey(String algorithm) throws NoSuchAlgorithmException, InvalidKeySpecException {
//公私钥Base64.decode
Base64.Decoder decoder = Base64.getDecoder();
byte[] decodePublicKey = decoder.decode(publicKeyEncodeStr);
byte[] decodePrivateKey = decoder.decode(privateKeyEncodeStr);
//公钥编码
X509EncodedKeySpec publickeyX509 = new X509EncodedKeySpec(decodePublicKey);
//私钥编码
PKCS8EncodedKeySpec PrivateKeyPKCS8 = new PKCS8EncodedKeySpec(decodePrivateKey);
//密钥工厂获取密钥对象
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
publicKey = keyFactory.generatePublic(publickeyX509);
privateKey = keyFactory.generatePrivate(PrivateKeyPKCS8);
}
}
对称、非对称加密解密、数字签名
最新推荐文章于 2022-11-11 15:19:58 发布