Bouncycastle PGP解密和验证 [英] Bouncycastle PGP decrypt and verify

查看:1011
本文介绍了Bouncycastle PGP解密和验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用java BouncyCastle库解密和验证PGP消息,但遇到问题,抱怨PartialInputStream的过早结束。



我知道加密工作正常,因为我可以使用命令行上的gpg解密和验证使用加密功能创建的消息。



这是代码:

  public static void signEncryptMessage(InputStream in ,OutputStream out,PGPPublicKey publicKey,PGPPrivateKey secretKey,SecureRandom rand)throws Exception {
out = new ArmoredOutputStream(out);

PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator(new BcPGPDataEncryptorBuilder(PGPEncryptedData.AES_256).setWithIntegrityPacket(true).setSecureRandom(rand));
encryptedDataGenerator.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(publicKey));

OutputStream compressedOut = new PGPCompressedDataGenerator(PGPCompressedData.ZIP).open(encryptedDataGenerator.open(out,4096),新字节[4096]);

PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(new BcPGPContentSignerBuilder(publicKey.getAlgorithm(),HashAlgorithmTags.SHA512));
signatureGenerator.init(PGPSignature.BINARY_DOCUMENT,secretKey);
signatureGenerator.generateOnePassVersion(true).encode(compressedOut);

OutputStream finalOut = new PGPLiteralDataGenerator()。open(compressedOut,PGPLiteralData.BINARY,,new Date(),新字节[4096]);

byte [] buf = new byte [4096];
int len;
while((len = in.read(buf))> 0){
finalOut.write(buf,0,len);
signatureGenerator.update(buf,0,len);
}

finalOut.close();
in.close();
signatureGenerator.generate()。encode(compressedOut);
compressedOut.close();
encryptedDataGenerator.close();
out.close();
}

public static void decryptVerifyMessage(InputStream in,OutputStream out,PGPPrivateKey secretKey,PGPPublicKey publicKey)throws Exception {
in = new ArmoredInputStream(in);

PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc =(PGPEncryptedDataList)pgpF.nextObject();

PGPObjectFactory plainFact = new PGPObjectFactory((PGPPublicKeyEncryptedData)enc.getEncryptedDataObjects()。next())。getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder()。setProvider(BC)。build(secretKey)))

对象消息= null;

PGPOnePassSignatureList onePassSignatureList = null;
PGPSignatureList signatureList = null;
PGPCompressedData compressedData = null;

message = plainFact.nextObject();
ByteArrayOutputStream actualOutput = new ByteArrayOutputStream();

while(message!= null){
System.out.println(message.toString());
if(message instanceof PGPCompressedData){
compressedData =(PGPCompressedData)消息;
plainFact = new PGPObjectFactory(compressedData.getDataStream());
message = plainFact.nextObject();
System.out.println(message.toString());
}

if(message instanceof PGPLiteralData){
Streams.pipeAll(((PGPLiteralData))).getInputStream(),actualOutput);
} else if(message instanceof PGPOnePassSignatureList){
onePassSignatureList =(PGPOnePassSignatureList)消息;
} else if(message instanceof PGPSignatureList){
signatureList =(PGPSignatureList)message;
} else {
throw new PGPException(message unknown message type。);
}
message = plainFact.nextObject();
}
actualOutput.close();
byte [] output = actualOutput.toByteArray();
if(onePassSignatureList == null || signatureList == null){
throw new PGPException(Poor PGP。Signatures not found。);
} else {

for(int i = 0; i< onePassSignatureList.size(); i ++){
PGPOnePassSignature ops = onePassSignatureList.get(0);
System.out.println(verifier:+ ops.getKeyID());
if(publicKey!= null){
ops.init(new JcaPGPContentVerifierBuilderProvider()。setProvider(BC),publicKey);
ops.update(output);
PGPS签名签名= signatureList.get(i);
if(ops.verify(signature)){
Iterator<?> userIds = publicKey.getUserIDs();
while(userIds.hasNext()){
String userId =(String)userIds.next();
System.out.println(由+ userId签名);
}
System.out.println(签名验证);
} else {
throw new SignatureException(Signature verification failed);
}
}
}

}

out.write(output);
out.flush();
out.close();
}

public static void main(String args []){
Security.insertProviderAt(new BouncyCastleProvider(),0);
byte inBytes [] =快速的棕色狐狸跳过懒狗。getBytes();

try {
SecureRandom rand = new SecureRandom();

RSAKeyPairGenerator kpg = new RSAKeyPairGenerator();
kpg.init(new RSAKeyGenerationParameters(BigInteger.valueOf(0x10001),rand,1024,90));

BcPGPKeyPair sender = new BcPGPKeyPair(PGPPublicKey.RSA_GENERAL,kpg.generateKeyPair(),new Date());
BcPGPKeyPair recip = new BcPGPKeyPair(PGPPublicKey.RSA_GENERAL,kpg.generateKeyPair(),new Date());

ByteArrayOutputStream sendMessage = new ByteArrayOutputStream();
ByteArrayOutputStream recvMessage = new ByteArrayOutputStream();
signEncryptMessage(new ByteArrayInputStream(inBytes),sendMessage,recipesgetPublicKey(),sender.getPrivateKey(),rand);

System.out.println(sendMessage.toString());

decryptVerifyMessage(new ByteArrayInputStream(sendMessage.toByteArray()),recvMessage,recip.getPrivateKey(),sender.getPublicKey());

System.out.println(recvMessage.toString());
} catch(Exception e){
e.printStackTrace();
}
}

经过几次 message = plainFact.nextObject(); 抛出异常:

  ----- BEGIN PGP MESSAGE ----- 
版:BCPG v1.49

hIwDbgERMnl / xpUBA / 980 / by9Ib6 / nzXiYWuwT2CYulTqzcY07iuHKB4KQc6m + H1
ZBVAx + HozgxQXQdQcBTcp + YS7Xn3tsReiH28Z9805f65tmASoqrzdf35qiVgFhfA
CbCfIq7cqC4rKut3Y8pNOs1mmhpeVNa + AqTZ1r46uyuloBTllI8OWzWoxjTcZdLP
aQHe2BQnfYk + dFgXZ2LMBMtL9mcsEqRLWIdisJQ4gppyIbQNNE7q5gV1Es63yVoM
3dpfYHxlnIZASuynSZyGorHpYMV6tWNwSRQ9Ziwaw4DwvQGyAHpb1O / tLqrfjLqN
5dj5qNY6nElT1EM94Dd4FOBzI6x6JkfuCH3 / Jp8lCA / p8K7jmYu9Xvdld8BgHmRF
ymasPf1JC4xYFa9YQVnn4fK2l // 2iVcVayv0On32kxD9XfkPUysYVH38glPaHb48
qWk9i / x0Y3mmCy1RVAGWqimR5DEhZPubJ + Kjk3UsB1m90Pm / 6A + / ZfpAEHcxshdX
Je le le le le .openpgp.PGPOnePassSignatu reList @ 7e224235
org.bouncycastle.openpgp.PGPLiteralData@7b28e644
java.io.EOFException:PartialInputStream中的流过早结束
在org.bouncycastle.bcpg.BCPGInputStream $ PartialInputStream.read(未知来源)
在org.bouncycastle.bcpg.BCPGInputStream.read(未知源)
在java.io.InputStream.read(InputStream.java:101)
在javax.crypto.CipherInputStream。 getMoreData(CipherInputStream.java:103)
在javax.crypto.CipherInputStream.read(CipherInputStream.java:177)
在org.bouncycastle.bcpg.BCPGInputStream.read(未知来源)
在org.bouncycastle.openpgp.PGPEncryptedData $ TruncatedStream.read(未知源)
在java.io.InputStream.read(InputStream.java:170)
在org.bouncycastle.util.io.TeeInputStream.read (未知来源)
在org.bouncycastle.bcpg.BCPGInputStream.read(未知来源)
在org.bouncycastle.bcpg.BCPGInputStream $ PartialInputStream.read(未知来源)
在org.bouncyc astle.bcpg.BCPGInputStream.read(未知来源)
在org.bouncycastle.openpgp.PGPCompressedData $ 1.fill(未知来源)
在java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158 )
在org.bouncycastle.bcpg.BCPGInputStream.read(未知来源)
在org.bouncycastle.bcpg.BCPGInputStream $ PartialInputStream.read(未知来源)
在org.bouncycastle.bcpg。 BCPGInputStream.read(未知来源)
在org.bouncycastle.util.io.Streams.readFully(未知来源)
在org.bouncycastle.bcpg.BCPGInputStream.readFully(未知来源)
at $ org.bouncycastle.bcpg.BCPGInputStream.readFully ;(未知源)
在org.bouncycastle.bcpg.BCPGInputStream.readPacket(未知源)
在org.bouncycastle.openpgp.PGPSignature。< init>(未知来源)
在org .bouncycastle.o penpgp.PGPObjectFactory.nextObject(未知来源)
在main.decryptVerifyMessage(main.java:113)
在main.main(main.java:167)

任何想法?



旁注,这个解密代码来自如何解密签名的pgp加密文件?,稍作修改以适合:消息将仅来自该加密方法,直接处理密钥而不是密钥流。



干杯



Ramo

解决方案

我最近正在尝试做同样的事情,并将这个方法放在基于Bouncycastle示例中发现的代码以及我在网络上找到的教程。为了我的目的,我的代码有一个具有公/私钥对的单例加密对象。在示例代码中,您可以替换

  INSTANCE._secretKeyRingCollection.getSecretKey(pbe.getKeyID());你的秘密密钥

我已经测试了这个方法,一个长久的过程,做了几十个加密&签收/解密验证操作,没有得到您看到的异常。

  public static void decryptAndVerify(InputStream in,OutputStream fOut,InputStream publicKeyIn)throws IOException,SignatureException,PGPException {
in = PGPUtil.getDecoderStream(in);

PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc;

Object o = pgpF.nextObject();
//
//第一个对象可能是PGP标记数据包。
//
if(o instanceof PGPEncryptedDataList){
enc =(PGPEncryptedDataList)o;
} else {
enc =(PGPEncryptedDataList)pgpF.nextObject();
}

//
//找到密钥
//
迭代器&PGPPublicKeyEncryptedData> it = enc.getEncryptedDataObjects();
PGPPrivateKey sKey = null;
PGPPublicKeyEncryptedData pbe = null;
while(sKey == null&& it.hasNext()){
pbe = it.next();
PBESecretKeyDecryptor decryptor = new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider())。build(INSTANCE._secretKeyPass.toCharArray());
PGPSecretKey psKey = INSTANCE._secretKeyRingCollection.getSecretKey(pbe.getKeyID());
if(psKey!= null){
sKey = psKey.extractPrivateKey(decryptor);
}
}
if(sKey == null){
throw new IllegalArgumentException(Unable to find secret key to decrypt the message);
}

InputStream clear = pbe.getDataStream(new BcPublicKeyDataDecryptorFactory(sKey));

PGPObjectFactory plainFact = new PGPObjectFactory(clear);

对象消息;

PGPOnePassSignatureList onePassSignatureList = null;
PGPSignatureList signatureList = null;
PGPCompressedData compressedData;

message = plainFact.nextObject();
ByteArrayOutputStream actualOutput = new ByteArrayOutputStream();

while(message!= null){
__l.trace(message.toString());
if(message instanceof PGPCompressedData){
compressedData =(PGPCompressedData)消息;
plainFact = new PGPObjectFactory(compressedData.getDataStream());
message = plainFact.nextObject();
}

if(message instanceof PGPLiteralData){
//必须读取并保存在某个地方。
Streams.pipeAll(((PGPLiteralData)消息).getInputStream(),actualOutput);
} else if(message instanceof PGPOnePassSignatureList){
onePassSignatureList =(PGPOnePassSignatureList)消息;
} else if(message instanceof PGPSignatureList){
signatureList =(PGPSignatureList)message;
} else {
throw new PGPException(message unknown message type。);
}
message = plainFact.nextObject();
}
actualOutput.close();
PGPPublicKey publicKey = null;
byte [] output = actualOutput.toByteArray();
if(onePassSignatureList == null || signatureList == null){
throw new PGPException(Poor PGP。Signatures not found。);
} else {

for(int i = 0; i< onePassSignatureList.size(); i ++){
PGPOnePassSignature ops = onePassSignatureList.get(0);
__l.trace(verifier:+ ops.getKeyID());
PGPPublicKeyRingCollection pgpRing = new PGPPublicKeyRingCollection(
PGPUtil.getDecoderStream(publicKeyIn));
publicKey = pgpRing.getPublicKey(ops.getKeyID());
if(publicKey!= null){
ops.init(new JcaPGPContentVerifierBuilderProvider()。setProvider(BC),publicKey);
ops.update(output);
PGPS签名签名= signatureList.get(i);
if(ops.verify(signature)){
Iterator<?> userIds = publicKey.getUserIDs();
while(userIds.hasNext()){
String userId =(String)userIds.next();
__l.trace(String.format(由{%s}签名,userId));
}
__l.trace(签名验证);
} else {
throw new SignatureException(Signature verification failed);
}
}
}

}

如果(pbe.isIntegrityProtected()&!pbe.verify()) {
抛出新的PGPException(数据是完整性保护,但完整性丢失);
} else if(publicKey == null){
throw new SignatureException(Signature not found);
} else {
fOut.write(output);
fOut.flush();
fOut.close();
}
}


I'm trying to decrypt and verify a PGP message using the java BouncyCastle libraries, but am running into issues, complaining about premature ends of PartialInputStream.

I know the encrypt works fine, because I can decrypt and verify messages created with the encrypt function using gpg on the command line.

Here's the code:

public static void signEncryptMessage(InputStream in, OutputStream out, PGPPublicKey publicKey, PGPPrivateKey secretKey, SecureRandom rand) throws Exception {
        out = new ArmoredOutputStream(out);

        PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator(new BcPGPDataEncryptorBuilder(PGPEncryptedData.AES_256).setWithIntegrityPacket(true).setSecureRandom(rand));
        encryptedDataGenerator.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(publicKey));

        OutputStream compressedOut = new PGPCompressedDataGenerator(PGPCompressedData.ZIP).open(encryptedDataGenerator.open(out, 4096), new byte[4096]);

        PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(new BcPGPContentSignerBuilder(publicKey.getAlgorithm(), HashAlgorithmTags.SHA512));
        signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, secretKey);
        signatureGenerator.generateOnePassVersion(true).encode(compressedOut);

        OutputStream finalOut = new PGPLiteralDataGenerator().open(compressedOut, PGPLiteralData.BINARY, "", new Date(), new byte[4096]);

        byte[] buf = new byte[4096];
        int len;
        while ((len = in.read(buf)) > 0) {
            finalOut.write(buf, 0, len);
            signatureGenerator.update(buf, 0, len);
        }

        finalOut.close();
        in.close();
        signatureGenerator.generate().encode(compressedOut);
        compressedOut.close();
        encryptedDataGenerator.close();
        out.close();
    }

    public static void decryptVerifyMessage(InputStream in, OutputStream out, PGPPrivateKey secretKey, PGPPublicKey publicKey) throws Exception {
        in = new ArmoredInputStream(in);

        PGPObjectFactory pgpF = new PGPObjectFactory(in);
        PGPEncryptedDataList enc = (PGPEncryptedDataList) pgpF.nextObject();

        PGPObjectFactory plainFact = new PGPObjectFactory(((PGPPublicKeyEncryptedData) enc.getEncryptedDataObjects().next()).getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(secretKey)));

        Object message = null;

        PGPOnePassSignatureList onePassSignatureList = null;
        PGPSignatureList signatureList = null;
        PGPCompressedData compressedData = null;

        message = plainFact.nextObject();
        ByteArrayOutputStream actualOutput = new ByteArrayOutputStream();

        while (message != null) {
            System.out.println(message.toString());
            if (message instanceof PGPCompressedData) {
                compressedData = (PGPCompressedData) message;
                plainFact = new PGPObjectFactory(compressedData.getDataStream());
                message = plainFact.nextObject();
                System.out.println(message.toString());
            }

            if (message instanceof PGPLiteralData) {
                Streams.pipeAll(((PGPLiteralData) message).getInputStream(), actualOutput);
            } else if (message instanceof PGPOnePassSignatureList) {
                onePassSignatureList = (PGPOnePassSignatureList) message;
            } else if (message instanceof PGPSignatureList) {
                signatureList = (PGPSignatureList) message;
            } else {
                throw new PGPException("message unknown message type.");
            }
            message = plainFact.nextObject();
        }
        actualOutput.close();
        byte[] output = actualOutput.toByteArray();
        if (onePassSignatureList == null || signatureList == null) {
            throw new PGPException("Poor PGP. Signatures not found.");
        } else {

            for (int i = 0; i < onePassSignatureList.size(); i++) {
                PGPOnePassSignature ops = onePassSignatureList.get(0);
                System.out.println("verifier : " + ops.getKeyID());
                if (publicKey != null) {
                    ops.init(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"), publicKey);
                    ops.update(output);
                    PGPSignature signature = signatureList.get(i);
                    if (ops.verify(signature)) {
                        Iterator<?> userIds = publicKey.getUserIDs();
                        while (userIds.hasNext()) {
                            String userId = (String) userIds.next();
                            System.out.println("Signed by " + userId);
                        }
                        System.out.println("Signature verified");
                    } else {
                        throw new SignatureException("Signature verification failed");
                    }
                }
            }

        }

        out.write(output);
        out.flush();
        out.close();
    }

    public static void main(String args[]) {
        Security.insertProviderAt(new BouncyCastleProvider(), 0);
        byte inBytes[] = "The quick brown fox jumps over the lazy dog.".getBytes();

        try {
            SecureRandom rand = new SecureRandom();

            RSAKeyPairGenerator kpg = new RSAKeyPairGenerator();
            kpg.init(new RSAKeyGenerationParameters(BigInteger.valueOf(0x10001), rand, 1024, 90));

            BcPGPKeyPair sender = new BcPGPKeyPair(PGPPublicKey.RSA_GENERAL, kpg.generateKeyPair(), new Date());
            BcPGPKeyPair recip = new BcPGPKeyPair(PGPPublicKey.RSA_GENERAL, kpg.generateKeyPair(), new Date());

            ByteArrayOutputStream sendMessage = new ByteArrayOutputStream();
            ByteArrayOutputStream recvMessage = new ByteArrayOutputStream();
            signEncryptMessage(new ByteArrayInputStream(inBytes), sendMessage, recip.getPublicKey(), sender.getPrivateKey(), rand);

            System.out.println(sendMessage.toString());

            decryptVerifyMessage(new ByteArrayInputStream(sendMessage.toByteArray()), recvMessage, recip.getPrivateKey(), sender.getPublicKey());

            System.out.println(recvMessage.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

After a few runs of message = plainFact.nextObject(); the exception is thrown:

-----BEGIN PGP MESSAGE-----
Version: BCPG v1.49

hIwDbgERMnl/xpUBA/98O/by9Ib6/nzXiYWuwT2CYulTqzcY07iuHKB4KQc6m+H1
ZBVAx+HozgxQXQdQcBTcp+YS7Xn3tsReiH28Z9805f65tmASoqrzdf35qiVgFhfA
CbCfIq7cqC4rKut3Y8pNOs1mmhpeVNa+AqTZ1r46uyuloBTllI8OWzWoxjTcZdLP
aQHe2BQnfYk+dFgXZ2LMBMtL9mcsEqRLWIdisJQ4gppyIbQNNE7q5gV1Es63yVoM
3dpfYHxlnIZASuynSZyGorHpYMV6tWNwSRQ9Ziwaw4DwvQGyAHpb1O/tLqrfjLqN
5dj5qNY6nElT1EM94Dd4FOBzI6x6JkfuCH3/Jp8lCA/p8K7jmYu9Xvdld8BgHmRF
ymasPf1JC4xYFa9YQVnn4fK2l//2iVcVayv0On32kxD9XfkPUysYVH38glPaHb48
qWk9i/x0Y3mmCy1RVAGWqimR5DEhZPubJ+Kjk3UsB1m90Pm/6a+/ZfpAEHcxshdX
JeVBr7aQIX3PQIUl+ZPQsgAGEmo0abQVufuKfkfjX0Gh
=ApMf
-----END PGP MESSAGE-----

org.bouncycastle.openpgp.PGPCompressedData@cd36a6d
org.bouncycastle.openpgp.PGPOnePassSignatureList@7e224235
org.bouncycastle.openpgp.PGPLiteralData@7b28e644
java.io.EOFException: premature end of stream in PartialInputStream
    at org.bouncycastle.bcpg.BCPGInputStream$PartialInputStream.read(Unknown Source)
    at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
    at java.io.InputStream.read(InputStream.java:101)
    at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:103)
    at javax.crypto.CipherInputStream.read(CipherInputStream.java:177)
    at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
    at org.bouncycastle.openpgp.PGPEncryptedData$TruncatedStream.read(Unknown Source)
    at java.io.InputStream.read(InputStream.java:170)
    at org.bouncycastle.util.io.TeeInputStream.read(Unknown Source)
    at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
    at org.bouncycastle.bcpg.BCPGInputStream$PartialInputStream.read(Unknown Source)
    at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
    at org.bouncycastle.openpgp.PGPCompressedData$1.fill(Unknown Source)
    at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158)
    at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
    at org.bouncycastle.bcpg.BCPGInputStream$PartialInputStream.read(Unknown Source)
    at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
    at org.bouncycastle.util.io.Streams.readFully(Unknown Source)
    at org.bouncycastle.bcpg.BCPGInputStream.readFully(Unknown Source)
    at org.bouncycastle.bcpg.BCPGInputStream.readFully(Unknown Source)
    at org.bouncycastle.bcpg.MPInteger.<init>(Unknown Source)
    at org.bouncycastle.bcpg.SignaturePacket.<init>(Unknown Source)
    at org.bouncycastle.bcpg.BCPGInputStream.readPacket(Unknown Source)
    at org.bouncycastle.openpgp.PGPSignature.<init>(Unknown Source)
    at org.bouncycastle.openpgp.PGPObjectFactory.nextObject(Unknown Source)
    at main.decryptVerifyMessage(main.java:113)
    at main.main(main.java:167)

Any ideas?

Side note, this decryption code came from How to decrypt a signed pgp encrypted file?, slightly modified to suit: Messages will only be coming from that encryption method, and handling of the keys directly instead of key streams.

Cheers

Ramo

解决方案

I was recently trying to do the same kind of thing and put together this method based on code I found in the Bouncycastle examples and on tutorials I found on the web. For my purposes, my code has a singleton crypto object that has a public/private key pair. In the example code, you could replace

    INSTANCE._secretKeyRingCollection.getSecretKey(pbe.getKeyID());

with your secret key. I've tested this method with a long-lived process that did several tens of encrypt & sign / decrypt & verify actions and didn't get the exception you're seeing.

public static void decryptAndVerify(InputStream in, OutputStream fOut, InputStream publicKeyIn) throws IOException, SignatureException, PGPException {
    in = PGPUtil.getDecoderStream(in);

    PGPObjectFactory pgpF = new PGPObjectFactory(in);
    PGPEncryptedDataList enc;

    Object o = pgpF.nextObject();
    //
    // the first object might be a PGP marker packet.
    //
    if (o instanceof PGPEncryptedDataList) {
        enc = (PGPEncryptedDataList) o;
    } else {
        enc = (PGPEncryptedDataList) pgpF.nextObject();
    }

    //
    // find the secret key
    //
    Iterator<PGPPublicKeyEncryptedData> it = enc.getEncryptedDataObjects();
    PGPPrivateKey sKey = null;
    PGPPublicKeyEncryptedData pbe = null;
    while (sKey == null && it.hasNext()) {
        pbe = it.next();
        PBESecretKeyDecryptor decryptor = new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(INSTANCE._secretKeyPass.toCharArray());
        PGPSecretKey psKey = INSTANCE._secretKeyRingCollection.getSecretKey(pbe.getKeyID());
        if (psKey != null) {
            sKey = psKey.extractPrivateKey(decryptor);
        }
    }
    if (sKey == null) {
        throw new IllegalArgumentException("Unable to find secret key to decrypt the message");
    }

    InputStream clear = pbe.getDataStream(new BcPublicKeyDataDecryptorFactory(sKey));

    PGPObjectFactory plainFact = new PGPObjectFactory(clear);

    Object message;

    PGPOnePassSignatureList onePassSignatureList = null;
    PGPSignatureList signatureList = null;
    PGPCompressedData compressedData;

    message = plainFact.nextObject();
    ByteArrayOutputStream actualOutput = new ByteArrayOutputStream();

    while (message != null) {
        __l.trace(message.toString());
        if (message instanceof PGPCompressedData) {
            compressedData = (PGPCompressedData) message;
            plainFact = new PGPObjectFactory(compressedData.getDataStream());
            message = plainFact.nextObject();
        }

        if (message instanceof PGPLiteralData) {
            // have to read it and keep it somewhere.
            Streams.pipeAll(((PGPLiteralData) message).getInputStream(), actualOutput);
        } else if (message instanceof PGPOnePassSignatureList) {
            onePassSignatureList = (PGPOnePassSignatureList) message;
        } else if (message instanceof PGPSignatureList) {
            signatureList = (PGPSignatureList) message;
        } else {
            throw new PGPException("message unknown message type.");
        }
        message = plainFact.nextObject();
    }
    actualOutput.close();
    PGPPublicKey publicKey = null;
    byte[] output = actualOutput.toByteArray();
    if (onePassSignatureList == null || signatureList == null) {
        throw new PGPException("Poor PGP. Signatures not found.");
    } else {

        for (int i = 0; i < onePassSignatureList.size(); i++) {
            PGPOnePassSignature ops = onePassSignatureList.get(0);
            __l.trace("verifier : " + ops.getKeyID());
            PGPPublicKeyRingCollection pgpRing = new PGPPublicKeyRingCollection(
                    PGPUtil.getDecoderStream(publicKeyIn));
            publicKey = pgpRing.getPublicKey(ops.getKeyID());
            if (publicKey != null) {
                ops.init(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"), publicKey);
                ops.update(output);
                PGPSignature signature = signatureList.get(i);
                if (ops.verify(signature)) {
                    Iterator<?> userIds = publicKey.getUserIDs();
                    while (userIds.hasNext()) {
                        String userId = (String) userIds.next();
                        __l.trace(String.format("Signed by {%s}", userId));
                    }
                    __l.trace("Signature verified");
                } else {
                    throw new SignatureException("Signature verification failed");
                }
            }
        }

    }

    if (pbe.isIntegrityProtected() && !pbe.verify()) {
        throw new PGPException("Data is integrity protected but integrity is lost.");
    } else if (publicKey == null) {
        throw new SignatureException("Signature not found");
    } else {
        fOut.write(output);
        fOut.flush();
        fOut.close();
    }
}

这篇关于Bouncycastle PGP解密和验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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