1.jdk keytool
可以用keytool工具直接生成,需要openssl工具Binaries - OpenSSLWiki設(shè)置到環(huán)境變量里
@echo off
cd ../output
IF exist auth.jks del auth.jks
IF exist auth.key del auth.key
keytool -genkeypair -alias xxxx_key -keyalg RSA -keypass xxxxxx -keystore auth.jks -storepass xxxxxx -dname CN=xxx
keytool -list -rfc --keystore auth.jks -storepass xxxxxx | openssl x509 -inform pem -pubkey > temp.key
(@FOR /f "tokens=1* delims=:" %%a IN ('findstr /n "^" "temp.key"') DO @IF %%a leq 9 ECHO(%%b) > auth.key
del temp.key
echo Build OK!
pause
?2.認(rèn)證與鑒權(quán)使用
生成的authkey放到gateway下,生成的auth.jks放到auth認(rèn)證服務(wù)下
網(wǎng)關(guān)結(jié)合鑒權(quán),需要配置如下配置文件????????????????
spring:
security:
oauth2:
resourceserver:
jwt:
public-key-location: classpath:auth.key
認(rèn)證服務(wù)配置Bean
@Bean
public JWKSource<SecurityContext> jwkSource() throws Exception {
KeyStore keyStore = KeyStore.getInstance("JKS");
// 取得JKS文件
Resource resource = new ClassPathResource(DEFAULT_KEY_STORE_FILE);
if (!resource.exists()) {
resource = new FileSystemResource(DEFAULT_KEY_STORE_FILE);
}
try (InputStream inputStream = resource.getInputStream()) {
keyStore.load(inputStream, DEFAULT_KEY_STORE_PASSWORD.toCharArray());
RSAPublicKey publicKey = (RSAPublicKey) keyStore.getCertificate(DEFAULT_KEY_ALIAS).getPublicKey();
RSAPrivateKey privateKey = (RSAPrivateKey) keyStore.getKey(DEFAULT_KEY_ALIAS, DEFAULT_KEY_PASSWORD.toCharArray());
RSAKey rsaKey = new RSAKey.Builder(publicKey)
.privateKey(privateKey)
.keyStore(keyStore)
.build();
JWKSet jwkSet = new JWKSet(rsaKey);
return new ImmutableJWKSet<>(jwkSet);
}
}
3.工程項(xiàng)目直接生成
接口AuthToolController
package xxx.authtool.controller;
import xxx.authtool.util.RsaUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.security.KeyPair;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@RestController
@RequestMapping("/generate")
public class AuthToolController {
@Value("${file-path:}")
private String filePath;
/**
* 創(chuàng)建并下載auth.key和auth.jks
* @param days 創(chuàng)建證書的有效期 單位:天 不傳默認(rèn)90天
* @param response http返回值
* @throws IOException 異常
*/
@GetMapping("/downloadAuthKeyZip")
public void downloadAuthKeyZip(@RequestParam(required = false) Integer days, HttpServletResponse response) throws IOException {
String dirPath = mkdir();
// 創(chuàng)建一個(gè)臨時(shí)zip文件,用于存放要下載的多個(gè)文件
File zipFile = new File(dirPath + "/" + "authKeys.zip");
// 獲取需要下載的多個(gè)文件,并將它們添加到zip文件中
List<File> filesToDownload = getFilesToDownload(dirPath, days);
addFilesToZip(filesToDownload, zipFile);
deleteFiles(filesToDownload);
//設(shè)置響應(yīng)頭信息
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=authKeys.zip");
// 將zip文件內(nèi)容寫入到HttpServletResponse輸出流中,實(shí)現(xiàn)文件下載
try (InputStream inputStream = Files.newInputStream(zipFile.toPath());
OutputStream outputStream = response.getOutputStream()) {
byte[] buffer = new byte[4096];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
outputStream.flush();
}
}
}
/**
* 刪除文件
* @param filesToDownload 文件列表
*/
private void deleteFiles(List<File> filesToDownload) {
for (File file : filesToDownload) {
file.delete();
}
}
/**
* 獲取文件列表
* @param dirPath 文件路徑
* @param days 時(shí)間
* @return 文件列表
*/
private List<File> getFilesToDownload(String dirPath, Integer days) {
// 獲取需要下載的多個(gè)文件
List<File> files = new ArrayList<>();
KeyPair keyPair = RsaUtil.genKeyPair();
File publicFile = RsaUtil.genPublicFile(keyPair, dirPath);
File privateFile = RsaUtil.genPrivateFile(keyPair, dirPath, days);
files.add(publicFile);
files.add(privateFile);
return files;
}
/**
* 壓縮文件
* @param filesToDownload 文件列表
* @param zipFile 壓縮文件
* @throws IOException 異常
*/
private void addFilesToZip(List<File> filesToDownload, File zipFile) throws IOException {
// 將多個(gè)文件壓縮到zip文件中
try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(zipFile.toPath()))) {
for (File file : filesToDownload) {
zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
try (FileInputStream inputStream = new FileInputStream(file)) {
byte[] buf = new byte[1024];
int len;
while ((len = inputStream.read(buf)) > 0) {
zipOutputStream.write(buf, 0, len);
}
}
zipOutputStream.closeEntry();
}
}
}
/**
* 創(chuàng)建文件夾
* @return 文件路徑
*/
private String mkdir() {
String dateString = getDateString();
// 文件夾路徑
String dirPath = filePath + "/" + dateString;
File directory = new File(dirPath);
// 判斷文件夾是否存在
if (!directory.exists()) {
// 創(chuàng)建文件夾及其父目錄
directory.mkdirs();
}
return dirPath;
}
/**
* 獲取日期字符串
* @return 日期字符串
*/
private String getDateString() {
Date currentDate = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
return dateFormat.format(currentDate);
}
}
RSAUtil
package xxx.authtool.util;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import sun.security.x509.X500Name;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Date;
/**
* RSA工具類
*
* @author xxx
*/
public final class RsaUtil {
public static final String DEFAULT_KEY_STORE_FILE = "auth.jks";
public static final String DEFAULT_KEY_FILE = "auth.key";
public static final String DEFAULT_KEY_STORE_PASSWORD = "xxxxxx";
public static final String DEFAULT_KEY_ALIAS = "xxxx";
public static final String DEFAULT_KEY_PASSWORD = "xxxxxx";
/**
* 隨機(jī)生成密鑰對
*/
public static KeyPair genKeyPair() {
try {
// KeyPairGenerator類用于生成公鑰和私鑰對,基于RSA算法生成對象
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 初始化密鑰對生成器,密鑰大小為96-1024位
keyPairGen.initialize(2048, new SecureRandom());
// 生成一個(gè)密鑰對,保存在keyPair中
return keyPairGen.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
/**
* 生成私鑰
* @param keyPair 密鑰對
* @param dirPath 文件列表
* @param days 時(shí)間
* @return 秘鑰文件
*/
public static File genPrivateFile(KeyPair keyPair, String dirPath, Integer days) {
File file = new File(dirPath + "/" + DEFAULT_KEY_STORE_FILE);
try (FileOutputStream fos = new FileOutputStream(file)) {
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null, DEFAULT_KEY_PASSWORD.toCharArray());
// 得到私鑰
PrivateKey privateKey = keyPair.getPrivate();
// 為以下對象生成 2048 位RSA密鑰對和自簽名證書 (SHA256withRSA) (有效期為 90 天):
String dn = "CN=xxxx";
// 有效期默認(rèn)為 90 天
int day = 90;
if (days != null) {
day = days;
}
X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
new X500Name(dn).asX500Principal(),
BigInteger.valueOf(System.currentTimeMillis()),
new Date(System.currentTimeMillis()),
new Date(System.currentTimeMillis() + day * 24 * 60 * 60 * 1000L),
new X500Name(dn).asX500Principal(),
keyPair.getPublic());
ContentSigner signer =
new JcaContentSignerBuilder("SHA256withRSA").setProvider(new BouncyCastleProvider()).build(keyPair.getPrivate());
Certificate cert = new JcaX509CertificateConverter().setProvider(new BouncyCastleProvider()).getCertificate(builder.build(signer));
keyStore.setKeyEntry(DEFAULT_KEY_ALIAS, privateKey, DEFAULT_KEY_PASSWORD.toCharArray(), new Certificate[]{cert});
keyStore.store(fos, DEFAULT_KEY_STORE_PASSWORD.toCharArray());
return file;
} catch (KeyStoreException | IOException | CertificateException | NoSuchAlgorithmException |
OperatorCreationException e) {
throw new RuntimeException(e);
}
}
/**
* 生成公鑰文件
* @param keyPair 密鑰對
* @param dirPath 文件列表
* @return 公鑰文件
*/
public static File genPublicFile(KeyPair keyPair, String dirPath) {
try (StringWriter sw = new StringWriter()) {
// 得到公鑰
PublicKey publicKey = keyPair.getPublic();
// 獲取PublicKey并將其轉(zhuǎn)換為PEM格式的字符串
try (JcaPEMWriter pemWriter = new JcaPEMWriter(sw)) {
pemWriter.writeObject(publicKey);
} catch (IOException e) {
throw new RuntimeException(e);
}
File file = new File(dirPath + "/" + DEFAULT_KEY_FILE);
try (FileWriter fw = new FileWriter(file.getAbsoluteFile(), true);
BufferedWriter bw = new BufferedWriter(fw)
) {
bw.write(sw.toString());
} catch (IOException e) {
throw new RuntimeException(e);
}
return file;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
依賴
implementation 'org.bouncycastle:bcprov-jdk15on:1.69'
implementation 'org.bouncycastle:bcpkix-jdk15on:1.69'
訪問localhost:6080/generate/downloadAuthKeyZip可獲取90天許可的證書
4.RSA工具類
package xxx.socket.stomp.config;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.springframework.util.Assert;
/**
* RSA工具類
*
*/
public class RsaUtils {
private static String publicKeyStr = "";
private static String privateKeyStr = "";
public static void main(String[] args) {
genKeyPair();
String password = "xxxx";
String rawPassword = encrypt(password);
String password2 = decrypt(rawPassword);
Assert.isTrue(password.equals(password2), "Error");
}
public static String encrypt(String password) {
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyStr));
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] passwordBytes = cipher.doFinal(password.getBytes(StandardCharsets.UTF_8));
String result = new String(Base64.getEncoder().encode(passwordBytes), StandardCharsets.UTF_8);
System.out.println("Encrypt Password: " + result);
return result;
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
System.out.println("Algorithm Error\n" + e);
} catch (NoSuchPaddingException | InvalidKeyException e) {
System.out.println("Cipher Error\n" + e);
} catch (IllegalBlockSizeException | BadPaddingException e) {
System.out.println("Password Error\n" + e);
}
return null;
}
public static String decrypt(String password) {
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyStr));
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] passwordBytes = cipher.doFinal(Base64.getDecoder().decode(password.getBytes(StandardCharsets.UTF_8)));
String result = new String(passwordBytes, StandardCharsets.UTF_8);
System.out.println("Decrypt Password: " + result);
return result;
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
System.out.println("Algorithm Error\n" + e);
} catch (NoSuchPaddingException | InvalidKeyException e) {
System.out.println("Cipher Error\n" + e);
} catch (IllegalBlockSizeException | BadPaddingException e) {
System.out.println("Password Error\n" + e);
}
return null;
}
/**
* 隨機(jī)生成密鑰對
*/
public static void genKeyPair() {
try {
// KeyPairGenerator類用于生成公鑰和私鑰對,基于RSA算法生成對象
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 初始化密鑰對生成器,密鑰大小為96-1024位
keyPairGen.initialize(2048, new SecureRandom());
// 生成一個(gè)密鑰對,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
// 得到私鑰
PrivateKey privateKey = keyPair.getPrivate();
// 得到公鑰
PublicKey publicKey = keyPair.getPublic();
String publicKeyString = new String(Base64.getEncoder().encode(publicKey.getEncoded()));
// 得到私鑰字符串
String privateKeyString = new String(Base64.getEncoder().encode((privateKey.getEncoded())));
System.out.println("隨機(jī)生成的公鑰為:" + publicKeyString);
System.out.println("隨機(jī)生成的私鑰為:" + privateKeyString);
publicKeyStr = publicKeyString;
privateKeyStr = privateKeyString;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}
5. 參考資料文章來源:http://www.zghlxwxcb.cn/news/detail-524529.html
www.php1.cn/detail/Java_ShiYong_key_81410199.html文章來源地址http://www.zghlxwxcb.cn/news/detail-524529.html
到了這里,關(guān)于使用RSA生成公鑰和私鑰的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!