如何用Java中的Bouncy Castle签署公共PGP密钥 [英] How to sign public PGP key with Bouncy Castle in Java

查看:104
本文介绍了如何用Java中的Bouncy Castle签署公共PGP密钥的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写PGP服务器以为用户生成密钥。

我想用Bouncy Castle在Java中用我的私钥对任何生成的PGP公钥进行签名,以使其受到用户的信任。 / p>

生成密钥对没有问题-完美。



我尝试通过gpg签名-



但是我在Java中无法获得相同的效果。我尝试了许多类似的解决方案:用Bouncycastle的Java签署公共pgp密钥



和BC示例包中的DirectKeySignature类,但对我来说不起作用。



密钥已签名,但gpg- -check-sigs指示签名不正确:

  gpg --check-sigs Adrian(test)< al @ pc .pl> 
pub 4096R / 9D5D4AB8 2018-06-20
sig- E9798A8A 2018-08-04测试(test)< test@sample.com>
uid Adrian(测试)< al@p-c.pl>
信号! 9D5D4AB8 2018-06-20 Adrian(测试)< al@p-c.pl>

1个签名错误

两个版本的源代码:



版本1:

  public void signKey(String id,PGPSecretKey mySecretKey,PGPPublicKey publicKeyToBeSigned ,char [] passPhrase,OutputStream out)抛出PGPException,IOException {

PGPPrivateKey pgpPrivKey = mySecretKey.extractPrivateKey(
new JcePBESecretKeyDecryptorBuilder()。setProvider(provider).build(passPhrase)));

PGPSignatureGenerator signatureGenerator =新的PGPSignatureGenerator(
新的JcaPGPContentSignerBuilder(mySecretKey.getPublicKey()。getAlgorithm(),PGPUtil.SHA1));

signatureGenerator.init(PGPSignature.DIRECT_KEY,pgpPrivKey);

PGPSignature签名= signatureGenerator.generateCertification(id,publicKeyToBeSigned);

PGPPublicKey结果= PGPPublicKey.addCertification(publicKeyToBeSigned,签名);

out =新的ArmoredOutputStream(out);

result.encode(out);
out.close();
}

版本2(基于org.bouncycastle.openpgp.examples.DirectKeySignature):

  public void signPublicKey(PGPSecretKey secretKey,String secretKeyPass,PGPPublicKey keyToBeSigned,String notationName,String notationValue,OutputStream out)引发异常{

PGPPrivateKey pgpPrivKey = secretKey.extractPrivateKey(
new JcePBESecretKeyDecryptorBuilder()。setProvider( BC)。build(secretKeyPass.toCharArray()));

PGPSignatureGenerator sGen =新的PGPSignatureGenerator(
新的JcaPGPContentSignerBuilder(secretKey.getPublicKey()。getAlgorithm(),PGPUtil.SHA1).setProvider( BC));

sGen.init(PGPSignature.DIRECT_KEY,pgpPrivKey);

PGPSignatureSubpacketGenerator spGen =新的PGPSignatureSubpacketGenerator();

布尔值isHumanReadable = true;

spGen.setNotationData(true,isHumanReadable,notationName,notationValue);

PGPSignatureSubpacketVector packetVector = spGen.generate();

sGen.setHashedSubpackets(packetVector);

PGPPublicKey结果= PGPPublicKey.addCertification(keyToBeSigned,sGen.generate());

out =新的ArmoredOutputStream(out);

result.encode(out);
out.close();
}

测试:

  @Test 
public void signKey()引发异常{

FileInputStream in = new FileInputStream( src / test / resources / secret.dat) ;

PgpServiceImpl pgp = new PgpServiceImpl();

PGPSecretKey pgpSecretKey = pgp.readSecretKey(in, ..........。toCharArray());
PGPPublicKey pubKey = pgp.readPublicKey(new FileInputStream( src / test / resources / pub_other.dat));

ByteArrayOutputStream res = new ByteArrayOutputStream();

pgp.signPublicKey(pgpSecretKey, ..........,pubKey,测试(test)< test@sample.com>,艾德里安(test)< ; al@pc.pl>,res);

System.out.println(new String(res.toByteArray()));
}

结果:

  ----- BEGIN PGP公共密钥块----- 
版本:BCPG v1.60

mQINBFsqb5YBEADHhGX7m27h2gyj1sXtVBy6VmTzxf4uI9MhLNK1fEuM4L7B PQQ / dvIxefkX9CDIVkMeHgQI / KFN
1dtkSTtV8eHogdKhii2bDFNDY01WgIyxQtdgs + QrKXexVWbxBwBS3wUorUaegvfQ
b55w4LtjMfcSqQanIOMb9G0yVAx9 / RxCHBSGLEVzdQroTQQKyX0EBPFibB5Mxeaf
MHm821ds3a3rE / FCCCZRgRnGVTfgBgU1 / WtAoY4MsJ6MEVJjGDkT0VkVPtE + 8VE /
M2wRQx8sR42MhidDT9Kgmb2ma6sIOLdxnCbwlegnttpTG5zlSL98jxVtalvXvylO
hXLunrtJPQC1q2icjMwu4nIGaWNxT1bk7JAG29x80qE2NB9Ms8 + hYlsRPn6s5bY5
TGI4fzXY7 / WFN + Ho26nu69YTdpPuRfI7EJi0uOvsLeRCmszFzaIyFx1Ebt8qEDwB
C + WKcBwWb80tWUcARALdZAYGeMlJN4zELpQhFWb1bCmHKJfPUqr2VG5AzNqCp8KJ
1V9 + TG44USfYIkK24BAGwKnPrzSF0vNC + eB513m9ju7g92T0XjgaiZaQTTErnQHH
zwS6gfbsX8gMx8MndhYcTnmzXSRClg4Hp0bYCLZlmkiuroGywN2Yshe8gwARAQAB
iQJcBB8BAgBGBQJbZ / dTP5SAAAAAAB0AGVRlc3QgKHRlc3QpIDx0ZXN0QHNhbXBs
ZS5jb20 + QWR yaWFuICh0ZXN0KSA8YWxAcC1jLnBsPgAKCRABNke + 6XmKisFRD / 91
SF + WnBXm2Udh7S8feORaqZ4pe6SbYHuRkAhnqSZgrc8mrB6VfWuNrw6AjVSlFNCr
WtSXzi45Z5Nvgx69c2 / 1jMkEtIivhQHgB3WnE5 / nXXwFBbEMyFD1q8PzktgHQ / JQ
wGPFYeLf6BPkhmaXx0PhKFdad92e4qDbWk / CF4KS50uYeiCvwy1FVlRZrGyF7hM1
WCBGEQM4rVsF8BOCyTnWzaBzHq / 1e6cxdEemCXFCN8lR22l6bKSbS01gzM + VcY6R
5hfOi + LMSvbdsmuIQbDFzrw4QbAwcE / 0UJCmG0ceB1qq3jRB +乔/ 0HWT / knZaBIO
SPVWo0hnCqvkxyn3gzy0zmbW / ck8t5CZaQ9ylt7mwE9m9ynm6WUPEvf9IdK8Xniv
wiFURRfacvLOAbcegnjmFNrt + Pqf4OoWCrlPSYC8KxPAmMEKhdSRDBHK / s5gCNtx
Hjipu6ucSmt7KWwor8WOKXCUzSIdxO5DFBdCK2QkxwltNqZ / GSnszjLQO + ywxKef
xQasejw0vIWzEy4cp0EbGEVceBeBCwNrpphPj7 + btlaTLM8 / pRI1LmKUcBrxqnLz
jmrQfc15goTNW20Rtb7b70qY0aSi9ZPlVP + hKlywsHdH7I8lF03v403ZDyLXKB4K
sPSi7CsdDMUmEAVwxI8m2gsMFXvAaBVj / TxeptGMa7QZQWRyaWFuICh0ZXN0KSA8
YWxAcC1jLnBsPokCHAQQAQIABgUCWypvlgAKCRB5PbIpnV1KuMqUEACyhenXAwsx
BPgKpnnMAS6S + XUT6dz1pTH3hcQ5KZiw78XbZxUALFDqm3qKmjZnN4SUpbA71kK0
SG + RAL8ydjQerQ + LU4 + 6JOK5qDqsM / X KkpNRcgAL9g8GC5w1B / 7pSh3Im + 02U / AA
g7gi5sYtqo8fTZspHMf5pIeT75ln3IBLmkNSJUthNNixNZWXgn83L40twnPKaaQC
0QNua0xZJubFzmgg5KempIIGdYOgQh8rNc28cCsFrrIg / ggsifsVJDzVtMnSBBYb
L8G2Eb + fUiqCOL1jNEFy / aCBzMLWEXkBmdl9nwZQ1eB9qEaBRpfTLuIiq8U1KA8 /
fOfYtuftsUziuGYj9CvN // esA75HxwVtL7ssn1TGdWMYQ9KhuGmGHLkKBRUT91hU
HtO0SXQ8tyWkICJ3Lp9irEF / tdFwPorlLYoch3Ya5ybySXMtHprcBN5eCfBZpFw1
$ AllidwK0nvDQeaA0ZHVvMyXATO0AhCY6WArORaHM6tER51qxgz9vpffYaFxwJfn4 b $ b 9dApqV4Xx7Ei1VEdQ7t0YGcdvNByLRDeEvwEhC7808jPCLGoIP4rOKyAk3gTU98w
0vg3h9OLkCueT5482 / v5DFbtzPNOjksIbMhmNt0KUOxfla + S48Zb0xSw0jXZEDOi
snGdpaUOpLJZRe2zI / i59UIHi1OoKERxYw ==
= 9lxJ
----- END PGP公钥BLOCK -----


解决方案

这很完美:

  public void signPublicKey(PGPSecretKey secretKey,char [] passPhrase,PGPPublicKey keyToBeSigned,OutputStream out)抛出PGPException,IOException {

PGPPrivateKey pgpPrivKey = secretKe y.extractPrivateKey(
新的JcePBESecretKeyDecryptorBuilder()。setProvider(提供者)
.build(passPhrase));

PGPSignatureGenerator signatureGenerator =新的PGPSignatureGenerator(
新的JcaPGPContentSignerBuilder(secretKey.getPublicKey()。getAlgorithm(),PGPUtil.SHA1));

signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION,pgpPrivKey);

Iterator< String> ids = keyToBeSigned.getUserIDs();
if(!ids.hasNext())throw new IllegalArgumentException( klucz nie posiadażadnegoUser ID);
字符串id = ids.next();

PGPSignature签名= signatureGenerator.generateCertification(id,keyToBeSigned);
PGPPublicKey newKey = PGPPublicKey.addCertification(keyToBeSigned,id,signature);

out =新的ArmoredOutputStream(out);

newKey.encode(out);
out.close();
}


I'm writing PGP server to generate keys for users.
I want to sign any generated PGP public key with my private key in Java with Bouncy Castle, to make it trusted for my users.

I have no problems with generating key pair - it works perfect.

I tried to sign by gpg --sign-key command line and it works good.

But I can't get the same in Java. I tried many solutions like this: java sign public pgp key with bouncycastle

and DirectKeySignature class from BC examples package, but nothing works for my.

Key is signed but gpg --check-sigs tell that signature is incorrect:

gpg --check-sigs "Adrian (test) <al@p-c.pl>"
pub   4096R/9D5D4AB8 2018-06-20
sig-         E9798A8A 2018-08-04  Test (test) <test@sample.com>
uid                  Adrian (test) <al@p-c.pl>
sig!         9D5D4AB8 2018-06-20  Adrian (test) <al@p-c.pl>

1 incorrect signature

Source code in two versions:

version 1:

public void signKey(String id, PGPSecretKey mySecretKey, PGPPublicKey publicKeyToBeSigned, char[] passPhrase, OutputStream out) throws PGPException, IOException {

    PGPPrivateKey pgpPrivKey = mySecretKey.extractPrivateKey(
            new JcePBESecretKeyDecryptorBuilder().setProvider(provider).build(passPhrase));

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

    signatureGenerator.init(PGPSignature.DIRECT_KEY, pgpPrivKey);

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

    PGPPublicKey result = PGPPublicKey.addCertification(publicKeyToBeSigned, signature);

    out = new ArmoredOutputStream(out);

    result.encode(out);
    out.close();
}

version 2 (baset on org.bouncycastle.openpgp.examples.DirectKeySignature):

public void signPublicKey(PGPSecretKey secretKey, String secretKeyPass, PGPPublicKey keyToBeSigned, String notationName, String notationValue, OutputStream out) throws Exception {

    PGPPrivateKey pgpPrivKey = secretKey.extractPrivateKey(
            new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(secretKeyPass.toCharArray()));

    PGPSignatureGenerator sGen = new PGPSignatureGenerator(
            new JcaPGPContentSignerBuilder(secretKey.getPublicKey().getAlgorithm(), PGPUtil.SHA1).setProvider("BC"));

    sGen.init(PGPSignature.DIRECT_KEY, pgpPrivKey);

    PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();

    boolean isHumanReadable = true;

    spGen.setNotationData(true, isHumanReadable, notationName, notationValue);

    PGPSignatureSubpacketVector packetVector = spGen.generate();

    sGen.setHashedSubpackets(packetVector);

    PGPPublicKey result = PGPPublicKey.addCertification(keyToBeSigned, sGen.generate());

    out = new ArmoredOutputStream(out);

    result.encode(out);
    out.close();
}

Test:

@Test
public void signKey() throws Exception {

    FileInputStream in = new FileInputStream("src/test/resources/secret.dat");

    PgpServiceImpl pgp = new PgpServiceImpl();

    PGPSecretKey pgpSecretKey = pgp.readSecretKey(in, "..........".toCharArray());
    PGPPublicKey pubKey = pgp.readPublicKey(new FileInputStream("src/test/resources/pub_other.dat"));

    ByteArrayOutputStream res = new ByteArrayOutputStream();

    pgp.signPublicKey(pgpSecretKey, "..........", pubKey, "Test (test) <test@sample.com>", "Adrian (test) <al@p-c.pl>", res);

    System.out.println(new String(res.toByteArray()));
}

result:

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: BCPG v1.60

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
snGdpaUOpLJZRe2zI/i59UIHi1OoKERxYw==
=9lxJ
-----END PGP PUBLIC KEY BLOCK-----

解决方案

this works perfectly:

public void signPublicKey(PGPSecretKey secretKey, char[] passPhrase, PGPPublicKey keyToBeSigned, OutputStream out) throws PGPException, IOException {

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

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

        signatureGenerator.init( PGPSignature.DEFAULT_CERTIFICATION, pgpPrivKey );

        Iterator<String> ids = keyToBeSigned.getUserIDs();
        if(!ids.hasNext()) throw new IllegalArgumentException("klucz nie posiada żadnego User ID");
        String id = ids.next();

        PGPSignature signature = signatureGenerator.generateCertification(id, keyToBeSigned);
        PGPPublicKey newKey = PGPPublicKey.addCertification(keyToBeSigned, id, signature);

        out = new ArmoredOutputStream(out);

        newKey.encode(out);
        out.close();
    }

这篇关于如何用Java中的Bouncy Castle签署公共PGP密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆