【问题标题】:Bouncycastle openpgpg: How to create a PGP keypair with two user ids?Bouncycastle openpgpg:如何创建具有两个用户 ID 的 PGP 密钥对?
【发布时间】:2013-10-04 18:03:32
【问题描述】:

使用命令行 gnupg 我可以为“John Doe ”创建一个带有 RSA 密钥的密钥环。我还可以使用--edit-keyadduid 添加另一个具有uid "Jane Doe " 的用户。生成的 secring.gpg 如下所示:

$ gpg -vv secring.gpg
:secret key packet:
        version 4, algo 1, created 1380898817, expires 0
        skey[0]: [2048 bits]
        skey[1]: [17 bits]
        iter+salt S2K, algo: 9, SHA1 protection, hash: 2, salt: 3825c4409323d7b0
        protect count: 65536 (96)
        protect IV:  ac f9 8d 4a b7 3a 5d 7c b2 3c 28 ff 82 6d 4c ef
        encrypted stuff follows
:user ID packet: "John Doe <john@doe.com>"
:signature packet: algo 1, keyid 9991E2282A9906C7
        version 4, created 1380898818, md5len 0, sigclass 0x13
        digest algo 2, begin of digest bd 01
        hashed subpkt 2 len 4 (sig created 2013-10-04)
        hashed subpkt 27 len 1 (key flags: 03)
        hashed subpkt 11 len 5 (pref-sym-algos: 9 8 7 3 2)
        hashed subpkt 21 len 5 (pref-hash-algos: 8 2 9 10 11)
        hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
        hashed subpkt 30 len 1 (features: 01)
        subpkt 16 len 8 (issuer key ID 9991E2282A9906C7)
        data: [2045 bits]
:trust packet: flag=00 sigcache=00
:user ID packet: "Jane Doe <jane@doe.com>"
:signature packet: algo 1, keyid 9991E2282A9906C7
        version 4, created 1380899570, md5len 0, sigclass 0x13
        digest algo 2, begin of digest 2f 50
        hashed subpkt 2 len 4 (sig created 2013-10-04)
        hashed subpkt 27 len 1 (key flags: 03)
        hashed subpkt 11 len 5 (pref-sym-algos: 9 8 7 3 2)
        hashed subpkt 21 len 5 (pref-hash-algos: 8 2 9 10 11)
        hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
        hashed subpkt 30 len 1 (features: 01)
        hashed subpkt 23 len 1 (key server preferences: 80)
        subpkt 16 len 8 (issuer key ID 9991E2282A9906C7)
        data: [2047 bits]
:trust packet: flag=00 sigcache=00
sec  2048R/2A9906C7 2013-10-04 John Doe <john@doe.com>
sig        2A9906C7 2013-10-04   [selfsig]
uid                            Jane Doe <jane@doe.com>
sig        2A9906C7 2013-10-04   [selfsig]

我想使用 Bouncycastle 在 Java 中创建相同的内容,从 java.security.KeyPair 开始,即使用如下签名:

public void createKeyRing(KeyPair keyPair, char[] pass, String[] ids)

其中 pass 是密码,ids = new String[] {"John Doe &lt;john@doe.com&gt;", "Jane Doe &lt;jane@doe.com&gt;"}。我按照this tutorial的行,代码的关键部分是:

PGPKeyRingGenerator keyRingGen =
    new PGPKeyRingGenerator(
        PGPSignature.POSITIVE_CERTIFICATION, rsakp_sign,
        id, sha1Calc, signhashgen.generate(), null,
        new BcPGPContentSignerBuilder(
            rsakp_sign.getPublicKey().getAlgorithm(),
            HashAlgorithmTags.SHA1),
        pske);

// Add our encryption subkey, together with its signature.
keyRingGen.addSubKey(rsakp_enc, enchashgen.generate(), null);

其中 rsakp_sign 和 rsakp_enc 分别是签名和加密密钥的 RSA 密钥对,signhashgen 和 enchashgen 是包含算法偏好等的子包的生成器。

只要我只为 John 创建一个密钥,一切都很好。但是当我想添加 Jane 时,我遇到了一个问题:显然我无法使用 addSubKey 为 Jane 添加一个 signhashgen-ified 密钥对。第一次天真的尝试是这样的:

PGPSignatureGenerator sGen = new PGPSignatureGenerator(
  new BcPGPContentSignerBuilder(PGPPublicKey.RSA_SIGN, PGPUtil.SHA1));
sGen.init(PGPSignature.POSITIVE_CERTIFICATION, pgpPrivateKey);
PGPSignature certification = sGen.generateCertification("Jane Doe <jane@doe.com>", pgpPublicKey);

PGPPublicKey newKey = PGPPublicKey.addCertification(pgpPublicKey, "Jane Doe <jane@doe.com>", certification);

keyRingGen.addSubKey(new PGPKeyPair(newKey, pgpPrivateKey), enchashgen.generate(), null);

这并没有做任何事情,gpg --vv meeththedoes.asc 中不会显示其他条目。

或者,我可以使用 John 的密钥环,提取密钥,然后添加 Jane:

PGPSecretKeyRing keyRing = keyRingGen.generateSecretKeyRing();

PGPSecretKey pgpSecretKey = keyRing.getSecretKey();
BcPGPDigestCalculatorProvider calculatorProvider = new BcPGPDigestCalculatorProvider();
BcPBESecretKeyDecryptorBuilder decryptor = new BcPBESecretKeyDecryptorBuilder(calculatorProvider);
PGPPrivateKey pgpPrivateKey = pgpSecretKey.extractPrivateKey(decryptor.build(pass));    
PGPPublicKey pgpPublicKey = pgpSecretKey.getPublicKey();

PGPSignatureGenerator    sGen = new PGPSignatureGenerator(
  new BcPGPContentSignerBuilder(PGPPublicKey.RSA_SIGN, PGPUtil.SHA1));
sGen.init(PGPSignature.POSITIVE_CERTIFICATION, pgpPrivateKey);
PGPSignature certification = sGen.generateCertification("Jane Doe <jane@doe.com>", pgpPublicKey);

PGPPublicKey newKey = PGPPublicKey.addCertification(pgpPublicKey, "Jane Doe <jane@doe.com>", certification);

pgpSecretKey = PGPSecretKey.replacePublicKey(pgpSecretKey, newKey);

这有点工作,但在生成的密钥环中,John 和 Jane 有不同的子包集:

$ gpg -vv meetthedoes.asc
gpg: ASCII-Hülle: BEGIN PGP PRIVATE KEY BLOCK
gpg: ASCII-Hülle: Version: BCPG v1.48
:secret key packet:
        version 4, algo 3, created 1380908986, expires 0
        skey[0]: [2048 bits]
        skey[1]: [17 bits]
        iter+salt S2K, algo: 9, SHA1 protection, hash: 2, salt: 696d2d42bd6b727c
        protect count: 65536 (96)
        protect IV:  87 31 81 df 17 fa 74 c4 c3 35 39 26 98 c1 15 27
        encrypted stuff follows
:user ID packet: "John Doe <john@doe.com>"
:signature packet: algo 3, keyid 3A80073198CF2010
        version 4, created 1380908986, md5len 0, sigclass 0x13
        digest algo 2, begin of digest a5 c8
        hashed subpkt 2 len 4 (sig created 2013-10-04)
        hashed subpkt 27 len 1 (key flags: 03)
        hashed subpkt 11 len 5 (pref-sym-algos: 9 8 7 3 2)
        hashed subpkt 21 len 5 (pref-hash-algos: 8 2 9 10 11)
        hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
        hashed subpkt 30 len 1 (features: 01)
        subpkt 16 len 8 (issuer key ID 3A80073198CF2010)
        data: [2047 bits]
:user ID packet: "Jane Doe <jane@doe.com>"
:signature packet: algo 3, keyid 3A80073198CF2010
        version 4, created 1380908986, md5len 0, sigclass 0x13
        digest algo 2, begin of digest f6 e8
        hashed subpkt 2 len 4 (sig created 2013-10-04)
        subpkt 16 len 8 (issuer key ID 3A80073198CF2010)
        data: [2039 bits]
sec  2048s/98CF2010 2013-10-04 John Doe <john@doe.com>
sig        98CF2010 2013-10-04   [selfsig]
uid                            Jane Doe <jane@doe.com>
sig        98CF2010 2013-10-04   [selfsig]

我可能不想要,对吧?无论如何,该方法似乎也是错误的。我不应该先完全检测生成器,然后让 Bouncycastle 一下子生成密钥环文件吗?我在这里做错了什么?

【问题讨论】:

    标签: java bouncycastle openpgp


    【解决方案1】:

    API 在添加第一个和后续 uid 之间明显不同。对于约翰,我可以说

    PGPKeyRingGenerator generator = new PGPKeyRingGenerator(
      PGPSignature.POSITIVE_CERTIFICATION, 
      signKeyPair, john, sha1Calc,
      signhashgen.generate(), null,
      new BcPGPContentSignerBuilder(
        signKeyPair.getPublicKey().getAlgorithm(),
        HashAlgorithmTags.SHA1),
        new BcPBESecretKeyEncryptorBuilder(PGPEncryptedData.AES_256).build(pass)
    );    
    generator.addSubKey(encKeyPair, enchashgen.generate(), null);    
    PGPSecretKeyRing ring = generator.generateSecretKeyRing();
    

    这会创建带有签名密钥和加密子密钥的密钥环,就像 gnupgp 一样。但对 Jane 来说,这行不通,因为将携带有关她的子密钥的信息的 signhashgen 不是 addSubKey 的参数。相反,我可以从环中提取 John 的密钥,从中创建一个 PGPPrivateKey 并使用它来签署 Jane 的 uid。

    PGPSignatureGenerator generator = new PGPSignatureGenerator(new BcPGPContentSignerBuilder(PGPPublicKey.RSA_GENERAL,
      PGPUtil.SHA1)); 
    generator.init(PGPSignature.POSITIVE_CERTIFICATION, johnsPrivateKey);
    PGPSignatureSubpacketGenerator signhashgen = copyJohnsSignhashgen();      
    generator.setHashedSubpackets(signhashgen.generate());    
    PGPSignature certification = generator.generateCertification(jane, getEncryptionKey(secretKeyRing));
    PGPPublicKey janesKey = PGPPublicKey.addCertification(getEncryptionKey(secretKeyRing), jane, certification);
    

    剩下要做的就是将新密钥添加到密钥环。

    【讨论】:

      猜你喜欢
      • 2014-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-15
      • 2022-08-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多