2

我正在尝试使用 BouncyCastle 库创建签名和加密的消息,然后在命令行上针对 gpg 进行测试以确认它是否有效。然而,虽然它显示了一条看起来不错的 PGP 消息,但 gpg 在解密它时遇到了麻烦。

Java代码:

public class main {

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

        BcPGPDataEncryptorBuilder dataEncryptor = new BcPGPDataEncryptorBuilder(PGPEncryptedData.CAST5);
        dataEncryptor.setWithIntegrityPacket(true);
        dataEncryptor.setSecureRandom(new SecureRandom());

        PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator(dataEncryptor);
        encryptedDataGenerator.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(publicKey));

        OutputStream encryptedOut = encryptedDataGenerator.open(out, 4096);

        PGPCompressedDataGenerator compressedDataGenerator = new PGPCompressedDataGenerator(PGPCompressedData.UNCOMPRESSED);
        OutputStream compressedOut = compressedDataGenerator.open(encryptedOut, new byte[4096]);

        PGPContentSignerBuilder signerBuilder = new BcPGPContentSignerBuilder(publicKey.getAlgorithm(), HashAlgorithmTags.SHA1);

        PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(signerBuilder);
        signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, secretKey);

        boolean firstTime = true;
        Iterator<String> it = publicKey.getUserIDs();
        while (it.hasNext() && firstTime) {
            PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
            spGen.setSignerUserID(false, it.next());
            signatureGenerator.setHashedSubpackets(spGen.generate());
            firstTime = false;
        }
        signatureGenerator.generateOnePassVersion(false).encode(compressedOut);

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

        in.close();
        signatureGenerator.generate().encode(compressedOut);
        compressedDataGenerator.close();
        encryptedDataGenerator.close();
        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 {
            RSAKeyPairGenerator kpg = new RSAKeyPairGenerator();
            kpg.init(new RSAKeyGenerationParameters(BigInteger.valueOf(0x10001), new SecureRandom(), 1024, 90));
            BcPGPKeyPair kp = new BcPGPKeyPair(PGPPublicKey.RSA_GENERAL, kpg.generateKeyPair(), new Date());

            ByteArrayInputStream bais = new ByteArrayInputStream(inBytes);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            ArmoredInputStream ais = new ArmoredInputStream(new ByteArrayInputStream(PGPPublicKeyString.getBytes()));

            PGPPublicKeyRing pub = (PGPPublicKeyRing) new PGPObjectFactory(ais).nextObject();

            signEncryptMessage(bais, baos, pub.getPublicKey(), kp.getPrivateKey());

            System.out.println(new String(baos.toByteArray()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static final String PGPPublicKeyString = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
            + "Version: GnuPG v2.0.19 (GNU/Linux)\n"
            + "\n"
            + "mQENBFJLq9IBCADvxNEfagIpxX+8bgXqKKxhjvT0c5WbgkJFyIP8LzkAwTrtQWiT\n"
            + "+5kpIi3xxf94zz4EyuDF5bsEwIJRNvamqcSARxvlEh4U2mTxafl8D7bPhyi476fZ\n"
            + "iFQTwOrK6lAtEboSE+lRMUoB04Lmh0IluhWmKumA6vOI7Mlg0JMbdS9G27kSrhBq\n"
            + "/TfHzQmjbt5WsunKagetzAFM+PXsceD1Yg69GPkRluuXs5LsmSdMpMT7wcK+sZgI\n"
            + "v9+3DbXRxdTQLUWL0g1yE58vMTlbiQ7z5i1jMVMq1YSYmThEW+cnoRmUUsle99ly\n"
            + "IX6IE0gvMySYxIaXTx9LRE538bD2E4UN9bIrABEBAAG0GXJlYWwgbmFtZSA8ZW1h\n"
            + "aWxAYWRkcmVzcz6JATkEEwECACMFAlJLq9ICGwMHCwkIBwMCAQYVCAIJCgsEFgID\n"
            + "AQIeAQIXgAAKCRD/zlUK7kqMk8XGCADMxe3WAUdd+qg4gAL5s+F/ziPozV8cVNP+\n"
            + "ThCHMvNkhoCYswzc30YcGAAsttvgYq7RlyG5yFdXFbo8wMEdDS6rQ72Ya7atNqKN\n"
            + "CB8VV3e87iN+Nv66HyZ59++d0GNO+yFvebmJoyhI2qZ05ng0m9ApZMpCUflhreXE\n"
            + "8+bGCg4fDECmOPnzbx2W68nFFXJEP8M7Bk8bD62Jtxto/hjg12Sv3HCbQMahR3mH\n"
            + "eTIHQUbySAQYBrEyshiv1Rcq+VDAJjO6EtkhxSo0w6T/FI475EdVg45G49wZ/FuX\n"
            + "FmuRqzLT5HGICaICQVxvvcrQ0c5WNwN0lnomoGOxxU73z810L74VuQENBFJLq9IB\n"
            + "CADevC5hdZ6IC8Cq773YsEME6QzIvHwsMVFb3IuUd7h/ZgglGwer6RwPl6lzF7w3\n"
            + "hiFVNysrQ542yEmB3gYk1ha/IVl/+OQg9DiNwN2e2Z3sp7vqapi42Qnbbt4HyQUY\n"
            + "di7l8uQzhEbtuvbKX2w1/P2EF/jLXOu9lSz4ZltElt39IgWejYkpLwVO3b3qpt7e\n"
            + "fuC9nvy12rW7iSUg+czqB16OdO7qKT1xvrAuxTT0LsJpHO1xQt91II8vNOxLSOft\n"
            + "RnX8097Zl0B7UWNTsPeecYbenmcLRTWNbzZaPMbMqEgUYqQEXJerBUIIom+lhPhm\n"
            + "EUtcPdioBXZs0OrbDp1vvVIbABEBAAGJAR8EGAECAAkFAlJLq9ICGwwACgkQ/85V\n"
            + "Cu5KjJM5iAf+OAkj/H6+SuRif356KlZFWjSzOdVtQvV96DbRWq3M18owK8Vq+7ee\n"
            + "wfGFNlBBnnqH4rYyqQUvac+358A0M+1lKdZXHZTLmpi48NeXUGe3AffTaFq7uOJr\n"
            + "P/IvV+06hRBMlAzuwMswG6hFQ9hjIGhas8lImJZZiuFaIauhCOHKe7/Ai6qLw4F6\n"
            + "7+i6QzExeeVmyoEBGqGA1KKmNJgZSq53X3T6yOQmXmAADj7wh1YdWh1r2dHXPc14\n"
            + "L1zehpW1497Dj5Fi4FCNxaKp9NEnIM9Cvv+2XN8gP//R7q0Tia2J6uxDRmMbtFK2\n"
            + "xG2RMc1kGXlWvre1qNASvr2ru7lQoQU8Iw==\n"
            + "=IsmN\n"
            + "-----END PGP PUBLIC KEY BLOCK-----\n";
}

和 gpg 命令行输出:

$ gpg -vvv -d test2
gpg: using character set `utf-8'
gpg: armor: BEGIN PGP MESSAGE
Version: BCPG v1.49
:pubkey enc packet: version 3, algo 1, keyid FFCE550AEE4A8C93
    data: [2048 bits]
gpg: armor header: 
gpg: public key is EE4A8C93

You need a passphrase to unlock the secret key for
user: "real name <email@address>"
2048-bit RSA key, ID EE4A8C93, created 2013-10-02

gpg: public key encrypted data: good DEK
:encrypted data packet:
    length: 4129
    mdc_method: 2
gpg: encrypted with 2048-bit RSA key, ID EE4A8C93, created 2013-10-02
      "real name <email@address>"
gpg: CAST5 encrypted data
:trust packet: flag=e8 sigcache=00
gpg: ring trust w/o key
gpg: mdc_packet with invalid encoding
gpg: decryption failed: Invalid packet

任何帮助,将不胜感激。

干杯

拉莫

4

1 回答 1

1

邓肯琼斯在评论中让我走上了正确的道路。这是其他可能需要它的人的结果函数。

public void signEncryptMessage(InputStream in, OutputStream out, String name) throws IOException, PGPException, SignatureException {
        out = new ArmoredOutputStream(out);

        PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(new JcePGPDataEncryptorBuilder(SYMM_ALG).setWithIntegrityPacket(true).setSecureRandom(rand).setProvider(PROVIDER));
        encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(keys.get(name)).setProvider(PROVIDER));

        OutputStream encryptedOut = encGen.open(out, new byte[BUFFER_SIZE]);
        OutputStream compressedData = new PGPCompressedDataGenerator(COMP_ALG).open(encryptedOut);

        PGPSignatureGenerator sGen = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(kp.getPrivateKey().getPublicKeyPacket().getAlgorithm(), HASH_ALG).setProvider(PROVIDER));
        sGen.init(PGPSignature.BINARY_DOCUMENT, kp.getPrivateKey());
        sGen.generateOnePassVersion(false).encode(compressedData);

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

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

        in.close();

        finalOut.close();
        sGen.generate().encode(compressedData);
        compressedData.close();
        encryptedOut.close();
        out.close();
    }

现在开始解密!

于 2013-10-03T03:36:22.750 回答