使用 Java 中的 PGP BouncyCastle 库加密文件大小

问题描述

我有以下非常标准的代码,用于在 PGP 中使用 BouncyCastle 库加密文件

        String publicKeyString = Files.readString(Paths.get(PUBLIC_KEY_PATH),StandardCharsets.UTF_8);
        String privateKeyString = Files.readString(Paths.get(PRIVATE_KEY_PATH),StandardCharsets.UTF_8);

        Security.addProvider(new BouncyCastleProvider());

        File plainFile = new File(PLAIN_FILE);
        File encryptedFile = new File(ENCRYPTED_FILE);

        PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator(
                new JcePGPDataEncryptorBuilder(CAST5)
                        .setWithIntegrityPacket(true)
                        .setSecureRandom(new SecureRandom())
                        .setProvider("BC"));

        final PGPPublicKey publicKey = readPublicKey(IoUtils.toInputStream(publicKeyString,StandardCharsets.UTF_8));
        encryptedDataGenerator.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(publicKey).setProvider("BC"));

        OutputStream encOutStream = encryptedDataGenerator.open(new FileOutputStream(encryptedFile),new byte[BUFFER_SIZE]);

        PGPCompressedDataGenerator cData = new PGPCompressedDataGenerator(ZIP,BEST_SPEED);

        OutputStream cDataOut = cData.open(encOutStream,new byte[BUFFER_SIZE]);

        PGPV3SignatureGenerator sGen = getPgpSignatureGenerator(privateKeyString,PASSWORD.tochararray());

        BCPGOutputStream bOut = new BCPGOutputStream(cDataOut);

        sGen.generateOnePassversion(false).encode(bOut);
        PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
        OutputStream lOut = lGen.open(bOut,BINARY,"plain.txt.unencrypted",new Date(),new byte[BUFFER_SIZE]);

        copy(new FileInputStream(plainFile),lOut,sGen);

        lGen.close();

        sGen.generate().encode(bOut);

        cData.close();
        encOutStream.close();
        encryptedDataGenerator.close();

支持方法

    public static PGPPublicKey readPublicKey(InputStream input) throws IOException,PGPException {

        final PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(getDecoderStream(input),new JcaKeyFingerprintCalculator());
        final Iterator keyRingIter = pgpPub.getKeyRings();

        while (keyRingIter.hasNext()) {
            final PGPPublicKeyRing keyRing = (PGPPublicKeyRing) keyRingIter.next();
            final Iterator keyIter = keyRing.getPublicKeys();

            while (keyIter.hasNext()) {
                final PGPPublicKey key = (PGPPublicKey) keyIter.next();

                if (key.isEncryptionKey()) {
                    System.out.println("found " + key.getBitStrength() + " bit public key");
                    return key;
                }
            }
        }
        throw new IllegalArgumentException("Can't find encryption key in key ring.");
    }

    public static PGPV3SignatureGenerator getPgpSignatureGenerator(String keyIn,char[] pass) throws IOException,PGPException {

        PGPSecretKey pgpSec = readSecretKey(keyIn);
        PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(pass));
        PGPV3SignatureGenerator sGen = new PGPV3SignatureGenerator(new JcaPGPContentSignerBuilder(pgpSec.getPublicKey().getAlgorithm(),PGPUtil.SHA256).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());
        }
        return sGen;
    }

    public static void copy(InputStream in,OutputStream out,PGPV3SignatureGenerator sGen) throws IOException,NoSuchAlgorithmException {

        try(out) {
            byte[] buffer = new byte[BUFFER_SIZE];
            int bytesRead =  -1;

            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer,bytesRead);
                sGen.update(buffer,bytesRead);
            }

            out.flush();
        }
    }

一个文件,每次生成的加密文件大小都不一样。这会导致在验证外部分发的校验和时出现问题。

我已尝试更改 BUFFER_SIZE,但仍然存在相同的问题。此外,尝试更改标志 WithIntegrityPacket 并使用 SecureRandom 删除 JcePGPDataEncryptorBuilder

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)