千家信息网

Java怎么使用rsa非对称加密法进行加密

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这篇文章主要介绍了Java怎么使用rsa非对称加密法进行加密,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。公钥与私钥是成对的,一般的,
千家信息网最后更新 2026年10月31日Java怎么使用rsa非对称加密法进行加密

这篇文章主要介绍了Java怎么使用rsa非对称加密法进行加密,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

公钥与私钥是成对的,一般的,我们认为的是公钥加密、私钥解密、私钥签名、公钥验证,有人说成私钥加密,公钥解密时不对的。

公钥与私钥的生成有多种方式,可以通过程序生成(下文具体实现),可以通过openssl工具:  

# 生成一个私钥,推荐使用1024位的秘钥,秘钥以pem格式保存到-out参数指定的文件中,采用PKCS1格式openssl genrsa -out rsa.pem 1024# 生成与私钥对应的公钥,生成的是Subject Public Key,一般配合PKCS8格式私钥使用openssl rsa -in rsa.pem -pubout -out rsa.pub

RSA生成公钥与私钥一般有两种格式:PKCS1和PKCS8,上面的命令生成的秘钥是PKCS1格式的,而公钥是Subject Public Key,一般配合PKCS8格式私钥使用,所以就可能会涉及到PKCS1和PKCS8之间的转换:

# PKCS1格式私钥转换为PKCS8格式私钥,私钥直接输出到-out参数指定的文件中openssl pkcs8 -topk8 -inform PEM -in rsa.pem -outform pem -nocrypt -out rsa_pkcs8.pem# PKCS8格式私钥转换为PKCS1格式私钥,私钥直接输出到-out参数指定的文件中openssl rsa -in rsa_pkcs8.pem -out rsa_pkcs1.pem # PKCS1格式公钥转换为PKCS8格式公钥,转换后的内容直接输出openssl rsa -pubin -in rsa.pub -RSAPublicKey_out# PKCS8格式公钥转换为PKCS1格式公钥,转换后的内容直接输出openssl rsa -RSAPublicKey_in -pubout -in rsa.pub

现实中,我们往往从pem、crt、pfx文件获取公私和私钥,crt、pfx的制作可以参考:简单的制作ssl证书,并在nginx和IIS中使用。

Java实现

为简化说明介绍,这里我直接封装了一个工具类,因为要从pem、crt、pfx文件获取公私和私钥,因此引用了一个第三方包:BouncyCastle,可以直接在pom.xml中添加依赖:  

org.bouncycastlebcprov-jdk15on1.68

简单封装的RsaUtil.java:  

import java.io.FileInputStream;import java.io.FileReader;import java.io.FileWriter;import java.math.BigInteger;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.KeyStore;import java.security.PrivateKey;import java.security.PublicKey;import java.security.SecureRandom;import java.security.Security;import java.security.Signature;import java.security.cert.Certificate;import java.security.cert.CertificateFactory;import java.security.cert.X509Certificate;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.KeySpec;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.RSAPrivateCrtKeySpec;import java.security.spec.RSAPublicKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.Enumeration; import javax.crypto.Cipher; import org.bouncycastle.asn1.ASN1Integer;import org.bouncycastle.asn1.ASN1Primitive;import org.bouncycastle.asn1.DLSequence;import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;import org.bouncycastle.asn1.x509.AlgorithmIdentifier;import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;import org.bouncycastle.jce.provider.BouncyCastleProvider;import org.bouncycastle.util.io.pem.PemObject;import org.bouncycastle.util.io.pem.PemReader;import org.bouncycastle.util.io.pem.PemWriter; public class RsaUtil { static {Security.addProvider(new BouncyCastleProvider());} /*** 随机生成密钥对** @param usePKCS8*            是否采用PKCS8填充模式*/public static Object[] generateRsaKey(boolean usePKCS8) throws Exception {KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);// 初始化keyPairGen.initialize(1024, new SecureRandom());// 生成一个密钥对,保存在keyPair中KeyPair keyPair = keyPairGen.generateKeyPair();RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥 // 这两个公私钥是PKCS8格式的byte[] publicKeyBytes = publicKey.getEncoded();byte[] privateKeyBytes = privateKey.getEncoded(); if (!usePKCS8) {// 将PSCK8格式公私钥转换为PKCS1格式publicKeyBytes = pkcs8ToPkcs1(false, publicKeyBytes);privateKeyBytes = pkcs8ToPkcs1(true, privateKeyBytes);} return new Object[] { publicKeyBytes, privateKeyBytes };} /*** 从Pem文件读取密钥对** @param reader*            输入流* @param pemFileName*            pem文件*/public static byte[] readFromPem(String pemFileName) throws Exception {PemReader pemReader = new PemReader(new FileReader(pemFileName));PemObject pemObject = pemReader.readPemObject();byte[] publicKey = pemObject.getContent();pemReader.close();return publicKey;} /*** 从Pem文件读取密钥** @param isPrivateKey*            是否是私钥* @param buffer*            字节* @param pemFileName*            pem文件*/public static void writeToPem(byte[] buffer, boolean isPrivateKey, String pemFileName) throws Exception { PemObject pemObject = new PemObject(isPrivateKey ? "RSA PRIVATE KEY" : "RSA PUBLIC KEY", buffer);FileWriter fileWriter = new FileWriter(pemFileName);PemWriter pemWriter = new PemWriter(fileWriter);pemWriter.writeObject(pemObject);pemWriter.close();} /*** 从crt文件读取公钥(pkcs8)** @param crtFileName*            crt文件* @return 公钥*/public static byte[] readPublicKeyFromCrt(String crtFileName) throws Exception {CertificateFactory cf = CertificateFactory.getInstance("X.509");X509Certificate cert = (X509Certificate) cf.generateCertificate(new FileInputStream(crtFileName)); PublicKey publicKey = cert.getPublicKey();return publicKey.getEncoded();} /*** 从pfx文件读取秘钥对(pkcs8)** @param pfxFileName*            pfx文件* @return 秘钥对*/public static Object[] readFromPfx(String pfxFileName, String password) throws Exception {KeyStore keystore = KeyStore.getInstance("PKCS12");char[] passwordChars = null;if (password == null || password.equals("")) {passwordChars = null;} else {passwordChars = password.toCharArray();}keystore.load(new FileInputStream(pfxFileName), passwordChars);Enumeration enums = keystore.aliases(); PrivateKey privateKey = null;Certificate certificate = null;while (enums.hasMoreElements()) {String alias = enums.nextElement();System.out.println(alias);if (keystore.isKeyEntry(alias)) {privateKey = (PrivateKey) keystore.getKey(alias, passwordChars);certificate = keystore.getCertificate(alias);}if (privateKey != null && certificate != null)break;}if (privateKey == null || certificate == null) {throw new Exception("fail to read key from pfx");} PublicKey publicKey = certificate.getPublicKey();return new Object[] { publicKey.getEncoded(), privateKey.getEncoded() };} /*** Pkcs8转Pkcs1** @param isPrivateKey*            是否是私钥转换* @param buffer*            Pkcs1秘钥* @return Pkcs8秘钥* @throws Exception*             加密过程中的异常信息*/public static byte[] pkcs8ToPkcs1(boolean isPrivateKey, byte[] buffer) throws Exception {if (isPrivateKey) {PrivateKeyInfo privateKeyInfo = PrivateKeyInfo.getInstance(buffer);return privateKeyInfo.parsePrivateKey().toASN1Primitive().getEncoded();} else {SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(buffer);return subjectPublicKeyInfo.parsePublicKey().toASN1Primitive().getEncoded();}} /*** Pkcs1转Pkcs8** @param isPrivateKey*            是否是私钥转换* @param buffer*            Pkcs1秘钥* @return Pkcs8秘钥* @throws Exception*             加密过程中的异常信息*/public static byte[] pkcs1ToPkcs8(boolean isPrivateKey, byte[] buffer) throws Exception {AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption);ASN1Primitive asn1Primitive = ASN1Primitive.fromByteArray(buffer);if (isPrivateKey) {PrivateKeyInfo privateKeyInfo = new PrivateKeyInfo(algorithmIdentifier, asn1Primitive);return privateKeyInfo.getEncoded();} else {SubjectPublicKeyInfo subjectPublicKeyInfo = new SubjectPublicKeyInfo(algorithmIdentifier, asn1Primitive);return subjectPublicKeyInfo.getEncoded();}} /*** RSA公钥** @param usePKCS8*            是否采用PKCS8填充模式* @param publicKey*            公钥* @return 公钥* @throws Exception*             加密过程中的异常信息*/public static RSAPublicKey generatePublicKey(boolean usePKCS8, byte[] publicKey) throws Exception {KeySpec keySpec;if (usePKCS8) {// PKCS8填充keySpec = new X509EncodedKeySpec(publicKey);} else {// PKCS1填充DLSequence sequence = (DLSequence) ASN1Primitive.fromByteArray(publicKey);BigInteger v1 = ((ASN1Integer) sequence.getObjectAt(0)).getValue();BigInteger v2 = ((ASN1Integer) sequence.getObjectAt(1)).getValue();keySpec = new RSAPublicKeySpec(v1, v2);} RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME).generatePublic(keySpec);return pubKey;} /*** RSA私钥** @param usePKCS8*            是否采用PKCS8填充模式* @param privateKey*            私钥* @return 私钥* @throws Exception*             解密过程中的异常信息*/public static RSAPrivateKey generatePrivateKey(boolean usePKCS8, byte[] privateKey) throws Exception {KeySpec keySpec;if (usePKCS8) {// PKCS8填充keySpec = new PKCS8EncodedKeySpec(privateKey);} else {// PKCS1填充DLSequence sequence = (DLSequence) ASN1Primitive.fromByteArray(privateKey);// BigInteger v1= ((ASN1Integer)sequence.getObjectAt(0)).getValue();BigInteger v2 = ((ASN1Integer) sequence.getObjectAt(1)).getValue();BigInteger v3 = ((ASN1Integer) sequence.getObjectAt(2)).getValue();BigInteger v4 = ((ASN1Integer) sequence.getObjectAt(3)).getValue();BigInteger v5 = ((ASN1Integer) sequence.getObjectAt(4)).getValue();BigInteger v6 = ((ASN1Integer) sequence.getObjectAt(5)).getValue();BigInteger v7 = ((ASN1Integer) sequence.getObjectAt(6)).getValue();BigInteger v8 = ((ASN1Integer) sequence.getObjectAt(7)).getValue();BigInteger v9 = ((ASN1Integer) sequence.getObjectAt(8)).getValue();keySpec = new RSAPrivateCrtKeySpec(v2, v3, v4, v5, v6, v7, v8, v9);} RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME).generatePrivate(keySpec);return priKey;} /*** RSA公钥加密** @param value*            加密字符串* @param publicKey*            公钥* @return 密文* @throws Exception*             加密过程中的异常信息*/public static String rsaEncrypt(String value, RSAPublicKey publicKey) throws Exception {if (value == null || value.length() == 0)return ""; // RSA加密Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] buffer = cipher.doFinal(value.getBytes("utf-8")); // 使用hex格式输出公钥StringBuffer result = new StringBuffer();for (int i = 0; i < buffer.length; i++) {result.append(String.format("x", buffer[i]));}return result.toString();} /*** RSA私钥解密** @param value*            加密字符串* @param privateKey*            私钥* @return 明文* @throws Exception*             解密过程中的异常信息*/public static String rsaDecrypt(String value, RSAPrivateKey privateKey) throws Exception {if (value == null || value.length() == 0)return ""; byte[] buffer = new byte[value.length() / 2];for (int i = 0; i < buffer.length; i++) {buffer[i] = (byte) Integer.parseInt(value.substring(i * 2, i * 2 + 2), 16);} // RSA解密Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);buffer = cipher.doFinal(buffer);return new String(buffer, "utf-8");} /*** RSA签名** @param value*            加密字符串* @param privateKey*            私钥* @param halg*            加密算法,如MD5, SHA1, SHA256, SHA384, SHA512等* @return 签名* @throws Exception*             签名过程中的异常信息*/public static String sign(String value, RSAPrivateKey privateKey, String halg) throws Exception { Signature s = Signature.getInstance(halg.toUpperCase().endsWith("WithRSA") ? halg : (halg + "WithRSA")); s.initSign(privateKey);s.update(value.getBytes("utf-8")); byte[] buffer = s.sign(); // 使用hex格式输出公钥StringBuffer result = new StringBuffer();for (int i = 0; i < buffer.length; i++) {result.append(String.format("x", buffer[i]));}return result.toString();} /*** RSA签名验证** @param value*            加密字符串* @param publicKey*            公钥* @param halg*            加密算法,如MD5, SHA1, SHA256, SHA384, SHA512等* @return 签名合法则返回true,否则返回false* @throws Exception*             验证过程中的异常信息*/public static boolean verify(String value, RSAPublicKey publicKey, String signature, String halg) throws Exception {Signature s = Signature.getInstance(halg.toUpperCase().endsWith("WithRSA") ? halg : (halg + "WithRSA"));s.initVerify(publicKey);s.update(value.getBytes("utf-8")); byte[] buffer = new byte[signature.length() / 2];for (int i = 0; i < buffer.length; i++) {buffer[i] = (byte) Integer.parseInt(signature.substring(i * 2, i * 2 + 2), 16);} return s.verify(buffer);} }

生成公钥和私钥:  

// 生成公私钥Object[] rsaKey = RsaUtil.generateRsaKey(usePKCS8); //usePKCS8=true表示是否成PKCS8格式的公私秘钥,否则乘车PKCS1格式的公私秘钥byte[] publicKey = (byte[]) rsaKey[0];byte[] privateKey = (byte[]) rsaKey[1];

生成秘钥后,需要保存,一般保存到pem文件中: 

// 保存到pem文件,filePath是保存目录RsaUtil.writeToPem(publicKey, false, filePath + "rsa.pub");RsaUtil.writeToPem(privateKey, true, filePath + "rsa.pem");

可以保存到pem文件中,当然也可以从pem文件中读取了:  

// 从Pem文件读取公私钥,filePath是文件目录byte[] publicKey = RsaUtil.readFromPem(filePath + "rsa.pub");byte[] privateKey = RsaUtil.readFromPem(filePath + "rsa.pem");

还可以从crt证书中读取公钥,而crt文件不包含私钥,因此需要单独获取私钥: 

// 从crt文件读取公钥(crt文件中不包含私钥),filePath是文件目录byte[] publicKey = RsaUtil.readPublicKeyFromCrt(filePath + "demo.crt");byte[] privateKey = RsaUtil.readFromPem(filePath + "demo.key");

pfx文件中包含了公钥和私钥,可以很方便就读取到:  

// 从pfx文件读取公私钥,filePath是文件目录Object[] rsaKey = RsaUtil.readFromPfx(filePath + "demo.pfx", "123456");byte[] publicKey = (byte[]) rsaKey[0];byte[] privateKey = (byte[]) rsaKey[1];

有时候我们还可能需要进行秘钥的转换:  

// Pkcs8格式公钥转换为Pkcs1格式公钥publicKey = RsaUtil.pkcs8ToPkcs1(false, publicKey);// Pkcs8格式私钥转换为Pkcs1格式私钥privateKey = RsaUtil.pkcs8ToPkcs1(true, privateKey);// Pkcs1格式公钥转换为Pkcs8格式公钥publicKey = RsaUtil.pkcs1ToPkcs8(false, publicKey);// Pkcs1格式私钥转换为Pkcs8格式私钥privateKey = RsaUtil.pkcs1ToPkcs8(true, privateKey);

有了公钥和私钥,接下就就能实现加密、解密、签名、验证签名等操作了:  

RSAPublicKey rsaPublicKey = RsaUtil.generatePublicKey(usePKCS8, publicKey);RSAPrivateKey rsaPrivateKey = RsaUtil.generatePrivateKey(usePKCS8, privateKey); String encryptText = RsaUtil.rsaEncrypt(text, rsaPublicKey);System.out.printf("【%s】经过【RSA】加密后:%s\n", text, encryptText); String decryptText = RsaUtil.rsaDecrypt(encryptText, rsaPrivateKey);System.out.printf("【%s】经过【RSA】解密后:%s\n", encryptText, decryptText); String signature = RsaUtil.sign(text, rsaPrivateKey, "MD5");System.out.printf("【%s】经过【RSA】签名后:%s\n", text, signature); boolean result = RsaUtil.verify(text, rsaPublicKey, signature, "MD5");System.out.printf("【%s】的签名【%s】经过【RSA】验证后结果是:" + result, text, signature);

这里完整的demo代码:

import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey; public class RsaMain { public static void main(String[] args) {try {String text = "上山打老虎";boolean usePKCS8 = true; // usePKCS8=true表示是否成PKCS8格式的公私秘钥,否则乘车PKCS1格式的公私秘钥String filePath = RsaUtil.class.getClassLoader().getResource("").getPath();System.out.printf("文件路径:%s\n", filePath);// 存放pem,crt,pfx等文件的目录byte[] publicKey, privateKey;// 公钥和私钥 // 生成公私钥Object[] rsaKey = RsaUtil.generateRsaKey(usePKCS8); // usePKCS8=true表示是否成PKCS8格式的公私秘钥,否则乘车PKCS1格式的公私秘钥publicKey = (byte[]) rsaKey[0];privateKey = (byte[]) rsaKey[1];// 从Pem文件读取公私钥,filePath是文件目录// publicKey = RsaUtil.readFromPem(filePath + "rsa.pub");// privateKey = RsaUtil.readFromPem(filePath + "rsa.pem");// 从pfx文件读取公私钥,filePath是文件目录// Object[] rsaKey = RsaUtil.readFromPfx(filePath + "demo.pfx",// "123456");// publicKey = (byte[]) rsaKey[0];// privateKey = (byte[]) rsaKey[1];// 从crt文件读取公钥(crt文件中不包含私钥),filePath是文件目录// publicKey = RsaUtil.readPublicKeyFromCrt(filePath + "demo.crt");// privateKey = RsaUtil.readFromPem(filePath + "demo.key"); // 保存到pem文件,filePath是保存目录RsaUtil.writeToPem(publicKey, false, filePath + "rsa.pub");RsaUtil.writeToPem(privateKey, true, filePath + "rsa.pem"); // Pkcs8格式公钥转换为Pkcs1格式公钥publicKey = RsaUtil.pkcs8ToPkcs1(false, publicKey);// Pkcs8格式私钥转换为Pkcs1格式私钥privateKey = RsaUtil.pkcs8ToPkcs1(true, privateKey);// Pkcs1格式公钥转换为Pkcs8格式公钥publicKey = RsaUtil.pkcs1ToPkcs8(false, publicKey);// Pkcs1格式私钥转换为Pkcs8格式私钥privateKey = RsaUtil.pkcs1ToPkcs8(true, privateKey); RSAPublicKey rsaPublicKey = RsaUtil.generatePublicKey(usePKCS8, publicKey);RSAPrivateKey rsaPrivateKey = RsaUtil.generatePrivateKey(usePKCS8, privateKey); String encryptText = RsaUtil.rsaEncrypt(text, rsaPublicKey);System.out.printf("【%s】经过【RSA】加密后:%s\n", text, encryptText); String decryptText = RsaUtil.rsaDecrypt(encryptText, rsaPrivateKey);System.out.printf("【%s】经过【RSA】解密后:%s\n", encryptText, decryptText); String signature = RsaUtil.sign(text, rsaPrivateKey, "MD5");System.out.printf("【%s】经过【RSA】签名后:%s\n", text, signature); boolean result = RsaUtil.verify(text, rsaPublicKey, signature, "MD5");System.out.printf("【%s】的签名【%s】经过【RSA】验证后结果是:" + result, text, signature); } catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

感谢你能够认真阅读完这篇文章,希望小编分享的"Java怎么使用rsa非对称加密法进行加密"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!

格式 公钥 文件 加密 公私 生成 目录 信息 过程 输出 验证 字符 字符串 密钥 篇文章 utf-8 参数 模式 对称 内容 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 花魁咖啡 天津市摩尔互联网科技 互联网金融监管科技数据 互联网科技公司税收优惠 以房互联网科技 凡科互联网科技 壹账通互联网科技 深圳艾佳互联网科技 四个字互联网科技公司取名 深圳互联网科技怎么样 农村开互联网科技讲堂 互联网科技产品 河南猎农互联网科技有限公司 如何创新互联网科技 中国互联网公司排名锤子科技 用友工业互联网科技发展 群盈汇互联网科技有限公司 陕西九四连强互联网科技有限公司 恒生科技指数 中概互联网 株洲百竞科技的互联网营销顾问 互联网科技工作委员会主任 湖南永感互联网科技有限公司 致骋互联网科技 奇酷互联网络科技公司 广西互联网科技公司 汉立互联网科技有限公司联系电话 电子科技大学互联网创业大赛 深圳育鹏互联网科技有限公司招聘 广西互联网科技孵化中心 锡山区互联网智能科技产品供应
0