使用RSA生成公钥和私钥

服务器 0

1.jdk keytool

可以用keytool工具直接生成,需要openssl工具Binaries - OpenSSLWiki设置到环境变量里

@echo offcd ../outputIF exist auth.jks del auth.jksIF exist auth.key del auth.keykeytool -genkeypair -alias xxxx_key -keyalg RSA -keypass xxxxxx -keystore auth.jks -storepass xxxxxx -dname CN=xxxkeytool -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.keydel temp.keyecho Build OK!pause

 2.认证与鉴权使用

生成的authkey放到gateway下,生成的auth.jks放到auth认证服务下

网关结合鉴权,需要配置如下配置文件                

spring:    security:        oauth2:            resourceserver:                jwt:                    public-key-location: classpath:auth.key

认证服务配置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.工程项目直接生成

接口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;    /**     * 创建并下载auth.key和auth.jks     * @param days 创建证书的有效期 单位:天 不传默认90天     * @param response http返回值     * @throws IOException 异常     */    @GetMapping("/downloadAuthKeyZip")    public void downloadAuthKeyZip(@RequestParam(required = false) Integer days, HttpServletResponse response) throws IOException {        String dirPath = mkdir();        // 创建一个临时zip文件,用于存放要下载的多个文件        File zipFile = new File(dirPath + "/" + "authKeys.zip");        // 获取需要下载的多个文件,并将它们添加到zip文件中        List<File> filesToDownload = getFilesToDownload(dirPath, days);        addFilesToZip(filesToDownload, zipFile);        deleteFiles(filesToDownload);        //设置响应头信息        response.setContentType("application/zip");        response.setHeader("Content-Disposition", "attachment; filename=authKeys.zip");        // 将zip文件内容写入到HttpServletResponse输出流中,实现文件下载        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 时间     * @return 文件列表     */    private List<File> getFilesToDownload(String dirPath, Integer days) {        // 获取需要下载的多个文件        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 {        // 将多个文件压缩到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();            }        }    }    /**     * 创建文件夹     * @return 文件路径     */    private String mkdir() {        String dateString = getDateString();        // 文件夹路径        String dirPath = filePath + "/" + dateString;        File directory = new File(dirPath);        // 判断文件夹是否存在        if (!directory.exists()) {            // 创建文件夹及其父目录            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";    /**     * 随机生成密钥对     */    public static KeyPair genKeyPair() {        try {            // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");            // 初始化密钥对生成器,密钥大小为96-1024位            keyPairGen.initialize(2048, new SecureRandom());            // 生成一个密钥对,保存在keyPair中            return keyPairGen.generateKeyPair();        } catch (NoSuchAlgorithmException e) {            throw new RuntimeException(e);        }    }    /**     * 生成私钥     * @param keyPair 密钥对     * @param dirPath 文件列表     * @param days 时间     * @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";            // 有效期默认为 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并将其转换为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;    }    /**     * 随机生成密钥对     */    public static void genKeyPair() {        try {            // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");            // 初始化密钥对生成器,密钥大小为96-1024位            keyPairGen.initialize(2048, new SecureRandom());            // 生成一个密钥对,保存在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("随机生成的公钥为:" + publicKeyString);            System.out.println("随机生成的私钥为:" + privateKeyString);            publicKeyStr = publicKeyString;            privateKeyStr = privateKeyString;        } catch (NoSuchAlgorithmException e) {            throw new RuntimeException(e);        }    }}

5. 参考资料

www.php1.cn/detail/Java_ShiYong_key_81410199.html

也许您对下面的内容还感兴趣: