【问题标题】:java sign public pgp key with bouncycastlejava用bouncycastle签署公共pgp密钥
【发布时间】:2015-02-18 18:57:45
【问题描述】:

我有一个疑问.. 据说我必须使用 bouncycastle api 签署一个 pgp 公钥。 现在:据我所知,用另一种方式签署密钥最终意味着向这个公钥添加一个“证书”。 因此没有任何其他方法,我在图书馆里盲目搜索。 到目前为止,我唯一的发现是 PGPSignatureGenerator 中的方法 generateCertification。但是这种方法会在主 PgpPublicKey 和另一个 PgpPublicKey 之间生成一个认证。这让我觉得很奇怪: 我假设为了信任另一个公钥,必须使用您自己的私有 pgp 密钥对其进行签名,就像在具有 CA 认证的常规 x.509 中一样...... 这是我在尝试从其他库中获取一些想法时看到的一些方法的假设:例如,didisoft 在密钥库上有一个类似的方法,您必须提供 PgpPrivatekey keyuid...

任何人有任何提示或一段代码建议? 提前致谢。

【问题讨论】:

  • 你为什么要签署一个公钥?通常,您要么使用您的私钥签署消息(或文件)(以证明您发送了它并且它没有被更改),要么使用收件人的公钥加密您要发送的消息(或文件)他(只有他的私钥才能解密。)
  • 嗯,也许是我没有完全清楚 pgp 概念...我的意思是,您想信任某人的密钥并说对您来说他们的密钥是“好的”,基本上类似于 CA 概念的等价物。 . 在这种情况下,您签署他们的公钥.. 身份的“信任”值由谁/多少个收件人签署了该 pgp 公钥.. 这就是为什么我认为您需要签署一个密钥。

标签: java bouncycastle pgp


【解决方案1】:

这可用于检查一个密钥是否将默认证书授予另一个密钥

  /**
 * Signs a public key
 *
 * @param publicKeyRing a public key ring containing the single public key to sign
 * @param id the id we are certifying against the public key
 * @param secretKey the signing key
 * @param secretKeyPassword the signing key password
 *
 * @return a public key ring with the signed public key
 */
public static PGPPublicKeyRing signPublicKey( PGPPublicKeyRing publicKeyRing, String id, PGPSecretKey secretKey,
                                              String secretKeyPassword ) throws PGPException
{
    try
    {
        PGPPublicKey oldKey = publicKeyRing.getPublicKey();

        PGPPrivateKey pgpPrivKey = secretKey.extractPrivateKey(
                new JcePBESecretKeyDecryptorBuilder().setProvider( provider )
                                                     .build( secretKeyPassword.toCharArray() ) );

        PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
                new JcaPGPContentSignerBuilder( secretKey.getPublicKey().getAlgorithm(), PGPUtil.SHA1 ) );

        signatureGenerator.init( PGPSignature.DEFAULT_CERTIFICATION, pgpPrivKey );

        PGPSignature signature = signatureGenerator.generateCertification( id, oldKey );

        PGPPublicKey newKey = PGPPublicKey.addCertification( oldKey, signature );

        PGPPublicKeyRing newPublicKeyRing = PGPPublicKeyRing.removePublicKey( publicKeyRing, oldKey );

        return PGPPublicKeyRing.insertPublicKey( newPublicKeyRing, newKey );
    }
    catch ( Exception e )
    {
        //throw custom  exception
        throw new PGPException( "Error signing public key", e );
    }
}


/**
 * Verifies that a public key is signed with another public key
 *
 * @param keyToVerify the public key to verify
 * @param id the id we are verifying against the public key
 * @param keyToVerifyWith the key to verify with
 *
 * @return true if verified, false otherwise
 */
public static boolean verifyPublicKey( PGPPublicKey keyToVerify, String id, PGPPublicKey keyToVerifyWith )
        throws PGPException
{
    try
    {
        Iterator<PGPSignature> signIterator = keyToVerify.getSignatures();
        while ( signIterator.hasNext() )
        {
            PGPSignature signature = signIterator.next();
            signature.init( new JcaPGPContentVerifierBuilderProvider().setProvider( provider ), keyToVerifyWith );
            if ( signature.verifyCertification( id.getBytes(), keyToVerify ) )
            {
                return true;
            }
        }
        return false;
    }
    catch ( Exception e )
    {
        //throw custom  exception
        throw new PGPException( "Error verifying public key", e );
    }
}

【讨论】:

    【解决方案2】:

    这是一个签署公钥的代码示例:

        PGPSecretKey mySecretKey;
        PGPPublicKey publicKeyToBeSigned; 
        PGPPrivateKey pgpPrivKey = mySecretKey
                .extractPrivateKey(new JcePBESecretKeyDecryptorBuilder()
                        .setProvider("BC").build("password for your private key"));
        PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
                new JcaPGPContentSignerBuilder(mySecretKey.getPublicKey()
                        .getAlgorithm(), PGPUtil.SHA512));
        signatureGenerator.init(PGPSignature.DIRECT_KEY, pgpPrivKey);
    
        PGPSignature signature = signatureGenerator.generateCertification(
                id, publicKeyToBeSigned);
    

    这段代码只是创建了签名。您需要将其添加到您的公钥中:

    PGPPublicKey.addCertification(publicKeyToBeSigned, signature);
    

    希望对你有帮助:)

    【讨论】:

    • 我很可能会在明天晚些时候检查这个。我已经推测出一个非常像这样的代码,唯一的区别是我没有先运行一个 init ..(我注意到对于其他操作也是强制性的,例如在验证吊销证书时)...我会告诉你的。
    • 现在...如果我想反其道而行之:我有已由 key1 签名的 key2 .. 我尝试了一些类似这些行的东西 [code] BcPGPContentVerifierBuilderProvider verifierBuilderProvider = new BcPGPContentVerifierBuilderProvider( ); signature.init(verifierBuilderProvider, signedKey); boolean resultOfMatching = signature.verifyCertification(authorKey, signedKey); [/code] 但不幸的是它不起作用..对此有什么建议吗?
    • 有趣的事情:你正在做与我完全相同的失败;)。我没有代码,但要验证签名,您需要两个公钥。签名者并签名!一个进入 init,另一个进入 verifyCertification。如果您无法弄清楚,我可以在今天或明天晚上发布一个示例。如果我的代码示例对您有用,如果您将我的答案标记为已接受,那就太好了。
    • 当然,我将您的答案标记为已接受!感谢您花时间回答我!第二点的代码示例将是最受欢迎的,但是你帮助了我很多..我真的对 pgp 的数量(或者我应该说缺乏..)样本以及 bouncycastle api 感到震惊。 . 我的意思是,就 X509 而言,bouncycasatle 很棒,但至于 pgp,考虑到一些主题的复杂性(信任网络等),我真的希望在代码中以 in- 的形式提供更多详细信息深度 javadoc 或文档形式...但它是一个免费的 api,所以就是这样..
    • 是的,我知道你的意思......必须处理同样的问题;)。这是一个简短的代码 sn-p 但它应该显示它是如何工作的。 pgpSignature.init(new JcaPGPContentVerifierBuilderProvider() .setProvider("BC"), publicKeyOfSigner); boolean result = pgpSignature.verifyCertification(signedPublicKey);
    猜你喜欢
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多