java pgp异常,java - 无法gpg解密BouncyCastlePGP加密的消息 - 堆栈内存溢出

当我尝试使用通过BouncyCastle加密的GnuPG解密消息时,得到两个gpg: [don't know]: invalid packet (ctb=xx)消息,并且解密失败。

我gpg (GnuPG) 2.0.30 on OSX使用BouncyCastle 1.54和gpg (GnuPG) 2.0.30 on OSX

细节

1) PGP密钥是使用gpg生成的,如下所示:

$ gpg --gen-key

gpg (GnuPG) 2.0.30; Copyright (C) 2015 Free Software Foundation, Inc.

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:

(1) RSA and RSA (default)

(2) DSA and Elgamal

(3) DSA (sign only)

(4) RSA (sign only)

Your selection? 1

RSA keys may be between 1024 and 4096 bits long.

What keysize do you want? (2048)

Requested keysize is 2048 bits

Please specify how long the key should be valid.

0 = key does not expire

= key expires in n days

w = key expires in n weeks

m = key expires in n months

y = key expires in n years

Key is valid for? (0) 0

Key does not expire at all

Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: Foo Bar

Email address: foo@bar.com

Comment: Test Key

You selected this USER-ID:

"Foo Bar (Test Key) "

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O

You need a Passphrase to protect your secret key.

We need to generate a lot of random bytes. It is a good idea to perform

some other action (type on the keyboard, move the mouse, utilize the

disks) during the prime generation; this gives the random number

generator a better chance to gain enough entropy.

We need to generate a lot of random bytes. It is a good idea to perform

some other action (type on the keyboard, move the mouse, utilize the

disks) during the prime generation; this gives the random number

generator a better chance to gain enough entropy.

public and secret key created and signed.

pub 2048R/79CC322A 2017-08-17

Key fingerprint = 93B9 0D06 08D2 EB84 9F83 4CD3 A470 748E 79CC 322A

uid [ unknown] Foo Bar (Test Key)

sub 2048R/21B41E21 2017-08-17

$

2)以asc格式导出的PGP公钥如下所示:

-----BEGIN PGP PUBLIC KEY BLOCK-----

Version: GnuPG v2

mQENBFmWE88BCADB+esy+D2Zobru86ztUTp7hWyDy5w9B2iHlyORLI6mQ0JH+ya6

cbaO9nWT7WC68l1ocWaeak0t/9hx0CDWv6zdAXfEUPu8qB53M4m1NACDJp3UDeQS

UytmpB/kutViUO+yiRhtezYsFP70PHOO7o9Tgze5H/qF/hgAVmk1/eN4oSTH4hqo

VIvlsvTNZYLt+a2wYN0RPPryfXnvrKOSXdE5roQd/TMaMwwd2Mbhhh31IB1ROw2/

I+tvJfrM4zLseuo0ndYmWL7ZfjPslsFUezUQf5BDmFdIi9M3/UWHtHmSR6GGG1ko

uo0XjABiIjwfj1mQSA3txI1yO+RLHYrI5UL1ABEBAAG0IEZvbyBCYXIgKFRlc3Qg

S2V5KSA8Zm9vQGJhci5jb20+iQE5BBMBCAAjBQJZlhPPAhsDBwsJCAcDAgEGFQgC

CQoLBBYCAwECHgECF4AACgkQpHB0jnnMMipk+Qf/cKLSdv+aYHKteS/rtAXQbRWG

5nEGKk8vU5HseESr9tDbzkMpruYXtGG99GjPjZO2NqoYF+3NzD6suiQzP95dHyH0

g3i2AHLoyd7W9VvZEieH7vGRrUjYYP2N/qifUepdiu3gKQLHDBE14tXRHEfTN5WV

BxClZ4MwmMvHzsg6NB2RXJb7t5e9apgQ/+0O9l5LwGsSSkCQr53OmoMSUnQP0lrz

gqMxzbC6sI/FYaVaoMGnAUMFQ+8l7nI/Tv6R/sCN5d4egcIC1AzVcDE+zGkwRrmX

4lcKen0XvolJfpUNx9D2CIAQttz0nvygxjBAByXT4oFcbPw9GZCNmxKo/eUp4LkB

DQRZlhPPAQgAz4tebylTFXZCj4xwzy7wyrw4J+vUkMrOh5tOVgISPMaEiDBzFyhf

oqs0uAamImUyF2HGVGXEGappZncjrympdYFpDXG6jb0oYap03hheli1R6h+56PNq

zNyVzlfq85BqgVa5Qed1VnDbEz29JMjLwSvCEY3V0SIOgVZxE5GfMjvAkUhPoE+o

T5uVuRUlnfdKXMYgNRh5gbNEsvx+PMGihC3pSrWWYbBtU6otNXCVCYQryORaHWAf

pvB99P6YzP0nc6Dbu2ZSiGsDAQwa3ZCow+E997upf22WMfowwkNFtarnrr1fVLkl

exR28nJdeAbh0R3WpgQJqeCGmH9fYQEBjwARAQABiQEfBBgBCAAJBQJZlhPPAhsM

AAoJEKRwdI55zDIqgAAH/39teAauUrB+xEVr/Q+McXa0PQSrErB2P4jaVIBuZH2/

6EeRycp6bIwc5R/gpkIVcPg8DmDYtobRbj2YDc5o+4tPVgSKJUgOB2l9CryP+aCm

lx8R0nCN8q53vqtmm7LYc+W1K6tXQJZi8VbCC9sLGUxH0HuDP2ldcBnrialV2cLZ

zsxRgoFF3f8u/We97z2qwzRQXshvw4GVL3wSs511mTcOZW8LnO1YMt3m5ABIsZN0

P/avr7zEqsvr0iJOQ7WbJLbgHkxKu03SfcN0XfVDX4VzqykLvn9THHVtofU6h4LE

LoIRKGg57DXFrsc93a1GWzN9z764sXQ7JgWqnW6a72g=

=n8OZ

-----END PGP PUBLIC KEY BLOCK-----

3) PGP公钥以其“ PUBLIC KEY BLOCK”形式传递,并按以下方式解析:(pgpKeyBytes是密钥的String表示形式的UTF-8字节编码)

private PGPPublicKey resolvePgpPublicKey(byte[] pgpKeyBytes) throws IOException, PGPException {

PGPPublicKeyRingCollection keyRingCollection;

try (InputStream in = PGPUtil.getDecoderStream(new ByteArrayInputStream(pgpKeyBytes))) {

keyRingCollection = new PGPPublicKeyRingCollection(

PGPUtil.getDecoderStream(in), new JcaKeyFingerprintCalculator());

}

Iterator> keyRingIterator = keyRingCollection.getKeyRings();

while (keyRingIterator.hasNext()) {

PGPPublicKeyRing keyRing = (PGPPublicKeyRing) keyRingIterator.next();

Iterator> keyIterator = keyRing.getPublicKeys();

while (keyIterator.hasNext()) {

PGPPublicKey key = (PGPPublicKey) keyIterator.next();

if (key.isMasterKey()) {

continue;

}

if (key.isEncryptionKey()) {

return key;

}

}

}

throw new ServiceRequestException("Cannot resolve PGPPublicKey");

}

4)使PGP加密的是16字节数组的十六进制字符串表示形式(作为keyBytes传递),如下所示:

private byte[] encryptKeyBytes(byte[] keyBytes, byte[] pgpKey) throws GeneralSecurityException {

ByteArrayOutputStream encKeyBytes = new ByteArrayOutputStream(keyBytes.length);

try (Handle randomHandle = RngSupport.getRandom()) {

JcePGPDataEncryptorBuilder encryptorBuilder =

new JcePGPDataEncryptorBuilder(PGPEncryptedDataGenerator.AES_256);

encryptorBuilder.setWithIntegrityPacket(true);

encryptorBuilder.setSecureRandom(randomHandle.getObject());

encryptorBuilder.setProvider("BC");

PGPEncryptedDataGenerator encryptor = new PGPEncryptedDataGenerator(encryptorBuilder);

try {

JcePublicKeyKeyEncryptionMethodGenerator keyEncryptionMethodGenerator =

new JcePublicKeyKeyEncryptionMethodGenerator(resolvePgpPublicKey(pgpKey));

keyEncryptionMethodGenerator.setProvider("BC");

encryptor.addMethod(keyEncryptionMethodGenerator);

try (

OutputStream ao = new ArmoredOutputStream(encKeyBytes);

OutputStream eo = encryptor.open(ao, keyBytes.length)) {

eo.write(BytesSupport.encodeHex(keyBytes).getBytes(StandardCharsets.UTF_8));

}

} catch (ServiceRequestException e) {

throw e;

} catch (Exception e) {

throw new GeneralSecurityException("Cannot perform PGP encryption", e);

}

}

return encKeyBytes.toByteArray();

}

5)这种加密的结果示例如下:

-----BEGIN PGP MESSAGE-----

Version: BCPG v@RELEASE_NAME@

hQEMA0a1HkkhtB4hAQf+MfDa3ILJJivDYO+V9GwLDXMq1Oi8YFe/oNfScT2KT6aG

rKBIaCQvwTQPD95QS3lo9sRZYvD64C7+Y+PA2e4nSJYNiLmyEczqFVzSgoI8ibhD

LDG+trkAgEd3UiSltju8oF/d5SUPaubVrfH413xZ2xg5lbx7z78U4KtAZ1IMk/XN

DN2nCaOVIw/EbqzVt8YCdDpQRrnfh1ZB5lDmLYoRuJykQ08UCrxv9dyQN3wpOX/G

K7Nq3w6Q6+vT8LiP9iA7NEEu3BObNHAQ371VQ4uJQaZOysxPAH/RFHDHRtDa6R/J

F6ca8z28mliQdZxFpyrqKgPwjrsthZ4BApUnHZ6dm9I5ATnr4m4jPQefMeSgGLYD

I3Mk82COdct8ZNk108bOQjSAl+CPlARb53pItOZm21PL1lVwzcq1IXvUjJYjEOSA

6SccakqFhF8cgQ==

=A56Z

-----END PGP MESSAGE-----

6)当我尝试解密消息时,收到两个“ gpg:[不知道]:无效数据包”消息,并且解密失败:

$ gpg -vv --decrypt /tmp/ct.asc

gpg: armor: BEGIN PGP MESSAGE

Version: BCPG v@RELEASE_NAME@

:pubkey enc packet: version 3, algo 1, keyid 46B51E4921B41E21

data: [2046 bits]

gpg: armor header:

gpg: public key is 21B41E21

gpg: using subkey 21B41E21 instead of primary key 79CC322A

You need a passphrase to unlock the secret key for

user: "Foo Bar (Test Key) "

gpg: using subkey 21B41E21 instead of primary key 79CC322A

2048-bit RSA key, ID 21B41E21, created 2017-08-17 (main key ID 79CC322A)

gpg: no running gpg-agent - starting one

gpg: public key encrypted data: good DEK

:encrypted data packet:

length: 57

mdc_method: 2

gpg: encrypted with 2048-bit RSA key, ID 21B41E21, created 2017-08-17

"Foo Bar (Test Key) "

gpg: AES256 encrypted data

gpg: [don't know]: invalid packet (ctb=39)

gpg: decryption okay

gpg: [don't know]: invalid packet (ctb=44)

$

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值