From 8cf0638f54fc4679c33a0243e17c514271931c48 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 4 May 2014 16:56:44 +0200 Subject: wrapped-key-ring: introduce Uncached*Key objects --- .../keychain/pgp/CachedPublicKey.java | 133 ++------------------ .../keychain/pgp/CachedPublicKeyRing.java | 2 +- .../keychain/pgp/CachedSecretKey.java | 7 +- .../keychain/pgp/UncachedPublicKey.java | 140 +++++++++++++++++++++ .../keychain/pgp/UncachedSecretKey.java | 26 ++++ 5 files changed, 179 insertions(+), 129 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java index c1d866fba..dee03db6f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java @@ -1,139 +1,28 @@ package org.sufficientlysecure.keychain.pgp; -import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPOnePassSignature; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSignature; -import org.spongycastle.openpgp.PGPSignatureSubpacketVector; import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.util.IterableIterator; import java.security.SignatureException; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -public class CachedPublicKey { +public class CachedPublicKey extends UncachedPublicKey { // this is the parent key ring final CachedKeyRing mRing; - private final PGPPublicKey mKey; - CachedPublicKey(CachedKeyRing ring, PGPPublicKey key) { + super(key); mRing = ring; - mKey = key; - } - - public long getKeyId() { - return mKey.getKeyID(); - } - - public boolean isRevoked() { - return mKey.isRevoked(); - } - - public Date getCreationTime() { - return mKey.getCreationTime(); - } - - public Date getExpiryTime() { - Date creationDate = getCreationTime(); - if (mKey.getValidDays() == 0) { - // no expiry - return null; - } - Calendar calendar = GregorianCalendar.getInstance(); - calendar.setTime(creationDate); - calendar.add(Calendar.DATE, mKey.getValidDays()); - - return calendar.getTime(); - } - - public boolean isExpired() { - Date creationDate = mKey.getCreationTime(); - Date expiryDate = mKey.getValidSeconds() > 0 - ? new Date(creationDate.getTime() + mKey.getValidSeconds() * 1000) : null; - - Date now = new Date(); - return creationDate.after(now) || (expiryDate != null && expiryDate.before(now)); - } - - public boolean isMasterKey() { - return mKey.isMasterKey(); - } - - public int getAlgorithm() { - return mKey.getAlgorithm(); } public IterableIterator getUserIds() { - return new IterableIterator(mKey.getUserIDs()); - } - - private Integer mCacheUsage = null; - @SuppressWarnings("unchecked") - public int getKeyUsage() { - if(mCacheUsage == null) { - mCacheUsage = 0; - if (mKey.getVersion() >= 4) { - for (PGPSignature sig : new IterableIterator(mKey.getSignatures())) { - if (mKey.isMasterKey() && sig.getKeyID() != mKey.getKeyID()) { - continue; - } - - PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets(); - if (hashed != null) { - mCacheUsage |= hashed.getKeyFlags(); - } - - PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets(); - if (unhashed != null) { - mCacheUsage |= unhashed.getKeyFlags(); - } - } - } - } - return mCacheUsage; - } - - public boolean canAuthenticate() { - return mKey.getVersion() <= 3 || (getKeyUsage() & KeyFlags.AUTHENTICATION) != 0; - } - - public boolean canCertify() { - return mKey.getVersion() <= 3 || (getKeyUsage() & KeyFlags.CERTIFY_OTHER) != 0; - } - - public boolean canEncrypt() { - if (!mKey.isEncryptionKey()) { - return false; - } - - // special cases - if (mKey.getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT) { - return true; - } - - if (mKey.getAlgorithm() == PGPPublicKey.RSA_ENCRYPT) { - return true; - } - - return mKey.getVersion() <= 3 || - (getKeyUsage() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0; - - } - - public boolean canSign() { - // special case - if (mKey.getAlgorithm() == PGPPublicKey.RSA_SIGN) { - return true; - } - - return mKey.getVersion() <= 3 || (getKeyUsage() & KeyFlags.SIGN_DATA) != 0; + return new IterableIterator(mPublicKey.getUserIDs()); } public CachedKeyRing getKeyRing() { @@ -141,21 +30,21 @@ public class CachedPublicKey { } JcePublicKeyKeyEncryptionMethodGenerator getPubKeyEncryptionGenerator() { - return new JcePublicKeyKeyEncryptionMethodGenerator(mKey); + return new JcePublicKeyKeyEncryptionMethodGenerator(mPublicKey); } public void initSignature(PGPSignature sig) throws PGPException { JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider() .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - sig.init(contentVerifierBuilderProvider, mKey); + sig.init(contentVerifierBuilderProvider, mPublicKey); } public void initSignature(PGPOnePassSignature sig) throws PGPException { JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider() .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - sig.init(contentVerifierBuilderProvider, mKey); + sig.init(contentVerifierBuilderProvider, mPublicKey); } /** Verify a signature for this pubkey, after it has been initialized by the signer using @@ -164,18 +53,10 @@ public class CachedPublicKey { */ public boolean verifySignature(PGPSignature sig, String uid) throws PGPException { try { - return sig.verifyCertification(uid, mKey); + return sig.verifyCertification(uid, mPublicKey); } catch (SignatureException e) { throw new PGPException("Error!", e); } } - public byte[] getFingerprint() { - return mKey.getFingerprint(); - } - - // Note that this method has package visibility - no access outside the pgp package! - PGPPublicKey getKey() { - return mKey; - } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java index bbce42f86..108ed1a4a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java @@ -72,7 +72,7 @@ public class CachedPublicKeyRing extends CachedKeyRing { boolean validPrimaryKeyBinding = false; PGPPublicKey masterKey = getRing().getPublicKey(); - PGPPublicKey subKey = cachedSubkey.getKey(); + PGPPublicKey subKey = cachedSubkey.getPublicKey(); // Is this the master key? Match automatically, then. if(Arrays.equals(masterKey.getFingerprint(), subKey.getFingerprint())) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java index 948227819..d1634859a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java @@ -1,6 +1,5 @@ package org.sufficientlysecure.keychain.pgp; -import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPPrivateKey; import org.spongycastle.openpgp.PGPPublicKey; @@ -157,7 +156,7 @@ public class CachedSecretKey extends CachedPublicKey { } // get the master subkey (which we certify for) - PGPPublicKey publicKey = publicKeyRing.getSubkey().getKey(); + PGPPublicKey publicKey = publicKeyRing.getSubkey().getPublicKey(); // fetch public key ring, add the certification and return it for (String userId : new IterableIterator(userIds.iterator())) { @@ -175,4 +174,8 @@ public class CachedSecretKey extends CachedPublicKey { // the private key is called without a previous call to unlock() } + public UncachedSecretKey getUncached() { + return new UncachedSecretKey(mSecretKey); + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java new file mode 100644 index 000000000..bc37f6201 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java @@ -0,0 +1,140 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.bcpg.sig.KeyFlags; +import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.openpgp.PGPSignature; +import org.spongycastle.openpgp.PGPSignatureSubpacketVector; +import org.sufficientlysecure.keychain.util.IterableIterator; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +public class UncachedPublicKey { + protected final PGPPublicKey mPublicKey; + private Integer mCacheUsage = null; + + public UncachedPublicKey(PGPPublicKey key) { + mPublicKey = key; + } + + public long getKeyId() { + return mPublicKey.getKeyID(); + } + + public boolean isRevoked() { + return mPublicKey.isRevoked(); + } + + public Date getCreationTime() { + return mPublicKey.getCreationTime(); + } + + public Date getExpiryTime() { + Date creationDate = getCreationTime(); + if (mPublicKey.getValidDays() == 0) { + // no expiry + return null; + } + Calendar calendar = GregorianCalendar.getInstance(); + calendar.setTime(creationDate); + calendar.add(Calendar.DATE, mPublicKey.getValidDays()); + + return calendar.getTime(); + } + + public boolean isExpired() { + Date creationDate = mPublicKey.getCreationTime(); + Date expiryDate = mPublicKey.getValidSeconds() > 0 + ? new Date(creationDate.getTime() + mPublicKey.getValidSeconds() * 1000) : null; + + Date now = new Date(); + return creationDate.after(now) || (expiryDate != null && expiryDate.before(now)); + } + + public boolean isMasterKey() { + return mPublicKey.isMasterKey(); + } + + public int getAlgorithm() { + return mPublicKey.getAlgorithm(); + } + + public boolean isElGamalEncrypt() { + return getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT; + } + + public boolean isDSA() { + return getAlgorithm() == PGPPublicKey.DSA; + } + + @SuppressWarnings("unchecked") + public int getKeyUsage() { + if(mCacheUsage == null) { + mCacheUsage = 0; + if (mPublicKey.getVersion() >= 4) { + for (PGPSignature sig : new IterableIterator(mPublicKey.getSignatures())) { + if (mPublicKey.isMasterKey() && sig.getKeyID() != mPublicKey.getKeyID()) { + continue; + } + + PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets(); + if (hashed != null) { + mCacheUsage |= hashed.getKeyFlags(); + } + + PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets(); + if (unhashed != null) { + mCacheUsage |= unhashed.getKeyFlags(); + } + } + } + } + return mCacheUsage; + } + + public boolean canAuthenticate() { + return mPublicKey.getVersion() <= 3 || (getKeyUsage() & KeyFlags.AUTHENTICATION) != 0; + } + + public boolean canCertify() { + return mPublicKey.getVersion() <= 3 || (getKeyUsage() & KeyFlags.CERTIFY_OTHER) != 0; + } + + public boolean canEncrypt() { + if (!mPublicKey.isEncryptionKey()) { + return false; + } + + // special cases + if (mPublicKey.getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT) { + return true; + } + + if (mPublicKey.getAlgorithm() == PGPPublicKey.RSA_ENCRYPT) { + return true; + } + + return mPublicKey.getVersion() <= 3 || + (getKeyUsage() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0; + + } + + public boolean canSign() { + // special case + if (mPublicKey.getAlgorithm() == PGPPublicKey.RSA_SIGN) { + return true; + } + + return mPublicKey.getVersion() <= 3 || (getKeyUsage() & KeyFlags.SIGN_DATA) != 0; + } + + public byte[] getFingerprint() { + return mPublicKey.getFingerprint(); + } + + // Note that this method has package visibility - no access outside the pgp package! + PGPPublicKey getPublicKey() { + return mPublicKey; + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java new file mode 100644 index 000000000..82224c6cf --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java @@ -0,0 +1,26 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.openpgp.PGPSecretKey; + +import java.io.IOException; +import java.io.OutputStream; + +public class UncachedSecretKey extends UncachedPublicKey { + + final PGPSecretKey mSecretKey; + + public UncachedSecretKey(PGPSecretKey secretKey) { + super(secretKey.getPublicKey()); + mSecretKey = secretKey; + } + + @Deprecated + public PGPSecretKey getSecretKeyExternal() { + return mSecretKey; + } + + public void encodeSecretKey(OutputStream os) throws IOException { + mSecretKey.encode(os); + } + +} -- cgit v1.2.3