通過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)和一些常見的使用場(chǎng)景:
- 非對(duì)稱加密: RSA是一種非對(duì)稱加密算法,意味著它使用不同的密鑰進(jìn)行加密和解密。公鑰用于加密數(shù)據(jù),只有擁有相應(yīng)私鑰的用戶才能解密它。這種非對(duì)稱性使得RSA在安全通信中非常有用,因?yàn)?code>公鑰可以公開分享,而私鑰必須保密。
- 數(shù)字簽名和驗(yàn)證: RSA還可以用于
數(shù)字簽名和驗(yàn)證。發(fā)送方可以使用其私鑰對(duì)消息進(jìn)行簽名,接收方可以使用發(fā)送方的公鑰來驗(yàn)證簽名。這確保了消息的完整性和來源認(rèn)證。數(shù)字簽名在網(wǎng)絡(luò)安全、電子郵件認(rèn)證和電子商務(wù)中廣泛使用。 - 密鑰交換: RSA可用于安全地交換對(duì)稱密鑰。
在兩個(gè)通信方之間建立安全連接時(shí),可以使用RSA加密傳輸對(duì)稱密鑰,然后使用該對(duì)稱密鑰進(jìn)行快速的數(shù)據(jù)加密和解密。這提高了性能并確保了密鑰的安全交換。 - 安全通信: RSA可用于保護(hù)通信的機(jī)密性和完整性。通信雙方可以使用對(duì)方的公鑰來加密數(shù)據(jù),以確保只有持有私鑰的一方能夠解密它。這在保護(hù)敏感信息傳輸時(shí)非常重要,例如,網(wǎng)上銀行、電子商務(wù)和VPN連接。
- 數(shù)字證書:
RSA也與數(shù)字證書一起使用,以驗(yàn)證網(wǎng)站的身份和安全性。數(shù)字證書中包含了網(wǎng)站的公鑰,通過驗(yàn)證證書的簽名,用戶可以確保他們正在與合法的網(wǎng)站通信,而不是受到中間人攻擊。 - 安全存儲(chǔ):
RSA可以用于加密敏感數(shù)據(jù),然后將其存儲(chǔ)在不安全的環(huán)境中,只有持有私鑰的用戶才能解密和訪問數(shù)據(jù)。這對(duì)于存儲(chǔ)密碼、加密錢包和數(shù)據(jù)庫等敏感數(shù)據(jù)非常有用。
總的來說,RSA是一種強(qiáng)大且多用途的加密算法,廣泛應(yīng)用于網(wǎng)絡(luò)通信、數(shù)據(jù)安全、數(shù)字簽名、身份驗(yàn)證和加密存儲(chǔ)等領(lǐng)域。然而,需要注意的是,RSA的性能較低,特別是對(duì)于長消息,因此在某些情況下,可能需要與對(duì)稱加密算法結(jié)合使用,以提高性能。
本文主要講述如何通過Java實(shí)現(xiàn)RSA加密與驗(yàn)證,應(yīng)用場(chǎng)景為與其他平臺(tái)對(duì)接接口時(shí),通過RSA加密和解密驗(yàn)證請(qǐng)求的有效性,在對(duì)接時(shí)雙方互換公鑰。
生成公私鑰
要實(shí)現(xiàn)加密和驗(yàn)證,首先你需要生成一對(duì)RSA密鑰對(duì),包括公鑰和私鑰。你可以使用Java的KeyPairGenerator類來生成密鑰對(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 共飲一杯無
*/
public class GenerateRSAKeys {
public static void main(String[] args) throws Exception {
// 創(chuàng)建一個(gè)RSA密鑰對(duì)生成器
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
// 設(shè)置密鑰長度,通常為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 共飲一杯無
*/
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)
通過對(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 共飲一杯無
*/
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\":\"共飲一杯無\"\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é)果都說明解密失敗。
正常執(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 共飲一杯無
*/
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é)果輸出如下:

以上就是通過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è)簡單的Starter啟動(dòng)器
這篇文章主要介紹了spring自定義一個(gè)簡單的Starter啟動(dòng)器,一個(gè) starter其實(shí)就是對(duì)一個(gè)功能的集成封裝,然后對(duì)外提供一個(gè)依賴,讓業(yè)務(wù)去使用,像我們熟悉的 Redis,mongo,mybatis 等均屬于,需要的朋友可以參考下2023-07-07
基于Java并發(fā)容器ConcurrentHashMap#put方法解析
下面小編就為大家?guī)硪黄贘ava并發(fā)容器ConcurrentHashMap#put方法解析。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06
IDEA版使用Java操作Redis數(shù)據(jù)庫的方法
這篇文章主要介紹了IDEA版使用Java操作Redis數(shù)據(jù)庫的方法,首先需要下載jedis.jar包,然后再工程中設(shè)置具體操作步驟跟隨小編一起學(xué)習(xí)下吧2021-08-08
Idea配置maven-tomcat-plugin插件實(shí)現(xiàn)項(xiàng)目部署
今天小編就為大家分享一篇關(guān)于Idea配置maven-tomcat-plugin插件實(shí)現(xiàn)項(xiàng)目部署,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-02-02
JavaWeb 入門篇:創(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ì)步驟,本文分兩步通過實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-08-08
Idea打包springboot項(xiàng)目沒有.original文件解決方案
這篇文章主要介紹了Idea打包springboot項(xiàng)目沒有.original文件解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
Java用正則表達(dá)式實(shí)現(xiàn)${name}形式的字符串模板實(shí)例
這篇文章主要給大家介紹了Java如何用正則表達(dá)式實(shí)現(xiàn)${name}形式的字符串模板,文章給出詳細(xì)的實(shí)例代碼,對(duì)大家的理解和學(xué)習(xí)會(huì)很有幫助,有需要的朋友們下面來一起看看吧。2016-12-12

