通過(guò)Java實(shí)現(xiàn)RSA加密與驗(yàn)證的方法詳解
RSA(Rivest–Shamir–Adleman)是一種非對(duì)稱加密算法,由Ron Rivest、Adi Shamir和Leonard Adleman于1977年提出,是目前廣泛應(yīng)用于加密和數(shù)字簽名領(lǐng)域的一種加密算法。RSA的工作原理基于兩個(gè)密鑰:公鑰和私鑰,分別用于加密和解密數(shù)據(jù),以及數(shù)字簽名和驗(yàn)證。
以下是RSA的主要特點(diǎn)和一些常見(jiàn)的使用場(chǎng)景:
- 非對(duì)稱加密: RSA是一種非對(duì)稱加密算法,意味著它使用不同的密鑰進(jìn)行加密和解密。公鑰用于加密數(shù)據(jù),只有擁有相應(yīng)私鑰的用戶才能解密它。這種非對(duì)稱性使得RSA在安全通信中非常有用,因?yàn)?code>公鑰可以公開(kāi)分享,而私鑰必須保密。
- 數(shù)字簽名和驗(yàn)證: RSA還可以用于
數(shù)字簽名和驗(yàn)證
。發(fā)送方可以使用其私鑰對(duì)消息進(jìn)行簽名,接收方可以使用發(fā)送方的公鑰來(lái)驗(yàn)證簽名。這確保了消息的完整性和來(lái)源認(rèn)證。數(shù)字簽名在網(wǎng)絡(luò)安全、電子郵件認(rèn)證和電子商務(wù)中廣泛使用。 - 密鑰交換: RSA可用于安全地交換對(duì)稱密鑰。
在兩個(gè)通信方之間建立安全連接時(shí),可以使用RSA加密傳輸對(duì)稱密鑰,然后使用該對(duì)稱密鑰進(jìn)行快速的數(shù)據(jù)加密和解密
。這提高了性能并確保了密鑰的安全交換。 - 安全通信: RSA可用于保護(hù)通信的機(jī)密性和完整性。通信雙方可以使用對(duì)方的公鑰來(lái)加密數(shù)據(jù),以確保只有持有私鑰的一方能夠解密它。這在保護(hù)敏感信息傳輸時(shí)非常重要,例如,網(wǎng)上銀行、電子商務(wù)和VPN連接。
- 數(shù)字證書(shū):
RSA也與數(shù)字證書(shū)一起使用,以驗(yàn)證網(wǎng)站的身份和安全性
。數(shù)字證書(shū)中包含了網(wǎng)站的公鑰,通過(guò)驗(yàn)證證書(shū)的簽名,用戶可以確保他們正在與合法的網(wǎng)站通信,而不是受到中間人攻擊。 - 安全存儲(chǔ):
RSA可以用于加密敏感數(shù)據(jù)
,然后將其存儲(chǔ)在不安全的環(huán)境中,只有持有私鑰的用戶才能解密和訪問(wèn)數(shù)據(jù)。這對(duì)于存儲(chǔ)密碼、加密錢(qián)包和數(shù)據(jù)庫(kù)等敏感數(shù)據(jù)非常有用。
總的來(lái)說(shuō),RSA是一種強(qiáng)大且多用途的加密算法,廣泛應(yīng)用于網(wǎng)絡(luò)通信、數(shù)據(jù)安全、數(shù)字簽名、身份驗(yàn)證和加密存儲(chǔ)等領(lǐng)域。然而,需要注意的是,RSA的性能較低,特別是對(duì)于長(zhǎng)消息,因此在某些情況下,可能需要與對(duì)稱加密算法結(jié)合使用,以提高性能。
本文主要講述如何通過(guò)Java實(shí)現(xiàn)RSA加密與驗(yàn)證,應(yīng)用場(chǎng)景為與其他平臺(tái)對(duì)接接口時(shí),通過(guò)RSA加密和解密驗(yàn)證請(qǐng)求的有效性,在對(duì)接時(shí)雙方互換公鑰
。
生成公私鑰
要實(shí)現(xiàn)加密和驗(yàn)證,首先你需要生成一對(duì)RSA密鑰對(duì),包括公鑰和私鑰。你可以使用Java的KeyPairGenerator
類來(lái)生成密鑰對(duì)。實(shí)現(xiàn)代碼如下:
package com.zjq.dailyrecord.security; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.util.Base64; /** * RSA公私鑰生成 * @author 共飲一杯無(wú) */ public class GenerateRSAKeys { public static void main(String[] args) throws Exception { // 創(chuàng)建一個(gè)RSA密鑰對(duì)生成器 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); // 設(shè)置密鑰長(zhǎng)度,通常為2048位 keyPairGenerator.initialize(2048); // 生成RSA密鑰對(duì) KeyPair keyPair = keyPairGenerator.generateKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); System.out.println("公鑰: " + Base64.getEncoder().encodeToString(publicKey.getEncoded())); System.out.println("私鑰: " + Base64.getEncoder().encodeToString(privateKey.getEncoded())); } }
基礎(chǔ)的公鑰加密私鑰解密
具體代碼實(shí)現(xiàn)如下:
package com.zjq.dailyrecord.security; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import javax.crypto.Cipher; /** * RSA加密和解密 * @author 共飲一杯無(wú) */ public class RSAEncryptionDecryption { public static void main(String[] args) throws Exception { String originalText = "Hello, RSA encryption and decryption!"; // 將公鑰和私鑰的Base64編碼字符串轉(zhuǎn)換為PublicKey和PrivateKey對(duì)象 String publicKeyBase64 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhRJqXuMDyyc4b3+LrsZqwh+sZtV3n2pwjkWZ+SIkfW3GlrVPEQmGDbCB2xJ3coSc/IQ5ukkdh1ArTzf69kmn3zNZT34ZJgYjLNnvi9I2dBRZkARV2ERFhPYZsUt8WecSGt29SK22NsctMkSroRmsLRMUArmZ2r3knMrhy54PLvoeXwvDdpXC19EsioK5I7Huh29G+c3Bi8IWySR4/U2kpH+8CU2iZGiChwIZ6qqJgvaVbUuSdksHFnrVbl1LjqGKlb+Vos16UnluPlW4PGJMCfRYZcPqLSm728qT+jQFIUK17yAeznIvx5nccg6ke1GgnwhqeDicPuKnj4FKFm33/wIDAQAB"; String privateKeyBase64 = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCFEmpe4wPLJzhvf4uuxmrCH6xm1XefanCORZn5IiR9bcaWtU8RCYYNsIHbEndyhJz8hDm6SR2HUCtPN/r2SaffM1lPfhkmBiMs2e+L0jZ0FFmQBFXYREWE9hmxS3xZ5xIa3b1IrbY2xy0yRKuhGawtExQCuZnaveScyuHLng8u+h5fC8N2lcLX0SyKgrkjse6Hb0b5zcGLwhbJJHj9TaSkf7wJTaJkaIKHAhnqqomC9pVtS5J2SwcWetVuXUuOoYqVv5WizXpSeW4+Vbg8YkwJ9Fhlw+otKbvbypP6NAUhQrXvIB7Oci/HmdxyDqR7UaCfCGp4OJw+4qePgUoWbff/AgMBAAECggEAWWJOSuAn6yy0DsjYlZQ3n59Q2V4n1M/VPOtpiluxsQKsswykSGhiQA3Am9timmyTWlaixAtap0plXPfYPdipxxYhtnCYCd9zfywAaKXR59THeCJBW1w4aiA4j8uJgoXgtmUdQJVWYKMXK73Onw60hS5ccZwjyTdmOR9Z3cCUqFNmX9EIAj9jUE9/nASNgnGNH5ULspaBUSH59B0D/2kNUexMrteShtlxKL73iFdptGu68NLk05GvghLG3o0HMJtOIyF+kj6x0BtPcD5xh7YxN6PTdrxnj4tmKsAesc38NBJphFFFmvxY5B9m9gKMOBQcGVW0By6AJLbE5Pj1w5GlMQKBgQDJ7+XQc3Q8VgXQZYpO2CA8Kygkls7GTsXwblB6u0aYT7uhht4Dwk2xCtkRWoUri6rVkcOKKY/SrU4GvVyK8E5AMHfOjTc1M6GQ6UOj760NUMqUwwzR45pUFKLtYq+gOlWqHz0Vu84DCQqU7nhJGqv5cMUoZRkTrqV6zPq/oWLa6QKBgQCosroKI3NfvkaTxYboNF8Bn6j1nzCrNW3VrtZvXXbeTWTxSgH01p45IcPPEfauQqHHzFSzrVP4HL9PNz8SYpwhS61i3PX5S2ftLRKsfOheYKWG7l5clu80SZfAcpXblp4QTZmHdp67dp2XMEFi/3VGDhZU/LCpLMvIUs/8MpmapwKBgBXALD3Gocd58Ihg14PkjZxNfbZrM/xyManTCAIgN9tiAzDDyRgYjqu6ImVXHa7yDUWRvMEd9urXVect8FDaz2LklZL+7OpjFEz6gxmeUEJ16Ewbsj7NSCs0SdRN4+LbRazcToUPxIHZMHWYNgaRw+JLPkE6mnffQN24RG3toSs5AoGBAIgoEI2kRTduXIpiL9t0gYXO9lCgVmio6+g+f+ZMemc78g/pWqDhI70a6m5TolTNhMO8wFRwvcgQc7wc6/QL0NXyvZOAoaq+2LeN3HeJLQcXXCIGe/ShAZmjGC8EjL052INyDktOSxkkyFbBZNThOCb9sbqQZIl2lVcut51mvaEbAoGBALwLpxIjj7N+dxkbScZCTWCgSPZ6t9y5rO9VkLtJ31aDAFqXljh4hphHhnsUq9z2pT3fo5mNRnaYutIixmzxQSQlzmjvnzFe+ZHFXMHm2l1fgOi5ByV9a/prUmyTuLuiwCf1/Q+E+qFPNnl5Actbamqk26zlMbZVTK6lrTM5PN+/"; PublicKey publicKey = KeyFactory.getInstance("RSA") .generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyBase64))); PrivateKey privateKey = KeyFactory.getInstance("RSA") .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyBase64))); // 使用公鑰加密數(shù)據(jù) Cipher encryptCipher = Cipher.getInstance("RSA"); encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedBytes = encryptCipher.doFinal(originalText.getBytes()); // 使用私鑰解密數(shù)據(jù) Cipher decryptCipher = Cipher.getInstance("RSA"); decryptCipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedBytes = decryptCipher.doFinal(encryptedBytes); String decryptedText = new String(decryptedBytes); System.out.println("加密后的數(shù)據(jù): " + Base64.getEncoder().encodeToString(encryptedBytes)); System.out.println("解密后的數(shù)據(jù): " + decryptedText); } }
執(zhí)行結(jié)果如下:
自定義密鑰加密及校驗(yàn)
通過(guò)對(duì)接雙方各自生成對(duì)應(yīng)的公私鑰,然后交換公鑰和jwt用戶key的形式實(shí)現(xiàn)加密和驗(yàn)證。
需要引入如下坐標(biāo)依賴:
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.8.3</version> </dependency>
具體代碼實(shí)現(xiàn)如下:
加密
/** * 加密 * @param dataJson * @param priKey * @param pubKey * @return */ public static String encodeJwtToken(String dataJson, String priKey, String pubKey) { try { RSAPublicKey publicKey = defaultRSAPublicKey(pubKey); RSAPrivateKey privateKey = defaultRSAPrivateKey(priKey); //加密 Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey); String token = JWT.create() .withIssuer(RSAKeyUtil.USER_KEY) //.withExpiresAt(expiresAt) .withClaim("data", dataJson) .sign(algorithm); return token; } catch (Exception e) { e.printStackTrace(); return null; } } public static RSAPublicKey defaultRSAPublicKey(String pubKey) throws Exception { RSAPublicKey publicKey = getRSAPublicKey(pubKey); return publicKey; } public static RSAPrivateKey defaultRSAPrivateKey(String priKey) throws Exception { RSAPrivateKey privateKey = getRSAPrivateKey(priKey); return privateKey; } public static RSAPublicKey getRSAPublicKey(String publicKey) throws Exception { byte[] publicBytes = decryptBASE64(publicKey); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(keySpec); return pubKey; } public static RSAPrivateKey getRSAPrivateKey(String privateKey) throws Exception { byte[] clear = decryptBASE64(privateKey); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(clear); KeyFactory fact = KeyFactory.getInstance("RSA"); RSAPrivateKey priKey = (RSAPrivateKey) fact.generatePrivate(keySpec); Arrays.fill(clear, (byte) 0); return priKey; } /** * 解碼返回byte * @param key * @return * @throws Exception */ public static byte[] decryptBASE64(String key) throws Exception { return (new BASE64Decoder()).decodeBuffer(key); }
校驗(yàn)
/** * 驗(yàn)簽校驗(yàn) * @param jwtToken * @param priKey * @param pubKey * @return * @throws Exception */ public static Boolean verify(String jwtToken, String priKey, String pubKey) throws Exception { RSAPublicKey publicKey = RSAKeyUtil.defaultRSAPublicKey(pubKey); RSAPrivateKey privateKey = RSAKeyUtil.defaultRSAPrivateKey(priKey); //加密 Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey); //解密 JWTVerifier verifier = JWT.require(algorithm) .withIssuer(RSAKeyUtil.USER_KEY) .build(); DecodedJWT jwt = null; try{ jwt = verifier.verify(jwtToken); }catch (Exception e){ e.printStackTrace(); return false; } return !StringUtils.isEmpty(jwt); }
測(cè)試驗(yàn)證
測(cè)試驗(yàn)證代碼如下:
package com.zjq.dailyrecord.security; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.JWTVerifier; import org.springframework.util.StringUtils; import sun.misc.BASE64Decoder; import java.security.KeyFactory; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; /** * 商戶公司驗(yàn)簽加解密工具類 * @author 共飲一杯無(wú) */ public class RSAKeyUtil { public final static String USER_KEY = "gongyinyibeiwu"; /** * 驗(yàn)簽校驗(yàn) * @param jwtToken * @param priKey * @param pubKey * @return * @throws Exception */ public static Boolean verify(String jwtToken, String priKey, String pubKey) throws Exception { RSAPublicKey publicKey = RSAKeyUtil.defaultRSAPublicKey(pubKey); RSAPrivateKey privateKey = RSAKeyUtil.defaultRSAPrivateKey(priKey); //加密 Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey); //解密 JWTVerifier verifier = JWT.require(algorithm) .withIssuer(RSAKeyUtil.USER_KEY) .build(); DecodedJWT jwt = null; try{ jwt = verifier.verify(jwtToken); Claim subjectClaim = verifier.verify(jwtToken).getClaim("data"); String result = subjectClaim.asString(); System.out.println("解密結(jié)果:"+result); }catch (Exception e){ e.printStackTrace(); return false; } return !StringUtils.isEmpty(jwt); } /** * 加密 * @param dataJson * @param priKey * @param pubKey * @return */ public static String encodeJwtToken(String dataJson, String priKey, String pubKey) { try { RSAPublicKey publicKey = defaultRSAPublicKey(pubKey); RSAPrivateKey privateKey = defaultRSAPrivateKey(priKey); //加密 Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey); String token = JWT.create() .withIssuer(RSAKeyUtil.USER_KEY) //.withExpiresAt(expiresAt) .withClaim("data", dataJson) .sign(algorithm); return token; } catch (Exception e) { e.printStackTrace(); return null; } } public static RSAPublicKey defaultRSAPublicKey(String pubKey) throws Exception { RSAPublicKey publicKey = getRSAPublicKey(pubKey); return publicKey; } public static RSAPrivateKey defaultRSAPrivateKey(String priKey) throws Exception { RSAPrivateKey privateKey = getRSAPrivateKey(priKey); return privateKey; } public static RSAPublicKey getRSAPublicKey(String publicKey) throws Exception { byte[] publicBytes = decryptBASE64(publicKey); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(keySpec); return pubKey; } public static RSAPrivateKey getRSAPrivateKey(String privateKey) throws Exception { byte[] clear = decryptBASE64(privateKey); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(clear); KeyFactory fact = KeyFactory.getInstance("RSA"); RSAPrivateKey priKey = (RSAPrivateKey) fact.generatePrivate(keySpec); Arrays.fill(clear, (byte) 0); return priKey; } /** * 解碼返回byte * @param key * @return * @throws Exception */ public static byte[] decryptBASE64(String key) throws Exception { return (new BASE64Decoder()).decodeBuffer(key); } public static void main(String[] args) { // 當(dāng)前平臺(tái)的公鑰 String ownPubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgBu0tGxKBDDUzEW498JYS5ibAtCTxXcw7fEALMek3D6mfbV9JOe10+Ukf9CSRYd4FEhjaq63Vy57mVs/Bmse9RQcv2AxyCBThwKJELA8kH2B8ulYkwlthEyz5/HJ49eLKljak9+b5Ya6uHTo3d5xIhXLc20IzW1O4QsxJVkmkTYS0jruFx3YrZdiiluawCYdmAUQ34JONS4cgsMrjwF8sRNsZ6Vu0trCttY94i2NYWJU1X0XCMWcYoTKLCenMa4XMoP+cgI1Q+6Ni4zZbCLMkwxo7rr+LBD6jpzrfi9/p15PdnzGFvOr+ZCQbKwemex+GuR86Xq/+ZozHK9YIjrcvQIDAQAB"; // 當(dāng)前平臺(tái)的私鑰 String ownPriKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCAG7S0bEoEMNTMRbj3wlhLmJsC0JPFdzDt8QAsx6TcPqZ9tX0k57XT5SR/0JJFh3gUSGNqrrdXLnuZWz8Gax71FBy/YDHIIFOHAokQsDyQfYHy6ViTCW2ETLPn8cnj14sqWNqT35vlhrq4dOjd3nEiFctzbQjNbU7hCzElWSaRNhLSOu4XHditl2KKW5rAJh2YBRDfgk41LhyCwyuPAXyxE2xnpW7S2sK21j3iLY1hYlTVfRcIxZxihMosJ6cxrhcyg/5yAjVD7o2LjNlsIsyTDGjuuv4sEPqOnOt+L3+nXk92fMYW86v5kJBsrB6Z7H4a5Hzper/5mjMcr1giOty9AgMBAAECggEANjoEEr8n0YBOAy2cLxvPvigZrWZWtqZOStnRxiK38RZ/6QRStbVzLP94pLXHxLCkLom5s2XDa57caLzL/86GKx1ZUdTJHbo5QRPcqvi+mjbWM9l8Sbka536ERLD/UXdijAlSdHeZiN2v2fZ6v7ex0cjB9tj3eeVEF1RieDm1bo+IffHsiDKidfJ3/VaG5rlOzxQvxq22R9BBh5I8C1N3OnDX+A4R4lqy85OTH5+IQcJh4Z4lDP2gMHMqDJDoa6yxOB4UdL9gmfWDx2TBD9Y0XbaILDRGHG/gdPPtUb7ybhuZ3GaRO0JfH6k0oeGo+g7dAOTkyZlkPFa++jgXf/YYrQKBgQC/Ar3E54fZAzdQv0f9uBtEhtgT4Um0OcXZin6WUqBbcYwH1XnATPxPpQG0SNpRDWlKiBVSGH2d9OcE6Rxtal3IbXR/nTtGQumWSFJ8cYIaQGS22Bynb5e5H5XXfgXZ+0qlGgMW3WeqJv7f47g/W14w8rBf4zCbQ44JALd3+CraBwKBgQCrshV+86pjEQfWzuuGGNOaVt4GEyomheGGxWd1vncDm6TwFYixiWEnt/0ZKRXjN7gmljv07u17WZHANRKeHJJ5mYTfge/ZKrrY5LUorWA3lpzTbFEdOof+ea7FUujfZ0VcFmRtEb1yyOwtxTNyUSuwJn9OzmbhsGZngUGtIbuyGwKBgBy4TsxSe8yXfTO47xwpGIB/PfIPR8O/hA4nks0Lc20Mb5+l636MlMts5gqzgY/6UkCQoZQMdqbPcgT8//c7rQo72u5tN8JiwTiFe1GWx5cm433SlMxgLRH6u88A9eRGsnyMorZHaBTfdCc52DQ+irUVaIuiX2aZC7wyzWNOfzL1AoGADEbJfrBRiI/ZLaTR9l6kEq8PZQPNyb9c5tQKl8Kso9dnLbt8cKVQCxT+xePIKtz7D9dCJjtHQ8CdyU6CLEgCuSse8xRJYA/MGGISCfyLmq3sPLnL+vkKbEmrE3TgLckmjnUTbTENiL2RFZy6Fvxy0T+PbsUXWh/Q0qnNVmHJF+0CgYBstz+ESSvKJhSCNpWccnsCNyza9gy1KrgHFQn8RbJ/ss4s21iXEBZYEex2sjwFUZmH2xUxeV45x2zOyCrxJrHqgaA+0og8CmD5mqLDpliiBOpIQr2Du7DLMUAQDZ4oJvkul/ADQ3HJcCcMqQs7xLI0PzIKHjhh/IeWtxbQDDp72g=="; // 對(duì)接平臺(tái)公鑰 String otherPubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4A6SXgt/nNh76Hn85pZxvh2mRv2y4VWfrwM8lFv7urzJ3xt5FocujjEoQT3Q5jeByxiZaOmPk6mfpTTCsel5vGZqLtM8mrNKoPrXiKuq0U0sWUpXdlRLaFV+SMujTsuYl76get9kLVjwXRu4qlhtZlLlWcLpNu6wEu1JwY8Kl9BDP46X0J+IoL+f9iB0i8PAw71n6NJmGk4bvYAjwnMd9zMPdY+s9hfbv2OILdGkSAcaZGoan03HK8u5JBikMZOvhXHkNkgBtRX8ATqCbYK4fTAC70RdOwqbyOhcW/qie18KnfZJsINb7cPfN406wIK6rMapCx7RJ7eu7Ey0Hm8GGQIDAQAB"; // 對(duì)接平臺(tái)私鑰 String otherPriKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDgDpJeC3+c2HvoefzmlnG+HaZG/bLhVZ+vAzyUW/u6vMnfG3kWhy6OMShBPdDmN4HLGJlo6Y+TqZ+lNMKx6Xm8Zmou0zyas0qg+teIq6rRTSxZSld2VEtoVX5Iy6NOy5iXvqB632QtWPBdG7iqWG1mUuVZwuk27rAS7UnBjwqX0EM/jpfQn4igv5/2IHSLw8DDvWfo0mYaThu9gCPCcx33Mw91j6z2F9u/Y4gt0aRIBxpkahqfTccry7kkGKQxk6+FceQ2SAG1FfwBOoJtgrh9MALvRF07CpvI6Fxb+qJ7Xwqd9kmwg1vtw983jTrAgrqsxqkLHtEnt67sTLQebwYZAgMBAAECggEAHh23TM7M21854HitJq1oIn7Hv9kP9zvUF+kedm6aunHvzH5b20xWVKSE3agacSda2dq3nCNwug9dtw4NcW6Jf2pgsWSRS9X3nQW6fNNeRX3TDTlx4iTYcfCz5cMBc3DoVNU5qupmA7ZlsI4uVy9FnTBdRaBuSoTww8qDVHIOoXMLenXArosyQEytxEL1uBGF8xijBWC5CGQfLjegcqYiVJ7Bl5kGXGwo0q0dzTabx/P4sH1BBRWMkTEUgfBZs4QvFiTfCIB0/X44cIHpokBnaeYGKX7aVVDIRni1ot3gzYDgBnIGM9ZY/CjLn0mrnZciVr8SemTyobGf/GlPoID+xQKBgQD4HLuAQR1SqiNwuB+lDz0hYqFL/r3VvEa4Wety7lznppz9EWeDEnN89bk9+RXxq+cSg7EwGdI+LGNeZpShpCBrb/93VYN/kohywb6vgZJ3gjT50J+8mmvxm0cE61xZ+VGkAKn1QqO6voF17mOcHD4k/h1je0SVj7d40q2QbQwKWwKBgQDnLhCF9JZE23gPP2CCccQlA4QHR89i6YwQpFWyINIJA/p42cdVPErprQqsBDBoV5sk9GX9X08GBsU2tDDvOxCsQjPShe/pVSvdCg8aFnQzi5r8lEhGpirH16N9LHRx2dsFvoN/h+zqbuF4MRdmsPmUb6UFs3CnGfvraWo/OCATmwKBgAsS1TeDMHjZCR3lydvHE1ZjHYnTw8s/TPS7ZqvJgbIBGK6e0TzjXO4t1Wezr0wK/RQxdn4MGPsXZhP3hhi0x5Gj/QXpdiYCdz6P8R/KK6xTzmN78TUsuzacVI4epw+I9iDYur0sjTwvdn259w4noIpsIQmoncYDFRA6bu6sP0ZTAoGBAIra/Em5c1jAigh+hLVVJ/8jcXX+B+7dYKfOTTrEw+NuZE+aX0QvBr/8k+BmU70YgbNcqLXbPVfdUS9eY9YNoCIXUZEtqcB4y/PkStXcjsc3H0x+tDrbK+8E8soInZiUxh1ZJRrAxei52OuccPXZbs9dj70w3oU/8jSgCJUYXQvpAoGBAIv+AsEpjKnSCukCftO4XBdRFgyf4+XXbnqOqThHzUlSd02qk2aijjs9XFMtnoBobqOM/jDhh6uYSX5vWJtrarlgX7cvKD9xDroC54RmDnDfOl0CfN5DaffofsD8+z6MSQU1FN1PYigkqfDHCKCFRL4Hp90PvGuynejhAl8x1OfC"; String jsonStr = "{\n" + " \"name\":\"共飲一杯無(wú)\"\n" + "}"; // 1.先加密 String jwtToken = RSAKeyUtil.encodeJwtToken(jsonStr,ownPriKey,otherPubKey); System.out.println(jwtToken); try { // 2.解密 Boolean verify = RSAKeyUtil.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJkYXRhIjoie1xuICAgIFwibmFtZVwiOlwi5YWx6aWu5LiA5p2v5pegXCJcbn0iLCJpc3MiOiJnb25neWlueWliZWl3dSJ9.BGat7UWtc75ZyTMoySrtBOLyED9iNBOJOvw198_yg6ZbjCuitFIvl4p7qs9v2oo3BoAPWH8gKLQsLLhsUQ6p9thcCimB0ClTJkxQlxd_2I8J-fli2Jmc09I53mIptNOtfB_zDn5UuXyVtB5-aD_mUs9xLXkEb8DJbMl4__LHDQyr1v3ixh0rq_e5LaY0ZOfSq2l06MaSAssdKQRvN_H0snO0KJkodcPktfRr4hOXI_ZvcbZHgiuv6JUpbp6x7T9BWMvixD7TTd-lqqm2OsqGOCtWJ4URSJmjYdLDswHY89jNzfVHrQ6exuUIeranWJoRf2-smE8KpLAN8kxs1o1Rpg" ,otherPriKey,ownPubKey); System.out.println(verify); } catch (Exception e) { e.printStackTrace(); } } }
如果用戶key不對(duì)會(huì)報(bào)如下錯(cuò)誤:
如果公私鑰不匹配會(huì)報(bào)如下錯(cuò)誤:
兩種結(jié)果都說(shuō)明解密失敗。
正常執(zhí)行返回結(jié)果:
使用RSA進(jìn)行數(shù)字簽名和驗(yàn)證
實(shí)現(xiàn)邏輯為使用私鑰對(duì)數(shù)據(jù)進(jìn)行簽名
,然后使用公鑰進(jìn)行驗(yàn)證
。具體代碼實(shí)現(xiàn)如下:
import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; /** * RSA數(shù)字簽名實(shí)現(xiàn) * @author 共飲一杯無(wú) */ public class RSASignatureVerification { public static void main(String[] args) throws Exception { String data = "待簽署及核實(shí)的資料。"; // 將公鑰和私鑰的Base64編碼字符串轉(zhuǎn)換為PublicKey和PrivateKey對(duì)象 String publicKeyBase64 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhRJqXuMDyyc4b3+LrsZqwh+sZtV3n2pwjkWZ+SIkfW3GlrVPEQmGDbCB2xJ3coSc/IQ5ukkdh1ArTzf69kmn3zNZT34ZJgYjLNnvi9I2dBRZkARV2ERFhPYZsUt8WecSGt29SK22NsctMkSroRmsLRMUArmZ2r3knMrhy54PLvoeXwvDdpXC19EsioK5I7Huh29G+c3Bi8IWySR4/U2kpH+8CU2iZGiChwIZ6qqJgvaVbUuSdksHFnrVbl1LjqGKlb+Vos16UnluPlW4PGJMCfRYZcPqLSm728qT+jQFIUK17yAeznIvx5nccg6ke1GgnwhqeDicPuKnj4FKFm33/wIDAQAB"; String privateKeyBase64 = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCFEmpe4wPLJzhvf4uuxmrCH6xm1XefanCORZn5IiR9bcaWtU8RCYYNsIHbEndyhJz8hDm6SR2HUCtPN/r2SaffM1lPfhkmBiMs2e+L0jZ0FFmQBFXYREWE9hmxS3xZ5xIa3b1IrbY2xy0yRKuhGawtExQCuZnaveScyuHLng8u+h5fC8N2lcLX0SyKgrkjse6Hb0b5zcGLwhbJJHj9TaSkf7wJTaJkaIKHAhnqqomC9pVtS5J2SwcWetVuXUuOoYqVv5WizXpSeW4+Vbg8YkwJ9Fhlw+otKbvbypP6NAUhQrXvIB7Oci/HmdxyDqR7UaCfCGp4OJw+4qePgUoWbff/AgMBAAECggEAWWJOSuAn6yy0DsjYlZQ3n59Q2V4n1M/VPOtpiluxsQKsswykSGhiQA3Am9timmyTWlaixAtap0plXPfYPdipxxYhtnCYCd9zfywAaKXR59THeCJBW1w4aiA4j8uJgoXgtmUdQJVWYKMXK73Onw60hS5ccZwjyTdmOR9Z3cCUqFNmX9EIAj9jUE9/nASNgnGNH5ULspaBUSH59B0D/2kNUexMrteShtlxKL73iFdptGu68NLk05GvghLG3o0HMJtOIyF+kj6x0BtPcD5xh7YxN6PTdrxnj4tmKsAesc38NBJphFFFmvxY5B9m9gKMOBQcGVW0By6AJLbE5Pj1w5GlMQKBgQDJ7+XQc3Q8VgXQZYpO2CA8Kygkls7GTsXwblB6u0aYT7uhht4Dwk2xCtkRWoUri6rVkcOKKY/SrU4GvVyK8E5AMHfOjTc1M6GQ6UOj760NUMqUwwzR45pUFKLtYq+gOlWqHz0Vu84DCQqU7nhJGqv5cMUoZRkTrqV6zPq/oWLa6QKBgQCosroKI3NfvkaTxYboNF8Bn6j1nzCrNW3VrtZvXXbeTWTxSgH01p45IcPPEfauQqHHzFSzrVP4HL9PNz8SYpwhS61i3PX5S2ftLRKsfOheYKWG7l5clu80SZfAcpXblp4QTZmHdp67dp2XMEFi/3VGDhZU/LCpLMvIUs/8MpmapwKBgBXALD3Gocd58Ihg14PkjZxNfbZrM/xyManTCAIgN9tiAzDDyRgYjqu6ImVXHa7yDUWRvMEd9urXVect8FDaz2LklZL+7OpjFEz6gxmeUEJ16Ewbsj7NSCs0SdRN4+LbRazcToUPxIHZMHWYNgaRw+JLPkE6mnffQN24RG3toSs5AoGBAIgoEI2kRTduXIpiL9t0gYXO9lCgVmio6+g+f+ZMemc78g/pWqDhI70a6m5TolTNhMO8wFRwvcgQc7wc6/QL0NXyvZOAoaq+2LeN3HeJLQcXXCIGe/ShAZmjGC8EjL052INyDktOSxkkyFbBZNThOCb9sbqQZIl2lVcut51mvaEbAoGBALwLpxIjj7N+dxkbScZCTWCgSPZ6t9y5rO9VkLtJ31aDAFqXljh4hphHhnsUq9z2pT3fo5mNRnaYutIixmzxQSQlzmjvnzFe+ZHFXMHm2l1fgOi5ByV9a/prUmyTuLuiwCf1/Q+E+qFPNnl5Actbamqk26zlMbZVTK6lrTM5PN+/"; PublicKey publicKey = KeyFactory.getInstance("RSA") .generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyBase64))); PrivateKey privateKey = KeyFactory.getInstance("RSA") .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyBase64))); // 使用私鑰進(jìn)行數(shù)字簽名 Signature signature = Signature.getInstance("SHA256withRSA"); signature.initSign(privateKey); signature.update(data.getBytes()); byte[] signatureBytes = signature.sign(); System.out.println("數(shù)字簽名: " + Base64.getEncoder().encodeToString(signatureBytes)); // 使用公鑰進(jìn)行驗(yàn)證 signature.initVerify(publicKey); signature.update(data.getBytes()); boolean verified = signature.verify(signatureBytes); if (verified) { System.out.println("數(shù)字簽名驗(yàn)證成功!"); } else { System.out.println("數(shù)字簽名驗(yàn)證失?。?); } } }
結(jié)果輸出如下:
以上就是通過(guò)Java實(shí)現(xiàn)RSA加密與驗(yàn)證的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于Java實(shí)現(xiàn)RSA加密與驗(yàn)證的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
spring自定義一個(gè)簡(jiǎn)單的Starter啟動(dòng)器
這篇文章主要介紹了spring自定義一個(gè)簡(jiǎn)單的Starter啟動(dòng)器,一個(gè) starter其實(shí)就是對(duì)一個(gè)功能的集成封裝,然后對(duì)外提供一個(gè)依賴,讓業(yè)務(wù)去使用,像我們熟悉的 Redis,mongo,mybatis 等均屬于,需要的朋友可以參考下2023-07-07基于Java并發(fā)容器ConcurrentHashMap#put方法解析
下面小編就為大家?guī)?lái)一篇基于Java并發(fā)容器ConcurrentHashMap#put方法解析。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06IDEA版使用Java操作Redis數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了IDEA版使用Java操作Redis數(shù)據(jù)庫(kù)的方法,首先需要下載jedis.jar包,然后再工程中設(shè)置具體操作步驟跟隨小編一起學(xué)習(xí)下吧2021-08-08Idea配置maven-tomcat-plugin插件實(shí)現(xiàn)項(xiàng)目部署
今天小編就為大家分享一篇關(guān)于Idea配置maven-tomcat-plugin插件實(shí)現(xiàn)項(xiàng)目部署,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-02-02JavaWeb 入門(mén)篇:創(chuàng)建Web項(xiàng)目,Idea配置tomcat
這篇文章主要介紹了IDEA創(chuàng)建web項(xiàng)目配置Tomcat的詳細(xì)教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-07教你使用IDEA搭建spring源碼閱讀環(huán)境的詳細(xì)步驟
這篇文章主要介紹了使用IDEA搭建spring源碼閱讀環(huán)境的詳細(xì)步驟,本文分兩步通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-08-08Idea打包springboot項(xiàng)目沒(méi)有.original文件解決方案
這篇文章主要介紹了Idea打包springboot項(xiàng)目沒(méi)有.original文件解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07Java用正則表達(dá)式實(shí)現(xiàn)${name}形式的字符串模板實(shí)例
這篇文章主要給大家介紹了Java如何用正則表達(dá)式實(shí)現(xiàn)${name}形式的字符串模板,文章給出詳細(xì)的實(shí)例代碼,對(duì)大家的理解和學(xué)習(xí)會(huì)很有幫助,有需要的朋友們下面來(lái)一起看看吧。2016-12-12