从 KeyStore 中获取 PublicKey 和 PrivateKey

KeyStore(译:密钥存储库) 代表用于加密密钥和证书的存储设施。

KeyStore 管理不同类型的 entry(译:条目)。每种类型的 entry 都实现了 KeyStore.Entry 接口。提供了三个基本的 KeyStore.Entry 实现:

  • KeyStore.PrivateKeyEntry

  • 这种类型的 Entry 持有一个加密PrivateKey,可以选择以受保护的格式存储,以防止未经授权的访问。它还伴随着对应的公钥的证书链。私钥和证书链由给定实体用于自我身份验证。这种身份验证的应用程序包括软件分发组织,它们将JAR文件作为发布和/或许可软件的一部分进行签名。

  • KeyStore.SecretKeyEntry

  • 这种类型的 Entry 持有一个加密的SecretKey,它可以选择以受保护的格式存储,以防止未经授权的访问。

  • KeyStore.TrustedCertificateEntry

  • 这种类型的Entry包含一个属于另一方的公钥证书。它被称为受信任的证书,因为密钥存储库所有者信任证书中的公钥确实属于证书的主体(所有者)标识的身份。这种类型的Entry可用于对其他方进行身份验证。

KeyStore 中的每个 Entry 都由一个“alias”字符串标识。对于私钥及其关联的证书链,这些字符串区分实体对自身进行身份验证的不同方式。例如,实体可以使用不同的证书颁发机构或使用不同的公钥算法对自己进行身份验证。

这里没有指定密钥存储库是否持久,以及密钥存储库使用的机制(如果它是持久的)。

请求KeyStore对象的典型方法包括依赖默认类型和提供特定的KeyStore类型:

  • 依赖默认类型:

  • KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
  • 提供特定的密钥存储库类型:

  • KeyStore ks = KeyStore.getInstance("JKS");

在访问密钥存储库之前,必须先加载它。

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());

// get user password and file input stream
char[] password = getPassword();

try (FileInputStream fis = new FileInputStream("keyStoreName")) {
  ks.load(fis, password);
}

为了用上面的方法创建一个空的 KeyStore(密钥存储库),可以传递null作为InputStream参数。

一旦加载了密钥存储库,就可以从密钥存储库中读取现有条目,或者将新条目写入密钥存储库:

KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(password);

// get my private key
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry("privateKeyAlias", protParam);
PrivateKey myPrivateKey = pkEntry.getPrivateKey();

// save my secret key
javax.crypto.SecretKey mySecretKey;
KeyStore.SecretKeyEntry skEntry = new KeyStore.SecretKeyEntry(mySecretKey);
ks.setEntry("secretKeyAlias", skEntry, protParam);

// store away the keystore
try (FileOutputStream fos = new FileOutputStream("newKeyStoreName")) {
   ks.store(fos, password);
}

注意,尽管可以使用相同的密码加载keystore、保护private key entry、保护secret key entry和存储keystore(如上面的示例代码所示),但也可以使用不同的密码或其他保护参数。

更多请参见 java.security.KeyStore

下面,演示一下

首先,生成一个密钥文件

keytool -genkeypair -alias soas -keypass 123456 -keyalg RSA -storepass 123456 -keysize 1024 -validity 3650 -keystore F:/soas.jks

加载keystore

//  创建KeyStore
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
KeyStore ks2 = KeyStore.getInstance("JKS");

//  加载KeyStore
InputStream is = new ClassPathResource("keyStoreName").getInputStream();
ks.load(is, "storepass".toCharArray());

FileInputStream fis = new FileInputStream("keyStoreName");
ks.load(is, "storepass".toCharArray());

//  获取PrivateKey/PublicKey(方式一)
KeyStore.ProtectionParameter protectionParameter = new KeyStore.PasswordProtection("keypass".toCharArray());
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry("alias", protectionParameter);

PrivateKey myPrivateKey = privateKeyEntry.getPrivateKey();
PublicKey myPublicKey = privateKeyEntry.getCertificate().getPublicKey();

System.out.println(myPrivateKey);
System.out.println(myPublicKey);

//  获取PrivateKey/PublicKey(方式二)
PrivateKey myPrivateKey2 = (PrivateKey) ks.getKey("alias", "keypass".toCharArray());
PublicKey myPublicKey2 = ks.getCertificate("alias").getPublicKey();

System.out.println(myPrivateKey2);
System.out.println(myPublicKey2);

补充:生成token

package com.soa.supervision.portal.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.List;

/**
 * @Author ChengJianSheng
 * @Date 2022/5/14
 */
@Slf4j
public class RSAUtils {

    private static final Logger logger = LoggerFactory.getLogger(RSAUtils.class);
    private static final String CLAIM = "user";

    public static RSAPublicKey rsaPublicKey;
    private static RSAPrivateKey rsaPrivateKey;

    static {
        try {
//            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
//            keyPairGenerator.initialize(2048);
//            KeyPair keyPair = keyPairGenerator.generateKeyPair();
//            publicKey = (RSAPublicKey) keyPair.getPublic();
//            privateKey = (RSAPrivateKey) keyPair.getPrivate();


            KeyStore keyStore = KeyStore.getInstance("JKS");
            InputStream is = new ClassPathResource("soas.jks").getInputStream();
            keyStore.load(is, "123456".toCharArray());
            is.close();
            PrivateKey privateKey = (PrivateKey) keyStore.getKey("soas", "123456".toCharArray());
            PublicKey publicKey = keyStore.getCertificate("soas").getPublicKey();

            rsaPrivateKey = (RSAPrivateKey) privateKey;
            rsaPublicKey = (RSAPublicKey)publicKey;

        } catch (NoSuchAlgorithmException | KeyStoreException | IOException | CertificateException | UnrecoverableKeyException e) {
            logger.error("生成密钥对失败!原因: {}", e.getMessage(), e);
        }
    }

    public static String createToken(String name, Integer userId, List authorities) {
        Algorithm algorithm = Algorithm.RSA256(rsaPublicKey, rsaPrivateKey);
        String token = JWT.create()
                .withClaim(CLAIM, name)
                .withClaim("userId", userId)
                .withClaim("authorities", authorities)
                .sign(algorithm);
        return token;
    }

    public static Claim parseToken(String token) {
        Algorithm algorithm = Algorithm.RSA256(rsaPublicKey, rsaPrivateKey);
        JWTVerifier verifier = JWT.require(algorithm).build();
        DecodedJWT jwt = verifier.verify(token);
        return jwt.getClaim(CLAIM);
    }
}
posted @ 2022-06-08 17:33  废物大师兄  阅读(858)  评论(0编辑  收藏  举报