背景
最近有接触到加密相关的内容,本期以非对称加密为例子,做个简单的总结和记录。首先了解下非对称加密,简单来说非对称指的是加密和解密用不同的秘钥,典型的RSA,这个算法名称是基于三个发明人的名字首字母取的;而对称加密必须要在加解密使用相同的秘钥,典型的AES。这里细节不多展开阐述,涉及到很多数学原理,如大数的质因数分解等,感兴趣的可以找找李永乐等网上比较优秀的科普。这篇文章只是java原生实现的加解密例子。至于其他的如md5,hash等,如果从主观可读的角度来说,也可以称为加密。
描述
如下的示例是使用Java原生实现RSA的加密解密,包括用公钥加密,然后私钥解密;或者使用私钥加密,然后公钥解密。注意不同key大小,限制的解密内容大小也不一样,感兴趣的同学可以试试修改key大小和加密内容长度来试试。还有要注意的是RSA加密有一定的性能损耗。
代码
import lombok.Data;
import org.junit.Test;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
@Data
public class CipherTest {
public static RSAPublicKey rsaPublicKey;
public static RSAPrivateKey rsaPrivateKey;
static {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
System.out.println("pub:" + Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded()));
System.out.println("pri:" + Base64.getEncoder().encodeToString(rsaPrivateKey.getEncoded()));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
//加密数据
String text = "abcdefghijklmn";
//公钥加密私钥解密
@Test
public void securityByPub() {
String s = encodeByPub(text);
System.out.println(s);
System.out.println(decodeByPri(s));
}
//私钥加密公钥解密
@Test
public void securityByPri() {
String s = encodeByPri(text);
System.out.println(s);
System.out.println(decodeByPub(s));
}
//公钥加密
private String encodeByPub(String text) {
try {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] res = cipher.doFinal(text.getBytes());
return Base64.getEncoder().encodeToString(res);
} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
//私钥加密
private String encodeByPri(String text) {
try {
RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(rsaPrivateKey.getModulus(), rsaPrivateKey.getPrivateExponent());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(rsaPrivateKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] res = cipher.doFinal(text.getBytes());
return Base64.getEncoder().encodeToString(res);
} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
//私钥解密
private String decodeByPri(String encrypt) {
try {
byte[] data = Base64.getDecoder().decode(encrypt);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] res = cipher.doFinal(data);
return new String(res);
} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
//公钥解密
private String decodeByPub(String encrypt) {
try {
byte[] data = Base64.getDecoder().decode(encrypt);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] res = cipher.doFinal(data);
return new String(res);
} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
}
总结
想了解原理相关的内容可以看如下的参考内容。
[1]. RSA原理