Java 實(shí)現(xiàn)RSA非對(duì)稱(chēng)加密算法
公鑰與私鑰
公鑰與私鑰是成對(duì)的,一般的,我們認(rèn)為的是公鑰加密、私鑰解密、私鑰簽名、公鑰驗(yàn)證,有人說(shuō)成私鑰加密,公鑰解密時(shí)不對(duì)的。
公鑰與私鑰的生成有多種方式,可以通過(guò)程序生成(下文具體實(shí)現(xiàn)),可以通過(guò)openssl工具:
# 生成一個(gè)私鑰,推薦使用1024位的秘鑰,秘鑰以pem格式保存到-out參數(shù)指定的文件中,采用PKCS1格式
openssl genrsa -out rsa.pem 1024
# 生成與私鑰對(duì)應(yīng)的公鑰,生成的是Subject Public Key,一般配合PKCS8格式私鑰使用
openssl rsa -in rsa.pem -pubout -out rsa.pub
RSA生成公鑰與私鑰一般有兩種格式:PKCS1和PKCS8,上面的命令生成的秘鑰是PKCS1格式的,而公鑰是Subject Public Key,一般配合PKCS8格式私鑰使用,所以就可能會(huì)涉及到PKCS1和PKCS8之間的轉(zhuǎn)換:
# PKCS1格式私鑰轉(zhuǎn)換為PKCS8格式私鑰,私鑰直接輸出到-out參數(shù)指定的文件中
openssl pkcs8 -topk8 -inform PEM -in rsa.pem -outform pem -nocrypt -out rsa_pkcs8.pem
# PKCS8格式私鑰轉(zhuǎn)換為PKCS1格式私鑰,私鑰直接輸出到-out參數(shù)指定的文件中
openssl rsa -in rsa_pkcs8.pem -out rsa_pkcs1.pem
# PKCS1格式公鑰轉(zhuǎn)換為PKCS8格式公鑰,轉(zhuǎn)換后的內(nèi)容直接輸出
openssl rsa -pubin -in rsa.pub -RSAPublicKey_out
# PKCS8格式公鑰轉(zhuǎn)換為PKCS1格式公鑰,轉(zhuǎn)換后的內(nèi)容直接輸出
openssl rsa -RSAPublicKey_in -pubout -in rsa.pub
現(xiàn)實(shí)中,我們往往從pem、crt、pfx文件獲取公私和私鑰,crt、pfx的制作可以參考:簡(jiǎn)單的制作ssl證書(shū),并在nginx和IIS中使用,或者使用現(xiàn)成的:https://pan.baidu.com/s/1MJ5YmuZiLBnf-DfNR_6D7A (提取碼:c6tj),密碼都是:123456
Java實(shí)現(xiàn)
為簡(jiǎn)化說(shuō)明介紹,這里我直接封裝了一個(gè)工具類(lèi),因?yàn)橐獜膒em、crt、pfx文件獲取公私和私鑰,因此引用了一個(gè)第三方包:BouncyCastle,可以直接在pom.xml中添加依賴(lài):
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.68</version>
</dependency>
或者去mvn上下載:跳轉(zhuǎn)
簡(jiǎn)單封裝的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());
}
/**
* 隨機(jī)生成密鑰對(duì)
*
* @param usePKCS8
* 是否采用PKCS8填充模式
*/
public static Object[] generateRsaKey(boolean usePKCS8) throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
// 初始化
keyPairGen.initialize(1024, new SecureRandom());
// 生成一個(gè)密鑰對(duì),保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私鑰
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公鑰
// 這兩個(gè)公私鑰是PKCS8格式的
byte[] publicKeyBytes = publicKey.getEncoded();
byte[] privateKeyBytes = privateKey.getEncoded();
if (!usePKCS8) {
// 將PSCK8格式公私鑰轉(zhuǎn)換為PKCS1格式
publicKeyBytes = pkcs8ToPkcs1(false, publicKeyBytes);
privateKeyBytes = pkcs8ToPkcs1(true, privateKeyBytes);
}
return new Object[] { publicKeyBytes, privateKeyBytes };
}
/**
* 從Pem文件讀取密鑰對(duì)
*
* @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
* 字節(jié)
* @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文件讀取秘鑰對(duì)(pkcs8)
*
* @param pfxFileName
* pfx文件
* @return 秘鑰對(duì)
*/
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轉(zhuǎn)Pkcs1
*
* @param isPrivateKey
* 是否是私鑰轉(zhuǎn)換
* @param buffer
* Pkcs1秘鑰
* @return Pkcs8秘鑰
* @throws Exception
* 加密過(guò)程中的異常信息
*/
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轉(zhuǎn)Pkcs8
*
* @param isPrivateKey
* 是否是私鑰轉(zhuǎn)換
* @param buffer
* Pkcs1秘鑰
* @return Pkcs8秘鑰
* @throws Exception
* 加密過(guò)程中的異常信息
*/
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
* 加密過(guò)程中的異常信息
*/
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
* 解密過(guò)程中的異常信息
*/
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
* 加密過(guò)程中的異常信息
*/
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
* 解密過(guò)程中的異常信息
*/
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
* 簽名過(guò)程中的異常信息
*/
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簽名驗(yàn)證
*
* @param value
* 加密字符串
* @param publicKey
* 公鑰
* @param halg
* 加密算法,如MD5, SHA1, SHA256, SHA384, SHA512等
* @return 簽名合法則返回true,否則返回false
* @throws Exception
* 驗(yàn)證過(guò)程中的異常信息
*/
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格式的公私秘鑰,否則乘車(chē)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文件中,當(dāng)然也可以從pem文件中讀取了:
// 從Pem文件讀取公私鑰,filePath是文件目錄
byte[] publicKey = RsaUtil.readFromPem(filePath + "rsa.pub");
byte[] privateKey = RsaUtil.readFromPem(filePath + "rsa.pem");
還可以從crt證書(shū)中讀取公鑰,而crt文件不包含私鑰,因此需要單獨(dú)獲取私鑰:
// 從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];
有時(shí)候我們還可能需要進(jìn)行秘鑰的轉(zhuǎn)換:
// Pkcs8格式公鑰轉(zhuǎn)換為Pkcs1格式公鑰
publicKey = RsaUtil.pkcs8ToPkcs1(false, publicKey);
// Pkcs8格式私鑰轉(zhuǎn)換為Pkcs1格式私鑰
privateKey = RsaUtil.pkcs8ToPkcs1(true, privateKey);
// Pkcs1格式公鑰轉(zhuǎn)換為Pkcs8格式公鑰
publicKey = RsaUtil.pkcs1ToPkcs8(false, publicKey);
// Pkcs1格式私鑰轉(zhuǎn)換為Pkcs8格式私鑰
privateKey = RsaUtil.pkcs1ToPkcs8(true, privateKey);
有了公鑰和私鑰,接下就就能實(shí)現(xiàn)加密、解密、簽名、驗(yàn)證簽名等操作了:
RSAPublicKey rsaPublicKey = RsaUtil.generatePublicKey(usePKCS8, publicKey);
RSAPrivateKey rsaPrivateKey = RsaUtil.generatePrivateKey(usePKCS8, privateKey);
String encryptText = RsaUtil.rsaEncrypt(text, rsaPublicKey);
System.out.printf("【%s】經(jīng)過(guò)【RSA】加密后:%s\n", text, encryptText);
String decryptText = RsaUtil.rsaDecrypt(encryptText, rsaPrivateKey);
System.out.printf("【%s】經(jīng)過(guò)【RSA】解密后:%s\n", encryptText, decryptText);
String signature = RsaUtil.sign(text, rsaPrivateKey, "MD5");
System.out.printf("【%s】經(jīng)過(guò)【RSA】簽名后:%s\n", text, signature);
boolean result = RsaUtil.verify(text, rsaPublicKey, signature, "MD5");
System.out.printf("【%s】的簽名【%s】經(jīng)過(guò)【RSA】驗(yàn)證后結(jié)果是:" + 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格式的公私秘鑰,否則乘車(chē)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格式的公私秘鑰,否則乘車(chē)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格式公鑰轉(zhuǎn)換為Pkcs1格式公鑰
publicKey = RsaUtil.pkcs8ToPkcs1(false, publicKey);
// Pkcs8格式私鑰轉(zhuǎn)換為Pkcs1格式私鑰
privateKey = RsaUtil.pkcs8ToPkcs1(true, privateKey);
// Pkcs1格式公鑰轉(zhuǎn)換為Pkcs8格式公鑰
publicKey = RsaUtil.pkcs1ToPkcs8(false, publicKey);
// Pkcs1格式私鑰轉(zhuǎn)換為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】經(jīng)過(guò)【RSA】加密后:%s\n", text, encryptText);
String decryptText = RsaUtil.rsaDecrypt(encryptText, rsaPrivateKey);
System.out.printf("【%s】經(jīng)過(guò)【RSA】解密后:%s\n", encryptText, decryptText);
String signature = RsaUtil.sign(text, rsaPrivateKey, "MD5");
System.out.printf("【%s】經(jīng)過(guò)【RSA】簽名后:%s\n", text, signature);
boolean result = RsaUtil.verify(text, rsaPublicKey, signature, "MD5");
System.out.printf("【%s】的簽名【%s】經(jīng)過(guò)【RSA】驗(yàn)證后結(jié)果是:" + result, text, signature);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
以上就是Java 實(shí)現(xiàn)RSA非對(duì)稱(chēng)加密算法的詳細(xì)內(nèi)容,更多關(guān)于Java RSA非對(duì)稱(chēng)加密算法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- JAVA加密算法- 非對(duì)稱(chēng)加密算法(DH,RSA)的詳細(xì)介紹
- Java編程實(shí)現(xiàn)非對(duì)稱(chēng)加密的方法詳解
- java 非對(duì)稱(chēng)加密算法RSA實(shí)現(xiàn)詳解
- java 非對(duì)稱(chēng)加密算法DH實(shí)現(xiàn)詳解
- 解決JAVA非對(duì)稱(chēng)加密不同系統(tǒng)加密結(jié)果不一致的問(wèn)題
- Java 實(shí)現(xiàn)常見(jiàn)的非對(duì)稱(chēng)加密算法
- 教你用Java實(shí)現(xiàn)RSA非對(duì)稱(chēng)加密算法
- Java對(duì)稱(chēng)與非對(duì)稱(chēng)加密算法原理詳細(xì)講解
- 淺析Java中對(duì)稱(chēng)與非對(duì)稱(chēng)加密算法原理與使用
- Java實(shí)現(xiàn)非對(duì)稱(chēng)加密的三種方法
相關(guān)文章
Spring Security方法鑒權(quán)的實(shí)現(xiàn)
在Spring Security中,主要有兩種鑒權(quán)方式,一個(gè)是基于web請(qǐng)求的鑒權(quán),一個(gè)是基于方法的鑒權(quán),本文就來(lái)介紹一下Spring Security方法鑒權(quán)的實(shí)現(xiàn),感興趣的可以了解一下2023-12-12
spring boot配置多個(gè)請(qǐng)求服務(wù)代理的完整步驟
這篇文章主要給大家介紹了關(guān)于spring boot配置多個(gè)請(qǐng)求服務(wù)代理的完整步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
SpringBoot中OKHttp和壓縮文件的使用實(shí)戰(zhàn)教程
本文介紹了如何在SpringBoot中使用OKHttp發(fā)起請(qǐng)求和處理壓縮文件,包括文件的存儲(chǔ)配置、實(shí)體類(lèi)、配置類(lèi)和初始化類(lèi)的設(shè)置,以及如何通過(guò)主程序和測(cè)試類(lèi)進(jìn)行實(shí)際操作,最后提供了必要的依賴(lài)添加方法,以確保功能的實(shí)現(xiàn)2024-10-10
Java Mybatis中的 ${ } 和 #{ }的區(qū)別使用詳解
這篇文章主要介紹了Mybatis中的 ${ } 和 #{ }的區(qū)別使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
GraalVM系列Native?Image?Basics靜態(tài)分析
這篇文章主要為大家介紹了GraalVM系列Native?Image?Basics靜態(tài)分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
SpringBoot 注解事務(wù)聲明式事務(wù)的方式
springboot使用上述注解的幾種方式開(kāi)啟事物,可以達(dá)到和xml中聲明的同樣效果,但是卻告別了xml,使你的代碼遠(yuǎn)離配置文件。今天就扒一扒springboot中事務(wù)使用注解的玩法,感興趣的朋友一起看看吧2017-09-09
Java利用剪貼板實(shí)現(xiàn)交換程序間數(shù)據(jù)的方法
這篇文章主要介紹了Java利用剪貼板實(shí)現(xiàn)交換程序間數(shù)據(jù)的方法,需要的朋友可以參考下2014-07-07

