前言
本篇简单介绍下非对称加密以及公钥和私钥加密不同的使用场景,以及如何用Java代码实现AES加解密的工具类和例子
非对称加密简介
需要两个密钥(公钥和私钥)来进行加密和解密,公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥) ,公钥加密的信息只有私钥才能解开,私钥加密的信息只有公钥才能解开。这个公钥和私钥必须是一对的,如果用公钥对数据进行加密,那么只有使用对应的私钥才能解密,所以只要私钥不泄露,那么我
- 对于签名:私钥加密,公钥解密。好比你的签名只有你自已签的才是真的,别人签的都是假的。
们的数据就是安全的。
公钥加密或私钥加密
- 对于加密:公钥加密,私钥加密。毕竟公钥可以公开,但是私钥只有你自已知道,你也同样希望只有你自已才能解密
- 对于签名:私钥加密,公钥解密。好比你的签名只有你自已签的才是真的,别人签的都是假的。
Java实现常用的AES非对称加解密工具类
RSA 算法是非对称加解密中比较常用的加密算法,基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
在加载的时候PKCS#1 format的私钥的时候,可能会报错,需要加如下maven依赖,我在代码里loadPrivateKey也有说明
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.58</version> </dependency>
下面直接上干货,测试代码,写在main方法里了,其他说明写在注释里。
如有需要Javascript版本的RSA加解密,请看 https://blog.terrynow.com/2021/04/20/javascript-tool-rsa-encrypt-implement/
RSAUtil.java
package com.terrynow.test; import javax.crypto.Cipher; import java.nio.charset.StandardCharsets; 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.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; /** * @author Terry E-mail: yaoxinghuo at 126 dot com * @date 2021-4-14 10:51 * @description */ public class RSAUtil { public static void main(String[] args) throws Exception { PrivateKey privateKey = loadPrivateKey("-----BEGIN RSA PRIVATE KEY-----\n" + "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAJlTlMmhFxhVZ/U6xd3\n" + "TZTelu0g8a+tZYAqoOegsJXXlelthlLTzx5qkWEf4STjIMaIYtduIO1xVs1L3Gsjyl3\n" + "IhofjuVwI2qk2QVCtuVXkDvO/gPXCzur5iTDCG7Jrh5jJI5VtaVGHVH37TSWUYiowKv\n" + "SzdKViPQ1h1J/BPewI5AgMBAAECgYAwBq4kOgEx7g6SEcbIpN6ff5oaFlL3dRdQP0Fk\n" + "J+/T7f1VgktCItny5meAo5TL5GknjPXpvdJaKb3xztTk/JfS+X4uZBuEumb+UV8hWzJ\n" + "0hvxIMtVf0rwFLbEB6btiNJHDCIv2+eJSEoK2RjYF/qGb0zzFz1YGICY5Vjl2TDnlwQ\n" + "JBAPHbqEWKT1KeEXKzNBcZadglfjF+qXQmWFGN3yUrd8Xxmet+oKfhXgPgybfo8/uwM\n" + "6ijJaEYNWWU6wbvMf9jkZ8CQQCiSrTLyzEe9pObKpwGk3U2jkaYOnSKdMYebxvF9BGN\n" + "CnLsen0rDOefgHGNwUMphzWaqWESnb1TB7Mck/kanU0nAkEA3D1Zg1HKoAI/A0L62Vo\n" + "UD3c87hdYeeN9I27c1/04SXGT52XdKGNKeJ+XMTkaDITM1fETEBp6bXFpgFwLHHRwIw\n" + "JBAKExPFOyNM7BMCiM8L2jVmdidwGaBcjDZUgzKU27Nnd06mKw4oOQ5LnKtH6Mdy3XK\n" + "sm79DuuSq4eVqtK2b+yfz8CQQC7frRjmYPe9+2JrTWMbzfFlLysCn7xmdbW5rVCs8sO\n" + "5jq8YxW5nV99IVGaKjYw6wcjIGut9uZw6Mmec05CODzh\n" + "-----END RSA PRIVATE KEY-----"); PublicKey publicKey = loadPublicKey("-----BEGIN PUBLIC KEY-----\n" + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCZU5TJoRcYVWf1OsXd02U3pbtIPGv\n" + "rWWAKqDnoLCV15XpbYZS088eapFhH+Ek4yDGiGLXbiDtcVbNS9xrI8pdyIaH47lcCNq\n" + "pNkFQrblV5A7zv4D1ws7q+Ykwwhuya4eYySOVbWlRh1R9+00llGIqMCr0s3SlYj0NYd\n" + "SfwT3sCOQIDAQAB\n" + "-----END PUBLIC KEY-----"); // KeyPair keyPair = buildKeyPair(); // String privateString = base64Encode(keyPair.getPrivate().getEncoded()); // String publicString = base64Encode(keyPair.getPublic().getEncoded()); // System.out.println("private:"); // System.out.println(privateString); // System.out.println("public:"); // System.out.println(publicString); byte[] encrypted = encrypt(publicKey, "This is a test!"); System.out.println(base64Encode(encrypted)); byte[] bytes = decrypt(privateKey, base64Decode("VX1x8DRvRyvklwXPCXzUgg7eZx7j8wQ2ZdwLSv68rHIk4PAkdwXvk+7WHgG8R27Xq8u2Q/5V6Yrji43EqD7b02JjjYlN1XbfjiJvP4HoBR8yTgjOrhXBd3N+fIhEl6B7CYCaEVdQtL32q7x+CKDIlZbnTt1E3ofCtAc17/H8m8s=")); System.out.println(new String(bytes)); } public static final String RSA_ALGORITHM = "RSA"; /** * 成功密钥对 */ public static KeyPair buildKeyPair() throws NoSuchAlgorithmException { final int keySize = 1024; KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM); keyPairGenerator.initialize(keySize); return keyPairGenerator.genKeyPair(); } /** * 用私钥加密 */ public static byte[] encrypt(PrivateKey privateKey, String message) throws Exception { Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, privateKey); return cipher.doFinal(message.getBytes(StandardCharsets.UTF_8)); } /** * 用公钥加密 */ public static byte[] encrypt(PublicKey publicKey, String message) throws Exception { Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(message.getBytes(StandardCharsets.UTF_8)); } /** * 用公钥解密 */ public static byte[] decrypt(PublicKey publicKey, byte[] encrypted) throws Exception { Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(encrypted); } /** * 用私钥解密 */ public static byte[] decrypt(PrivateKey privateKey, byte[] encrypted) throws Exception { Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(encrypted); } /** * 从文本中加载公钥 */ public static PublicKey loadPublicKey(String publicKeyStr) throws Exception { String string = publicKeyStr .replace("-----BEGIN PUBLIC KEY-----", "") .replace("-----END PUBLIC KEY-----", "") .replaceAll("\\s", ""); byte[] buffer = base64Decode(string); KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); return keyFactory.generatePublic(keySpec); } /** * 从文本中加载私钥 */ public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception { // PKCS#1 format 格式的私钥会报错,需要假如如下addProvider,maven需要添加如下dependency // <dependency> // <groupId>org.bouncycastle</groupId> // <artifactId>bcprov-jdk15on</artifactId> // <version>1.58</version> // </dependency> java.security.Security.addProvider( new org.bouncycastle.jce.provider.BouncyCastleProvider() ); String string = privateKeyStr .replace("-----BEGIN RSA PRIVATE KEY-----", "") .replace("-----END RSA PRIVATE KEY-----", "") .replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") .replaceAll("\\s", ""); byte[] buffer = base64Decode(string); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(keySpec); } public static String base64Encode(byte[] data) { return Base64.getEncoder().encodeToString(data); } public static byte[] base64Decode(String data) { return Base64.getDecoder().decode(data); } }
文章评论