中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java怎么使用rsa非對稱加密法進行加密

發布時間:2022-02-23 14:30:12 來源:億速云 閱讀:153 作者:小新 欄目:開發技術

這篇文章主要介紹了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中添加依賴:  

<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.68</version></dependency>

簡單封裝的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<String> 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("%02x", 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("%02x", 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非對稱加密法進行加密”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

比如县| 曲沃县| 敦化市| 常熟市| 七台河市| 蓬莱市| 龙游县| 额尔古纳市| 浦城县| 漯河市| 南陵县| 台南市| 民丰县| 炉霍县| 孝感市| 齐齐哈尔市| 临颍县| 崇文区| 台南市| 瑞金市| 麻江县| 晋中市| 东平县| 冕宁县| 寿宁县| 莱州市| 光山县| 西藏| 桃园县| 竹山县| 汕头市| 保山市| 峨山| 阳江市| 平潭县| 响水县| 宁阳县| 汤原县| 卢龙县| 唐海县| 界首市|