From 10ad7be46bd44956116c5ac363ea970bcd8082d6 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Fri, 23 May 2014 16:44:50 +0200 Subject: wrapped-key-ring: UncachedKeyRing wraps only one ring of dynamic type --- .../keychain/pgp/PgpImportExport.java | 19 ++++++-- .../keychain/pgp/PgpKeyOperation.java | 12 ++--- .../keychain/pgp/UncachedKeyRing.java | 56 +++++++++++++++++----- .../keychain/pgp/UncachedPublicKey.java | 36 +++++++++++++- .../keychain/pgp/WrappedPublicKey.java | 26 ---------- 5 files changed, 99 insertions(+), 50 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java index a55765542..e858012f5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java @@ -165,7 +165,8 @@ public class PgpImportExport { } newPubRing = PGPPublicKeyRing.insertPublicKey(newPubRing, key); } - status = storeKeyRingInCache(new UncachedKeyRing(newPubRing ,secretKeyRing)); + status = storeKeyRingInCache(new UncachedKeyRing(newPubRing), + new UncachedKeyRing(secretKeyRing)); } else { status = storeKeyRingInCache(new UncachedKeyRing((PGPPublicKeyRing) keyring)); } @@ -278,15 +279,23 @@ public class PgpImportExport { return returnData; } + public int storeKeyRingInCache(UncachedKeyRing ring) { + return storeKeyRingInCache(ring, null); + } + @SuppressWarnings("unchecked") - public int storeKeyRingInCache(UncachedKeyRing keyring) { + public int storeKeyRingInCache(UncachedKeyRing ring, UncachedKeyRing secretRing) { int status; try { - PGPSecretKeyRing secretKeyRing = keyring.getSecretRing(); - PGPPublicKeyRing publicKeyRing = keyring.getPublicRing(); + // TODO make sure these are correctly typed! + PGPPublicKeyRing publicKeyRing = (PGPPublicKeyRing) ring.getRing(); + PGPSecretKeyRing secretKeyRing = null; + if(secretRing != null) { + secretKeyRing = (PGPSecretKeyRing) secretRing.getRing(); + } // see what type we have. we can either have a secret + public keyring, or just public if (secretKeyRing != null) { - mProviderHelper.saveKeyRing(publicKeyRing, secretKeyRing); + mProviderHelper.saveKeyRing(ring, secretRing); status = RETURN_OK; } else { mProviderHelper.saveKeyRing(publicKeyRing); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index b9634c34a..5e7134dc6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -331,15 +331,14 @@ public class PgpKeyOperation { } PGPSecretKeyRing secretKeyRing = keyGen.generateSecretKeyRing(); - PGPPublicKeyRing publicKeyRing = keyGen.generatePublicKeyRing(); - return new UncachedKeyRing(publicKeyRing, secretKeyRing); + return new UncachedKeyRing(secretKeyRing); } - public UncachedKeyRing buildSecretKey(WrappedSecretKeyRing wmKR, - WrappedPublicKeyRing wpKR, - SaveKeyringParcel saveParcel) + public Pair buildSecretKey(WrappedSecretKeyRing wmKR, + WrappedPublicKeyRing wpKR, + SaveKeyringParcel saveParcel) throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException { PGPSecretKeyRing mKR = wmKR.getRing(); @@ -664,7 +663,8 @@ public class PgpKeyOperation { */ - return new UncachedKeyRing(pKR, mKR); + return new Pair(new UncachedKeyRing(pKR), + new UncachedKeyRing(mKR)); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 58601c49a..06f890fb4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -1,40 +1,51 @@ package org.sufficientlysecure.keychain.pgp; +import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPObjectFactory; import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPUtil; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.util.Log; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.List; +import java.util.Vector; public class UncachedKeyRing { - final PGPPublicKeyRing mPublicRing; - final PGPSecretKeyRing mSecretRing; + final PGPKeyRing mRing; + final boolean mIsSecret; - UncachedKeyRing(PGPPublicKeyRing publicRing, PGPSecretKeyRing secretRing) { - mPublicRing = publicRing; - mSecretRing = secretRing; + UncachedKeyRing(PGPKeyRing ring) { + mRing = ring; + mIsSecret = ring instanceof PGPSecretKeyRing; } - UncachedKeyRing(PGPPublicKeyRing publicRing) { - this(publicRing, null); + /* TODO don't use this */ + @Deprecated + public PGPKeyRing getRing() { + return mRing; } - public PGPPublicKeyRing getPublicRing() { - return mPublicRing; + public UncachedPublicKey getPublicKey() { + return new UncachedPublicKey(mRing.getPublicKey()); } - public PGPSecretKeyRing getSecretRing() { - return mSecretRing; + public boolean isSecret() { + return mIsSecret; + } + + public byte[] getEncoded() throws IOException { + return mRing.getEncoded(); } public byte[] getFingerprint() { - return mPublicRing.getPublicKey().getFingerprint(); + return mRing.getPublicKey().getFingerprint(); } public static UncachedKeyRing decodePubkeyFromData(byte[] data) @@ -57,4 +68,25 @@ public class UncachedKeyRing { } } + public static List fromStream(InputStream stream) + throws PgpGeneralException, IOException { + + PGPObjectFactory objectFactory = new PGPObjectFactory(PGPUtil.getDecoderStream(stream)); + + List result = new Vector(); + + // go through all objects in this block + Object obj; + while ((obj = objectFactory.nextObject()) != null) { + Log.d(Constants.TAG, "Found class: " + obj.getClass()); + + if (obj instanceof PGPKeyRing) { + result.add(new UncachedKeyRing((PGPKeyRing) obj)); + } else { + Log.e(Constants.TAG, "Object not recognized as PGPKeyRing!"); + } + } + return result; + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java index bc37f6201..7f6fae4a6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java @@ -1,14 +1,19 @@ package org.sufficientlysecure.keychain.pgp; +import org.spongycastle.bcpg.SignatureSubpacketTags; import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureSubpacketVector; +import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.util.IterableIterator; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.List; public class UncachedPublicKey { protected final PGPPublicKey mPublicKey; @@ -22,7 +27,8 @@ public class UncachedPublicKey { return mPublicKey.getKeyID(); } - public boolean isRevoked() { + /** The revocation signature is NOT checked here, so this may be false! */ + public boolean maybeRevoked() { return mPublicKey.isRevoked(); } @@ -60,6 +66,34 @@ public class UncachedPublicKey { return mPublicKey.getAlgorithm(); } + public int getBitStrength() { + return mPublicKey.getBitStrength(); + } + + public String getPrimaryUserId() { + List userIds = new ArrayList(); + for (String userId : new IterableIterator(mPublicKey.getUserIDs())) { + userIds.add(userId); + for (PGPSignature sig : new IterableIterator(mPublicKey.getSignaturesForID(userId))) { + if (sig.getHashedSubPackets() != null + && sig.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.PRIMARY_USER_ID)) { + try { + // make sure it's actually valid + sig.init(new JcaPGPContentVerifierBuilderProvider().setProvider( + Constants.BOUNCY_CASTLE_PROVIDER_NAME), mPublicKey); + if (sig.verifyCertification(userId, mPublicKey)) { + return userId; + } + } catch (Exception e) { + // nothing bad happens, the key is just not considered the primary key id + } + } + + } + } + return null; + } + public boolean isElGamalEncrypt() { return getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKey.java index 72352a451..32c6910be 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKey.java @@ -33,30 +33,4 @@ public class WrappedPublicKey extends UncachedPublicKey { return new JcePublicKeyKeyEncryptionMethodGenerator(mPublicKey); } - public void initSignature(PGPSignature sig) throws PGPException { - JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = - new JcaPGPContentVerifierBuilderProvider() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - sig.init(contentVerifierBuilderProvider, mPublicKey); - } - - public void initSignature(PGPOnePassSignature sig) throws PGPException { - JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = - new JcaPGPContentVerifierBuilderProvider() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - sig.init(contentVerifierBuilderProvider, mPublicKey); - } - - /** Verify a signature for this pubkey, after it has been initialized by the signer using - * initSignature(). This method should probably move into a wrapped PGPSignature class - * at some point. - */ - public boolean verifySignature(PGPSignature sig, String uid) throws PGPException { - try { - return sig.verifyCertification(uid, mPublicKey); - } catch (SignatureException e) { - throw new PGPException("Error!", e); - } - } - } -- cgit v1.2.3