From eb9d991ea9129c8a25eaf23ed50f3fea198bf32c Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 15 May 2017 14:52:53 +0200 Subject: [PATCH] add unit tests for insecure decrypt operations --- .../keychain/pgp/PgpSignEncryptData.java | 48 ++-- .../keychain/pgp/PgpSignEncryptOperation.java | 2 +- .../keychain/pgp/SecurityProblem.java | 1 - .../keychain/pgp/PgpEncryptDecryptTest.java | 271 ++++++++++-------- .../keychain/pgp/UncachedKeyringTest.java | 2 +- .../support/KeyringTestingHelper.java | 3 + .../test-ciphertexts/algo_des.pgp.asc | 13 + .../resources/test-ciphertexts/no_mdc.pgp.asc | 13 + .../test-ciphertexts/rsa_1024.pgp.asc | 11 + .../test-keys/encrypt_decrypt_key_1.sec | Bin 0 -> 1192 bytes .../test-keys/encrypt_decrypt_key_2.sec | Bin 0 -> 922 bytes .../encrypt_decrypt_key_insecure.sec | Bin 0 -> 2227 bytes 12 files changed, 208 insertions(+), 156 deletions(-) create mode 100644 OpenKeychain/src/test/resources/test-ciphertexts/algo_des.pgp.asc create mode 100644 OpenKeychain/src/test/resources/test-ciphertexts/no_mdc.pgp.asc create mode 100644 OpenKeychain/src/test/resources/test-ciphertexts/rsa_1024.pgp.asc create mode 100644 OpenKeychain/src/test/resources/test-keys/encrypt_decrypt_key_1.sec create mode 100644 OpenKeychain/src/test/resources/test-keys/encrypt_decrypt_key_2.sec create mode 100644 OpenKeychain/src/test/resources/test-keys/encrypt_decrypt_key_insecure.sec diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptData.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptData.java index c4e569d24..74052e300 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptData.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptData.java @@ -27,28 +27,26 @@ import org.sufficientlysecure.keychain.util.Passphrase; public class PgpSignEncryptData implements Parcelable { - - protected String mVersionHeader = null; - protected boolean mEnableAsciiArmorOutput = false; - protected int mCompressionAlgorithm = CompressionAlgorithmTags.UNCOMPRESSED; - protected long[] mEncryptionMasterKeyIds = null; - protected Passphrase mSymmetricPassphrase = null; - protected int mSymmetricEncryptionAlgorithm = PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT; - protected long mSignatureMasterKeyId = Constants.key.none; - protected Long mSignatureSubKeyId = null; - protected int mSignatureHashAlgorithm = PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT; - protected long mAdditionalEncryptId = Constants.key.none; - protected String mCharset; - protected boolean mCleartextSignature; - protected boolean mDetachedSignature = false; - protected boolean mHiddenRecipients = false; - protected boolean mIntegrityProtected = true; - protected boolean mAddBackupHeader = false; + private String mVersionHeader = null; + private boolean mEnableAsciiArmorOutput = false; + private int mCompressionAlgorithm = CompressionAlgorithmTags.UNCOMPRESSED; + private long[] mEncryptionMasterKeyIds = null; + private Passphrase mSymmetricPassphrase = null; + private int mSymmetricEncryptionAlgorithm = PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT; + private long mSignatureMasterKeyId = Constants.key.none; + private Long mSignatureSubKeyId = null; + private int mSignatureHashAlgorithm = PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT; + private long mAdditionalEncryptId = Constants.key.none; + private String mCharset; + private boolean mCleartextSignature; + private boolean mDetachedSignature = false; + private boolean mHiddenRecipients = false; + private boolean mAddBackupHeader = false; public PgpSignEncryptData(){ } - PgpSignEncryptData(Parcel source) { + private PgpSignEncryptData(Parcel source) { ClassLoader loader = getClass().getClassLoader(); mVersionHeader = source.readString(); @@ -65,7 +63,6 @@ public class PgpSignEncryptData implements Parcelable { mCleartextSignature = source.readInt() == 1; mDetachedSignature = source.readInt() == 1; mHiddenRecipients = source.readInt() == 1; - mIntegrityProtected = source.readInt() == 1; mAddBackupHeader = source.readInt() == 1; } @@ -95,7 +92,6 @@ public class PgpSignEncryptData implements Parcelable { dest.writeInt(mCleartextSignature ? 1 : 0); dest.writeInt(mDetachedSignature ? 1 : 0); dest.writeInt(mHiddenRecipients ? 1 : 0); - dest.writeInt(mIntegrityProtected ? 1 : 0); dest.writeInt(mAddBackupHeader ? 1 : 0); } @@ -220,18 +216,6 @@ public class PgpSignEncryptData implements Parcelable { return this; } - public boolean isIntegrityProtected() { - return mIntegrityProtected; - } - - /** - * Only use for testing! Never disable integrity protection! - */ - public PgpSignEncryptData setIntegrityProtected(boolean integrityProtected) { - this.mIntegrityProtected = integrityProtected; - return this; - } - public PgpSignEncryptData setAddBackupHeader(boolean addBackupHeader) { this.mAddBackupHeader = addBackupHeader; return this; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java index 28cc15267..3082ee605 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -321,7 +321,7 @@ public class PgpSignEncryptOperation extends BaseOperation + * Copyright (C) 2014-2017 Vincent Breitmoser * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,11 +18,23 @@ package org.sufficientlysecure.keychain.pgp; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.PrintStream; +import java.security.Security; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; + import org.apache.tools.ant.util.StringUtils; import org.bouncycastle.bcpg.BCPGInputStream; import org.bouncycastle.bcpg.Packet; import org.bouncycastle.bcpg.PacketTags; +import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; import org.bouncycastle.bcpg.PublicKeyEncSessionPacket; +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.bcpg.sig.KeyFlags; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.Assert; @@ -38,13 +50,13 @@ import org.robolectric.shadows.ShadowLog; import org.sufficientlysecure.keychain.KeychainTestRunner; import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; -import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult; import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; +import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureBitStrength; +import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureEncryptionAlgorithm; +import org.sufficientlysecure.keychain.pgp.SecurityProblem.MissingMdc; import org.sufficientlysecure.keychain.provider.KeyWritableRepository; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; -import org.sufficientlysecure.keychain.service.ChangeUnlockParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; -import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType; @@ -55,28 +67,18 @@ import org.sufficientlysecure.keychain.util.Passphrase; import org.sufficientlysecure.keychain.util.ProgressScaler; import org.sufficientlysecure.keychain.util.TestingUtils; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.security.Security; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; - import static org.hamcrest.core.AnyOf.anyOf; import static org.hamcrest.core.Is.is; +@SuppressWarnings("WeakerAccess") @RunWith(KeychainTestRunner.class) public class PgpEncryptDecryptTest { static Passphrase mSymmetricPassphrase = TestingUtils.genPassphrase(true); static UncachedKeyRing mStaticRing1, mStaticRing2, mStaticRingInsecure; - static Passphrase mKeyPhrase1 = TestingUtils.genPassphrase(true); - static Passphrase mKeyPhrase2 = TestingUtils.genPassphrase(true); -// static Passphrase mKeyPhraseInsecure = TestingUtils.genPassphrase(true); + static Passphrase mKeyPhrase1, mKeyPhrase2; static PrintStream oldShadowStream; @@ -86,65 +88,64 @@ public class PgpEncryptDecryptTest { oldShadowStream = ShadowLog.stream; // ShadowLog.stream = System.out; - PgpKeyOperation op = new PgpKeyOperation(null); + /* generation parameters: - { - SaveKeyringParcel parcel = new SaveKeyringParcel(); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); - parcel.mAddUserIds.add("bloom"); - parcel.setNewUnlock(new ChangeUnlockParcel(mKeyPhrase1)); + SaveKeyringParcel parcel = new SaveKeyringParcel(); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); + parcel.mAddUserIds.add("bloom"); + parcel.setNewUnlock(new ChangeUnlockParcel(new Passphrase("RsKrW^raOPcnQ=ZJr-pP"))); - PgpEditKeyResult result = op.createSecretKeyRing(parcel); - Assert.assertTrue("initial test key creation must succeed", result.success()); - Assert.assertNotNull("initial test key creation must succeed", result.getRing()); + PgpEditKeyResult result = op.createSecretKeyRing(parcel); + */ - mStaticRing1 = result.getRing(); - } + mKeyPhrase1 = new Passphrase("RsKrW^raOPcnQ=ZJr-pP"); + mStaticRing1 = KeyringTestingHelper.readRingFromResource("/test-keys/encrypt_decrypt_key_1.sec"); - { - SaveKeyringParcel parcel = new SaveKeyringParcel(); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); - parcel.mAddUserIds.add("belle"); - parcel.setNewUnlock(new ChangeUnlockParcel(mKeyPhrase2)); + /* generation: + SaveKeyringParcel parcel = new SaveKeyringParcel(); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.CERTIFY_OTHER, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.ECDSA, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.SIGN_DATA, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.ECDH, 0, SaveKeyringParcel.Curve.NIST_P256, KeyFlags.ENCRYPT_COMMS, 0L)); + parcel.mAddUserIds.add("belle"); + parcel.setNewUnlock(new ChangeUnlockParcel(new Passphrase("x"))); - PgpEditKeyResult result = op.createSecretKeyRing(parcel); - Assert.assertTrue("initial test key creation must succeed", result.success()); - Assert.assertNotNull("initial test key creation must succeed", result.getRing()); + PgpKeyOperation op = new PgpKeyOperation(new ProgressScaler()); + PgpEditKeyResult result = op.createSecretKeyRing(parcel); + new FileOutputStream("/tmp/key.sec").write(result.getRing().getEncoded()); + */ - mStaticRing2 = result.getRing(); - } + mKeyPhrase2 = new Passphrase("x"); + mStaticRing2 = KeyringTestingHelper.readRingFromResource("/test-keys/encrypt_decrypt_key_2.sec"); -// { -// // insecure (1024 bit) RSA key -// SaveKeyringParcel parcel = new SaveKeyringParcel(); -// parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( -// Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L)); -// parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( -// Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L)); -// parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( -// Algorithm.RSA, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L)); -// parcel.mAddUserIds.add("eve"); -// parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhraseInsecure); -// -// PgpEditKeyResult result = op.createSecretKeyRing(parcel); -// Assert.assertTrue("initial test key creation must succeed", result.success()); -// Assert.assertNotNull("initial test key creation must succeed", result.getRing()); -// -// mStaticRingInsecure = result.getRing(); -// } + /* generation parameters (insecure key, requires removal of of security checks!): + SaveKeyringParcel parcel = new SaveKeyringParcel(); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.RSA, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L)); + parcel.mAddUserIds.add("eve"); + parcel.setNewUnlock(new ChangeUnlockParcel(new Passphrase(""))); + + PgpEditKeyResult result = new PgpKeyOperation(new ProgressScaler()).createSecretKeyRing(parcel); + Assert.assertTrue("initial test key creation must succeed", result.success()); + Assert.assertNotNull("initial test key creation must succeed", result.getRing()); + new FileOutputStream("/tmp/key.sec").write(result.getRing().getEncoded()); + */ + + mStaticRingInsecure = KeyringTestingHelper.readRingFromResource("/test-keys/encrypt_decrypt_key_insecure.sec"); } @Before @@ -157,6 +158,7 @@ public class PgpEncryptDecryptTest { databaseInteractor.saveSecretKeyRing(mStaticRing1, new ProgressScaler()); databaseInteractor.saveSecretKeyRing(mStaticRing2, new ProgressScaler()); + databaseInteractor.saveSecretKeyRing(mStaticRingInsecure, new ProgressScaler()); // ok NOW log verbosely! ShadowLog.stream = System.out; @@ -420,7 +422,7 @@ public class PgpEncryptDecryptTest { InputData data = new InputData(in, in.available()); - PgpSignEncryptData pgpData = new PgpSignEncryptData(); + PgpSignEncryptData pgpData = new PgpSignEncryptData(); // only sign, as cleartext pgpData.setSignatureMasterKeyId(mStaticRing1.getMasterKeyId()); pgpData.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1)); @@ -997,76 +999,73 @@ public class PgpEncryptDecryptTest { } @Test - public void testAsymmetricInsecureEncryptDecrypt() { + public void testAsymmetricSymmetricDesDecrypt() throws Exception { + InputStream in = getResourceAsStream("/test-ciphertexts/algo_des.pgp.asc"); + String plaintext = "dies ist ein plaintext ☭"; - // insecure symmetric algo - subtestInsecureEncryptDecrypt(mStaticRing1, mKeyPhrase1, - PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.DES, true); - // don't use MDC - subtestInsecureEncryptDecrypt(mStaticRing1, mKeyPhrase1, - PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_256, false); - // TODO: test not working! - // insecure key (1024 bit RSA) -// subtestInsecureEncryptDecrypt(mStaticRingInsecure, mKeyPhraseInsecure, -// PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.AES_256, true); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + InputData data = new InputData(in, in.available()); + + PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(null, null, null); + PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(); + DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out); + + + Assert.assertTrue(result.success()); + Assert.assertArrayEquals(out.toByteArray(), plaintext.getBytes()); + Assert.assertEquals(OpenPgpDecryptionResult.RESULT_INSECURE, result.getDecryptionResult().getResult()); + Assert.assertEquals(OpenPgpSignatureResult.RESULT_NO_SIGNATURE, result.getSignatureResult().getResult()); + + InsecureEncryptionAlgorithm symmetricSecurityProblem = + (InsecureEncryptionAlgorithm) result.getSecurityProblem().symmetricSecurityProblem; + Assert.assertEquals((symmetricSecurityProblem).symmetricAlgorithm, SymmetricKeyAlgorithmTags.DES); } - private void subtestInsecureEncryptDecrypt(UncachedKeyRing key, Passphrase passphrase, - int algorithm, boolean isIntegrityProtected) { - String plaintext = "dies ist ein plaintext ☭" + TestingUtils.genPassphrase(true); - byte[] ciphertext; + public void testAsymmetricNoMdcDecrypt() throws Exception { + InputStream in = getResourceAsStream("/test-ciphertexts/no_mdc.pgp.asc"); + String plaintext = "dies ist ein plaintext ☭"; - { // encrypt data with insecure key - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(plaintext.getBytes()); - PgpSignEncryptOperation op = new PgpSignEncryptOperation(RuntimeEnvironment.application, - KeyWritableRepository.createDatabaseReadWriteInteractor(RuntimeEnvironment.application), null); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + InputData data = new InputData(in, in.available()); - InputData data = new InputData(in, in.available()); + PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(null, null, null); + PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(); + DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out); - PgpSignEncryptData pgpData = new PgpSignEncryptData(); - pgpData.setEncryptionMasterKeyIds(new long[]{key.getMasterKeyId()}) - .setSymmetricEncryptionAlgorithm(algorithm) - .setIntegrityProtected(isIntegrityProtected); - PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel(pgpData); + Assert.assertTrue(result.success()); + Assert.assertArrayEquals(out.toByteArray(), plaintext.getBytes()); + Assert.assertEquals(OpenPgpDecryptionResult.RESULT_INSECURE, result.getDecryptionResult().getResult()); + Assert.assertEquals(OpenPgpSignatureResult.RESULT_NO_SIGNATURE, result.getSignatureResult().getResult()); - PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(new Date()), - data, out); - Assert.assertTrue("encryption must succeed", result.success()); + Assert.assertTrue(result.getSecurityProblem().symmetricSecurityProblem instanceof MissingMdc); + } - ciphertext = out.toByteArray(); - } + public void testAsymmetricRsa1024Decrypt() throws Exception { + InputStream in = getResourceAsStream("/test-ciphertexts/rsa_1024.pgp.asc"); + String plaintext = "dies ist ein plaintext ☭"; - { // decryption with provided passphrase should yield insecure status - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayInputStream in = new ByteArrayInputStream(ciphertext); - InputData data = new InputData(in, in.available()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + InputData data = new InputData(in, in.available()); - PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(null, null, null); - PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(); - DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(passphrase), data, out); + PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(null, null, null); + PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(); + DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out); - Assert.assertTrue("decryption with provided passphrase must succeed", result.success()); - Assert.assertArrayEquals("decrypted ciphertext with provided passphrase should equal plaintext", - out.toByteArray(), plaintext.getBytes()); - Assert.assertEquals("decryptionResult should be RESULT_INSECURE", - OpenPgpDecryptionResult.RESULT_INSECURE, result.getDecryptionResult().getResult()); - Assert.assertEquals("signatureResult should be RESULT_NO_SIGNATURE", - OpenPgpSignatureResult.RESULT_NO_SIGNATURE, result.getSignatureResult().getResult()); - CryptoInputParcel cryptoInput = result.getCachedCryptoInputParcel(); - Assert.assertEquals("must have one cached session key", - 1, cryptoInput.getCryptoData().size()); + Assert.assertTrue(result.success()); + Assert.assertArrayEquals(out.toByteArray(), plaintext.getBytes()); + Assert.assertEquals(OpenPgpDecryptionResult.RESULT_INSECURE, result.getDecryptionResult().getResult()); + Assert.assertEquals(OpenPgpSignatureResult.RESULT_NO_SIGNATURE, result.getSignatureResult().getResult()); - OpenPgpMetadata metadata = result.getDecryptionMetadata(); - Assert.assertEquals("filesize must be correct", - out.toByteArray().length, metadata.getOriginalSize()); - - } + InsecureBitStrength encryptionKeySecurityProblem = + (InsecureBitStrength) result.getSecurityProblem().encryptionKeySecurityProblem; + Assert.assertEquals(mStaticRingInsecure.getMasterKeyId(), encryptionKeySecurityProblem.masterKeyId); + Assert.assertEquals(PublicKeyAlgorithmTags.RSA_ENCRYPT, encryptionKeySecurityProblem.algorithm); + Assert.assertEquals(1024, encryptionKeySecurityProblem.bitStrength); } private PgpDecryptVerifyOperation operationWithFakePassphraseCache( @@ -1092,4 +1091,34 @@ public class PgpEncryptDecryptTest { } }; } + + private static InputStream getResourceAsStream(String name) { + return PgpEncryptDecryptTest.class.getResourceAsStream(name); + } + + /* skeleton for generating test data + @Test + public void generateData() throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayInputStream in = new ByteArrayInputStream("dies ist ein plaintext ☭".getBytes()); + + PgpSignEncryptOperation op = new PgpSignEncryptOperation(RuntimeEnvironment.application, + KeyWritableRepository.createDatabaseReadWriteInteractor(RuntimeEnvironment.application), null); + + InputData data = new InputData(in, in.available()); + + PgpSignEncryptData pgpData = new PgpSignEncryptData(); + pgpData.setEncryptionMasterKeyIds(new long[]{ mStaticRingInsecure.getMasterKeyId()}); + + PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel(pgpData); + + PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(new Date()), + data, out); + Assert.assertTrue("encryption must succeed", result.success()); + + ArmoredOutputStream armoredOutputStream = new ArmoredOutputStream(new FileOutputStream("/tmp/rsa_1024.pgp.asc")); + armoredOutputStream.write(out.toByteArray()); + armoredOutputStream.close(); + } + */ } \ No newline at end of file diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java index 486b1f95a..d6d949289 100644 --- a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java +++ b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java @@ -152,7 +152,7 @@ public class UncachedKeyringTest { readRingFromResource("/test-keys/broken_cert_version.asc"); } - UncachedKeyRing readRingFromResource(String name) throws Throwable { + private UncachedKeyRing readRingFromResource(String name) throws Throwable { return UncachedKeyRing.fromStream(UncachedKeyringTest.class.getResourceAsStream(name)).next(); } diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java index 34558b5bf..445376368 100644 --- a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java +++ b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java @@ -364,4 +364,7 @@ public class KeyringTestingHelper { return result; } + public static UncachedKeyRing readRingFromResource(String name) throws Exception { + return UncachedKeyRing.fromStream(KeyringTestingHelper.class.getResourceAsStream(name)).next(); + } } diff --git a/OpenKeychain/src/test/resources/test-ciphertexts/algo_des.pgp.asc b/OpenKeychain/src/test/resources/test-ciphertexts/algo_des.pgp.asc new file mode 100644 index 000000000..f7d8420c0 --- /dev/null +++ b/OpenKeychain/src/test/resources/test-ciphertexts/algo_des.pgp.asc @@ -0,0 +1,13 @@ +-----BEGIN PGP MESSAGE----- +Testcase: encrypted using DES (should be marked insecure) +Plaintext: 'dies ist ein plaintext ☭' + +hH4DGQB0mNo0qa0SAgME9glrSS/q7JAz+wh0WoOydUAVsCS9jaMRx8gBWrx8NJB4 +OcEZnYiKU5Nu14qDkPKpqUwq0l/D2ykvfk3oDerb2jDL2M9j+sy/lWPeaSd7MbWO +8cVKqMaNkXFSDp4V/wRTrj+xnDaZZ2v/OUT3jWZuneGEfgNG/bBLBjduwxICAwQS +Jr1sGq9DUNHkhDXX+t9Y7Z1idE7kr/skjziBP3L1RhIavVtU6sEjDOs/3IAZUgQx +RnU7ITIw0dVrVMPCZ0zWMEG5WZCBCtqdPHfXyESTqR891e5uqAtLf9Og7LIPkwiN +GXNc3r+dm5tcqfALmmwHttJDAYW22pFTOf52358ENWEBIgePFiKXImAXjS/VAVAV +t1OnpO81+BnJDBTrbzbXYy/2wxFMwnqt6HiVLTSTB93p61VFAw== +=4WKW +-----END PGP MESSAGE----- diff --git a/OpenKeychain/src/test/resources/test-ciphertexts/no_mdc.pgp.asc b/OpenKeychain/src/test/resources/test-ciphertexts/no_mdc.pgp.asc new file mode 100644 index 000000000..fb744edc5 --- /dev/null +++ b/OpenKeychain/src/test/resources/test-ciphertexts/no_mdc.pgp.asc @@ -0,0 +1,13 @@ +-----BEGIN PGP MESSAGE----- +Testcase: encrypted and unsigned, without mdc +Plaintext: 'dies ist ein plaintext ☭' + +hH4DGQB0mNo0qa0SAgMEThtzE4S/Y1z03qmQ05p0uydye5zzgFSyefNFmvneu1rh +m7VX0bXfQfnK3QlKtONFzhgzmZLIdo8q6JNP1CtkfTCOjRgcA6sdZA6PbPgAXgoq +CY1Dpt69K+TOzD37jxpzbEyB2S3yEO9VjxJVo6u0JbSEfgNG/bBLBjduwxICAwSU +sILMkNnz3Qz9kSrjNwXR/PcQSdOdt9EI4ei26+Fp+eC6txTo8DC7YMcdXe9XqXoe +xX5DvjhoBOQvCjmeCbeXMDxflR/ygybvZCyzrVxgTs7kkjUalI16saXjkelcF3Kt +WVnLRbVs0+SWMwLt+Nf6HMk0ieELGF6MMR+2AXNC0VY3b3WwJAMWZFsz9P4VG7rP +YiHtyfyVSnXiyaKPzevD3TKaZtse/g== +=sUCU +-----END PGP MESSAGE----- diff --git a/OpenKeychain/src/test/resources/test-ciphertexts/rsa_1024.pgp.asc b/OpenKeychain/src/test/resources/test-ciphertexts/rsa_1024.pgp.asc new file mode 100644 index 000000000..4b41a560e --- /dev/null +++ b/OpenKeychain/src/test/resources/test-ciphertexts/rsa_1024.pgp.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP MESSAGE----- +Testcase: 1024 bit rsa (should be marked insecure) +Plaintext: 'dies ist ein plaintext ☭' + +hIsDUIIrlXQHiJEBA/YiKQH9teIvmGQ057tyUsVplsM68phoS6xG9aMP1DXZsHB3 +a0nzPCJ/s/9Ct9X1VwrFv6gKMZVAjDOvizDpc8Q+R88BMyXxcxTJjg7x4ZIGxLAL +7p7aEBJj243SWgu9SVQ5I6zF4M0RZBb50Q5EVIjeYhI2HN3CZYQTllgZySgg0ksB +rHEsemlxXivKscIkhYSAlkx9pGQ+eEIXtgzsFacbYuk2rVAztaO7NQFu/Zrnbpyn +UMdSEVfpIBLLHep71wA4P55fxBubAJ/YUvw= +=v0D8 +-----END PGP MESSAGE----- diff --git a/OpenKeychain/src/test/resources/test-keys/encrypt_decrypt_key_1.sec b/OpenKeychain/src/test/resources/test-keys/encrypt_decrypt_key_1.sec new file mode 100644 index 0000000000000000000000000000000000000000..a46d4c189c5edd6af77f7a3822b8fb0077a351ac GIT binary patch literal 1192 zcmbQTlqFJf;t636tu~Kyw#IK0j;YTFW~3uakGT z%gbe zz}f`z0@FN3rrC@PT$}>sJ}xT{vtPcO6wC0x?k&&zeSbPvJU*#=L@jkygX|u@KleYr z6nY?%x9EfJ^B#tOs``t#4q0YN&zhBE`}+s;Lz!ar2||^VwnqNhlwomdsmL5GA++m6 zgbIUu0&iz6Al(5*@xCpZ#^ho$eo>rX4W8^}#w}cc-P3!u7eq zHru}>9l7^ZB55GEZJw_htB$i?c)%?RMnm$dS9n%cD+OQOV+=q z-_L4)5FU|Q!Lpruv*@0e;y<@Oy1S_P zs9Y+T_%?m!wfp^N?EJ5Pc@er(cFu|B|M!zW9XtN^ojoJNB?VtQ6X(0$qAS}1e~0Q7 zv3}N$7kgEGfM-`!=ei4QhvuvVr$r&;w8(ofMVdeM@Yn@`@#$nfsv6vpn-+Tc|O=1;8M@@C<-Qp3K;?CEk>jiywc{vfynTWCC- z6?FK($B&;>|NbnrPE20$ydYXO>U_=)f$0Y){X4h4a&y9^bpi^!-K?d5B^ji70v;c{ z(W$bo@NCQ18>{cc*gV7t4cjY!uch>s+{}9Cq87jV#k{BGzoaH`9@p#UJ-@0ri|N@_ zwFej8?)<2oZKq=N`f-i*pWy1}w|Lt}Lz!~aytS#8Uw z*6%bly)x0~K-22jMx`l#8TQTln5L;HUF$K8kzp0HweEVw{nc*{n@njK{WK*psOkb0|Qnt-k?li;XUDy4l39+283QbvdYPM>`ZY?)S z5iQ4}x<^Y>e!qY2*YV_vyv^CqyFQ93~JoBInMe@;5ML7L$=Tkv$=n z?83Y}^X`sSGpY|}ql8fH|4Uc>J9r*W%=NP~`6)gzHYmVBT;$1*l9c>uug|=AxGU70 zBd767kn;D6lpA(#x|41R?&rGvC~M8e?MGXhUcOZQ<$U==d&fZ*31HB0LIYzq6GIjv zB;psaNCG9|0X9vGNepOj3ggrI+zyZZ-MuvM@ z{tMneKQ;9^OV3ws4e36s^f!XWZfB;7FAg(Y%J_0W!(WN$o%Ov@dTD1KZz)vZcg?!_ zCV+8~h81_oflC**%hl`8SqV;yLda=RV%ba{tG^DuD<$_VazC(xE6q}ZD>TL8@ezyd z-Cqov|1IoMsyO17^kqx23486?6&am6kC$$J?pv{o|5_23# zn5V}-xbn|F_o|)mw>4+-6pq9P`UQ7H=II-~V!Rr}NJI^77UXp2c8uYF;k5s9Om`+9x#m0hkwMc|j_r%~cP@Ia ymywbG$fR2G=|M(@We1cD%`Ytea{I*-K2g(OUsZc83$jY{o0qPdw%GK15+eX@X{S5@ literal 0 HcmV?d00001 diff --git a/OpenKeychain/src/test/resources/test-keys/encrypt_decrypt_key_insecure.sec b/OpenKeychain/src/test/resources/test-keys/encrypt_decrypt_key_insecure.sec new file mode 100644 index 0000000000000000000000000000000000000000..abf5e529d7acefe698de90c9c07df4aa5fc69e94 GIT binary patch literal 2227 zcmZY9c{~%01IO`g=GY$hF;`J@X32e2Hs#D5%Pl2Wp$8%6$hBpWbBdTD=Ezl>#ERso z97PiSA_Wm6uRO7Tt)W;z_l+mqQ0N9794mEggay7)cIt+4rQdsB^ou(=RkI+9V^7H$DK z86uo)Dtf0{m)jH|0t5g#5H9GKQ%}q$N}9H_ac|xXQ?FwR7pKLQ0o>*$NUGMSG5^Y0 z+3z{+n?<7nR&`kP!>@2ZGVC+nYzhmNy})+s8M{aEW^7qoA3E!2c~j8!El>Y=A3P2% zE)OcQY>0OoRyT5hBqR>8K~E;bTH)tL6v=hu9E%moRDiS}70VeK{^1 zU;FCtweQ0)(HH~i@$AY|T$JKoy^l_(YnD;*wvKaqqNRxAH{>QxyI|O6cQiQ&`Qh)X z9Rv6^rFGTQBY84svc+nUJvv5{3JaqBU1g12S0k_9sRxSzp#T~19}qrXkOUM21A?Rh z+_!!U0X+bM3V{G9M7ZjC40pbRG41FNFkr!l@?z&07gK=uu+hLzB^fN!8XmK<)AY8`uR`)CA$0S^$VsI!6w{d|p z--^-HLBd~%VR*dg5G(6lby7t<9NCDZ3cd2KERImpWumjz<&g_}Q&6Q4Bh}@F;=ldo zDa5ghY)HaiDePA97mrl`eH{LC0FYn1R$rv(S~tF@d}ludH%JvKHmYb=!~J&R@%NxNy*+uSklJm+ zzIiU`2TIaT|JZ6aJt$J+^FvyPf<_OMctYgQME!~Ehg%5a{xUl-det&VXp+-BM=+}d z#pdD_nCG-ki>x=yu}7r(_q?nAa-j+2P9)OeA0 zY>;rKY8|r~1uWvTi`O6c5HYOq^wiN*AQCL~mtDyJv=)K@)qhhhE(J^fHS%zSepCL9 zn1A1?zzPa_drP0|;7UFmz7%4jEhk^~7UN+-Cnj|U#+Z-|3;wu~GHHUoorsJH;q6O?Nz4MAr?_ zpKwnRN?VmXV0526pc0qK!*{kcrM6coswE93PvMyq1l}i<%17_do3&uW8O1iy)vDWe(z^re=L)_-_qn0~ndTx8wZc0?3 zw5Qy^E`Pm3bJNQ>{3!E&SxGm4(6}b|mB1egyjA*9K8mc1Fa8~py+d1CG|Txi-AFF3 zRW=LF37cc2_9G?W-9(-X)HL`JkWEnP+BnhR0p!N~?Od#nd0i-k((G>0G5a&_$SUw< zO{y(>{^qv(x4Rda^7vmB2fxB*?GW*wj>~QmA4#1c$N)VaR1b9U?)n(sIz`7Q>psV- zJky)#f|f8odo3jRG@PW}JnT2GZDcz0ZoiCG*vBw9vMExWpC%G3=JRPK!^cxNeP4LM zSq+X-%NFWVN~k`a&aGqcr*&c!FGen2eP!oN4KjT1rKf=2E>mmB525pXS@@}J9rdvt zjuc7C`L>b^;jUfqrEAVA4DSsVCz!d|=qYKx4vYJ26@f|*j8!dhyNaJTm7tcH>{bXq z7;g`d#a{zh76PG@6jcnt+iruL#L7RGVdq72nllq(O(I^yUCkusN znTR~^jn_=`JNHNtsa)UmZpk>Q*{~6iWw38uH=O?(0Y&_b=#aZp^8X!y|9SZ>5UvA{ zmL*@ExTLOg^FYrSX$6Ao;84|Cj*jw(dcQ3rvwhcI9@47smVEC$J~OG7)2Th1g;-xK zH9BaiylS* literal 0 HcmV?d00001