mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-27 11:12:15 -05:00
add test case for duplicate keys in keyring (#870)
This commit is contained in:
parent
862c9a8b3c
commit
3759d74ac8
@ -26,8 +26,10 @@ import org.junit.Before;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.shadows.ShadowLog;
|
||||
import org.spongycastle.bcpg.BCPGInputStream;
|
||||
import org.spongycastle.bcpg.HashAlgorithmTags;
|
||||
import org.spongycastle.bcpg.Packet;
|
||||
import org.spongycastle.bcpg.PacketTags;
|
||||
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
|
||||
import org.spongycastle.bcpg.UserIDPacket;
|
||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
||||
@ -40,16 +42,22 @@ import org.spongycastle.openpgp.PGPSignatureGenerator;
|
||||
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||
import org.spongycastle.openpgp.PGPUtil;
|
||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
|
||||
import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
|
||||
import org.spongycastle.openpgp.operator.PGPDigestCalculator;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
|
||||
import org.spongycastle.util.Strings;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.service.results.OperationResult;
|
||||
import org.sufficientlysecure.keychain.service.results.EditKeyResult;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
|
||||
import org.sufficientlysecure.keychain.service.results.OperationResult.LogType;
|
||||
import org.sufficientlysecure.keychain.service.results.OperationResult.OperationLog;
|
||||
import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
|
||||
import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket;
|
||||
|
||||
@ -465,6 +473,69 @@ public class UncachedKeyringCanonicalizeTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicateSubkey() throws Exception {
|
||||
|
||||
{ // duplicate subkey
|
||||
|
||||
// get subkey packets
|
||||
Iterator<RawPacket> it = KeyringTestingHelper.parseKeyring(ring.getEncoded());
|
||||
RawPacket subKey = KeyringTestingHelper.getNth(it, 5);
|
||||
RawPacket subSig = it.next();
|
||||
|
||||
// inject at a second position
|
||||
UncachedKeyRing modified = ring;
|
||||
modified = KeyringTestingHelper.injectPacket(modified, subKey.buf, 7);
|
||||
modified = KeyringTestingHelper.injectPacket(modified, subSig.buf, 8);
|
||||
|
||||
// canonicalize, and check if we lose the bad signature
|
||||
OperationLog log = new OperationLog();
|
||||
CanonicalizedKeyRing canonicalized = modified.canonicalize(log, 0);
|
||||
Assert.assertNull("canonicalization with duplicate subkey should fail", canonicalized);
|
||||
Assert.assertTrue("log should contain dup_key event", log.containsType(LogType.MSG_KC_ERROR_DUP_KEY));
|
||||
}
|
||||
|
||||
{ // duplicate subkey, which is the same as the master key
|
||||
|
||||
// We actually encountered one of these in the wild:
|
||||
// https://www.sparkasse-holstein.de/firmenkunden/electronic_banking/secure-e-mail/pdf/Spk_Holstein_PGP_Domain-Zertifikat.asc
|
||||
|
||||
CanonicalizedSecretKeyRing canonicalized = (CanonicalizedSecretKeyRing) ring.canonicalize(log, 0);
|
||||
|
||||
CanonicalizedSecretKey masterSecretKey = canonicalized.getSecretKey();
|
||||
masterSecretKey.unlock("");
|
||||
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
|
||||
PGPSignature cert = PgpKeyOperation.generateSubkeyBindingSignature(
|
||||
masterPublicKey, masterSecretKey.getPrivateKey(), masterSecretKey.getPrivateKey(),
|
||||
masterPublicKey, masterSecretKey.getKeyUsage(), 0);
|
||||
PGPPublicKey subPubKey = PGPPublicKey.addSubkeyBindingCertification(masterPublicKey, cert);
|
||||
|
||||
PGPSecretKey sKey;
|
||||
{
|
||||
// Build key encrypter and decrypter based on passphrase
|
||||
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder()
|
||||
.build().get(HashAlgorithmTags.SHA256);
|
||||
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
|
||||
SymmetricKeyAlgorithmTags.AES_256, encryptorHashCalc, 10)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray());
|
||||
|
||||
// NOTE: only SHA1 is supported for key checksum calculations.
|
||||
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
|
||||
.build().get(HashAlgorithmTags.SHA1);
|
||||
sKey = new PGPSecretKey(masterSecretKey.getPrivateKey(), subPubKey, sha1Calc, false, keyEncryptor);
|
||||
}
|
||||
|
||||
UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, sKey.getEncoded(), 5);
|
||||
|
||||
// canonicalize, and check if we lose the bad signature
|
||||
OperationLog log = new OperationLog();
|
||||
CanonicalizedKeyRing result = modified.canonicalize(log, 0);
|
||||
Assert.assertNull("canonicalization with duplicate subkey (from master) should fail", result);
|
||||
Assert.assertTrue("log should contain dup_key event", log.containsType(LogType.MSG_KC_ERROR_DUP_KEY));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final int[] sigtypes_direct = new int[] {
|
||||
PGPSignature.KEY_REVOCATION,
|
||||
PGPSignature.DIRECT_KEY,
|
||||
|
@ -329,9 +329,9 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
||||
return new UncachedSecretKey(mSecretKey);
|
||||
}
|
||||
|
||||
// HACK
|
||||
public PGPSecretKey getSecretKey() {
|
||||
return mSecretKey;
|
||||
// HACK, for TESTING ONLY!!
|
||||
PGPPrivateKey getPrivateKey () {
|
||||
return mPrivateKey;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1118,7 +1118,7 @@ public class PgpKeyOperation {
|
||||
pKey, flags, expiry);
|
||||
}
|
||||
|
||||
private static PGPSignature generateSubkeyBindingSignature(
|
||||
static PGPSignature generateSubkeyBindingSignature(
|
||||
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
|
||||
PGPPrivateKey subPrivateKey, PGPPublicKey pKey, int flags, long expiry)
|
||||
throws IOException, PGPException, SignatureException {
|
||||
|
Loading…
Reference in New Issue
Block a user