常用命令
#查看私钥信息 openssl rsa -in private.key -text -noout #查看公钥信息 openssl rsa -in public.key -pubin -text -noout #生成私钥,PKCS1格式 openssl genrsa -out rsa_private_key.pem 1024 #私钥转为PKCS8格式,java 默认只支持该格式私钥 openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out rsa_private_key_pcks8.pem #生成公钥 openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem #pem(base64)转换为der格式(二进制) openssl rsa -in rsa_private_key.pem -out rsa_private_key.der -outform DER
帮助命令
#查看帮助 man openssl #查看子命令帮助 man gendsa #其他 asn1parse(1), ca(1), config(5), crl(1), crl2pkcs7(1), dgst(1), dhparam(1), dsa(1), dsaparam(1), enc(1), gendsa(1), genpkey(1), genrsa(1), nseq(1), openssl(1), sslpasswd(1), pkcs12(1), pkcs7(1), pkcs8(1), sslrand(1), req(1), rsa(1), rsautl(1), s_client(1), s_server(1), s_time(1), smime(1), spkac(1), verify(1), version(1), x509(1), crypto(3), ssl(3), x509v3_config(5)
pem 密钥格式
pkcs1 头:-----BEGIN RSA PRIVATE KEY-----
pkcs8头:-----BEGIN PRIVATE KEY-----
数字证书格式
- *.DER或*.CER文件: 这样的证书文件是二进制格式,只含有证书信息,不包含私钥。
- *.CRT文件: 这样的证书文件可以是二进制格式,也可以是文本格式,一般均为文本格式,功能与 *.DER及*.CER证书文件相同。
- *.PEM文件: 这样的证书文件一般是文本格式,可以存放证书或私钥,或者两者都包含。 *.PEM 文件如果只包含私钥,一般用*.KEY文件代替。
- *.PFX或*.P12文件: 这样的证书文件是二进制格式,同时包含证书和私钥,且一般有密码保护。
- 如果存在
——BEGIN CERTIFICATE——
,则说明这是一个证书文件。 - 如果存在
—–BEGIN RSA PRIVATE KEY—–
,则说明这是一个私钥文件。
java加解密【rsa】
读取公钥:X509EncodedKeySpec
读取私钥:PKCS8EncodedKeySpec ,java 只支持PKCS8格式
der 格式为二进制存储
pem 格式为 base64存储和一些格式化
明文长度:密钥长度(Bytes)-11
理论上为密钥长度,但是有时候明文小于密钥长度,这时候需要 padding
只要用到padding,那么就要占用实际的明文长度,于是才有117字节的说法。我们一般使用的padding标准有NoPPadding、OAEPPadding、PKCS1Padding等,其中PKCS#1建议的padding就占用了11个字节。
如果加密字段过长,需要切分后在分块加密
密文长度:密文位长跟密钥的位长度是相同的
java 原生代码读取 der 格式
class Signer { private KeyFactory keyFactory; public Signer() { this.keyFactory = KeyFactory.getInstance("RSA"); } public PublicKey getPublicKey() { byte[] publicKey = readFileAsBytes("public-key.der"); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); return keyFactory.generatePublic(keySpec); } public PrivateKey getPrivateKey() { byte[] privateKey = readFileAsBytes("private-key.der"); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey); return keyFactory.generatePrivate(keySpec); } private URI readFileAsBytes(String name) { URI fileUri = getClass().getClassLoader().getResource(name).toURI(); return Files.readAllBytes(Paths.get(fileUri)); } }
node 加密 ,java 解密【rsa】
node 加密
/** * 参考 * https://tomoya92.github.io/2018/10/12/node-rsa/ * https://github.com/rzcoder/node-rsa/wiki/Advanced-options * */ var NodeRSA = require('node-rsa') var fs = require('fs') const constants = require("constants"); function encrypt() { fs.readFile('./pem/rsa_public_key.pem', function (err, data) { var key = new NodeRSA(data); options = { encryptionScheme: { scheme: 'pkcs1', //默认 pkcs1_oaep padding: constants.RSA_PKCS1_PADDING } } key.setOptions(options) let cipherText = key.encrypt('hello world', 'base64'); console.log(cipherText); }); } //generator(); encrypt();
java 解密
import java.io.File; import java.io.FileReader; import java.io.IOException; import java.security.KeyPair; import java.security.PrivateKey; import java.security.Security; import java.util.Objects; import javax.crypto.Cipher; import org.apache.commons.codec.binary.Base64; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import org.junit.Test; public class RsaTest2 { static { Security.addProvider(new BouncyCastleProvider()); } /** * 公钥 */ private static final File PUBLIC_KEY_FILE = new File( Objects.requireNonNull(RsaTest2.class.getClassLoader().getResource("rsa_public_key.pem")) .getFile()); /** * 私钥 PKCS1 */ private static final File PRIVATE_KEY_FILE = new File( Objects.requireNonNull(RsaTest2.class.getClassLoader().getResource("rsa_private_key.pem")) .getFile()); /** * 私钥 PKCS8 java 支持此格式 */ private static final File PRIVATE_PKCS8_KEY_FILE = new File( Objects.requireNonNull(RsaTest2.class.getClassLoader().getResource("rsa_private_key_8.pem")) .getFile()); /** * 测试解密 */ @Test public void testUnencrypt() throws Exception { PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE); PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE); String encrypt = "gE0OmGUdTp5z+6HwmMUc5JPGOAY4nU84/OFvk0sWV+Zk392m91isaYoE64A2k" + "+REv7zZMDu1w1ucmk1jQzFj4N9CoqBGN9QisMDo7WyDB1NAg5enXd9Rz9gvZ4j" + "+z6cuk0SVrpPpUTlPCLIUz8CGAkvVGOCqUNQedwQkl4GwBO0="; String unencrypt = this.decrypt(rsaPrivateKey2, encrypt); System.out.println(unencrypt); unencrypt = this.decrypt(rsaPrivateKey2, encrypt); System.out.println(unencrypt); System.out.println(rsaPrivateKey2.equals(rsaPrivateKey1)); } public PrivateKey readPrivateKeySecondApproach(File file) throws IOException { try (FileReader keyReader = new FileReader(file)) { PEMParser pemParser = new PEMParser(keyReader); JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); Object obj = pemParser.readObject(); if (obj instanceof PrivateKeyInfo) {// //pkcs#8 case return converter.getPrivateKey((PrivateKeyInfo)obj); } else { //pkcs#1 case KeyPair kp = converter.getKeyPair((PEMKeyPair)obj); return kp.getPrivate(); } } } public static String decrypt(PrivateKey privateKey, String enStr) throws Exception { //Cipher.getInstance("RSA"); 等价于 Cipher.getInstance("RSA/ECB/PKCS1Padding"); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] deBytes = cipher.doFinal(Base64.decodeBase64(enStr)); return new String(deBytes); } }
node 加密 ,java 解密【aes】
node 加密
/** * 对标 java 中 AES/CBC/PKCS7Padding * PKCS5 是 PKCS7 的特殊情况,固定 8bit 分组 * 在线测试: http://tools.jb51.net/password/rsa_encode * * @type {{}} */ const CryptoJS = require("crypto-js"); // 加密 // let str = '思齐'; // 密钥 16 位 let key = '491c15367010fbe1'; // 初始向量 initial vector 16 位 let iv = '13bf32d4419b54b8'; // key 和 iv 可以一致 key = CryptoJS.enc.Utf8.parse(key); iv = CryptoJS.enc.Utf8.parse(iv); { var encrypted = CryptoJS.AES.encrypt(str, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); // 转换为字符串 16 进制 // encrypted = encrypted.toString(CryptoJS.format.Hex); // console.log(encrypted) // 转换为字符串 base64 encrypted = encrypted.toString(CryptoJS.format.Base64); console.log(encrypted) } { // mode 支持 CBC、CFB、CTR、ECB、OFB, 默认 CBC // padding 支持 Pkcs7、AnsiX923、Iso10126 // NoPadding、ZeroPadding, 默认 Pkcs7, 即 Pkcs5 // 解密 var decrypted = CryptoJS.AES.decrypt(encrypted, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); // 转换为 utf8 字符串 decrypted = CryptoJS.enc.Utf8.stringify(decrypted); }
java 解密
/** * AES加解密 * * * java 中默认要求支持以下实现 https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher * * AES/CBC/NoPadding (128) * AES/CBC/PKCS5Padding (128) * AES/ECB/NoPadding (128) * AES/ECB/PKCS5Padding (128) * DES/CBC/NoPadding (56) * DES/CBC/PKCS5Padding (56) * DES/ECB/NoPadding (56) * DES/ECB/PKCS5Padding (56) * DESede/CBC/NoPadding (168) * DESede/CBC/PKCS5Padding (168) * DESede/ECB/NoPadding (168) * DESede/ECB/PKCS5Padding (168) * RSA/ECB/PKCS1Padding (1024, 2048) * RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048) * RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048) * * * @date * @author */ @Slf4j public class AesCrypt2 { /** * 使用固定长度密钥 */ private static final int KEY_LENGTH = 16; /** * 算法/模式/填充方式 */ private static final String TRANSFORMATION = "AES/CBC/PKCS7Padding"; private static final String AES_ALGORITHM = "AES"; private static final IvParameterSpec IV = new IvParameterSpec("13bf32d4419b54b8".getBytes()); static { //support PKCS7Padding if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { Security.addProvider(new BouncyCastleProvider()); } } /** * aes解密 * @param data 加密数据 * @param key 解密密钥 * @return null 参数不符合要求或解密失败 */ public static byte[] decrypt(byte[] data, byte[] key) { if (data == null || key == null) { return null; } if (key.length != KEY_LENGTH) { throw new RuntimeException("Invalid AES key length (must be 16 bytes)"); } try { SecretKeySpec secretKey = new SecretKeySpec(key, AES_ALGORITHM); byte[] enCodeFormat = secretKey.getEncoded(); SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, AES_ALGORITHM); Cipher cipher = Cipher.getInstance(TRANSFORMATION); cipher.init(Cipher.DECRYPT_MODE, seckey, IV); return cipher.doFinal(data); } catch (Exception e) { log.error(" decrypt fail:{}", e.getMessage(), e); } return null; } /** * aes加密 * @param data 需要加密的内容 * @param key 加密密钥 * @return 参数不符合要求或加密失败 */ public static byte[] encrypt(byte[] data, byte[] key) { if (data == null || key == null) { return null; } if (key.length != KEY_LENGTH) { throw new RuntimeException("Invalid AES key length (must be 16 bytes)"); } try { SecretKeySpec secretKey = new SecretKeySpec(key, AES_ALGORITHM); byte[] enCodeFormat = secretKey.getEncoded(); SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, AES_ALGORITHM); Cipher cipher = Cipher.getInstance(TRANSFORMATION); cipher.init(Cipher.ENCRYPT_MODE, seckey, IV); return cipher.doFinal(data); } catch (Exception e) { log.error(" encrypt fail:{}", e.getMessage(), e); } return null; } }
String raw = "eFsqUJGjPd6FO16dgZ6xlg=="; byte[] decode = Base64.getDecoder().decode(raw); byte[] last = OgnvAesCrypt.decrypt(decode, "491c15367010fbe1".getBytes()); //System.out.println(Hex.encodeHex(last)); System.out.println(new String(last));
java 读写公钥、私钥
/** * RSA 加解密 * * BouncyCastle 三方开发的加解密和消息摘要组件, 需要添加 provider * * https://www.baeldung.com/java-read-pem-file-keys * https://github.com/rzcoder/node-rsa */ public class RsaTest { static { Security.addProvider(new BouncyCastleProvider()); } /** * 公钥 */ private static final File PUBLIC_KEY_FILE = new File( Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_public_key.pem")) .getFile()); /** * 私钥 PKCS1 */ private static final File PRIVATE_KEY_FILE = new File( Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_private_key.pem")) .getFile()); /** * 私钥 PKCS8 java 支持此格式 */ private static final File PRIVATE_PKCS8_KEY_FILE = new File( Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_private_key_8.pem")) .getFile()); @Test public void testReadKey() throws Exception { //PublicKey rsaPublicKey = this.readPublicKey(PUBLIC_KEY_FILE); //PublicKey rsaPrivateKey = this.readPrivateKey(PRIVATE_PKCS8_KEY_FILE); //BouncyCastle library supports the PKCS1 format,需要加载 provider PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE); PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE); PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE); } /** * 测试加密 */ @Test public void testEncrypt() throws Exception { //BouncyCastle library supports the PKCS1 format,需要加载 provider PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE); // fFAajnaTQOJUDllbS1qkr/w7yx4vgkMyro8xDIpUEYMYbi43PpdMEF9TnO5hMnL1HmgA4PhD1Uws/EpQtDFBE+0ls+iQa1F6 // +QwakVrUTMttnJF5kS2WQ0+0yLstXclR1JMFmSZnJGL2dlg1tTIJjREmrKljC2c1VJfoZK5kPps= String data = "jksong"; String encrypt = this.encrypt(rsaPublicKey, data); System.out.println(encrypt); } /** * 测试解密 */ @Test public void testUnencrypt() throws Exception { PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE); PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE); String encrypt = "gE0OmGUdTp5z+6HwmMUc5JPGOAY4nU84/OFvk0sWV+Zk392m91isaYoE64A2k" + "+REv7zZMDu1w1ucmk1jQzFj4N9CoqBGN9QisMDo7WyDB1NAg5enXd9Rz9gvZ4j" + "+z6cuk0SVrpPpUTlPCLIUz8CGAkvVGOCqUNQedwQkl4GwBO0="; String unencrypt = this.decrypt(rsaPrivateKey2, encrypt); System.out.println(unencrypt); //unencrypt = this.decrypt(rsaPrivateKey2, encrypt); //System.out.println(unencrypt); // //System.out.println(rsaPrivateKey2.equals(rsaPrivateKey1)); } //public static void main(String[] args) throws IOException { // RsaTest rsaTest = new RsaTest(); // PrivateKey rsaPrivateKey = rsaTest.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE); // rsaTest.readPrivateKeySecondApproach(PRIVATE_KEY_FILE); // //} public PublicKey readPublicKey(File file) throws Exception { String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset()); String publicKeyPEM = key .replace("-----BEGIN PUBLIC KEY-----", "") .replaceAll(System.lineSeparator(), "") .replace("-----END PUBLIC KEY-----", ""); byte[] encoded = Base64.decodeBase64(publicKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded); return keyFactory.generatePublic(keySpec); } public RSAPrivateKey readPrivateKey(File file) throws Exception { String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset()); String privateKeyPEM = key .replace("-----BEGIN PRIVATE KEY-----", "") .replaceAll(System.lineSeparator(), "") .replace("-----END PRIVATE KEY-----", ""); byte[] encoded = Base64.decodeBase64(privateKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); return (RSAPrivateKey)keyFactory.generatePrivate(keySpec); } /** * 使用 BouncyCastle,可以支持读取 pem 文件 * @param file * @return * @throws IOException */ public RSAPublicKey readPublicKeySecondApproach(File file) throws IOException { try (FileReader keyReader = new FileReader(file)) { PEMParser pemParser = new PEMParser(keyReader); JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(pemParser.readObject()); return (RSAPublicKey)converter.getPublicKey(publicKeyInfo); } } public PrivateKey readPrivateKeySecondApproach(File file) throws IOException { try (FileReader keyReader = new FileReader(file)) { PEMParser pemParser = new PEMParser(keyReader); JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); Object obj = pemParser.readObject(); if (obj instanceof PrivateKeyInfo) {// //pkcs#8 case return converter.getPrivateKey((PrivateKeyInfo)obj); } else { //pkcs#1 case KeyPair kp = converter.getKeyPair((PEMKeyPair)obj); return kp.getPrivate(); } } } public String encrypt(PublicKey publicKey, String plainText) throws Exception { //等价于 RSA/ECB/PKCS1Padding (1024, 2048) => RSA/None/PKCS1Padding Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] enBytes = cipher.doFinal(plainText.getBytes()); return Base64.encodeBase64String(enBytes); } public static String decrypt(PrivateKey privateKey, String enStr) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] deBytes = cipher.doFinal(Base64.decodeBase64(enStr)); return new String(deBytes); } }
数字签名【防篡改】
/** * RSA 加解密 * * BouncyCastle 三方开发的加解密和消息摘要组件, 需要添加 provider * * https://www.baeldung.com/java-read-pem-file-keys * https://github.com/rzcoder/node-rsa */ public class RsaTest { static { Security.addProvider(new BouncyCastleProvider()); } /** * 公钥 */ private static final File PUBLIC_KEY_FILE = new File( Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_public_key.pem")) .getFile()); /** * 私钥 PKCS1 */ private static final File PRIVATE_KEY_FILE = new File( Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_private_key.pem")) .getFile()); /** * 私钥 PKCS8 java 支持此格式 */ private static final File PRIVATE_PKCS8_KEY_FILE = new File( Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_private_key_8.pem")) .getFile()); @Test public void testReadKey() throws Exception { //PublicKey rsaPublicKey = this.readPublicKey(PUBLIC_KEY_FILE); //PublicKey rsaPrivateKey = this.readPrivateKey(PRIVATE_PKCS8_KEY_FILE); //BouncyCastle library supports the PKCS1 format,需要加载 provider PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE); PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE); PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE); } /** * 测试加密 */ @Test public void testEncrypt() throws Exception { //BouncyCastle library supports the PKCS1 format,需要加载 provider PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE); // fFAajnaTQOJUDllbS1qkr/w7yx4vgkMyro8xDIpUEYMYbi43PpdMEF9TnO5hMnL1HmgA4PhD1Uws/EpQtDFBE+0ls+iQa1F6 // +QwakVrUTMttnJF5kS2WQ0+0yLstXclR1JMFmSZnJGL2dlg1tTIJjREmrKljC2c1VJfoZK5kPps= String data = "jksong"; String encrypt = this.encrypt(rsaPublicKey, data); System.out.println(encrypt); } /** * 测试解密 */ @Test public void testUnencrypt() throws Exception { PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE); PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE); String encrypt = "gE0OmGUdTp5z+6HwmMUc5JPGOAY4nU84/OFvk0sWV+Zk392m91isaYoE64A2k" + "+REv7zZMDu1w1ucmk1jQzFj4N9CoqBGN9QisMDo7WyDB1NAg5enXd9Rz9gvZ4j" + "+z6cuk0SVrpPpUTlPCLIUz8CGAkvVGOCqUNQedwQkl4GwBO0="; String unencrypt = this.decrypt(rsaPrivateKey2, encrypt); System.out.println(unencrypt); //unencrypt = this.decrypt(rsaPrivateKey2, encrypt); //System.out.println(unencrypt); // //System.out.println(rsaPrivateKey2.equals(rsaPrivateKey1)); } /** * 数字签名 * @throws Exception */ @Test public void testSign() throws Exception { /** * 签名算法 * MD2withRSA * MD5withRSA * RSASSA-PSS * SHA1withRSA * SHA224withRSA * SHA256withRSA * SHA384withRSA * SHA512withRSA * SHA512/224withRSA * SHA512/256withRSA * 等 * * https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html#Introduction * */ String signType = "SHA1withRSA"; //待签名数据 byte[] data = "思齐".getBytes(StandardCharsets.UTF_8); //生成签名 PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE); String sign = this.sign("SHA1withRSA", data, rsaPrivateKey1); System.out.println("签名:" + sign); //验证签名 PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE); boolean verifySign = this.verifySign("SHA1withRSA", data, rsaPublicKey, sign); System.out.println("签名验证结果:" + verifySign); } public PublicKey readPublicKey(File file) throws Exception { String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset()); String publicKeyPEM = key .replace("-----BEGIN PUBLIC KEY-----", "") .replaceAll(System.lineSeparator(), "") .replace("-----END PUBLIC KEY-----", ""); byte[] encoded = Base64.decodeBase64(publicKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded); return keyFactory.generatePublic(keySpec); } public RSAPrivateKey readPrivateKey(File file) throws Exception { String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset()); String privateKeyPEM = key .replace("-----BEGIN PRIVATE KEY-----", "") .replaceAll(System.lineSeparator(), "") .replace("-----END PRIVATE KEY-----", ""); byte[] encoded = Base64.decodeBase64(privateKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); return (RSAPrivateKey)keyFactory.generatePrivate(keySpec); } /** * 使用 BouncyCastle,可以支持读取 pem 文件 * @param file * @return * @throws IOException */ public RSAPublicKey readPublicKeySecondApproach(File file) throws IOException { try (FileReader keyReader = new FileReader(file)) { PEMParser pemParser = new PEMParser(keyReader); JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(pemParser.readObject()); return (RSAPublicKey)converter.getPublicKey(publicKeyInfo); } } public PrivateKey readPrivateKeySecondApproach(File file) throws IOException { try (FileReader keyReader = new FileReader(file)) { PEMParser pemParser = new PEMParser(keyReader); JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); Object obj = pemParser.readObject(); if (obj instanceof PrivateKeyInfo) {// //pkcs#8 case return converter.getPrivateKey((PrivateKeyInfo)obj); } else { //pkcs#1 case KeyPair kp = converter.getKeyPair((PEMKeyPair)obj); return kp.getPrivate(); } } } public String encrypt(PublicKey publicKey, String plainText) throws Exception { //等价于 RSA/ECB/PKCS1Padding (1024, 2048) => RSA/None/PKCS1Padding Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] enBytes = cipher.doFinal(plainText.getBytes()); return Base64.encodeBase64String(enBytes); } public static String decrypt(PrivateKey privateKey, String enStr) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] deBytes = cipher.doFinal(Base64.decodeBase64(enStr)); return new String(deBytes); } public String sign(String signType, byte[] data, PrivateKey privateKey) throws Exception { Signature signature = Signature.getInstance(signType); signature.initSign(privateKey); signature.update(data); return Base64.encodeBase64String(signature.sign()); } public boolean verifySign(String signType, byte[] data, PublicKey publicKey, String sign) throws Exception { Signature signature = Signature.getInstance(signType); signature.initVerify(publicKey); signature.update(data); return signature.verify(Base64.decodeBase64(sign)); } }
读取证书
/** * 读取证书信息 * @throws CertificateException */ @Test public void test497() throws CertificateException { InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("pub_server.crt"); CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); X509Certificate x509Cert = (X509Certificate)certificateFactory.generateCertificate(resourceAsStream); PublicKey publicKey = x509Cert.getPublicKey(); BASE64Encoder encoder = new BASE64Encoder(); String encoded = encoder.encode(publicKey.getEncoded()); System.out.println("公钥:" + encoded); System.out.println("输出证书信息:" + x509Cert.toString()); System.out.println("版本号:" + x509Cert.getVersion()); System.out.println("序列号:" + x509Cert.getSerialNumber().toString(16)); System.out.println("主体名:" + x509Cert.getSubjectDN()); System.out.println("签发者:" + x509Cert.getIssuerDN()); System.out.println("有效期:" + x509Cert.getNotBefore()); System.out.println("签名算法:" + x509Cert.getSigAlgName()); byte[] sig = x509Cert.getSignature(); System.out.println("签名值:" + Arrays.toString(sig)); }
测试密钥
rsa_private_key.pem
-----BEGIN PRIVATE KEY----- MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMpWEnTXc7jl7fJg hMJp5lv3c/Lwv5q7qamRcQIBx6qDNcrMvKfQRqcGS8WqsmWx3qZCWzi40Brexlo/ V0RN0ktfDXrKl9qO5++yqPk/0mVhN/raF32SSrCP6WNEvSwc5ln3LUV/NPZ6rRTI wFLeilruVjvtT1yw/f6cbf5ac+n5AgMBAAECgYAkZy305ZqFZqDT3bek/saaP0AW MmhWn3Lb9jXdxZI1xFuWPBWpH5jGjiRt0NM95q2HPiMJZn7ShsgrDoBV4qZ15LdT 8iHGvDVhmcqv1GPkKoyI1HoCvcff0bhblMb70m14ZnOHgf4MlNeOVvrkd8LdaoST 7y61akphJdTIKLZVAQJBAPv4rNjA0yjZvwLeR/mZdQyYexI/yJCEJhPj591BeeMI ZzPlEcyZS+vMYtMpGaxHqtUJG8zoCcXluj/lZmPlsCECQQDNkj0vLk/ZpRE+paOj SKrjQJF/OJ9SWu0FGpQ9PfqrFgLUvVYTzFpFfW0k345r4CK6I9eX/4ey7oGgbUfh Zd7ZAkEAnRVt5H9p5SjCnS4oXuIdh6mz6C+dgQLxnirSDSzZqQE/HaosS4oyO6Gi 5pPT7oSLat6P11G9bgOG9ni0OYkjIQJAHCFOzg4AT0APRAtWgRmIiOBlCIuvAY3/ sRsZ/edlTdQNPx9JkBv+nlOzg8AztP9OwTn2Xo5Q+2M3ycQqeeV+wQJBAJRyBEh1 2RuDjCMjz7K8KCWJcZ1wZT+7Xb51ICyQPwnIiz1fSRpwmzO8dS7gZQ9qaqa1uAEl O+aDMRvr202Wm2s= -----END PRIVATE KEY-----
rsa_private_key_8.pem
-----BEGIN PRIVATE KEY----- MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMpWEnTXc7jl7fJg hMJp5lv3c/Lwv5q7qamRcQIBx6qDNcrMvKfQRqcGS8WqsmWx3qZCWzi40Brexlo/ V0RN0ktfDXrKl9qO5++yqPk/0mVhN/raF32SSrCP6WNEvSwc5ln3LUV/NPZ6rRTI wFLeilruVjvtT1yw/f6cbf5ac+n5AgMBAAECgYAkZy305ZqFZqDT3bek/saaP0AW MmhWn3Lb9jXdxZI1xFuWPBWpH5jGjiRt0NM95q2HPiMJZn7ShsgrDoBV4qZ15LdT 8iHGvDVhmcqv1GPkKoyI1HoCvcff0bhblMb70m14ZnOHgf4MlNeOVvrkd8LdaoST 7y61akphJdTIKLZVAQJBAPv4rNjA0yjZvwLeR/mZdQyYexI/yJCEJhPj591BeeMI ZzPlEcyZS+vMYtMpGaxHqtUJG8zoCcXluj/lZmPlsCECQQDNkj0vLk/ZpRE+paOj SKrjQJF/OJ9SWu0FGpQ9PfqrFgLUvVYTzFpFfW0k345r4CK6I9eX/4ey7oGgbUfh Zd7ZAkEAnRVt5H9p5SjCnS4oXuIdh6mz6C+dgQLxnirSDSzZqQE/HaosS4oyO6Gi 5pPT7oSLat6P11G9bgOG9ni0OYkjIQJAHCFOzg4AT0APRAtWgRmIiOBlCIuvAY3/ sRsZ/edlTdQNPx9JkBv+nlOzg8AztP9OwTn2Xo5Q+2M3ycQqeeV+wQJBAJRyBEh1 2RuDjCMjz7K8KCWJcZ1wZT+7Xb51ICyQPwnIiz1fSRpwmzO8dS7gZQ9qaqa1uAEl O+aDMRvr202Wm2s= -----END PRIVATE KEY-----
rsa_public_key.pem
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKVhJ013O45e3yYITCaeZb93Py 8L+au6mpkXECAceqgzXKzLyn0EanBkvFqrJlsd6mQls4uNAa3sZaP1dETdJLXw16 ypfajufvsqj5P9JlYTf62hd9kkqwj+ljRL0sHOZZ9y1FfzT2eq0UyMBS3opa7lY7 7U9csP3+nG3+WnPp+QIDAQAB -----END PUBLIC KEY-----
参考
Java Cryptography Architecture Standard Algorithm Name
Java Cryptography Architecture Oracle Providers Documentation for JDK 8