@Test public void testImportSymantec() throws Exception { // symantec pgp desktop exports secret keys without self certificates. we don't support // those on their own, but if they are imported together with their public key (or if // the public key is already known), the self certs info will be merged in as a special // case. UncachedKeyRing seckey = readRingFromResource("/test-keys/symantec_secret.asc"); UncachedKeyRing pubkey = readRingFromResource("/test-keys/symantec_public.asc"); SaveKeyringResult result; // insert secret, this should fail because of missing self-cert result = new ProviderHelper(RuntimeEnvironment.application) .saveSecretKeyRing(seckey, new ProgressScaler()); Assert.assertFalse("secret keyring import before pubring import should fail", result.success()); // insert pubkey, then seckey - both should succeed result = new ProviderHelper(RuntimeEnvironment.application).savePublicKeyRing(pubkey); Assert.assertTrue("public keyring import should succeed", result.success()); result = new ProviderHelper(RuntimeEnvironment.application) .saveSecretKeyRing(seckey, new ProgressScaler()); Assert.assertTrue( "secret keyring import after pubring import should succeed", result.success()); }
@Test public void testImportCooperPair() throws Exception { // insert two keys with same long key id, make sure the second one gets rejected either way! UncachedKeyRing first = readRingFromResource("/test-keys/cooperpair/9E669861368BCA0BE42DAF7DDDA252EBB8EBE1AF.asc"); UncachedKeyRing second = readRingFromResource("/test-keys/cooperpair/A55120427374F3F7AA5F1166DDA252EBB8EBE1AF.asc"); SaveKeyringResult result; // insert both keys, second should fail result = new ProviderHelper(RuntimeEnvironment.application).savePublicKeyRing(first); Assert.assertTrue("first keyring import should succeed", result.success()); result = new ProviderHelper(RuntimeEnvironment.application).savePublicKeyRing(second); Assert.assertFalse("second keyring import should fail", result.success()); new KeychainDatabase(RuntimeEnvironment.application).clearDatabase(); // and the other way around result = new ProviderHelper(RuntimeEnvironment.application).savePublicKeyRing(second); Assert.assertTrue("first keyring import should succeed", result.success()); result = new ProviderHelper(RuntimeEnvironment.application).savePublicKeyRing(first); Assert.assertFalse("second keyring import should fail", result.success()); }
@Test /** * Tests a master key which may sign, but is stripped. In this case, if there is a different * subkey available which can sign, that one should be selected. */ public void testImportStrippedFlags() throws Exception { UncachedKeyRing key = readRingFromResource("/test-keys/stripped_flags.asc"); long masterKeyId = key.getMasterKeyId(); SaveKeyringResult result; result = mProviderHelper.saveSecretKeyRing(key, new ProgressScaler()); Assert.assertTrue("import of keyring should succeed", result.success()); long signId; { CanonicalizedSecretKeyRing ring = mProviderHelper.getCanonicalizedSecretKeyRing(masterKeyId); Assert.assertTrue("master key should have sign flag", ring.getPublicKey().canSign()); Assert.assertTrue("master key should have encrypt flag", ring.getPublicKey().canEncrypt()); signId = ring.getSecretSignId(); Assert.assertNotEquals("encrypt id should not be 0", 0, signId); Assert.assertNotEquals( "encrypt key should be different from master key", masterKeyId, signId); } { CachedPublicKeyRing ring = mProviderHelper.getCachedPublicKeyRing(masterKeyId); Assert.assertEquals( "signing key should be same id cached as uncached", signId, ring.getSecretSignId()); } }
@Test public void testImportBadEncodedUserId() throws Exception { UncachedKeyRing key = readRingFromResource("/test-keys/bad_user_id_encoding.asc"); long keyId = key.getMasterKeyId(); SaveKeyringResult result; result = mProviderHelper.savePublicKeyRing(key, new ProgressScaler(), null); Assert.assertTrue("import of keyring should succeed", result.success()); CanonicalizedPublicKeyRing ring = mProviderHelper.getCanonicalizedPublicKeyRing(keyId); boolean found = false; byte[] badUserId = Hex.decode( "436c61757320467261656e6b656c203c436c6175732e4672e46e6b656c4068616c696661782e727774682d61616368656e2e64653e"); for (byte[] rawUserId : new IterableIterator<byte[]>(ring.getUnorderedRawUserIds().iterator())) { if (Arrays.equals(rawUserId, badUserId)) { found = true; } } Assert.assertTrue("import of the badly encoded user id should succeed", found); }
@NonNull public OperationResult execute(ChangeUnlockParcel unlockParcel, CryptoInputParcel cryptoInput) { OperationResult.OperationLog log = new OperationResult.OperationLog(); log.add(OperationResult.LogType.MSG_ED, 0); if (unlockParcel == null || unlockParcel.mMasterKeyId == null) { log.add(OperationResult.LogType.MSG_ED_ERROR_NO_PARCEL, 1); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } // Perform actual modification PgpEditKeyResult modifyResult; { PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(mProgressable, 0, 70, 100)); try { log.add( OperationResult.LogType.MSG_ED_FETCHING, 1, KeyFormattingUtils.convertKeyIdToHex(unlockParcel.mMasterKeyId)); CanonicalizedSecretKeyRing secRing = mProviderHelper.getCanonicalizedSecretKeyRing(unlockParcel.mMasterKeyId); modifyResult = keyOperations.modifyKeyRingPassphrase(secRing, cryptoInput, unlockParcel); if (modifyResult.isPending()) { // obtain original passphrase from user log.add(modifyResult, 1); return new EditKeyResult(log, modifyResult); } } catch (ProviderHelper.NotFoundException e) { log.add(OperationResult.LogType.MSG_ED_ERROR_KEY_NOT_FOUND, 2); return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } } log.add(modifyResult, 1); if (!modifyResult.success()) { // error is already logged by modification return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } // Cannot cancel from here on out! mProgressable.setPreventCancel(); // It's a success, so this must be non-null now UncachedKeyRing ring = modifyResult.getRing(); SaveKeyringResult saveResult = mProviderHelper.saveSecretKeyRing(ring, new ProgressScaler(mProgressable, 70, 95, 100)); log.add(saveResult, 1); // If the save operation didn't succeed, exit here if (!saveResult.success()) { return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } updateProgress(R.string.progress_done, 100, 100); log.add(OperationResult.LogType.MSG_ED_SUCCESS, 0); return new EditKeyResult(EditKeyResult.RESULT_OK, log, ring.getMasterKeyId()); }
@Test public void testImportDivertToCard() throws Exception { UncachedKeyRing sec = readRingFromResource("/test-keys/divert_to_card_sec.asc"); long keyId = sec.getMasterKeyId(); SaveKeyringResult result; result = mProviderHelper.saveSecretKeyRing(sec, new ProgressScaler()); Assert.assertTrue("import of secret keyring should succeed", result.success()); // make sure both the CanonicalizedSecretKeyRing as well as the CachedPublicKeyRing correctly // indicate the secret key type CachedPublicKeyRing cachedRing = mProviderHelper.getCachedPublicKeyRing(keyId); CanonicalizedSecretKeyRing secRing = mProviderHelper.getCanonicalizedSecretKeyRing(keyId); Iterator<CanonicalizedSecretKey> it = secRing.secretKeyIterator().iterator(); { // first subkey Assert.assertTrue("keyring should have 3 subkeys (1)", it.hasNext()); CanonicalizedSecretKey key = it.next(); Assert.assertEquals( "first subkey should be of type sign+certify", KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA, (int) key.getKeyUsage()); Assert.assertEquals( "first subkey should be divert-to-card", SecretKeyType.DIVERT_TO_CARD, key.getSecretKeyType()); Assert.assertTrue("canCertify() should be true", key.canCertify()); Assert.assertTrue("canSign() should be true", key.canSign()); // cached Assert.assertEquals( "all subkeys from CachedPublicKeyRing should be divert-to-key", SecretKeyType.DIVERT_TO_CARD, cachedRing.getSecretKeyType(key.getKeyId())); } { // second subkey Assert.assertTrue("keyring should have 3 subkeys (2)", it.hasNext()); CanonicalizedSecretKey key = it.next(); Assert.assertEquals( "second subkey should be of type authenticate", KeyFlags.AUTHENTICATION, (int) key.getKeyUsage()); Assert.assertEquals( "second subkey should be divert-to-card", SecretKeyType.DIVERT_TO_CARD, key.getSecretKeyType()); Assert.assertTrue("canAuthenticate() should be true", key.canAuthenticate()); // cached Assert.assertEquals( "all subkeys from CachedPublicKeyRing should be divert-to-key", SecretKeyType.DIVERT_TO_CARD, cachedRing.getSecretKeyType(key.getKeyId())); } { // third subkey Assert.assertTrue("keyring should have 3 subkeys (3)", it.hasNext()); CanonicalizedSecretKey key = it.next(); Assert.assertEquals( "first subkey should be of type encrypt (both types)", KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, (int) key.getKeyUsage()); Assert.assertEquals( "third subkey should be divert-to-card", SecretKeyType.DIVERT_TO_CARD, key.getSecretKeyType()); Assert.assertTrue("canEncrypt() should be true", key.canEncrypt()); // cached Assert.assertEquals( "all subkeys from CachedPublicKeyRing should be divert-to-key", SecretKeyType.DIVERT_TO_CARD, cachedRing.getSecretKeyType(key.getKeyId())); } Assert.assertFalse("keyring should have 3 subkeys (4)", it.hasNext()); }