MDC packet in inter-operation with openpgpjs

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

MDC packet in inter-operation with openpgpjs

Lou Wynn

Hi,

I have a Java server app that uses BC to encrypt data. The client running in a browser uses the OpenPGPJS (v3.x) to decrypt it. In the default mode I get this error from OpenPGPJS:

Error decrypting message: Decryption failed due to missing MDC.
    at SymmetricallyEncrypted._callee$ (openpgp.js:49622)
    at tryCatch (openpgp.js:26630)
    at Generator.invoke [as _invoke] (openpgp.js:26864)
    at Generator.prototype.(anonymous function) [as next] (chrome-extension://dmeinfklhaiihnaiiaiimanofkcmefpa/background.js:28478:21)
    at step (openpgp.js:4012)
    at openpgp.js:4030
    at new Promise (<anonymous>)
    at new F (openpgp.js:9832)
    at SymmetricallyEncrypted.<anonymous> (openpgp.js:4009)
    at SymmetricallyEncrypted.decrypt (openpgp.js:49638)


If I disable the MDC feature by setting "openpgp.config.ignore_mdc_error = true;" then the error is gone.

When I looked at my BC code, I found that the PGPEncryptedDataGenerator does add a MDC packet in its close() function, which reads like this:

// hand code a mod detection packet
//
BCPGOutputStream bOut = new BCPGOutputStream(genOut, PacketTags.MOD_DETECTION_CODE, 20);


Could anyone help me point out where I did wrong? My BC code that encrypts is as follows.

byte[] signEncrypt(final PGPPrivateKey priKey,
            final PGPPublicKey encKey, final byte[] bytes) {
    try {
            // Prepare to sign
            PGPSignatureGenerator sigG = null;
            if (priKey != null) {
                sigG = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(
                        priKey.getPublicKeyPacket().getAlgorithm(), KeyGen.SignatureHash)
                                .setProvider(Provider));
                sigG.init(PGPSignature.BINARY_DOCUMENT, priKey);
//                log.info("Signing key is {}", Long.toHexString(priKey.getKeyID()));
            }

            // Encrypt
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(
                    new JcePGPDataEncryptorBuilder(EncAlg).setSecureRandom(Random)
                            .setProvider(Provider));
            encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey)
                    .setProvider(Provider));
            OutputStream encOut = encGen.open(bout, new byte[BufferSize]);
            BCPGOutputStream bcOut = null;

            // Compress data before encryption
            if (pgpCompressed) {
                PGPCompressedDataGenerator compG = new PGPCompressedDataGenerator(
                        PGPCompressedData.ZIP);
                bcOut = new BCPGOutputStream(compG.open(encOut));
            }
            else {
                bcOut = new BCPGOutputStream(encOut);
            }

            if (sigG != null)
                sigG.generateOnePassVersion(false).encode(bcOut);

            // Write to pgp object
            PGPLiteralDataGenerator literalG = new PGPLiteralDataGenerator();
            OutputStream ldOut = literalG.open(bcOut, PGPLiteralData.BINARY,
                    PGPLiteralData.CONSOLE, bytes.length, new Date());

            ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
            byte[] buf = new byte[BufferSize];
            for (int n = 0; (n = bIn.read(buf)) >= 0;) {
                ldOut.write(buf, 0, n);
                if (sigG != null)
                    sigG.update(buf, 0, n);
            }

            if (sigG != null) {
                sigG.generate().encode(bcOut);
            }
            ldOut.close();
            bcOut.close();
            encGen.close();

            return bout.toByteArray();
        }
        catch (PGPException | IOException e) {
            throw new CryptoServiceException(e);
        }
    }


-- 
Thanks,
Lou

Reply | Threaded
Open this post in threaded view
|

Re: MDC packet in inter-operation with openpgpjs

David Hook-3

You need to call setWithIntegrityPacket(true) on the JcePGPDataEncryptorBuilder.

Regards,

David

On 08/08/18 16:11, Lou Wynn wrote:

Hi,

I have a Java server app that uses BC to encrypt data. The client running in a browser uses the OpenPGPJS (v3.x) to decrypt it. In the default mode I get this error from OpenPGPJS:

Error decrypting message: Decryption failed due to missing MDC.
    at SymmetricallyEncrypted._callee$ (openpgp.js:49622)
    at tryCatch (openpgp.js:26630)
    at Generator.invoke [as _invoke] (openpgp.js:26864)
    at Generator.prototype.(anonymous function) [as next] (chrome-extension://dmeinfklhaiihnaiiaiimanofkcmefpa/background.js:28478:21)
    at step (openpgp.js:4012)
    at openpgp.js:4030
    at new Promise (<anonymous>)
    at new F (openpgp.js:9832)
    at SymmetricallyEncrypted.<anonymous> (openpgp.js:4009)
    at SymmetricallyEncrypted.decrypt (openpgp.js:49638)


If I disable the MDC feature by setting "openpgp.config.ignore_mdc_error = true;" then the error is gone.

When I looked at my BC code, I found that the PGPEncryptedDataGenerator does add a MDC packet in its close() function, which reads like this:

// hand code a mod detection packet
//
BCPGOutputStream bOut = new BCPGOutputStream(genOut, PacketTags.MOD_DETECTION_CODE, 20);


Could anyone help me point out where I did wrong? My BC code that encrypts is as follows.

byte[] signEncrypt(final PGPPrivateKey priKey,
            final PGPPublicKey encKey, final byte[] bytes) {
    try {
            // Prepare to sign
            PGPSignatureGenerator sigG = null;
            if (priKey != null) {
                sigG = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(
                        priKey.getPublicKeyPacket().getAlgorithm(), KeyGen.SignatureHash)
                                .setProvider(Provider));
                sigG.init(PGPSignature.BINARY_DOCUMENT, priKey);
//                log.info("Signing key is {}", Long.toHexString(priKey.getKeyID()));
            }

            // Encrypt
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(
                    new JcePGPDataEncryptorBuilder(EncAlg).setSecureRandom(Random)
                            .setProvider(Provider));
            encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey)
                    .setProvider(Provider));
            OutputStream encOut = encGen.open(bout, new byte[BufferSize]);
            BCPGOutputStream bcOut = null;

            // Compress data before encryption
            if (pgpCompressed) {
                PGPCompressedDataGenerator compG = new PGPCompressedDataGenerator(
                        PGPCompressedData.ZIP);
                bcOut = new BCPGOutputStream(compG.open(encOut));
            }
            else {
                bcOut = new BCPGOutputStream(encOut);
            }

            if (sigG != null)
                sigG.generateOnePassVersion(false).encode(bcOut);

            // Write to pgp object
            PGPLiteralDataGenerator literalG = new PGPLiteralDataGenerator();
            OutputStream ldOut = literalG.open(bcOut, PGPLiteralData.BINARY,
                    PGPLiteralData.CONSOLE, bytes.length, new Date());

            ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
            byte[] buf = new byte[BufferSize];
            for (int n = 0; (n = bIn.read(buf)) >= 0;) {
                ldOut.write(buf, 0, n);
                if (sigG != null)
                    sigG.update(buf, 0, n);
            }

            if (sigG != null) {
                sigG.generate().encode(bcOut);
            }
            ldOut.close();
            bcOut.close();
            encGen.close();

            return bout.toByteArray();
        }
        catch (PGPException | IOException e) {
            throw new CryptoServiceException(e);
        }
    }


-- 
Thanks,
Lou