【问题标题】:Generate CSR from private key or Key Store从私钥或密钥库生成 CSR
【发布时间】:2016-07-02 12:08:31
【问题描述】:

如何从 Key Store 生成 CSR。

我已从密钥对生成 CSR。下面是我的代码。

public static PKCS10CertificationRequest generateCSR(KeyPair keyPair, String cn) throws IOException,
        OperatorCreationException {
    String principal = String.format(CN_PATTERN, cn);

    ContentSigner signer = new JCESigner (keyPair.getPrivate(),DEFAULT_SIGNATURE_ALGORITHM);

    PKCS10CertificationRequestBuilder csrBuilder = new JcaPKCS10CertificationRequestBuilder(
            new X500Name(principal), keyPair.getPublic());
    ExtensionsGenerator extensionsGenerator = new ExtensionsGenerator();
    extensionsGenerator.addExtension(Extension.basicConstraints, true, new BasicConstraints(
            true));
    csrBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest,
            extensionsGenerator.generate());
    Log.e("csr builder ","csr "+csrBuilder.toString());
    PKCS10CertificationRequest csr = csrBuilder.build(signer);

    return csr;
}

但我无法从 Keystore(私钥)生成 CSR。 有什么方法可以从 Keystore 生成密钥对?

请帮助我。在此先感谢。

【问题讨论】:

标签: android keystore private-key public-key csr


【解决方案1】:

您的代码与 Android KeyStore 兼容。您只需要将KeyPair 生成到Keystore

从 Android 4.3(API 级别 18)开始提供 KeyStore。版本略有不同

Android >=18

KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
                .setAlias(alias)
                .setSubject(new X500Principal("CN=" + alias + ", O=Android Authority"))
                .setSerialNumber(BigInteger.ONE)
                .setStartDate(start.getTime())
                .setEndDate(end.getTime())
                .build();

KeyPairGenerator kpg = KeyPairGenerator.getInstance(
                KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");

kpg.initialize(spec);
KeyPair keyPair = kpg.generateKeyPair();

Android >=23

KeyPairGenerator kpg = KeyPairGenerator.getInstance(
                KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");


kpg.initialize(new KeyGenParameterSpec.Builder(
                alias,
                KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
                .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
                .build());

KeyPair keyPair = kpg.generateKeyPair();

【讨论】:

  • 嗨 pedrofb,问题是我只有私钥,是否可以仅从私钥而不是密钥对生成 CSR。
  • 不,这是不可能的。 CSR 必须包含稍后嵌入在您的 CA 构建和签名的 X509Certificate 中的公钥。但是,我不明白,私钥与公钥相关联,所以如果你有私钥,你也应该有公钥
  • 实际上 pedrofb 我正在智能卡中生成密钥对。但由于安全原因,我无法获得密钥对值。我只看到生成密钥的密钥库(KeyStore store = null;store = GPKIKeyStore.getInstance(); store.load(null /* stream used /, null / password used */) ; 别名 = store.aliases();) 。然后我生成 Key(Key key = store.getKey(alias, null);) 所以这只包含私钥。
  • 有什么方法可以从密钥库中获取密钥对值?
  • KeyPair 不是,但是java.security.KeyStore 有你需要的私钥和公钥。使用PublicKey publicKey = store.getCertificate(alias).getPublicKey()
【解决方案2】:

我猜你说的是java.security.KeyStore。这种抽象要求每个存储的PrivateKey 都有一个对应的Certificate 实例链(一个或多个证书)。这意味着您应该能够从KeyStore 的私钥条目创建KeyPair。例如,如果私钥存储在“test”下:

String alias = "test";
KeyStore keyStore = KeyStore.getInstance(...);
keyStore.load(...;);
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, null);
PublicKey publicKey = keyStore.getCertificate(alias).getPublicKey();
KeyPair keyPair = new KeyPair(publicKey, privateKey);
generateCsr(keyPair, ...);

【讨论】: