我正在尝试实现一个字节数组的OpenPGP签名(也可能是一个字符串,因为源是JSON而不应该很重要)但是我从Java BouncyCastle实现得到了错误的输出。我正在测试,我想模仿gnupg的--sign选项。这是我从示例用法中修改的代码:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.SignatureException;
import java.util.Date;
import java.util.Iterator;
import org.bouncycastle.bcpg.BCPGOutputStream;
import org.bouncycastle.openpgp.PGPCompressedData;
import org.bouncycastle.openpgp.PGPCompressedDataGenerator;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPLiteralData;
import org.bouncycastle.openpgp.PGPLiteralDataGenerator;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureGenerator;
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
public class OpenPGP {
private static PGPSecretKey readSecretKey(final InputStream input)
throws IOException, PGPException {
final PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(
PGPUtil.getDecoderStream(input));
final Iterator keyRingIter = pgpSec.getKeyRings();
while (keyRingIter.hasNext()) {
final PGPSecretKeyRing keyRing = (PGPSecretKeyRing) keyRingIter
.next();
final Iterator keyIter = keyRing.getSecretKeys();
while (keyIter.hasNext()) {
final PGPSecretKey key = (PGPSecretKey) keyIter.next();
if (key.isSigningKey())
return key;
}
}
throw new IllegalArgumentException(
"Can't find signing key in key ring.");
}
public static byte[] sign(final byte[] data, final String key)
throws IOException, PGPException, SignatureException {
PGPSecretKey pgpSec;
pgpSec = readSecretKey(new ByteArrayInputStream(key.getBytes()));
PGPPrivateKey pgpPrivKey;
pgpPrivKey = pgpSec
.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder()
.setProvider("BC").build("".toCharArray()));
final PGPSignatureGenerator sGen = new PGPSignatureGenerator(
new JcaPGPContentSignerBuilder(pgpSec.getPublicKey()
.getAlgorithm(), PGPUtil.SHA1).setProvider("BC"));
sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
@SuppressWarnings("rawtypes")
final Iterator it = pgpSec.getPublicKey().getUserIDs();
if (it.hasNext()) {
final PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
spGen.setSignerUserID(false, (String) it.next());
sGen.setHashedSubpackets(spGen.generate());
}
final PGPCompressedDataGenerator compressDataGenerator = new PGPCompressedDataGenerator(
PGPCompressedData.ZLIB);
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final BCPGOutputStream bOut = new BCPGOutputStream(
compressDataGenerator.open(out));
sGen.generateOnePassVersion(false).encode(bOut);
final PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
OutputStream lOut;
lOut = lGen.open(bOut, PGPLiteralData.BINARY, "score.dat", new Date(),
data);
final InputStream fIn = new ByteArrayInputStream(data);
int ch;
while ((ch = fIn.read()) >= 0) {
lOut.write(ch);
sGen.update((byte) ch);
}
lGen.close();
sGen.generate().encode(bOut);
compressDataGenerator.close();
return out.toByteArray();
}
}
现在,sign函数的结果是base64编码,然后对url保持安全,并且似乎具有适当的长度,但在解码时消息无效。以下是解码内容的示例:
0:
version: 3
signature_type: 0
hash_algorithm: 2
key_algorithm: 1
key_id: 4F65C291695F46BA
nested: 0
tag: 4
size: <NULL>
data: <NULL>
这是一个非常印刷的PHP对象,从我的旧版php openpgp lib的端口到更新的标准,它在github @ mudhairless / openpgp上,是
的结果\OpenPGP\Message::parse($message);
key_id有正确但消息与gnupg生成的消息有很大不同,缺少实际数据:
0:
0:
version: 3
signature_type: 0
hash_algorithm: 2
key_algorithm: 1
key_id: 4F65C291695F46BA
nested: 1
tag: 4
size: <NULL>
data: <NULL>
1:
format: b
filename: data.txt
timestamp: 1400821038
tag: 11
size: 12
data: 1234567890
2:
version: 4
signature_type: 0
hash_algorithm: 2
key_algorithm: 1
hashed_subpackets:
0:
tag: 2
size: <NULL>
data: 1400821038
unhashed_subpackets:
0:
tag: 16
size: <NULL>
data: 4F65C291695F46BA
hash_head: 51977
trailer: S~�.�
tag: 2
size: <NULL>
data:
0: <long string of random characters>
我已经在这个问题上做了很多搜索,没有运气,所以任何助理都会受到赞赏。