首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何解密签名的pgp加密文件?

如何解密签名的pgp加密文件?
EN

Stack Overflow用户
提问于 2011-07-26 17:08:49
回答 1查看 21K关注 0票数 6

如何使用BouncyCastle Java API解密和验证使用PGP加密的文件?

EN

回答 1

Stack Overflow用户

发布于 2013-05-16 05:15:36

加密代码:

private static void encryptFile(OutputStream out, String fileName, PGPPublicKey encKey, PGPSecretKey pgpSec, boolean armor, boolean withIntegrityCheck, char[] pass) throws IOException, NoSuchProviderException {
    if (armor) {
        out = new ArmoredOutputStream(out);
    }

    try {
        PGPEncryptedDataGenerator encGen =
                new PGPEncryptedDataGenerator(
                new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(
                new SecureRandom())
                .setProvider("BC"));
        encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider("BC"));
        OutputStream encryptedOut = encGen.open(out, new byte[BUFFER_SIZE]);

        PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
        OutputStream compressedData = comData.open(encryptedOut);

        //OutputStream compressedData = encryptedOut;

        PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(
                new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(pass));
        PGPSignatureGenerator sGen = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(
                pgpSec.getPublicKey().getAlgorithm(), PGPUtil.SHA1).setProvider("BC"));
        sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
        Iterator it = pgpSec.getPublicKey().getUserIDs();
        if (it.hasNext()) {
            PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
            spGen.setSignerUserID(false, (String) it.next());
            sGen.setHashedSubpackets(spGen.generate());
        }
        //BCPGOutputStream bOut = new BCPGOutputStream(compressedData);
        sGen.generateOnePassVersion(false).encode(compressedData); // bOut

        File file = new File(fileName);
        PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
        OutputStream lOut = lGen.open(compressedData, PGPLiteralData.BINARY, file.getName(), new Date(),
                                      new byte[BUFFER_SIZE]); //bOut
        FileInputStream fIn = new FileInputStream(file);
        int ch;

        while ((ch = fIn.read()) >= 0) {
            lOut.write(ch);
            sGen.update((byte) ch);
        }

        fIn.close();
        lOut.close();
        lGen.close();

        sGen.generate().encode(compressedData);

        //bOut.close();

        comData.close();
        compressedData.close();

        encryptedOut.close();
        encGen.close();

        if (armor) {
            out.close();
        }
    } catch (PGPException e) {
        System.err.println(e);
        if (e.getUnderlyingException() != null) {
            e.getUnderlyingException().printStackTrace();
        }
    } catch (SignatureException e) {
        System.err.println(e);
    }
}

解密代码:

public static void decryptFile(InputStream in, InputStream keyIn, char[] passwd, OutputStream fOut, InputStream publicKeyIn) throws IOException, NoSuchProviderException, 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<?> it = enc.getEncryptedDataObjects();
    PGPPrivateKey sKey = null;
    PGPPublicKeyEncryptedData pbe = null;
    PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyIn));

    while (sKey == null && it.hasNext()) {
        pbe = (PGPPublicKeyEncryptedData) it.next();
        sKey = PGPTools.findSecretKey(pgpSec, pbe.getKeyID(), passwd);
    }

    if (sKey == null) {
        throw new IllegalArgumentException("secret key for message not found.");
    }

    InputStream clear = pbe.getDataStream(
            new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(sKey));

    PGPObjectFactory plainFact = new PGPObjectFactory(clear);

    Object message = null;

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

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

    while (message != null) {
        log.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);
            log.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();
                        log.trace("Signed by {}", userId);
                    }
                    log.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();
    }
}

作为参考,PGPTools.findSecretKey是这样做的:

public static PGPPrivateKey findSecretKey(InputStream keyIn, long keyID, char[] pass)
        throws IOException, PGPException {
    PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyIn));
    PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);
    if (pgpSecKey == null) return null;

    PBESecretKeyDecryptor decryptor = new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass);
    return pgpSecKey.extractPrivateKey(decryptor);
}
票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6827725

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档