Java读取pem格式公钥/私钥实现RSA加解密
代码如下:
生成.pem,这里使用2048位长度:
openssl genrsa -out private_key.pem 1024
将.pem转为.der:
openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der
读取public_key.der:
import java.nio.file.Files; import java.nio.file.Paths; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.X509EncodedKeySpec; public class PublicKeyReader { public static PublicKey get(String filename) throws Exception { byte[] keyBytes = Files.readAllBytes(Paths.get(filename)); X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePublic(spec); } }
读取private_key.der:
import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.nio.file.Files; import java.nio.file.Paths; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; public class PrivateKeyReader { public static PrivateKey get(String filename) throws Exception { byte[] keyBytes = Files.readAllBytes(Paths.get(filename)); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate(spec); } }
测试:
import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.PrivateKey; import java.security.PublicKey; public class RSAReadKeyTest { public static void main(String[] args) throws Exception { String text = "When and where\n" + "Join us on June 25, 2020 10:00 Pacific Daylight Time. The workshops will be livestreamed to YouTube via Google Cloud Platform in partnership with AI Huddle.\n" + "\n" + "Is this for me?\n" + "This session is especially geared for professional working data scientists. You should be comfortable with Python to build machine or deep learning models. If you’re curious how accelerators can improve your workflow, this is for you!\n" + "\n" + "Agenda\n" + "Session 1: 10:00-10:30 AM PDT\n" + "Compete in a Kaggle Competition Using TensorFlow GPUs with Chris Deotte \n" + "“Follow along as I make a simple notebook from my team's Gold medal solution to Bengali Handwriting Classification competition.”\n" + "\n" + "Session 2: 10:30-11:00 AM PDT \n" + "Approach (Almost) Any Deep Learning Problem Using PyTorch and TPUs with Abhishek Thakur\n" + "“Allow me to show you how to harness the power of TPUs and Pytorch to quickly train almost any model!”"; PublicKey pubKey = PublicKeyReader.get("src/gj/secure/rsa_public_key.der"); byte[] bytes = RSAUtil.encryptByPublicKey(pubKey, text.getBytes()); String cipherText = toBase64(bytes); System.out.println(cipherText); PrivateKey priKey = PrivateKeyReader.get("src/gj/secure/rsa_private_key.der"); byte[] cipherBytes = fromBase64(cipherText); byte[] result = RSAUtil.decryptByPrivateKey(priKey, cipherBytes); System.out.println(new String(result, StandardCharsets.UTF_8)); } public static String toBase64(byte[] bytes) { return new BASE64Encoder().encode(bytes); } public static byte[] fromBase64(String b64String) throws IOException { return new BASE64Decoder().decodeBuffer(b64String); } }
附RSAUtil.java代码:
import javax.crypto.Cipher; import java.io.ByteArrayOutputStream; import java.security.*; /** * @author areful * Date: 2019/2/12 */ public class RSAUtil { public static final String ALGORITHM_RSA = "RSA"; public static final String ALGORITHM_RSA_PKCS1PADDING = "RSA/ECB/PKCS1PADDING"; public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; private static final int MAX_ENCRYPT_BLOCK = 117; private static final int MAX_DECRYPT_BLOCK = 128; public static KeyPair genKeyPair() throws Exception { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM_RSA); keyPairGen.initialize(1024); return keyPairGen.generateKeyPair(); } public static byte[] encryptByPublicKey(PublicKey pubKey, byte[] data) throws Exception { return doFinal(pubKey, Mode.ENCRYPT, data); } public static byte[] decryptByPrivateKey(PrivateKey priKey, byte[] data) throws Exception { return doFinal(priKey, Mode.DECRYPT, data); } public static byte[] encryptByPrivateKey(PrivateKey priKey, byte[] data) throws Exception { return doFinal(priKey, Mode.ENCRYPT, data); } public static byte[] decryptByPublicKey(PublicKey pubKey, byte[] data) throws Exception { return doFinal(pubKey, Mode.DECRYPT, data); } public static byte[] sign(PrivateKey priKey, byte[] data) throws Exception { Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(priKey); signature.update(data); return signature.sign(); } public static boolean verify(PublicKey pubKey, byte[] data, byte[] sign) throws Exception { Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(pubKey); signature.update(data); return signature.verify(sign); } private enum Mode { ENCRYPT(Cipher.ENCRYPT_MODE), DECRYPT(Cipher.DECRYPT_MODE); private final int value; Mode(int value) { this.value = value; } } private static byte[] doFinal(Key key, Mode mode, byte[] data) throws Exception { final int MAX = (mode == Mode.ENCRYPT) ? MAX_ENCRYPT_BLOCK : MAX_DECRYPT_BLOCK; final int LEN = data.length; byte[] cache; int i = 0, off = 0; ByteArrayOutputStream out = new ByteArrayOutputStream(); Cipher cipher = Cipher.getInstance(ALGORITHM_RSA_PKCS1PADDING); cipher.init(mode.value, key); while (off < LEN) { cache = cipher.doFinal(data, off, Math.min(LEN - off, MAX)); out.write(cache, 0, cache.length); i++; off = i * MAX; } byte[] result = out.toByteArray(); out.close(); return result; } }
附RSAUtil.java测试代码:
import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; import java.util.Arrays; public class RSATest { public static void main(String[] args) throws Exception { KeyPair keyPair = RSAUtil.genKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); System.err.println("公钥加密——私钥解密"); String src = "第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。"; System.out.println("原文字:\t" + src); byte[] encodedData = RSAUtil.encryptByPublicKey(publicKey, src.getBytes()); System.out.println("加密后:\t" + Arrays.toString(encodedData)); String plainText = new String(RSAUtil.decryptByPrivateKey(privateKey, encodedData)); System.out.println("解密后: \t" + plainText); System.err.println("私钥加密——公钥解密"); System.out.println("原文字:\t" + src); encodedData = RSAUtil.encryptByPrivateKey(privateKey, src.getBytes()); System.out.println("加密后:\t" + Arrays.toString(encodedData)); plainText = new String(RSAUtil.decryptByPublicKey(publicKey, encodedData)); System.out.println("解密后: \t" + plainText); System.err.println("私钥签名——公钥验证签名"); byte[] sign = RSAUtil.sign(privateKey, encodedData); System.err.println("签名:\t\t" + Arrays.toString(sign)); boolean status = RSAUtil.verify(publicKey, encodedData, sign); System.err.println("验证结果:\t" + status); } }
Thanks to:https://stackoverflow.com/questions/11410770/load-rsa-public-key-from-file