简体   繁体   中英

Bouncy Castle PGP sign and encrypt in one pass?

I'm looking for an implementation of Bouncy Castle PGP 'sign and encrypt'. Ideally in one operation, if that makes any difference.

I've taken the encrypt example and the signing example and tried to turn it into a 'one pass' encrypt and sign operation.

I see this relatively dated implementation Boncode . It seems to show that the two operations are just linked together.

I'm not getting the consumer to decrypt the code. The signature seems to be able to be verified. This is true whether I use the merged operations or separate encrypt then sign.

Is there a better Bouncy Castle PGP implementation?

Here is my current implementation of a one pass, Bouncy Castle PGP encrypt+sign. The signature seems to verify, but the payload is not decrypted.

public class SinglePassSignedEncryptedFileProcessor {
private static final Logger logger = LoggerFactory.getLogger(SinglePassSignedEncryptedFileProcessor.class);

/*
 * This is the primary function that will create encrypt a file and sign it
 * with a one pass signature. This leans on an C# example by John Opincar
 * @author Bilal Soylu
 * @param targetFileName
 *            -- file name on drive systems that will contain encrypted content
 * @param embeddedFileName
 *            -- the original file name before encryption
 * @param secretKeyRingInputStream
 *            -- Private Key Ring File
 * @param targetFileStream
 *            -- The stream for the encrypted target file
 * @param secretKeyPassphrase
 *            -- The private key password for the key retrieved from
 *            collection used for signing
 * @param signPublicKeyInputStream
 *            -- the public key of the target recipient to be used to
 *            encrypt the file
 * @throws Exception
 */
public void encryptOnePassSign(
        String fileName,
        InputStream keyIn,
        OutputStream out,
        char[] pass,
        PGPPublicKey encryptionKey,
        boolean armor,
        boolean withIntegrityCheck,
        String providerName)
        throws IOException, NoSuchAlgorithmException, NoSuchProviderException, PGPException, SignatureException {
    if (armor) {
        out = new ArmoredOutputStream(out);
    }

    // Compress
    byte[] bytes = PGPEncryptUtil.compressFile(fileName, CompressionAlgorithmTags.ZIP);

    // Encryption process.
    PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(
            new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("BC"));

    encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encryptionKey).setProvider("BC"));

    ByteArrayOutputStream encryptedOutputStream = new ByteArrayOutputStream();
    OutputStream encryptedOut = encGen.open(encryptedOutputStream, bytes);
    encryptedOut.write(bytes);
    encryptedOut.close();
    byte[] bytesEncrypted = encryptedOutputStream.toByteArray();
    encryptedOutputStream.close();

    // Signing process.
    PGPSecretKey pgpSec = PGPEncryptUtil.readSecretKey(keyIn);
    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());
    }

    PGPCompressedDataGenerator cGen = new PGPCompressedDataGenerator(
            PGPCompressedData.UNCOMPRESSED);

    // Write to the output stream.
    BCPGOutputStream bOut = new BCPGOutputStream(cGen.open(out));
    sGen.generateOnePassVersion(false).encode(bOut);

    File file = new File(fileName);
    PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
    // file is encoding name.
    Date lastModified = new Date(file.lastModified());
    OutputStream lOut = lGen.open(bOut, PGPLiteralData.BINARY, fileName, lastModified, bytesEncrypted);


    //FileInputStream fIn = new FileInputStream(file);
    //int ch;

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

    // ?
    lGen.close();

    sGen.generate().encode(bOut);
    cGen.close();

    if (armor) {
        out.close();
    }
    // close everything down we are done
    /*
    literalOut.close();
    literalDataGenerator.close();
    signatureGenerator.generate().encode(compressedOut);
    compressedOut.close();
    compressedDataGenerator.close();
    encryptedOut.close();
    encryptedDataGenerator.close();
     */

    // if (armor) targetFileStream.close();

}
}

Latest answer is to use BouncyGPG

Works as per the test cases. Kotlin

  val encryptionStream = BouncyGPG
            .encryptToStream()
            .withConfig(keyringConfig)
            .withStrongAlgorithms()
            .toRecipient("recipient@example.com")
            .andSignWith("sender@example.com")
            .armorAsciiOutput()
            .andWriteTo(cipherText)

    encryptionStream.write(expectedPlaintext)
    encryptionStream.close()
    cipherText.close()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM