diff options
Diffstat (limited to 'OpenKeychain')
14 files changed, 209 insertions, 269 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java index 9e5671a97..334f676c4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java @@ -1,44 +1,26 @@ package org.sufficientlysecure.keychain.pgp; -import org.spongycastle.openpgp.PGPSignature; - public abstract class CachedKeyRing { private final long mMasterKeyId; - private final int mKeySize; - private final boolean mIsRevoked; private final boolean mCanCertify; - private final long mCreation; - private final long mExpiry; - private final int mAlgorithm; private final byte[] mFingerprint; private final String mUserId; private final int mVerified; private final boolean mHasSecret; - protected CachedKeyRing(long masterKeyId, int keySize, boolean isRevoked, - boolean canCertify, long creation, long expiry, int algorithm, + protected CachedKeyRing(long masterKeyId, boolean canCertify, byte[] fingerprint, String userId, int verified, boolean hasSecret) { mMasterKeyId = masterKeyId; - mKeySize = keySize; - mIsRevoked = isRevoked; mCanCertify = canCertify; - mCreation = creation; - mExpiry = expiry; - mAlgorithm = algorithm; mFingerprint = fingerprint; mUserId = userId; mVerified = verified; mHasSecret = hasSecret; } - public boolean isRevoked() { - return mIsRevoked; - } - public byte[] getFingerprint() { - return mFingerprint; } @@ -54,4 +36,12 @@ public abstract class CachedKeyRing { return mVerified; } + public boolean canCertify() { + return mCanCertify; + } + + public boolean hasSecret() { + return mHasSecret; + } + } 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 08b9d5a0c..2862b21c5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java @@ -31,6 +31,10 @@ public class CachedPublicKey { return mKey.getKeyID(); } + public boolean isRevoked() { + return mKey.isRevoked(); + } + public Date getCreationTime() { return mKey.getCreationTime(); } @@ -48,6 +52,15 @@ public class CachedPublicKey { 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(); } 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 3a45b4ff9..8970d18ec 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java @@ -2,7 +2,6 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.SignatureSubpacketTags; -import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPPublicKeyRing; @@ -17,7 +16,6 @@ import org.sufficientlysecure.keychain.util.IterableIterator; import java.io.IOException; import java.security.SignatureException; import java.util.Arrays; -import java.util.Date; import java.util.Iterator; public class CachedPublicKeyRing extends CachedKeyRing { @@ -30,8 +28,7 @@ public class CachedPublicKeyRing extends CachedKeyRing { byte[] fingerprint, String userId, int verified, boolean hasSecret, byte[] pubkey) { - super(masterKeyId, keySize, isRevoked, canCertify, creation, expiry, - algorithm, fingerprint, userId, verified, hasSecret); + super(masterKeyId, canCertify, fingerprint, userId, verified, hasSecret); mPubKey = pubkey; } @@ -55,24 +52,46 @@ public class CachedPublicKeyRing extends CachedKeyRing { return new CachedPublicKey(this, getRing().getPublicKey(id)); } + public CachedPublicKey getFirstSignSubkey() throws PgpGeneralException { + // only return master key if no other signing key is available + CachedPublicKey masterKey = null; + for (PGPPublicKey k : new IterableIterator<PGPPublicKey>(getRing().getPublicKeys())) { + CachedPublicKey key = new CachedPublicKey(this, k); + if (key.isRevoked() || key.canSign() || key.isExpired()) { + continue; + } + if (key.isMasterKey()) { + masterKey = key; + } else { + return key; + } + } + if(masterKey == null) { + // TODO proper exception + throw new PgpGeneralException("key not found"); + } + return masterKey; + } + public CachedPublicKey getFirstEncryptSubkey() throws PgpGeneralException { // only return master key if no other encryption key is available - PGPPublicKey masterKey = null; - for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(getRing().getPublicKeys())) { - if (key.isRevoked() || !isEncryptionKey(key) || isExpired(key)) { + CachedPublicKey masterKey = null; + for (PGPPublicKey k : new IterableIterator<PGPPublicKey>(getRing().getPublicKeys())) { + CachedPublicKey key = new CachedPublicKey(this, k); + if (key.isRevoked() || key.canEncrypt() || key.isExpired()) { continue; } if (key.isMasterKey()) { masterKey = key; } else { - return new CachedPublicKey(this, key); + return key; } } if(masterKey == null) { // TODO proper exception throw new PgpGeneralException("key not found"); } - return new CachedPublicKey(this, masterKey); + return masterKey; } public boolean verifySubkeyBinding(CachedPublicKey cachedSubkey) { @@ -132,55 +151,6 @@ public class CachedPublicKeyRing extends CachedKeyRing { } - static boolean isEncryptionKey(PGPPublicKey key) { - if (!key.isEncryptionKey()) { - return false; - } - - if (key.getVersion() <= 3) { - // this must be true now - return key.isEncryptionKey(); - } - - // special cases - if (key.getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT) { - return true; - } - - if (key.getAlgorithm() == PGPPublicKey.RSA_ENCRYPT) { - return true; - } - - for (PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignatures())) { - if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) { - continue; - } - PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets(); - - if (hashed != null - && (hashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) { - return true; - } - - PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets(); - - if (unhashed != null - && (unhashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) { - return true; - } - } - return false; - } - - static boolean isExpired(PGPPublicKey key) { - Date creationDate = key.getCreationTime(); - Date expiryDate = key.getValidSeconds() > 0 - ? new Date(creationDate.getTime() + key.getValidSeconds() * 1000) : null; - - Date now = new Date(); - return creationDate.after(now) || (expiryDate != null && expiryDate.before(now)); - } - static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector pkts, PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java index 097f530fd..590a02b95 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java @@ -9,9 +9,14 @@ import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureSubpacketVector; import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; +import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; +import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.util.IterableIterator; +import java.io.IOException; +import java.security.NoSuchProviderException; import java.util.Iterator; public class CachedSecretKeyRing extends CachedKeyRing { @@ -23,12 +28,15 @@ public class CachedSecretKeyRing extends CachedKeyRing { byte[] fingerprint, String userId, int verified, boolean hasSecret, byte[] blob) { - super(masterKeyId, keySize, isRevoked, canCertify, creation, expiry, - algorithm, fingerprint, userId, verified, hasSecret); + super(masterKeyId, canCertify, fingerprint, userId, verified, hasSecret); mRing = (PGPSecretKeyRing) PgpConversionHelper.BytesToPGPKeyRing(blob); } + PGPSecretKeyRing getRing() { + return mRing; + } + public CachedSecretKey getSubKey() { return new CachedSecretKey(this, mRing.getSecretKey()); } @@ -110,4 +118,27 @@ public class CachedSecretKeyRing extends CachedKeyRing { return false; } + public UncachedSecretKeyRing changeSecretKeyPassphrase(String oldPassphrase, + String newPassphrase) + throws IOException, PGPException, NoSuchProviderException { + + if (oldPassphrase == null) { + oldPassphrase = ""; + } + if (newPassphrase == null) { + newPassphrase = ""; + } + + PGPSecretKeyRing newKeyRing = PGPSecretKeyRing.copyWithNewPassword( + mRing, + new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build()).setProvider( + Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassphrase.toCharArray()), + new JcePBESecretKeyEncryptorBuilder(mRing.getSecretKey() + .getKeyEncryptionAlgorithm()).build(newPassphrase.toCharArray())); + + return new UncachedSecretKeyRing(newKeyRing); + + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java index 86fba979c..2199047cd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java @@ -165,36 +165,4 @@ public class PgpConversionHelper { return os.toByteArray(); } - /** - * Convert from PGPSecretKey to byte[] - * - * @param key - * @return - */ - public static byte[] PGPSecretKeyToBytes(PGPSecretKey key) { - try { - return key.getEncoded(); - } catch (IOException e) { - Log.e(Constants.TAG, "Encoding failed", e); - - return null; - } - } - - /** - * Convert from PGPSecretKeyRing to byte[] - * - * @param keyRing - * @return - */ - public static byte[] PGPSecretKeyRingToBytes(PGPSecretKeyRing keyRing) { - try { - return keyRing.getEncoded(); - } catch (IOException e) { - Log.e(Constants.TAG, "Encoding failed", e); - - return null; - } - } - } 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 6de958d8d..a7e1bd603 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java @@ -277,7 +277,7 @@ public class PgpImportExport { @SuppressWarnings("unchecked") public int storeKeyRingInCache(UncachedKeyRing keyring) { - int status = RETURN_ERROR; + int status; try { PGPSecretKeyRing secretKeyRing = keyring.getSecretRing(); PGPPublicKeyRing publicKeyRing = keyring.getPublicRing(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java index 5e78a5764..e888d594e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java @@ -81,18 +81,6 @@ public class PgpKeyHelper { return getExpiryDate(key.getPublicKey()); } - @Deprecated - public static boolean isExpired(PGPPublicKey key) { - Date creationDate = getCreationDate(key); - Date expiryDate = getExpiryDate(key); - Date now = new Date(); - if (now.compareTo(creationDate) >= 0 - && (expiryDate == null || now.compareTo(expiryDate) <= 0)) { - return false; - } - return true; - } - @SuppressWarnings("unchecked") @Deprecated public static PGPSecretKey getKeyNum(PGPSecretKeyRing keyRing, long num) { @@ -110,48 +98,6 @@ public class PgpKeyHelper { return null; } - @SuppressWarnings("unchecked") - @Deprecated - private static Vector<PGPSecretKey> getSigningKeys(PGPSecretKeyRing keyRing) { - Vector<PGPSecretKey> signingKeys = new Vector<PGPSecretKey>(); - - for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) { - if (isSigningKey(key)) { - signingKeys.add(key); - } - } - - return signingKeys; - } - - @Deprecated - private static Vector<PGPSecretKey> getUsableSigningKeys(PGPSecretKeyRing keyRing) { - Vector<PGPSecretKey> usableKeys = new Vector<PGPSecretKey>(); - Vector<PGPSecretKey> signingKeys = getSigningKeys(keyRing); - PGPSecretKey masterKey = null; - for (int i = 0; i < signingKeys.size(); ++i) { - PGPSecretKey key = signingKeys.get(i); - if (key.isMasterKey()) { - masterKey = key; - } else { - usableKeys.add(key); - } - } - if (masterKey != null) { - usableKeys.add(masterKey); - } - return usableKeys; - } - - @Deprecated - public static PGPSecretKey getFirstSigningSubkey(PGPSecretKeyRing keyRing) { - Vector<PGPSecretKey> signingKeys = getUsableSigningKeys(keyRing); - if (signingKeys.size() == 0) { - return null; - } - return signingKeys.get(0); - } - public static int getKeyUsage(PGPSecretKey key) { return getKeyUsage(key.getPublicKey()); } 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 2033a91e7..7251709e0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -35,7 +35,6 @@ import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureGenerator; import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator; -import org.spongycastle.openpgp.PGPSignatureSubpacketVector; import org.spongycastle.openpgp.PGPUtil; import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor; @@ -48,10 +47,8 @@ import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; -import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Primes; import java.io.IOException; @@ -66,7 +63,6 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Iterator; -import java.util.List; import java.util.TimeZone; /** @@ -124,7 +120,7 @@ public class PgpKeyOperation { */ // TODO: key flags? - public PGPSecretKey createKey(int algorithmChoice, int keySize, String passphrase, + public byte[] createKey(int algorithmChoice, int keySize, String passphrase, boolean isMasterKey) throws NoSuchAlgorithmException, PGPException, NoSuchProviderException, PgpGeneralMsgIdException, InvalidAlgorithmParameterException { @@ -188,35 +184,15 @@ public class PgpKeyOperation { PGPEncryptedData.CAST5, sha1Calc) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); - return new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(), - sha1Calc, isMasterKey, keyEncryptor); - } - - public PGPSecretKeyRing changeSecretKeyPassphrase(PGPSecretKeyRing keyRing, String oldPassphrase, - String newPassphrase) - throws IOException, PGPException, NoSuchProviderException { - - updateProgress(R.string.progress_building_key, 0, 100); - if (oldPassphrase == null) { - oldPassphrase = ""; - } - if (newPassphrase == null) { - newPassphrase = ""; + try { + return new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(), + sha1Calc, isMasterKey, keyEncryptor).getEncoded(); + } catch(IOException e) { + throw new PgpGeneralMsgIdException(R.string.error_encoding); } - - PGPSecretKeyRing newKeyRing = PGPSecretKeyRing.copyWithNewPassword( - keyRing, - new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build()).setProvider( - Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassphrase.toCharArray()), - new JcePBESecretKeyEncryptorBuilder(keyRing.getSecretKey() - .getKeyEncryptionAlgorithm()).build(newPassphrase.toCharArray())); - - return newKeyRing; - } - public Pair<PGPSecretKeyRing, PGPPublicKeyRing> buildNewSecretKey( + public UncachedKeyRing buildNewSecretKey( SaveKeyringParcel saveParcel) throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException { @@ -357,17 +333,19 @@ public class PgpKeyOperation { PGPSecretKeyRing secretKeyRing = keyGen.generateSecretKeyRing(); PGPPublicKeyRing publicKeyRing = keyGen.generatePublicKeyRing(); - return new Pair<PGPSecretKeyRing, PGPPublicKeyRing>(secretKeyRing, publicKeyRing); + return new UncachedKeyRing(publicKeyRing, secretKeyRing); } - public Pair<PGPSecretKeyRing, PGPPublicKeyRing> buildSecretKey(PGPSecretKeyRing mKR, - PGPPublicKeyRing pKR, + public UncachedKeyRing buildSecretKey(CachedSecretKeyRing wmKR, + CachedPublicKeyRing wpKR, SaveKeyringParcel saveParcel) throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException { + PGPSecretKeyRing mKR = wmKR.getRing(); + PGPPublicKeyRing pKR = wpKR.getRing(); + updateProgress(R.string.progress_building_key, 0, 100); - PGPSecretKey masterKey = saveParcel.keys.get(0); if (saveParcel.oldPassphrase == null) { saveParcel.oldPassphrase = ""; @@ -404,7 +382,7 @@ public class PgpKeyOperation { } } - masterKey = mKR.getSecretKey(); + PGPSecretKey masterKey = mKR.getSecretKey(); PGPPublicKey masterPublicKey = masterKey.getPublicKey(); int usageId = saveParcel.keysUsages.get(0); @@ -686,7 +664,7 @@ public class PgpKeyOperation { */ - return new Pair<PGPSecretKeyRing, PGPPublicKeyRing>(mKR, pKR); + return new UncachedKeyRing(pKR, 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 86a2ed48d..58601c49a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -1,7 +1,15 @@ package org.sufficientlysecure.keychain.pgp; +import org.spongycastle.openpgp.PGPObjectFactory; import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPSecretKeyRing; +import org.spongycastle.openpgp.PGPUtil; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; public class UncachedKeyRing { @@ -9,8 +17,6 @@ public class UncachedKeyRing { final PGPSecretKeyRing mSecretRing; UncachedKeyRing(PGPPublicKeyRing publicRing, PGPSecretKeyRing secretRing) { - // this one must not be false! - assert(publicRing != null); mPublicRing = publicRing; mSecretRing = secretRing; } @@ -26,4 +32,29 @@ public class UncachedKeyRing { public PGPSecretKeyRing getSecretRing() { return mSecretRing; } + + public byte[] getFingerprint() { + return mPublicRing.getPublicKey().getFingerprint(); + } + + public static UncachedKeyRing decodePubkeyFromData(byte[] data) + throws PgpGeneralException, IOException { + BufferedInputStream bufferedInput = + new BufferedInputStream(new ByteArrayInputStream(data)); + if (bufferedInput.available() > 0) { + InputStream in = PGPUtil.getDecoderStream(bufferedInput); + PGPObjectFactory objectFactory = new PGPObjectFactory(in); + + // get first object in block + Object obj; + if ((obj = objectFactory.nextObject()) != null && obj instanceof PGPPublicKeyRing) { + return new UncachedKeyRing((PGPPublicKeyRing) obj); + } else { + throw new PgpGeneralException("Object not recognized as PGPPublicKeyRing!"); + } + } else { + throw new PgpGeneralException("Object not recognized as PGPPublicKeyRing!"); + } + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKeyRing.java new file mode 100644 index 000000000..bda9ebbcf --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKeyRing.java @@ -0,0 +1,19 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.openpgp.PGPSecretKeyRing; + +public class UncachedSecretKeyRing { + + final PGPSecretKeyRing mSecretRing; + + UncachedSecretKeyRing(PGPSecretKeyRing secretRing) { + mSecretRing = secretRing; + } + + // Breaking the pattern here, for key import! + // TODO reduce this from public to default visibility! + public PGPSecretKeyRing getSecretKeyRing() { + return mSecretRing; + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 0fe989e84..b135f8920 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -43,6 +43,8 @@ import org.sufficientlysecure.keychain.pgp.CachedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; +import org.sufficientlysecure.keychain.pgp.UncachedSecretKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; @@ -488,8 +490,18 @@ public class ProviderHelper { * Saves a PGPSecretKeyRing in the DB. This will only work if a corresponding public keyring * is already in the database! */ + public void saveKeyRing(UncachedSecretKeyRing wrappedRing) throws IOException { + // TODO split up getters + PGPSecretKeyRing keyRing = wrappedRing.getSecretKeyRing(); + saveKeyRing(keyRing); + } + + /** + * Saves a PGPSecretKeyRing in the DB. This will only work if a corresponding public keyring + * is already in the database! + */ public void saveKeyRing(PGPSecretKeyRing keyRing) throws IOException { - long masterKeyId = keyRing.getPublicKey().getKeyID(); + long masterKeyId = keyRing.getSecretKey().getKeyID(); { Uri uri = Keys.buildKeysUri(Long.toString(masterKeyId)); @@ -526,6 +538,12 @@ public class ProviderHelper { } + public void saveKeyRing(UncachedKeyRing wrappedRing) throws IOException { + PGPPublicKeyRing pubRing = wrappedRing.getPublicRing(); + PGPSecretKeyRing secRing = wrappedRing.getSecretRing(); + saveKeyRing(pubRing, secRing); + } + /** * Saves (or updates) a pair of public and secret KeyRings in the database */ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index d02906c4f..972362f5f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -27,12 +27,6 @@ import android.os.Messenger; import android.os.RemoteException; import org.spongycastle.bcpg.sig.KeyFlags; -import org.spongycastle.openpgp.PGPKeyRing; -import org.spongycastle.openpgp.PGPObjectFactory; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.spongycastle.openpgp.PGPUtil; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; @@ -41,7 +35,6 @@ import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.pgp.CachedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.CachedSecretKey; import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing; -import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.PgpHelper; @@ -51,6 +44,7 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyOperation; import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt; import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; +import org.sufficientlysecure.keychain.pgp.UncachedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; @@ -63,7 +57,6 @@ import org.sufficientlysecure.keychain.util.KeychainServiceListener; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressScaler; -import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -516,19 +509,19 @@ public class KeychainIntentService extends IntentService /* Operation */ ProviderHelper providerHelper = new ProviderHelper(this); if (!canSign) { - PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 50, 100)); - PGPSecretKeyRing keyRing = providerHelper.getPGPSecretKeyRing(masterKeyId); - keyRing = keyOperations.changeSecretKeyPassphrase(keyRing, - oldPassphrase, newPassphrase); + setProgress(R.string.progress_building_key, 0, 100); + CachedSecretKeyRing keyRing = providerHelper.getCachedSecretKeyRing(masterKeyId); + UncachedSecretKeyRing newKeyRing = + keyRing.changeSecretKeyPassphrase(oldPassphrase, newPassphrase); setProgress(R.string.progress_saving_key_ring, 50, 100); - providerHelper.saveKeyRing(keyRing); + providerHelper.saveKeyRing(newKeyRing); setProgress(R.string.progress_done, 100, 100); } else { PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 90, 100)); - PgpKeyOperation.Pair<PGPSecretKeyRing, PGPPublicKeyRing> pair; + UncachedKeyRing pair; try { - PGPSecretKeyRing privkey = providerHelper.getPGPSecretKeyRing(masterKeyId); - PGPPublicKeyRing pubkey = providerHelper.getPGPPublicKeyRing(masterKeyId); + CachedSecretKeyRing privkey = providerHelper.getCachedSecretKeyRing(masterKeyId); + CachedPublicKeyRing pubkey = providerHelper.getCachedPublicKeyRing(masterKeyId); pair = keyOperations.buildSecretKey(privkey, pubkey, saveParcel); // edit existing } catch (ProviderHelper.NotFoundException e) { @@ -537,7 +530,7 @@ public class KeychainIntentService extends IntentService setProgress(R.string.progress_saving_key_ring, 90, 100); // save the pair - providerHelper.saveKeyRing(pair.second, pair.first); + providerHelper.saveKeyRing(pair); setProgress(R.string.progress_done, 100, 100); } PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassphrase); @@ -557,13 +550,11 @@ public class KeychainIntentService extends IntentService /* Operation */ PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 100, 100)); - PGPSecretKey newKey = keyOperations.createKey(algorithm, keysize, - passphrase, masterKey); + byte[] newKey = keyOperations.createKey(algorithm, keysize, passphrase, masterKey); /* Output */ Bundle resultData = new Bundle(); - resultData.putByteArray(RESULT_NEW_KEY, - PgpConversionHelper.PGPSecretKeyToBytes(newKey)); + resultData.putByteArray(RESULT_NEW_KEY, newKey); OtherHelper.logDebugBundle(resultData, "resultData"); @@ -576,7 +567,6 @@ public class KeychainIntentService extends IntentService try { /* Input */ String passphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE); - ArrayList<PGPSecretKey> newKeys = new ArrayList<PGPSecretKey>(); ArrayList<Integer> keyUsageList = new ArrayList<Integer>(); /* Operation */ @@ -589,23 +579,27 @@ public class KeychainIntentService extends IntentService keysTotal); PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 100, 100)); - PGPSecretKey masterKey = keyOperations.createKey(Constants.choice.algorithm.rsa, + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + byte[] buf; + + buf = keyOperations.createKey(Constants.choice.algorithm.rsa, 4096, passphrase, true); - newKeys.add(masterKey); + os.write(buf); keyUsageList.add(KeyFlags.CERTIFY_OTHER); keysCreated++; setProgress(keysCreated, keysTotal); - PGPSecretKey subKey = keyOperations.createKey(Constants.choice.algorithm.rsa, + buf = keyOperations.createKey(Constants.choice.algorithm.rsa, 4096, passphrase, false); - newKeys.add(subKey); + os.write(buf); keyUsageList.add(KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE); keysCreated++; setProgress(keysCreated, keysTotal); - subKey = keyOperations.createKey(Constants.choice.algorithm.rsa, + buf = keyOperations.createKey(Constants.choice.algorithm.rsa, 4096, passphrase, false); - newKeys.add(subKey); + os.write(buf); keyUsageList.add(KeyFlags.SIGN_DATA); keysCreated++; setProgress(keysCreated, keysTotal); @@ -614,10 +608,8 @@ public class KeychainIntentService extends IntentService // for sign /* Output */ - Bundle resultData = new Bundle(); - resultData.putByteArray(RESULT_NEW_KEY, - PgpConversionHelper.PGPSecretKeyArrayListToBytes(newKeys)); + resultData.putByteArray(RESULT_NEW_KEY, os.toByteArray()); resultData.putIntegerArrayList(RESULT_KEY_USAGES, keyUsageList); OtherHelper.logDebugBundle(resultData, "resultData"); @@ -755,30 +747,13 @@ public class KeychainIntentService extends IntentService } // create PGPKeyRing object based on downloaded armored key - PGPKeyRing downloadedKey = null; - BufferedInputStream bufferedInput = - new BufferedInputStream(new ByteArrayInputStream(downloadedKeyBytes)); - if (bufferedInput.available() > 0) { - InputStream in = PGPUtil.getDecoderStream(bufferedInput); - PGPObjectFactory objectFactory = new PGPObjectFactory(in); - - // get first object in block - Object obj; - if ((obj = objectFactory.nextObject()) != null) { - Log.d(Constants.TAG, "Found class: " + obj.getClass()); - - if (obj instanceof PGPKeyRing) { - downloadedKey = (PGPKeyRing) obj; - } else { - throw new PgpGeneralException("Object not recognized as PGPKeyRing!"); - } - } - } + UncachedKeyRing downloadedKey = + UncachedKeyRing.decodePubkeyFromData(downloadedKeyBytes); // verify downloaded key by comparing fingerprints if (entry.getFingerPrintHex() != null) { String downloadedKeyFp = PgpKeyHelper.convertFingerprintToHex( - downloadedKey.getPublicKey().getFingerprint()); + downloadedKey.getFingerprint()); if (downloadedKeyFp.equals(entry.getFingerPrintHex())) { Log.d(Constants.TAG, "fingerprint of downloaded key is the same as " + "the requested fingerprint!"); @@ -790,7 +765,7 @@ public class KeychainIntentService extends IntentService // save key bytes in entry object for doing the // actual import afterwards - entry.setBytes(downloadedKey.getEncoded()); + entry.setBytes(downloadedKeyBytes); } Intent importIntent = new Intent(this, KeychainIntentService.class); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index d1a5dca07..51a229677 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -34,7 +34,12 @@ import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.CachedPublicKey; +import org.sufficientlysecure.keychain.pgp.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.pgp.CachedSecretKey; +import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.Log; @@ -144,18 +149,14 @@ public class EncryptAsymmetricFragment extends Fragment { */ private void preselectKeys(long preselectedSignatureKeyId, long[] preselectedEncryptionKeyIds, ProviderHelper providerHelper) { + // TODO all of this works under the assumption that the first suitable subkey is always used! + // not sure if we need to distinguish between different subkeys here? if (preselectedSignatureKeyId != 0) { - // TODO: don't use bouncy castle objects! try { - PGPSecretKeyRing keyRing = providerHelper.getPGPSecretKeyRingWithKeyId( - preselectedSignatureKeyId); - - PGPSecretKey masterKey = keyRing.getSecretKey(); - if (masterKey != null) { - PGPSecretKey signKey = PgpKeyHelper.getFirstSigningSubkey(keyRing); - if (signKey != null) { - setSignatureKeyId(masterKey.getKeyID()); - } + CachedPublicKeyRing keyring = + providerHelper.getCachedPublicKeyRing(preselectedSignatureKeyId); + if(keyring.hasSecret()) { + setSignatureKeyId(keyring.getMasterKeyId()); } } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "key not found!", e); @@ -165,7 +166,6 @@ public class EncryptAsymmetricFragment extends Fragment { if (preselectedEncryptionKeyIds != null) { Vector<Long> goodIds = new Vector<Long>(); for (int i = 0; i < preselectedEncryptionKeyIds.length; ++i) { - // TODO One query per selected key?! wtf try { long id = providerHelper.getMasterKeyId( KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 330bc349d..72a1b38cc 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -500,5 +500,6 @@ <string name="title_view_cert">View Certificate Details</string> <string name="unknown_algorithm">unknown</string> <string name="can_sign_not">cannot sign</string> + <string name="error_encoding">Encoding error</string> </resources> |