From 4b3cfd4fa41ef8339a0691b38c4c6ec481b5c3df Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 3 May 2014 15:55:10 +0200 Subject: wrapped-key-ring: first steps, get rid of key imports in decryptverify and signencrypt --- .../keychain/pgp/CachedKeyRing.java | 61 +++++ .../keychain/pgp/CachedPublicKey.java | 53 ++++ .../keychain/pgp/CachedPublicKeyRing.java | 219 ++++++++++++++++ .../keychain/pgp/CachedSecretKey.java | 121 +++++++++ .../keychain/pgp/CachedSecretKeyRing.java | 74 ++++++ .../keychain/pgp/PgpDecryptVerify.java | 274 ++++----------------- .../keychain/pgp/PgpImportExport.java | 8 +- .../keychain/pgp/PgpKeyHelper.java | 48 ++-- .../keychain/pgp/PgpSignEncrypt.java | 82 ++---- .../keychain/provider/KeychainContract.java | 6 + .../keychain/provider/KeychainProvider.java | 22 ++ .../keychain/provider/ProviderHelper.java | 96 +++++++- 12 files changed, 744 insertions(+), 320 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java new file mode 100644 index 000000000..5cf89b6a6 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java @@ -0,0 +1,61 @@ +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, + 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; + } + + public String getPrimaryUserId() { + return mUserId; + } + + public long getMasterKeyId() { + return mMasterKeyId; + } + + public int getVerified() { + return mVerified; + } + + public void initSignature(PGPSignature sig) { + + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java new file mode 100644 index 000000000..fb065c85f --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java @@ -0,0 +1,53 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPOnePassSignature; +import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.openpgp.PGPSignature; +import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; +import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator; +import org.sufficientlysecure.keychain.Constants; + +public class CachedPublicKey { + + // this is the parent key ring + private final CachedPublicKeyRing mRing; + + private final PGPPublicKey mKey; + + CachedPublicKey(CachedPublicKeyRing ring, PGPPublicKey key) { + mRing = ring; + mKey = key; + } + + public CachedPublicKeyRing getKeyRing() { + return mRing; + } + + JcePublicKeyKeyEncryptionMethodGenerator getPubKeyEncryptionGenerator() { + return new JcePublicKeyKeyEncryptionMethodGenerator(mKey); + } + + public void initSignature(PGPSignature sig) throws PGPException { + JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = + new JcaPGPContentVerifierBuilderProvider() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + sig.init(contentVerifierBuilderProvider, mKey); + } + + public void initSignature(PGPOnePassSignature sig) throws PGPException { + JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = + new JcaPGPContentVerifierBuilderProvider() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + sig.init(contentVerifierBuilderProvider, mKey); + } + + 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 new file mode 100644 index 000000000..fb142adce --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java @@ -0,0 +1,219 @@ +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; +import org.spongycastle.openpgp.PGPSignature; +import org.spongycastle.openpgp.PGPSignatureList; +import org.spongycastle.openpgp.PGPSignatureSubpacketVector; +import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +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 { + + private PGPPublicKeyRing mRing; + private final byte[] mPubKey; + + public CachedPublicKeyRing(long masterKeyId, int keySize, boolean isRevoked, + boolean canCertify, long creation, long expiry, int algorithm, + byte[] fingerprint, String userId, int verified, boolean hasSecret, + byte[] pubkey) + { + super(masterKeyId, keySize, isRevoked, canCertify, creation, expiry, + algorithm, fingerprint, userId, verified, hasSecret); + + mPubKey = pubkey; + } + + private PGPPublicKeyRing getRing() { + if(mRing == null) { + mRing = (PGPPublicKeyRing) PgpConversionHelper.BytesToPGPKeyRing(mPubKey); + } + return mRing; + } + + public void encode(ArmoredOutputStream stream) throws IOException { + getRing().encode(stream); + } + + public CachedPublicKey getSubkey(long id) { + return new CachedPublicKey(this, getRing().getPublicKey(id)); + } + + public CachedPublicKey getFirstEncryptSubkey() throws PgpGeneralException { + // only return master key if no other encryption key is available + PGPPublicKey masterKey = null; + for (PGPPublicKey key : new IterableIterator(getRing().getPublicKeys())) { + if (key.isRevoked() || !isEncryptionKey(key) || isExpired(key)) { + continue; + } + if (key.isMasterKey()) { + masterKey = key; + } else { + return new CachedPublicKey(this, key); + } + } + if(masterKey == null) { + // TODO proper exception + throw new PgpGeneralException("key not found"); + } + return new CachedPublicKey(this, masterKey); + } + + public boolean verifySubkeyBinding(CachedPublicKey cachedSubkey) { + boolean validSubkeyBinding = false; + boolean validTempSubkeyBinding = false; + boolean validPrimaryKeyBinding = false; + + PGPPublicKey masterKey = getRing().getPublicKey(); + PGPPublicKey subKey = cachedSubkey.getKey(); + + // Is this the master key? Match automatically, then. + if(Arrays.equals(masterKey.getFingerprint(), subKey.getFingerprint())) { + return true; + } + + JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = + new JcaPGPContentVerifierBuilderProvider() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + + Iterator itr = subKey.getSignatures(); + + while (itr.hasNext()) { //what does gpg do if the subkey binding is wrong? + //gpg has an invalid subkey binding error on key import I think, but doesn't shout + //about keys without subkey signing. Can't get it to import a slightly broken one + //either, so we will err on bad subkey binding here. + PGPSignature sig = itr.next(); + if (sig.getKeyID() == masterKey.getKeyID() && + sig.getSignatureType() == PGPSignature.SUBKEY_BINDING) { + //check and if ok, check primary key binding. + try { + sig.init(contentVerifierBuilderProvider, masterKey); + validTempSubkeyBinding = sig.verifyCertification(masterKey, subKey); + } catch (PGPException e) { + continue; + } catch (SignatureException e) { + continue; + } + + if (validTempSubkeyBinding) { + validSubkeyBinding = true; + } + if (validTempSubkeyBinding) { + validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getUnhashedSubPackets(), + masterKey, subKey); + if (validPrimaryKeyBinding) { + break; + } + validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getHashedSubPackets(), + masterKey, subKey); + if (validPrimaryKeyBinding) { + break; + } + } + } + } + return validSubkeyBinding && validPrimaryKeyBinding; + + } + + + 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(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) { + boolean validPrimaryKeyBinding = false; + JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = + new JcaPGPContentVerifierBuilderProvider() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + PGPSignatureList eSigList; + + if (pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) { + try { + eSigList = pkts.getEmbeddedSignatures(); + } catch (IOException e) { + return false; + } catch (PGPException e) { + return false; + } + for (int j = 0; j < eSigList.size(); ++j) { + PGPSignature emSig = eSigList.get(j); + if (emSig.getSignatureType() == PGPSignature.PRIMARYKEY_BINDING) { + try { + emSig.init(contentVerifierBuilderProvider, signingPublicKey); + validPrimaryKeyBinding = emSig.verifyCertification(masterPublicKey, signingPublicKey); + if (validPrimaryKeyBinding) { + break; + } + } catch (PGPException e) { + continue; + } catch (SignatureException e) { + continue; + } + } + } + } + + return validPrimaryKeyBinding; + } + +} \ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java new file mode 100644 index 000000000..514fca6fb --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java @@ -0,0 +1,121 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPPrivateKey; +import org.spongycastle.openpgp.PGPSecretKey; +import org.spongycastle.openpgp.PGPSignature; +import org.spongycastle.openpgp.PGPSignatureGenerator; +import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator; +import org.spongycastle.openpgp.PGPV3SignatureGenerator; +import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; +import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory; +import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; +import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; +import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; + +public class CachedSecretKey { + + // this is the parent key ring + private final CachedSecretKeyRing mRing; + + private final PGPSecretKey mKey; + private PGPPrivateKey mPrivateKey = null; + + CachedSecretKey(CachedSecretKeyRing ring, PGPSecretKey key) { + mRing = ring; + mKey = key; + } + + public CachedSecretKeyRing getRing() { + return mRing; + } + + public void unlock(String passphrase) throws PgpGeneralException { + try { + PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( + Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); + mPrivateKey = mKey.extractPrivateKey(keyDecryptor); + } catch (PGPException e) { + throw new PgpGeneralException("error extracting key!", e); + } + if(mPrivateKey == null) { + throw new PgpGeneralException("error extracting key (bad passphrase?)"); + } + } + + public PGPSignatureGenerator getSignatureGenerator(int hashAlgo, boolean cleartext) + throws PgpGeneralException { + if(mPrivateKey == null) { + throw new PrivateKeyNotUnlockedException(); + } + + // content signer based on signing key algorithm and chosen hash algorithm + JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( + mKey.getPublicKey().getAlgorithm(), hashAlgo) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + + int signatureType; + if (cleartext) { + // for sign-only ascii text + signatureType = PGPSignature.CANONICAL_TEXT_DOCUMENT; + } else { + signatureType = PGPSignature.BINARY_DOCUMENT; + } + + try { + PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder); + signatureGenerator.init(signatureType, mPrivateKey); + + PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); + spGen.setSignerUserID(false, mRing.getPrimaryUserId()); + signatureGenerator.setHashedSubpackets(spGen.generate()); + return signatureGenerator; + } catch(PGPException e) { + throw new PgpGeneralException("Error initializing signature!", e); + } + } + + public PGPV3SignatureGenerator getV3SignatureGenerator(int hashAlgo, boolean cleartext) + throws PgpGeneralException { + if(mPrivateKey == null) { + throw new PrivateKeyNotUnlockedException(); + } + + // content signer based on signing key algorithm and chosen hash algorithm + JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( + mKey.getPublicKey().getAlgorithm(), hashAlgo) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + + int signatureType; + if (cleartext) { + // for sign-only ascii text + signatureType = PGPSignature.CANONICAL_TEXT_DOCUMENT; + } else { + signatureType = PGPSignature.BINARY_DOCUMENT; + } + + try { + PGPV3SignatureGenerator signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder); + signatureV3Generator.init(signatureType, mPrivateKey); + return signatureV3Generator; + } catch(PGPException e) { + throw new PgpGeneralException("Error initializing signature!", e); + } + } + + public PublicKeyDataDecryptorFactory getDecryptorFactory() { + if(mPrivateKey == null) { + throw new PrivateKeyNotUnlockedException(); + } + return new JcePublicKeyDataDecryptorFactoryBuilder() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(mPrivateKey); + } + + static class PrivateKeyNotUnlockedException extends RuntimeException { + // this exception is a programming error which happens when an operation which requires + // the private key is called without a previous call to unlock() + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java new file mode 100644 index 000000000..a2b2b2832 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java @@ -0,0 +1,74 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.bcpg.sig.KeyFlags; +import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.openpgp.PGPSecretKey; +import org.spongycastle.openpgp.PGPSecretKeyRing; +import org.spongycastle.openpgp.PGPSignature; +import org.spongycastle.openpgp.PGPSignatureSubpacketVector; +import org.sufficientlysecure.keychain.util.IterableIterator; + +public class CachedSecretKeyRing extends CachedKeyRing { + + private PGPSecretKeyRing mRing; + + public CachedSecretKeyRing(long masterKeyId, int keySize, boolean isRevoked, + boolean canCertify, long creation, long expiry, int algorithm, + byte[] fingerprint, String userId, int verified, boolean hasSecret, + byte[] blob) + { + super(masterKeyId, keySize, isRevoked, canCertify, creation, expiry, + algorithm, fingerprint, userId, verified, hasSecret); + + mRing = (PGPSecretKeyRing) PgpConversionHelper.BytesToPGPKeyRing(blob); + } + + CachedSecretKey getSubKey(long id) { + return new CachedSecretKey(this, mRing.getSecretKey(id)); + } + + /** This returns the subkey that should be used for signing. + * At this point, this is simply the first suitable subkey. + */ + CachedSecretKey getSigningSubKey() { + for (PGPSecretKey key : new IterableIterator(mRing.getSecretKeys())) { + if (isSigningKey(key.getPublicKey())) { + return new CachedSecretKey(this, key); + } + } + // TODO exception + return null; + } + + @SuppressWarnings("unchecked") + public static boolean isSigningKey(PGPPublicKey key) { + if (key.getVersion() <= 3) { + return true; + } + + // special case + if (key.getAlgorithm() == PGPPublicKey.RSA_SIGN) { + return true; + } + + for (PGPSignature sig : new IterableIterator(key.getSignatures())) { + if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) { + continue; + } + PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets(); + + if (hashed != null && (hashed.getKeyFlags() & KeyFlags.SIGN_DATA) != 0) { + return true; + } + + PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets(); + + if (unhashed != null && (unhashed.getKeyFlags() & KeyFlags.SIGN_DATA) != 0) { + return true; + } + } + + return false; + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 506c161ba..c84b9413f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -18,10 +18,7 @@ package org.sufficientlysecure.keychain.pgp; -import android.net.Uri; - import org.spongycastle.bcpg.ArmoredInputStream; -import org.spongycastle.bcpg.SignatureSubpacketTags; import org.spongycastle.openpgp.PGPCompressedData; import org.spongycastle.openpgp.PGPEncryptedData; import org.spongycastle.openpgp.PGPEncryptedDataList; @@ -31,29 +28,18 @@ import org.spongycastle.openpgp.PGPObjectFactory; import org.spongycastle.openpgp.PGPOnePassSignature; import org.spongycastle.openpgp.PGPOnePassSignatureList; import org.spongycastle.openpgp.PGPPBEEncryptedData; -import org.spongycastle.openpgp.PGPPrivateKey; -import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPPublicKeyEncryptedData; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureList; -import org.spongycastle.openpgp.PGPSignatureSubpacketVector; import org.spongycastle.openpgp.PGPUtil; import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory; -import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider; import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory; -import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder; -import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; -import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.Progressable; -import org.sufficientlysecure.keychain.provider.KeychainContract; +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.InputData; @@ -67,7 +53,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.security.SignatureException; import java.util.Iterator; -import java.util.Map; import java.util.Set; /** @@ -248,7 +233,7 @@ public class PgpDecryptVerify { PGPPublicKeyEncryptedData encryptedDataAsymmetric = null; PGPPBEEncryptedData encryptedDataSymmetric = null; - PGPSecretKey secretEncryptionKey = null; + CachedSecretKey secretEncryptionKey = null; Iterator it = enc.getEncryptedDataObjects(); boolean asymmetricPacketFound = false; boolean symmetricPacketFound = false; @@ -260,15 +245,13 @@ public class PgpDecryptVerify { PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj; - long masterKeyId; - PGPSecretKeyRing secretKeyRing; + CachedSecretKeyRing secretKeyRing; try { - // get master key id for this encryption key id - masterKeyId = mProviderHelper.getMasterKeyId( - KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(encData.getKeyID())) - ); // get actual keyring object based on master key id - secretKeyRing = mProviderHelper.getPGPSecretKeyRing(masterKeyId); + secretKeyRing = mProviderHelper.getCachedSecretKeyRing( + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( + Long.toString(encData.getKeyID())) + ); } catch (ProviderHelper.NotFoundException e) { // continue with the next packet in the while loop continue; @@ -278,13 +261,14 @@ public class PgpDecryptVerify { continue; } // get subkey which has been used for this encryption packet - secretEncryptionKey = secretKeyRing.getSecretKey(encData.getKeyID()); + secretEncryptionKey = secretKeyRing.getSubKey(encData.getKeyID()); if (secretEncryptionKey == null) { // continue with the next packet in the while loop continue; } /* secret key exists in database! */ + long masterKeyId = secretEncryptionKey.getRing().getMasterKeyId(); // allow only specific keys for decryption? if (mAllowedKeyIds != null) { @@ -359,23 +343,15 @@ public class PgpDecryptVerify { } else if (asymmetricPacketFound) { currentProgress += 5; updateProgress(R.string.progress_extracting_key, currentProgress, 100); - PGPPrivateKey privateKey; try { - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( - mPassphrase.toCharArray()); - privateKey = secretEncryptionKey.extractPrivateKey(keyDecryptor); - } catch (PGPException e) { + secretEncryptionKey.unlock(mPassphrase); + } catch (PgpGeneralException e) { throw new WrongPassphraseException(); } - if (privateKey == null) { - throw new KeyExtractionException(); - } currentProgress += 5; updateProgress(R.string.progress_preparing_streams, currentProgress, 100); - PublicKeyDataDecryptorFactory decryptorFactory = new JcePublicKeyDataDecryptorFactoryBuilder() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(privateKey); + PublicKeyDataDecryptorFactory decryptorFactory = secretEncryptionKey.getDecryptorFactory(); clear = encryptedDataAsymmetric.getDataStream(decryptorFactory); @@ -388,10 +364,9 @@ public class PgpDecryptVerify { PGPObjectFactory plainFact = new PGPObjectFactory(clear); Object dataChunk = plainFact.nextObject(); - PGPOnePassSignature signature = null; OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); - PGPPublicKey signatureKey = null; int signatureIndex = -1; + CachedPublicKey signingKey = null; if (dataChunk instanceof PGPCompressedData) { updateProgress(R.string.progress_decompressing_data, currentProgress, 100); @@ -403,6 +378,8 @@ public class PgpDecryptVerify { currentProgress += 10; } + PGPOnePassSignature signature = null; + if (dataChunk instanceof PGPOnePassSignatureList) { updateProgress(R.string.progress_processing_signature, currentProgress, 100); @@ -410,19 +387,15 @@ public class PgpDecryptVerify { // go through all signatures // and find out for which signature we have a key in our database - Long masterKeyId = null; - String primaryUserId = null; for (int i = 0; i < sigList.size(); ++i) { try { - Uri uri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( - Long.toString(sigList.get(i).getKeyID())); - Map data = mProviderHelper.getGenericData(uri, - new String[] { KeyRings.MASTER_KEY_ID, KeyRings.USER_ID }, - new int[] { ProviderHelper.FIELD_TYPE_INTEGER, - ProviderHelper.FIELD_TYPE_STRING } + long sigKeyId = sigList.get(i).getKeyID(); + CachedPublicKeyRing signingRing = mProviderHelper.getCachedPublicKeyRing( + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( + Long.toString(sigKeyId) + ) ); - masterKeyId = (Long) data.get(KeyRings.MASTER_KEY_ID); - primaryUserId = (String) data.get(KeyRings.USER_ID); + signingKey = signingRing.getSubkey(sigKeyId); signatureIndex = i; } catch (ProviderHelper.NotFoundException e) { Log.d(Constants.TAG, "key not found!"); @@ -430,43 +403,17 @@ public class PgpDecryptVerify { } } - if (masterKeyId != null) { + if (signingKey != null) { // key found in our database! signature = sigList.get(signatureIndex); - PGPPublicKeyRing publicKeyRing = null; - try { - publicKeyRing = mProviderHelper - .getPGPPublicKeyRing(masterKeyId); - } catch (ProviderHelper.NotFoundException e) { - // can't happen - } - - // get the subkey which has been used to generate this signature - signatureKey = publicKeyRing.getPublicKey(signature.getKeyID()); - signatureResultBuilder.signatureAvailable(true); signatureResultBuilder.knownKey(true); - signatureResultBuilder.userId(primaryUserId); - signatureResultBuilder.keyId(masterKeyId); + signatureResultBuilder.keyId(signingKey.getKeyRing().getMasterKeyId()); + signatureResultBuilder.userId(signingKey.getKeyRing().getPrimaryUserId()); + signatureResultBuilder.signatureKeyCertified(signingKey.getKeyRing().getVerified() > 0); - JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = - new JcaPGPContentVerifierBuilderProvider() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - signature.init(contentVerifierBuilderProvider, signatureKey); - - // get certification status of this key - boolean isSignatureKeyCertified; - try { - Object data = mProviderHelper.getGenericData( - KeychainContract.KeyRings.buildUnifiedKeyRingUri(Long.toString(masterKeyId)), - KeyRings.VERIFIED, - ProviderHelper.FIELD_TYPE_INTEGER); - isSignatureKeyCertified = ((Long) data > 0); - } catch (ProviderHelper.NotFoundException e) { - isSignatureKeyCertified = false; - } - signatureResultBuilder.signatureKeyCertified(isSignatureKeyCertified); + signingKey.initSignature(signature); } else { // no key in our database -> return "unknown pub key" status including the first key id if (!sigList.isEmpty()) { @@ -541,7 +488,7 @@ public class PgpDecryptVerify { // Verify signature and check binding signatures boolean validSignature = signature.verify(messageSignature); - boolean validKeyBinding = verifyKeyBinding(messageSignature, signatureKey); + boolean validKeyBinding = signingKey.getKeyRing().verifySubkeyBinding(signingKey); signatureResultBuilder.validSignature(validSignature); signatureResultBuilder.validKeyBinding(validKeyBinding); @@ -617,22 +564,20 @@ public class PgpDecryptVerify { throw new InvalidDataException(); } + CachedPublicKey signingKey = null; + int signatureIndex = -1; + // go through all signatures // and find out for which signature we have a key in our database - Long masterKeyId = null; - String primaryUserId = null; - int signatureIndex = 0; for (int i = 0; i < sigList.size(); ++i) { try { - Uri uri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( - Long.toString(sigList.get(i).getKeyID())); - Map data = mProviderHelper.getGenericData(uri, - new String[] { KeyRings.MASTER_KEY_ID, KeyRings.USER_ID }, - new int[] { ProviderHelper.FIELD_TYPE_INTEGER, - ProviderHelper.FIELD_TYPE_STRING } + long sigKeyId = sigList.get(i).getKeyID(); + CachedPublicKeyRing signingRing = mProviderHelper.getCachedPublicKeyRing( + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( + Long.toString(sigKeyId) + ) ); - masterKeyId = (Long) data.get(KeyRings.MASTER_KEY_ID); - primaryUserId = (String) data.get(KeyRings.USER_ID); + signingKey = signingRing.getSubkey(sigKeyId); signatureIndex = i; } catch (ProviderHelper.NotFoundException e) { Log.d(Constants.TAG, "key not found!"); @@ -641,44 +586,18 @@ public class PgpDecryptVerify { } PGPSignature signature = null; - PGPPublicKey signatureKey = null; - if (masterKeyId != null) { + + if (signingKey != null) { // key found in our database! signature = sigList.get(signatureIndex); - PGPPublicKeyRing publicKeyRing = null; - try { - publicKeyRing = mProviderHelper - .getPGPPublicKeyRing(masterKeyId); - } catch (ProviderHelper.NotFoundException e) { - // can't happen - } - - // get the subkey which has been used to generate this signature - signatureKey = publicKeyRing.getPublicKey(signature.getKeyID()); - signatureResultBuilder.signatureAvailable(true); signatureResultBuilder.knownKey(true); - signatureResultBuilder.userId(primaryUserId); - signatureResultBuilder.keyId(masterKeyId); + signatureResultBuilder.keyId(signingKey.getKeyRing().getMasterKeyId()); + signatureResultBuilder.userId(signingKey.getKeyRing().getPrimaryUserId()); + signatureResultBuilder.signatureKeyCertified(signingKey.getKeyRing().getVerified() > 0); - JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = - new JcaPGPContentVerifierBuilderProvider() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - signature.init(contentVerifierBuilderProvider, signatureKey); - - // get certification status of this key - boolean isSignatureKeyCertified; - try { - Object data = mProviderHelper.getGenericData( - KeychainContract.KeyRings.buildUnifiedKeyRingUri(Long.toString(masterKeyId)), - KeyRings.VERIFIED, - ProviderHelper.FIELD_TYPE_INTEGER); - isSignatureKeyCertified = ((Long) data > 0); - } catch (ProviderHelper.NotFoundException e) { - isSignatureKeyCertified = false; - } - signatureResultBuilder.signatureKeyCertified(isSignatureKeyCertified); + signingKey.initSignature(signature); } else { // no key in our database -> return "unknown pub key" status including the first key id if (!sigList.isEmpty()) { @@ -710,7 +629,7 @@ public class PgpDecryptVerify { // Verify signature and check binding signatures boolean validSignature = signature.verify(); - boolean validKeyBinding = verifyKeyBinding(signature, signatureKey); + boolean validKeyBinding = signingKey.getKeyRing().verifySubkeyBinding(signingKey); signatureResultBuilder.validSignature(validSignature); signatureResultBuilder.validKeyBinding(validKeyBinding); @@ -722,113 +641,6 @@ public class PgpDecryptVerify { return result; } - private boolean verifyKeyBinding(PGPSignature signature, PGPPublicKey signatureKey) { - long signatureKeyId = signature.getKeyID(); - boolean validKeyBinding = false; - - PGPPublicKey mKey = null; - try { - PGPPublicKeyRing signKeyRing = mProviderHelper.getPGPPublicKeyRingWithKeyId( - signatureKeyId); - mKey = signKeyRing.getPublicKey(); - } catch (ProviderHelper.NotFoundException e) { - Log.d(Constants.TAG, "key not found"); - } - - if (signature.getKeyID() != mKey.getKeyID()) { - validKeyBinding = verifyKeyBinding(mKey, signatureKey); - } else { //if the key used to make the signature was the master key, no need to check binding sigs - validKeyBinding = true; - } - return validKeyBinding; - } - - private boolean verifyKeyBinding(PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) { - boolean validSubkeyBinding = false; - boolean validTempSubkeyBinding = false; - boolean validPrimaryKeyBinding = false; - - JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = - new JcaPGPContentVerifierBuilderProvider() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - - Iterator itr = signingPublicKey.getSignatures(); - - while (itr.hasNext()) { //what does gpg do if the subkey binding is wrong? - //gpg has an invalid subkey binding error on key import I think, but doesn't shout - //about keys without subkey signing. Can't get it to import a slightly broken one - //either, so we will err on bad subkey binding here. - PGPSignature sig = itr.next(); - if (sig.getKeyID() == masterPublicKey.getKeyID() && - sig.getSignatureType() == PGPSignature.SUBKEY_BINDING) { - //check and if ok, check primary key binding. - try { - sig.init(contentVerifierBuilderProvider, masterPublicKey); - validTempSubkeyBinding = sig.verifyCertification(masterPublicKey, signingPublicKey); - } catch (PGPException e) { - continue; - } catch (SignatureException e) { - continue; - } - - if (validTempSubkeyBinding) { - validSubkeyBinding = true; - } - if (validTempSubkeyBinding) { - validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getUnhashedSubPackets(), - masterPublicKey, signingPublicKey); - if (validPrimaryKeyBinding) { - break; - } - validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getHashedSubPackets(), - masterPublicKey, signingPublicKey); - if (validPrimaryKeyBinding) { - break; - } - } - } - } - return (validSubkeyBinding & validPrimaryKeyBinding); - } - - private boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector pkts, - PGPPublicKey masterPublicKey, - PGPPublicKey signingPublicKey) { - boolean validPrimaryKeyBinding = false; - JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = - new JcaPGPContentVerifierBuilderProvider() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - PGPSignatureList eSigList; - - if (pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) { - try { - eSigList = pkts.getEmbeddedSignatures(); - } catch (IOException e) { - return false; - } catch (PGPException e) { - return false; - } - for (int j = 0; j < eSigList.size(); ++j) { - PGPSignature emSig = eSigList.get(j); - if (emSig.getSignatureType() == PGPSignature.PRIMARYKEY_BINDING) { - try { - emSig.init(contentVerifierBuilderProvider, signingPublicKey); - validPrimaryKeyBinding = emSig.verifyCertification(masterPublicKey, signingPublicKey); - if (validPrimaryKeyBinding) { - break; - } - } catch (PGPException e) { - continue; - } catch (SignatureException e) { - continue; - } - } - } - } - - return validPrimaryKeyBinding; - } - /** * Mostly taken from ClearSignedFileProcessor in Bouncy Castle * 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 bfbcd582e..6aeb19e65 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java @@ -32,8 +32,8 @@ import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry; @@ -208,9 +208,11 @@ public class PgpImportExport { updateProgress(progress * 100 / masterKeyIdsSize, 100); try { - PGPPublicKeyRing publicKeyRing = mProviderHelper.getPGPPublicKeyRing(pubKeyMasterId); + CachedPublicKeyRing ring = mProviderHelper.getCachedPublicKeyRing( + KeychainContract.KeyRings.buildGenericKeyRingUri(pubKeyMasterId) + ); - publicKeyRing.encode(arOutStream); + ring.encode(arOutStream); } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "key not found!", e); // TODO: inform user? 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 f90250f57..ecaeac7e7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java @@ -52,14 +52,17 @@ public class PgpKeyHelper { private static final Pattern USER_ID_PATTERN = Pattern.compile("^(.*?)(?: \\((.*)\\))?(?: <(.*)>)?$"); + @Deprecated public static Date getCreationDate(PGPPublicKey key) { return key.getCreationTime(); } + @Deprecated public static Date getCreationDate(PGPSecretKey key) { return key.getPublicKey().getCreationTime(); } + @Deprecated public static Date getExpiryDate(PGPPublicKey key) { Date creationDate = getCreationDate(key); if (key.getValidDays() == 0) { @@ -73,10 +76,12 @@ public class PgpKeyHelper { return calendar.getTime(); } + @Deprecated public static Date getExpiryDate(PGPSecretKey key) { return getExpiryDate(key.getPublicKey()); } + @Deprecated public static boolean isExpired(PGPPublicKey key) { Date creationDate = getCreationDate(key); Date expiryDate = getExpiryDate(key); @@ -89,6 +94,7 @@ public class PgpKeyHelper { } @SuppressWarnings("unchecked") + @Deprecated public static PGPSecretKey getKeyNum(PGPSecretKeyRing keyRing, long num) { long cnt = 0; if (keyRing == null) { @@ -105,6 +111,7 @@ public class PgpKeyHelper { } @SuppressWarnings("unchecked") + @Deprecated private static Vector getEncryptKeys(PGPPublicKeyRing keyRing) { Vector encryptKeys = new Vector(); @@ -118,6 +125,7 @@ public class PgpKeyHelper { } @SuppressWarnings("unchecked") + @Deprecated private static Vector getSigningKeys(PGPSecretKeyRing keyRing) { Vector signingKeys = new Vector(); @@ -131,6 +139,7 @@ public class PgpKeyHelper { } @SuppressWarnings("unchecked") + @Deprecated private static Vector getCertificationKeys(PGPSecretKeyRing keyRing) { Vector signingKeys = new Vector(); @@ -143,26 +152,7 @@ public class PgpKeyHelper { return signingKeys; } - private static Vector getUsableEncryptKeys(PGPPublicKeyRing keyRing) { - Vector usableKeys = new Vector(); - Vector encryptKeys = getEncryptKeys(keyRing); - PGPPublicKey masterKey = null; - for (int i = 0; i < encryptKeys.size(); ++i) { - PGPPublicKey key = encryptKeys.get(i); - if (!isExpired(key) && !key.isRevoked()) { - if (key.isMasterKey()) { - masterKey = key; - } else { - usableKeys.add(key); - } - } - } - if (masterKey != null) { - usableKeys.add(masterKey); - } - return usableKeys; - } - + @Deprecated private static Vector getUsableCertificationKeys(PGPSecretKeyRing keyRing) { Vector usableKeys = new Vector(); Vector signingKeys = getCertificationKeys(keyRing); @@ -181,6 +171,7 @@ public class PgpKeyHelper { return usableKeys; } + @Deprecated private static Vector getUsableSigningKeys(PGPSecretKeyRing keyRing) { Vector usableKeys = new Vector(); Vector signingKeys = getSigningKeys(keyRing); @@ -199,16 +190,6 @@ public class PgpKeyHelper { return usableKeys; } - - public static PGPPublicKey getFirstEncryptSubkey(PGPPublicKeyRing keyRing) { - Vector encryptKeys = getUsableEncryptKeys(keyRing); - if (encryptKeys.size() == 0) { - Log.e(Constants.TAG, "encryptKeys is null!"); - return null; - } - return encryptKeys.get(0); - } - public static PGPSecretKey getFirstCertificationSubkey(PGPSecretKeyRing keyRing) { Vector signingKeys = getUsableCertificationKeys(keyRing); if (signingKeys.size() == 0) { @@ -253,6 +234,7 @@ public class PgpKeyHelper { } @SuppressWarnings("unchecked") + @Deprecated public static boolean isEncryptionKey(PGPPublicKey key) { if (!key.isEncryptionKey()) { return false; @@ -298,6 +280,7 @@ public class PgpKeyHelper { } @SuppressWarnings("unchecked") + @Deprecated public static boolean isSigningKey(PGPPublicKey key) { if (key.getVersion() <= 3) { return true; @@ -328,11 +311,13 @@ public class PgpKeyHelper { return false; } + @Deprecated public static boolean isSigningKey(PGPSecretKey key) { return isSigningKey(key.getPublicKey()); } @SuppressWarnings("unchecked") + @Deprecated public static boolean isCertificationKey(PGPPublicKey key) { if (key.getVersion() <= 3) { return true; @@ -358,11 +343,13 @@ public class PgpKeyHelper { return false; } + @Deprecated public static boolean isAuthenticationKey(PGPSecretKey key) { return isAuthenticationKey(key.getPublicKey()); } @SuppressWarnings("unchecked") + @Deprecated public static boolean isAuthenticationKey(PGPPublicKey key) { if (key.getVersion() <= 3) { return true; @@ -388,6 +375,7 @@ public class PgpKeyHelper { return false; } + @Deprecated public static boolean isCertificationKey(PGPSecretKey key) { return isCertificationKey(key.getPublicKey()); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java index 30cac9b77..48cc5d6da 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -25,25 +25,14 @@ import org.spongycastle.openpgp.PGPEncryptedDataGenerator; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPLiteralData; import org.spongycastle.openpgp.PGPLiteralDataGenerator; -import org.spongycastle.openpgp.PGPPrivateKey; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureGenerator; -import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator; import org.spongycastle.openpgp.PGPV3SignatureGenerator; -import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; -import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePBEKeyEncryptionMethodGenerator; -import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder; -import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.Progressable; -import org.sufficientlysecure.keychain.provider.KeychainContract; +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.InputData; import org.sufficientlysecure.keychain.util.Log; @@ -279,19 +268,15 @@ public class PgpSignEncrypt { } /* Get keys for signature generation for later usage */ - PGPSecretKey signingKey = null; - PGPSecretKeyRing signingKeyRing = null; - PGPPrivateKey signaturePrivateKey = null; - String signingUserId = null; + CachedSecretKey signingKey = null; if (enableSignature) { + CachedSecretKeyRing signingKeyRing = null; try { - signingKeyRing = mProviderHelper.getPGPSecretKeyRing(mSignatureMasterKeyId); - signingUserId = (String) mProviderHelper.getUnifiedData(mSignatureMasterKeyId, - KeychainContract.KeyRings.USER_ID, ProviderHelper.FIELD_TYPE_STRING); + signingKeyRing = mProviderHelper.getCachedSecretKeyRing(mSignatureMasterKeyId); } catch (ProviderHelper.NotFoundException e) { throw new NoSigningKeyException(); } - signingKey = PgpKeyHelper.getFirstSigningSubkey(signingKeyRing); + signingKey = signingKeyRing.getSigningSubKey(); if (signingKey == null) { throw new NoSigningKeyException(); } @@ -302,10 +287,9 @@ public class PgpSignEncrypt { updateProgress(R.string.progress_extracting_signature_key, 0, 100); - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( - Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(mSignaturePassphrase.toCharArray()); - signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor); - if (signaturePrivateKey == null) { + try { + signingKey.unlock(mSignaturePassphrase); + } catch (PgpGeneralException e) { throw new KeyExtractionException(); } } @@ -333,13 +317,12 @@ public class PgpSignEncrypt { // Asymmetric encryption for (long id : mEncryptionMasterKeyIds) { try { - PGPPublicKeyRing keyRing = mProviderHelper.getPGPPublicKeyRing(id); - PGPPublicKey key = PgpKeyHelper.getFirstEncryptSubkey(keyRing); - if (key != null) { - JcePublicKeyKeyEncryptionMethodGenerator pubKeyEncryptionGenerator = - new JcePublicKeyKeyEncryptionMethodGenerator(key); - cPk.addMethod(pubKeyEncryptionGenerator); - } + CachedPublicKeyRing keyRing = mProviderHelper.getCachedPublicKeyRing( + KeyRings.buildUnifiedKeyRingUri(Long.toString(id))); + CachedPublicKey key = keyRing.getFirstEncryptSubkey(); + cPk.addMethod(key.getPubKeyEncryptionGenerator()); + } catch (PgpGeneralException e) { + Log.e(Constants.TAG, "key not found!", e); } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "key not found!", e); } @@ -353,29 +336,18 @@ public class PgpSignEncrypt { if (enableSignature) { updateProgress(R.string.progress_preparing_signature, 10, 100); - // content signer based on signing key algorithm and chosen hash algorithm - JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( - signingKey.getPublicKey().getAlgorithm(), mSignatureHashAlgorithm) - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - - int signatureType; - if (mCleartextInput && mEnableAsciiArmorOutput && !enableEncryption) { - // for sign-only ascii text - signatureType = PGPSignature.CANONICAL_TEXT_DOCUMENT; - } else { - signatureType = PGPSignature.BINARY_DOCUMENT; - } - - if (mSignatureForceV3) { - signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder); - signatureV3Generator.init(signatureType, signaturePrivateKey); - } else { - signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder); - signatureGenerator.init(signatureType, signaturePrivateKey); - - PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); - spGen.setSignerUserID(false, signingUserId); - signatureGenerator.setHashedSubpackets(spGen.generate()); + try { + boolean cleartext = mCleartextInput && mEnableAsciiArmorOutput && !enableEncryption; + if (mSignatureForceV3) { + signatureV3Generator = signingKey.getV3SignatureGenerator( + mSignatureHashAlgorithm,cleartext); + } else { + signatureGenerator = signingKey.getSignatureGenerator( + mSignatureHashAlgorithm, cleartext); + } + } catch (PgpGeneralException e) { + // TODO throw correct type of exception (which shouldn't be PGPException) + throw new KeyExtractionException(); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index a4fa3dac9..a3c9fab1b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -110,6 +110,8 @@ public class KeychainContract { public static final String HAS_ANY_SECRET = "has_any_secret"; public static final String HAS_ENCRYPT = "has_encrypt"; public static final String HAS_SIGN = "has_sign"; + public static final String PUBKEY_DATA = "pubkey_data"; + public static final String PRIVKEY_DATA = "privkey_data"; public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() .appendPath(BASE_KEY_RINGS).build(); @@ -123,6 +125,10 @@ public class KeychainContract { return CONTENT_URI.buildUpon().appendPath(PATH_UNIFIED).build(); } + public static Uri buildGenericKeyRingUri(long masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(Long.toString(masterKeyId)).build(); + } + public static Uri buildGenericKeyRingUri(String masterKeyId) { return CONTENT_URI.buildUpon().appendPath(masterKeyId).build(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 1dc822ac2..64dab3020 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -254,6 +254,12 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(KeyRings.FINGERPRINT, Keys.FINGERPRINT); projectionMap.put(KeyRings.USER_ID, UserIds.USER_ID); projectionMap.put(KeyRings.VERIFIED, KeyRings.VERIFIED); + projectionMap.put(KeyRings.PUBKEY_DATA, + Tables.KEY_RINGS_PUBLIC + "." + KeyRingData.KEY_RING_DATA + + " AS " + KeyRings.PUBKEY_DATA); + projectionMap.put(KeyRings.PRIVKEY_DATA, + Tables.KEY_RINGS_SECRET + "." + KeyRingData.KEY_RING_DATA + + " AS " + KeyRings.PRIVKEY_DATA); projectionMap.put(KeyRings.HAS_SECRET, KeyRings.HAS_SECRET); projectionMap.put(KeyRings.HAS_ANY_SECRET, "(EXISTS (SELECT * FROM " + Tables.KEY_RINGS_SECRET @@ -295,6 +301,22 @@ public class KeychainProvider extends ContentProvider { + " AND " + Tables.CERTS + "." + Certs.VERIFIED + " = " + Certs.VERIFIED_SECRET + ")" + // fairly expensive join (due to blob data), only do it when requested + + (Arrays.asList(projection).contains(KeyRings.PUBKEY_DATA) ? + " INNER JOIN " + Tables.KEY_RINGS_PUBLIC + " ON (" + + Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " = " + + Tables.KEY_RINGS_PUBLIC + "." + KeyRingData.MASTER_KEY_ID + + ")" + : "") + // fairly expensive join (due to blob data), only do it when requested + + (Arrays.asList(projection).contains(KeyRings.PRIVKEY_DATA) ? + " LEFT JOIN " + Tables.KEY_RINGS_SECRET + " ON (" + + Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " = " + + Tables.KEY_RINGS_SECRET + "." + KeyRingData.MASTER_KEY_ID + + ")" + : "") ); qb.appendWhere(Tables.KEYS + "." + Keys.RANK + " = 0"); // in case there are multiple verifying certificates 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 214a9988c..80a3fe6e6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -36,9 +36,10 @@ import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSignature; -import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing; +import org.sufficientlysecure.keychain.pgp.CachedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; @@ -167,6 +168,7 @@ public class ProviderHelper { } } + @Deprecated public Map getPGPKeyRings(Uri queryUri) { Cursor cursor = mContentResolver.query(queryUri, new String[]{KeyRingData.MASTER_KEY_ID, KeyRingData.KEY_RING_DATA}, @@ -188,6 +190,94 @@ public class ProviderHelper { return result; } + public CachedPublicKeyRing getCachedPublicKeyRing(Uri queryUri) throws NotFoundException { + Cursor cursor = mContentResolver.query(queryUri, + new String[] { + KeyRings.MASTER_KEY_ID, KeyRings.KEY_SIZE, + KeyRings.IS_REVOKED, KeyRings.CAN_CERTIFY, + KeyRings.CREATION, KeyRings.EXPIRY, + KeyRings.ALGORITHM, KeyRings.FINGERPRINT, + KeyRings.USER_ID, KeyRings.VERIFIED, + KeyRings.HAS_SECRET, KeyRings.PUBKEY_DATA + }, null, null, null); + try { + if (cursor != null && cursor.moveToFirst()) { + long masterKeyId = cursor.getLong(0); + int keySize = cursor.getInt(1); + boolean isRevoked = cursor.getInt(2) > 0; + boolean canCertify = cursor.getInt(3) > 0; + long creation = cursor.getLong(4); + long expiry = cursor.getLong(5); + int algorithm = cursor.getInt(6); + byte[] fingerprint = cursor.getBlob(7); + String userId = cursor.getString(8); + int verified = cursor.getInt(9); + boolean hasSecret = cursor.getInt(10) > 0; + byte[] pubkey = cursor.getBlob(11); + return new CachedPublicKeyRing( + masterKeyId, keySize, isRevoked, canCertify, + creation, expiry, algorithm, fingerprint, + userId, verified, hasSecret, pubkey + ); + } else { + throw new NotFoundException("Key not found!"); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + } + + public CachedSecretKeyRing getCachedSecretKeyRing(long id) throws NotFoundException { + return getCachedSecretKeyRing(KeyRings.buildUnifiedKeyRingUri(Long.toString(id))); + } + + public CachedSecretKeyRing getCachedSecretKeyRing(Uri queryUri) throws NotFoundException { + Cursor cursor = mContentResolver.query(queryUri, + new String[] { + KeyRings.MASTER_KEY_ID, KeyRings.KEY_SIZE, + KeyRings.IS_REVOKED, KeyRings.CAN_CERTIFY, + KeyRings.CREATION, KeyRings.EXPIRY, + KeyRings.ALGORITHM, KeyRings.FINGERPRINT, + KeyRings.USER_ID, KeyRings.VERIFIED, + KeyRings.HAS_SECRET, KeyRings.PRIVKEY_DATA + }, null, null, null); + try { + if (cursor != null && cursor.moveToFirst()) { + // check if a privkey is actually available + byte[] privkey = cursor.getBlob(11); + if(privkey == null) { + throw new NotFoundException("Key found, but no secret key available!"); + } + + long masterKeyId = cursor.getLong(0); + int keySize = cursor.getInt(1); + boolean isRevoked = cursor.getInt(2) > 0; + boolean canCertify = cursor.getInt(3) > 0; + long creation = cursor.getLong(4); + long expiry = cursor.getLong(5); + int algorithm = cursor.getInt(6); + byte[] fingerprint = cursor.getBlob(7); + String userId = cursor.getString(8); + int verified = cursor.getInt(9); + boolean hasSecret = cursor.getInt(10) > 0; + return new CachedSecretKeyRing( + masterKeyId, keySize, isRevoked, canCertify, + creation, expiry, algorithm, fingerprint, + userId, verified, hasSecret, privkey + ); + } else { + throw new NotFoundException("Key not found!"); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + } + + @Deprecated public PGPKeyRing getPGPKeyRing(Uri queryUri) throws NotFoundException { Map result = getPGPKeyRings(queryUri); if (result.isEmpty()) { @@ -197,6 +287,7 @@ public class ProviderHelper { } } + @Deprecated public PGPPublicKeyRing getPGPPublicKeyRingWithKeyId(long keyId) throws NotFoundException { Uri uri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId)); @@ -204,6 +295,7 @@ public class ProviderHelper { return getPGPPublicKeyRing(masterKeyId); } + @Deprecated public PGPSecretKeyRing getPGPSecretKeyRingWithKeyId(long keyId) throws NotFoundException { Uri uri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId)); @@ -214,6 +306,7 @@ public class ProviderHelper { /** * Retrieves the actual PGPPublicKeyRing object from the database blob based on the masterKeyId */ + @Deprecated public PGPPublicKeyRing getPGPPublicKeyRing(long masterKeyId) throws NotFoundException { Uri queryUri = KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId)); return (PGPPublicKeyRing) getPGPKeyRing(queryUri); @@ -222,6 +315,7 @@ public class ProviderHelper { /** * Retrieves the actual PGPSecretKeyRing object from the database blob based on the maserKeyId */ + @Deprecated public PGPSecretKeyRing getPGPSecretKeyRing(long masterKeyId) throws NotFoundException { Uri queryUri = KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId)); return (PGPSecretKeyRing) getPGPKeyRing(queryUri); -- cgit v1.2.3 From c2c6a90991397929b024f726e4d515095e21d9a2 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 3 May 2014 15:59:25 +0200 Subject: certification is always done with the master key --- .../keychain/pgp/PgpKeyHelper.java | 55 ---------------------- .../keychain/service/KeychainIntentService.java | 2 +- 2 files changed, 1 insertion(+), 56 deletions(-) (limited to 'OpenKeychain') 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 ecaeac7e7..e884c0e2f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java @@ -110,20 +110,6 @@ public class PgpKeyHelper { return null; } - @SuppressWarnings("unchecked") - @Deprecated - private static Vector getEncryptKeys(PGPPublicKeyRing keyRing) { - Vector encryptKeys = new Vector(); - - for (PGPPublicKey key : new IterableIterator(keyRing.getPublicKeys())) { - if (isEncryptionKey(key)) { - encryptKeys.add(key); - } - } - - return encryptKeys; - } - @SuppressWarnings("unchecked") @Deprecated private static Vector getSigningKeys(PGPSecretKeyRing keyRing) { @@ -138,39 +124,6 @@ public class PgpKeyHelper { return signingKeys; } - @SuppressWarnings("unchecked") - @Deprecated - private static Vector getCertificationKeys(PGPSecretKeyRing keyRing) { - Vector signingKeys = new Vector(); - - for (PGPSecretKey key : new IterableIterator(keyRing.getSecretKeys())) { - if (isCertificationKey(key)) { - signingKeys.add(key); - } - } - - return signingKeys; - } - - @Deprecated - private static Vector getUsableCertificationKeys(PGPSecretKeyRing keyRing) { - Vector usableKeys = new Vector(); - Vector signingKeys = getCertificationKeys(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 private static Vector getUsableSigningKeys(PGPSecretKeyRing keyRing) { Vector usableKeys = new Vector(); @@ -190,14 +143,6 @@ public class PgpKeyHelper { return usableKeys; } - public static PGPSecretKey getFirstCertificationSubkey(PGPSecretKeyRing keyRing) { - Vector signingKeys = getUsableCertificationKeys(keyRing); - if (signingKeys.size() == 0) { - return null; - } - return signingKeys.get(0); - } - public static PGPSecretKey getFirstSigningSubkey(PGPSecretKeyRing keyRing) { Vector signingKeys = getUsableSigningKeys(keyRing); if (signingKeys.size() == 0) { 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 5615b59c4..99d12ee8b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -836,7 +836,7 @@ public class KeychainIntentService extends IntentService Log.e(Constants.TAG, "key not found!", e); // TODO: throw exception here! } - PGPSecretKey certificationKey = PgpKeyHelper.getFirstCertificationSubkey(secretKeyRing); + PGPSecretKey certificationKey = secretKeyRing.getSecretKey(); publicKey = keyOperation.certifyKey(certificationKey, publicKey, userIds, signaturePassphrase); publicRing = PGPPublicKeyRing.insertPublicKey(publicRing, publicKey); -- cgit v1.2.3 From 1f8210f743687063a36da03ba327fa6a534280fa Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 3 May 2014 18:32:20 +0200 Subject: wrapped-key-ring: move certification logic into secretkey --- .../keychain/pgp/CachedPublicKeyRing.java | 7 ++- .../keychain/pgp/CachedSecretKey.java | 58 ++++++++++++++++++ .../keychain/pgp/CachedSecretKeyRing.java | 6 +- .../keychain/pgp/PgpImportExport.java | 69 +++++++++------------- .../keychain/pgp/PgpKeyOperation.java | 53 ----------------- .../keychain/provider/ProviderHelper.java | 4 ++ .../keychain/service/KeychainIntentService.java | 46 ++++++--------- 7 files changed, 118 insertions(+), 125 deletions(-) (limited to 'OpenKeychain') 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 fb142adce..3a45b4ff9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java @@ -36,7 +36,7 @@ public class CachedPublicKeyRing extends CachedKeyRing { mPubKey = pubkey; } - private PGPPublicKeyRing getRing() { + PGPPublicKeyRing getRing() { if(mRing == null) { mRing = (PGPPublicKeyRing) PgpConversionHelper.BytesToPGPKeyRing(mPubKey); } @@ -47,6 +47,10 @@ public class CachedPublicKeyRing extends CachedKeyRing { getRing().encode(stream); } + public CachedPublicKey getSubkey() { + return new CachedPublicKey(this, getRing().getPublicKey()); + } + public CachedPublicKey getSubkey(long id) { return new CachedPublicKey(this, getRing().getPublicKey(id)); } @@ -128,7 +132,6 @@ public class CachedPublicKeyRing extends CachedKeyRing { } - static boolean isEncryptionKey(PGPPublicKey key) { if (!key.isEncryptionKey()) { return false; 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 514fca6fb..ea302ea0b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java @@ -2,10 +2,14 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPPrivateKey; +import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPSecretKey; 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.PGPV3SignatureGenerator; import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory; @@ -14,6 +18,13 @@ import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; +import org.sufficientlysecure.keychain.util.IterableIterator; + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SignatureException; +import java.util.List; public class CachedSecretKey { @@ -113,6 +124,53 @@ public class CachedSecretKey { .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(mPrivateKey); } + /** + * Certify the given pubkeyid with the given masterkeyid. + * + * @param publicKeyRing Keyring to add certification to. + * @param userIds User IDs to certify, must not be null or empty + * @return A keyring with added certifications + */ + public UncachedKeyRing certifyUserIds(CachedPublicKeyRing publicKeyRing, List userIds) + throws PgpGeneralMsgIdException, NoSuchAlgorithmException, NoSuchProviderException, + PGPException, SignatureException { + + if(mPrivateKey == null) { + throw new PrivateKeyNotUnlockedException(); + } + + // create a signatureGenerator from the supplied masterKeyId and passphrase + PGPSignatureGenerator signatureGenerator; + { + // TODO: SHA256 fixed? + JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( + mKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + + signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder); + signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, mPrivateKey); + } + + { // supply signatureGenerator with a SubpacketVector + PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); + PGPSignatureSubpacketVector packetVector = spGen.generate(); + signatureGenerator.setHashedSubpackets(packetVector); + } + + // get the master subkey (which we certify for) + PGPPublicKey publicKey = publicKeyRing.getSubkey().getKey(); + + // fetch public key ring, add the certification and return it + for (String userId : new IterableIterator(userIds.iterator())) { + PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey); + publicKey = PGPPublicKey.addCertification(publicKey, userId, sig); + } + + PGPPublicKeyRing ring = PGPPublicKeyRing.insertPublicKey(publicKeyRing.getRing(), publicKey); + + return new UncachedKeyRing(ring); + } + static class PrivateKeyNotUnlockedException extends RuntimeException { // this exception is a programming error which happens when an operation which requires // the private key is called without a previous call to unlock() 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 a2b2b2832..5403e1510 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java @@ -23,7 +23,11 @@ public class CachedSecretKeyRing extends CachedKeyRing { mRing = (PGPSecretKeyRing) PgpConversionHelper.BytesToPGPKeyRing(blob); } - CachedSecretKey getSubKey(long id) { + public CachedSecretKey getSubKey() { + return new CachedSecretKey(this, mRing.getSecretKey()); + } + + public CachedSecretKey getSubKey(long id) { return new CachedSecretKey(this, mRing.getSecretKey(id)); } 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 6aeb19e65..6de958d8d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java @@ -97,12 +97,12 @@ public class PgpImportExport { } } - public boolean uploadKeyRingToServer(HkpKeyServer server, PGPPublicKeyRing keyring) { + public boolean uploadKeyRingToServer(HkpKeyServer server, CachedPublicKeyRing keyring) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ArmoredOutputStream aos = null; try { aos = new ArmoredOutputStream(bos); - aos.write(keyring.getEncoded()); + keyring.encode(aos); aos.close(); String armoredKey = bos.toString("UTF-8"); @@ -147,8 +147,25 @@ public class PgpImportExport { if (obj instanceof PGPKeyRing) { PGPKeyRing keyring = (PGPKeyRing) obj; - - int status = storeKeyRingInCache(keyring); + int status; + // TODO Better try to get this one from the db first! + if(keyring instanceof PGPSecretKeyRing) { + PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring; + // TODO: preserve certifications + // (http://osdir.com/ml/encryption.bouncy-castle.devel/2007-01/msg00054.html ?) + PGPPublicKeyRing newPubRing = null; + for (PGPPublicKey key : new IterableIterator( + secretKeyRing.getPublicKeys())) { + if (newPubRing == null) { + newPubRing = new PGPPublicKeyRing(key.getEncoded(), + new JcaKeyFingerprintCalculator()); + } + newPubRing = PGPPublicKeyRing.insertPublicKey(newPubRing, key); + } + status = storeKeyRingInCache(new UncachedKeyRing(newPubRing ,secretKeyRing)); + } else { + status = storeKeyRingInCache(new UncachedKeyRing((PGPPublicKeyRing) keyring)); + } if (status == RETURN_ERROR) { throw new PgpGeneralException( @@ -259,44 +276,16 @@ public class PgpImportExport { } @SuppressWarnings("unchecked") - public int storeKeyRingInCache(PGPKeyRing keyring) { + public int storeKeyRingInCache(UncachedKeyRing keyring) { int status = RETURN_ERROR; try { - if (keyring instanceof PGPSecretKeyRing) { - PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring; - boolean save = true; - - for (PGPSecretKey testSecretKey : new IterableIterator( - secretKeyRing.getSecretKeys())) { - if (!testSecretKey.isMasterKey()) { - if (testSecretKey.isPrivateKeyEmpty()) { - // this is bad, something is very wrong... - save = false; - status = RETURN_BAD; - } - } - } - - if (save) { - // TODO: preserve certifications - // (http://osdir.com/ml/encryption.bouncy-castle.devel/2007-01/msg00054.html ?) - PGPPublicKeyRing newPubRing = null; - for (PGPPublicKey key : new IterableIterator( - secretKeyRing.getPublicKeys())) { - if (newPubRing == null) { - newPubRing = new PGPPublicKeyRing(key.getEncoded(), - new JcaKeyFingerprintCalculator()); - } - newPubRing = PGPPublicKeyRing.insertPublicKey(newPubRing, key); - } - if (newPubRing != null) { - mProviderHelper.saveKeyRing(newPubRing); - } - mProviderHelper.saveKeyRing(secretKeyRing); - status = RETURN_OK; - } - } else if (keyring instanceof PGPPublicKeyRing) { - PGPPublicKeyRing publicKeyRing = (PGPPublicKeyRing) keyring; + PGPSecretKeyRing secretKeyRing = keyring.getSecretRing(); + PGPPublicKeyRing publicKeyRing = keyring.getPublicRing(); + // see what type we have. we can either have a secret + public keyring, or just public + if (secretKeyRing != null) { + mProviderHelper.saveKeyRing(publicKeyRing, secretKeyRing); + status = RETURN_OK; + } else { mProviderHelper.saveKeyRing(publicKeyRing); status = RETURN_OK; } 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 9dd9f660b..2033a91e7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -690,59 +690,6 @@ public class PgpKeyOperation { } - /** - * Certify the given pubkeyid with the given masterkeyid. - * - * @param certificationKey Certifying key - * @param publicKey public key to certify - * @param userIds User IDs to certify, must not be null or empty - * @param passphrase Passphrase of the secret key - * @return A keyring with added certifications - */ - public PGPPublicKey certifyKey(PGPSecretKey certificationKey, PGPPublicKey publicKey, - List userIds, String passphrase) - throws PgpGeneralMsgIdException, NoSuchAlgorithmException, NoSuchProviderException, - PGPException, SignatureException { - - // create a signatureGenerator from the supplied masterKeyId and passphrase - PGPSignatureGenerator signatureGenerator; - { - - if (certificationKey == null) { - throw new PgpGeneralMsgIdException(R.string.error_no_signature_key); - } - - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( - Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); - PGPPrivateKey signaturePrivateKey = certificationKey.extractPrivateKey(keyDecryptor); - if (signaturePrivateKey == null) { - throw new PgpGeneralMsgIdException(R.string.error_could_not_extract_private_key); - } - - // TODO: SHA256 fixed? - JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( - certificationKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256) - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - - signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder); - signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, signaturePrivateKey); - } - - { // supply signatureGenerator with a SubpacketVector - PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); - PGPSignatureSubpacketVector packetVector = spGen.generate(); - signatureGenerator.setHashedSubpackets(packetVector); - } - - // fetch public key ring, add the certification and return it - for (String userId : new IterableIterator(userIds.iterator())) { - PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey); - publicKey = PGPPublicKey.addCertification(publicKey, userId, sig); - } - - return publicKey; - } - /** * Simple static subclass that stores two values. *

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 80a3fe6e6..0fe989e84 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -190,6 +190,10 @@ public class ProviderHelper { return result; } + public CachedPublicKeyRing getCachedPublicKeyRing(long id) throws NotFoundException { + return getCachedPublicKeyRing(KeyRings.buildUnifiedKeyRingUri(Long.toString(id))); + } + public CachedPublicKeyRing getCachedPublicKeyRing(Uri queryUri) throws NotFoundException { Cursor cursor = mContentResolver.query(queryUri, new String[] { 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 99d12ee8b..d02906c4f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -29,7 +29,6 @@ import android.os.RemoteException; import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPObjectFactory; -import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; @@ -39,6 +38,9 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; import org.sufficientlysecure.keychain.helper.OtherHelper; 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; @@ -48,6 +50,7 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; 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.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; @@ -648,10 +651,8 @@ public class KeychainIntentService extends IntentService try { List entries = data.getParcelableArrayList(IMPORT_KEY_LIST); - Bundle resultData = new Bundle(); - PgpImportExport pgpImportExport = new PgpImportExport(this, this); - resultData = pgpImportExport.importKeyRings(entries); + Bundle resultData = pgpImportExport.importKeyRings(entries); sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); } catch (Exception e) { @@ -724,15 +725,12 @@ public class KeychainIntentService extends IntentService HkpKeyServer server = new HkpKeyServer(keyServer); ProviderHelper providerHelper = new ProviderHelper(this); - PGPPublicKeyRing keyring = (PGPPublicKeyRing) providerHelper.getPGPKeyRing(dataUri); - if (keyring != null) { - PgpImportExport pgpImportExport = new PgpImportExport(this, null); - - boolean uploaded = pgpImportExport.uploadKeyRingToServer(server, - (PGPPublicKeyRing) keyring); - if (!uploaded) { - throw new PgpGeneralException("Unable to export key to selected server"); - } + CachedPublicKeyRing keyring = providerHelper.getCachedPublicKeyRing(dataUri); + PgpImportExport pgpImportExport = new PgpImportExport(this, null); + + boolean uploaded = pgpImportExport.uploadKeyRingToServer(server, keyring); + if (!uploaded) { + throw new PgpGeneralException("Unable to export key to selected server"); } sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); @@ -795,7 +793,6 @@ public class KeychainIntentService extends IntentService entry.setBytes(downloadedKey.getEncoded()); } - Intent importIntent = new Intent(this, KeychainIntentService.class); importIntent.setAction(ACTION_IMPORT_KEYRING); Bundle importData = new Bundle(); @@ -826,24 +823,15 @@ public class KeychainIntentService extends IntentService } ProviderHelper providerHelper = new ProviderHelper(this); - PgpKeyOperation keyOperation = new PgpKeyOperation(new ProgressScaler(this, 0, 100, 100)); - PGPPublicKeyRing publicRing = providerHelper.getPGPPublicKeyRing(pubKeyId); - PGPPublicKey publicKey = publicRing.getPublicKey(pubKeyId); - PGPSecretKeyRing secretKeyRing = null; - try { - secretKeyRing = providerHelper.getPGPSecretKeyRing(masterKeyId); - } catch (ProviderHelper.NotFoundException e) { - Log.e(Constants.TAG, "key not found!", e); - // TODO: throw exception here! - } - PGPSecretKey certificationKey = secretKeyRing.getSecretKey(); - publicKey = keyOperation.certifyKey(certificationKey, publicKey, - userIds, signaturePassphrase); - publicRing = PGPPublicKeyRing.insertPublicKey(publicRing, publicKey); + CachedPublicKeyRing publicRing = providerHelper.getCachedPublicKeyRing(pubKeyId); + CachedSecretKeyRing secretKeyRing = providerHelper.getCachedSecretKeyRing(masterKeyId); + CachedSecretKey certificationKey = secretKeyRing.getSubKey(); + certificationKey.unlock(signaturePassphrase); + UncachedKeyRing newRing = certificationKey.certifyUserIds(publicRing, userIds); // store the signed key in our local cache PgpImportExport pgpImportExport = new PgpImportExport(this, null); - int retval = pgpImportExport.storeKeyRingInCache(publicRing); + int retval = pgpImportExport.storeKeyRingInCache(newRing); if (retval != PgpImportExport.RETURN_OK && retval != PgpImportExport.RETURN_UPDATED) { throw new PgpGeneralException("Failed to store signed key in local cache"); } -- cgit v1.2.3 From 2176e1ef1c29ca4549b256745c26c871503fe5ce Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 3 May 2014 19:04:23 +0200 Subject: wrapped-key-ring: move more helper methods into keys --- .../keychain/pgp/CachedPublicKey.java | 108 ++++++++++++++++++++- .../keychain/pgp/CachedSecretKey.java | 22 ++--- .../keychain/pgp/CachedSecretKeyRing.java | 35 +++++++ .../keychain/pgp/PgpKeyHelper.java | 1 + .../keychain/service/PassphraseCacheService.java | 2 + 5 files changed, 153 insertions(+), 15 deletions(-) (limited to 'OpenKeychain') 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 fb065c85f..08b9d5a0c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java @@ -1,26 +1,128 @@ 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.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; public class CachedPublicKey { // this is the parent key ring - private final CachedPublicKeyRing mRing; + final CachedKeyRing mRing; private final PGPPublicKey mKey; - CachedPublicKey(CachedPublicKeyRing ring, PGPPublicKey key) { + CachedPublicKey(CachedKeyRing ring, PGPPublicKey key) { mRing = ring; mKey = key; } - public CachedPublicKeyRing getKeyRing() { + public long getKeyId() { + return mKey.getKeyID(); + } + + 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 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; + } + + public CachedKeyRing getKeyRing() { return mRing; } 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 ea302ea0b..d0b18d757 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java @@ -1,5 +1,6 @@ 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; @@ -26,28 +27,25 @@ import java.security.NoSuchProviderException; import java.security.SignatureException; import java.util.List; -public class CachedSecretKey { +public class CachedSecretKey extends CachedPublicKey { - // this is the parent key ring - private final CachedSecretKeyRing mRing; - - private final PGPSecretKey mKey; + private final PGPSecretKey mSecretKey; private PGPPrivateKey mPrivateKey = null; CachedSecretKey(CachedSecretKeyRing ring, PGPSecretKey key) { - mRing = ring; - mKey = key; + super(ring, key.getPublicKey()); + mSecretKey = key; } public CachedSecretKeyRing getRing() { - return mRing; + return (CachedSecretKeyRing) mRing; } public void unlock(String passphrase) throws PgpGeneralException { try { PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); - mPrivateKey = mKey.extractPrivateKey(keyDecryptor); + mPrivateKey = mSecretKey.extractPrivateKey(keyDecryptor); } catch (PGPException e) { throw new PgpGeneralException("error extracting key!", e); } @@ -64,7 +62,7 @@ public class CachedSecretKey { // content signer based on signing key algorithm and chosen hash algorithm JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( - mKey.getPublicKey().getAlgorithm(), hashAlgo) + mSecretKey.getPublicKey().getAlgorithm(), hashAlgo) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); int signatureType; @@ -96,7 +94,7 @@ public class CachedSecretKey { // content signer based on signing key algorithm and chosen hash algorithm JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( - mKey.getPublicKey().getAlgorithm(), hashAlgo) + mSecretKey.getPublicKey().getAlgorithm(), hashAlgo) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); int signatureType; @@ -144,7 +142,7 @@ public class CachedSecretKey { { // TODO: SHA256 fixed? JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( - mKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256) + mSecretKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder); 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 5403e1510..097f530fd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java @@ -1,13 +1,19 @@ 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; import org.spongycastle.openpgp.PGPSecretKey; 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.JcePBESecretKeyDecryptorBuilder; import org.sufficientlysecure.keychain.util.IterableIterator; +import java.util.Iterator; + public class CachedSecretKeyRing extends CachedKeyRing { private PGPSecretKeyRing mRing; @@ -31,6 +37,35 @@ public class CachedSecretKeyRing extends CachedKeyRing { return new CachedSecretKey(this, mRing.getSecretKey(id)); } + public IterableIterator iterator() { + return new IterableIterator(mRing.getSecretKeys()); + } + + public boolean hasPassphrase() { + PGPSecretKey secretKey = null; + boolean foundValidKey = false; + for (Iterator keys = mRing.getSecretKeys(); keys.hasNext(); ) { + secretKey = (PGPSecretKey) keys.next(); + if (!secretKey.isPrivateKeyEmpty()) { + foundValidKey = true; + break; + } + } + if(!foundValidKey) { + return false; + } + + try { + PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() + .setProvider("SC").build("".toCharArray()); + PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor); + return testKey == null; + } catch(PGPException e) { + // this means the crc check failed -> passphrase required + return true; + } + } + /** This returns the subkey that should be used for signing. * At this point, this is simply the first suitable subkey. */ 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 e884c0e2f..5e78a5764 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java @@ -143,6 +143,7 @@ public class PgpKeyHelper { return usableKeys; } + @Deprecated public static PGPSecretKey getFirstSigningSubkey(PGPSecretKeyRing keyRing) { Vector signingKeys = getUsableSigningKeys(keyRing); if (signingKeys.size() == 0) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index db4fecef0..88e974288 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -197,6 +197,7 @@ public class PassphraseCacheService extends Service { return cachedPassphrase; } + @Deprecated public static boolean hasPassphrase(PGPSecretKeyRing secretKeyRing) { PGPSecretKey secretKey = null; boolean foundValidKey = false; @@ -228,6 +229,7 @@ public class PassphraseCacheService extends Service { * @param secretKeyId * @return true if it has a passphrase */ + @Deprecated public static boolean hasPassphrase(Context context, long secretKeyId) { // check if the key has no passphrase try { -- cgit v1.2.3 From ef6211e0bd380c4f6bca28cda327cfbe4c57a21e Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 3 May 2014 19:05:03 +0200 Subject: wrapped-key-ring: forgot to add UncachedKeyRing class --- .../keychain/pgp/UncachedKeyRing.java | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java new file mode 100644 index 000000000..86a2ed48d --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -0,0 +1,29 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.openpgp.PGPPublicKeyRing; +import org.spongycastle.openpgp.PGPSecretKeyRing; + +public class UncachedKeyRing { + + final PGPPublicKeyRing mPublicRing; + final PGPSecretKeyRing mSecretRing; + + UncachedKeyRing(PGPPublicKeyRing publicRing, PGPSecretKeyRing secretRing) { + // this one must not be false! + assert(publicRing != null); + mPublicRing = publicRing; + mSecretRing = secretRing; + } + + UncachedKeyRing(PGPPublicKeyRing publicRing) { + this(publicRing, null); + } + + public PGPPublicKeyRing getPublicRing() { + return mPublicRing; + } + + public PGPSecretKeyRing getSecretRing() { + return mSecretRing; + } +} -- cgit v1.2.3 From 32baf425151b32bca7ce8db97b732bce44238c81 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 3 May 2014 19:14:30 +0200 Subject: wrapped-key-ring: small fix to make it work again --- .../keychain/pgp/CachedKeyRing.java | 4 ---- .../keychain/pgp/PgpDecryptVerify.java | 22 ++++++++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) (limited to 'OpenKeychain') 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 5cf89b6a6..9e5671a97 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java @@ -54,8 +54,4 @@ public abstract class CachedKeyRing { return mVerified; } - public void initSignature(PGPSignature sig) { - - } - } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index c84b9413f..37dfee8b9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -366,6 +366,7 @@ public class PgpDecryptVerify { Object dataChunk = plainFact.nextObject(); OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); int signatureIndex = -1; + CachedPublicKeyRing signingRing = null; CachedPublicKey signingKey = null; if (dataChunk instanceof PGPCompressedData) { @@ -390,7 +391,7 @@ public class PgpDecryptVerify { for (int i = 0; i < sigList.size(); ++i) { try { long sigKeyId = sigList.get(i).getKeyID(); - CachedPublicKeyRing signingRing = mProviderHelper.getCachedPublicKeyRing( + signingRing = mProviderHelper.getCachedPublicKeyRing( KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( Long.toString(sigKeyId) ) @@ -409,9 +410,9 @@ public class PgpDecryptVerify { signatureResultBuilder.signatureAvailable(true); signatureResultBuilder.knownKey(true); - signatureResultBuilder.keyId(signingKey.getKeyRing().getMasterKeyId()); - signatureResultBuilder.userId(signingKey.getKeyRing().getPrimaryUserId()); - signatureResultBuilder.signatureKeyCertified(signingKey.getKeyRing().getVerified() > 0); + signatureResultBuilder.keyId(signingRing.getMasterKeyId()); + signatureResultBuilder.userId(signingRing.getPrimaryUserId()); + signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0); signingKey.initSignature(signature); } else { @@ -488,7 +489,7 @@ public class PgpDecryptVerify { // Verify signature and check binding signatures boolean validSignature = signature.verify(messageSignature); - boolean validKeyBinding = signingKey.getKeyRing().verifySubkeyBinding(signingKey); + boolean validKeyBinding = signingRing.verifySubkeyBinding(signingKey); signatureResultBuilder.validSignature(validSignature); signatureResultBuilder.validKeyBinding(validKeyBinding); @@ -564,6 +565,7 @@ public class PgpDecryptVerify { throw new InvalidDataException(); } + CachedPublicKeyRing signingRing = null; CachedPublicKey signingKey = null; int signatureIndex = -1; @@ -572,7 +574,7 @@ public class PgpDecryptVerify { for (int i = 0; i < sigList.size(); ++i) { try { long sigKeyId = sigList.get(i).getKeyID(); - CachedPublicKeyRing signingRing = mProviderHelper.getCachedPublicKeyRing( + signingRing = mProviderHelper.getCachedPublicKeyRing( KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( Long.toString(sigKeyId) ) @@ -593,9 +595,9 @@ public class PgpDecryptVerify { signatureResultBuilder.signatureAvailable(true); signatureResultBuilder.knownKey(true); - signatureResultBuilder.keyId(signingKey.getKeyRing().getMasterKeyId()); - signatureResultBuilder.userId(signingKey.getKeyRing().getPrimaryUserId()); - signatureResultBuilder.signatureKeyCertified(signingKey.getKeyRing().getVerified() > 0); + signatureResultBuilder.keyId(signingRing.getMasterKeyId()); + signatureResultBuilder.userId(signingRing.getPrimaryUserId()); + signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0); signingKey.initSignature(signature); } else { @@ -629,7 +631,7 @@ public class PgpDecryptVerify { // Verify signature and check binding signatures boolean validSignature = signature.verify(); - boolean validKeyBinding = signingKey.getKeyRing().verifySubkeyBinding(signingKey); + boolean validKeyBinding = signingRing.verifySubkeyBinding(signingKey); signatureResultBuilder.validSignature(validSignature); signatureResultBuilder.validKeyBinding(validKeyBinding); -- cgit v1.2.3 From f524fa692c8ab9bd737f7b03a5104ff2b2867669 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 3 May 2014 22:29:09 +0200 Subject: wrapped-key-ring: more refactoring - no more pgp imports in KeychainIntentService! --- .../keychain/pgp/CachedKeyRing.java | 28 +++---- .../keychain/pgp/CachedPublicKey.java | 13 ++++ .../keychain/pgp/CachedPublicKeyRing.java | 86 +++++++--------------- .../keychain/pgp/CachedSecretKeyRing.java | 35 ++++++++- .../keychain/pgp/PgpConversionHelper.java | 32 -------- .../keychain/pgp/PgpImportExport.java | 2 +- .../keychain/pgp/PgpKeyHelper.java | 54 -------------- .../keychain/pgp/PgpKeyOperation.java | 52 ++++--------- .../keychain/pgp/UncachedKeyRing.java | 35 ++++++++- .../keychain/pgp/UncachedSecretKeyRing.java | 19 +++++ .../keychain/provider/ProviderHelper.java | 20 ++++- .../keychain/service/KeychainIntentService.java | 79 +++++++------------- .../keychain/ui/EncryptAsymmetricFragment.java | 22 +++--- OpenKeychain/src/main/res/values/strings.xml | 1 + 14 files changed, 209 insertions(+), 269 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKeyRing.java (limited to 'OpenKeychain') 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(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(getRing().getPublicKeys())) { - if (key.isRevoked() || !isEncryptionKey(key) || isExpired(key)) { + CachedPublicKey masterKey = null; + for (PGPPublicKey k : new IterableIterator(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(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 getSigningKeys(PGPSecretKeyRing keyRing) { - Vector signingKeys = new Vector(); - - for (PGPSecretKey key : new IterableIterator(keyRing.getSecretKeys())) { - if (isSigningKey(key)) { - signingKeys.add(key); - } - } - - return signingKeys; - } - - @Deprecated - private static Vector getUsableSigningKeys(PGPSecretKeyRing keyRing) { - Vector usableKeys = new Vector(); - Vector 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 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 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(secretKeyRing, publicKeyRing); + return new UncachedKeyRing(publicKeyRing, secretKeyRing); } - public Pair 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(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; @@ -484,12 +486,22 @@ 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 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 newKeys = new ArrayList(); ArrayList keyUsageList = new ArrayList(); /* 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 goodIds = new Vector(); 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 @@ View Certificate Details unknown cannot sign + Encoding error -- cgit v1.2.3 From b5647b2062e3233451532f44ce03c8b1bcdb7a3e Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 4 May 2014 03:38:58 +0200 Subject: wrapped-key-ring: no more pgp imports in PassphraseDialogFragment --- .../keychain/pgp/CachedSecretKey.java | 7 +- .../keychain/pgp/PgpDecryptVerify.java | 8 +- .../keychain/pgp/PgpKeyOperation.java | 4 +- .../keychain/provider/ProviderHelper.java | 8 -- .../keychain/service/KeychainIntentService.java | 4 +- .../ui/dialog/PassphraseDialogFragment.java | 117 +++++++++------------ 6 files changed, 61 insertions(+), 87 deletions(-) (limited to 'OpenKeychain') 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 d0b18d757..948227819 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java @@ -41,17 +41,18 @@ public class CachedSecretKey extends CachedPublicKey { return (CachedSecretKeyRing) mRing; } - public void unlock(String passphrase) throws PgpGeneralException { + public boolean unlock(String passphrase) throws PgpGeneralException { try { PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); mPrivateKey = mSecretKey.extractPrivateKey(keyDecryptor); } catch (PGPException e) { - throw new PgpGeneralException("error extracting key!", e); + return false; } if(mPrivateKey == null) { - throw new PgpGeneralException("error extracting key (bad passphrase?)"); + throw new PgpGeneralException("error extracting key"); } + return true; } public PGPSignatureGenerator getSignatureGenerator(int hashAlgo, boolean cleartext) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 37dfee8b9..27e9e8ebd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -344,9 +344,11 @@ public class PgpDecryptVerify { currentProgress += 5; updateProgress(R.string.progress_extracting_key, currentProgress, 100); try { - secretEncryptionKey.unlock(mPassphrase); - } catch (PgpGeneralException e) { - throw new WrongPassphraseException(); + if (!secretEncryptionKey.unlock(mPassphrase)) { + throw new WrongPassphraseException(); + } + } catch(PgpGeneralException e) { + throw new KeyExtractionException(); } currentProgress += 5; updateProgress(R.string.progress_preparing_streams, currentProgress, 100); 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 7251709e0..1dfbfaf3a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -338,8 +338,8 @@ public class PgpKeyOperation { } public UncachedKeyRing buildSecretKey(CachedSecretKeyRing wmKR, - CachedPublicKeyRing wpKR, - SaveKeyringParcel saveParcel) + CachedPublicKeyRing wpKR, + SaveKeyringParcel saveParcel) throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException { PGPSecretKeyRing mKR = wmKR.getRing(); 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 b135f8920..f2abd915e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -293,14 +293,6 @@ public class ProviderHelper { } } - @Deprecated - public PGPPublicKeyRing getPGPPublicKeyRingWithKeyId(long keyId) - throws NotFoundException { - Uri uri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId)); - long masterKeyId = getMasterKeyId(uri); - return getPGPPublicKeyRing(masterKeyId); - } - @Deprecated public PGPSecretKeyRing getPGPSecretKeyRingWithKeyId(long keyId) throws NotFoundException { 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 972362f5f..af6e66937 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -801,7 +801,9 @@ public class KeychainIntentService extends IntentService CachedPublicKeyRing publicRing = providerHelper.getCachedPublicKeyRing(pubKeyId); CachedSecretKeyRing secretKeyRing = providerHelper.getCachedSecretKeyRing(masterKeyId); CachedSecretKey certificationKey = secretKeyRing.getSubKey(); - certificationKey.unlock(signaturePassphrase); + if(!certificationKey.unlock(signaturePassphrase)) { + throw new PgpGeneralException("Error extracting key (bad passphrase?)"); + } UncachedKeyRing newRing = certificationKey.certifyUserIds(publicRing, userIds); // store the signed key in our local cache diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java index 3cb1ce7b4..256d9d4b7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java @@ -41,17 +41,12 @@ import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import android.widget.Toast; -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPPrivateKey; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; -import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.pgp.CachedSecretKey; +import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.util.Log; @@ -139,18 +134,17 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor alert.setTitle(R.string.title_authentication); - final PGPSecretKey secretKey; + final CachedSecretKeyRing secretRing; final String userId; if (secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none) { - secretKey = null; + secretRing = null; alert.setMessage(R.string.passphrase_for_symmetric_encryption); } else { try { ProviderHelper helper = new ProviderHelper(activity); - secretKey = helper.getPGPSecretKeyRing(secretKeyId).getSecretKey(); - userId = (String) helper.getUnifiedData(secretKeyId, - KeychainContract.KeyRings.USER_ID, ProviderHelper.FIELD_TYPE_STRING); + secretRing = helper.getCachedSecretKeyRing(secretKeyId); + userId = secretRing.getPrimaryUserId(); } catch (ProviderHelper.NotFoundException e) { alert.setTitle(R.string.title_key_not_found); alert.setMessage(getString(R.string.key_not_found, secretKeyId)); @@ -179,76 +173,59 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor @Override public void onClick(DialogInterface dialog, int id) { dismiss(); - long curKeyIndex = 1; - boolean keyOK = true; + String passphrase = mPassphraseEditText.getText().toString(); - long keyId; - PGPSecretKey clickSecretKey = secretKey; - - if (clickSecretKey != null) { - while (keyOK) { - if (clickSecretKey != null) { // check again for loop - try { - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( - passphrase.toCharArray()); - PGPPrivateKey testKey = clickSecretKey - .extractPrivateKey(keyDecryptor); - if (testKey == null) { - if (!clickSecretKey.isMasterKey()) { - Toast.makeText(activity, - R.string.error_could_not_extract_private_key, - Toast.LENGTH_SHORT).show(); - - sendMessageToHandler(MESSAGE_CANCEL); - return; - } else { - try { - clickSecretKey = PgpKeyHelper.getKeyNum(new ProviderHelper(activity) - .getPGPSecretKeyRingWithKeyId(secretKeyId), - curKeyIndex - ); - } catch (ProviderHelper.NotFoundException e) { - Log.e(Constants.TAG, "key not found!", e); - } - curKeyIndex++; // does post-increment work like C? - continue; - } - } else { - keyOK = false; - } - } catch (PGPException e) { - Toast.makeText(activity, R.string.wrong_passphrase, - Toast.LENGTH_SHORT).show(); - - sendMessageToHandler(MESSAGE_CANCEL); - return; - } - } else { - Toast.makeText(activity, R.string.error_could_not_extract_private_key, - Toast.LENGTH_SHORT).show(); - - sendMessageToHandler(MESSAGE_CANCEL); - return; // ran out of keys to try + + // Early breakout if we are dealing with a symmetric key + if (secretRing == null) { + PassphraseCacheService.addCachedPassphrase(activity, Constants.key.symmetric, passphrase); + // also return passphrase back to activity + Bundle data = new Bundle(); + data.putString(MESSAGE_DATA_PASSPHRASE, passphrase); + sendMessageToHandler(MESSAGE_OKAY, data); + return; + } + + CachedSecretKey unlockedSecretKey = null; + + for(CachedSecretKey clickSecretKey : secretRing.iterator()) { + try { + boolean unlocked = clickSecretKey.unlock(passphrase); + if (unlocked) { + unlockedSecretKey = clickSecretKey; + break; } + } catch (PgpGeneralException e) { + Toast.makeText(activity, R.string.error_could_not_extract_private_key, + Toast.LENGTH_SHORT).show(); + + sendMessageToHandler(MESSAGE_CANCEL); + return; // ran out of keys to try } - keyId = secretKey.getKeyID(); - } else { - keyId = Constants.key.symmetric; } + // Means we got an exception every time + if (unlockedSecretKey == null) { + Toast.makeText(activity, R.string.wrong_passphrase, + Toast.LENGTH_SHORT).show(); + + sendMessageToHandler(MESSAGE_CANCEL); + return; + } + + long masterKeyId = secretRing.getMasterKeyId(); + // cache the new passphrase Log.d(Constants.TAG, "Everything okay! Caching entered passphrase"); - PassphraseCacheService.addCachedPassphrase(activity, keyId, passphrase); - if (!keyOK && clickSecretKey.getKeyID() != keyId) { - PassphraseCacheService.addCachedPassphrase(activity, clickSecretKey.getKeyID(), - passphrase); + PassphraseCacheService.addCachedPassphrase(activity, masterKeyId, passphrase); + if (unlockedSecretKey.getKeyId() != masterKeyId) { + PassphraseCacheService.addCachedPassphrase( + activity, unlockedSecretKey.getKeyId(), passphrase); } // also return passphrase back to activity Bundle data = new Bundle(); data.putString(MESSAGE_DATA_PASSPHRASE, passphrase); - sendMessageToHandler(MESSAGE_OKAY, data); } }); -- cgit v1.2.3 From d68fce687500fc308b5efaef8108e0ff9a26f556 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 4 May 2014 12:07:19 +0200 Subject: wrapped-key-ring: view certify --- .../keychain/pgp/CachedPublicKey.java | 13 +++++++++++++ .../keychain/ui/ViewCertActivity.java | 22 +++++----------------- 2 files changed, 18 insertions(+), 17 deletions(-) (limited to 'OpenKeychain') 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 2862b21c5..c1d866fba 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java @@ -11,6 +11,7 @@ import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodG 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; @@ -157,6 +158,18 @@ public class CachedPublicKey { sig.init(contentVerifierBuilderProvider, mKey); } + /** 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, mKey); + } catch (SignatureException e) { + throw new PGPException("Error!", e); + } + } + public byte[] getFingerprint() { return mKey.getFingerprint(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java index f740cfc22..1d2b50faa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -37,20 +37,17 @@ import org.spongycastle.bcpg.SignatureSubpacket; import org.spongycastle.bcpg.SignatureSubpacketTags; import org.spongycastle.bcpg.sig.RevocationReason; import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPSignature; -import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.CachedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.Log; -import java.security.SignatureException; import java.util.Date; public class ViewCertActivity extends ActionBarActivity @@ -147,26 +144,17 @@ public class ViewCertActivity extends ActionBarActivity PGPSignature sig = PgpConversionHelper.BytesToPGPSignature(data.getBlob(INDEX_DATA)); try { ProviderHelper providerHelper = new ProviderHelper(this); - PGPKeyRing signeeRing = providerHelper.getPGPKeyRing( - KeychainContract.KeyRingData.buildPublicKeyRingUri( - Long.toString(data.getLong(INDEX_MASTER_KEY_ID)))); - PGPKeyRing signerRing = providerHelper.getPGPKeyRing( - KeychainContract.KeyRingData.buildPublicKeyRingUri( - Long.toString(sig.getKeyID()))); - + CachedPublicKeyRing signeeRing = providerHelper.getCachedPublicKeyRing(data.getLong(INDEX_MASTER_KEY_ID)); + CachedPublicKeyRing signerRing = providerHelper.getCachedPublicKeyRing(sig.getKeyID()); try { - sig.init(new JcaPGPContentVerifierBuilderProvider().setProvider( - Constants.BOUNCY_CASTLE_PROVIDER_NAME), signerRing.getPublicKey()); - if (sig.verifyCertification(signeeUid, signeeRing.getPublicKey())) { + signerRing.getSubkey().initSignature(sig); + if (signeeRing.getSubkey().verifySignature(sig, signeeUid)) { mStatus.setText(R.string.cert_verify_ok); mStatus.setTextColor(getResources().getColor(R.color.bbutton_success)); } else { mStatus.setText(R.string.cert_verify_failed); mStatus.setTextColor(getResources().getColor(R.color.alert)); } - } catch (SignatureException e) { - mStatus.setText(R.string.cert_verify_error); - mStatus.setTextColor(getResources().getColor(R.color.alert)); } catch (PGPException e) { mStatus.setText(R.string.cert_verify_error); mStatus.setTextColor(getResources().getColor(R.color.alert)); -- cgit v1.2.3 From d0e3af505cb0bd1405fac9f28ec32a404a8b0751 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 4 May 2014 12:08:53 +0200 Subject: wrapped-key-ring: cached data revamp --- .../keychain/provider/KeychainProvider.java | 70 ++++++++++++---------- 1 file changed, 37 insertions(+), 33 deletions(-) (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 64dab3020..c67c2eca4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.util.Log; import java.util.Arrays; import java.util.Date; import java.util.HashMap; +import java.util.List; public class KeychainProvider extends ContentProvider { @@ -242,16 +243,16 @@ public class KeychainProvider extends ContentProvider { HashMap projectionMap = new HashMap(); projectionMap.put(KeyRings._ID, Tables.KEYS + ".oid AS _id"); projectionMap.put(KeyRings.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID); - projectionMap.put(KeyRings.KEY_ID, Keys.KEY_ID); - projectionMap.put(KeyRings.KEY_SIZE, Keys.KEY_SIZE); + projectionMap.put(KeyRings.KEY_ID, Tables.KEYS + "." + Keys.KEY_ID); + projectionMap.put(KeyRings.KEY_SIZE, Tables.KEYS + "." + Keys.KEY_SIZE); projectionMap.put(KeyRings.IS_REVOKED, Tables.KEYS + "." + Keys.IS_REVOKED); - projectionMap.put(KeyRings.CAN_CERTIFY, Keys.CAN_CERTIFY); - projectionMap.put(KeyRings.CAN_ENCRYPT, Keys.CAN_ENCRYPT); - projectionMap.put(KeyRings.CAN_SIGN, Keys.CAN_SIGN); + projectionMap.put(KeyRings.CAN_CERTIFY, Tables.KEYS + "." + Keys.CAN_CERTIFY); + projectionMap.put(KeyRings.CAN_ENCRYPT, Tables.KEYS + "." + Keys.CAN_ENCRYPT); + projectionMap.put(KeyRings.CAN_SIGN, Tables.KEYS + "." + Keys.CAN_SIGN); projectionMap.put(KeyRings.CREATION, Tables.KEYS + "." + Keys.CREATION); - projectionMap.put(KeyRings.EXPIRY, Keys.EXPIRY); - projectionMap.put(KeyRings.ALGORITHM, Keys.ALGORITHM); - projectionMap.put(KeyRings.FINGERPRINT, Keys.FINGERPRINT); + projectionMap.put(KeyRings.EXPIRY, Tables.KEYS + "." + Keys.EXPIRY); + projectionMap.put(KeyRings.ALGORITHM, Tables.KEYS + "." + Keys.ALGORITHM); + projectionMap.put(KeyRings.FINGERPRINT, Tables.KEYS + "." + Keys.FINGERPRINT); projectionMap.put(KeyRings.USER_ID, UserIds.USER_ID); projectionMap.put(KeyRings.VERIFIED, KeyRings.VERIFIED); projectionMap.put(KeyRings.PUBKEY_DATA, @@ -267,26 +268,14 @@ public class KeychainProvider extends ContentProvider { + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + ")) AS " + KeyRings.HAS_ANY_SECRET); projectionMap.put(KeyRings.HAS_ENCRYPT, - "(EXISTS (SELECT * FROM " + Tables.KEYS + " AS k" - +" WHERE k." + Keys.MASTER_KEY_ID - + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " AND k." + Keys.IS_REVOKED + " = 0" - + " AND k." + Keys.CAN_ENCRYPT + " = 1" - + " AND ( k." + Keys.EXPIRY + " IS NULL OR k." + Keys.EXPIRY - + " >= " + new Date().getTime() / 1000 + " )" - + ")) AS " + KeyRings.HAS_ENCRYPT); + "kE." + Keys.KEY_ID + " AS " + KeyRings.HAS_ENCRYPT); projectionMap.put(KeyRings.HAS_SIGN, - "(EXISTS (SELECT * FROM " + Tables.KEYS + " AS k" - +" WHERE k." + Keys.MASTER_KEY_ID - + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " AND k." + Keys.IS_REVOKED + " = 0" - + " AND k." + Keys.HAS_SECRET + " = 1" - + " AND k." + Keys.CAN_SIGN + " = 1" - + " AND ( k." + Keys.EXPIRY + " IS NULL OR k." + Keys.EXPIRY - + " >= " + new Date().getTime() / 1000 + " )" - + ")) AS " + KeyRings.HAS_SIGN); + "kS." + Keys.KEY_ID + " AS " + KeyRings.HAS_SIGN); qb.setProjectionMap(projectionMap); + // Need this as list so we can search in it + List plist = Arrays.asList(projection); + qb.setTables( Tables.KEYS + " INNER JOIN " + Tables.USER_IDS + " ON (" @@ -301,22 +290,37 @@ public class KeychainProvider extends ContentProvider { + " AND " + Tables.CERTS + "." + Certs.VERIFIED + " = " + Certs.VERIFIED_SECRET + ")" - // fairly expensive join (due to blob data), only do it when requested - + (Arrays.asList(projection).contains(KeyRings.PUBKEY_DATA) ? + // fairly expensive joins following, only do when requested + + (plist.contains(KeyRings.PUBKEY_DATA) ? " INNER JOIN " + Tables.KEY_RINGS_PUBLIC + " ON (" + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = " + Tables.KEY_RINGS_PUBLIC + "." + KeyRingData.MASTER_KEY_ID - + ")" - : "") - // fairly expensive join (due to blob data), only do it when requested - + (Arrays.asList(projection).contains(KeyRings.PRIVKEY_DATA) ? + + ")" : "") + + (plist.contains(KeyRings.PRIVKEY_DATA) ? " LEFT JOIN " + Tables.KEY_RINGS_SECRET + " ON (" + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = " + Tables.KEY_RINGS_SECRET + "." + KeyRingData.MASTER_KEY_ID - + ")" - : "") + + ")" : "") + + (plist.contains(KeyRings.HAS_ENCRYPT) ? + " LEFT JOIN " + Tables.KEYS + " AS kE ON (" + +"kE." + Keys.MASTER_KEY_ID + + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " AND kE." + Keys.IS_REVOKED + " = 0" + + " AND kE." + Keys.CAN_ENCRYPT + " = 1" + + " AND ( kE." + Keys.EXPIRY + " IS NULL OR kE." + Keys.EXPIRY + + " >= " + new Date().getTime() / 1000 + " )" + + ")" : "") + + (plist.contains(KeyRings.HAS_SIGN) ? + " LEFT JOIN " + Tables.KEYS + " AS kS ON (" + +"kS." + Keys.MASTER_KEY_ID + + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + + " AND kS." + Keys.IS_REVOKED + " = 0" + + " AND kS." + Keys.CAN_SIGN + " = 1" + + " AND ( kS." + Keys.EXPIRY + " IS NULL OR kS." + Keys.EXPIRY + + " >= " + new Date().getTime() / 1000 + " )" + + ")" : "") ); qb.appendWhere(Tables.KEYS + "." + Keys.RANK + " = 0"); // in case there are multiple verifying certificates -- cgit v1.2.3 From 411b4cfeb2caa1d7d1c33129711bc1cd617778cf Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 4 May 2014 12:55:22 +0200 Subject: wrapped-key-ring: redesign underlying CachedKeyRing --- .../keychain/pgp/CachedKeyRing.java | 53 +++++++---- .../keychain/pgp/CachedPublicKeyRing.java | 80 ++++++++--------- .../keychain/pgp/CachedSecretKeyRing.java | 94 ++++++++----------- .../keychain/pgp/PgpSignEncrypt.java | 9 +- .../keychain/provider/ProviderHelper.java | 100 ++++++++------------- .../keychain/ui/EncryptAsymmetricFragment.java | 8 +- 6 files changed, 153 insertions(+), 191 deletions(-) (limited to 'OpenKeychain') 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 334f676c4..def673469 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java @@ -3,45 +3,66 @@ package org.sufficientlysecure.keychain.pgp; public abstract class CachedKeyRing { private final long mMasterKeyId; - private final boolean mCanCertify; - private final byte[] mFingerprint; private final String mUserId; + private final boolean mHasAnySecret; + private final boolean mIsRevoked; + private final boolean mCanCertify; + private final long mHasEncryptId; + private final long mHasSignId; private final int mVerified; - private final boolean mHasSecret; - protected CachedKeyRing(long masterKeyId, boolean canCertify, - byte[] fingerprint, String userId, int verified, boolean hasSecret) + protected CachedKeyRing(long masterKeyId, String userId, boolean hasAnySecret, + boolean isRevoked, boolean canCertify, long hasEncryptId, long hasSignId, + int verified) { mMasterKeyId = masterKeyId; - mCanCertify = canCertify; - mFingerprint = fingerprint; mUserId = userId; + mHasAnySecret = hasAnySecret; + mIsRevoked = isRevoked; + mCanCertify = canCertify; + mHasEncryptId = hasEncryptId; + mHasSignId = hasSignId; mVerified = verified; - mHasSecret = hasSecret; } - public byte[] getFingerprint() { - return mFingerprint; + public long getMasterKeyId() { + return mMasterKeyId; } public String getPrimaryUserId() { return mUserId; } - public long getMasterKeyId() { - return mMasterKeyId; + public boolean hasAnySecret() { + return mHasAnySecret; } - public int getVerified() { - return mVerified; + public boolean isRevoked() { + return mIsRevoked; } public boolean canCertify() { return mCanCertify; } - public boolean hasSecret() { - return mHasSecret; + public long getEncryptId() { + return mHasEncryptId; + } + + public boolean hasEncrypt() { + return mHasEncryptId != 0; + } + + public long getSignId() { + return mHasSignId; + } + + public boolean hasSign() { + return mHasSignId != 0; + } + + public int getVerified() { + return mVerified; } } 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 8970d18ec..bbce42f86 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java @@ -23,14 +23,14 @@ public class CachedPublicKeyRing extends CachedKeyRing { private PGPPublicKeyRing mRing; private final byte[] mPubKey; - public CachedPublicKeyRing(long masterKeyId, int keySize, boolean isRevoked, - boolean canCertify, long creation, long expiry, int algorithm, - byte[] fingerprint, String userId, int verified, boolean hasSecret, - byte[] pubkey) + public CachedPublicKeyRing(long masterKeyId, String userId, boolean hasAnySecret, + boolean isRevoked, boolean canCertify, long hasEncryptId, long hasSignId, + int verified, byte[] blob) { - super(masterKeyId, canCertify, fingerprint, userId, verified, hasSecret); + super(masterKeyId, userId, hasAnySecret, isRevoked, canCertify, + hasEncryptId, hasSignId, verified); - mPubKey = pubkey; + mPubKey = blob; } PGPPublicKeyRing getRing() { @@ -52,46 +52,18 @@ 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(getRing().getPublicKeys())) { - CachedPublicKey key = new CachedPublicKey(this, k); - if (key.isRevoked() || key.canSign() || key.isExpired()) { - continue; + /** Getter that returns the subkey that should be used for signing. */ + CachedPublicKey getEncryptionSubKey() throws PgpGeneralException { + PGPPublicKey key = getRing().getPublicKey(getEncryptId()); + if(key != null) { + CachedPublicKey cKey = new CachedPublicKey(this, key); + if(!cKey.canEncrypt()) { + throw new PgpGeneralException("key error"); } - 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 - CachedPublicKey masterKey = null; - for (PGPPublicKey k : new IterableIterator(getRing().getPublicKeys())) { - CachedPublicKey key = new CachedPublicKey(this, k); - if (key.isRevoked() || key.canEncrypt() || key.isExpired()) { - continue; - } - if (key.isMasterKey()) { - masterKey = key; - } else { - return key; - } - } - if(masterKey == null) { - // TODO proper exception - throw new PgpGeneralException("key not found"); + return cKey; } - return masterKey; + // TODO handle with proper exception + throw new PgpGeneralException("no encryption key available"); } public boolean verifySubkeyBinding(CachedPublicKey cachedSubkey) { @@ -189,4 +161,24 @@ public class CachedPublicKeyRing extends CachedKeyRing { return validPrimaryKeyBinding; } + public IterableIterator iterator() { + final Iterator it = getRing().getPublicKeys(); + return new IterableIterator(new Iterator() { + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public CachedPublicKey next() { + return new CachedPublicKey(CachedPublicKeyRing.this, it.next()); + } + + @Override + public void remove() { + it.remove(); + } + }); + } + } \ No newline at end of file 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 590a02b95..398092aeb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java @@ -1,18 +1,15 @@ 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; import org.spongycastle.openpgp.PGPSecretKey; 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.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.util.IterableIterator; import java.io.IOException; @@ -23,12 +20,13 @@ public class CachedSecretKeyRing extends CachedKeyRing { private PGPSecretKeyRing mRing; - public CachedSecretKeyRing(long masterKeyId, int keySize, boolean isRevoked, - boolean canCertify, long creation, long expiry, int algorithm, - byte[] fingerprint, String userId, int verified, boolean hasSecret, - byte[] blob) + public CachedSecretKeyRing(long masterKeyId, String userId, boolean hasAnySecret, + boolean isRevoked, boolean canCertify, long hasEncryptId, long hasSignId, + int verified, byte[] blob) { - super(masterKeyId, canCertify, fingerprint, userId, verified, hasSecret); + super(masterKeyId, userId, hasAnySecret, + isRevoked, canCertify, hasEncryptId, hasSignId, + verified); mRing = (PGPSecretKeyRing) PgpConversionHelper.BytesToPGPKeyRing(blob); } @@ -45,8 +43,18 @@ public class CachedSecretKeyRing extends CachedKeyRing { return new CachedSecretKey(this, mRing.getSecretKey(id)); } - public IterableIterator iterator() { - return new IterableIterator(mRing.getSecretKeys()); + /** Getter that returns the subkey that should be used for signing. */ + CachedSecretKey getSigningSubKey() throws PgpGeneralException { + PGPSecretKey key = mRing.getSecretKey(getSignId()); + if(key != null) { + CachedSecretKey cKey = new CachedSecretKey(this, key); + if(!cKey.canSign()) { + throw new PgpGeneralException("key error"); + } + return cKey; + } + // TODO handle with proper exception + throw new PgpGeneralException("no signing key available"); } public boolean hasPassphrase() { @@ -74,50 +82,6 @@ public class CachedSecretKeyRing extends CachedKeyRing { } } - /** This returns the subkey that should be used for signing. - * At this point, this is simply the first suitable subkey. - */ - CachedSecretKey getSigningSubKey() { - for (PGPSecretKey key : new IterableIterator(mRing.getSecretKeys())) { - if (isSigningKey(key.getPublicKey())) { - return new CachedSecretKey(this, key); - } - } - // TODO exception - return null; - } - - @SuppressWarnings("unchecked") - public static boolean isSigningKey(PGPPublicKey key) { - if (key.getVersion() <= 3) { - return true; - } - - // special case - if (key.getAlgorithm() == PGPPublicKey.RSA_SIGN) { - return true; - } - - for (PGPSignature sig : new IterableIterator(key.getSignatures())) { - if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) { - continue; - } - PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets(); - - if (hashed != null && (hashed.getKeyFlags() & KeyFlags.SIGN_DATA) != 0) { - return true; - } - - PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets(); - - if (unhashed != null && (unhashed.getKeyFlags() & KeyFlags.SIGN_DATA) != 0) { - return true; - } - } - - return false; - } - public UncachedSecretKeyRing changeSecretKeyPassphrase(String oldPassphrase, String newPassphrase) throws IOException, PGPException, NoSuchProviderException { @@ -141,4 +105,24 @@ public class CachedSecretKeyRing extends CachedKeyRing { } + public IterableIterator iterator() { + final Iterator it = mRing.getSecretKeys(); + return new IterableIterator(new Iterator() { + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public CachedSecretKey next() { + return new CachedSecretKey(CachedSecretKeyRing.this, it.next()); + } + + @Override + public void remove() { + it.remove(); + } + }); + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java index 48cc5d6da..ccbbb3719 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -270,14 +270,15 @@ public class PgpSignEncrypt { /* Get keys for signature generation for later usage */ CachedSecretKey signingKey = null; if (enableSignature) { - CachedSecretKeyRing signingKeyRing = null; + CachedSecretKeyRing signingKeyRing; try { signingKeyRing = mProviderHelper.getCachedSecretKeyRing(mSignatureMasterKeyId); } catch (ProviderHelper.NotFoundException e) { throw new NoSigningKeyException(); } - signingKey = signingKeyRing.getSigningSubKey(); - if (signingKey == null) { + try { + signingKey = signingKeyRing.getSigningSubKey(); + } catch(PgpGeneralException e) { throw new NoSigningKeyException(); } @@ -319,7 +320,7 @@ public class PgpSignEncrypt { try { CachedPublicKeyRing keyRing = mProviderHelper.getCachedPublicKeyRing( KeyRings.buildUnifiedKeyRingUri(Long.toString(id))); - CachedPublicKey key = keyRing.getFirstEncryptSubkey(); + CachedPublicKey key = keyRing.getEncryptionSubKey(); cPk.addMethod(key.getPubKeyEncryptionGenerator()); } catch (PgpGeneralException e) { Log.e(Constants.TAG, "key not found!", e); 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 f2abd915e..d1a003ec1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -38,6 +38,7 @@ import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.pgp.CachedKeyRing; import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.CachedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; @@ -193,86 +194,55 @@ public class ProviderHelper { } public CachedPublicKeyRing getCachedPublicKeyRing(long id) throws NotFoundException { - return getCachedPublicKeyRing(KeyRings.buildUnifiedKeyRingUri(Long.toString(id))); + return (CachedPublicKeyRing) getCachedKeyRing( + KeyRings.buildUnifiedKeyRingUri(Long.toString(id)), false); } public CachedPublicKeyRing getCachedPublicKeyRing(Uri queryUri) throws NotFoundException { - Cursor cursor = mContentResolver.query(queryUri, - new String[] { - KeyRings.MASTER_KEY_ID, KeyRings.KEY_SIZE, - KeyRings.IS_REVOKED, KeyRings.CAN_CERTIFY, - KeyRings.CREATION, KeyRings.EXPIRY, - KeyRings.ALGORITHM, KeyRings.FINGERPRINT, - KeyRings.USER_ID, KeyRings.VERIFIED, - KeyRings.HAS_SECRET, KeyRings.PUBKEY_DATA - }, null, null, null); - try { - if (cursor != null && cursor.moveToFirst()) { - long masterKeyId = cursor.getLong(0); - int keySize = cursor.getInt(1); - boolean isRevoked = cursor.getInt(2) > 0; - boolean canCertify = cursor.getInt(3) > 0; - long creation = cursor.getLong(4); - long expiry = cursor.getLong(5); - int algorithm = cursor.getInt(6); - byte[] fingerprint = cursor.getBlob(7); - String userId = cursor.getString(8); - int verified = cursor.getInt(9); - boolean hasSecret = cursor.getInt(10) > 0; - byte[] pubkey = cursor.getBlob(11); - return new CachedPublicKeyRing( - masterKeyId, keySize, isRevoked, canCertify, - creation, expiry, algorithm, fingerprint, - userId, verified, hasSecret, pubkey - ); - } else { - throw new NotFoundException("Key not found!"); - } - } finally { - if (cursor != null) { - cursor.close(); - } - } + return (CachedPublicKeyRing) getCachedKeyRing(queryUri, false); } public CachedSecretKeyRing getCachedSecretKeyRing(long id) throws NotFoundException { - return getCachedSecretKeyRing(KeyRings.buildUnifiedKeyRingUri(Long.toString(id))); + return (CachedSecretKeyRing) getCachedKeyRing( + KeyRings.buildUnifiedKeyRingUri(Long.toString(id)), true); } public CachedSecretKeyRing getCachedSecretKeyRing(Uri queryUri) throws NotFoundException { + return (CachedSecretKeyRing) getCachedKeyRing(queryUri, true); + } + + + private CachedKeyRing getCachedKeyRing(Uri queryUri, boolean secret) throws NotFoundException { Cursor cursor = mContentResolver.query(queryUri, new String[] { - KeyRings.MASTER_KEY_ID, KeyRings.KEY_SIZE, - KeyRings.IS_REVOKED, KeyRings.CAN_CERTIFY, - KeyRings.CREATION, KeyRings.EXPIRY, - KeyRings.ALGORITHM, KeyRings.FINGERPRINT, - KeyRings.USER_ID, KeyRings.VERIFIED, - KeyRings.HAS_SECRET, KeyRings.PRIVKEY_DATA + // we pick from cache: + // basic data, primary uid in particular because it's expensive + KeyRings.MASTER_KEY_ID, KeyRings.USER_ID, KeyRings.HAS_ANY_SECRET, + // complex knowledge about subkeys + KeyRings.IS_REVOKED, KeyRings.CAN_CERTIFY, KeyRings.HAS_ENCRYPT, KeyRings.HAS_SIGN, + // stuff only the db knows and of course, ring data + KeyRings.VERIFIED, secret ? KeyRings.PRIVKEY_DATA : KeyRings.PUBKEY_DATA }, null, null, null); try { if (cursor != null && cursor.moveToFirst()) { - // check if a privkey is actually available - byte[] privkey = cursor.getBlob(11); - if(privkey == null) { - throw new NotFoundException("Key found, but no secret key available!"); - } - long masterKeyId = cursor.getLong(0); - int keySize = cursor.getInt(1); - boolean isRevoked = cursor.getInt(2) > 0; - boolean canCertify = cursor.getInt(3) > 0; - long creation = cursor.getLong(4); - long expiry = cursor.getLong(5); - int algorithm = cursor.getInt(6); - byte[] fingerprint = cursor.getBlob(7); - String userId = cursor.getString(8); - int verified = cursor.getInt(9); - boolean hasSecret = cursor.getInt(10) > 0; - return new CachedSecretKeyRing( - masterKeyId, keySize, isRevoked, canCertify, - creation, expiry, algorithm, fingerprint, - userId, verified, hasSecret, privkey - ); + String userId = cursor.getString(1); + boolean hasAnySecret = cursor.getInt(2) > 0; + boolean isRevoked = cursor.getInt(3) > 0; + boolean canCertify = cursor.getInt(4) > 0; + long hasEncryptId = cursor.getLong(5); + long hasSignId = cursor.getLong(6); + int verified = cursor.getInt(7); + byte[] blob = cursor.getBlob(8); + return secret + ? new CachedSecretKeyRing( + masterKeyId, userId, hasAnySecret, + isRevoked, canCertify, hasEncryptId, hasSignId, + verified, blob) + : new CachedPublicKeyRing( + masterKeyId, userId, hasAnySecret, + isRevoked, canCertify, hasEncryptId, hasSignId, + verified, blob); } else { throw new NotFoundException("Key not found!"); } 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 51a229677..0b6449cda 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -30,16 +30,10 @@ import android.widget.TextView; import com.beardedhen.androidbootstrap.BootstrapButton; -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; @@ -155,7 +149,7 @@ public class EncryptAsymmetricFragment extends Fragment { try { CachedPublicKeyRing keyring = providerHelper.getCachedPublicKeyRing(preselectedSignatureKeyId); - if(keyring.hasSecret()) { + if(keyring.hasAnySecret()) { setSignatureKeyId(keyring.getMasterKeyId()); } } catch (ProviderHelper.NotFoundException e) { -- cgit v1.2.3 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 (limited to 'OpenKeychain') 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 From cd8af25ba71d95ebb2ab2a3ab4b19dc28cad63fc Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 4 May 2014 16:59:20 +0200 Subject: wrapped-key-ring: more work on passphrase caching and certification --- .../keychain/pgp/PgpKeyHelper.java | 17 ------ .../keychain/service/PassphraseCacheService.java | 66 +++++++++++----------- .../keychain/ui/CertifyKeyActivity.java | 63 ++++++--------------- .../ui/dialog/PassphraseDialogFragment.java | 8 ++- 4 files changed, 56 insertions(+), 98 deletions(-) (limited to 'OpenKeychain') 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 e888d594e..77697b026 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java @@ -81,23 +81,6 @@ public class PgpKeyHelper { return getExpiryDate(key.getPublicKey()); } - @SuppressWarnings("unchecked") - @Deprecated - public static PGPSecretKey getKeyNum(PGPSecretKeyRing keyRing, long num) { - long cnt = 0; - if (keyRing == null) { - return null; - } - for (PGPSecretKey key : new IterableIterator(keyRing.getSecretKeys())) { - if (cnt == num) { - return key; - } - cnt++; - } - - return null; - } - public static int getKeyUsage(PGPSecretKey key) { return getKeyUsage(key.getPublicKey()); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index 88e974288..2889b89c6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -42,6 +42,7 @@ import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.Log; @@ -163,38 +164,46 @@ public class PassphraseCacheService extends Service { * @return */ private String getCachedPassphraseImpl(long keyId) { - Log.d(TAG, "getCachedPassphraseImpl() get masterKeyId for " + keyId); - - // try to get master key id which is used as an identifier for cached passphrases - long masterKeyId = keyId; - if (masterKeyId != Constants.key.symmetric) { - try { - masterKeyId = new ProviderHelper(this).getMasterKeyId( - KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId))); - } catch (ProviderHelper.NotFoundException e) { + // passphrase for symmetric encryption? + if (keyId == Constants.key.symmetric) { + Log.d(TAG, "getCachedPassphraseImpl() for symmetric encryption"); + String cachedPassphrase = mPassphraseCache.get(Constants.key.symmetric); + if (cachedPassphrase == null) { return null; } + addCachedPassphrase(this, Constants.key.symmetric, cachedPassphrase); + return cachedPassphrase; } - Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + masterKeyId); - // get cached passphrase - String cachedPassphrase = mPassphraseCache.get(masterKeyId); - if (cachedPassphrase == null) { - // if key has no passphrase -> cache and return empty passphrase - if (!hasPassphrase(this, masterKeyId)) { + // try to get master key id which is used as an identifier for cached passphrases + try { + Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + keyId); + CachedSecretKeyRing key = new ProviderHelper(this).getCachedSecretKeyRing( + KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId))); + // no passphrase needed? just add empty string and return it, then + if (!key.hasPassphrase()) { Log.d(Constants.TAG, "Key has no passphrase! Caches and returns empty passphrase!"); - addCachedPassphrase(this, masterKeyId, ""); + addCachedPassphrase(this, keyId, ""); return ""; - } else { + } + + // get cached passphrase + String cachedPassphrase = mPassphraseCache.get(keyId); + if (cachedPassphrase == null) { + // this is an error return null; } - } - // set it again to reset the cache life cycle - Log.d(TAG, "Cache passphrase again when getting it!"); - addCachedPassphrase(this, masterKeyId, cachedPassphrase); - return cachedPassphrase; + // set it again to reset the cache life cycle + Log.d(TAG, "Cache passphrase again when getting it!"); + addCachedPassphrase(this, keyId, cachedPassphrase); + return cachedPassphrase; + + } catch (ProviderHelper.NotFoundException e) { + Log.e(TAG, "Passphrase for unknown key was requested!"); + return null; + } } @Deprecated @@ -230,16 +239,9 @@ public class PassphraseCacheService extends Service { * @return true if it has a passphrase */ @Deprecated - public static boolean hasPassphrase(Context context, long secretKeyId) { - // check if the key has no passphrase - try { - PGPSecretKeyRing secRing = new ProviderHelper(context).getPGPSecretKeyRing(secretKeyId); - return hasPassphrase(secRing); - } catch (ProviderHelper.NotFoundException e) { - Log.e(Constants.TAG, "key not found!", e); - } - - return true; + public static boolean hasPassphrase(Context context, long secretKeyId) + throws ProviderHelper.NotFoundException { + return new ProviderHelper(context).getCachedSecretKeyRing(secretKeyId).hasPassphrase(); } /** diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index fbcbbb0c3..30e8d9537 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -226,53 +226,22 @@ public class CertifyKeyActivity extends ActionBarActivity implements * handles the UI bits of the signing process on the UI thread */ private void initiateSigning() { - try { - PGPPublicKeyRing pubring = new ProviderHelper(this).getPGPPublicKeyRing(mPubKeyId); - - // if we have already signed this key, dont bother doing it again - boolean alreadySigned = false; - - /* todo: reconsider this at a later point when certs are in the db - @SuppressWarnings("unchecked") - Iterator itr = pubring.getPublicKey(mPubKeyId).getSignatures(); - while (itr.hasNext()) { - PGPSignature sig = itr.next(); - if (sig.getKeyID() == mMasterKeyId) { - alreadySigned = true; - break; - } - } - */ - - if (!alreadySigned) { - /* - * get the user's passphrase for this key (if required) - */ - String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId); - if (passphrase == null) { - PassphraseDialogFragment.show(this, mMasterKeyId, - new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - startSigning(); - } - } - }); - // bail out; need to wait until the user has entered the passphrase before trying again - return; - } else { - startSigning(); - } - } else { - AppMsg.makeText(this, R.string.key_has_already_been_certified, AppMsg.STYLE_ALERT) - .show(); - - setResult(RESULT_CANCELED); - finish(); - } - } catch (ProviderHelper.NotFoundException e) { - Log.e(Constants.TAG, "key not found!", e); + // get the user's passphrase for this key (if required) + String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId); + if (passphrase == null) { + PassphraseDialogFragment.show(this, mMasterKeyId, + new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { + startSigning(); + } + } + }); + // bail out; need to wait until the user has entered the passphrase before trying again + return; + } else { + startSigning(); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java index 256d9d4b7..9b5581cc7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java @@ -101,8 +101,12 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor long secretKeyId) throws PgpGeneralException { // check if secret key has a passphrase if (!(secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none)) { - if (!PassphraseCacheService.hasPassphrase(context, secretKeyId)) { - throw new PgpGeneralException("No passphrase! No passphrase dialog needed!"); + try { + if (new ProviderHelper(context).getCachedSecretKeyRing(secretKeyId).hasPassphrase()) { + throw new PgpGeneralException("No passphrase! No passphrase dialog needed!"); + } + } catch(ProviderHelper.NotFoundException e) { + throw new PgpGeneralException("Error: Key not found!", e); } } -- cgit v1.2.3 From 9baddb7d719b09fb88f6fc4e7ed8ec495b68c3e1 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 4 May 2014 16:59:55 +0200 Subject: wrapped-key-ring: get rid of bc objects in key editor --- .../keychain/pgp/CachedSecretKey.java | 8 ++++ .../keychain/pgp/PgpConversionHelper.java | 33 +++------------- .../keychain/pgp/PgpKeyOperation.java | 10 ++--- .../keychain/remote/OpenPgpService.java | 2 +- .../keychain/service/KeychainIntentService.java | 2 +- .../keychain/service/SaveKeyringParcel.java | 35 ++++++++++++----- .../keychain/ui/CertifyKeyActivity.java | 2 - .../keychain/ui/EditKeyActivity.java | 45 ++++++++++------------ .../keychain/ui/widget/KeyEditor.java | 45 +++++++++++----------- .../keychain/ui/widget/SectionView.java | 16 ++++---- 10 files changed, 98 insertions(+), 100 deletions(-) (limited to 'OpenKeychain') 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 d1634859a..8e45ceb4f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java @@ -40,6 +40,14 @@ public class CachedSecretKey extends CachedPublicKey { return (CachedSecretKeyRing) mRing; } + /** Returns the wrapped PGPSecretKeyRing. + * This function is for compatibility only, should not be used anymore and will be removed + */ + @Deprecated + public PGPSecretKey getKeyExternal() { + return mSecretKey; + } + public boolean unlock(String passphrase) throws PgpGeneralException { try { PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( 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 2199047cd..63e2ff2f2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java @@ -26,12 +26,10 @@ import org.spongycastle.openpgp.PGPSignatureList; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.util.Log; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; - public class PgpConversionHelper { /** @@ -60,10 +58,10 @@ public class PgpConversionHelper { * @param keysBytes * @return */ - public static ArrayList BytesToPGPSecretKeyList(byte[] keysBytes) { + public static ArrayList BytesToPGPSecretKeyList(byte[] keysBytes) { PGPObjectFactory factory = new PGPObjectFactory(keysBytes); Object obj = null; - ArrayList keys = new ArrayList(); + ArrayList keys = new ArrayList(); try { while ((obj = factory.nextObject()) != null) { PGPSecretKey secKey = null; @@ -72,7 +70,7 @@ public class PgpConversionHelper { if (secKey == null) { Log.e(Constants.TAG, "No keys given!"); } - keys.add(secKey); + keys.add(new UncachedSecretKey(secKey)); } else if (obj instanceof PGPSecretKeyRing) { //master keys are sent as keyrings PGPSecretKeyRing keyRing = null; keyRing = (PGPSecretKeyRing) obj; @@ -82,7 +80,7 @@ public class PgpConversionHelper { @SuppressWarnings("unchecked") Iterator itr = keyRing.getSecretKeys(); while (itr.hasNext()) { - keys.add(itr.next()); + keys.add(new UncachedSecretKey(itr.next())); } } } @@ -100,7 +98,7 @@ public class PgpConversionHelper { * @param keyBytes * @return */ - public static PGPSecretKey BytesToPGPSecretKey(byte[] keyBytes) { + public static UncachedSecretKey BytesToPGPSecretKey(byte[] keyBytes) { PGPObjectFactory factory = new PGPObjectFactory(keyBytes); Object obj = null; try { @@ -121,7 +119,7 @@ public class PgpConversionHelper { secKey = keyRing.getSecretKey(); } - return secKey; + return new UncachedSecretKey(secKey); } /** @@ -146,23 +144,4 @@ public class PgpConversionHelper { return signatures.get(0); } - /** - * Convert from ArrayList to byte[] - * - * @param keys - * @return - */ - public static byte[] PGPSecretKeyArrayListToBytes(ArrayList keys) { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - for (PGPSecretKey key : keys) { - try { - key.encode(os); - } catch (IOException e) { - Log.e(Constants.TAG, "Error while converting ArrayList to byte[]!", e); - } - } - - return os.toByteArray(); - } - } 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 1dfbfaf3a..d0ca77da7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -200,7 +200,7 @@ public class PgpKeyOperation { boolean canSign; String mainUserId = saveParcel.userIds.get(0); - PGPSecretKey masterKey = saveParcel.keys.get(0); + PGPSecretKey masterKey = saveParcel.keys.get(0).getSecretKeyExternal(); // this removes all userIds and certifications previously attached to the masterPublicKey PGPPublicKey masterPublicKey = masterKey.getPublicKey(); @@ -275,7 +275,7 @@ public class PgpKeyOperation { for (int i = 1; i < saveParcel.keys.size(); ++i) { updateProgress(40 + 40 * (i - 1) / (saveParcel.keys.size() - 1), 100); - PGPSecretKey subKey = saveParcel.keys.get(i); + PGPSecretKey subKey = saveParcel.keys.get(i).getSecretKeyExternal(); PGPPublicKey subPublicKey = subKey.getPublicKey(); PBESecretKeyDecryptor keyDecryptor2 = new JcePBESecretKeyDecryptorBuilder() @@ -377,8 +377,8 @@ public class PgpKeyOperation { */ if (saveParcel.deletedKeys != null) { - for (PGPSecretKey dKey : saveParcel.deletedKeys) { - mKR = PGPSecretKeyRing.removeSecretKey(mKR, dKey); + for (UncachedSecretKey dKey : saveParcel.deletedKeys) { + mKR = PGPSecretKeyRing.removeSecretKey(mKR, dKey.getSecretKeyExternal()); } } @@ -542,7 +542,7 @@ public class PgpKeyOperation { for (int i = 1; i < saveParcel.keys.size(); ++i) { updateProgress(40 + 50 * i / saveParcel.keys.size(), 100); if (saveParcel.moddedKeys[i]) { - PGPSecretKey subKey = saveParcel.keys.get(i); + PGPSecretKey subKey = saveParcel.keys.get(i).getSecretKeyExternal(); PGPPublicKey subPublicKey = subKey.getPublicKey(); PBESecretKeyDecryptor keyDecryptor2; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 1e0cfaa8e..8a247a11b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -412,7 +412,7 @@ public class OpenPgpService extends RemoteService { try { // try to find key, throws NotFoundException if not in db! - mProviderHelper.getPGPPublicKeyRing(masterKeyId); + mProviderHelper.getCachedPublicKeyRing(masterKeyId); Intent result = new Intent(); result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); 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 af6e66937..5365ed62c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -504,7 +504,7 @@ public class KeychainIntentService extends IntentService newPassphrase = oldPassphrase; } - long masterKeyId = saveParcel.keys.get(0).getKeyID(); + long masterKeyId = saveParcel.keys.get(0).getKeyId(); /* Operation */ ProviderHelper providerHelper = new ProviderHelper(this); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 3f0b37b75..60fdf895d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -20,9 +20,14 @@ package org.sufficientlysecure.keychain.service; import android.os.Parcel; import android.os.Parcelable; -import org.spongycastle.openpgp.PGPSecretKey; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; +import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; +import org.sufficientlysecure.keychain.util.IterableIterator; +import org.sufficientlysecure.keychain.util.Log; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; @@ -34,13 +39,13 @@ public class SaveKeyringParcel implements Parcelable { public boolean[] newIDs; public boolean primaryIDChanged; public boolean[] moddedKeys; - public ArrayList deletedKeys; + public ArrayList deletedKeys; public ArrayList keysExpiryDates; public ArrayList keysUsages; public String newPassphrase; public String oldPassphrase; public boolean[] newKeys; - public ArrayList keys; + public ArrayList keys; public String originalPrimaryID; public SaveKeyringParcel() {} @@ -75,17 +80,13 @@ public class SaveKeyringParcel implements Parcelable { destination.writeBooleanArray(newIDs); destination.writeByte((byte) (primaryIDChanged ? 1 : 0)); destination.writeBooleanArray(moddedKeys); - byte[] tmp = null; - if (deletedKeys.size() != 0) { - tmp = PgpConversionHelper.PGPSecretKeyArrayListToBytes(deletedKeys); - } - destination.writeByteArray(tmp); + destination.writeByteArray(encodeArrayList(deletedKeys)); destination.writeSerializable(keysExpiryDates); destination.writeList(keysUsages); destination.writeString(newPassphrase); destination.writeString(oldPassphrase); destination.writeBooleanArray(newKeys); - destination.writeByteArray(PgpConversionHelper.PGPSecretKeyArrayListToBytes(keys)); + destination.writeByteArray(encodeArrayList(keys)); destination.writeString(originalPrimaryID); } @@ -99,6 +100,22 @@ public class SaveKeyringParcel implements Parcelable { } }; + private static byte[] encodeArrayList(ArrayList list) { + if(list.isEmpty()) { + return null; + } + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + for(UncachedSecretKey key : new IterableIterator(list.iterator())) { + try { + key.encodeSecretKey(os); + } catch (IOException e) { + Log.e(Constants.TAG, "Error while converting ArrayList to byte[]!", e); + } + } + return os.toByteArray(); + } + @Override public int describeContents() { return 0; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index 30e8d9537..eb8ef003c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -43,7 +43,6 @@ import android.widget.TextView; import com.beardedhen.androidbootstrap.BootstrapButton; import com.devspark.appmsg.AppMsg; -import org.spongycastle.openpgp.PGPPublicKeyRing; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.Preferences; @@ -51,7 +50,6 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; -import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.PassphraseCacheService; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java index 4c747d0d9..529ea62a3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -44,16 +44,17 @@ import android.widget.Toast; import com.beardedhen.androidbootstrap.BootstrapButton; import com.devspark.appmsg.AppMsg; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.ActionBarHelper; import org.sufficientlysecure.keychain.helper.ExportHelper; +import org.sufficientlysecure.keychain.pgp.CachedSecretKey; +import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; @@ -66,7 +67,6 @@ import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener; import org.sufficientlysecure.keychain.ui.widget.KeyEditor; import org.sufficientlysecure.keychain.ui.widget.SectionView; import org.sufficientlysecure.keychain.ui.widget.UserIdEditor; -import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; import java.util.ArrayList; @@ -88,8 +88,6 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener // EDIT private Uri mDataUri; - private PGPSecretKeyRing mKeyRing = null; - private SectionView mUserIdsView; private SectionView mKeysView; @@ -105,7 +103,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener private CheckBox mNoPassphrase; Vector mUserIds; - Vector mKeys; + Vector mKeys; Vector mKeysUsages; boolean mMasterCanSign = true; @@ -158,7 +156,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener ); mUserIds = new Vector(); - mKeys = new Vector(); + mKeys = new Vector(); mKeysUsages = new Vector(); // Catch Intents opened from other apps @@ -239,7 +237,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener // get new key from data bundle returned from service Bundle data = message.getData(); - ArrayList newKeys = + ArrayList newKeys = PgpConversionHelper.BytesToPGPSecretKeyList(data .getByteArray(KeychainIntentService.RESULT_NEW_KEY)); @@ -287,18 +285,18 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener Log.d(Constants.TAG, "uri: " + mDataUri); try { - Uri secretUri = KeychainContract.KeyRingData.buildSecretKeyRingUri(mDataUri); - mKeyRing = (PGPSecretKeyRing) new ProviderHelper(this).getPGPKeyRing(secretUri); - - PGPSecretKey masterKey = mKeyRing.getSecretKey(); - mMasterCanSign = PgpKeyHelper.isCertificationKey(mKeyRing.getSecretKey()); - for (PGPSecretKey key : new IterableIterator(mKeyRing.getSecretKeys())) { - mKeys.add(key); - mKeysUsages.add(-1); // get usage when view is created + Uri secretUri = KeyRings.buildUnifiedKeyRingUri(mDataUri); + CachedSecretKeyRing keyRing = new ProviderHelper(this).getCachedSecretKeyRing(secretUri); + + mMasterCanSign = keyRing.getSubKey().canCertify(); + for (CachedSecretKey key : keyRing.iterator()) { + // Turn into uncached instance + mKeys.add(key.getUncached()); + mKeysUsages.add(key.getKeyUsage()); // get usage when view is created } boolean isSet = false; - for (String userId : new IterableIterator(masterKey.getUserIDs())) { + for (String userId : keyRing.getSubKey().getUserIds()) { Log.d(Constants.TAG, "Added userId " + userId); if (!isSet) { isSet = true; @@ -313,7 +311,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener buildLayout(false); mCurrentPassphrase = ""; - mIsPassphraseSet = PassphraseCacheService.hasPassphrase(mKeyRing); + mIsPassphraseSet = keyRing.hasPassphrase(); if (!mIsPassphraseSet) { // check "no passphrase" checkbox and remove button mNoPassphrase.setChecked(true); @@ -431,7 +429,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener if (mKeysView.getEditors().getChildCount() == 0) { return 0; } - return ((KeyEditor) mKeysView.getEditors().getChildAt(0)).getValue().getKeyID(); + return ((KeyEditor) mKeysView.getEditors().getChildAt(0)).getValue().getKeyId(); } public boolean isPassphraseSet() { @@ -571,7 +569,6 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener saveParams.keys = getKeys(mKeysView); saveParams.originalPrimaryID = mUserIdsView.getOriginalPrimaryID(); - // fill values for this action Bundle data = new Bundle(); data.putBoolean(KeychainIntentService.SAVE_KEYRING_CAN_SIGN, mMasterCanSign); @@ -590,7 +587,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener Intent data = new Intent(); // return uri pointing to new created key - Uri uri = KeychainContract.KeyRings.buildGenericKeyRingUri( + Uri uri = KeyRings.buildGenericKeyRingUri( String.valueOf(getMasterKeyId())); data.setData(uri); @@ -689,8 +686,8 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener * @param keysView * @return */ - private ArrayList getKeys(SectionView keysView) throws PgpGeneralException { - ArrayList keys = new ArrayList(); + private ArrayList getKeys(SectionView keysView) throws PgpGeneralException { + ArrayList keys = new ArrayList(); ViewGroup keyEditors = keysView.getEditors(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java index 1628c9e95..e1a603787 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java @@ -39,21 +39,18 @@ import android.widget.TextView; import com.beardedhen.androidbootstrap.BootstrapButton; import org.spongycastle.bcpg.sig.KeyFlags; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPSecretKey; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.util.Choice; +import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; import java.text.DateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; -import java.util.Vector; public class KeyEditor extends LinearLayout implements Editor, OnClickListener { - private PGPSecretKey mKey; + private UncachedSecretKey mKey; private EditorListener mEditorListener = null; @@ -208,7 +205,7 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener { } } - public void setValue(PGPSecretKey key, boolean isMasterKey, int usage, boolean isNewKey) { + public void setValue(UncachedSecretKey key, boolean isMasterKey, int usage, boolean isNewKey) { mKey = key; mIsMasterKey = isMasterKey; @@ -216,13 +213,12 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener { mDeleteButton.setVisibility(View.INVISIBLE); } - mAlgorithm.setText(PgpKeyHelper.getAlgorithmInfo(getContext(), key)); - String keyIdStr = PgpKeyHelper.convertKeyIdToHex(key.getKeyID()); + mAlgorithm.setText(PgpKeyHelper.getAlgorithmInfo(getContext(), key.getAlgorithm())); + String keyIdStr = PgpKeyHelper.convertKeyIdToHex(key.getKeyId()); mKeyId.setText(keyIdStr); - Vector choices = new Vector(); - boolean isElGamalKey = (key.getPublicKey().getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT); - boolean isDSAKey = (key.getPublicKey().getAlgorithm() == PGPPublicKey.DSA); + boolean isElGamalKey = (key.isElGamalEncrypt()); + boolean isDSAKey = (key.isDSA()); if (isElGamalKey) { mChkSign.setVisibility(View.INVISIBLE); TableLayout table = (TableLayout) findViewById(R.id.table_keylayout); @@ -254,32 +250,35 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener { ((usage & KeyFlags.ENCRYPT_STORAGE) == KeyFlags.ENCRYPT_STORAGE)); mChkAuthenticate.setChecked((usage & KeyFlags.AUTHENTICATION) == KeyFlags.AUTHENTICATION); } else { - mUsage = PgpKeyHelper.getKeyUsage(key); + mUsage = key.getKeyUsage(); mOriginalUsage = mUsage; if (key.isMasterKey()) { - mChkCertify.setChecked(PgpKeyHelper.isCertificationKey(key)); + mChkCertify.setChecked(key.canCertify()); } - mChkSign.setChecked(PgpKeyHelper.isSigningKey(key)); - mChkEncrypt.setChecked(PgpKeyHelper.isEncryptionKey(key)); - mChkAuthenticate.setChecked(PgpKeyHelper.isAuthenticationKey(key)); + mChkSign.setChecked(key.canSign()); + mChkEncrypt.setChecked(key.canEncrypt()); + mChkAuthenticate.setChecked(key.canAuthenticate()); } - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - cal.setTime(PgpKeyHelper.getCreationDate(key)); - setCreatedDate(cal); - cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - Date expiryDate = PgpKeyHelper.getExpiryDate(key); + { + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + cal.setTime(key.getCreationTime()); + setCreatedDate(cal); + } + + Date expiryDate = key.getExpiryTime(); if (expiryDate == null) { setExpiryDate(null); } else { - cal.setTime(PgpKeyHelper.getExpiryDate(key)); + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + cal.setTime(expiryDate); setExpiryDate(cal); mOriginalExpiryDate = cal; } } - public PGPSecretKey getValue() { + public UncachedSecretKey getValue() { return mKey; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java index a7719012a..35ebfcd58 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java @@ -36,9 +36,9 @@ import android.widget.TextView; import com.beardedhen.androidbootstrap.BootstrapButton; import org.spongycastle.openpgp.PGPKeyFlags; -import org.spongycastle.openpgp.PGPSecretKey; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; +import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.PassphraseCacheService; @@ -63,7 +63,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor private int mNewKeySize; private boolean mOldItemDeleted = false; private ArrayList mDeletedIDs = new ArrayList(); - private ArrayList mDeletedKeys = new ArrayList(); + private ArrayList mDeletedKeys = new ArrayList(); private boolean mCanBeEdited = true; private ActionBarActivity mActivity; @@ -227,7 +227,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor return mDeletedIDs; } - public ArrayList getDeletedKeys() { + public ArrayList getDeletedKeys() { return mDeletedKeys; } @@ -325,7 +325,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor this.updateEditorsVisible(); } - public void setKeys(Vector list, Vector usages, boolean newKeys) { + public void setKeys(Vector list, Vector usages, boolean newKeys) { if (mType != TYPE_KEY) { return; } @@ -358,9 +358,9 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor String passphrase; if (mEditors.getChildCount() > 0) { - PGPSecretKey masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue(); + UncachedSecretKey masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue(); passphrase = PassphraseCacheService - .getCachedPassphrase(mActivity, masterKey.getKeyID()); + .getCachedPassphrase(mActivity, masterKey.getKeyId()); isMasterKey = false; } else { passphrase = ""; @@ -395,7 +395,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { // get new key from data bundle returned from service Bundle data = message.getData(); - PGPSecretKey newKey = (PGPSecretKey) PgpConversionHelper + UncachedSecretKey newKey = PgpConversionHelper .BytesToPGPSecretKey(data .getByteArray(KeychainIntentService.RESULT_NEW_KEY)); addGeneratedKeyToView(newKey); @@ -413,7 +413,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor mActivity.startService(intent); } - private void addGeneratedKeyToView(PGPSecretKey newKey) { + private void addGeneratedKeyToView(UncachedSecretKey newKey) { // add view with new key KeyEditor view = (KeyEditor) mInflater.inflate(R.layout.edit_key_key_item, mEditors, false); -- cgit v1.2.3 From 90ac60b6db0637fbefbce5cb2cd80a64f5bb708d Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 4 May 2014 17:44:10 +0200 Subject: wrapped-key-ring: remove more unneeded methods --- .../keychain/pgp/PgpKeyHelper.java | 91 ---------------------- .../keychain/provider/ProviderHelper.java | 17 ---- .../keychain/ui/ViewKeyActivity.java | 8 +- 3 files changed, 4 insertions(+), 112 deletions(-) (limited to 'OpenKeychain') 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 77697b026..59a48e7eb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java @@ -57,11 +57,6 @@ public class PgpKeyHelper { return key.getCreationTime(); } - @Deprecated - public static Date getCreationDate(PGPSecretKey key) { - return key.getPublicKey().getCreationTime(); - } - @Deprecated public static Date getExpiryDate(PGPPublicKey key) { Date creationDate = getCreationDate(key); @@ -76,38 +71,6 @@ public class PgpKeyHelper { return calendar.getTime(); } - @Deprecated - public static Date getExpiryDate(PGPSecretKey key) { - return getExpiryDate(key.getPublicKey()); - } - - public static int getKeyUsage(PGPSecretKey key) { - return getKeyUsage(key.getPublicKey()); - } - - @SuppressWarnings("unchecked") - private static int getKeyUsage(PGPPublicKey key) { - int usage = 0; - if (key.getVersion() >= 4) { - for (PGPSignature sig : new IterableIterator(key.getSignatures())) { - if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) { - continue; - } - - PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets(); - if (hashed != null) { - usage |= hashed.getKeyFlags(); - } - - PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets(); - if (unhashed != null) { - usage |= unhashed.getKeyFlags(); - } - } - } - return usage; - } - @SuppressWarnings("unchecked") @Deprecated public static boolean isEncryptionKey(PGPPublicKey key) { @@ -150,10 +113,6 @@ public class PgpKeyHelper { return false; } - public static boolean isEncryptionKey(PGPSecretKey key) { - return isEncryptionKey(key.getPublicKey()); - } - @SuppressWarnings("unchecked") @Deprecated public static boolean isSigningKey(PGPPublicKey key) { @@ -186,11 +145,6 @@ public class PgpKeyHelper { return false; } - @Deprecated - public static boolean isSigningKey(PGPSecretKey key) { - return isSigningKey(key.getPublicKey()); - } - @SuppressWarnings("unchecked") @Deprecated public static boolean isCertificationKey(PGPPublicKey key) { @@ -218,51 +172,6 @@ public class PgpKeyHelper { return false; } - @Deprecated - public static boolean isAuthenticationKey(PGPSecretKey key) { - return isAuthenticationKey(key.getPublicKey()); - } - - @SuppressWarnings("unchecked") - @Deprecated - public static boolean isAuthenticationKey(PGPPublicKey key) { - if (key.getVersion() <= 3) { - return true; - } - - for (PGPSignature sig : new IterableIterator(key.getSignatures())) { - if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) { - continue; - } - PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets(); - - if (hashed != null && (hashed.getKeyFlags() & KeyFlags.AUTHENTICATION) != 0) { - return true; - } - - PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets(); - - if (unhashed != null && (unhashed.getKeyFlags() & KeyFlags.AUTHENTICATION) != 0) { - return true; - } - } - - return false; - } - - @Deprecated - public static boolean isCertificationKey(PGPSecretKey key) { - return isCertificationKey(key.getPublicKey()); - } - - public static String getAlgorithmInfo(Context context, PGPPublicKey key) { - return getAlgorithmInfo(context, key.getAlgorithm(), key.getBitStrength()); - } - - public static String getAlgorithmInfo(Context context, PGPSecretKey key) { - return getAlgorithmInfo(context, key.getPublicKey()); - } - /** * TODO: Only used in HkpKeyServer. Get rid of this one! */ 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 d1a003ec1..0784a0f33 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -263,23 +263,6 @@ public class ProviderHelper { } } - @Deprecated - public PGPSecretKeyRing getPGPSecretKeyRingWithKeyId(long keyId) - throws NotFoundException { - Uri uri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId)); - long masterKeyId = getMasterKeyId(uri); - return getPGPSecretKeyRing(masterKeyId); - } - - /** - * Retrieves the actual PGPPublicKeyRing object from the database blob based on the masterKeyId - */ - @Deprecated - public PGPPublicKeyRing getPGPPublicKeyRing(long masterKeyId) throws NotFoundException { - Uri queryUri = KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId)); - return (PGPPublicKeyRing) getPGPKeyRing(queryUri); - } - /** * Retrieves the actual PGPSecretKeyRing object from the database blob based on the maserKeyId */ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index e595c1889..79f409663 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -367,10 +367,10 @@ public class ViewKeyActivity extends ActionBarActivity { try { Uri blobUri = KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri); - mNfcKeyringBytes = mProviderHelper.getPGPKeyRing( - blobUri).getEncoded(); - } catch (IOException e) { - Log.e(Constants.TAG, "Error parsing keyring", e); + mNfcKeyringBytes = (byte[]) mProviderHelper.getGenericData( + blobUri, + KeychainContract.KeyRingData.KEY_RING_DATA, + ProviderHelper.FIELD_TYPE_BLOB); } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "key not found!", e); } -- cgit v1.2.3 From 761d87b661ef14023870ad7be107d33d69ab03e7 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 21 May 2014 21:07:32 +0200 Subject: wrapped-key-ring: split up CachedKeyRing and WrappedKeyRing --- .../keychain/pgp/CachedKeyRing.java | 68 -------- .../keychain/pgp/CachedPublicKey.java | 62 ------- .../keychain/pgp/CachedPublicKeyRing.java | 184 -------------------- .../keychain/pgp/CachedSecretKey.java | 189 --------------------- .../keychain/pgp/CachedSecretKeyRing.java | 128 -------------- .../sufficientlysecure/keychain/pgp/KeyRing.java | 25 +++ .../keychain/pgp/PgpDecryptVerify.java | 30 ++-- .../keychain/pgp/PgpImportExport.java | 5 +- .../keychain/pgp/PgpKeyHelper.java | 3 - .../keychain/pgp/PgpKeyOperation.java | 4 +- .../keychain/pgp/PgpSignEncrypt.java | 10 +- .../keychain/pgp/WrappedKeyRing.java | 81 +++++++++ .../keychain/pgp/WrappedPublicKey.java | 62 +++++++ .../keychain/pgp/WrappedPublicKeyRing.java | 179 +++++++++++++++++++ .../keychain/pgp/WrappedSecretKey.java | 189 +++++++++++++++++++++ .../keychain/pgp/WrappedSecretKeyRing.java | 123 ++++++++++++++ .../pgp/exception/PgpGeneralException.java | 3 + .../keychain/provider/CachedPublicKeyRing.java | 125 ++++++++++++++ .../keychain/provider/KeychainProvider.java | 2 +- .../keychain/provider/ProviderHelper.java | 63 +++---- .../keychain/remote/OpenPgpService.java | 2 +- .../keychain/service/KeychainIntentService.java | 24 +-- .../keychain/service/PassphraseCacheService.java | 6 +- .../keychain/ui/EditKeyActivity.java | 9 +- .../keychain/ui/EncryptAsymmetricFragment.java | 6 +- .../keychain/ui/ViewCertActivity.java | 6 +- .../ui/dialog/PassphraseDialogFragment.java | 27 +-- 27 files changed, 887 insertions(+), 728 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKey.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKeyRing.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKey.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java deleted file mode 100644 index def673469..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedKeyRing.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.sufficientlysecure.keychain.pgp; - -public abstract class CachedKeyRing { - - private final long mMasterKeyId; - private final String mUserId; - private final boolean mHasAnySecret; - private final boolean mIsRevoked; - private final boolean mCanCertify; - private final long mHasEncryptId; - private final long mHasSignId; - private final int mVerified; - - protected CachedKeyRing(long masterKeyId, String userId, boolean hasAnySecret, - boolean isRevoked, boolean canCertify, long hasEncryptId, long hasSignId, - int verified) - { - mMasterKeyId = masterKeyId; - mUserId = userId; - mHasAnySecret = hasAnySecret; - mIsRevoked = isRevoked; - mCanCertify = canCertify; - mHasEncryptId = hasEncryptId; - mHasSignId = hasSignId; - mVerified = verified; - } - - public long getMasterKeyId() { - return mMasterKeyId; - } - - public String getPrimaryUserId() { - return mUserId; - } - - public boolean hasAnySecret() { - return mHasAnySecret; - } - - public boolean isRevoked() { - return mIsRevoked; - } - - public boolean canCertify() { - return mCanCertify; - } - - public long getEncryptId() { - return mHasEncryptId; - } - - public boolean hasEncrypt() { - return mHasEncryptId != 0; - } - - public long getSignId() { - return mHasSignId; - } - - public boolean hasSign() { - return mHasSignId != 0; - } - - public int getVerified() { - return mVerified; - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java deleted file mode 100644 index dee03db6f..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.sufficientlysecure.keychain.pgp; - -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPOnePassSignature; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPSignature; -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; - -public class CachedPublicKey extends UncachedPublicKey { - - // this is the parent key ring - final CachedKeyRing mRing; - - CachedPublicKey(CachedKeyRing ring, PGPPublicKey key) { - super(key); - mRing = ring; - } - - public IterableIterator getUserIds() { - return new IterableIterator(mPublicKey.getUserIDs()); - } - - public CachedKeyRing getKeyRing() { - return mRing; - } - - JcePublicKeyKeyEncryptionMethodGenerator getPubKeyEncryptionGenerator() { - 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); - } - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java deleted file mode 100644 index 108ed1a4a..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKeyRing.java +++ /dev/null @@ -1,184 +0,0 @@ -package org.sufficientlysecure.keychain.pgp; - -import org.spongycastle.bcpg.ArmoredOutputStream; -import org.spongycastle.bcpg.SignatureSubpacketTags; -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSignature; -import org.spongycastle.openpgp.PGPSignatureList; -import org.spongycastle.openpgp.PGPSignatureSubpacketVector; -import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.util.IterableIterator; - -import java.io.IOException; -import java.security.SignatureException; -import java.util.Arrays; -import java.util.Iterator; - -public class CachedPublicKeyRing extends CachedKeyRing { - - private PGPPublicKeyRing mRing; - private final byte[] mPubKey; - - public CachedPublicKeyRing(long masterKeyId, String userId, boolean hasAnySecret, - boolean isRevoked, boolean canCertify, long hasEncryptId, long hasSignId, - int verified, byte[] blob) - { - super(masterKeyId, userId, hasAnySecret, isRevoked, canCertify, - hasEncryptId, hasSignId, verified); - - mPubKey = blob; - } - - PGPPublicKeyRing getRing() { - if(mRing == null) { - mRing = (PGPPublicKeyRing) PgpConversionHelper.BytesToPGPKeyRing(mPubKey); - } - return mRing; - } - - public void encode(ArmoredOutputStream stream) throws IOException { - getRing().encode(stream); - } - - public CachedPublicKey getSubkey() { - return new CachedPublicKey(this, getRing().getPublicKey()); - } - - public CachedPublicKey getSubkey(long id) { - return new CachedPublicKey(this, getRing().getPublicKey(id)); - } - - /** Getter that returns the subkey that should be used for signing. */ - CachedPublicKey getEncryptionSubKey() throws PgpGeneralException { - PGPPublicKey key = getRing().getPublicKey(getEncryptId()); - if(key != null) { - CachedPublicKey cKey = new CachedPublicKey(this, key); - if(!cKey.canEncrypt()) { - throw new PgpGeneralException("key error"); - } - return cKey; - } - // TODO handle with proper exception - throw new PgpGeneralException("no encryption key available"); - } - - public boolean verifySubkeyBinding(CachedPublicKey cachedSubkey) { - boolean validSubkeyBinding = false; - boolean validTempSubkeyBinding = false; - boolean validPrimaryKeyBinding = false; - - PGPPublicKey masterKey = getRing().getPublicKey(); - PGPPublicKey subKey = cachedSubkey.getPublicKey(); - - // Is this the master key? Match automatically, then. - if(Arrays.equals(masterKey.getFingerprint(), subKey.getFingerprint())) { - return true; - } - - JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = - new JcaPGPContentVerifierBuilderProvider() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - - Iterator itr = subKey.getSignatures(); - - while (itr.hasNext()) { //what does gpg do if the subkey binding is wrong? - //gpg has an invalid subkey binding error on key import I think, but doesn't shout - //about keys without subkey signing. Can't get it to import a slightly broken one - //either, so we will err on bad subkey binding here. - PGPSignature sig = itr.next(); - if (sig.getKeyID() == masterKey.getKeyID() && - sig.getSignatureType() == PGPSignature.SUBKEY_BINDING) { - //check and if ok, check primary key binding. - try { - sig.init(contentVerifierBuilderProvider, masterKey); - validTempSubkeyBinding = sig.verifyCertification(masterKey, subKey); - } catch (PGPException e) { - continue; - } catch (SignatureException e) { - continue; - } - - if (validTempSubkeyBinding) { - validSubkeyBinding = true; - } - if (validTempSubkeyBinding) { - validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getUnhashedSubPackets(), - masterKey, subKey); - if (validPrimaryKeyBinding) { - break; - } - validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getHashedSubPackets(), - masterKey, subKey); - if (validPrimaryKeyBinding) { - break; - } - } - } - } - return validSubkeyBinding && validPrimaryKeyBinding; - - } - - static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector pkts, - PGPPublicKey masterPublicKey, - PGPPublicKey signingPublicKey) { - boolean validPrimaryKeyBinding = false; - JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = - new JcaPGPContentVerifierBuilderProvider() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - PGPSignatureList eSigList; - - if (pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) { - try { - eSigList = pkts.getEmbeddedSignatures(); - } catch (IOException e) { - return false; - } catch (PGPException e) { - return false; - } - for (int j = 0; j < eSigList.size(); ++j) { - PGPSignature emSig = eSigList.get(j); - if (emSig.getSignatureType() == PGPSignature.PRIMARYKEY_BINDING) { - try { - emSig.init(contentVerifierBuilderProvider, signingPublicKey); - validPrimaryKeyBinding = emSig.verifyCertification(masterPublicKey, signingPublicKey); - if (validPrimaryKeyBinding) { - break; - } - } catch (PGPException e) { - continue; - } catch (SignatureException e) { - continue; - } - } - } - } - - return validPrimaryKeyBinding; - } - - public IterableIterator iterator() { - final Iterator it = getRing().getPublicKeys(); - return new IterableIterator(new Iterator() { - @Override - public boolean hasNext() { - return it.hasNext(); - } - - @Override - public CachedPublicKey next() { - return new CachedPublicKey(CachedPublicKeyRing.this, it.next()); - } - - @Override - public void remove() { - it.remove(); - } - }); - } - -} \ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java deleted file mode 100644 index 8e45ceb4f..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java +++ /dev/null @@ -1,189 +0,0 @@ -package org.sufficientlysecure.keychain.pgp; - -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPPrivateKey; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKey; -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.PGPV3SignatureGenerator; -import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; -import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory; -import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; -import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; -import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; -import org.sufficientlysecure.keychain.util.IterableIterator; - -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.SignatureException; -import java.util.List; - -public class CachedSecretKey extends CachedPublicKey { - - private final PGPSecretKey mSecretKey; - private PGPPrivateKey mPrivateKey = null; - - CachedSecretKey(CachedSecretKeyRing ring, PGPSecretKey key) { - super(ring, key.getPublicKey()); - mSecretKey = key; - } - - public CachedSecretKeyRing getRing() { - return (CachedSecretKeyRing) mRing; - } - - /** Returns the wrapped PGPSecretKeyRing. - * This function is for compatibility only, should not be used anymore and will be removed - */ - @Deprecated - public PGPSecretKey getKeyExternal() { - return mSecretKey; - } - - public boolean unlock(String passphrase) throws PgpGeneralException { - try { - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( - Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); - mPrivateKey = mSecretKey.extractPrivateKey(keyDecryptor); - } catch (PGPException e) { - return false; - } - if(mPrivateKey == null) { - throw new PgpGeneralException("error extracting key"); - } - return true; - } - - public PGPSignatureGenerator getSignatureGenerator(int hashAlgo, boolean cleartext) - throws PgpGeneralException { - if(mPrivateKey == null) { - throw new PrivateKeyNotUnlockedException(); - } - - // content signer based on signing key algorithm and chosen hash algorithm - JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( - mSecretKey.getPublicKey().getAlgorithm(), hashAlgo) - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - - int signatureType; - if (cleartext) { - // for sign-only ascii text - signatureType = PGPSignature.CANONICAL_TEXT_DOCUMENT; - } else { - signatureType = PGPSignature.BINARY_DOCUMENT; - } - - try { - PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder); - signatureGenerator.init(signatureType, mPrivateKey); - - PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); - spGen.setSignerUserID(false, mRing.getPrimaryUserId()); - signatureGenerator.setHashedSubpackets(spGen.generate()); - return signatureGenerator; - } catch(PGPException e) { - throw new PgpGeneralException("Error initializing signature!", e); - } - } - - public PGPV3SignatureGenerator getV3SignatureGenerator(int hashAlgo, boolean cleartext) - throws PgpGeneralException { - if(mPrivateKey == null) { - throw new PrivateKeyNotUnlockedException(); - } - - // content signer based on signing key algorithm and chosen hash algorithm - JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( - mSecretKey.getPublicKey().getAlgorithm(), hashAlgo) - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - - int signatureType; - if (cleartext) { - // for sign-only ascii text - signatureType = PGPSignature.CANONICAL_TEXT_DOCUMENT; - } else { - signatureType = PGPSignature.BINARY_DOCUMENT; - } - - try { - PGPV3SignatureGenerator signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder); - signatureV3Generator.init(signatureType, mPrivateKey); - return signatureV3Generator; - } catch(PGPException e) { - throw new PgpGeneralException("Error initializing signature!", e); - } - } - - public PublicKeyDataDecryptorFactory getDecryptorFactory() { - if(mPrivateKey == null) { - throw new PrivateKeyNotUnlockedException(); - } - return new JcePublicKeyDataDecryptorFactoryBuilder() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(mPrivateKey); - } - - /** - * Certify the given pubkeyid with the given masterkeyid. - * - * @param publicKeyRing Keyring to add certification to. - * @param userIds User IDs to certify, must not be null or empty - * @return A keyring with added certifications - */ - public UncachedKeyRing certifyUserIds(CachedPublicKeyRing publicKeyRing, List userIds) - throws PgpGeneralMsgIdException, NoSuchAlgorithmException, NoSuchProviderException, - PGPException, SignatureException { - - if(mPrivateKey == null) { - throw new PrivateKeyNotUnlockedException(); - } - - // create a signatureGenerator from the supplied masterKeyId and passphrase - PGPSignatureGenerator signatureGenerator; - { - // TODO: SHA256 fixed? - JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( - mSecretKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256) - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - - signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder); - signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, mPrivateKey); - } - - { // supply signatureGenerator with a SubpacketVector - PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); - PGPSignatureSubpacketVector packetVector = spGen.generate(); - signatureGenerator.setHashedSubpackets(packetVector); - } - - // get the master subkey (which we certify for) - PGPPublicKey publicKey = publicKeyRing.getSubkey().getPublicKey(); - - // fetch public key ring, add the certification and return it - for (String userId : new IterableIterator(userIds.iterator())) { - PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey); - publicKey = PGPPublicKey.addCertification(publicKey, userId, sig); - } - - PGPPublicKeyRing ring = PGPPublicKeyRing.insertPublicKey(publicKeyRing.getRing(), publicKey); - - return new UncachedKeyRing(ring); - } - - static class PrivateKeyNotUnlockedException extends RuntimeException { - // this exception is a programming error which happens when an operation which requires - // 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/CachedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java deleted file mode 100644 index 398092aeb..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.sufficientlysecure.keychain.pgp; - -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPPrivateKey; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -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.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.util.IterableIterator; - -import java.io.IOException; -import java.security.NoSuchProviderException; -import java.util.Iterator; - -public class CachedSecretKeyRing extends CachedKeyRing { - - private PGPSecretKeyRing mRing; - - public CachedSecretKeyRing(long masterKeyId, String userId, boolean hasAnySecret, - boolean isRevoked, boolean canCertify, long hasEncryptId, long hasSignId, - int verified, byte[] blob) - { - super(masterKeyId, userId, hasAnySecret, - isRevoked, canCertify, hasEncryptId, hasSignId, - verified); - - mRing = (PGPSecretKeyRing) PgpConversionHelper.BytesToPGPKeyRing(blob); - } - - PGPSecretKeyRing getRing() { - return mRing; - } - - public CachedSecretKey getSubKey() { - return new CachedSecretKey(this, mRing.getSecretKey()); - } - - public CachedSecretKey getSubKey(long id) { - return new CachedSecretKey(this, mRing.getSecretKey(id)); - } - - /** Getter that returns the subkey that should be used for signing. */ - CachedSecretKey getSigningSubKey() throws PgpGeneralException { - PGPSecretKey key = mRing.getSecretKey(getSignId()); - if(key != null) { - CachedSecretKey cKey = new CachedSecretKey(this, key); - if(!cKey.canSign()) { - throw new PgpGeneralException("key error"); - } - return cKey; - } - // TODO handle with proper exception - throw new PgpGeneralException("no signing key available"); - } - - public boolean hasPassphrase() { - PGPSecretKey secretKey = null; - boolean foundValidKey = false; - for (Iterator keys = mRing.getSecretKeys(); keys.hasNext(); ) { - secretKey = (PGPSecretKey) keys.next(); - if (!secretKey.isPrivateKeyEmpty()) { - foundValidKey = true; - break; - } - } - if(!foundValidKey) { - return false; - } - - try { - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() - .setProvider("SC").build("".toCharArray()); - PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor); - return testKey == null; - } catch(PGPException e) { - // this means the crc check failed -> passphrase required - return true; - } - } - - 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); - - } - - public IterableIterator iterator() { - final Iterator it = mRing.getSecretKeys(); - return new IterableIterator(new Iterator() { - @Override - public boolean hasNext() { - return it.hasNext(); - } - - @Override - public CachedSecretKey next() { - return new CachedSecretKey(CachedSecretKeyRing.this, it.next()); - } - - @Override - public void remove() { - it.remove(); - } - }); - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java new file mode 100644 index 000000000..cfbad89b7 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java @@ -0,0 +1,25 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; + +public abstract class KeyRing { + + abstract public long getMasterKeyId() throws PgpGeneralException; + + abstract public String getPrimaryUserId() throws PgpGeneralException; + + abstract public boolean isRevoked() throws PgpGeneralException; + + abstract public boolean canCertify() throws PgpGeneralException; + + abstract public long getEncryptId() throws PgpGeneralException; + + abstract public boolean hasEncrypt() throws PgpGeneralException; + + abstract public long getSignId() throws PgpGeneralException; + + abstract public boolean hasSign() throws PgpGeneralException; + + abstract public int getVerified() throws PgpGeneralException; + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 27e9e8ebd..21a7c20e3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -233,7 +233,7 @@ public class PgpDecryptVerify { PGPPublicKeyEncryptedData encryptedDataAsymmetric = null; PGPPBEEncryptedData encryptedDataSymmetric = null; - CachedSecretKey secretEncryptionKey = null; + WrappedSecretKey secretEncryptionKey = null; Iterator it = enc.getEncryptedDataObjects(); boolean asymmetricPacketFound = false; boolean symmetricPacketFound = false; @@ -245,10 +245,10 @@ public class PgpDecryptVerify { PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj; - CachedSecretKeyRing secretKeyRing; + WrappedSecretKeyRing secretKeyRing; try { // get actual keyring object based on master key id - secretKeyRing = mProviderHelper.getCachedSecretKeyRing( + secretKeyRing = mProviderHelper.getWrappedSecretKeyRing( KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( Long.toString(encData.getKeyID())) ); @@ -368,8 +368,8 @@ public class PgpDecryptVerify { Object dataChunk = plainFact.nextObject(); OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); int signatureIndex = -1; - CachedPublicKeyRing signingRing = null; - CachedPublicKey signingKey = null; + WrappedPublicKeyRing signingRing = null; + WrappedPublicKey signingKey = null; if (dataChunk instanceof PGPCompressedData) { updateProgress(R.string.progress_decompressing_data, currentProgress, 100); @@ -393,7 +393,7 @@ public class PgpDecryptVerify { for (int i = 0; i < sigList.size(); ++i) { try { long sigKeyId = sigList.get(i).getKeyID(); - signingRing = mProviderHelper.getCachedPublicKeyRing( + signingRing = mProviderHelper.getWrappedPublicKeyRing( KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( Long.toString(sigKeyId) ) @@ -413,7 +413,11 @@ public class PgpDecryptVerify { signatureResultBuilder.signatureAvailable(true); signatureResultBuilder.knownKey(true); signatureResultBuilder.keyId(signingRing.getMasterKeyId()); - signatureResultBuilder.userId(signingRing.getPrimaryUserId()); + try { + signatureResultBuilder.userId(signingRing.getPrimaryUserId()); + } catch(PgpGeneralException e) { + Log.d(Constants.TAG, "No primary user id in key " + signingRing.getMasterKeyId()); + } signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0); signingKey.initSignature(signature); @@ -567,8 +571,8 @@ public class PgpDecryptVerify { throw new InvalidDataException(); } - CachedPublicKeyRing signingRing = null; - CachedPublicKey signingKey = null; + WrappedPublicKeyRing signingRing = null; + WrappedPublicKey signingKey = null; int signatureIndex = -1; // go through all signatures @@ -576,7 +580,7 @@ public class PgpDecryptVerify { for (int i = 0; i < sigList.size(); ++i) { try { long sigKeyId = sigList.get(i).getKeyID(); - signingRing = mProviderHelper.getCachedPublicKeyRing( + signingRing = mProviderHelper.getWrappedPublicKeyRing( KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( Long.toString(sigKeyId) ) @@ -598,7 +602,11 @@ public class PgpDecryptVerify { signatureResultBuilder.signatureAvailable(true); signatureResultBuilder.knownKey(true); signatureResultBuilder.keyId(signingRing.getMasterKeyId()); - signatureResultBuilder.userId(signingRing.getPrimaryUserId()); + try { + signatureResultBuilder.userId(signingRing.getPrimaryUserId()); + } catch(PgpGeneralException e) { + Log.d(Constants.TAG, "No primary user id in key " + signingRing.getMasterKeyId()); + } signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0); signingKey.initSignature(signature); 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 a0d2d5cea..5c4604647 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java @@ -27,7 +27,6 @@ import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; import org.sufficientlysecure.keychain.Constants; @@ -101,7 +100,7 @@ public class PgpImportExport { } } - public boolean uploadKeyRingToServer(HkpKeyServer server, CachedPublicKeyRing keyring) { + public boolean uploadKeyRingToServer(HkpKeyServer server, WrappedPublicKeyRing keyring) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ArmoredOutputStream aos = null; try { @@ -229,7 +228,7 @@ public class PgpImportExport { updateProgress(progress * 100 / masterKeyIdsSize, 100); try { - CachedPublicKeyRing ring = mProviderHelper.getCachedPublicKeyRing( + WrappedPublicKeyRing ring = mProviderHelper.getWrappedPublicKeyRing( KeychainContract.KeyRings.buildGenericKeyRingUri(pubKeyMasterId) ); 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 59a48e7eb..b25c38f1a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java @@ -72,7 +72,6 @@ public class PgpKeyHelper { } @SuppressWarnings("unchecked") - @Deprecated public static boolean isEncryptionKey(PGPPublicKey key) { if (!key.isEncryptionKey()) { return false; @@ -114,7 +113,6 @@ public class PgpKeyHelper { } @SuppressWarnings("unchecked") - @Deprecated public static boolean isSigningKey(PGPPublicKey key) { if (key.getVersion() <= 3) { return true; @@ -146,7 +144,6 @@ public class PgpKeyHelper { } @SuppressWarnings("unchecked") - @Deprecated public static boolean isCertificationKey(PGPPublicKey key) { if (key.getVersion() <= 3) { return true; 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 d0ca77da7..b9634c34a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -337,8 +337,8 @@ public class PgpKeyOperation { } - public UncachedKeyRing buildSecretKey(CachedSecretKeyRing wmKR, - CachedPublicKeyRing wpKR, + public UncachedKeyRing buildSecretKey(WrappedSecretKeyRing wmKR, + WrappedPublicKeyRing wpKR, SaveKeyringParcel saveParcel) throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java index 96ee3f10a..24d090d04 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -266,11 +266,11 @@ public class PgpSignEncrypt { } /* Get keys for signature generation for later usage */ - CachedSecretKey signingKey = null; + WrappedSecretKey signingKey = null; if (enableSignature) { - CachedSecretKeyRing signingKeyRing; + WrappedSecretKeyRing signingKeyRing; try { - signingKeyRing = mProviderHelper.getCachedSecretKeyRing(mSignatureMasterKeyId); + signingKeyRing = mProviderHelper.getWrappedSecretKeyRing(mSignatureMasterKeyId); } catch (ProviderHelper.NotFoundException e) { throw new NoSigningKeyException(); } @@ -316,9 +316,9 @@ public class PgpSignEncrypt { // Asymmetric encryption for (long id : mEncryptionMasterKeyIds) { try { - CachedPublicKeyRing keyRing = mProviderHelper.getCachedPublicKeyRing( + WrappedPublicKeyRing keyRing = mProviderHelper.getWrappedPublicKeyRing( KeyRings.buildUnifiedKeyRingUri(Long.toString(id))); - CachedPublicKey key = keyRing.getEncryptionSubKey(); + WrappedPublicKey key = keyRing.getEncryptionSubKey(); cPk.addMethod(key.getPubKeyEncryptionGenerator()); } catch (PgpGeneralException e) { Log.e(Constants.TAG, "key not found!", e); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java new file mode 100644 index 000000000..94eb91420 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java @@ -0,0 +1,81 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.openpgp.PGPKeyRing; +import org.spongycastle.openpgp.PGPPublicKey; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.util.IterableIterator; + +public abstract class WrappedKeyRing extends KeyRing { + + private final boolean mHasAnySecret; + private final int mVerified; + + WrappedKeyRing(boolean hasAnySecret, int verified) { + mHasAnySecret = hasAnySecret; + mVerified = verified; + } + + public long getMasterKeyId() { + return getRing().getPublicKey().getKeyID(); + } + + public boolean hasAnySecret() { + return mHasAnySecret; + } + + public int getVerified() { + return mVerified; + } + + public String getPrimaryUserId() throws PgpGeneralException { + return (String) getRing().getPublicKey().getUserIDs().next(); + }; + + public boolean isRevoked() throws PgpGeneralException { + // Is the master key revoked? + return getRing().getPublicKey().isRevoked(); + } + + public boolean canCertify() throws PgpGeneralException { + return getRing().getPublicKey().isEncryptionKey(); + } + + public long getEncryptId() throws PgpGeneralException { + for(PGPPublicKey key : new IterableIterator(getRing().getPublicKeys())) { + if(PgpKeyHelper.isEncryptionKey(key)) { + return key.getKeyID(); + } + } + throw new PgpGeneralException("No valid encryption key found!"); + } + + public boolean hasEncrypt() throws PgpGeneralException { + try { + getEncryptId(); + return true; + } catch(PgpGeneralException e) { + return false; + } + } + + public long getSignId() throws PgpGeneralException { + for(PGPPublicKey key : new IterableIterator(getRing().getPublicKeys())) { + if(PgpKeyHelper.isSigningKey(key)) { + return key.getKeyID(); + } + } + throw new PgpGeneralException("No valid signing key found!"); + } + + public boolean hasSign() throws PgpGeneralException { + try { + getSignId(); + return true; + } catch (PgpGeneralException e) { + return false; + } + } + + abstract PGPKeyRing getRing(); + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKey.java new file mode 100644 index 000000000..72352a451 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKey.java @@ -0,0 +1,62 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPOnePassSignature; +import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.openpgp.PGPSignature; +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; + +public class WrappedPublicKey extends UncachedPublicKey { + + // this is the parent key ring + final KeyRing mRing; + + WrappedPublicKey(KeyRing ring, PGPPublicKey key) { + super(key); + mRing = ring; + } + + public IterableIterator getUserIds() { + return new IterableIterator(mPublicKey.getUserIDs()); + } + + public KeyRing getKeyRing() { + return mRing; + } + + JcePublicKeyKeyEncryptionMethodGenerator getPubKeyEncryptionGenerator() { + 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); + } + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKeyRing.java new file mode 100644 index 000000000..624382165 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKeyRing.java @@ -0,0 +1,179 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.bcpg.ArmoredOutputStream; +import org.spongycastle.bcpg.SignatureSubpacketTags; +import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.openpgp.PGPPublicKeyRing; +import org.spongycastle.openpgp.PGPSignature; +import org.spongycastle.openpgp.PGPSignatureList; +import org.spongycastle.openpgp.PGPSignatureSubpacketVector; +import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.util.IterableIterator; + +import java.io.IOException; +import java.security.SignatureException; +import java.util.Arrays; +import java.util.Iterator; + +public class WrappedPublicKeyRing extends WrappedKeyRing { + + private PGPPublicKeyRing mRing; + private final byte[] mPubKey; + + public WrappedPublicKeyRing(byte[] blob, boolean hasAnySecret, int verified) { + super(hasAnySecret, verified); + mPubKey = blob; + } + + PGPPublicKeyRing getRing() { + if(mRing == null) { + mRing = (PGPPublicKeyRing) PgpConversionHelper.BytesToPGPKeyRing(mPubKey); + } + return mRing; + } + + public void encode(ArmoredOutputStream stream) throws IOException { + getRing().encode(stream); + } + + public WrappedPublicKey getSubkey() { + return new WrappedPublicKey(this, getRing().getPublicKey()); + } + + public WrappedPublicKey getSubkey(long id) { + return new WrappedPublicKey(this, getRing().getPublicKey(id)); + } + + /** Getter that returns the subkey that should be used for signing. */ + WrappedPublicKey getEncryptionSubKey() throws PgpGeneralException { + PGPPublicKey key = getRing().getPublicKey(getEncryptId()); + if(key != null) { + WrappedPublicKey cKey = new WrappedPublicKey(this, key); + if(!cKey.canEncrypt()) { + throw new PgpGeneralException("key error"); + } + return cKey; + } + // TODO handle with proper exception + throw new PgpGeneralException("no encryption key available"); + } + + public boolean verifySubkeyBinding(WrappedPublicKey cachedSubkey) { + boolean validSubkeyBinding = false; + boolean validTempSubkeyBinding = false; + boolean validPrimaryKeyBinding = false; + + PGPPublicKey masterKey = getRing().getPublicKey(); + PGPPublicKey subKey = cachedSubkey.getPublicKey(); + + // Is this the master key? Match automatically, then. + if(Arrays.equals(masterKey.getFingerprint(), subKey.getFingerprint())) { + return true; + } + + JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = + new JcaPGPContentVerifierBuilderProvider() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + + Iterator itr = subKey.getSignatures(); + + while (itr.hasNext()) { //what does gpg do if the subkey binding is wrong? + //gpg has an invalid subkey binding error on key import I think, but doesn't shout + //about keys without subkey signing. Can't get it to import a slightly broken one + //either, so we will err on bad subkey binding here. + PGPSignature sig = itr.next(); + if (sig.getKeyID() == masterKey.getKeyID() && + sig.getSignatureType() == PGPSignature.SUBKEY_BINDING) { + //check and if ok, check primary key binding. + try { + sig.init(contentVerifierBuilderProvider, masterKey); + validTempSubkeyBinding = sig.verifyCertification(masterKey, subKey); + } catch (PGPException e) { + continue; + } catch (SignatureException e) { + continue; + } + + if (validTempSubkeyBinding) { + validSubkeyBinding = true; + } + if (validTempSubkeyBinding) { + validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getUnhashedSubPackets(), + masterKey, subKey); + if (validPrimaryKeyBinding) { + break; + } + validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getHashedSubPackets(), + masterKey, subKey); + if (validPrimaryKeyBinding) { + break; + } + } + } + } + return validSubkeyBinding && validPrimaryKeyBinding; + + } + + static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector pkts, + PGPPublicKey masterPublicKey, + PGPPublicKey signingPublicKey) { + boolean validPrimaryKeyBinding = false; + JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = + new JcaPGPContentVerifierBuilderProvider() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + PGPSignatureList eSigList; + + if (pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) { + try { + eSigList = pkts.getEmbeddedSignatures(); + } catch (IOException e) { + return false; + } catch (PGPException e) { + return false; + } + for (int j = 0; j < eSigList.size(); ++j) { + PGPSignature emSig = eSigList.get(j); + if (emSig.getSignatureType() == PGPSignature.PRIMARYKEY_BINDING) { + try { + emSig.init(contentVerifierBuilderProvider, signingPublicKey); + validPrimaryKeyBinding = emSig.verifyCertification(masterPublicKey, signingPublicKey); + if (validPrimaryKeyBinding) { + break; + } + } catch (PGPException e) { + continue; + } catch (SignatureException e) { + continue; + } + } + } + } + + return validPrimaryKeyBinding; + } + + public IterableIterator iterator() { + final Iterator it = getRing().getPublicKeys(); + return new IterableIterator(new Iterator() { + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public WrappedPublicKey next() { + return new WrappedPublicKey(WrappedPublicKeyRing.this, it.next()); + } + + @Override + public void remove() { + it.remove(); + } + }); + } + +} \ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKey.java new file mode 100644 index 000000000..a03e10098 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKey.java @@ -0,0 +1,189 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPPrivateKey; +import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.openpgp.PGPPublicKeyRing; +import org.spongycastle.openpgp.PGPSecretKey; +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.PGPV3SignatureGenerator; +import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; +import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory; +import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; +import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; +import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; +import org.sufficientlysecure.keychain.util.IterableIterator; + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SignatureException; +import java.util.List; + +public class WrappedSecretKey extends WrappedPublicKey { + + private final PGPSecretKey mSecretKey; + private PGPPrivateKey mPrivateKey = null; + + WrappedSecretKey(WrappedSecretKeyRing ring, PGPSecretKey key) { + super(ring, key.getPublicKey()); + mSecretKey = key; + } + + public WrappedSecretKeyRing getRing() { + return (WrappedSecretKeyRing) mRing; + } + + /** Returns the wrapped PGPSecretKeyRing. + * This function is for compatibility only, should not be used anymore and will be removed + */ + @Deprecated + public PGPSecretKey getKeyExternal() { + return mSecretKey; + } + + public boolean unlock(String passphrase) throws PgpGeneralException { + try { + PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( + Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); + mPrivateKey = mSecretKey.extractPrivateKey(keyDecryptor); + } catch (PGPException e) { + return false; + } + if(mPrivateKey == null) { + throw new PgpGeneralException("error extracting key"); + } + return true; + } + + public PGPSignatureGenerator getSignatureGenerator(int hashAlgo, boolean cleartext) + throws PgpGeneralException { + if(mPrivateKey == null) { + throw new PrivateKeyNotUnlockedException(); + } + + // content signer based on signing key algorithm and chosen hash algorithm + JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( + mSecretKey.getPublicKey().getAlgorithm(), hashAlgo) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + + int signatureType; + if (cleartext) { + // for sign-only ascii text + signatureType = PGPSignature.CANONICAL_TEXT_DOCUMENT; + } else { + signatureType = PGPSignature.BINARY_DOCUMENT; + } + + try { + PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder); + signatureGenerator.init(signatureType, mPrivateKey); + + PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); + spGen.setSignerUserID(false, mRing.getPrimaryUserId()); + signatureGenerator.setHashedSubpackets(spGen.generate()); + return signatureGenerator; + } catch(PGPException e) { + throw new PgpGeneralException("Error initializing signature!", e); + } + } + + public PGPV3SignatureGenerator getV3SignatureGenerator(int hashAlgo, boolean cleartext) + throws PgpGeneralException { + if(mPrivateKey == null) { + throw new PrivateKeyNotUnlockedException(); + } + + // content signer based on signing key algorithm and chosen hash algorithm + JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( + mSecretKey.getPublicKey().getAlgorithm(), hashAlgo) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + + int signatureType; + if (cleartext) { + // for sign-only ascii text + signatureType = PGPSignature.CANONICAL_TEXT_DOCUMENT; + } else { + signatureType = PGPSignature.BINARY_DOCUMENT; + } + + try { + PGPV3SignatureGenerator signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder); + signatureV3Generator.init(signatureType, mPrivateKey); + return signatureV3Generator; + } catch(PGPException e) { + throw new PgpGeneralException("Error initializing signature!", e); + } + } + + public PublicKeyDataDecryptorFactory getDecryptorFactory() { + if(mPrivateKey == null) { + throw new PrivateKeyNotUnlockedException(); + } + return new JcePublicKeyDataDecryptorFactoryBuilder() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(mPrivateKey); + } + + /** + * Certify the given pubkeyid with the given masterkeyid. + * + * @param publicKeyRing Keyring to add certification to. + * @param userIds User IDs to certify, must not be null or empty + * @return A keyring with added certifications + */ + public UncachedKeyRing certifyUserIds(WrappedPublicKeyRing publicKeyRing, List userIds) + throws PgpGeneralMsgIdException, NoSuchAlgorithmException, NoSuchProviderException, + PGPException, SignatureException { + + if(mPrivateKey == null) { + throw new PrivateKeyNotUnlockedException(); + } + + // create a signatureGenerator from the supplied masterKeyId and passphrase + PGPSignatureGenerator signatureGenerator; + { + // TODO: SHA256 fixed? + JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( + mSecretKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + + signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder); + signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, mPrivateKey); + } + + { // supply signatureGenerator with a SubpacketVector + PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); + PGPSignatureSubpacketVector packetVector = spGen.generate(); + signatureGenerator.setHashedSubpackets(packetVector); + } + + // get the master subkey (which we certify for) + PGPPublicKey publicKey = publicKeyRing.getSubkey().getPublicKey(); + + // fetch public key ring, add the certification and return it + for (String userId : new IterableIterator(userIds.iterator())) { + PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey); + publicKey = PGPPublicKey.addCertification(publicKey, userId, sig); + } + + PGPPublicKeyRing ring = PGPPublicKeyRing.insertPublicKey(publicKeyRing.getRing(), publicKey); + + return new UncachedKeyRing(ring); + } + + static class PrivateKeyNotUnlockedException extends RuntimeException { + // this exception is a programming error which happens when an operation which requires + // 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/WrappedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java new file mode 100644 index 000000000..c94b7dfba --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java @@ -0,0 +1,123 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPPrivateKey; +import org.spongycastle.openpgp.PGPSecretKey; +import org.spongycastle.openpgp.PGPSecretKeyRing; +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.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.util.IterableIterator; + +import java.io.IOException; +import java.security.NoSuchProviderException; +import java.util.Iterator; + +public class WrappedSecretKeyRing extends WrappedKeyRing { + + private PGPSecretKeyRing mRing; + + public WrappedSecretKeyRing(byte[] blob, boolean isRevoked, int verified) + { + super(isRevoked, verified); + mRing = (PGPSecretKeyRing) PgpConversionHelper.BytesToPGPKeyRing(blob); + } + + PGPSecretKeyRing getRing() { + return mRing; + } + + public WrappedSecretKey getSubKey() { + return new WrappedSecretKey(this, mRing.getSecretKey()); + } + + public WrappedSecretKey getSubKey(long id) { + return new WrappedSecretKey(this, mRing.getSecretKey(id)); + } + + /** Getter that returns the subkey that should be used for signing. */ + WrappedSecretKey getSigningSubKey() throws PgpGeneralException { + PGPSecretKey key = mRing.getSecretKey(getSignId()); + if(key != null) { + WrappedSecretKey cKey = new WrappedSecretKey(this, key); + if(!cKey.canSign()) { + throw new PgpGeneralException("key error"); + } + return cKey; + } + // TODO handle with proper exception + throw new PgpGeneralException("no signing key available"); + } + + public boolean hasPassphrase() { + PGPSecretKey secretKey = null; + boolean foundValidKey = false; + for (Iterator keys = mRing.getSecretKeys(); keys.hasNext(); ) { + secretKey = (PGPSecretKey) keys.next(); + if (!secretKey.isPrivateKeyEmpty()) { + foundValidKey = true; + break; + } + } + if(!foundValidKey) { + return false; + } + + try { + PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() + .setProvider("SC").build("".toCharArray()); + PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor); + return testKey == null; + } catch(PGPException e) { + // this means the crc check failed -> passphrase required + return true; + } + } + + 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); + + } + + public IterableIterator iterator() { + final Iterator it = mRing.getSecretKeys(); + return new IterableIterator(new Iterator() { + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public WrappedSecretKey next() { + return new WrappedSecretKey(WrappedSecretKeyRing.this, it.next()); + } + + @Override + public void remove() { + it.remove(); + } + }); + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/exception/PgpGeneralException.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/exception/PgpGeneralException.java index 37d21eea4..f37a61852 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/exception/PgpGeneralException.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/exception/PgpGeneralException.java @@ -27,4 +27,7 @@ public class PgpGeneralException extends Exception { public PgpGeneralException(String message, Throwable cause) { super(message, cause); } + public PgpGeneralException(Throwable cause) { + super(cause); + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java new file mode 100644 index 000000000..6f7623d65 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java @@ -0,0 +1,125 @@ +package org.sufficientlysecure.keychain.provider; + +import android.net.Uri; + +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; + +public class CachedPublicKeyRing extends KeyRing { + + final ProviderHelper mProviderHelper; + final Uri mUri; + + public CachedPublicKeyRing(ProviderHelper providerHelper, Uri uri) { + mProviderHelper = providerHelper; + mUri = uri; + } + + public long getMasterKeyId() throws PgpGeneralException { + try { + return mProviderHelper.getMasterKeyId(mUri); + } catch(ProviderHelper.NotFoundException e) { + throw new PgpGeneralException(e); + } + } + + public String getPrimaryUserId() throws PgpGeneralException { + try { + Object data = mProviderHelper.getGenericData(mUri, + KeychainContract.KeyRings.MASTER_KEY_ID, + ProviderHelper.FIELD_TYPE_STRING); + return (String) data; + } catch(ProviderHelper.NotFoundException e) { + throw new PgpGeneralException(e); + } + } + + public boolean isRevoked() throws PgpGeneralException { + try { + Object data = mProviderHelper.getGenericData(mUri, + KeychainContract.KeyRings.MASTER_KEY_ID, + ProviderHelper.FIELD_TYPE_INTEGER); + return (Long) data > 0; + } catch(ProviderHelper.NotFoundException e) { + throw new PgpGeneralException(e); + } + } + + public boolean canCertify() throws PgpGeneralException { + try { + Object data = mProviderHelper.getGenericData(mUri, + KeychainContract.KeyRings.MASTER_KEY_ID, + ProviderHelper.FIELD_TYPE_INTEGER); + return (Long) data > 0; + } catch(ProviderHelper.NotFoundException e) { + throw new PgpGeneralException(e); + } + } + + public long getEncryptId() throws PgpGeneralException { + try { + Object data = mProviderHelper.getGenericData(mUri, + KeychainContract.KeyRings.MASTER_KEY_ID, + ProviderHelper.FIELD_TYPE_INTEGER); + return (Long) data; + } catch(ProviderHelper.NotFoundException e) { + throw new PgpGeneralException(e); + } + } + + public boolean hasEncrypt() throws PgpGeneralException { + try { + Object data = mProviderHelper.getGenericData(mUri, + KeychainContract.KeyRings.MASTER_KEY_ID, + ProviderHelper.FIELD_TYPE_INTEGER); + return (Long) data > 0; + } catch(ProviderHelper.NotFoundException e) { + throw new PgpGeneralException(e); + } + } + + public long getSignId() throws PgpGeneralException { + try { + Object data = mProviderHelper.getGenericData(mUri, + KeychainContract.KeyRings.MASTER_KEY_ID, + ProviderHelper.FIELD_TYPE_INTEGER); + return (Long) data; + } catch(ProviderHelper.NotFoundException e) { + throw new PgpGeneralException(e); + } + } + + public boolean hasSign() throws PgpGeneralException { + try { + Object data = mProviderHelper.getGenericData(mUri, + KeychainContract.KeyRings.MASTER_KEY_ID, + ProviderHelper.FIELD_TYPE_INTEGER); + return (Long) data > 0; + } catch(ProviderHelper.NotFoundException e) { + throw new PgpGeneralException(e); + } + } + + public int getVerified() throws PgpGeneralException { + try { + Object data = mProviderHelper.getGenericData(mUri, + KeychainContract.KeyRings.MASTER_KEY_ID, + ProviderHelper.FIELD_TYPE_INTEGER); + return (Integer) data; + } catch(ProviderHelper.NotFoundException e) { + throw new PgpGeneralException(e); + } + } + + public boolean hasAnySecret() throws PgpGeneralException { + try { + Object data = mProviderHelper.getGenericData(mUri, + KeychainContract.KeyRings.MASTER_KEY_ID, + ProviderHelper.FIELD_TYPE_INTEGER); + return (Long) data > 0; + } catch(ProviderHelper.NotFoundException e) { + throw new PgpGeneralException(e); + } + + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 9f6314329..be7bd1556 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -261,7 +261,7 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(KeyRings.PRIVKEY_DATA, Tables.KEY_RINGS_SECRET + "." + KeyRingData.KEY_RING_DATA + " AS " + KeyRings.PRIVKEY_DATA); - projectionMap.put(KeyRings.HAS_SECRET, KeyRings.HAS_SECRET); + projectionMap.put(KeyRings.HAS_SECRET, Tables.KEYS + "." + KeyRings.HAS_SECRET); projectionMap.put(KeyRings.HAS_ANY_SECRET, "(EXISTS (SELECT * FROM " + Tables.KEY_RINGS_SECRET + " WHERE " + Tables.KEY_RINGS_SECRET + "." + KeyRingData.MASTER_KEY_ID 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 18035eefe..be769dfbe 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -39,9 +39,9 @@ import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.pgp.CachedKeyRing; -import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing; -import org.sufficientlysecure.keychain.pgp.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing; +import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; @@ -67,7 +67,6 @@ import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; public class ProviderHelper { @@ -198,56 +197,46 @@ public class ProviderHelper { return result; } - public CachedPublicKeyRing getCachedPublicKeyRing(long id) throws NotFoundException { - return (CachedPublicKeyRing) getCachedKeyRing( + public CachedPublicKeyRing getCachedPublicKeyRing(Uri queryUri) { + return new CachedPublicKeyRing(this, queryUri); + } + + public WrappedPublicKeyRing getWrappedPublicKeyRing(long id) throws NotFoundException { + return (WrappedPublicKeyRing) getWrappedKeyRing( KeyRings.buildUnifiedKeyRingUri(Long.toString(id)), false); } - public CachedPublicKeyRing getCachedPublicKeyRing(Uri queryUri) throws NotFoundException { - return (CachedPublicKeyRing) getCachedKeyRing(queryUri, false); + public WrappedPublicKeyRing getWrappedPublicKeyRing(Uri queryUri) throws NotFoundException { + return (WrappedPublicKeyRing) getWrappedKeyRing(queryUri, false); } - public CachedSecretKeyRing getCachedSecretKeyRing(long id) throws NotFoundException { - return (CachedSecretKeyRing) getCachedKeyRing( + public WrappedSecretKeyRing getWrappedSecretKeyRing(long id) throws NotFoundException { + return (WrappedSecretKeyRing) getWrappedKeyRing( KeyRings.buildUnifiedKeyRingUri(Long.toString(id)), true); } - public CachedSecretKeyRing getCachedSecretKeyRing(Uri queryUri) throws NotFoundException { - return (CachedSecretKeyRing) getCachedKeyRing(queryUri, true); + public WrappedSecretKeyRing getWrappedSecretKeyRing(Uri queryUri) throws NotFoundException { + return (WrappedSecretKeyRing) getWrappedKeyRing(queryUri, true); } - private CachedKeyRing getCachedKeyRing(Uri queryUri, boolean secret) throws NotFoundException { + private KeyRing getWrappedKeyRing(Uri queryUri, boolean secret) throws NotFoundException { Cursor cursor = mContentResolver.query(queryUri, new String[] { - // we pick from cache: - // basic data, primary uid in particular because it's expensive - KeyRings.MASTER_KEY_ID, KeyRings.USER_ID, KeyRings.HAS_ANY_SECRET, - // complex knowledge about subkeys - KeyRings.IS_REVOKED, KeyRings.CAN_CERTIFY, KeyRings.HAS_ENCRYPT, KeyRings.HAS_SIGN, - // stuff only the db knows and of course, ring data - KeyRings.VERIFIED, secret ? KeyRings.PRIVKEY_DATA : KeyRings.PUBKEY_DATA + // we pick from cache only information that is not easily available from keyrings + KeyRings.HAS_ANY_SECRET, KeyRings.VERIFIED, + // and of course, ring data + secret ? KeyRings.PRIVKEY_DATA : KeyRings.PUBKEY_DATA }, null, null, null); try { if (cursor != null && cursor.moveToFirst()) { - long masterKeyId = cursor.getLong(0); - String userId = cursor.getString(1); - boolean hasAnySecret = cursor.getInt(2) > 0; - boolean isRevoked = cursor.getInt(3) > 0; - boolean canCertify = cursor.getInt(4) > 0; - long hasEncryptId = cursor.getLong(5); - long hasSignId = cursor.getLong(6); - int verified = cursor.getInt(7); - byte[] blob = cursor.getBlob(8); + + boolean hasAnySecret = cursor.getInt(0) > 0; + int verified = cursor.getInt(1); + byte[] blob = cursor.getBlob(2); return secret - ? new CachedSecretKeyRing( - masterKeyId, userId, hasAnySecret, - isRevoked, canCertify, hasEncryptId, hasSignId, - verified, blob) - : new CachedPublicKeyRing( - masterKeyId, userId, hasAnySecret, - isRevoked, canCertify, hasEncryptId, hasSignId, - verified, blob); + ? new WrappedSecretKeyRing(blob, hasAnySecret, verified) + : new WrappedPublicKeyRing(blob, hasAnySecret, verified); } else { throw new NotFoundException("Key not found!"); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 58aa2ece8..d8a52ee83 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -419,7 +419,7 @@ public class OpenPgpService extends RemoteService { try { // try to find key, throws NotFoundException if not in db! - mProviderHelper.getCachedPublicKeyRing(masterKeyId); + mProviderHelper.getWrappedPublicKeyRing(masterKeyId); Intent result = new Intent(); result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); 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 ff599aaa1..f0d01e2ce 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -27,14 +27,17 @@ 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.PGPUtil; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; import org.sufficientlysecure.keychain.helper.OtherHelper; 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.WrappedPublicKeyRing; +import org.sufficientlysecure.keychain.pgp.WrappedSecretKey; +import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.PgpHelper; @@ -57,6 +60,7 @@ import org.sufficientlysecure.keychain.keyimport.KeybaseKeyServer; 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; @@ -512,7 +516,7 @@ public class KeychainIntentService extends IntentService ProviderHelper providerHelper = new ProviderHelper(this); if (!canSign) { setProgress(R.string.progress_building_key, 0, 100); - CachedSecretKeyRing keyRing = providerHelper.getCachedSecretKeyRing(masterKeyId); + WrappedSecretKeyRing keyRing = providerHelper.getWrappedSecretKeyRing(masterKeyId); UncachedSecretKeyRing newKeyRing = keyRing.changeSecretKeyPassphrase(oldPassphrase, newPassphrase); setProgress(R.string.progress_saving_key_ring, 50, 100); @@ -522,8 +526,8 @@ public class KeychainIntentService extends IntentService PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 90, 100)); UncachedKeyRing pair; try { - CachedSecretKeyRing privkey = providerHelper.getCachedSecretKeyRing(masterKeyId); - CachedPublicKeyRing pubkey = providerHelper.getCachedPublicKeyRing(masterKeyId); + WrappedSecretKeyRing privkey = providerHelper.getWrappedSecretKeyRing(masterKeyId); + WrappedPublicKeyRing pubkey = providerHelper.getWrappedPublicKeyRing(masterKeyId); pair = keyOperations.buildSecretKey(privkey, pubkey, saveParcel); // edit existing } catch (ProviderHelper.NotFoundException e) { @@ -720,7 +724,7 @@ public class KeychainIntentService extends IntentService HkpKeyServer server = new HkpKeyServer(keyServer); ProviderHelper providerHelper = new ProviderHelper(this); - CachedPublicKeyRing keyring = providerHelper.getCachedPublicKeyRing(dataUri); + WrappedPublicKeyRing keyring = providerHelper.getWrappedPublicKeyRing(dataUri); PgpImportExport pgpImportExport = new PgpImportExport(this, null); boolean uploaded = pgpImportExport.uploadKeyRingToServer(server, keyring); @@ -850,9 +854,9 @@ public class KeychainIntentService extends IntentService } ProviderHelper providerHelper = new ProviderHelper(this); - CachedPublicKeyRing publicRing = providerHelper.getCachedPublicKeyRing(pubKeyId); - CachedSecretKeyRing secretKeyRing = providerHelper.getCachedSecretKeyRing(masterKeyId); - CachedSecretKey certificationKey = secretKeyRing.getSubKey(); + WrappedPublicKeyRing publicRing = providerHelper.getWrappedPublicKeyRing(pubKeyId); + WrappedSecretKeyRing secretKeyRing = providerHelper.getWrappedSecretKeyRing(masterKeyId); + WrappedSecretKey certificationKey = secretKeyRing.getSubKey(); if(!certificationKey.unlock(signaturePassphrase)) { throw new PgpGeneralException("Error extracting key (bad passphrase?)"); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index 2889b89c6..ef9adaf08 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -42,7 +42,7 @@ import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.helper.Preferences; -import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing; +import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.Log; @@ -178,7 +178,7 @@ public class PassphraseCacheService extends Service { // try to get master key id which is used as an identifier for cached passphrases try { Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + keyId); - CachedSecretKeyRing key = new ProviderHelper(this).getCachedSecretKeyRing( + WrappedSecretKeyRing key = new ProviderHelper(this).getWrappedSecretKeyRing( KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId))); // no passphrase needed? just add empty string and return it, then if (!key.hasPassphrase()) { @@ -241,7 +241,7 @@ public class PassphraseCacheService extends Service { @Deprecated public static boolean hasPassphrase(Context context, long secretKeyId) throws ProviderHelper.NotFoundException { - return new ProviderHelper(context).getCachedSecretKeyRing(secretKeyId).hasPassphrase(); + return new ProviderHelper(context).getWrappedSecretKeyRing(secretKeyId).hasPassphrase(); } /** diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java index fdcb98976..630b23645 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; -import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; @@ -48,8 +47,8 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.ActionBarHelper; import org.sufficientlysecure.keychain.helper.ExportHelper; -import org.sufficientlysecure.keychain.pgp.CachedSecretKey; -import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing; +import org.sufficientlysecure.keychain.pgp.WrappedSecretKey; +import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; @@ -287,10 +286,10 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener try { Uri secretUri = KeyRings.buildUnifiedKeyRingUri(mDataUri); - CachedSecretKeyRing keyRing = new ProviderHelper(this).getCachedSecretKeyRing(secretUri); + WrappedSecretKeyRing keyRing = new ProviderHelper(this).getWrappedSecretKeyRing(secretUri); mMasterCanSign = keyRing.getSubKey().canCertify(); - for (CachedSecretKey key : keyRing.iterator()) { + for (WrappedSecretKey key : keyRing.iterator()) { // Turn into uncached instance mKeys.add(key.getUncached()); mKeysUsages.add(key.getKeyUsage()); // get usage when view is created 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 2b0c94f22..86067086c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -32,7 +32,7 @@ import com.beardedhen.androidbootstrap.BootstrapButton; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; @@ -147,8 +147,8 @@ public class EncryptAsymmetricFragment extends Fragment { // not sure if we need to distinguish between different subkeys here? if (preselectedSignatureKeyId != 0) { try { - CachedPublicKeyRing keyring = - providerHelper.getCachedPublicKeyRing(preselectedSignatureKeyId); + WrappedPublicKeyRing keyring = + providerHelper.getWrappedPublicKeyRing(preselectedSignatureKeyId); if(keyring.hasAnySecret()) { setSignatureKeyId(keyring.getMasterKeyId()); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java index cf7fdcd89..48beb9cf5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -39,7 +39,7 @@ import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPSignature; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; @@ -147,8 +147,8 @@ public class ViewCertActivity extends ActionBarActivity try { ProviderHelper providerHelper = new ProviderHelper(this); - CachedPublicKeyRing signeeRing = providerHelper.getCachedPublicKeyRing(data.getLong(INDEX_MASTER_KEY_ID)); - CachedPublicKeyRing signerRing = providerHelper.getCachedPublicKeyRing(sig.getKeyID()); + WrappedPublicKeyRing signeeRing = providerHelper.getWrappedPublicKeyRing(data.getLong(INDEX_MASTER_KEY_ID)); + WrappedPublicKeyRing signerRing = providerHelper.getWrappedPublicKeyRing(sig.getKeyID()); try { signerRing.getSubkey().initSignature(sig); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java index cc653e58c..e7bcd2bc0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java @@ -44,8 +44,8 @@ import android.widget.Toast; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; -import org.sufficientlysecure.keychain.pgp.CachedSecretKey; -import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing; +import org.sufficientlysecure.keychain.pgp.WrappedSecretKey; +import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.PassphraseCacheService; @@ -102,7 +102,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor // check if secret key has a passphrase if (!(secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none)) { try { - if (new ProviderHelper(context).getCachedSecretKeyRing(secretKeyId).hasPassphrase()) { + if (new ProviderHelper(context).getWrappedSecretKeyRing(secretKeyId).hasPassphrase()) { throw new PgpGeneralException("No passphrase! No passphrase dialog needed!"); } } catch(ProviderHelper.NotFoundException e) { @@ -138,17 +138,24 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor alert.setTitle(R.string.title_authentication); - final CachedSecretKeyRing secretRing; - final String userId; + final WrappedSecretKeyRing secretRing; + String userId; if (secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none) { - secretRing = null; alert.setMessage(R.string.passphrase_for_symmetric_encryption); + secretRing = null; } else { try { ProviderHelper helper = new ProviderHelper(activity); - secretRing = helper.getCachedSecretKeyRing(secretKeyId); - userId = secretRing.getPrimaryUserId(); + secretRing = helper.getWrappedSecretKeyRing(secretKeyId); + // yes the inner try/catch block is necessary, otherwise the final variable + // above can't be statically verified to have been set in all cases because + // the catch clause doesn't return. + try { + userId = secretRing.getPrimaryUserId(); + } catch (PgpGeneralException e) { + userId = null; + } } catch (ProviderHelper.NotFoundException e) { alert.setTitle(R.string.title_key_not_found); alert.setMessage(getString(R.string.key_not_found, secretKeyId)); @@ -190,9 +197,9 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor return; } - CachedSecretKey unlockedSecretKey = null; + WrappedSecretKey unlockedSecretKey = null; - for(CachedSecretKey clickSecretKey : secretRing.iterator()) { + for(WrappedSecretKey clickSecretKey : secretRing.iterator()) { try { boolean unlocked = clickSecretKey.unlock(passphrase); if (unlocked) { -- cgit v1.2.3 From ab6c47a9b3642b9f7fe2e3bb45ebbd971517d7e1 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 21 May 2014 21:21:28 +0200 Subject: use long rather than String to build uris by key --- .../keychain/pgp/PgpDecryptVerify.java | 11 +++-------- .../sufficientlysecure/keychain/pgp/PgpSignEncrypt.java | 2 +- .../keychain/provider/KeychainContract.java | 16 ++++++++++------ .../keychain/provider/KeychainProvider.java | 2 +- .../keychain/provider/ProviderHelper.java | 8 +++----- .../keychain/remote/OpenPgpService.java | 2 +- .../keychain/service/PassphraseCacheService.java | 2 +- .../sufficientlysecure/keychain/ui/EditKeyActivity.java | 3 +-- .../keychain/ui/EncryptAsymmetricFragment.java | 12 +++++++----- .../sufficientlysecure/keychain/ui/KeyListFragment.java | 2 +- .../keychain/ui/SelectSecretKeyFragment.java | 2 +- .../keychain/ui/SelectSecretKeyLayoutFragment.java | 2 +- .../sufficientlysecure/keychain/ui/ViewCertActivity.java | 6 ++---- 13 files changed, 33 insertions(+), 37 deletions(-) (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 21a7c20e3..abe7d0fb1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -249,8 +249,7 @@ public class PgpDecryptVerify { try { // get actual keyring object based on master key id secretKeyRing = mProviderHelper.getWrappedSecretKeyRing( - KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( - Long.toString(encData.getKeyID())) + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(encData.getKeyID()) ); } catch (ProviderHelper.NotFoundException e) { // continue with the next packet in the while loop @@ -394,9 +393,7 @@ public class PgpDecryptVerify { try { long sigKeyId = sigList.get(i).getKeyID(); signingRing = mProviderHelper.getWrappedPublicKeyRing( - KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( - Long.toString(sigKeyId) - ) + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId) ); signingKey = signingRing.getSubkey(sigKeyId); signatureIndex = i; @@ -581,9 +578,7 @@ public class PgpDecryptVerify { try { long sigKeyId = sigList.get(i).getKeyID(); signingRing = mProviderHelper.getWrappedPublicKeyRing( - KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( - Long.toString(sigKeyId) - ) + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId) ); signingKey = signingRing.getSubkey(sigKeyId); signatureIndex = i; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java index 24d090d04..4cb92c368 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -317,7 +317,7 @@ public class PgpSignEncrypt { for (long id : mEncryptionMasterKeyIds) { try { WrappedPublicKeyRing keyRing = mProviderHelper.getWrappedPublicKeyRing( - KeyRings.buildUnifiedKeyRingUri(Long.toString(id))); + KeyRings.buildUnifiedKeyRingUri(id)); WrappedPublicKey key = keyRing.getEncryptionSubKey(); cPk.addMethod(key.getPubKeyEncryptionGenerator()); } catch (PgpGeneralException e) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index a3c9fab1b..483f762f7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -137,20 +137,24 @@ public class KeychainContract { return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).build(); } - public static Uri buildUnifiedKeyRingUri(String masterKeyId) { - return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_UNIFIED).build(); + public static Uri buildUnifiedKeyRingUri(long masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(Long.toString(masterKeyId)) + .appendPath(PATH_UNIFIED).build(); } public static Uri buildUnifiedKeyRingUri(Uri uri) { - return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_UNIFIED).build(); + return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)) + .appendPath(PATH_UNIFIED).build(); } public static Uri buildUnifiedKeyRingsFindByEmailUri(String email) { - return CONTENT_URI.buildUpon().appendPath(PATH_FIND).appendPath(PATH_BY_EMAIL).appendPath(email).build(); + return CONTENT_URI.buildUpon().appendPath(PATH_FIND) + .appendPath(PATH_BY_EMAIL).appendPath(email).build(); } - public static Uri buildUnifiedKeyRingsFindBySubkeyUri(String subkey) { - return CONTENT_URI.buildUpon().appendPath(PATH_FIND).appendPath(PATH_BY_SUBKEY).appendPath(subkey).build(); + public static Uri buildUnifiedKeyRingsFindBySubkeyUri(long subkey) { + return CONTENT_URI.buildUpon().appendPath(PATH_FIND) + .appendPath(PATH_BY_SUBKEY).appendPath(Long.toString(subkey)).build(); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index be7bd1556..2f6cded91 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -644,7 +644,7 @@ public class KeychainProvider extends ContentProvider { } if(keyId != null) { - uri = KeyRings.buildGenericKeyRingUri(keyId.toString()); + uri = KeyRings.buildGenericKeyRingUri(keyId); rowUri = uri; } 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 be769dfbe..d97260298 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -144,7 +144,7 @@ public class ProviderHelper { public HashMap getUnifiedData(long masterKeyId, String[] proj, int[] types) throws NotFoundException { - return getGenericData(KeyRings.buildUnifiedKeyRingUri(Long.toString(masterKeyId)), proj, types); + return getGenericData(KeyRings.buildUnifiedKeyRingUri(masterKeyId), proj, types); } /** @@ -202,8 +202,7 @@ public class ProviderHelper { } public WrappedPublicKeyRing getWrappedPublicKeyRing(long id) throws NotFoundException { - return (WrappedPublicKeyRing) getWrappedKeyRing( - KeyRings.buildUnifiedKeyRingUri(Long.toString(id)), false); + return (WrappedPublicKeyRing) getWrappedKeyRing(KeyRings.buildUnifiedKeyRingUri(id), false); } public WrappedPublicKeyRing getWrappedPublicKeyRing(Uri queryUri) throws NotFoundException { @@ -211,8 +210,7 @@ public class ProviderHelper { } public WrappedSecretKeyRing getWrappedSecretKeyRing(long id) throws NotFoundException { - return (WrappedSecretKeyRing) getWrappedKeyRing( - KeyRings.buildUnifiedKeyRingUri(Long.toString(id)), true); + return (WrappedSecretKeyRing) getWrappedKeyRing(KeyRings.buildUnifiedKeyRingUri(id), true); } public WrappedSecretKeyRing getWrappedSecretKeyRing(Uri queryUri) throws NotFoundException { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index d8a52ee83..17c277026 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -426,7 +426,7 @@ public class OpenPgpService extends RemoteService { // also return PendingIntent that opens the key view activity Intent intent = new Intent(getBaseContext(), ViewKeyActivity.class); - intent.setData(KeyRings.buildGenericKeyRingUri(Long.toString(masterKeyId))); + intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId)); PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, intent, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index ef9adaf08..17ba9df5c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -179,7 +179,7 @@ public class PassphraseCacheService extends Service { try { Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + keyId); WrappedSecretKeyRing key = new ProviderHelper(this).getWrappedSecretKeyRing( - KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId))); + KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(keyId)); // no passphrase needed? just add empty string and return it, then if (!key.hasPassphrase()) { Log.d(Constants.TAG, "Key has no passphrase! Caches and returns empty passphrase!"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java index 630b23645..ae380552a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -587,8 +587,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener Intent data = new Intent(); // return uri pointing to new created key - Uri uri = KeyRings.buildGenericKeyRingUri( - String.valueOf(getMasterKeyId())); + Uri uri = KeyRings.buildGenericKeyRingUri(getMasterKeyId()); data.setData(uri); setResult(RESULT_OK, data); 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 86067086c..c0ed87a95 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -32,8 +32,9 @@ import com.beardedhen.androidbootstrap.BootstrapButton; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.Log; @@ -147,12 +148,13 @@ public class EncryptAsymmetricFragment extends Fragment { // not sure if we need to distinguish between different subkeys here? if (preselectedSignatureKeyId != 0) { try { - WrappedPublicKeyRing keyring = - providerHelper.getWrappedPublicKeyRing(preselectedSignatureKeyId); + CachedPublicKeyRing keyring = + providerHelper.getCachedPublicKeyRing( + KeyRings.buildUnifiedKeyRingUri(preselectedSignatureKeyId)); if(keyring.hasAnySecret()) { setSignatureKeyId(keyring.getMasterKeyId()); } - } catch (ProviderHelper.NotFoundException e) { + } catch (PgpGeneralException e) { Log.e(Constants.TAG, "key not found!", e); } } @@ -163,7 +165,7 @@ public class EncryptAsymmetricFragment extends Fragment { try { long id = providerHelper.getMasterKeyId( KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( - Long.toString(preselectedEncryptionKeyIds[i])) + preselectedEncryptionKeyIds[i]) ); goodIds.add(id); } catch (ProviderHelper.NotFoundException e) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index 3fd958bcc..a3f4b0753 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -308,7 +308,7 @@ public class KeyListFragment extends LoaderFragment public void onItemClick(AdapterView adapterView, View view, int position, long id) { Intent viewIntent = new Intent(getActivity(), ViewKeyActivity.class); viewIntent.setData( - KeyRings.buildGenericKeyRingUri(Long.toString(mAdapter.getMasterKeyId(position)))); + KeyRings.buildGenericKeyRingUri(mAdapter.getMasterKeyId(position))); startActivity(viewIntent); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java index 38a0c8478..9ddc8e3e1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyFragment.java @@ -84,7 +84,7 @@ public class SelectSecretKeyFragment extends ListFragment implements @Override public void onItemClick(AdapterView adapterView, View view, int position, long id) { long masterKeyId = mAdapter.getMasterKeyId(position); - Uri result = KeyRings.buildGenericKeyRingUri(String.valueOf(masterKeyId)); + Uri result = KeyRings.buildGenericKeyRingUri(masterKeyId); // return data to activity, which results in finishing it mActivity.afterListSelection(result); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java index 8db750917..fe2ecf3a3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectSecretKeyLayoutFragment.java @@ -132,7 +132,7 @@ public class SelectSecretKeyLayoutFragment extends Fragment implements LoaderMan //For AppSettingsFragment public void selectKey(long masterKeyId) { - Uri buildUri = KeychainContract.KeyRings.buildGenericKeyRingUri(String.valueOf(masterKeyId)); + Uri buildUri = KeychainContract.KeyRings.buildGenericKeyRingUri(masterKeyId); mReceivedUri = buildUri; getActivity().getSupportLoaderManager().restartLoader(LOADER_ID, null, this); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java index 48beb9cf5..e6d090062 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -212,11 +212,9 @@ public class ViewCertActivity extends ActionBarActivity try { ProviderHelper providerHelper = new ProviderHelper(ViewCertActivity.this); long signerMasterKeyId = providerHelper.getMasterKeyId( - KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(mCertifierKeyId)) - ); - viewIntent.setData(KeyRings.buildGenericKeyRingUri( - Long.toString(signerMasterKeyId)) + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(mCertifierKeyId) ); + viewIntent.setData(KeyRings.buildGenericKeyRingUri(signerMasterKeyId)); startActivity(viewIntent); } catch (ProviderHelper.NotFoundException e) { // TODO notify user of this, maybe offer download? -- cgit v1.2.3 From 6d7daec37f9ac7efbdd687c97ca45f9c9ddc5602 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 21 May 2014 21:41:51 +0200 Subject: wrapped-key-ring: use CachedKeyRing where possible --- .../keychain/helper/ExportHelper.java | 6 +++-- .../keychain/provider/CachedPublicKeyRing.java | 24 ++++++++++++++++++-- .../keychain/provider/ProviderHelper.java | 26 ---------------------- .../remote/ui/AccountSettingsFragment.java | 6 +++-- .../keychain/ui/EncryptAsymmetricFragment.java | 6 ++--- .../keychain/ui/ViewCertActivity.java | 8 +++---- .../keychain/ui/ViewKeyMainFragment.java | 10 ++++++--- 7 files changed, 44 insertions(+), 42 deletions(-) (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java index 31b88856f..16ef28311 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java @@ -31,6 +31,7 @@ import android.widget.Toast; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; @@ -51,14 +52,15 @@ public class ExportHelper { public void deleteKey(Uri dataUri, Handler deleteHandler) { try { - long masterKeyId = new ProviderHelper(mActivity).extractOrGetMasterKeyId(dataUri); + long masterKeyId = new ProviderHelper(mActivity).getCachedPublicKeyRing(dataUri) + .extractOrGetMasterKeyId(); // Create a new Messenger for the communication back Messenger messenger = new Messenger(deleteHandler); DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger, new long[]{ masterKeyId }); deleteKeyDialog.show(mActivity.getSupportFragmentManager(), "deleteKeyDialog"); - } catch (ProviderHelper.NotFoundException e) { + } catch (PgpGeneralException e) { Log.e(Constants.TAG, "key not found!", e); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java index 6f7623d65..ed1988336 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java @@ -2,8 +2,10 @@ package org.sufficientlysecure.keychain.provider; import android.net.Uri; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.util.Log; public class CachedPublicKeyRing extends KeyRing { @@ -17,12 +19,30 @@ public class CachedPublicKeyRing extends KeyRing { public long getMasterKeyId() throws PgpGeneralException { try { - return mProviderHelper.getMasterKeyId(mUri); - } catch(ProviderHelper.NotFoundException e) { + Object data = mProviderHelper.getGenericData(mUri, + KeychainContract.KeyRings.MASTER_KEY_ID, ProviderHelper.FIELD_TYPE_INTEGER); + return (Long) data; + } catch (ProviderHelper.NotFoundException e) { throw new PgpGeneralException(e); } } + /** + * Find the master key id related to a given query. The id will either be extracted from the + * query, which should work for all specific /key_rings/ queries, or will be queried if it can't. + */ + public long extractOrGetMasterKeyId() throws PgpGeneralException { + // try extracting from the uri first + String firstSegment = mUri.getPathSegments().get(1); + if (!firstSegment.equals("find")) try { + return Long.parseLong(firstSegment); + } catch (NumberFormatException e) { + // didn't work? oh well. + Log.d(Constants.TAG, "Couldn't get masterKeyId from URI, querying..."); + } + return getMasterKeyId(); + } + public String getPrimaryUserId() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, 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 d97260298..4df86ee9b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -147,32 +147,6 @@ public class ProviderHelper { return getGenericData(KeyRings.buildUnifiedKeyRingUri(masterKeyId), proj, types); } - /** - * Find the master key id related to a given query. The id will either be extracted from the - * query, which should work for all specific /key_rings/ queries, or will be queried if it can't. - */ - public long extractOrGetMasterKeyId(Uri queryUri) - throws NotFoundException { - // try extracting from the uri first - String firstSegment = queryUri.getPathSegments().get(1); - if (!firstSegment.equals("find")) try { - return Long.parseLong(firstSegment); - } catch (NumberFormatException e) { - // didn't work? oh well. - Log.d(Constants.TAG, "Couldn't get masterKeyId from URI, querying..."); - } - return getMasterKeyId(queryUri); - } - - public long getMasterKeyId(Uri queryUri) throws NotFoundException { - Object data = getGenericData(queryUri, KeyRings.MASTER_KEY_ID, FIELD_TYPE_INTEGER); - if (data != null) { - return (Long) data; - } else { - throw new NotFoundException(); - } - } - @Deprecated public LongSparseArray getPGPKeyRings(Uri queryUri) { Cursor cursor = mContentResolver.query(queryUri, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java index 20223e319..cb58f8734 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java @@ -33,6 +33,7 @@ import com.beardedhen.androidbootstrap.BootstrapButton; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.remote.AccountSettings; import org.sufficientlysecure.keychain.ui.EditKeyActivity; @@ -179,9 +180,10 @@ public class AccountSettingsFragment extends Fragment implements // select newly created key try { long masterKeyId = new ProviderHelper(getActivity()) - .extractOrGetMasterKeyId(data.getData()); + .getCachedPublicKeyRing(data.getData()) + .extractOrGetMasterKeyId(); mSelectKeyFragment.selectKey(masterKeyId); - } catch (ProviderHelper.NotFoundException e) { + } catch (PgpGeneralException e) { Log.e(Constants.TAG, "key not found!", e); } } 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 c0ed87a95..03483575c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -163,12 +163,12 @@ public class EncryptAsymmetricFragment extends Fragment { Vector goodIds = new Vector(); for (int i = 0; i < preselectedEncryptionKeyIds.length; ++i) { try { - long id = providerHelper.getMasterKeyId( + long id = providerHelper.getCachedPublicKeyRing( KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( preselectedEncryptionKeyIds[i]) - ); + ).getMasterKeyId(); goodIds.add(id); - } catch (ProviderHelper.NotFoundException e) { + } catch (PgpGeneralException e) { Log.e(Constants.TAG, "key not found!", e); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java index e6d090062..465815f14 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -42,6 +42,7 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; @@ -211,12 +212,11 @@ public class ViewCertActivity extends ActionBarActivity try { ProviderHelper providerHelper = new ProviderHelper(ViewCertActivity.this); - long signerMasterKeyId = providerHelper.getMasterKeyId( - KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(mCertifierKeyId) - ); + long signerMasterKeyId = providerHelper.getCachedPublicKeyRing( + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(mCertifierKeyId)).getMasterKeyId(); viewIntent.setData(KeyRings.buildGenericKeyRingUri(signerMasterKeyId)); startActivity(viewIntent); - } catch (ProviderHelper.NotFoundException e) { + } catch (PgpGeneralException e) { // TODO notify user of this, maybe offer download? Log.e(Constants.TAG, "key not found!", e); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java index 026417776..c16bb82af 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java @@ -32,7 +32,9 @@ import android.widget.ListView; import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R;import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.provider.ProviderHelper; @@ -235,14 +237,16 @@ public class ViewKeyMainFragment extends LoaderFragment implements return; } try { - long keyId = new ProviderHelper(getActivity()).extractOrGetMasterKeyId(dataUri); + long keyId = new ProviderHelper(getActivity()) + .getCachedPublicKeyRing(dataUri) + .extractOrGetMasterKeyId(); long[] encryptionKeyIds = new long[]{keyId}; Intent intent = new Intent(getActivity(), EncryptActivity.class); intent.setAction(EncryptActivity.ACTION_ENCRYPT); intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds); // used instead of startActivity set actionbar based on callingPackage startActivityForResult(intent, 0); - } catch (ProviderHelper.NotFoundException e) { + } catch (PgpGeneralException e) { Log.e(Constants.TAG, "key not found!", e); } } -- cgit v1.2.3 From cd0aba9d43403877df2130a54bde8ab51c8030d7 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 22 May 2014 13:05:02 +0200 Subject: wrapped-key-ring: encapsulate key flags --- .../keychain/pgp/UncachedSecretKey.java | 7 +++++ .../keychain/ui/widget/KeyEditor.java | 35 ++++++++++++---------- .../keychain/ui/widget/SectionView.java | 3 +- 3 files changed, 27 insertions(+), 18 deletions(-) (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java index 82224c6cf..0e14a7fd3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKey.java @@ -1,5 +1,6 @@ package org.sufficientlysecure.keychain.pgp; +import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.openpgp.PGPSecretKey; import java.io.IOException; @@ -7,6 +8,12 @@ import java.io.OutputStream; public class UncachedSecretKey extends UncachedPublicKey { + public static final int CERTIFY_OTHER = KeyFlags.CERTIFY_OTHER; + public static final int SIGN_DATA = KeyFlags.SIGN_DATA; + public static final int ENCRYPT_COMMS = KeyFlags.ENCRYPT_COMMS; + public static final int ENCRYPT_STORAGE = KeyFlags.ENCRYPT_STORAGE; + public static final int AUTHENTICATION = KeyFlags.AUTHENTICATION; + final PGPSecretKey mSecretKey; public UncachedSecretKey(PGPSecretKey secretKey) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java index e1a603787..40fe7665c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java @@ -38,7 +38,6 @@ import android.widget.TextView; import com.beardedhen.androidbootstrap.BootstrapButton; -import org.spongycastle.bcpg.sig.KeyFlags; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; @@ -244,11 +243,15 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener { mIsNewKey = isNewKey; if (isNewKey) { mUsage = usage; - mChkCertify.setChecked((usage & KeyFlags.CERTIFY_OTHER) == KeyFlags.CERTIFY_OTHER); - mChkSign.setChecked((usage & KeyFlags.SIGN_DATA) == KeyFlags.SIGN_DATA); - mChkEncrypt.setChecked(((usage & KeyFlags.ENCRYPT_COMMS) == KeyFlags.ENCRYPT_COMMS) || - ((usage & KeyFlags.ENCRYPT_STORAGE) == KeyFlags.ENCRYPT_STORAGE)); - mChkAuthenticate.setChecked((usage & KeyFlags.AUTHENTICATION) == KeyFlags.AUTHENTICATION); + mChkCertify.setChecked( + (usage & UncachedSecretKey.CERTIFY_OTHER) == UncachedSecretKey.CERTIFY_OTHER); + mChkSign.setChecked( + (usage & UncachedSecretKey.SIGN_DATA) == UncachedSecretKey.SIGN_DATA); + mChkEncrypt.setChecked( + ((usage & UncachedSecretKey.ENCRYPT_COMMS) == UncachedSecretKey.ENCRYPT_COMMS) || + ((usage & UncachedSecretKey.ENCRYPT_STORAGE) == UncachedSecretKey.ENCRYPT_STORAGE)); + mChkAuthenticate.setChecked( + (usage & UncachedSecretKey.AUTHENTICATION) == UncachedSecretKey.AUTHENTICATION); } else { mUsage = key.getKeyUsage(); mOriginalUsage = mUsage; @@ -319,16 +322,16 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener { } public int getUsage() { - mUsage = (mUsage & ~KeyFlags.CERTIFY_OTHER) | - (mChkCertify.isChecked() ? KeyFlags.CERTIFY_OTHER : 0); - mUsage = (mUsage & ~KeyFlags.SIGN_DATA) | - (mChkSign.isChecked() ? KeyFlags.SIGN_DATA : 0); - mUsage = (mUsage & ~KeyFlags.ENCRYPT_COMMS) | - (mChkEncrypt.isChecked() ? KeyFlags.ENCRYPT_COMMS : 0); - mUsage = (mUsage & ~KeyFlags.ENCRYPT_STORAGE) | - (mChkEncrypt.isChecked() ? KeyFlags.ENCRYPT_STORAGE : 0); - mUsage = (mUsage & ~KeyFlags.AUTHENTICATION) | - (mChkAuthenticate.isChecked() ? KeyFlags.AUTHENTICATION : 0); + mUsage = (mUsage & ~UncachedSecretKey.CERTIFY_OTHER) | + (mChkCertify.isChecked() ? UncachedSecretKey.CERTIFY_OTHER : 0); + mUsage = (mUsage & ~UncachedSecretKey.SIGN_DATA) | + (mChkSign.isChecked() ? UncachedSecretKey.SIGN_DATA : 0); + mUsage = (mUsage & ~UncachedSecretKey.ENCRYPT_COMMS) | + (mChkEncrypt.isChecked() ? UncachedSecretKey.ENCRYPT_COMMS : 0); + mUsage = (mUsage & ~UncachedSecretKey.ENCRYPT_STORAGE) | + (mChkEncrypt.isChecked() ? UncachedSecretKey.ENCRYPT_STORAGE : 0); + mUsage = (mUsage & ~UncachedSecretKey.AUTHENTICATION) | + (mChkAuthenticate.isChecked() ? UncachedSecretKey.AUTHENTICATION : 0); return mUsage; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java index 35ebfcd58..3e8e18ce5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java @@ -35,7 +35,6 @@ import android.widget.TextView; import com.beardedhen.androidbootstrap.BootstrapButton; -import org.spongycastle.openpgp.PGPKeyFlags; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; @@ -420,7 +419,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor view.setEditorListener(SectionView.this); int usage = 0; if (mEditors.getChildCount() == 0) { - usage = PGPKeyFlags.CAN_CERTIFY; + usage = UncachedSecretKey.CERTIFY_OTHER; } view.setValue(newKey, newKey.isMasterKey(), usage, true); mEditors.addView(view); -- cgit v1.2.3 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/keyimport/ImportKeysListEntry.java | 49 +++++-------------- .../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 ---------- .../keychain/provider/ProviderHelper.java | 15 +++--- .../keychain/service/KeychainIntentService.java | 14 +++--- 8 files changed, 126 insertions(+), 101 deletions(-) (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java index 04b86e295..2d8a97809 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java @@ -21,15 +21,10 @@ import android.content.Context; import android.os.Parcel; import android.os.Parcelable; -import org.spongycastle.bcpg.SignatureSubpacketTags; -import org.spongycastle.openpgp.PGPKeyRing; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.spongycastle.openpgp.PGPSignature; -import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.util.IterableIterator; +import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; +import org.sufficientlysecure.keychain.pgp.UncachedPublicKey; import org.sufficientlysecure.keychain.util.Log; import java.io.IOException; @@ -233,10 +228,12 @@ public class ImportKeysListEntry implements Serializable, Parcelable { * Constructor based on key object, used for import from NFC, QR Codes, files */ @SuppressWarnings("unchecked") - public ImportKeysListEntry(Context context, PGPKeyRing pgpKeyRing) { + public ImportKeysListEntry(Context context, UncachedKeyRing ring) { + // TODO less bouncy castle objects! + // save actual key object into entry, used to import it later try { - this.mBytes = pgpKeyRing.getEncoded(); + this.mBytes = ring.getEncoded(); } catch (IOException e) { Log.e(Constants.TAG, "IOException on pgpKeyRing.getEncoded()", e); } @@ -244,42 +241,20 @@ public class ImportKeysListEntry implements Serializable, Parcelable { // selected is default this.mSelected = true; - if (pgpKeyRing instanceof PGPSecretKeyRing) { - secretKey = true; - } else { - secretKey = false; - } - PGPPublicKey key = pgpKeyRing.getPublicKey(); + secretKey = ring.isSecret(); + UncachedPublicKey key = ring.getPublicKey(); + + mPrimaryUserId = key.getPrimaryUserId(); - userIds = new ArrayList(); - for (String userId : new IterableIterator(key.getUserIDs())) { - userIds.add(userId); - for (PGPSignature sig : new IterableIterator(key.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), key); - if (sig.verifyCertification(userId, key)) { - mPrimaryUserId = userId; - } - } catch (Exception e) { - // nothing bad happens, the key is just not considered the primary key id - } - } - - } - } // if there was no user id flagged as primary, use the first one if (mPrimaryUserId == null) { mPrimaryUserId = userIds.get(0); } - this.keyId = key.getKeyID(); + this.keyId = key.getKeyId(); this.keyIdHex = PgpKeyHelper.convertKeyIdToHex(keyId); - this.revoked = key.isRevoked(); + this.revoked = key.maybeRevoked(); this.fingerprintHex = PgpKeyHelper.convertFingerprintToHex(key.getFingerprint()); this.bitStrength = key.getBitStrength(); final int algorithm = key.getAlgorithm(); 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); - } - } - } 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 4df86ee9b..67d11f9f0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -449,24 +449,23 @@ public class ProviderHelper { } - public void saveKeyRing(UncachedKeyRing wrappedRing) throws IOException { - PGPPublicKeyRing pubRing = wrappedRing.getPublicRing(); - PGPSecretKeyRing secRing = wrappedRing.getSecretRing(); - saveKeyRing(pubRing, secRing); + public void saveKeyRing(UncachedKeyRing ring) throws IOException { + PGPPublicKeyRing pubRing = (PGPPublicKeyRing) ring.getRing(); + saveKeyRing(pubRing); } /** * Saves (or updates) a pair of public and secret KeyRings in the database */ - public void saveKeyRing(PGPPublicKeyRing pubRing, PGPSecretKeyRing privRing) throws IOException { - long masterKeyId = pubRing.getPublicKey().getKeyID(); + public void saveKeyRing(UncachedKeyRing pubRing, UncachedKeyRing secRing) throws IOException { + long masterKeyId = pubRing.getPublicKey().getKeyId(); // delete secret keyring (so it isn't unnecessarily saved by public-saveKeyRing below) mContentResolver.delete(KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId)), null, null); // save public keyring - saveKeyRing(pubRing); - saveKeyRing(privRing); + saveKeyRing((PGPPublicKeyRing) pubRing.getRing()); + saveKeyRing((PGPSecretKeyRing) secRing.getRing()); } /** 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 b866bdf7f..250e1cdda 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -524,19 +524,21 @@ public class KeychainIntentService extends IntentService setProgress(R.string.progress_done, 100, 100); } else { PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 90, 100)); - UncachedKeyRing pair; try { WrappedSecretKeyRing privkey = providerHelper.getWrappedSecretKeyRing(masterKeyId); WrappedPublicKeyRing pubkey = providerHelper.getWrappedPublicKeyRing(masterKeyId); - pair = keyOperations.buildSecretKey(privkey, pubkey, saveParcel); // edit existing + PgpKeyOperation.Pair pair = + keyOperations.buildSecretKey(privkey, pubkey, saveParcel); // edit existing + setProgress(R.string.progress_saving_key_ring, 90, 100); + providerHelper.saveKeyRing(pair.first, pair.second); } catch (ProviderHelper.NotFoundException e) { - pair = keyOperations.buildNewSecretKey(saveParcel); //new Keyring + UncachedKeyRing ring = keyOperations.buildNewSecretKey(saveParcel); //new Keyring + // save the pair + setProgress(R.string.progress_saving_key_ring, 90, 100); + providerHelper.saveKeyRing(ring); } - setProgress(R.string.progress_saving_key_ring, 90, 100); - // save the pair - providerHelper.saveKeyRing(pair); setProgress(R.string.progress_done, 100, 100); } PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassphrase); -- cgit v1.2.3 From 91a8a6c2d1f243f0a3f13b11fd1f920b34717116 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Fri, 23 May 2014 16:48:03 +0200 Subject: wrapped-key-ring: use UncachedKeyRing in ImportKeysListLoader --- .../keychain/ui/adapter/ImportKeysListLoader.java | 36 +++++----------------- 1 file changed, 8 insertions(+), 28 deletions(-) (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java index b6c829677..46b50ac98 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java @@ -20,18 +20,16 @@ package org.sufficientlysecure.keychain.ui.adapter; import android.content.Context; import android.support.v4.content.AsyncTaskLoader; -import org.spongycastle.openpgp.PGPKeyRing; -import org.spongycastle.openpgp.PGPObjectFactory; -import org.spongycastle.openpgp.PGPUtil; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; +import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.PositionAwareInputStream; import java.io.BufferedInputStream; -import java.io.InputStream; import java.util.ArrayList; +import java.util.List; public class ImportKeysListLoader extends AsyncTaskLoader>> { @@ -116,7 +114,6 @@ public class ImportKeysListLoader private void generateListOfKeyrings(InputData inputData) { boolean isEmpty = true; - int nonPgpCounter = 0; PositionAwareInputStream progressIn = new PositionAwareInputStream( inputData.getInputStream()); @@ -129,28 +126,16 @@ public class ImportKeysListLoader // read all available blocks... (asc files can contain many blocks with BEGIN END) while (bufferedInput.available() > 0) { - isEmpty = false; - InputStream in = PGPUtil.getDecoderStream(bufferedInput); - PGPObjectFactory objectFactory = new PGPObjectFactory(in); - - // 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) { - PGPKeyRing newKeyring = (PGPKeyRing) obj; - addToData(newKeyring); - } else { - Log.e(Constants.TAG, "Object not recognized as PGPKeyRing!"); - nonPgpCounter++; - } + // todo deal with non-keyring objects? + List rings = UncachedKeyRing.fromStream(bufferedInput); + for(UncachedKeyRing key : rings) { + addToData(key); + isEmpty = false; } } } catch (Exception e) { Log.e(Constants.TAG, "Exception on parsing key file!", e); mEntryListWrapper = new AsyncTaskResultWrapper>(mData, e); - nonPgpCounter = 0; } if (isEmpty) { @@ -158,14 +143,9 @@ public class ImportKeysListLoader mEntryListWrapper = new AsyncTaskResultWrapper> (mData, new FileHasNoContent()); } - - if (nonPgpCounter > 0) { - mEntryListWrapper = new AsyncTaskResultWrapper> - (mData, new NonPgpPart(nonPgpCounter)); - } } - private void addToData(PGPKeyRing keyring) { + private void addToData(UncachedKeyRing keyring) { ImportKeysListEntry item = new ImportKeysListEntry(getContext(), keyring); mData.add(item); } -- cgit v1.2.3 From c107fc668fb6ef1be2e2775fd2143fb2235942b2 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Fri, 23 May 2014 16:48:41 +0200 Subject: introduce WrappedSignature for the ViewCert* ui code --- .../keychain/pgp/WrappedSignature.java | 124 +++++++++++++++++++++ .../keychain/ui/ViewCertActivity.java | 44 ++++---- .../keychain/ui/ViewKeyCertsFragment.java | 12 +- 3 files changed, 149 insertions(+), 31 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java new file mode 100644 index 000000000..cdadbca7f --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java @@ -0,0 +1,124 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.bcpg.SignatureSubpacket; +import org.spongycastle.bcpg.SignatureSubpacketTags; +import org.spongycastle.bcpg.sig.RevocationReason; +import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPObjectFactory; +import org.spongycastle.openpgp.PGPSignature; +import org.spongycastle.openpgp.PGPSignatureList; +import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.util.Log; + +import java.io.IOException; +import java.security.SignatureException; + +public class WrappedSignature { + + public static final int DEFAULT_CERTIFICATION = PGPSignature.DEFAULT_CERTIFICATION; + public static final int NO_CERTIFICATION = PGPSignature.NO_CERTIFICATION; + public static final int CASUAL_CERTIFICATION = PGPSignature.CASUAL_CERTIFICATION; + public static final int POSITIVE_CERTIFICATION = PGPSignature.POSITIVE_CERTIFICATION; + public static final int CERTIFICATION_REVOCATION = PGPSignature.CERTIFICATION_REVOCATION; + + final PGPSignature mSig; + + protected WrappedSignature(PGPSignature sig) { + mSig = sig; + } + + public long getKeyId() { + return mSig.getKeyID(); + } + + public int getKeyAlgorithm() { + return mSig.getKeyAlgorithm(); + } + + public void init(WrappedPublicKey key) throws PgpGeneralException { + try { + JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = + new JcaPGPContentVerifierBuilderProvider() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + mSig.init(contentVerifierBuilderProvider, key.getPublicKey()); + } catch(PGPException e) { + throw new PgpGeneralException(e); + } + } + + public void update(byte[] data, int offset, int length) throws PgpGeneralException { + try { + mSig.update(data, offset, length); + } catch(SignatureException e) { + throw new PgpGeneralException(e); + } + } + + public void update(byte data) throws PgpGeneralException { + try { + mSig.update(data); + } catch(SignatureException e) { + throw new PgpGeneralException(e); + } + } + + public boolean verify() throws PgpGeneralException { + try { + return mSig.verify(); + } catch(SignatureException e) { + throw new PgpGeneralException(e); + } catch(PGPException e) { + throw new PgpGeneralException(e); + } + } + + public boolean isRevocation() { + return mSig.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.REVOCATION_REASON); + } + + public String getRevocationReason() throws PgpGeneralException { + if(!isRevocation()) { + throw new PgpGeneralException("Not a revocation signature."); + } + SignatureSubpacket p = mSig.getHashedSubPackets().getSubpacket( + SignatureSubpacketTags.REVOCATION_REASON); + // For some reason, this is missing in SignatureSubpacketInputStream:146 + if (!(p instanceof RevocationReason)) { + p = new RevocationReason(false, p.getData()); + } + return ((RevocationReason) p).getRevocationDescription(); + } + + /** 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(WrappedPublicKey key, String uid) throws PgpGeneralException { + try { + return mSig.verifyCertification(uid, key.getPublicKey()); + } catch (SignatureException e) { + throw new PgpGeneralException("Error!", e); + } catch (PGPException e) { + throw new PgpGeneralException("Error!", e); + } + } + + public static WrappedSignature fromBytes(byte[] data) { + PGPObjectFactory factory = new PGPObjectFactory(data); + PGPSignatureList signatures = null; + try { + if ((signatures = (PGPSignatureList) factory.nextObject()) == null || signatures.isEmpty()) { + Log.e(Constants.TAG, "No signatures given!"); + return null; + } + } catch (IOException e) { + Log.e(Constants.TAG, "Error while converting to PGPSignature!", e); + return null; + } + + return new WrappedSignature(signatures.get(0)); + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java index 465815f14..ae0206ab1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -32,16 +32,11 @@ import android.view.MenuItem; import android.view.View; import android.widget.TextView; -import org.spongycastle.bcpg.SignatureSubpacket; -import org.spongycastle.bcpg.SignatureSubpacketTags; -import org.spongycastle.bcpg.sig.RevocationReason; -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPSignature; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing; -import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.pgp.WrappedSignature; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; @@ -144,23 +139,25 @@ public class ViewCertActivity extends ActionBarActivity mCertifierUid.setText(R.string.unknown_uid); } - PGPSignature sig = PgpConversionHelper.BytesToPGPSignature(data.getBlob(INDEX_DATA)); + WrappedSignature sig = WrappedSignature.fromBytes(data.getBlob(INDEX_DATA)); try { ProviderHelper providerHelper = new ProviderHelper(this); - WrappedPublicKeyRing signeeRing = providerHelper.getWrappedPublicKeyRing(data.getLong(INDEX_MASTER_KEY_ID)); - WrappedPublicKeyRing signerRing = providerHelper.getWrappedPublicKeyRing(sig.getKeyID()); + WrappedPublicKeyRing signeeRing = + providerHelper.getWrappedPublicKeyRing(data.getLong(INDEX_MASTER_KEY_ID)); + WrappedPublicKeyRing signerRing = + providerHelper.getWrappedPublicKeyRing(sig.getKeyId()); try { - signerRing.getSubkey().initSignature(sig); - if (signeeRing.getSubkey().verifySignature(sig, signeeUid)) { + sig.init(signerRing.getSubkey()); + if (sig.verifySignature(signeeRing.getSubkey(), signeeUid)) { mStatus.setText(R.string.cert_verify_ok); mStatus.setTextColor(getResources().getColor(R.color.bbutton_success)); } else { mStatus.setText(R.string.cert_verify_failed); mStatus.setTextColor(getResources().getColor(R.color.alert)); } - } catch (PGPException e) { + } catch (PgpGeneralException e) { mStatus.setText(R.string.cert_verify_error); mStatus.setTextColor(getResources().getColor(R.color.alert)); } @@ -174,29 +171,26 @@ public class ViewCertActivity extends ActionBarActivity mRowReason.setVisibility(View.GONE); switch (data.getInt(INDEX_TYPE)) { - case PGPSignature.DEFAULT_CERTIFICATION: + case WrappedSignature.DEFAULT_CERTIFICATION: mType.setText(R.string.cert_default); break; - case PGPSignature.NO_CERTIFICATION: + case WrappedSignature.NO_CERTIFICATION: mType.setText(R.string.cert_none); break; - case PGPSignature.CASUAL_CERTIFICATION: + case WrappedSignature.CASUAL_CERTIFICATION: mType.setText(R.string.cert_casual); break; - case PGPSignature.POSITIVE_CERTIFICATION: + case WrappedSignature.POSITIVE_CERTIFICATION: mType.setText(R.string.cert_positive); break; - case PGPSignature.CERTIFICATION_REVOCATION: { + case WrappedSignature.CERTIFICATION_REVOCATION: { mType.setText(R.string.cert_revoke); - if (sig.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.REVOCATION_REASON)) { - SignatureSubpacket p = sig.getHashedSubPackets().getSubpacket( - SignatureSubpacketTags.REVOCATION_REASON); - // For some reason, this is missing in SignatureSubpacketInputStream:146 - if (!(p instanceof RevocationReason)) { - p = new RevocationReason(false, p.getData()); + if (sig.isRevocation()) { + try { + mReason.setText(sig.getRevocationReason()); + } catch(PgpGeneralException e) { + mReason.setText(R.string.none); } - String reason = ((RevocationReason) p).getRevocationDescription(); - mReason.setText(reason); mRowReason.setVisibility(View.VISIBLE); } break; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java index d5658586d..3cd43638a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyCertsFragment.java @@ -33,10 +33,10 @@ import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.TextView; -import org.spongycastle.openpgp.PGPSignature; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.pgp.WrappedSignature; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.util.Log; @@ -227,19 +227,19 @@ public class ViewKeyCertsFragment extends LoaderFragment wSignerKeyId.setText(signerKeyId); switch (cursor.getInt(mIndexType)) { - case PGPSignature.DEFAULT_CERTIFICATION: // 0x10 + case WrappedSignature.DEFAULT_CERTIFICATION: // 0x10 wSignStatus.setText(R.string.cert_default); break; - case PGPSignature.NO_CERTIFICATION: // 0x11 + case WrappedSignature.NO_CERTIFICATION: // 0x11 wSignStatus.setText(R.string.cert_none); break; - case PGPSignature.CASUAL_CERTIFICATION: // 0x12 + case WrappedSignature.CASUAL_CERTIFICATION: // 0x12 wSignStatus.setText(R.string.cert_casual); break; - case PGPSignature.POSITIVE_CERTIFICATION: // 0x13 + case WrappedSignature.POSITIVE_CERTIFICATION: // 0x13 wSignStatus.setText(R.string.cert_positive); break; - case PGPSignature.CERTIFICATION_REVOCATION: // 0x30 + case WrappedSignature.CERTIFICATION_REVOCATION: // 0x30 wSignStatus.setText(R.string.cert_revoke); break; } -- cgit v1.2.3 From 97af8b2a01af74069d72ca25539cb7465a6440f0 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Fri, 23 May 2014 17:04:15 +0200 Subject: wrapped-key-ring: forgot a part in PgpDecryptVerify --- .../org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index abe7d0fb1..c009d1b5c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -35,6 +35,7 @@ import org.spongycastle.openpgp.PGPUtil; import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory; import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider; import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory; +import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder; import org.sufficientlysecure.keychain.Constants; @@ -417,7 +418,10 @@ public class PgpDecryptVerify { } signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0); - signingKey.initSignature(signature); + JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = + new JcaPGPContentVerifierBuilderProvider() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey()); } else { // no key in our database -> return "unknown pub key" status including the first key id if (!sigList.isEmpty()) { @@ -604,7 +608,10 @@ public class PgpDecryptVerify { } signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0); - signingKey.initSignature(signature); + JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = + new JcaPGPContentVerifierBuilderProvider() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey()); } else { // no key in our database -> return "unknown pub key" status including the first key id if (!sigList.isEmpty()) { -- cgit v1.2.3 From 4a6aaf1e836bd3833c67418a3b77f647b2d8b782 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 27 May 2014 13:49:39 +0200 Subject: fix missing userIds in ImportKeysListEntry --- .../keychain/keyimport/ImportKeysListEntry.java | 3 +-- .../org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java | 10 ++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java index 2d8a97809..0187fe52a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java @@ -229,8 +229,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable { */ @SuppressWarnings("unchecked") public ImportKeysListEntry(Context context, UncachedKeyRing ring) { - // TODO less bouncy castle objects! - // save actual key object into entry, used to import it later try { this.mBytes = ring.getEncoded(); @@ -245,6 +243,7 @@ public class ImportKeysListEntry implements Serializable, Parcelable { UncachedPublicKey key = ring.getPublicKey(); mPrimaryUserId = key.getPrimaryUserId(); + userIds = key.getUnorderedUserIds(); // if there was no user id flagged as primary, use the first one if (mPrimaryUserId == null) { 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 7f6fae4a6..5dbe4b316 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java @@ -71,9 +71,7 @@ public class UncachedPublicKey { } 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)) { @@ -94,6 +92,14 @@ public class UncachedPublicKey { return null; } + public ArrayList getUnorderedUserIds() { + ArrayList userIds = new ArrayList(); + for (String userId : new IterableIterator(mPublicKey.getUserIDs())) { + userIds.add(userId); + } + return userIds; + } + public boolean isElGamalEncrypt() { return getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT; } -- cgit v1.2.3 From e7fa124108e72b0eaaa1319467d666d876278467 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 12 May 2014 22:18:11 +0200 Subject: update unit test support in build files --- OpenKeychain/build.gradle | 59 +++++++++------------- .../src/androidTest/java/tests/SomeTest.java | 12 +++++ .../keychain/PgpKeyOperationTest.java | 46 ----------------- .../keychain/RobolectricGradleTestRunner.java | 23 --------- 4 files changed, 35 insertions(+), 105 deletions(-) create mode 100644 OpenKeychain/src/androidTest/java/tests/SomeTest.java delete mode 100644 OpenKeychain/src/test/java/org/sufficientlysecure/keychain/PgpKeyOperationTest.java delete mode 100644 OpenKeychain/src/test/java/org/sufficientlysecure/keychain/RobolectricGradleTestRunner.java (limited to 'OpenKeychain') diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle index 090a7a2bf..11dd7f21c 100644 --- a/OpenKeychain/build.gradle +++ b/OpenKeychain/build.gradle @@ -1,9 +1,11 @@ apply plugin: 'android' +apply plugin: 'android-test' sourceSets { - testLocal { + androidTest { java.srcDir file('src/test/java') - resources.srcDir file('src/test/resources') + // configure the set of classes for JUnit tests + // include '**/*Test.class' } } @@ -23,24 +25,25 @@ dependencies { compile project(':extern:spongycastle:prov') compile project(':extern:AppMsg:library') - // Dependencies for the `testLocal` task, make sure to list all your global dependencies here as well - testLocalCompile 'junit:junit:4.11' - testLocalCompile 'org.robolectric:robolectric:2.2' - testLocalCompile 'com.google.android:android:4.1.1.4' - testLocalCompile 'com.android.support:support-v4:19.1.0' - testLocalCompile 'com.android.support:appcompat-v7:19.1.0' - testLocalCompile project(':extern:openpgp-api-lib') - testLocalCompile project(':extern:openkeychain-api-lib') - testLocalCompile project(':extern:html-textview') - testLocalCompile project(':extern:StickyListHeaders:library') - testLocalCompile project(':extern:AndroidBootstrap:AndroidBootstrap') - testLocalCompile project(':extern:zxing-qr-code') - testLocalCompile project(':extern:zxing-android-integration') - testLocalCompile project(':extern:spongycastle:core') - testLocalCompile project(':extern:spongycastle:pg') - testLocalCompile project(':extern:spongycastle:pkix') - testLocalCompile project(':extern:spongycastle:prov') - testLocalCompile project(':extern:AppMsg:library') + // Dependencies for the `instrumentTest` task, make sure to list all your global dependencies here as well + androidTestCompile 'junit:junit:4.10' + androidTestCompile 'org.robolectric:robolectric:2.1.+' + androidTestCompile 'com.squareup:fest-android:1.0.+' + androidTestCompile 'com.google.android:android:4.1.1.4' + androidTestCompile 'com.android.support:support-v4:19.1.0' + androidTestCompile 'com.android.support:appcompat-v7:19.1.0' + androidTestCompile project(':extern:openpgp-api-lib') + androidTestCompile project(':extern:openkeychain-api-lib') + androidTestCompile project(':extern:html-textview') + androidTestCompile project(':extern:StickyListHeaders:library') + androidTestCompile project(':extern:AndroidBootstrap:AndroidBootstrap') + androidTestCompile project(':extern:zxing-qr-code') + androidTestCompile project(':extern:zxing-android-integration') + androidTestCompile project(':extern:spongycastle:core') + androidTestCompile project(':extern:spongycastle:pg') + androidTestCompile project(':extern:spongycastle:pkix') + androidTestCompile project(':extern:spongycastle:prov') + androidTestCompile project(':extern:AppMsg:library') } android { @@ -92,20 +95,6 @@ android { } } -task localTest(type: Test, dependsOn: assemble) { - testClassesDir = sourceSets.testLocal.output.classesDir - - android.sourceSets.main.java.srcDirs.each { dir -> - def buildDir = dir.getAbsolutePath().split("\\" + File.separator) - buildDir = (buildDir[0..(buildDir.length - 4)] + ['build', 'classes', 'debug']).join("\\" + File.separator) - - sourceSets.testLocal.compileClasspath += files(buildDir) - sourceSets.testLocal.runtimeClasspath += files(buildDir) - } - - classpath = sourceSets.testLocal.runtimeClasspath -} - // NOTE: This disables Lint! tasks.whenTaskAdded { task -> if (task.name.equals("lint")) { @@ -113,5 +102,3 @@ tasks.whenTaskAdded { task -> } } -// NOTE: tests disabled! -//check.dependsOn localTest diff --git a/OpenKeychain/src/androidTest/java/tests/SomeTest.java b/OpenKeychain/src/androidTest/java/tests/SomeTest.java new file mode 100644 index 000000000..edf5f7bcc --- /dev/null +++ b/OpenKeychain/src/androidTest/java/tests/SomeTest.java @@ -0,0 +1,12 @@ +package tests; + +import org.junit.Assert; +import org.junit.Test; + +public class SomeTest { + @Test + public void willFail() { + // stub + // Assert.assertThat(); + } +} \ No newline at end of file diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/PgpKeyOperationTest.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/PgpKeyOperationTest.java deleted file mode 100644 index 72f29a1e3..000000000 --- a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/PgpKeyOperationTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.sufficientlysecure.keychain; - -import org.junit.Before; -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.Robolectric; - -import org.sufficientlysecure.keychain.pgp.*; -import org.spongycastle.openpgp.*; - -@RunWith(RobolectricGradleTestRunner.class) -public class PgpKeyOperationTest { - - PGPSecretKey key; - - @Before - public void setUp() throws Exception { - - /* Input */ - int algorithm = Id.choice.algorithm.dsa; - String passphrase = "swag"; - int keysize = 2048; - boolean masterKey = true; - - /* Operation */ - PgpKeyOperation keyOperations = new PgpKeyOperation(null); - key = keyOperations.createKey(algorithm, keysize, passphrase, masterKey); - - System.err.println("initialized, test key: " + PgpKeyHelper.convertKeyIdToHex(key.getKeyID())); - } - - @After - public void tearDown() { - } - - @Test - public void createTest() { - } - - @Test - public void certifyKey() { - System.err.println("swag"); - } - -} diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/RobolectricGradleTestRunner.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/RobolectricGradleTestRunner.java deleted file mode 100644 index b64ffde07..000000000 --- a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/RobolectricGradleTestRunner.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.sufficientlysecure.keychain; - -import org.junit.runners.model.InitializationError; -import org.robolectric.AndroidManifest; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; -import org.robolectric.res.Fs; -import org.robolectric.res.FsFile; - -import org.sufficientlysecure.keychain.KeychainApplication; - -public class RobolectricGradleTestRunner extends RobolectricTestRunner { - public RobolectricGradleTestRunner(Class testClass) throws InitializationError { - super(testClass); - } - - @Override protected AndroidManifest getAppManifest(Config config) { - String myAppPath = KeychainApplication.class.getProtectionDomain().getCodeSource().getLocation().getPath(); - String manifestPath = myAppPath + "../../../src/main/AndroidManifest.xml"; - return createAppManifest(Fs.fileFromPath(manifestPath)); - } -} - -- cgit v1.2.3 From ce1c3d1a1ee7f8d9b482419801aee494928741d2 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Fri, 9 May 2014 14:06:23 +0200 Subject: rename SaveKeyringParcel to OldSaveKeyringParcel --- .../keychain/pgp/PgpKeyOperation.java | 6 +- .../keychain/service/KeychainIntentService.java | 2 +- .../keychain/service/OldSaveKeyringParcel.java | 128 +++++++++++++++++++++ .../keychain/service/SaveKeyringParcel.java | 123 -------------------- .../keychain/ui/EditKeyActivity.java | 4 +- 5 files changed, 134 insertions(+), 129 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OldSaveKeyringParcel.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java (limited to 'OpenKeychain') 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 5e7134dc6..f49e0af4b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -48,7 +48,7 @@ import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; -import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.service.OldSaveKeyringParcel; import org.sufficientlysecure.keychain.util.Primes; import java.io.IOException; @@ -193,7 +193,7 @@ public class PgpKeyOperation { } public UncachedKeyRing buildNewSecretKey( - SaveKeyringParcel saveParcel) + OldSaveKeyringParcel saveParcel) throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException { int usageId = saveParcel.keysUsages.get(0); @@ -338,7 +338,7 @@ public class PgpKeyOperation { public Pair buildSecretKey(WrappedSecretKeyRing wmKR, WrappedPublicKeyRing wpKR, - SaveKeyringParcel saveParcel) + OldSaveKeyringParcel saveParcel) throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException { PGPSecretKeyRing mKR = wmKR.getRing(); 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 250e1cdda..c2fc4334a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -497,7 +497,7 @@ public class KeychainIntentService extends IntentService } else if (ACTION_SAVE_KEYRING.equals(action)) { try { /* Input */ - SaveKeyringParcel saveParcel = data.getParcelable(SAVE_KEYRING_PARCEL); + OldSaveKeyringParcel saveParcel = data.getParcelable(SAVE_KEYRING_PARCEL); String oldPassphrase = saveParcel.oldPassphrase; String newPassphrase = saveParcel.newPassphrase; boolean canSign = true; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OldSaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OldSaveKeyringParcel.java new file mode 100644 index 000000000..b722393ad --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OldSaveKeyringParcel.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2014 Ash Hughes + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.service; + +import android.os.Parcel; +import android.os.Parcelable; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; +import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; +import org.sufficientlysecure.keychain.util.IterableIterator; +import org.sufficientlysecure.keychain.util.Log; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Calendar; + +/** Class for parcelling data between ui and services. + * This class is outdated and scheduled for removal, pending a rewrite of the + * EditKeyActivity and save keyring routines. + */ +@Deprecated +public class OldSaveKeyringParcel implements Parcelable { + + public ArrayList userIds; + public ArrayList originalIDs; + public ArrayList deletedIDs; + public boolean[] newIDs; + public boolean primaryIDChanged; + public boolean[] moddedKeys; + public ArrayList deletedKeys; + public ArrayList keysExpiryDates; + public ArrayList keysUsages; + public String newPassphrase; + public String oldPassphrase; + public boolean[] newKeys; + public ArrayList keys; + public String originalPrimaryID; + + public OldSaveKeyringParcel() {} + + private OldSaveKeyringParcel(Parcel source) { + userIds = (ArrayList) source.readSerializable(); + originalIDs = (ArrayList) source.readSerializable(); + deletedIDs = (ArrayList) source.readSerializable(); + newIDs = source.createBooleanArray(); + primaryIDChanged = source.readByte() != 0; + moddedKeys = source.createBooleanArray(); + byte[] tmp = source.createByteArray(); + if (tmp == null) { + deletedKeys = null; + } else { + deletedKeys = PgpConversionHelper.BytesToPGPSecretKeyList(tmp); + } + keysExpiryDates = (ArrayList) source.readSerializable(); + keysUsages = source.readArrayList(Integer.class.getClassLoader()); + newPassphrase = source.readString(); + oldPassphrase = source.readString(); + newKeys = source.createBooleanArray(); + keys = PgpConversionHelper.BytesToPGPSecretKeyList(source.createByteArray()); + originalPrimaryID = source.readString(); + } + + @Override + public void writeToParcel(Parcel destination, int flags) { + destination.writeSerializable(userIds); //might not be the best method to store. + destination.writeSerializable(originalIDs); + destination.writeSerializable(deletedIDs); + destination.writeBooleanArray(newIDs); + destination.writeByte((byte) (primaryIDChanged ? 1 : 0)); + destination.writeBooleanArray(moddedKeys); + destination.writeByteArray(encodeArrayList(deletedKeys)); + destination.writeSerializable(keysExpiryDates); + destination.writeList(keysUsages); + destination.writeString(newPassphrase); + destination.writeString(oldPassphrase); + destination.writeBooleanArray(newKeys); + destination.writeByteArray(encodeArrayList(keys)); + destination.writeString(originalPrimaryID); + } + + public static final Creator CREATOR = new Creator() { + public OldSaveKeyringParcel createFromParcel(final Parcel source) { + return new OldSaveKeyringParcel(source); + } + + public OldSaveKeyringParcel[] newArray(final int size) { + return new OldSaveKeyringParcel[size]; + } + }; + + private static byte[] encodeArrayList(ArrayList list) { + if(list.isEmpty()) { + return null; + } + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + for(UncachedSecretKey key : new IterableIterator(list.iterator())) { + try { + key.encodeSecretKey(os); + } catch (IOException e) { + Log.e(Constants.TAG, "Error while converting ArrayList to byte[]!", e); + } + } + return os.toByteArray(); + } + + @Override + public int describeContents() { + return 0; + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java deleted file mode 100644 index 60fdf895d..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2014 Ash Hughes - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.service; - -import android.os.Parcel; -import android.os.Parcelable; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; -import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; -import org.sufficientlysecure.keychain.util.IterableIterator; -import org.sufficientlysecure.keychain.util.Log; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Calendar; - -public class SaveKeyringParcel implements Parcelable { - - public ArrayList userIds; - public ArrayList originalIDs; - public ArrayList deletedIDs; - public boolean[] newIDs; - public boolean primaryIDChanged; - public boolean[] moddedKeys; - public ArrayList deletedKeys; - public ArrayList keysExpiryDates; - public ArrayList keysUsages; - public String newPassphrase; - public String oldPassphrase; - public boolean[] newKeys; - public ArrayList keys; - public String originalPrimaryID; - - public SaveKeyringParcel() {} - - private SaveKeyringParcel(Parcel source) { - userIds = (ArrayList) source.readSerializable(); - originalIDs = (ArrayList) source.readSerializable(); - deletedIDs = (ArrayList) source.readSerializable(); - newIDs = source.createBooleanArray(); - primaryIDChanged = source.readByte() != 0; - moddedKeys = source.createBooleanArray(); - byte[] tmp = source.createByteArray(); - if (tmp == null) { - deletedKeys = null; - } else { - deletedKeys = PgpConversionHelper.BytesToPGPSecretKeyList(tmp); - } - keysExpiryDates = (ArrayList) source.readSerializable(); - keysUsages = source.readArrayList(Integer.class.getClassLoader()); - newPassphrase = source.readString(); - oldPassphrase = source.readString(); - newKeys = source.createBooleanArray(); - keys = PgpConversionHelper.BytesToPGPSecretKeyList(source.createByteArray()); - originalPrimaryID = source.readString(); - } - - @Override - public void writeToParcel(Parcel destination, int flags) { - destination.writeSerializable(userIds); //might not be the best method to store. - destination.writeSerializable(originalIDs); - destination.writeSerializable(deletedIDs); - destination.writeBooleanArray(newIDs); - destination.writeByte((byte) (primaryIDChanged ? 1 : 0)); - destination.writeBooleanArray(moddedKeys); - destination.writeByteArray(encodeArrayList(deletedKeys)); - destination.writeSerializable(keysExpiryDates); - destination.writeList(keysUsages); - destination.writeString(newPassphrase); - destination.writeString(oldPassphrase); - destination.writeBooleanArray(newKeys); - destination.writeByteArray(encodeArrayList(keys)); - destination.writeString(originalPrimaryID); - } - - public static final Creator CREATOR = new Creator() { - public SaveKeyringParcel createFromParcel(final Parcel source) { - return new SaveKeyringParcel(source); - } - - public SaveKeyringParcel[] newArray(final int size) { - return new SaveKeyringParcel[size]; - } - }; - - private static byte[] encodeArrayList(ArrayList list) { - if(list.isEmpty()) { - return null; - } - - ByteArrayOutputStream os = new ByteArrayOutputStream(); - for(UncachedSecretKey key : new IterableIterator(list.iterator())) { - try { - key.encodeSecretKey(os); - } catch (IOException e) { - Log.e(Constants.TAG, "Error while converting ArrayList to byte[]!", e); - } - } - return os.toByteArray(); - } - - @Override - public int describeContents() { - return 0; - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java index ae380552a..d9c7a1736 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -57,8 +57,8 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.service.OldSaveKeyringParcel; import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; @@ -553,7 +553,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener intent.setAction(KeychainIntentService.ACTION_SAVE_KEYRING); - SaveKeyringParcel saveParams = new SaveKeyringParcel(); + OldSaveKeyringParcel saveParams = new OldSaveKeyringParcel(); saveParams.userIds = getUserIds(mUserIdsView); saveParams.originalIDs = mUserIdsView.getOriginalIDs(); saveParams.deletedIDs = mUserIdsView.getDeletedIDs(); -- cgit v1.2.3 From 6415290b2d059752ebcfd74fa2c514aa5e5ef875 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Fri, 9 May 2014 15:30:14 +0200 Subject: introduce new SaveKeyringParcel --- .../keychain/service/SaveKeyringParcel.java | 113 +++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java new file mode 100644 index 000000000..fffcdacc8 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -0,0 +1,113 @@ +package org.sufficientlysecure.keychain.service; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.io.Serializable; +import java.util.HashMap; + +/** This class is a a transferable representation for a collection of changes + * to be done on a keyring. + * + * This class should include all types of operations supported in the backend. + * + * All changes are done in a differential manner. Besides the two key + * identification attributes, all attributes may be null, which indicates no + * change to the keyring. + * + * Application of operations in the backend should be fail-fast, which means an + * error in any included operation (for example revocation of a non-existent + * subkey) will cause the operation as a whole to fail. + */ +public class SaveKeyringParcel implements Parcelable { + + // the master key id to be edited + private final long mMasterKeyId; + // the key fingerprint, for safety + private final byte[] mFingerprint; + + public String newPassphrase; + + public String[] addUserIds; + public SubkeyAdd[] addSubKeys; + + public HashMap changeSubKeys; + public String changePrimaryUserId; + + public String[] revokeUserIds; + public long[] revokeSubKeys; + + public SaveKeyringParcel(long masterKeyId, byte[] fingerprint) { + mMasterKeyId = masterKeyId; + mFingerprint = fingerprint; + } + + // performance gain for using Parcelable here would probably be negligible, + // use Serializable instead. + public static class SubkeyAdd implements Serializable { + public final int mKeysize; + public final int mFlags; + public final Long mExpiry; + public SubkeyAdd(int keysize, int flags, long expiry) { + mKeysize = keysize; + mFlags = flags; + mExpiry = expiry; + } + } + + public static class SubkeyChange implements Serializable { + public final long mKeyId; + public final Integer mFlags; + public final Long mExpiry; + public SubkeyChange(long keyId, int flags, long expiry) { + mKeyId = keyId; + mFlags = flags; + mExpiry = expiry; + } + } + + public SaveKeyringParcel(Parcel source) { + mMasterKeyId = source.readLong(); + mFingerprint = source.createByteArray(); + + addUserIds = source.createStringArray(); + addSubKeys = (SubkeyAdd[]) source.readSerializable(); + + changeSubKeys = (HashMap) source.readSerializable(); + changePrimaryUserId = source.readString(); + + revokeUserIds = source.createStringArray(); + revokeSubKeys = source.createLongArray(); + } + + @Override + public void writeToParcel(Parcel destination, int flags) { + destination.writeLong(mMasterKeyId); + destination.writeByteArray(mFingerprint); + + destination.writeStringArray(addUserIds); + destination.writeSerializable(addSubKeys); + + destination.writeSerializable(changeSubKeys); + destination.writeString(changePrimaryUserId); + + destination.writeStringArray(revokeUserIds); + destination.writeLongArray(revokeSubKeys); + } + + public static final Creator CREATOR = new Creator() { + public SaveKeyringParcel createFromParcel(final Parcel source) { + return new SaveKeyringParcel(source); + } + + public SaveKeyringParcel[] newArray(final int size) { + return new SaveKeyringParcel[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + +} -- cgit v1.2.3 From a53da491c09fc7db814d4c2358ffe5dc9fe888bc Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 14 May 2014 15:37:55 +0200 Subject: new savekeyring operation (mostly stub) --- .../keychain/pgp/PgpConversionHelper.java | 24 -- .../keychain/pgp/PgpImportExport.java | 12 +- .../keychain/pgp/PgpKeyOperation.java | 338 ++++++++++++++++++++- .../keychain/pgp/UncachedKeyRing.java | 49 ++- .../keychain/pgp/UncachedPublicKey.java | 21 +- .../keychain/pgp/UncachedSecretKeyRing.java | 28 +- .../keychain/pgp/WrappedKeyRing.java | 7 + .../keychain/pgp/WrappedSecretKeyRing.java | 4 + .../keychain/pgp/WrappedSignature.java | 77 +++-- .../keychain/provider/KeychainDatabase.java | 34 +-- .../keychain/provider/ProviderHelper.java | 265 +++++----------- .../keychain/service/KeychainIntentService.java | 29 +- .../keychain/service/PassphraseCacheService.java | 48 +-- .../keychain/service/SaveKeyringParcel.java | 9 +- .../keychain/ui/ViewKeyShareFragment.java | 4 + .../ui/dialog/PassphraseDialogFragment.java | 2 +- 16 files changed, 595 insertions(+), 356 deletions(-) (limited to 'OpenKeychain') 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 63e2ff2f2..ea3c72fd0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java @@ -21,8 +21,6 @@ import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPObjectFactory; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.spongycastle.openpgp.PGPSignature; -import org.spongycastle.openpgp.PGPSignatureList; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.util.Log; @@ -122,26 +120,4 @@ public class PgpConversionHelper { return new UncachedSecretKey(secKey); } - /** - * Convert from byte[] to PGPSignature - * - * @param sigBytes - * @return - */ - public static PGPSignature BytesToPGPSignature(byte[] sigBytes) { - PGPObjectFactory factory = new PGPObjectFactory(sigBytes); - PGPSignatureList signatures = null; - try { - if ((signatures = (PGPSignatureList) factory.nextObject()) == null || signatures.isEmpty()) { - Log.e(Constants.TAG, "No signatures given!"); - return null; - } - } catch (IOException e) { - Log.e(Constants.TAG, "Error while converting to PGPSignature!", e); - return null; - } - - return signatures.get(0); - } - } 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 e858012f5..268906037 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java @@ -257,7 +257,8 @@ public class PgpImportExport { updateProgress(progress * 100 / masterKeyIdsSize, 100); try { - PGPSecretKeyRing secretKeyRing = mProviderHelper.getPGPSecretKeyRing(secretKeyMasterId); + WrappedSecretKeyRing secretKeyRing = + mProviderHelper.getWrappedSecretKeyRing(secretKeyMasterId); secretKeyRing.encode(arOutStream); } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "key not found!", e); @@ -287,18 +288,13 @@ public class PgpImportExport { public int storeKeyRingInCache(UncachedKeyRing ring, UncachedKeyRing secretRing) { int status; try { - // TODO make sure these are correctly typed! - PGPPublicKeyRing publicKeyRing = (PGPPublicKeyRing) ring.getRing(); - PGPSecretKeyRing secretKeyRing = null; - if(secretRing != null) { - secretKeyRing = (PGPSecretKeyRing) secretRing.getRing(); - } + UncachedSecretKeyRing secretKeyRing = null; // see what type we have. we can either have a secret + public keyring, or just public if (secretKeyRing != null) { mProviderHelper.saveKeyRing(ring, secretRing); status = RETURN_OK; } else { - mProviderHelper.saveKeyRing(publicKeyRing); + mProviderHelper.saveKeyRing(ring); status = RETURN_OK; } } catch (IOException e) { 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 f49e0af4b..3e296edb9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -35,6 +35,7 @@ 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; @@ -49,6 +50,8 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException; import org.sufficientlysecure.keychain.service.OldSaveKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Primes; import java.io.IOException; @@ -60,9 +63,11 @@ import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.security.SignatureException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.Iterator; +import java.util.List; import java.util.TimeZone; /** @@ -644,7 +649,7 @@ public class PgpKeyOperation { for(String uid : new IterableIterator(secretKeyRing.getPublicKey().getUserIDs())) { for(PGPSignature sig : new IterableIterator( - secretKeyRing.getPublicKey().getSignaturesForID(uid))) { + secretKeyRing.getPublicKey().getSignaturesForId(uid))) { Log.d(Constants.TAG, "sig: " + PgpKeyHelper.convertKeyIdToHex(sig.getKeyID()) + " for " + uid); } @@ -655,7 +660,7 @@ public class PgpKeyOperation { for(String uid : new IterableIterator(publicKeyRing.getPublicKey().getUserIDs())) { for(PGPSignature sig : new IterableIterator( - publicKeyRing.getPublicKey().getSignaturesForID(uid))) { + publicKeyRing.getPublicKey().getSignaturesForId(uid))) { Log.d(Constants.TAG, "sig: " + PgpKeyHelper.convertKeyIdToHex(sig.getKeyID()) + " for " + uid); } @@ -668,6 +673,335 @@ public class PgpKeyOperation { } + public Pair buildSecretKey(PGPSecretKeyRing sKR, + PGPPublicKeyRing pKR, + SaveKeyringParcel saveParcel, + String passphrase) + throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException { + + updateProgress(R.string.progress_building_key, 0, 100); + + // sort these, so we can use binarySearch later on + Arrays.sort(saveParcel.revokeSubKeys); + Arrays.sort(saveParcel.revokeUserIds); + + /* + * What's gonna happen here: + * + * 1. Unlock private key + * + * 2. Create new secret key ring + * + * 3. Copy subkeys + * - Generate revocation if requested + * - Copy old cert, or generate new if change requested + * + * 4. Generate and add new subkeys + * + * 5. Copy user ids + * - Generate revocation if requested + * - Copy old cert, or generate new if primary user id status changed + * + * 6. Add new user ids + * + * 7. Generate PublicKeyRing from SecretKeyRing + * + * 8. Return pair (PublicKeyRing,SecretKeyRing) + * + */ + + // 1. Unlock private key + updateProgress(R.string.progress_building_key, 0, 100); + + PGPPublicKey masterPublicKey = sKR.getPublicKey(); + PGPPrivateKey masterPrivateKey; { + PGPSecretKey masterKey = sKR.getSecretKey(); + PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( + Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); + masterPrivateKey = masterKey.extractPrivateKey(keyDecryptor); + } + + // 2. Create new secret key ring + updateProgress(R.string.progress_certifying_master_key, 20, 100); + + // Note we do NOT use PGPKeyRingGeneraor, it's just one level too high and does stuff + // we want to do manually. Instead, we simply use a list of secret keys. + ArrayList secretKeys = new ArrayList(); + ArrayList publicKeys = new ArrayList(); + + // 3. Copy subkeys + // - Generate revocation if requested + // - Copy old cert, or generate new if change requested + for (PGPSecretKey sKey : new IterableIterator(sKR.getSecretKeys())) { + PGPPublicKey pKey = sKey.getPublicKey(); + if (Arrays.binarySearch(saveParcel.revokeSubKeys, sKey.getKeyID()) >= 0) { + // add revocation signature to key, if there is none yet + if (!pKey.getSignaturesOfType(PGPSignature.SUBKEY_REVOCATION).hasNext()) { + // generate revocation signature + } + } + if (saveParcel.changeSubKeys.containsKey(sKey.getKeyID())) { + // change subkey flags? + SaveKeyringParcel.SubkeyChange change = saveParcel.changeSubKeys.get(sKey.getKeyID()); + // remove old subkey binding signature(s?) + for (PGPSignature sig : new IterableIterator( + pKey.getSignaturesOfType(PGPSignature.SUBKEY_BINDING))) { + pKey = PGPPublicKey.removeCertification(pKey, sig); + } + + // generate and add new signature + PGPSignature sig = generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey, + sKey, pKey, change.mFlags, change.mExpiry, passphrase); + pKey = PGPPublicKey.addCertification(pKey, sig); + } + secretKeys.add(PGPSecretKey.replacePublicKey(sKey, pKey)); + publicKeys.add(pKey); + } + + // 4. Generate and add new subkeys + // TODO + + // 5. Copy user ids + for (String userId : new IterableIterator(masterPublicKey.getUserIDs())) { + // - Copy old cert, or generate new if primary user id status changed + boolean certified = false, revoked = false; + for (PGPSignature sig : new IterableIterator( + masterPublicKey.getSignaturesForID(userId))) { + // We know there are only revocation and certification types in here. + switch(sig.getSignatureType()) { + case PGPSignature.CERTIFICATION_REVOCATION: + revoked = true; + continue; + + case PGPSignature.DEFAULT_CERTIFICATION: + case PGPSignature.NO_CERTIFICATION: + case PGPSignature.CASUAL_CERTIFICATION: + case PGPSignature.POSITIVE_CERTIFICATION: + // Already got one? Remove this one, then. + if (certified) { + masterPublicKey = PGPPublicKey.removeCertification( + masterPublicKey, userId, sig); + continue; + } + boolean primary = userId.equals(saveParcel.changePrimaryUserId); + // Generate a new one under certain circumstances + if (saveParcel.changePrimaryUserId != null && + sig.getHashedSubPackets().isPrimaryUserID() != primary) { + PGPSignature cert = generateUserIdSignature( + masterPrivateKey, masterPublicKey, userId, primary); + PGPPublicKey.addCertification(masterPublicKey, userId, cert); + } + certified = true; + } + } + // - Generate revocation if requested + if (!revoked && Arrays.binarySearch(saveParcel.revokeUserIds, userId) >= 0) { + PGPSignature cert = generateRevocationSignature(masterPrivateKey, + masterPublicKey, userId); + masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, cert); + } + } + + // 6. Add new user ids + for(String userId : saveParcel.addUserIds) { + PGPSignature cert = generateUserIdSignature(masterPrivateKey, + masterPublicKey, userId, userId.equals(saveParcel.changePrimaryUserId)); + masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, cert); + } + + // 7. Generate PublicKeyRing from SecretKeyRing + updateProgress(R.string.progress_building_master_key, 30, 100); + PGPSecretKeyRing ring = new PGPSecretKeyRing(secretKeys); + + // Copy all non-self uid certificates + for (String userId : new IterableIterator(masterPublicKey.getUserIDs())) { + // - Copy old cert, or generate new if primary user id status changed + boolean certified = false, revoked = false; + for (PGPSignature sig : new IterableIterator( + masterPublicKey.getSignaturesForID(userId))) { + } + } + + for (PGPPublicKey newKey : publicKeys) { + PGPPublicKey oldKey = pKR.getPublicKey(newKey.getKeyID()); + for (PGPSignature sig : new IterableIterator( + oldKey.getSignatures())) { + } + } + + // If requested, set new passphrase + if (saveParcel.newPassphrase != null) { + PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build() + .get(HashAlgorithmTags.SHA1); + PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( + Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); + // Build key encryptor based on new passphrase + PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder( + PGPEncryptedData.CAST5, sha1Calc) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( + saveParcel.newPassphrase.toCharArray()); + + sKR = PGPSecretKeyRing.copyWithNewPassword(sKR, keyDecryptor, keyEncryptorNew); + } + + // 8. Return pair (PublicKeyRing,SecretKeyRing) + + return new Pair(sKR, pKR); + + } + + private static PGPSignature generateUserIdSignature( + PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId, boolean primary) + throws IOException, PGPException, SignatureException { + PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( + pKey.getAlgorithm(), PGPUtil.SHA1) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); + PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); + subHashedPacketsGen.setSignatureCreationTime(false, new Date()); + subHashedPacketsGen.setPreferredSymmetricAlgorithms(true, PREFERRED_SYMMETRIC_ALGORITHMS); + subHashedPacketsGen.setPreferredHashAlgorithms(true, PREFERRED_HASH_ALGORITHMS); + subHashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS); + subHashedPacketsGen.setPrimaryUserID(false, primary); + sGen.setHashedSubpackets(subHashedPacketsGen.generate()); + sGen.init(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey); + return sGen.generateCertification(userId, pKey); + } + + private static PGPSignature generateRevocationSignature( + PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId) + throws IOException, PGPException, SignatureException { + PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( + pKey.getAlgorithm(), PGPUtil.SHA1) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); + PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); + subHashedPacketsGen.setSignatureCreationTime(false, new Date()); + sGen.setHashedSubpackets(subHashedPacketsGen.generate()); + sGen.init(PGPSignature.CERTIFICATION_REVOCATION, masterPrivateKey); + return sGen.generateCertification(userId, pKey); + } + + private static PGPSignature generateSubkeyBindingSignature( + PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey, + PGPSecretKey sKey, PGPPublicKey pKey, + int flags, Long expiry, String passphrase) + throws PgpGeneralMsgIdException, IOException, PGPException, SignatureException { + + // date for signing + Date todayDate = new Date(); + PGPSignatureSubpacketGenerator unhashedPacketsGen = new PGPSignatureSubpacketGenerator(); + + // If this key can sign, we need a primary key binding signature + if ((flags & KeyFlags.SIGN_DATA) != 0) { + + PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( + passphrase.toCharArray()); + PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor); + + // cross-certify signing keys + PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); + subHashedPacketsGen.setSignatureCreationTime(false, todayDate); + PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( + pKey.getAlgorithm(), PGPUtil.SHA1) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); + sGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey); + sGen.setHashedSubpackets(subHashedPacketsGen.generate()); + PGPSignature certification = sGen.generateCertification(masterPublicKey, pKey); + unhashedPacketsGen.setEmbeddedSignature(false, certification); + } + + PGPSignatureSubpacketGenerator hashedPacketsGen; + { + hashedPacketsGen = new PGPSignatureSubpacketGenerator(); + hashedPacketsGen.setSignatureCreationTime(false, todayDate); + hashedPacketsGen.setKeyFlags(false, flags); + } + + if (expiry != null) { + Calendar creationDate = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + creationDate.setTime(pKey.getCreationTime()); + // note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c + // here we purposefully ignore partial days in each date - long type has + // no fractional part! + long numDays = (expiry / 86400000) - + (creationDate.getTimeInMillis() / 86400000); + if (numDays <= 0) { + throw new PgpGeneralMsgIdException(R.string.error_expiry_must_come_after_creation); + } + hashedPacketsGen.setKeyExpirationTime(false, expiry - creationDate.getTimeInMillis()); + } else { + hashedPacketsGen.setKeyExpirationTime(false, 0); + } + + PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( + pKey.getAlgorithm(), PGPUtil.SHA1) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); + sGen.init(PGPSignature.SUBKEY_BINDING, masterPrivateKey); + sGen.setHashedSubpackets(hashedPacketsGen.generate()); + sGen.setUnhashedSubpackets(unhashedPacketsGen.generate()); + + return sGen.generateCertification(masterPublicKey, pKey); + + } + + + /** + * Certify the given pubkeyid with the given masterkeyid. + * + * @param certificationKey Certifying key + * @param publicKey public key to certify + * @param userIds User IDs to certify, must not be null or empty + * @param passphrase Passphrase of the secret key + * @return A keyring with added certifications + */ + public PGPPublicKey certifyKey(PGPSecretKey certificationKey, PGPPublicKey publicKey, + List userIds, String passphrase) + throws PgpGeneralMsgIdException, NoSuchAlgorithmException, NoSuchProviderException, + PGPException, SignatureException { + + // create a signatureGenerator from the supplied masterKeyId and passphrase + PGPSignatureGenerator signatureGenerator; + { + + if (certificationKey == null) { + throw new PgpGeneralMsgIdException(R.string.error_no_signature_key); + } + + PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( + Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); + PGPPrivateKey signaturePrivateKey = certificationKey.extractPrivateKey(keyDecryptor); + if (signaturePrivateKey == null) { + throw new PgpGeneralMsgIdException(R.string.error_could_not_extract_private_key); + } + + // TODO: SHA256 fixed? + JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder( + certificationKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + + signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder); + signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, signaturePrivateKey); + } + + { // supply signatureGenerator with a SubpacketVector + PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); + PGPSignatureSubpacketVector packetVector = spGen.generate(); + signatureGenerator.setHashedSubpackets(packetVector); + } + + // fetch public key ring, add the certification and return it + for (String userId : new IterableIterator(userIds.iterator())) { + PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey); + publicKey = PGPPublicKey.addCertification(publicKey, userId, sig); + } + + return publicKey; + } + /** * Simple static subclass that stores two values. *

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 06f890fb4..8bacb32c0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -1,8 +1,9 @@ package org.sufficientlysecure.keychain.pgp; +import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPObjectFactory; -import org.spongycastle.openpgp.PGPPublicKeyRing; +import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPUtil; import org.sufficientlysecure.keychain.Constants; @@ -13,6 +14,8 @@ import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; +import java.util.Iterator; import java.util.List; import java.util.Vector; @@ -26,6 +29,10 @@ public class UncachedKeyRing { mIsSecret = ring instanceof PGPSecretKeyRing; } + public long getMasterKeyId() { + return mRing.getPublicKey().getKeyID(); + } + /* TODO don't use this */ @Deprecated public PGPKeyRing getRing() { @@ -36,6 +43,21 @@ public class UncachedKeyRing { return new UncachedPublicKey(mRing.getPublicKey()); } + public Iterator getPublicKeys() { + final Iterator it = mRing.getPublicKeys(); + return new Iterator() { + public void remove() { + it.remove(); + } + public UncachedPublicKey next() { + return new UncachedPublicKey(it.next()); + } + public boolean hasNext() { + return it.hasNext(); + } + }; + } + public boolean isSecret() { return mIsSecret; } @@ -50,6 +72,15 @@ public class UncachedKeyRing { public static UncachedKeyRing decodePubkeyFromData(byte[] data) throws PgpGeneralException, IOException { + UncachedKeyRing ring = decodeFromData(data); + if(ring.isSecret()) { + throw new PgpGeneralException("Object not recognized as PGPPublicKeyRing!"); + } + return ring; + } + + public static UncachedKeyRing decodeFromData(byte[] data) + throws PgpGeneralException, IOException { BufferedInputStream bufferedInput = new BufferedInputStream(new ByteArrayInputStream(data)); if (bufferedInput.available() > 0) { @@ -58,13 +89,14 @@ public class UncachedKeyRing { // get first object in block Object obj; - if ((obj = objectFactory.nextObject()) != null && obj instanceof PGPPublicKeyRing) { - return new UncachedKeyRing((PGPPublicKeyRing) obj); + if ((obj = objectFactory.nextObject()) != null && obj instanceof PGPKeyRing) { + // the constructor will take care of the public/secret part + return new UncachedKeyRing((PGPKeyRing) obj); } else { - throw new PgpGeneralException("Object not recognized as PGPPublicKeyRing!"); + throw new PgpGeneralException("Object not recognized as PGPKeyRing!"); } } else { - throw new PgpGeneralException("Object not recognized as PGPPublicKeyRing!"); + throw new PgpGeneralException("Object not recognized as PGPKeyRing!"); } } @@ -89,4 +121,11 @@ public class UncachedKeyRing { return result; } + public void encodeArmored(OutputStream out, String version) throws IOException { + ArmoredOutputStream aos = new ArmoredOutputStream(out); + aos.setHeader("Version", version); + aos.write(mRing.getEncoded()); + aos.close(); + } + } 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 5dbe4b316..e3db03bf6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java @@ -13,6 +13,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.Iterator; import java.util.List; public class UncachedPublicKey { @@ -173,8 +174,24 @@ public class UncachedPublicKey { return mPublicKey.getFingerprint(); } - // Note that this method has package visibility - no access outside the pgp package! - PGPPublicKey getPublicKey() { + // TODO This method should have package visibility - no access outside the pgp package! + // (It's still used in ProviderHelper at this point) + public PGPPublicKey getPublicKey() { return mPublicKey; } + + public Iterator getSignaturesForId(String userId) { + final Iterator it = mPublicKey.getSignaturesForID(userId); + return new Iterator() { + public void remove() { + it.remove(); + } + public WrappedSignature next() { + return new WrappedSignature(it.next()); + } + public boolean hasNext() { + return it.hasNext(); + } + }; + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKeyRing.java index bda9ebbcf..ca784fbde 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKeyRing.java @@ -1,19 +1,33 @@ package org.sufficientlysecure.keychain.pgp; +import org.spongycastle.bcpg.S2K; +import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.util.IterableIterator; -public class UncachedSecretKeyRing { +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; - final PGPSecretKeyRing mSecretRing; +public class UncachedSecretKeyRing extends UncachedKeyRing { UncachedSecretKeyRing(PGPSecretKeyRing secretRing) { - mSecretRing = secretRing; + super(secretRing); } - // Breaking the pattern here, for key import! - // TODO reduce this from public to default visibility! - public PGPSecretKeyRing getSecretKeyRing() { - return mSecretRing; + public ArrayList getAvailableSubkeys() { + ArrayList result = new ArrayList(); + // then, mark exactly the keys we have available + for (PGPSecretKey sub : new IterableIterator( + ((PGPSecretKeyRing) mRing).getSecretKeys())) { + S2K s2k = sub.getS2K(); + // Set to 1, except if the encryption type is GNU_DUMMY_S2K + if(s2k == null || s2k.getType() != S2K.GNU_DUMMY_S2K) { + result.add(sub.getKeyID()); + } + } + return result; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java index 94eb91420..6e7b2a49e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java @@ -5,6 +5,9 @@ import org.spongycastle.openpgp.PGPPublicKey; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.util.IterableIterator; +import java.io.IOException; +import java.io.OutputStream; + public abstract class WrappedKeyRing extends KeyRing { private final boolean mHasAnySecret; @@ -76,6 +79,10 @@ public abstract class WrappedKeyRing extends KeyRing { } } + public void encode(OutputStream stream) throws IOException { + getRing().encode(stream); + } + abstract PGPKeyRing getRing(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java index c94b7dfba..656430969 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java @@ -120,4 +120,8 @@ public class WrappedSecretKeyRing extends WrappedKeyRing { }); } + public UncachedSecretKeyRing getUncached() { + return new UncachedSecretKeyRing(mRing); + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java index cdadbca7f..9f26439d2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java @@ -5,6 +5,7 @@ import org.spongycastle.bcpg.SignatureSubpacketTags; import org.spongycastle.bcpg.sig.RevocationReason; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPObjectFactory; +import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureList; import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; @@ -14,6 +15,7 @@ import org.sufficientlysecure.keychain.util.Log; import java.io.IOException; import java.security.SignatureException; +import java.util.Date; public class WrappedSignature { @@ -33,16 +35,57 @@ public class WrappedSignature { return mSig.getKeyID(); } + public int getSignatureType() { + return mSig.getSignatureType(); + } + public int getKeyAlgorithm() { return mSig.getKeyAlgorithm(); } + public Date getCreationTime() { + return mSig.getCreationTime(); + } + + public byte[] getEncoded() throws IOException { + return mSig.getEncoded(); + } + + public boolean isRevocation() { + return mSig.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.REVOCATION_REASON); + } + + public boolean isPrimaryUserId() { + return mSig.getHashedSubPackets().isPrimaryUserID(); + } + + public String getRevocationReason() throws PgpGeneralException { + if(!isRevocation()) { + throw new PgpGeneralException("Not a revocation signature."); + } + SignatureSubpacket p = mSig.getHashedSubPackets().getSubpacket( + SignatureSubpacketTags.REVOCATION_REASON); + // For some reason, this is missing in SignatureSubpacketInputStream:146 + if (!(p instanceof RevocationReason)) { + p = new RevocationReason(false, p.getData()); + } + return ((RevocationReason) p).getRevocationDescription(); + } + public void init(WrappedPublicKey key) throws PgpGeneralException { + init(key.getPublicKey()); + } + + public void init(UncachedPublicKey key) throws PgpGeneralException { + init(key.getPublicKey()); + } + + protected void init(PGPPublicKey key) throws PgpGeneralException { try { JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider() .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - mSig.init(contentVerifierBuilderProvider, key.getPublicKey()); + mSig.init(contentVerifierBuilderProvider, key); } catch(PGPException e) { throw new PgpGeneralException(e); } @@ -74,30 +117,9 @@ public class WrappedSignature { } } - public boolean isRevocation() { - return mSig.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.REVOCATION_REASON); - } - - public String getRevocationReason() throws PgpGeneralException { - if(!isRevocation()) { - throw new PgpGeneralException("Not a revocation signature."); - } - SignatureSubpacket p = mSig.getHashedSubPackets().getSubpacket( - SignatureSubpacketTags.REVOCATION_REASON); - // For some reason, this is missing in SignatureSubpacketInputStream:146 - if (!(p instanceof RevocationReason)) { - p = new RevocationReason(false, p.getData()); - } - return ((RevocationReason) p).getRevocationDescription(); - } - - /** 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(WrappedPublicKey key, String uid) throws PgpGeneralException { + protected boolean verifySignature(PGPPublicKey key, String uid) throws PgpGeneralException { try { - return mSig.verifyCertification(uid, key.getPublicKey()); + return mSig.verifyCertification(uid, key); } catch (SignatureException e) { throw new PgpGeneralException("Error!", e); } catch (PGPException e) { @@ -105,6 +127,13 @@ public class WrappedSignature { } } + public boolean verifySignature(UncachedPublicKey key, String uid) throws PgpGeneralException { + return verifySignature(key.getPublicKey(), uid); + } + public boolean verifySignature(WrappedPublicKey key, String uid) throws PgpGeneralException { + return verifySignature(key.getPublicKey(), uid); + } + public static WrappedSignature fromBytes(byte[] data) { PGPObjectFactory factory = new PGPObjectFactory(data); PGPSignatureList signatures = null; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index 68726d3e0..ed8171587 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -23,11 +23,9 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.provider.BaseColumns; -import org.spongycastle.openpgp.PGPKeyRing; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKeyRing; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; +import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAccountsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.CertsColumns; @@ -256,6 +254,8 @@ public class KeychainDatabase extends SQLiteOpenHelper { }.getReadableDatabase(); Cursor cursor = null; + ProviderHelper providerHelper = new ProviderHelper(context); + try { // we insert in two steps: first, all public keys that have secret keys cursor = db.rawQuery("SELECT key_ring_data FROM key_rings WHERE type = 1 OR EXISTS (" @@ -266,14 +266,11 @@ public class KeychainDatabase extends SQLiteOpenHelper { for (int i = 0; i < cursor.getCount(); i++) { cursor.moveToPosition(i); byte[] data = cursor.getBlob(0); - PGPKeyRing ring = PgpConversionHelper.BytesToPGPKeyRing(data); - ProviderHelper providerHelper = new ProviderHelper(context); - if (ring instanceof PGPPublicKeyRing) - providerHelper.saveKeyRing((PGPPublicKeyRing) ring); - else if (ring instanceof PGPSecretKeyRing) - providerHelper.saveKeyRing((PGPSecretKeyRing) ring); - else { - Log.e(Constants.TAG, "Unknown blob data type!"); + try { + UncachedKeyRing ring = UncachedKeyRing.decodeFromData(data); + providerHelper.saveKeyRing(ring); + } catch(PgpGeneralException e) { + Log.e(Constants.TAG, "Error decoding keyring blob!"); } } } @@ -293,14 +290,11 @@ public class KeychainDatabase extends SQLiteOpenHelper { for (int i = 0; i < cursor.getCount(); i++) { cursor.moveToPosition(i); byte[] data = cursor.getBlob(0); - PGPKeyRing ring = PgpConversionHelper.BytesToPGPKeyRing(data); - ProviderHelper providerHelper = new ProviderHelper(context); - if (ring instanceof PGPPublicKeyRing) { - providerHelper.saveKeyRing((PGPPublicKeyRing) ring); - } else if (ring instanceof PGPSecretKeyRing) { - providerHelper.saveKeyRing((PGPSecretKeyRing) ring); - } else { - Log.e(Constants.TAG, "Unknown blob data type!"); + try { + UncachedKeyRing ring = UncachedKeyRing.decodeFromData(data); + providerHelper.saveKeyRing(ring); + } catch(PgpGeneralException e) { + Log.e(Constants.TAG, "Error decoding keyring blob!"); } } } 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 67d11f9f0..b6f75e00d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -23,30 +23,21 @@ import android.content.ContentValues; import android.content.Context; import android.content.OperationApplicationException; import android.database.Cursor; -import android.database.DatabaseUtils; import android.net.Uri; import android.os.RemoteException; import android.support.v4.util.LongSparseArray; -import org.spongycastle.bcpg.ArmoredOutputStream; -import org.spongycastle.bcpg.S2K; -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPKeyRing; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.spongycastle.openpgp.PGPSignature; -import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.UncachedPublicKey; import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing; -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.pgp.WrappedSignature; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; @@ -60,7 +51,6 @@ import org.sufficientlysecure.keychain.util.Log; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.security.SignatureException; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -147,19 +137,26 @@ public class ProviderHelper { return getGenericData(KeyRings.buildUnifiedKeyRingUri(masterKeyId), proj, types); } - @Deprecated - public LongSparseArray getPGPKeyRings(Uri queryUri) { + private LongSparseArray getUncachedMasterKeys(Uri queryUri) { Cursor cursor = mContentResolver.query(queryUri, new String[]{KeyRingData.MASTER_KEY_ID, KeyRingData.KEY_RING_DATA}, null, null, null); - LongSparseArray result = new LongSparseArray(cursor.getCount()); + LongSparseArray result = + new LongSparseArray(cursor.getCount()); try { if (cursor != null && cursor.moveToFirst()) do { long masterKeyId = cursor.getLong(0); byte[] data = cursor.getBlob(1); if (data != null) { - result.put(masterKeyId, PgpConversionHelper.BytesToPGPKeyRing(data)); + try { + result.put(masterKeyId, + UncachedKeyRing.decodePubkeyFromData(data).getPublicKey()); + } catch(PgpGeneralException e) { + Log.e(Constants.TAG, "Error parsing keyring, skipping."); + } catch(IOException e) { + Log.e(Constants.TAG, "IO error, skipping keyring"); + } } } while (cursor.moveToNext()); } finally { @@ -194,12 +191,13 @@ public class ProviderHelper { private KeyRing getWrappedKeyRing(Uri queryUri, boolean secret) throws NotFoundException { Cursor cursor = mContentResolver.query(queryUri, - new String[] { - // we pick from cache only information that is not easily available from keyrings - KeyRings.HAS_ANY_SECRET, KeyRings.VERIFIED, - // and of course, ring data - secret ? KeyRings.PRIVKEY_DATA : KeyRings.PUBKEY_DATA - }, null, null, null); + new String[]{ + // we pick from cache only information that is not easily available from keyrings + KeyRings.HAS_ANY_SECRET, KeyRings.VERIFIED, + // and of course, ring data + secret ? KeyRings.PRIVKEY_DATA : KeyRings.PUBKEY_DATA + }, null, null, null + ); try { if (cursor != null && cursor.moveToFirst()) { @@ -219,37 +217,18 @@ public class ProviderHelper { } } - @Deprecated - public PGPKeyRing getPGPKeyRing(Uri queryUri) throws NotFoundException { - LongSparseArray result = getPGPKeyRings(queryUri); - if (result.size() == 0) { - throw new NotFoundException("PGPKeyRing object not found!"); - } else { - return result.valueAt(0); - } - } - - /** - * Retrieves the actual PGPSecretKeyRing object from the database blob based on the maserKeyId - */ - @Deprecated - public PGPSecretKeyRing getPGPSecretKeyRing(long masterKeyId) throws NotFoundException { - Uri queryUri = KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId)); - return (PGPSecretKeyRing) getPGPKeyRing(queryUri); - } - /** * Saves PGPPublicKeyRing with its keys and userIds in DB */ @SuppressWarnings("unchecked") - public void saveKeyRing(PGPPublicKeyRing keyRing) throws IOException { - PGPPublicKey masterKey = keyRing.getPublicKey(); - long masterKeyId = masterKey.getKeyID(); + public void saveKeyRing(UncachedKeyRing keyRing) throws IOException { + UncachedPublicKey masterKey = keyRing.getPublicKey(); + long masterKeyId = masterKey.getKeyId(); // IF there is a secret key, preserve it! - PGPSecretKeyRing secretRing = null; + UncachedSecretKeyRing secretRing = null; try { - secretRing = getPGPSecretKeyRing(masterKeyId); + secretRing = getWrappedSecretKeyRing(masterKeyId).getUncached(); } catch (NotFoundException e) { Log.e(Constants.TAG, "key not found!"); } @@ -272,36 +251,38 @@ public class ProviderHelper { ArrayList operations = new ArrayList(); int rank = 0; - for (PGPPublicKey key : new IterableIterator(keyRing.getPublicKeys())) { + for (UncachedPublicKey key : new IterableIterator(keyRing.getPublicKeys())) { operations.add(buildPublicKeyOperations(masterKeyId, key, rank)); ++rank; } // get a list of owned secret keys, for verification filtering - LongSparseArray allKeyRings = getPGPKeyRings(KeyRingData.buildSecretKeyRingUri()); + LongSparseArray allKeyRings = + getUncachedMasterKeys(KeyRingData.buildSecretKeyRingUri()); // special case: available secret keys verify themselves! - if (secretRing != null) - allKeyRings.put(secretRing.getSecretKey().getKeyID(), secretRing); + if (secretRing != null) { + allKeyRings.put(secretRing.getMasterKeyId(), secretRing.getPublicKey()); + } // classify and order user ids. primary are moved to the front, revoked to the back, // otherwise the order in the keyfile is preserved. List uids = new ArrayList(); - for (String userId : new IterableIterator(masterKey.getUserIDs())) { + for (String userId : new IterableIterator( + masterKey.getUnorderedUserIds().iterator())) { UserIdItem item = new UserIdItem(); uids.add(item); item.userId = userId; // look through signatures for this specific key - for (PGPSignature cert : new IterableIterator( - masterKey.getSignaturesForID(userId))) { - long certId = cert.getKeyID(); + for (WrappedSignature cert : new IterableIterator( + masterKey.getSignaturesForId(userId))) { + long certId = cert.getKeyId(); try { // self signature if (certId == masterKeyId) { - cert.init(new JcaPGPContentVerifierBuilderProvider().setProvider( - Constants.BOUNCY_CASTLE_PROVIDER_NAME), masterKey); - if (!cert.verifyCertification(userId, masterKey)) { + cert.init(masterKey); + if (!cert.verifySignature(masterKey, userId)) { // not verified?! dang! TODO notify user? this is kinda serious... Log.e(Constants.TAG, "Could not verify self signature for " + userId + "!"); continue; @@ -310,31 +291,22 @@ public class ProviderHelper { if (item.selfCert == null || item.selfCert.getCreationTime().before(cert.getCreationTime())) { item.selfCert = cert; - item.isPrimary = cert.getHashedSubPackets().isPrimaryUserID(); - item.isRevoked = - cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION; + item.isPrimary = cert.isPrimaryUserId(); + item.isRevoked = cert.isRevocation(); } } // verify signatures from known private keys if (allKeyRings.indexOfKey(certId) >= 0) { - // mark them as verified - cert.init(new JcaPGPContentVerifierBuilderProvider().setProvider( - Constants.BOUNCY_CASTLE_PROVIDER_NAME), - allKeyRings.get(certId).getPublicKey()); - if (cert.verifyCertification(userId, masterKey)) { + cert.init(allKeyRings.get(certId)); + if (cert.verifySignature(masterKey, userId)) { item.trustedCerts.add(cert); } } - } catch (SignatureException e) { - Log.e(Constants.TAG, "Signature verification failed! " - + PgpKeyHelper.convertKeyIdToHex(masterKey.getKeyID()) - + " from " - + PgpKeyHelper.convertKeyIdToHex(cert.getKeyID()), e); - } catch (PGPException e) { + } catch (PgpGeneralException e) { Log.e(Constants.TAG, "Signature verification failed! " - + PgpKeyHelper.convertKeyIdToHex(masterKey.getKeyID()) + + PgpKeyHelper.convertKeyIdToHex(masterKey.getKeyId()) + " from " - + PgpKeyHelper.convertKeyIdToHex(cert.getKeyID()), e); + + PgpKeyHelper.convertKeyIdToHex(cert.getKeyId()), e); } } } @@ -380,8 +352,8 @@ public class ProviderHelper { String userId; boolean isPrimary = false; boolean isRevoked = false; - PGPSignature selfCert; - List trustedCerts = new ArrayList(); + WrappedSignature selfCert; + List trustedCerts = new ArrayList(); @Override public int compareTo(UserIdItem o) { @@ -401,18 +373,8 @@ 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.getSecretKey().getKeyID(); + public void saveKeyRing(UncachedSecretKeyRing keyRing) throws IOException { + long masterKeyId = keyRing.getMasterKeyId(); { Uri uri = Keys.buildKeysUri(Long.toString(masterKeyId)); @@ -424,14 +386,10 @@ public class ProviderHelper { values.put(Keys.HAS_SECRET, 1); // then, mark exactly the keys we have available - for (PGPSecretKey sub : new IterableIterator(keyRing.getSecretKeys())) { - S2K s2k = sub.getS2K(); - // Set to 1, except if the encryption type is GNU_DUMMY_S2K - if(s2k == null || s2k.getType() != S2K.GNU_DUMMY_S2K) { - mContentResolver.update(uri, values, Keys.KEY_ID + " = ?", new String[]{ - Long.toString(sub.getKeyID()) - }); - } + for (Long sub : new IterableIterator(keyRing.getAvailableSubkeys().iterator())) { + mContentResolver.update(uri, values, Keys.KEY_ID + " = ?", new String[] { + Long.toString(sub) + }); } // this implicitly leaves all keys which were not in the secret key ring // with has_secret = 0 @@ -449,11 +407,6 @@ public class ProviderHelper { } - public void saveKeyRing(UncachedKeyRing ring) throws IOException { - PGPPublicKeyRing pubRing = (PGPPublicKeyRing) ring.getRing(); - saveKeyRing(pubRing); - } - /** * Saves (or updates) a pair of public and secret KeyRings in the database */ @@ -464,32 +417,32 @@ public class ProviderHelper { mContentResolver.delete(KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId)), null, null); // save public keyring - saveKeyRing((PGPPublicKeyRing) pubRing.getRing()); - saveKeyRing((PGPSecretKeyRing) secRing.getRing()); + saveKeyRing(pubRing); + saveKeyRing(secRing); } /** * Build ContentProviderOperation to add PGPPublicKey to database corresponding to a keyRing */ private ContentProviderOperation - buildPublicKeyOperations(long masterKeyId, PGPPublicKey key, int rank) throws IOException { + buildPublicKeyOperations(long masterKeyId, UncachedPublicKey key, int rank) throws IOException { ContentValues values = new ContentValues(); values.put(Keys.MASTER_KEY_ID, masterKeyId); values.put(Keys.RANK, rank); - values.put(Keys.KEY_ID, key.getKeyID()); + values.put(Keys.KEY_ID, key.getKeyId()); values.put(Keys.KEY_SIZE, key.getBitStrength()); values.put(Keys.ALGORITHM, key.getAlgorithm()); values.put(Keys.FINGERPRINT, key.getFingerprint()); - values.put(Keys.CAN_CERTIFY, (PgpKeyHelper.isCertificationKey(key))); - values.put(Keys.CAN_SIGN, (PgpKeyHelper.isSigningKey(key))); - values.put(Keys.CAN_ENCRYPT, PgpKeyHelper.isEncryptionKey(key)); - values.put(Keys.IS_REVOKED, key.isRevoked()); + values.put(Keys.CAN_CERTIFY, key.canCertify()); + values.put(Keys.CAN_SIGN, key.canSign()); + values.put(Keys.CAN_ENCRYPT, key.canEncrypt()); + values.put(Keys.IS_REVOKED, key.maybeRevoked()); - values.put(Keys.CREATION, PgpKeyHelper.getCreationDate(key).getTime() / 1000); - Date expiryDate = PgpKeyHelper.getExpiryDate(key); + values.put(Keys.CREATION, key.getCreationTime().getTime() / 1000); + Date expiryDate = key.getExpiryTime(); if (expiryDate != null) { values.put(Keys.EXPIRY, expiryDate.getTime() / 1000); } @@ -503,11 +456,12 @@ public class ProviderHelper { * Build ContentProviderOperation to add PGPPublicKey to database corresponding to a keyRing */ private ContentProviderOperation - buildCertOperations(long masterKeyId, int rank, PGPSignature cert, int verified) throws IOException { + buildCertOperations(long masterKeyId, int rank, WrappedSignature cert, int verified) + throws IOException { ContentValues values = new ContentValues(); values.put(Certs.MASTER_KEY_ID, masterKeyId); values.put(Certs.RANK, rank); - values.put(Certs.KEY_ID_CERTIFIER, cert.getKeyID()); + values.put(Certs.KEY_ID_CERTIFIER, cert.getKeyId()); values.put(Certs.TYPE, cert.getSignatureType()); values.put(Certs.CREATION, cert.getCreationTime().getTime() / 1000); values.put(Certs.VERIFIED, verified); @@ -535,23 +489,11 @@ public class ProviderHelper { return ContentProviderOperation.newInsert(uri).withValues(values).build(); } - private String getKeyRingAsArmoredString(byte[] data) throws IOException { - Object keyRing = null; - if (data != null) { - keyRing = PgpConversionHelper.BytesToPGPKeyRing(data); - } + private String getKeyRingAsArmoredString(byte[] data) throws IOException, PgpGeneralException { + UncachedKeyRing keyRing = UncachedKeyRing.decodeFromData(data); ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ArmoredOutputStream aos = new ArmoredOutputStream(bos); - aos.setHeader("Version", PgpHelper.getFullVersion(mContext)); - - if (keyRing instanceof PGPSecretKeyRing) { - aos.write(((PGPSecretKeyRing) keyRing).getEncoded()); - } else if (keyRing instanceof PGPPublicKeyRing) { - aos.write(((PGPPublicKeyRing) keyRing).getEncoded()); - } - aos.close(); - + keyRing.encodeArmored(bos, PgpHelper.getFullVersion(mContext)); String armoredKey = bos.toString("UTF-8"); Log.d(Constants.TAG, "armoredKey:" + armoredKey); @@ -560,77 +502,12 @@ public class ProviderHelper { } public String getKeyRingAsArmoredString(Uri uri) - throws NotFoundException, IOException { + throws NotFoundException, IOException, PgpGeneralException { byte[] data = (byte[]) getGenericData( uri, KeyRingData.KEY_RING_DATA, ProviderHelper.FIELD_TYPE_BLOB); return getKeyRingAsArmoredString(data); } - /** - * TODO: currently not used, but will be needed to upload many keys at once! - * - * @param masterKeyIds - * @return - * @throws IOException - */ - public ArrayList getKeyRingsAsArmoredString(long[] masterKeyIds) - throws IOException { - ArrayList output = new ArrayList(); - - if (masterKeyIds == null || masterKeyIds.length == 0) { - Log.e(Constants.TAG, "No master keys given!"); - return output; - } - - // Build a cursor for the selected masterKeyIds - Cursor cursor; - { - String inMasterKeyList = KeyRingData.MASTER_KEY_ID + " IN ("; - for (int i = 0; i < masterKeyIds.length; ++i) { - if (i != 0) { - inMasterKeyList += ", "; - } - inMasterKeyList += DatabaseUtils.sqlEscapeString("" + masterKeyIds[i]); - } - inMasterKeyList += ")"; - - cursor = mContentResolver.query(KeyRingData.buildPublicKeyRingUri(), new String[]{ - KeyRingData._ID, KeyRingData.MASTER_KEY_ID, KeyRingData.KEY_RING_DATA - }, inMasterKeyList, null, null); - } - - try { - if (cursor != null) { - int masterIdCol = cursor.getColumnIndex(KeyRingData.MASTER_KEY_ID); - int dataCol = cursor.getColumnIndex(KeyRingData.KEY_RING_DATA); - if (cursor.moveToFirst()) { - do { - Log.d(Constants.TAG, "masterKeyId: " + cursor.getLong(masterIdCol)); - - byte[] data = cursor.getBlob(dataCol); - - // get actual keyring data blob and write it to ByteArrayOutputStream - try { - output.add(getKeyRingAsArmoredString(data)); - } catch (IOException e) { - Log.e(Constants.TAG, "IOException", e); - } - } while (cursor.moveToNext()); - } - } - } finally { - if (cursor != null) { - cursor.close(); - } - } - - if (output.size() > 0) { - return output; - } else { - return null; - } - } - public ArrayList getRegisteredApiApps() { Cursor cursor = mContentResolver.query(ApiApps.CONTENT_URI, null, null, null, null); 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 c2fc4334a..69eab9d4e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -26,16 +26,13 @@ import android.os.Message; 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.PGPUtil; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; +import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.WrappedSecretKey; import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing; @@ -594,21 +591,21 @@ public class KeychainIntentService extends IntentService buf = keyOperations.createKey(Constants.choice.algorithm.rsa, 4096, passphrase, true); os.write(buf); - keyUsageList.add(KeyFlags.CERTIFY_OTHER); + keyUsageList.add(UncachedSecretKey.CERTIFY_OTHER); keysCreated++; setProgress(keysCreated, keysTotal); buf = keyOperations.createKey(Constants.choice.algorithm.rsa, 4096, passphrase, false); os.write(buf); - keyUsageList.add(KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE); + keyUsageList.add(UncachedSecretKey.ENCRYPT_COMMS | UncachedSecretKey.ENCRYPT_STORAGE); keysCreated++; setProgress(keysCreated, keysTotal); buf = keyOperations.createKey(Constants.choice.algorithm.rsa, 4096, passphrase, false); os.write(buf); - keyUsageList.add(KeyFlags.SIGN_DATA); + keyUsageList.add(UncachedSecretKey.SIGN_DATA); keysCreated++; setProgress(keysCreated, keysTotal); @@ -749,23 +746,15 @@ public class KeychainIntentService extends IntentService byte[] downloadedKeyBytes = server.get(keybaseId).getBytes(); // create PGPKeyRing object based on downloaded armored key - PGPKeyRing downloadedKey = null; + UncachedKeyRing 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) { - - if (obj instanceof PGPKeyRing) { - downloadedKey = (PGPKeyRing) obj; - } else { - throw new PgpGeneralException("Object not recognized as PGPKeyRing!"); - } + List rings = UncachedKeyRing.fromStream(bufferedInput); + if(rings.isEmpty()) { + throw new PgpGeneralException("No keys in result!"); } + downloadedKey = rings.get(0); } // save key bytes in entry object for doing the diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index 17ba9df5c..d42bae67a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -34,12 +34,6 @@ import android.os.Messenger; import android.os.RemoteException; import android.support.v4.util.LongSparseArray; -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPPrivateKey; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; -import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing; @@ -48,7 +42,6 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.Log; import java.util.Date; -import java.util.Iterator; /** * This service runs in its own process, but is available to all other processes as the main @@ -191,7 +184,8 @@ public class PassphraseCacheService extends Service { // get cached passphrase String cachedPassphrase = mPassphraseCache.get(keyId); if (cachedPassphrase == null) { - // this is an error + Log.d(TAG, "Passphrase not (yet) cached, returning null"); + // not really an error, just means the passphrase is not cached but not empty either return null; } @@ -206,44 +200,6 @@ public class PassphraseCacheService extends Service { } } - @Deprecated - public static boolean hasPassphrase(PGPSecretKeyRing secretKeyRing) { - PGPSecretKey secretKey = null; - boolean foundValidKey = false; - for (Iterator keys = secretKeyRing.getSecretKeys(); keys.hasNext(); ) { - secretKey = (PGPSecretKey) keys.next(); - if (!secretKey.isPrivateKeyEmpty()) { - foundValidKey = true; - break; - } - } - if(!foundValidKey) { - return false; - } - - try { - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() - .setProvider("SC").build("".toCharArray()); - PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor); - return testKey == null; - } catch(PGPException e) { - // this means the crc check failed -> passphrase required - return true; - } - } - - /** - * Checks if key has a passphrase. - * - * @param secretKeyId - * @return true if it has a passphrase - */ - @Deprecated - public static boolean hasPassphrase(Context context, long secretKeyId) - throws ProviderHelper.NotFoundException { - return new ProviderHelper(context).getWrappedSecretKeyRing(secretKeyId).hasPassphrase(); - } - /** * Register BroadcastReceiver that is unregistered when service is destroyed. This * BroadcastReceiver hears on intents with ACTION_PASSPHRASE_CACHE_SERVICE to then timeout diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index fffcdacc8..3514ab2e5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -13,7 +13,8 @@ import java.util.HashMap; * * All changes are done in a differential manner. Besides the two key * identification attributes, all attributes may be null, which indicates no - * change to the keyring. + * change to the keyring. This is also the reason why boxed values are used + * instead of primitives in the subclasses. * * Application of operations in the backend should be fail-fast, which means an * error in any included operation (for example revocation of a non-existent @@ -45,10 +46,12 @@ public class SaveKeyringParcel implements Parcelable { // performance gain for using Parcelable here would probably be negligible, // use Serializable instead. public static class SubkeyAdd implements Serializable { + public final int mAlgorithm; public final int mKeysize; public final int mFlags; public final Long mExpiry; - public SubkeyAdd(int keysize, int flags, long expiry) { + public SubkeyAdd(int algorithm, int keysize, int flags, Long expiry) { + mAlgorithm = algorithm; mKeysize = keysize; mFlags = flags; mExpiry = expiry; @@ -59,7 +62,7 @@ public class SaveKeyringParcel implements Parcelable { public final long mKeyId; public final Integer mFlags; public final Long mExpiry; - public SubkeyChange(long keyId, int flags, long expiry) { + public SubkeyChange(long keyId, Integer flags, Long expiry) { mKeyId = keyId; mFlags = flags; mExpiry = expiry; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java index b3655133d..a264a804f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java @@ -41,6 +41,7 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; @@ -190,6 +191,9 @@ public class ViewKeyShareFragment extends LoaderFragment implements } startActivity(Intent.createChooser(sendIntent, title)); } + } catch (PgpGeneralException e) { + Log.e(Constants.TAG, "error processing key!", e); + AppMsg.makeText(getActivity(), R.string.error_key_processing, AppMsg.STYLE_ALERT).show(); } catch (IOException e) { Log.e(Constants.TAG, "error processing key!", e); AppMsg.makeText(getActivity(), R.string.error_key_processing, AppMsg.STYLE_ALERT).show(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java index e7bcd2bc0..5f47ee13c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java @@ -102,7 +102,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor // check if secret key has a passphrase if (!(secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none)) { try { - if (new ProviderHelper(context).getWrappedSecretKeyRing(secretKeyId).hasPassphrase()) { + if (!new ProviderHelper(context).getWrappedSecretKeyRing(secretKeyId).hasPassphrase()) { throw new PgpGeneralException("No passphrase! No passphrase dialog needed!"); } } catch(ProviderHelper.NotFoundException e) { -- cgit v1.2.3 From 6d1369be56af0d61678d1632fd98f7a4ff41b11f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 31 May 2014 20:49:56 +0200 Subject: Pull from transifex --- OpenKeychain/src/main/res/raw-ar/help_about.html | 50 +++ .../src/main/res/raw-ar/help_changelog.html | 156 +++++++ .../src/main/res/raw-ar/help_nfc_beam.html | 12 + OpenKeychain/src/main/res/raw-ar/help_start.html | 22 + OpenKeychain/src/main/res/raw-ar/help_wot.html | 17 + .../src/main/res/raw-ar/nfc_beam_share.html | 11 + .../src/main/res/raw-cs-rCZ/help_about.html | 49 --- .../src/main/res/raw-cs-rCZ/help_changelog.html | 156 ------- .../src/main/res/raw-cs-rCZ/help_nfc_beam.html | 12 - .../src/main/res/raw-cs-rCZ/help_start.html | 24 -- .../src/main/res/raw-cs-rCZ/nfc_beam_share.html | 11 - OpenKeychain/src/main/res/raw-cs/help_about.html | 50 +++ .../src/main/res/raw-cs/help_changelog.html | 156 +++++++ .../src/main/res/raw-cs/help_nfc_beam.html | 12 + OpenKeychain/src/main/res/raw-cs/help_start.html | 22 + OpenKeychain/src/main/res/raw-cs/help_wot.html | 17 + .../src/main/res/raw-cs/nfc_beam_share.html | 11 + OpenKeychain/src/main/res/raw-de/help_about.html | 3 +- .../src/main/res/raw-de/help_changelog.html | 92 ++-- .../src/main/res/raw-de/help_nfc_beam.html | 10 +- OpenKeychain/src/main/res/raw-de/help_start.html | 22 + OpenKeychain/src/main/res/raw-de/help_wot.html | 17 + .../src/main/res/raw-de/nfc_beam_share.html | 8 +- OpenKeychain/src/main/res/raw-el/help_about.html | 1 + OpenKeychain/src/main/res/raw-el/help_start.html | 6 +- OpenKeychain/src/main/res/raw-el/help_wot.html | 17 + OpenKeychain/src/main/res/raw-es/help_about.html | 1 + .../src/main/res/raw-es/help_changelog.html | 8 +- OpenKeychain/src/main/res/raw-es/help_start.html | 6 +- OpenKeychain/src/main/res/raw-es/help_wot.html | 17 + OpenKeychain/src/main/res/raw-et/help_about.html | 1 + OpenKeychain/src/main/res/raw-et/help_start.html | 6 +- OpenKeychain/src/main/res/raw-et/help_wot.html | 17 + .../src/main/res/raw-fa-rIR/help_about.html | 49 --- .../src/main/res/raw-fa-rIR/help_changelog.html | 156 ------- .../src/main/res/raw-fa-rIR/help_nfc_beam.html | 12 - .../src/main/res/raw-fa-rIR/help_start.html | 24 -- .../src/main/res/raw-fa-rIR/nfc_beam_share.html | 11 - OpenKeychain/src/main/res/raw-fr/help_about.html | 1 + .../src/main/res/raw-fr/help_changelog.html | 10 +- OpenKeychain/src/main/res/raw-fr/help_start.html | 6 +- OpenKeychain/src/main/res/raw-fr/help_wot.html | 17 + .../src/main/res/raw-it-rIT/help_about.html | 49 --- .../src/main/res/raw-it-rIT/help_changelog.html | 156 ------- .../src/main/res/raw-it-rIT/help_nfc_beam.html | 12 - .../src/main/res/raw-it-rIT/help_start.html | 24 -- .../src/main/res/raw-it-rIT/nfc_beam_share.html | 11 - OpenKeychain/src/main/res/raw-it/help_about.html | 50 +++ .../src/main/res/raw-it/help_changelog.html | 156 +++++++ .../src/main/res/raw-it/help_nfc_beam.html | 12 + OpenKeychain/src/main/res/raw-it/help_start.html | 22 + OpenKeychain/src/main/res/raw-it/help_wot.html | 17 + .../src/main/res/raw-it/nfc_beam_share.html | 11 + OpenKeychain/src/main/res/raw-ja/help_about.html | 1 + .../src/main/res/raw-ja/help_changelog.html | 8 +- OpenKeychain/src/main/res/raw-ja/help_start.html | 8 +- OpenKeychain/src/main/res/raw-ja/help_wot.html | 17 + OpenKeychain/src/main/res/raw-ko/help_about.html | 1 + OpenKeychain/src/main/res/raw-ko/help_start.html | 6 +- OpenKeychain/src/main/res/raw-ko/help_wot.html | 17 + .../src/main/res/raw-nl-rNL/help_about.html | 49 --- .../src/main/res/raw-nl-rNL/help_changelog.html | 156 ------- .../src/main/res/raw-nl-rNL/help_nfc_beam.html | 12 - .../src/main/res/raw-nl-rNL/help_start.html | 24 -- .../src/main/res/raw-nl-rNL/nfc_beam_share.html | 11 - OpenKeychain/src/main/res/raw-nl/help_about.html | 50 +++ .../src/main/res/raw-nl/help_changelog.html | 156 +++++++ .../src/main/res/raw-nl/help_nfc_beam.html | 12 + OpenKeychain/src/main/res/raw-nl/help_start.html | 22 + OpenKeychain/src/main/res/raw-nl/help_wot.html | 17 + .../src/main/res/raw-nl/nfc_beam_share.html | 11 + OpenKeychain/src/main/res/raw-pl/help_about.html | 1 + .../src/main/res/raw-pl/help_changelog.html | 2 +- OpenKeychain/src/main/res/raw-pl/help_start.html | 6 +- OpenKeychain/src/main/res/raw-pl/help_wot.html | 17 + OpenKeychain/src/main/res/raw-ru/help_about.html | 1 + .../src/main/res/raw-ru/help_changelog.html | 10 +- OpenKeychain/src/main/res/raw-ru/help_start.html | 8 +- OpenKeychain/src/main/res/raw-ru/help_wot.html | 17 + OpenKeychain/src/main/res/raw-sl/help_about.html | 1 + .../src/main/res/raw-sl/help_changelog.html | 10 +- OpenKeychain/src/main/res/raw-sl/help_start.html | 6 +- OpenKeychain/src/main/res/raw-sl/help_wot.html | 17 + OpenKeychain/src/main/res/raw-tr/help_about.html | 1 + OpenKeychain/src/main/res/raw-tr/help_start.html | 6 +- OpenKeychain/src/main/res/raw-tr/help_wot.html | 17 + OpenKeychain/src/main/res/raw-uk/help_about.html | 1 + .../src/main/res/raw-uk/help_changelog.html | 14 +- OpenKeychain/src/main/res/raw-uk/help_start.html | 8 +- OpenKeychain/src/main/res/raw-uk/help_wot.html | 17 + OpenKeychain/src/main/res/raw-zh/help_about.html | 1 + OpenKeychain/src/main/res/raw-zh/help_start.html | 6 +- OpenKeychain/src/main/res/raw-zh/help_wot.html | 17 + .../src/main/res/raw-zh/nfc_beam_share.html | 2 +- OpenKeychain/src/main/res/values-ar/strings.xml | 31 ++ .../src/main/res/values-cs-rCZ/strings.xml | 48 --- OpenKeychain/src/main/res/values-cs/strings.xml | 31 ++ OpenKeychain/src/main/res/values-de/strings.xml | 7 +- OpenKeychain/src/main/res/values-es/strings.xml | 6 +- .../src/main/res/values-fa-rIR/strings.xml | 31 -- OpenKeychain/src/main/res/values-fr/strings.xml | 6 +- .../src/main/res/values-it-rIT/strings.xml | 475 --------------------- OpenKeychain/src/main/res/values-it/strings.xml | 474 ++++++++++++++++++++ OpenKeychain/src/main/res/values-ja/strings.xml | 6 +- .../src/main/res/values-nl-rNL/strings.xml | 198 --------- OpenKeychain/src/main/res/values-nl/strings.xml | 474 ++++++++++++++++++++ OpenKeychain/src/main/res/values-pl/strings.xml | 3 - OpenKeychain/src/main/res/values-ru/strings.xml | 56 ++- OpenKeychain/src/main/res/values-sl/strings.xml | 5 +- OpenKeychain/src/main/res/values-uk/strings.xml | 68 ++- 110 files changed, 2587 insertions(+), 1922 deletions(-) create mode 100644 OpenKeychain/src/main/res/raw-ar/help_about.html create mode 100644 OpenKeychain/src/main/res/raw-ar/help_changelog.html create mode 100644 OpenKeychain/src/main/res/raw-ar/help_nfc_beam.html create mode 100644 OpenKeychain/src/main/res/raw-ar/help_start.html create mode 100644 OpenKeychain/src/main/res/raw-ar/help_wot.html create mode 100644 OpenKeychain/src/main/res/raw-ar/nfc_beam_share.html delete mode 100644 OpenKeychain/src/main/res/raw-cs-rCZ/help_about.html delete mode 100644 OpenKeychain/src/main/res/raw-cs-rCZ/help_changelog.html delete mode 100644 OpenKeychain/src/main/res/raw-cs-rCZ/help_nfc_beam.html delete mode 100644 OpenKeychain/src/main/res/raw-cs-rCZ/help_start.html delete mode 100644 OpenKeychain/src/main/res/raw-cs-rCZ/nfc_beam_share.html create mode 100644 OpenKeychain/src/main/res/raw-cs/help_about.html create mode 100644 OpenKeychain/src/main/res/raw-cs/help_changelog.html create mode 100644 OpenKeychain/src/main/res/raw-cs/help_nfc_beam.html create mode 100644 OpenKeychain/src/main/res/raw-cs/help_start.html create mode 100644 OpenKeychain/src/main/res/raw-cs/help_wot.html create mode 100644 OpenKeychain/src/main/res/raw-cs/nfc_beam_share.html create mode 100644 OpenKeychain/src/main/res/raw-de/help_start.html create mode 100644 OpenKeychain/src/main/res/raw-de/help_wot.html create mode 100644 OpenKeychain/src/main/res/raw-el/help_wot.html create mode 100644 OpenKeychain/src/main/res/raw-es/help_wot.html create mode 100644 OpenKeychain/src/main/res/raw-et/help_wot.html delete mode 100644 OpenKeychain/src/main/res/raw-fa-rIR/help_about.html delete mode 100644 OpenKeychain/src/main/res/raw-fa-rIR/help_changelog.html delete mode 100644 OpenKeychain/src/main/res/raw-fa-rIR/help_nfc_beam.html delete mode 100644 OpenKeychain/src/main/res/raw-fa-rIR/help_start.html delete mode 100644 OpenKeychain/src/main/res/raw-fa-rIR/nfc_beam_share.html create mode 100644 OpenKeychain/src/main/res/raw-fr/help_wot.html delete mode 100644 OpenKeychain/src/main/res/raw-it-rIT/help_about.html delete mode 100644 OpenKeychain/src/main/res/raw-it-rIT/help_changelog.html delete mode 100644 OpenKeychain/src/main/res/raw-it-rIT/help_nfc_beam.html delete mode 100644 OpenKeychain/src/main/res/raw-it-rIT/help_start.html delete mode 100644 OpenKeychain/src/main/res/raw-it-rIT/nfc_beam_share.html create mode 100644 OpenKeychain/src/main/res/raw-it/help_about.html create mode 100644 OpenKeychain/src/main/res/raw-it/help_changelog.html create mode 100644 OpenKeychain/src/main/res/raw-it/help_nfc_beam.html create mode 100644 OpenKeychain/src/main/res/raw-it/help_start.html create mode 100644 OpenKeychain/src/main/res/raw-it/help_wot.html create mode 100644 OpenKeychain/src/main/res/raw-it/nfc_beam_share.html create mode 100644 OpenKeychain/src/main/res/raw-ja/help_wot.html create mode 100644 OpenKeychain/src/main/res/raw-ko/help_wot.html delete mode 100644 OpenKeychain/src/main/res/raw-nl-rNL/help_about.html delete mode 100644 OpenKeychain/src/main/res/raw-nl-rNL/help_changelog.html delete mode 100644 OpenKeychain/src/main/res/raw-nl-rNL/help_nfc_beam.html delete mode 100644 OpenKeychain/src/main/res/raw-nl-rNL/help_start.html delete mode 100644 OpenKeychain/src/main/res/raw-nl-rNL/nfc_beam_share.html create mode 100644 OpenKeychain/src/main/res/raw-nl/help_about.html create mode 100644 OpenKeychain/src/main/res/raw-nl/help_changelog.html create mode 100644 OpenKeychain/src/main/res/raw-nl/help_nfc_beam.html create mode 100644 OpenKeychain/src/main/res/raw-nl/help_start.html create mode 100644 OpenKeychain/src/main/res/raw-nl/help_wot.html create mode 100644 OpenKeychain/src/main/res/raw-nl/nfc_beam_share.html create mode 100644 OpenKeychain/src/main/res/raw-pl/help_wot.html create mode 100644 OpenKeychain/src/main/res/raw-ru/help_wot.html create mode 100644 OpenKeychain/src/main/res/raw-sl/help_wot.html create mode 100644 OpenKeychain/src/main/res/raw-tr/help_wot.html create mode 100644 OpenKeychain/src/main/res/raw-uk/help_wot.html create mode 100644 OpenKeychain/src/main/res/raw-zh/help_wot.html create mode 100644 OpenKeychain/src/main/res/values-ar/strings.xml delete mode 100644 OpenKeychain/src/main/res/values-cs-rCZ/strings.xml create mode 100644 OpenKeychain/src/main/res/values-cs/strings.xml delete mode 100644 OpenKeychain/src/main/res/values-fa-rIR/strings.xml delete mode 100644 OpenKeychain/src/main/res/values-it-rIT/strings.xml create mode 100644 OpenKeychain/src/main/res/values-it/strings.xml delete mode 100644 OpenKeychain/src/main/res/values-nl-rNL/strings.xml create mode 100644 OpenKeychain/src/main/res/values-nl/strings.xml (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/res/raw-ar/help_about.html b/OpenKeychain/src/main/res/raw-ar/help_about.html new file mode 100644 index 000000000..ab3c19375 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-ar/help_about.html @@ -0,0 +1,50 @@ + + + +

http://www.openkeychain.org

+

OpenKeychain is an OpenPGP implementation for Android.

+

License: GPLv3+

+ +

Developers OpenKeychain

+
    +
  • Dominik Schürmann (Lead developer)
  • +
  • Ash Hughes (crypto patches)
  • +
  • Brian C. Barnes
  • +
  • Bahtiar 'kalkin' Gadimov (UI)
  • +
  • Daniel Hammann
  • +
  • Daniel Haß
  • +
  • Greg Witczak
  • +
  • Miroojin Bakshi
  • +
  • Nikhil Peter Raj
  • +
  • Paul Sarbinowski
  • +
  • Sreeram Boyapati
  • +
  • Vincent Breitmoser
  • +
  • Tim Bray
  • +
+

Developers APG 1.x

+
    +
  • Thialfihar (Lead developer)
  • +
  • 'Senecaso' (QRCode, sign key, upload key)
  • +
  • Markus Doits
  • +
+

Libraries

+ + + diff --git a/OpenKeychain/src/main/res/raw-ar/help_changelog.html b/OpenKeychain/src/main/res/raw-ar/help_changelog.html new file mode 100644 index 000000000..ebada67f9 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-ar/help_changelog.html @@ -0,0 +1,156 @@ + + + +

2.7

+
    +
  • Purple! (Dominik, Vincent)
  • +
  • New key view design (Dominik, Vincent)
  • +
  • New flat Android buttons (Dominik, Vincent)
  • +
  • API fixes (Dominik)
  • +
  • Keybase.io import (Tim Bray)
  • +
+

2.6.1

+
    +
  • some fixes for regression bugs
  • +
+

2.6

+
    +
  • key certifications (thanks to Vincent Breitmoser)
  • +
  • support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
  • +
  • new design for signature verification
  • +
  • custom key length (thanks to Greg Witczak)
  • +
  • fix share-functionality from other apps
  • +
+

2.5

+
    +
  • fix decryption of symmetric pgp messages/files
  • +
  • refactored edit key screen (thanks to Ash Hughes)
  • +
  • new modern design for encrypt/decrypt screens
  • +
  • OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
  • +
+

2.4

+

Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free! +Besides several small patches, a notable number of patches are made by the following people (in alphabetical order): +Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.

+
    +
  • new unified key list
  • +
  • colorized key fingerprint
  • +
  • support for keyserver ports
  • +
  • deactivate possibility to generate weak keys
  • +
  • much more internal work on the API
  • +
  • certify user ids
  • +
  • keyserver query based on machine-readable output
  • +
  • lock navigation drawer on tablets
  • +
  • suggestions for emails on creation of keys
  • +
  • search in public key lists
  • +
  • and much more improvements and fixes…
  • +
+

2.3.1

+
    +
  • hotfix for crash when upgrading from old versions
  • +
+

2.3

+
    +
  • remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
  • +
  • fix setting expiry dates on keys (thanks to Ash Hughes)
  • +
  • more internal fixes when editing keys (thanks to Ash Hughes)
  • +
  • querying keyservers directly from the import screen
  • +
  • fix layout and dialog style on Android 2.2-3.0
  • +
  • fix crash on keys with empty user ids
  • +
  • fix crash and empty lists when coming back from signing screen
  • +
  • Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
  • +
  • fix upload of key from signing screen
  • +
+

2.2

+
    +
  • new design with navigation drawer
  • +
  • new public key list design
  • +
  • new public key view
  • +
  • bug fixes for importing of keys
  • +
  • key cross-certification (thanks to Ash Hughes)
  • +
  • handle UTF-8 passwords properly (thanks to Ash Hughes)
  • +
  • first version with new languages (thanks to the contributors on Transifex)
  • +
  • sharing of keys via QR Codes fixed and improved
  • +
  • package signature verification for API
  • +
+

2.1.1

+
    +
  • API Updates, preparation for K-9 Mail integration
  • +
+

2.1

+
    +
  • lots of bug fixes
  • +
  • new API for developers
  • +
  • PRNG bug fix by Google
  • +
+

2.0

+
    +
  • complete redesign
  • +
  • share public keys via qr codes, nfc beam
  • +
  • sign keys
  • +
  • upload keys to server
  • +
  • fixes import issues
  • +
  • new AIDL API
  • +
+

1.0.8

+
    +
  • basic keyserver support
  • +
  • app2sd
  • +
  • more choices for pass phrase cache: 1, 2, 4, 8, hours
  • +
  • translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
  • +
  • bugfixes
  • +
  • optimizations
  • +
+

1.0.7

+
    +
  • fixed problem with signature verification of texts with trailing newline
  • +
  • more options for pass phrase cache time to live (20, 40, 60 mins)
  • +
+

1.0.6

+
    +
  • account adding crash on Froyo fixed
  • +
  • secure file deletion
  • +
  • option to delete key file after import
  • +
  • stream encryption/decryption (gallery, etc.)
  • +
  • new options (language, force v3 signatures)
  • +
  • interface changes
  • +
  • bugfixes
  • +
+

1.0.5

+
    +
  • German and Italian translation
  • +
  • much smaller package, due to reduced BC sources
  • +
  • new preferences GUI
  • +
  • layout adjustment for localization
  • +
  • signature bugfix
  • +
+

1.0.4

+
    +
  • fixed another crash caused by some SDK bug with query builder
  • +
+

1.0.3

+
    +
  • fixed crashes during encryption/signing and possibly key export
  • +
+

1.0.2

+
    +
  • filterable key lists
  • +
  • smarter pre-selection of encryption keys
  • +
  • new Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
  • +
  • fixes and additional features (key preselection) for K-9 Mail, new beta build available
  • +
+

1.0.1

+
    +
  • GMail account listing was broken in 1.0.0, fixed again
  • +
+

1.0.0

+
    +
  • K-9 Mail integration, APG supporting beta build of K-9 Mail
  • +
  • support of more file managers (including ASTRO)
  • +
  • Slovenian translation
  • +
  • new database, much faster, less memory usage
  • +
  • defined Intents and content provider for other apps
  • +
  • bugfixes
  • +
+ + diff --git a/OpenKeychain/src/main/res/raw-ar/help_nfc_beam.html b/OpenKeychain/src/main/res/raw-ar/help_nfc_beam.html new file mode 100644 index 000000000..88492731c --- /dev/null +++ b/OpenKeychain/src/main/res/raw-ar/help_nfc_beam.html @@ -0,0 +1,12 @@ + + + +

How to receive keys

+
    +
  1. Go to your partners contacts and open the contact you want to share.
  2. +
  3. Hold the two devices back to back (they have to be almost touching) and you’ll feel a vibration.
  4. +
  5. After it vibrates you’ll see the content on your partners device turn into a card-like object with Star Trek warp speed-looking animation in the background.
  6. +
  7. Tap the card and the content will then load on the your device.
  8. +
+ + diff --git a/OpenKeychain/src/main/res/raw-ar/help_start.html b/OpenKeychain/src/main/res/raw-ar/help_start.html new file mode 100644 index 000000000..3a681f8fa --- /dev/null +++ b/OpenKeychain/src/main/res/raw-ar/help_start.html @@ -0,0 +1,22 @@ + + + +

Getting started

+

First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

+ +

It is recommended that you install OI File Manager for enhanced file selection and Barcode Scanner to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.

+ +

Applications

+

Several applications support OpenKeychain to encrypt/sign your private communication:

K-9 Mail: OpenKeychain support available in current alpha build!

Conversations
: Jabber/XMPP client

PGPAuth
: App to send a PGP-signed request to a server to open or close something, e.g. a door

+ +

I found a bug in OpenKeychain!

+

Please report the bug using the issue tracker of OpenKeychain.

+ +

Contribute

+

If you want to help us developing OpenKeychain by contributing code follow our small guide on Github.

+ +

Translations

+

Help translating OpenKeychain! Everybody can participate at OpenKeychain on Transifex.

+ + + diff --git a/OpenKeychain/src/main/res/raw-ar/help_wot.html b/OpenKeychain/src/main/res/raw-ar/help_wot.html new file mode 100644 index 000000000..29790139b --- /dev/null +++ b/OpenKeychain/src/main/res/raw-ar/help_wot.html @@ -0,0 +1,17 @@ + + + +

Web of Trust

+

The Web of Trust describes the part of PGP which deals with creation and bookkeeping of certifications. It provides mechanisms to help the user keep track of who a public key belongs to, and share this information with others; To ensure the privacy of encrypted communication, it is essential to know that the public key you encrypt to belongs to the person you think it does.

+ +

Support in OpenKeychain

+

There is only basic support for Web of Trust in OpenKeychain. This is a heavy work in progress and subject to changes in upcoming releases.

+ +

Trust Model

+

Trust evaluation is based on the simple assumption that all keys which have secret keys available are trusted. Public keys which contain at least one user id certified by a trusted key will be marked with a green dot in the key listings. It is not (yet) possible to specify trust levels for certificates of other known public keys.

+ +

Certifying keys

+

Support for key certification is available, and user ids can be certified individually. It is not yet possible to specify the level of trust or create local and other special types of certificates.

+ + + diff --git a/OpenKeychain/src/main/res/raw-ar/nfc_beam_share.html b/OpenKeychain/src/main/res/raw-ar/nfc_beam_share.html new file mode 100644 index 000000000..083e055c7 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-ar/nfc_beam_share.html @@ -0,0 +1,11 @@ + + + +
    +
  1. Make sure that NFC is turned on in Settings > More > NFC and make sure that Android Beam is also on in the same section.
  2. +
  3. Hold the two devices back to back (they have to be almost touching) and you'll feel a vibration.
  4. +
  5. After it vibrates you'll see the content on your device turn into a card-like object with Star Trek warp speed-looking animation in the background.
  6. +
  7. Tap the card and the content will then load on the other person’s device.
  8. +
+ + diff --git a/OpenKeychain/src/main/res/raw-cs-rCZ/help_about.html b/OpenKeychain/src/main/res/raw-cs-rCZ/help_about.html deleted file mode 100644 index 99977f75d..000000000 --- a/OpenKeychain/src/main/res/raw-cs-rCZ/help_about.html +++ /dev/null @@ -1,49 +0,0 @@ - - - -

http://www.openkeychain.org

-

OpenKeychain is an OpenPGP implementation for Android.

-

Licence: GPLv3+

- -

Developers OpenKeychain

-
    -
  • Dominik Schürmann (Hlavní vývojář)
  • -
  • Ash Hughes (crypto patches)
  • -
  • Brian C. Barnes
  • -
  • Bahtiar 'kalkin' Gadimov (UI)
  • -
  • Daniel Hammann
  • -
  • Daniel Haß
  • -
  • Greg Witczak
  • -
  • Miroojin Bakshi
  • -
  • Nikhil Peter Raj
  • -
  • Paul Sarbinowski
  • -
  • Sreeram Boyapati
  • -
  • Vincent Breitmoser
  • -
-

Developers APG 1.x

-
    -
  • Thialfihar (Lead developer)
  • -
  • 'Senecaso' (QRCode, sign key, upload key)
  • -
  • Markus Doits
  • -
-

Libraries

- - - diff --git a/OpenKeychain/src/main/res/raw-cs-rCZ/help_changelog.html b/OpenKeychain/src/main/res/raw-cs-rCZ/help_changelog.html deleted file mode 100644 index ebada67f9..000000000 --- a/OpenKeychain/src/main/res/raw-cs-rCZ/help_changelog.html +++ /dev/null @@ -1,156 +0,0 @@ - - - -

2.7

-
    -
  • Purple! (Dominik, Vincent)
  • -
  • New key view design (Dominik, Vincent)
  • -
  • New flat Android buttons (Dominik, Vincent)
  • -
  • API fixes (Dominik)
  • -
  • Keybase.io import (Tim Bray)
  • -
-

2.6.1

-
    -
  • some fixes for regression bugs
  • -
-

2.6

-
    -
  • key certifications (thanks to Vincent Breitmoser)
  • -
  • support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
  • -
  • new design for signature verification
  • -
  • custom key length (thanks to Greg Witczak)
  • -
  • fix share-functionality from other apps
  • -
-

2.5

-
    -
  • fix decryption of symmetric pgp messages/files
  • -
  • refactored edit key screen (thanks to Ash Hughes)
  • -
  • new modern design for encrypt/decrypt screens
  • -
  • OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
  • -
-

2.4

-

Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free! -Besides several small patches, a notable number of patches are made by the following people (in alphabetical order): -Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.

-
    -
  • new unified key list
  • -
  • colorized key fingerprint
  • -
  • support for keyserver ports
  • -
  • deactivate possibility to generate weak keys
  • -
  • much more internal work on the API
  • -
  • certify user ids
  • -
  • keyserver query based on machine-readable output
  • -
  • lock navigation drawer on tablets
  • -
  • suggestions for emails on creation of keys
  • -
  • search in public key lists
  • -
  • and much more improvements and fixes…
  • -
-

2.3.1

-
    -
  • hotfix for crash when upgrading from old versions
  • -
-

2.3

-
    -
  • remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
  • -
  • fix setting expiry dates on keys (thanks to Ash Hughes)
  • -
  • more internal fixes when editing keys (thanks to Ash Hughes)
  • -
  • querying keyservers directly from the import screen
  • -
  • fix layout and dialog style on Android 2.2-3.0
  • -
  • fix crash on keys with empty user ids
  • -
  • fix crash and empty lists when coming back from signing screen
  • -
  • Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
  • -
  • fix upload of key from signing screen
  • -
-

2.2

-
    -
  • new design with navigation drawer
  • -
  • new public key list design
  • -
  • new public key view
  • -
  • bug fixes for importing of keys
  • -
  • key cross-certification (thanks to Ash Hughes)
  • -
  • handle UTF-8 passwords properly (thanks to Ash Hughes)
  • -
  • first version with new languages (thanks to the contributors on Transifex)
  • -
  • sharing of keys via QR Codes fixed and improved
  • -
  • package signature verification for API
  • -
-

2.1.1

-
    -
  • API Updates, preparation for K-9 Mail integration
  • -
-

2.1

-
    -
  • lots of bug fixes
  • -
  • new API for developers
  • -
  • PRNG bug fix by Google
  • -
-

2.0

-
    -
  • complete redesign
  • -
  • share public keys via qr codes, nfc beam
  • -
  • sign keys
  • -
  • upload keys to server
  • -
  • fixes import issues
  • -
  • new AIDL API
  • -
-

1.0.8

-
    -
  • basic keyserver support
  • -
  • app2sd
  • -
  • more choices for pass phrase cache: 1, 2, 4, 8, hours
  • -
  • translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
  • -
  • bugfixes
  • -
  • optimizations
  • -
-

1.0.7

-
    -
  • fixed problem with signature verification of texts with trailing newline
  • -
  • more options for pass phrase cache time to live (20, 40, 60 mins)
  • -
-

1.0.6

-
    -
  • account adding crash on Froyo fixed
  • -
  • secure file deletion
  • -
  • option to delete key file after import
  • -
  • stream encryption/decryption (gallery, etc.)
  • -
  • new options (language, force v3 signatures)
  • -
  • interface changes
  • -
  • bugfixes
  • -
-

1.0.5

-
    -
  • German and Italian translation
  • -
  • much smaller package, due to reduced BC sources
  • -
  • new preferences GUI
  • -
  • layout adjustment for localization
  • -
  • signature bugfix
  • -
-

1.0.4

-
    -
  • fixed another crash caused by some SDK bug with query builder
  • -
-

1.0.3

-
    -
  • fixed crashes during encryption/signing and possibly key export
  • -
-

1.0.2

-
    -
  • filterable key lists
  • -
  • smarter pre-selection of encryption keys
  • -
  • new Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
  • -
  • fixes and additional features (key preselection) for K-9 Mail, new beta build available
  • -
-

1.0.1

-
    -
  • GMail account listing was broken in 1.0.0, fixed again
  • -
-

1.0.0

-
    -
  • K-9 Mail integration, APG supporting beta build of K-9 Mail
  • -
  • support of more file managers (including ASTRO)
  • -
  • Slovenian translation
  • -
  • new database, much faster, less memory usage
  • -
  • defined Intents and content provider for other apps
  • -
  • bugfixes
  • -
- - diff --git a/OpenKeychain/src/main/res/raw-cs-rCZ/help_nfc_beam.html b/OpenKeychain/src/main/res/raw-cs-rCZ/help_nfc_beam.html deleted file mode 100644 index 88492731c..000000000 --- a/OpenKeychain/src/main/res/raw-cs-rCZ/help_nfc_beam.html +++ /dev/null @@ -1,12 +0,0 @@ - - - -

How to receive keys

-
    -
  1. Go to your partners contacts and open the contact you want to share.
  2. -
  3. Hold the two devices back to back (they have to be almost touching) and you’ll feel a vibration.
  4. -
  5. After it vibrates you’ll see the content on your partners device turn into a card-like object with Star Trek warp speed-looking animation in the background.
  6. -
  7. Tap the card and the content will then load on the your device.
  8. -
- - diff --git a/OpenKeychain/src/main/res/raw-cs-rCZ/help_start.html b/OpenKeychain/src/main/res/raw-cs-rCZ/help_start.html deleted file mode 100644 index 6ded872ea..000000000 --- a/OpenKeychain/src/main/res/raw-cs-rCZ/help_start.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -

Getting started

-

First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

- -

It is recommended that you install OI File Manager for enhanced file selection and Barcode Scanner to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.

- -

Applications

-

Several applications support OpenKeychain to encrypt/sign your private communication:

-

Conversations: Jabber/XMPP client

-

K-9 Mail: OpenKeychain support available in current alpha build!

- -

I found a bug in OpenKeychain!

-

Please report the bug using the issue tracker of OpenKeychain.

- -

Contribute

-

If you want to help us developing OpenKeychain by contributing code follow our small guide on Github.

- -

Translations

-

Help translating OpenKeychain! Everybody can participate at OpenKeychain on Transifex.

- - - diff --git a/OpenKeychain/src/main/res/raw-cs-rCZ/nfc_beam_share.html b/OpenKeychain/src/main/res/raw-cs-rCZ/nfc_beam_share.html deleted file mode 100644 index 083e055c7..000000000 --- a/OpenKeychain/src/main/res/raw-cs-rCZ/nfc_beam_share.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
    -
  1. Make sure that NFC is turned on in Settings > More > NFC and make sure that Android Beam is also on in the same section.
  2. -
  3. Hold the two devices back to back (they have to be almost touching) and you'll feel a vibration.
  4. -
  5. After it vibrates you'll see the content on your device turn into a card-like object with Star Trek warp speed-looking animation in the background.
  6. -
  7. Tap the card and the content will then load on the other person’s device.
  8. -
- - diff --git a/OpenKeychain/src/main/res/raw-cs/help_about.html b/OpenKeychain/src/main/res/raw-cs/help_about.html new file mode 100644 index 000000000..ab3c19375 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-cs/help_about.html @@ -0,0 +1,50 @@ + + + +

http://www.openkeychain.org

+

OpenKeychain is an OpenPGP implementation for Android.

+

License: GPLv3+

+ +

Developers OpenKeychain

+
    +
  • Dominik Schürmann (Lead developer)
  • +
  • Ash Hughes (crypto patches)
  • +
  • Brian C. Barnes
  • +
  • Bahtiar 'kalkin' Gadimov (UI)
  • +
  • Daniel Hammann
  • +
  • Daniel Haß
  • +
  • Greg Witczak
  • +
  • Miroojin Bakshi
  • +
  • Nikhil Peter Raj
  • +
  • Paul Sarbinowski
  • +
  • Sreeram Boyapati
  • +
  • Vincent Breitmoser
  • +
  • Tim Bray
  • +
+

Developers APG 1.x

+
    +
  • Thialfihar (Lead developer)
  • +
  • 'Senecaso' (QRCode, sign key, upload key)
  • +
  • Markus Doits
  • +
+

Libraries

+ + + diff --git a/OpenKeychain/src/main/res/raw-cs/help_changelog.html b/OpenKeychain/src/main/res/raw-cs/help_changelog.html new file mode 100644 index 000000000..ebada67f9 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-cs/help_changelog.html @@ -0,0 +1,156 @@ + + + +

2.7

+
    +
  • Purple! (Dominik, Vincent)
  • +
  • New key view design (Dominik, Vincent)
  • +
  • New flat Android buttons (Dominik, Vincent)
  • +
  • API fixes (Dominik)
  • +
  • Keybase.io import (Tim Bray)
  • +
+

2.6.1

+
    +
  • some fixes for regression bugs
  • +
+

2.6

+
    +
  • key certifications (thanks to Vincent Breitmoser)
  • +
  • support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
  • +
  • new design for signature verification
  • +
  • custom key length (thanks to Greg Witczak)
  • +
  • fix share-functionality from other apps
  • +
+

2.5

+
    +
  • fix decryption of symmetric pgp messages/files
  • +
  • refactored edit key screen (thanks to Ash Hughes)
  • +
  • new modern design for encrypt/decrypt screens
  • +
  • OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
  • +
+

2.4

+

Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free! +Besides several small patches, a notable number of patches are made by the following people (in alphabetical order): +Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.

+
    +
  • new unified key list
  • +
  • colorized key fingerprint
  • +
  • support for keyserver ports
  • +
  • deactivate possibility to generate weak keys
  • +
  • much more internal work on the API
  • +
  • certify user ids
  • +
  • keyserver query based on machine-readable output
  • +
  • lock navigation drawer on tablets
  • +
  • suggestions for emails on creation of keys
  • +
  • search in public key lists
  • +
  • and much more improvements and fixes…
  • +
+

2.3.1

+
    +
  • hotfix for crash when upgrading from old versions
  • +
+

2.3

+
    +
  • remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
  • +
  • fix setting expiry dates on keys (thanks to Ash Hughes)
  • +
  • more internal fixes when editing keys (thanks to Ash Hughes)
  • +
  • querying keyservers directly from the import screen
  • +
  • fix layout and dialog style on Android 2.2-3.0
  • +
  • fix crash on keys with empty user ids
  • +
  • fix crash and empty lists when coming back from signing screen
  • +
  • Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
  • +
  • fix upload of key from signing screen
  • +
+

2.2

+
    +
  • new design with navigation drawer
  • +
  • new public key list design
  • +
  • new public key view
  • +
  • bug fixes for importing of keys
  • +
  • key cross-certification (thanks to Ash Hughes)
  • +
  • handle UTF-8 passwords properly (thanks to Ash Hughes)
  • +
  • first version with new languages (thanks to the contributors on Transifex)
  • +
  • sharing of keys via QR Codes fixed and improved
  • +
  • package signature verification for API
  • +
+

2.1.1

+
    +
  • API Updates, preparation for K-9 Mail integration
  • +
+

2.1

+
    +
  • lots of bug fixes
  • +
  • new API for developers
  • +
  • PRNG bug fix by Google
  • +
+

2.0

+
    +
  • complete redesign
  • +
  • share public keys via qr codes, nfc beam
  • +
  • sign keys
  • +
  • upload keys to server
  • +
  • fixes import issues
  • +
  • new AIDL API
  • +
+

1.0.8

+
    +
  • basic keyserver support
  • +
  • app2sd
  • +
  • more choices for pass phrase cache: 1, 2, 4, 8, hours
  • +
  • translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
  • +
  • bugfixes
  • +
  • optimizations
  • +
+

1.0.7

+
    +
  • fixed problem with signature verification of texts with trailing newline
  • +
  • more options for pass phrase cache time to live (20, 40, 60 mins)
  • +
+

1.0.6

+
    +
  • account adding crash on Froyo fixed
  • +
  • secure file deletion
  • +
  • option to delete key file after import
  • +
  • stream encryption/decryption (gallery, etc.)
  • +
  • new options (language, force v3 signatures)
  • +
  • interface changes
  • +
  • bugfixes
  • +
+

1.0.5

+
    +
  • German and Italian translation
  • +
  • much smaller package, due to reduced BC sources
  • +
  • new preferences GUI
  • +
  • layout adjustment for localization
  • +
  • signature bugfix
  • +
+

1.0.4

+
    +
  • fixed another crash caused by some SDK bug with query builder
  • +
+

1.0.3

+
    +
  • fixed crashes during encryption/signing and possibly key export
  • +
+

1.0.2

+
    +
  • filterable key lists
  • +
  • smarter pre-selection of encryption keys
  • +
  • new Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
  • +
  • fixes and additional features (key preselection) for K-9 Mail, new beta build available
  • +
+

1.0.1

+
    +
  • GMail account listing was broken in 1.0.0, fixed again
  • +
+

1.0.0

+
    +
  • K-9 Mail integration, APG supporting beta build of K-9 Mail
  • +
  • support of more file managers (including ASTRO)
  • +
  • Slovenian translation
  • +
  • new database, much faster, less memory usage
  • +
  • defined Intents and content provider for other apps
  • +
  • bugfixes
  • +
+ + diff --git a/OpenKeychain/src/main/res/raw-cs/help_nfc_beam.html b/OpenKeychain/src/main/res/raw-cs/help_nfc_beam.html new file mode 100644 index 000000000..88492731c --- /dev/null +++ b/OpenKeychain/src/main/res/raw-cs/help_nfc_beam.html @@ -0,0 +1,12 @@ + + + +

How to receive keys

+
    +
  1. Go to your partners contacts and open the contact you want to share.
  2. +
  3. Hold the two devices back to back (they have to be almost touching) and you’ll feel a vibration.
  4. +
  5. After it vibrates you’ll see the content on your partners device turn into a card-like object with Star Trek warp speed-looking animation in the background.
  6. +
  7. Tap the card and the content will then load on the your device.
  8. +
+ + diff --git a/OpenKeychain/src/main/res/raw-cs/help_start.html b/OpenKeychain/src/main/res/raw-cs/help_start.html new file mode 100644 index 000000000..3a681f8fa --- /dev/null +++ b/OpenKeychain/src/main/res/raw-cs/help_start.html @@ -0,0 +1,22 @@ + + + +

Getting started

+

First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

+ +

It is recommended that you install OI File Manager for enhanced file selection and Barcode Scanner to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.

+ +

Applications

+

Several applications support OpenKeychain to encrypt/sign your private communication:

K-9 Mail: OpenKeychain support available in current alpha build!

Conversations
: Jabber/XMPP client

PGPAuth
: App to send a PGP-signed request to a server to open or close something, e.g. a door

+ +

I found a bug in OpenKeychain!

+

Please report the bug using the issue tracker of OpenKeychain.

+ +

Contribute

+

If you want to help us developing OpenKeychain by contributing code follow our small guide on Github.

+ +

Translations

+

Help translating OpenKeychain! Everybody can participate at OpenKeychain on Transifex.

+ + + diff --git a/OpenKeychain/src/main/res/raw-cs/help_wot.html b/OpenKeychain/src/main/res/raw-cs/help_wot.html new file mode 100644 index 000000000..29790139b --- /dev/null +++ b/OpenKeychain/src/main/res/raw-cs/help_wot.html @@ -0,0 +1,17 @@ + + + +

Web of Trust

+

The Web of Trust describes the part of PGP which deals with creation and bookkeeping of certifications. It provides mechanisms to help the user keep track of who a public key belongs to, and share this information with others; To ensure the privacy of encrypted communication, it is essential to know that the public key you encrypt to belongs to the person you think it does.

+ +

Support in OpenKeychain

+

There is only basic support for Web of Trust in OpenKeychain. This is a heavy work in progress and subject to changes in upcoming releases.

+ +

Trust Model

+

Trust evaluation is based on the simple assumption that all keys which have secret keys available are trusted. Public keys which contain at least one user id certified by a trusted key will be marked with a green dot in the key listings. It is not (yet) possible to specify trust levels for certificates of other known public keys.

+ +

Certifying keys

+

Support for key certification is available, and user ids can be certified individually. It is not yet possible to specify the level of trust or create local and other special types of certificates.

+ + + diff --git a/OpenKeychain/src/main/res/raw-cs/nfc_beam_share.html b/OpenKeychain/src/main/res/raw-cs/nfc_beam_share.html new file mode 100644 index 000000000..083e055c7 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-cs/nfc_beam_share.html @@ -0,0 +1,11 @@ + + + +
    +
  1. Make sure that NFC is turned on in Settings > More > NFC and make sure that Android Beam is also on in the same section.
  2. +
  3. Hold the two devices back to back (they have to be almost touching) and you'll feel a vibration.
  4. +
  5. After it vibrates you'll see the content on your device turn into a card-like object with Star Trek warp speed-looking animation in the background.
  6. +
  7. Tap the card and the content will then load on the other person’s device.
  8. +
+ + diff --git a/OpenKeychain/src/main/res/raw-de/help_about.html b/OpenKeychain/src/main/res/raw-de/help_about.html index c40267e73..8eb033e9f 100644 --- a/OpenKeychain/src/main/res/raw-de/help_about.html +++ b/OpenKeychain/src/main/res/raw-de/help_about.html @@ -19,11 +19,12 @@
  • Paul Sarbinowski
  • Sreeram Boyapati
  • Vincent Breitmoser
  • +
  • Tim Bray
  • Entwickler APG 1.x

    • Thialfihar (Hauptentwickler)
    • -
    • 'Senecaso' (QR-Code, Schlüssel signtieren, Schlüssel hochladen)
    • +
    • 'Senecaso' (QR-Code, Schlüssel signieren, Schlüssel hochladen)
    • Markus Doits

    Bibliotheken

    diff --git a/OpenKeychain/src/main/res/raw-de/help_changelog.html b/OpenKeychain/src/main/res/raw-de/help_changelog.html index 4f8206bf7..9ef142382 100644 --- a/OpenKeychain/src/main/res/raw-de/help_changelog.html +++ b/OpenKeychain/src/main/res/raw-de/help_changelog.html @@ -3,11 +3,11 @@

    2.7

      -
    • Purple! (Dominik, Vincent)
    • -
    • New key view design (Dominik, Vincent)
    • -
    • New flat Android buttons (Dominik, Vincent)
    • -
    • API fixes (Dominik)
    • -
    • Keybase.io import (Tim Bray)
    • +
    • Lila! (Dominik, Vincent)
    • +
    • Neues Schlüsselansicht Design (Dominik, Vincent)
    • +
    • Neue flache Android Buttons (Dominik, Vincent)
    • +
    • API Fehler behoben (Dominik)
    • +
    • keybase.io importiert (Tim Bray)

    2.6.1

      @@ -15,51 +15,51 @@

    2.6

      -
    • key certifications (thanks to Vincent Breitmoser)
    • -
    • support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
    • -
    • new design for signature verification
    • -
    • custom key length (thanks to Greg Witczak)
    • -
    • fix share-functionality from other apps
    • +
    • Schlüsselzertifikation (Dank an Vincent Breitmoser)
    • +
    • Unterstützung für GnuPG teilweisegeheime Schlüssel (Dank an Vincent Breitmoser)
    • +
    • Neues Design für Signaturverifikation
    • +
    • Nutzerdefinierte Schlüssellänge (Dank an Greg Witczak)
    • +
    • Fehler behoben bei der Teilen-Funktion von anderen Apps

    2.5

      -
    • fix decryption of symmetric pgp messages/files
    • -
    • refactored edit key screen (thanks to Ash Hughes)
    • -
    • new modern design for encrypt/decrypt screens
    • -
    • OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
    • +
    • behoben: entschlüsseln von symetrischen pgp Nachrichten/Dateien
    • +
    • umgestalteter Schlüssel bearbeiten Bildschirm (Dank an Ash Hughes)
    • +
    • neues modernes Design für verschlüsselung/entschlüsselungs Bildschirme
    • +
    • OpenPGP API Version 3 (mehrfache api accounts, interne fehlerbehebungen, schlüssel suche)

    2.4

    -

    Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free! -Besides several small patches, a notable number of patches are made by the following people (in alphabetical order): +

    Danke an alle Bewerber beim Google Summer of Code 2014, die diese Version funktionsreich und fehlerfrei gemacht haben. +Neben mehreren kleinen Updates sind eine beachtliche Anzahl von Updates von den folgenden Personen gemacht worden (in alphabetischer Reihenfolge): Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.

      -
    • new unified key list
    • -
    • colorized key fingerprint
    • -
    • support for keyserver ports
    • -
    • deactivate possibility to generate weak keys
    • -
    • much more internal work on the API
    • -
    • certify user ids
    • -
    • keyserver query based on machine-readable output
    • +
    • neue vereinheitlichte Schlüssel liste.
    • +
    • eingefärbte Schlüssel fingerprints
    • +
    • Unterstützung für Schlüsselserver
    • +
    • deaktiviert die Möglichkeit schwache Schlüssel zu generieren.
    • +
    • viel mehr interne Arbeit an der API
    • +
    • zertifizieren von Benutzer IDs
    • +
    • Schlüsselserver Anfragen basieren auf Maschinenlesbaren Ausgaben.
    • lock navigation drawer on tablets
    • suggestions for emails on creation of keys
    • -
    • search in public key lists
    • -
    • and much more improvements and fixes…
    • +
    • suchen in öffentlichen Schlüssellisten
    • +
    • und viele weitere Verbesserungen und Fehlerbehebungen...

    2.3.1

      -
    • hotfix for crash when upgrading from old versions
    • +
    • schnelle Fehlerbehebung für Abstürze sobald man von einer alten Version geupdatet hat.

    2.3

      -
    • remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
    • -
    • fix setting expiry dates on keys (thanks to Ash Hughes)
    • -
    • more internal fixes when editing keys (thanks to Ash Hughes)
    • -
    • querying keyservers directly from the import screen
    • -
    • fix layout and dialog style on Android 2.2-3.0
    • +
    • entfernung von unnötigen exporten von öffentlichen Schlüsseln, wenn man den geheimen Schlüssel exportiert. (Dank an Ash Hughes)
    • +
    • Fehlerbehebung: Einstellen des Ablaufdatums von Schlüsseln (Dank an Ash Hughes)
    • +
    • mehr interne Fehlerbehebungen wenn man Schlüssel bearbeitet (Dank an Ash Hughes)
    • +
    • Suchzugriff auf die Schlüsselserver direkt vom Importieren Bildschirm
    • +
    • Fehlerbehebung beim Layout und Dialogstil auf Android 2.2-3.0
    • Absturz bei leeren Nutzer IDs behoben
    • -
    • fix crash and empty lists when coming back from signing screen
    • -
    • Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
    • -
    • fix upload of key from signing screen
    • +
    • Fehlerbehebung von Abstürzen und leeren Listen, wenn man vom signieren Bildschirm zurückkehrt.
    • +
    • Bouncy Castle (Kryptographie Bibliothek) upgedatet von 1.47 auf 1.50 und vom Quellcode kompiliert.
    • +
    • Fehlerbehebung vom hochladen von Schlüsseln vom signieren Bildschirm.

    2.2

      @@ -67,15 +67,15 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
    • Neus Design für die Liste der öffentlichen Schlüssel
    • Neue Ansicht für öffentliche Schlüssel
    • Fehler beim Schlüsselimport behoben
    • -
    • key cross-certification (thanks to Ash Hughes)
    • -
    • handle UTF-8 passwords properly (thanks to Ash Hughes)
    • +
    • Schlüssel Cross-Zertifizierung (Dank an Ash Hughes)
    • +
    • richtiges händling von UTF-8 Passwörtern (Danke an Ash Hughes)
    • Erste Version mit neuen Sprachen (Danke an die Mitwirkenden bei Transifex)
    • -
    • sharing of keys via QR Codes fixed and improved
    • -
    • package signature verification for API
    • +
    • teilen von schlüsseln per QR-Codes behoben und verbessert
    • +
    • paket signatur verifizierung für die API

    2.1.1

      -
    • API Updates, preparation for K-9 Mail integration
    • +
    • API Updates, vorbereitung für die K-9 Mail integration.

    2.1

      @@ -103,7 +103,7 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa

    1.0.7

      -
    • fixed problem with signature verification of texts with trailing newline
    • +
    • Fehlerbehebung bei Problemen mit der Signatur verifizierung von Texten mit folgender neuer Zeile.
    • weitere Optionen für die Time-to-live des Passphrasencaches (20, 40, 60 mins)

    1.0.6

    @@ -126,7 +126,7 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa

    1.0.4

      -
    • fixed another crash caused by some SDK bug with query builder
    • +
    • Einen anderen crash behoben, verursacht von irgendeinen SDK bug mit dem query builder.

    1.0.3

      @@ -135,13 +135,13 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa

      1.0.2

      • Filterbare Schlüsselliste
      • -
      • smarter pre-selection of encryption keys
      • -
      • new Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
      • -
      • fixes and additional features (key preselection) for K-9 Mail, new beta build available
      • +
      • leichtere vorauswahl von Verschlüsselungsschlüsseln
      • +
      • neues Intent händling für VIEW und SEND, erlaubt es Dateien zu ver-/entschlüsseln außerhalb des Dateimanagers.
      • +
      • Fehlerbehebungen und Extras (Schlüssel vorauswahl) für K-9 Mail, neue Beta Versionen verfügbar.

      1.0.1

        -
      • GMail account listing was broken in 1.0.0, fixed again
      • +
      • GMail Account auflistung war nicht in Ordnung in 1.0.0, wieder behoben.

      1.0.0

        @@ -149,7 +149,7 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
      • Unterstützung von mehr Filemanagern (einschließlich ASTRO)
      • Slowenische Übersetzung
      • Neue Datenbank, viel schneller, weniger Speicherbedarf
      • -
      • defined Intents and content provider for other apps
      • +
      • definierte intents und content provider für andere Apps
      • Fehlerbehebungen
      diff --git a/OpenKeychain/src/main/res/raw-de/help_nfc_beam.html b/OpenKeychain/src/main/res/raw-de/help_nfc_beam.html index 6fb3d6dd1..0526783cd 100644 --- a/OpenKeychain/src/main/res/raw-de/help_nfc_beam.html +++ b/OpenKeychain/src/main/res/raw-de/help_nfc_beam.html @@ -1,12 +1,12 @@ -

      Wie werden Schlüssel empfangen

      +

      Wie kann man Schlüssel empfangen

        -
      1. Gehen Sie zu Ihren Kontakten und öffnen Sie den Kontakt, den Sie teilen wollen.
      2. -
      3. Halten sie die zwei Geräte Rückseitig aneinander (sie müssen sich fast berühren) und sie werden ein Vibrieren fühlen.
      4. -
      5. After it vibrates you’ll see the content on your partners device turn into a card-like object with Star Trek warp speed-looking animation in the background.
      6. -
      7. Tippen sie die Karte an und der Inhalt wird dann auf Ihr Gerät geladen.
      8. +
      9. Gehen Sie zu den Kontakten ihres Bekannten und öffnen Sie den Kontakt, den Sie teilen möchten.
      10. +
      11. Halten Sie die zwei Geräte rückseitig aneinander (sodass sie sich fast berühren) und es wird vibrieren
      12. +
      13. Nachdem es vibriert sehen sie wie sich der Inhalt des Gerätes ihres Bekannten von einer Warp-Geschwindigkeit Animation umgeben wird
      14. +
      15. Wenn sie die Karte antippen, wird der Inhalt auf ihr Gerät übertragen
      diff --git a/OpenKeychain/src/main/res/raw-de/help_start.html b/OpenKeychain/src/main/res/raw-de/help_start.html new file mode 100644 index 000000000..1538fbce4 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-de/help_start.html @@ -0,0 +1,22 @@ + + + +

      Los gehts

      +

      Zuerst benötigen Sie einen geheimen privaten Schlüssel. Erstellen Sie einen Schlüssel über den Eintrag "Schlüssel" im Menu oder importieren Sie bestehende private Schlüssel. Anschließend können Sie die Schlüssel ihrer Freunde runterladen oder Sie über QR-Codes oder NFC austauschen.

      + +

      Es wird empfohlen, dass Sie den OI File Manager für ein verbessertes Dateihandling installieren, sowie den Barcode Scanner installieren um erstellte QR-Codes zu scannen. Die Links führen entweder zu Google Play oder zu F-Droid zur Installation.

      + +

      Anwendungen

      +

      Etliche Anwendungen unterstützen OpenKeychain um private Kommunikation zu verschlüsseln/signieren:

      K-9 Mail: OpenKeychainUnterstützung in der aktuellenen alpha Version!

      Conversations
      : Jabber/XMPP client

      PGPAuth
      : App zum senden von PGP-signierten Anfragen an einen Server um etwas zu öffnen oder zu schliessen, z.B. eine Tür.

      + +

      Ich habe einen Fehler in der OpenKeychain gefunden!

      +

      Bitte berichten Sie Bugs mithilfe des Issue Trackers der OpenKeychain.

      + +

      Unterstützen

      +

      Wenn Sie uns bei der Entwickelung von OpenKeychain durch das Beisteuern von Code helfen wollt, schaut euch unsere kurze Anleitung auf Github an.

      + +

      Übersetzungen

      +

      Hilf mit OpenKeychain zu übersetzten! Jeder kann auf OpenKeychain auf Transifex mitmachen.

      + + + diff --git a/OpenKeychain/src/main/res/raw-de/help_wot.html b/OpenKeychain/src/main/res/raw-de/help_wot.html new file mode 100644 index 000000000..ad33ddbb1 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-de/help_wot.html @@ -0,0 +1,17 @@ + + + +

      Web of Trust

      +

      Das Web of Trust beschreibt den Teil von PGP der sich mit der Erstellung und dem Verwalten von Zertifikaten beschäftigt. Nutzer können so im Auge behalten zu wem ein bestimmter Public Key gehört, sowie diese Information teilen: Um die Privatsphäre von verschlüsselter Kommunikation zu gewährleisten ist es essentiell zu wissen ob der Public Key den man zum Verschlüsseln nutzt zu der Person gehört, die man erwartet.

      + +

      Support in OpenKeychain

      +

      Es gibt nur eine rudimentäre Unterstützung für das Web of Trust in OpenKeychain. Am Web of Trust System wird kontinuierlich gearbeitet und es wird in den kommenden Version überarbeitet.

      + +

      Vertrauens-Modell

      +

      Die Bewertung des Vertrauens basiert auf der Grundannahme, dass alle Schlüssel zu denen ein privater Schlüssel vorhanden ist, vertrauenswürdig sind. Öffentliche Schlüssel welche mindestens eine User ID beinhalten, die von einem Trusted Key verifiziert wurden, werden mit einem grünen Punkt in der Schlüsselliste gekennzeichnet. Es ist (noch) nicht möglich bestimmte Trust Level für Zertifikate anderer bekannter öffentlicher Schlüssel festzulegen.

      + +

      Schlüssel beglaubigen

      +

      Die Unterstützung für die Zertifizierung von Schlüsseln ist vorhanden. Nutzer IDs können separat zertifiziert werden. Es ist jedoch sowohl noch nicht möglich das Vertrauenslevel festzulegen, als auch lokale oder andere spezielle Zertifikate zu erstellen.

      + + + diff --git a/OpenKeychain/src/main/res/raw-de/nfc_beam_share.html b/OpenKeychain/src/main/res/raw-de/nfc_beam_share.html index 083e055c7..8a2e1880e 100644 --- a/OpenKeychain/src/main/res/raw-de/nfc_beam_share.html +++ b/OpenKeychain/src/main/res/raw-de/nfc_beam_share.html @@ -2,10 +2,10 @@
        -
      1. Make sure that NFC is turned on in Settings > More > NFC and make sure that Android Beam is also on in the same section.
      2. -
      3. Hold the two devices back to back (they have to be almost touching) and you'll feel a vibration.
      4. -
      5. After it vibrates you'll see the content on your device turn into a card-like object with Star Trek warp speed-looking animation in the background.
      6. -
      7. Tap the card and the content will then load on the other person’s device.
      8. +
      9. Stellen Sie sicher, dass NFC und Android Beam in den Einstellungen unter > Mehr > NFC eingeschaltet sind
      10. +
      11. Halten sie die zwei Geräte rückseitig aneinander (sodass sie sich fast berühren) und es wird vibrieren
      12. +
      13. Nachdem es vibriert sehen sie wie der Inhalt ihres Gerätes von einer Warp-Geschwindigkeit Animation umgeben wird
      14. +
      15. Drücken Sie auf die Karte und der Inhalt wird auf das Gerät des Anderen geladen.
      diff --git a/OpenKeychain/src/main/res/raw-el/help_about.html b/OpenKeychain/src/main/res/raw-el/help_about.html index ae7e16aae..ab3c19375 100644 --- a/OpenKeychain/src/main/res/raw-el/help_about.html +++ b/OpenKeychain/src/main/res/raw-el/help_about.html @@ -19,6 +19,7 @@
    • Paul Sarbinowski
    • Sreeram Boyapati
    • Vincent Breitmoser
    • +
    • Tim Bray

    Developers APG 1.x

      diff --git a/OpenKeychain/src/main/res/raw-el/help_start.html b/OpenKeychain/src/main/res/raw-el/help_start.html index 6ded872ea..3a681f8fa 100644 --- a/OpenKeychain/src/main/res/raw-el/help_start.html +++ b/OpenKeychain/src/main/res/raw-el/help_start.html @@ -2,14 +2,12 @@

      Getting started

      -

      First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

      +

      First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

      It is recommended that you install OI File Manager for enhanced file selection and Barcode Scanner to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.

      Applications

      -

      Several applications support OpenKeychain to encrypt/sign your private communication:

      -

      Conversations: Jabber/XMPP client

      -

      K-9 Mail: OpenKeychain support available in current alpha build!

      +

      Several applications support OpenKeychain to encrypt/sign your private communication:

      K-9 Mail: OpenKeychain support available in current alpha build!

      Conversations
      : Jabber/XMPP client

      PGPAuth
      : App to send a PGP-signed request to a server to open or close something, e.g. a door

      I found a bug in OpenKeychain!

      Please report the bug using the issue tracker of OpenKeychain.

      diff --git a/OpenKeychain/src/main/res/raw-el/help_wot.html b/OpenKeychain/src/main/res/raw-el/help_wot.html new file mode 100644 index 000000000..29790139b --- /dev/null +++ b/OpenKeychain/src/main/res/raw-el/help_wot.html @@ -0,0 +1,17 @@ + + + +

      Web of Trust

      +

      The Web of Trust describes the part of PGP which deals with creation and bookkeeping of certifications. It provides mechanisms to help the user keep track of who a public key belongs to, and share this information with others; To ensure the privacy of encrypted communication, it is essential to know that the public key you encrypt to belongs to the person you think it does.

      + +

      Support in OpenKeychain

      +

      There is only basic support for Web of Trust in OpenKeychain. This is a heavy work in progress and subject to changes in upcoming releases.

      + +

      Trust Model

      +

      Trust evaluation is based on the simple assumption that all keys which have secret keys available are trusted. Public keys which contain at least one user id certified by a trusted key will be marked with a green dot in the key listings. It is not (yet) possible to specify trust levels for certificates of other known public keys.

      + +

      Certifying keys

      +

      Support for key certification is available, and user ids can be certified individually. It is not yet possible to specify the level of trust or create local and other special types of certificates.

      + + + diff --git a/OpenKeychain/src/main/res/raw-es/help_about.html b/OpenKeychain/src/main/res/raw-es/help_about.html index 7a4f61127..a6067c8b9 100644 --- a/OpenKeychain/src/main/res/raw-es/help_about.html +++ b/OpenKeychain/src/main/res/raw-es/help_about.html @@ -19,6 +19,7 @@
    • Paul Sarbinowski
    • Sreeram Boyapati
    • Vincent Breitmoser
    • +
    • Tim Bray

    Desarrolladores de APG 1.x

      diff --git a/OpenKeychain/src/main/res/raw-es/help_changelog.html b/OpenKeychain/src/main/res/raw-es/help_changelog.html index b86d29adb..0cd3773a2 100644 --- a/OpenKeychain/src/main/res/raw-es/help_changelog.html +++ b/OpenKeychain/src/main/res/raw-es/help_changelog.html @@ -4,10 +4,10 @@

      2.7

      • Purple! (Dominik, Vincent)
      • -
      • New key view design (Dominik, Vincent)
      • -
      • New flat Android buttons (Dominik, Vincent)
      • -
      • API fixes (Dominik)
      • -
      • Keybase.io import (Tim Bray)
      • +
      • Diseño de vista de nueva clave (Dominik, Vincent)
      • +
      • Nuevos botones de Android planos (Dominik, Vincent)
      • +
      • Reparaciones de la API (Dominik)
      • +
      • Importación de Keybase.io (Tim Bray)

      2.6.1

        diff --git a/OpenKeychain/src/main/res/raw-es/help_start.html b/OpenKeychain/src/main/res/raw-es/help_start.html index d9eaa90b5..5fcda44b4 100644 --- a/OpenKeychain/src/main/res/raw-es/help_start.html +++ b/OpenKeychain/src/main/res/raw-es/help_start.html @@ -2,14 +2,12 @@

        Primeros pasos

        -

        Primero necesita una clave privada (secreta) personal. Cree una mediante las opciones de menú en "Claves", o importe claves privadas existentes. En adelante puede descargar las claves de sus amigos, o intercambiarlas mediante códigos QR o vía NFC.

        +

        Primero necesita una clave privada (secreta) personal. Cree una mediante las opciones de menú en "Claves", o importe claves privadas existentes. En adelante puede descargar las claves de sus amigos, o intercambiarlas mediante códigos QR o vía NFC.

        Es recomendable que instales OI File Manager para una mejor selección de archivos y Barcode Scanner para escanear los códigos QR generados. Pulsando en los enlaces se abrirá Google Play o F-Droid.

        Aplicaciones

        -

        Varias aplicaciones soportan OpenKeychain para cifrar/firmar sus comunicaciones privadas:

        -

        Conversaciones: Cliente Jabber/XMPP

        -

        K-9 Mail: ¡Soporte para OpenKeychain disponible en la actual versión alfa!

        +

        Varias aplicaciones soportan OpenKeychain para cifrar/firmar sus comunicaciones privadas:

        K-9 Mail: Soporte para OpenKeychain disponible en la actual ¡versión alfa!

        Conversaciones
        : Cliente Jabber/XMPP

        PGPAuth
        : Aplicación para enviar una petición firmada-con-PGP a un servidor para abrir o cerrar algo, ej: una puerta

        ¡He encontrado un bug en OpenKeychain!

        Por favor, informa de errores usando el seguimiento de incidencias de OpenKeychain.

        diff --git a/OpenKeychain/src/main/res/raw-es/help_wot.html b/OpenKeychain/src/main/res/raw-es/help_wot.html new file mode 100644 index 000000000..60a2abb02 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-es/help_wot.html @@ -0,0 +1,17 @@ + + + +

        Web of Trust

        +

        El Web of Trust (web de confianza) describe la parte de PGP que trata con la creación y catalogación de certificaciones. Proporciona mecanismos para ayudar al usuario a llevar un seguimiento de a quién pertenece una clave pública, y comparte esta información con otros. Para asegurar la privacidad de las comunicaciones cifradas, es esencial saber que la clave pública que usted cifra pertenece a la misma persona que usted cree.

        + +

        Soporte en OpenKeychain

        +

        Sólo hay soporte básico para Web of Trust (web de confianza) en OpenKeychain. Este es un duro trabajo que tenemos en marcha sujeto a cambios en versiones posteriores.

        + +

        Modelo de confianza

        +

        La evaluación de la confianza está basada en la simple asunción de que todas las claves que tienen disponibles claves privadas (secretas) son de confianza. Las claves públicas que contienen al menos una identificación de usuario certificada por una clave de confianza serán marcadas con un punto verde en los listados de claves. No es posible (aún) especificar niveles de confianza para certificados de otras claves públicas conocidas.

        + +

        Certificando claves

        +

        Está disponible el soporte para certificación de clave, y las identificaciones de usuario pueden ser certificadas individualmente. No es posible aún especificar el nivel de confianza o crear certificados locales y otros tipos especiales de certificados.

        + + + diff --git a/OpenKeychain/src/main/res/raw-et/help_about.html b/OpenKeychain/src/main/res/raw-et/help_about.html index ae7e16aae..ab3c19375 100644 --- a/OpenKeychain/src/main/res/raw-et/help_about.html +++ b/OpenKeychain/src/main/res/raw-et/help_about.html @@ -19,6 +19,7 @@
      • Paul Sarbinowski
      • Sreeram Boyapati
      • Vincent Breitmoser
      • +
      • Tim Bray

      Developers APG 1.x

        diff --git a/OpenKeychain/src/main/res/raw-et/help_start.html b/OpenKeychain/src/main/res/raw-et/help_start.html index 6ded872ea..3a681f8fa 100644 --- a/OpenKeychain/src/main/res/raw-et/help_start.html +++ b/OpenKeychain/src/main/res/raw-et/help_start.html @@ -2,14 +2,12 @@

        Getting started

        -

        First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

        +

        First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

        It is recommended that you install OI File Manager for enhanced file selection and Barcode Scanner to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.

        Applications

        -

        Several applications support OpenKeychain to encrypt/sign your private communication:

        -

        Conversations: Jabber/XMPP client

        -

        K-9 Mail: OpenKeychain support available in current alpha build!

        +

        Several applications support OpenKeychain to encrypt/sign your private communication:

        K-9 Mail: OpenKeychain support available in current alpha build!

        Conversations
        : Jabber/XMPP client

        PGPAuth
        : App to send a PGP-signed request to a server to open or close something, e.g. a door

        I found a bug in OpenKeychain!

        Please report the bug using the issue tracker of OpenKeychain.

        diff --git a/OpenKeychain/src/main/res/raw-et/help_wot.html b/OpenKeychain/src/main/res/raw-et/help_wot.html new file mode 100644 index 000000000..29790139b --- /dev/null +++ b/OpenKeychain/src/main/res/raw-et/help_wot.html @@ -0,0 +1,17 @@ + + + +

        Web of Trust

        +

        The Web of Trust describes the part of PGP which deals with creation and bookkeeping of certifications. It provides mechanisms to help the user keep track of who a public key belongs to, and share this information with others; To ensure the privacy of encrypted communication, it is essential to know that the public key you encrypt to belongs to the person you think it does.

        + +

        Support in OpenKeychain

        +

        There is only basic support for Web of Trust in OpenKeychain. This is a heavy work in progress and subject to changes in upcoming releases.

        + +

        Trust Model

        +

        Trust evaluation is based on the simple assumption that all keys which have secret keys available are trusted. Public keys which contain at least one user id certified by a trusted key will be marked with a green dot in the key listings. It is not (yet) possible to specify trust levels for certificates of other known public keys.

        + +

        Certifying keys

        +

        Support for key certification is available, and user ids can be certified individually. It is not yet possible to specify the level of trust or create local and other special types of certificates.

        + + + diff --git a/OpenKeychain/src/main/res/raw-fa-rIR/help_about.html b/OpenKeychain/src/main/res/raw-fa-rIR/help_about.html deleted file mode 100644 index ae7e16aae..000000000 --- a/OpenKeychain/src/main/res/raw-fa-rIR/help_about.html +++ /dev/null @@ -1,49 +0,0 @@ - - - -

        http://www.openkeychain.org

        -

        OpenKeychain is an OpenPGP implementation for Android.

        -

        License: GPLv3+

        - -

        Developers OpenKeychain

        -
          -
        • Dominik Schürmann (Lead developer)
        • -
        • Ash Hughes (crypto patches)
        • -
        • Brian C. Barnes
        • -
        • Bahtiar 'kalkin' Gadimov (UI)
        • -
        • Daniel Hammann
        • -
        • Daniel Haß
        • -
        • Greg Witczak
        • -
        • Miroojin Bakshi
        • -
        • Nikhil Peter Raj
        • -
        • Paul Sarbinowski
        • -
        • Sreeram Boyapati
        • -
        • Vincent Breitmoser
        • -
        -

        Developers APG 1.x

        -
          -
        • Thialfihar (Lead developer)
        • -
        • 'Senecaso' (QRCode, sign key, upload key)
        • -
        • Markus Doits
        • -
        -

        Libraries

        - - - diff --git a/OpenKeychain/src/main/res/raw-fa-rIR/help_changelog.html b/OpenKeychain/src/main/res/raw-fa-rIR/help_changelog.html deleted file mode 100644 index ebada67f9..000000000 --- a/OpenKeychain/src/main/res/raw-fa-rIR/help_changelog.html +++ /dev/null @@ -1,156 +0,0 @@ - - - -

        2.7

        -
          -
        • Purple! (Dominik, Vincent)
        • -
        • New key view design (Dominik, Vincent)
        • -
        • New flat Android buttons (Dominik, Vincent)
        • -
        • API fixes (Dominik)
        • -
        • Keybase.io import (Tim Bray)
        • -
        -

        2.6.1

        -
          -
        • some fixes for regression bugs
        • -
        -

        2.6

        -
          -
        • key certifications (thanks to Vincent Breitmoser)
        • -
        • support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
        • -
        • new design for signature verification
        • -
        • custom key length (thanks to Greg Witczak)
        • -
        • fix share-functionality from other apps
        • -
        -

        2.5

        -
          -
        • fix decryption of symmetric pgp messages/files
        • -
        • refactored edit key screen (thanks to Ash Hughes)
        • -
        • new modern design for encrypt/decrypt screens
        • -
        • OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
        • -
        -

        2.4

        -

        Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free! -Besides several small patches, a notable number of patches are made by the following people (in alphabetical order): -Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.

        -
          -
        • new unified key list
        • -
        • colorized key fingerprint
        • -
        • support for keyserver ports
        • -
        • deactivate possibility to generate weak keys
        • -
        • much more internal work on the API
        • -
        • certify user ids
        • -
        • keyserver query based on machine-readable output
        • -
        • lock navigation drawer on tablets
        • -
        • suggestions for emails on creation of keys
        • -
        • search in public key lists
        • -
        • and much more improvements and fixes…
        • -
        -

        2.3.1

        -
          -
        • hotfix for crash when upgrading from old versions
        • -
        -

        2.3

        -
          -
        • remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
        • -
        • fix setting expiry dates on keys (thanks to Ash Hughes)
        • -
        • more internal fixes when editing keys (thanks to Ash Hughes)
        • -
        • querying keyservers directly from the import screen
        • -
        • fix layout and dialog style on Android 2.2-3.0
        • -
        • fix crash on keys with empty user ids
        • -
        • fix crash and empty lists when coming back from signing screen
        • -
        • Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
        • -
        • fix upload of key from signing screen
        • -
        -

        2.2

        -
          -
        • new design with navigation drawer
        • -
        • new public key list design
        • -
        • new public key view
        • -
        • bug fixes for importing of keys
        • -
        • key cross-certification (thanks to Ash Hughes)
        • -
        • handle UTF-8 passwords properly (thanks to Ash Hughes)
        • -
        • first version with new languages (thanks to the contributors on Transifex)
        • -
        • sharing of keys via QR Codes fixed and improved
        • -
        • package signature verification for API
        • -
        -

        2.1.1

        -
          -
        • API Updates, preparation for K-9 Mail integration
        • -
        -

        2.1

        -
          -
        • lots of bug fixes
        • -
        • new API for developers
        • -
        • PRNG bug fix by Google
        • -
        -

        2.0

        -
          -
        • complete redesign
        • -
        • share public keys via qr codes, nfc beam
        • -
        • sign keys
        • -
        • upload keys to server
        • -
        • fixes import issues
        • -
        • new AIDL API
        • -
        -

        1.0.8

        -
          -
        • basic keyserver support
        • -
        • app2sd
        • -
        • more choices for pass phrase cache: 1, 2, 4, 8, hours
        • -
        • translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
        • -
        • bugfixes
        • -
        • optimizations
        • -
        -

        1.0.7

        -
          -
        • fixed problem with signature verification of texts with trailing newline
        • -
        • more options for pass phrase cache time to live (20, 40, 60 mins)
        • -
        -

        1.0.6

        -
          -
        • account adding crash on Froyo fixed
        • -
        • secure file deletion
        • -
        • option to delete key file after import
        • -
        • stream encryption/decryption (gallery, etc.)
        • -
        • new options (language, force v3 signatures)
        • -
        • interface changes
        • -
        • bugfixes
        • -
        -

        1.0.5

        -
          -
        • German and Italian translation
        • -
        • much smaller package, due to reduced BC sources
        • -
        • new preferences GUI
        • -
        • layout adjustment for localization
        • -
        • signature bugfix
        • -
        -

        1.0.4

        -
          -
        • fixed another crash caused by some SDK bug with query builder
        • -
        -

        1.0.3

        -
          -
        • fixed crashes during encryption/signing and possibly key export
        • -
        -

        1.0.2

        -
          -
        • filterable key lists
        • -
        • smarter pre-selection of encryption keys
        • -
        • new Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
        • -
        • fixes and additional features (key preselection) for K-9 Mail, new beta build available
        • -
        -

        1.0.1

        -
          -
        • GMail account listing was broken in 1.0.0, fixed again
        • -
        -

        1.0.0

        -
          -
        • K-9 Mail integration, APG supporting beta build of K-9 Mail
        • -
        • support of more file managers (including ASTRO)
        • -
        • Slovenian translation
        • -
        • new database, much faster, less memory usage
        • -
        • defined Intents and content provider for other apps
        • -
        • bugfixes
        • -
        - - diff --git a/OpenKeychain/src/main/res/raw-fa-rIR/help_nfc_beam.html b/OpenKeychain/src/main/res/raw-fa-rIR/help_nfc_beam.html deleted file mode 100644 index 88492731c..000000000 --- a/OpenKeychain/src/main/res/raw-fa-rIR/help_nfc_beam.html +++ /dev/null @@ -1,12 +0,0 @@ - - - -

        How to receive keys

        -
          -
        1. Go to your partners contacts and open the contact you want to share.
        2. -
        3. Hold the two devices back to back (they have to be almost touching) and you’ll feel a vibration.
        4. -
        5. After it vibrates you’ll see the content on your partners device turn into a card-like object with Star Trek warp speed-looking animation in the background.
        6. -
        7. Tap the card and the content will then load on the your device.
        8. -
        - - diff --git a/OpenKeychain/src/main/res/raw-fa-rIR/help_start.html b/OpenKeychain/src/main/res/raw-fa-rIR/help_start.html deleted file mode 100644 index e8c04c7ae..000000000 --- a/OpenKeychain/src/main/res/raw-fa-rIR/help_start.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -

        شروع کار

        -

        First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

        - -

        It is recommended that you install OI File Manager for enhanced file selection and Barcode Scanner to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.

        - -

        Applications

        -

        Several applications support OpenKeychain to encrypt/sign your private communication:

        -

        Conversations: Jabber/XMPP client

        -

        K-9 Mail: OpenKeychain support available in current alpha build!

        - -

        I found a bug in OpenKeychain!

        -

        Please report the bug using the issue tracker of OpenKeychain.

        - -

        هم بخشی کردن

        -

        If you want to help us developing OpenKeychain by contributing code follow our small guide on Github.

        - -

        ترجمه ها

        -

        Help translating OpenKeychain! Everybody can participate at OpenKeychain on Transifex.

        - - - diff --git a/OpenKeychain/src/main/res/raw-fa-rIR/nfc_beam_share.html b/OpenKeychain/src/main/res/raw-fa-rIR/nfc_beam_share.html deleted file mode 100644 index 083e055c7..000000000 --- a/OpenKeychain/src/main/res/raw-fa-rIR/nfc_beam_share.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
          -
        1. Make sure that NFC is turned on in Settings > More > NFC and make sure that Android Beam is also on in the same section.
        2. -
        3. Hold the two devices back to back (they have to be almost touching) and you'll feel a vibration.
        4. -
        5. After it vibrates you'll see the content on your device turn into a card-like object with Star Trek warp speed-looking animation in the background.
        6. -
        7. Tap the card and the content will then load on the other person’s device.
        8. -
        - - diff --git a/OpenKeychain/src/main/res/raw-fr/help_about.html b/OpenKeychain/src/main/res/raw-fr/help_about.html index 00370c77e..351bdc8f4 100644 --- a/OpenKeychain/src/main/res/raw-fr/help_about.html +++ b/OpenKeychain/src/main/res/raw-fr/help_about.html @@ -19,6 +19,7 @@
      • Paul Sarbinowski
      • Sreeram Boyapati
      • Vincent Breitmoser
      • +
      • Tim Bray

      Les développeurs d'APG 1.x

        diff --git a/OpenKeychain/src/main/res/raw-fr/help_changelog.html b/OpenKeychain/src/main/res/raw-fr/help_changelog.html index 3a8b958c8..2746881fb 100644 --- a/OpenKeychain/src/main/res/raw-fr/help_changelog.html +++ b/OpenKeychain/src/main/res/raw-fr/help_changelog.html @@ -3,11 +3,11 @@

        2.7

          -
        • Purple! (Dominik, Vincent)
        • -
        • New key view design (Dominik, Vincent)
        • -
        • New flat Android buttons (Dominik, Vincent)
        • -
        • API fixes (Dominik)
        • -
        • Keybase.io import (Tim Bray)
        • +
        • Violet ! (Dominik, Vincent)
        • +
        • Nouvelle présentation de la visualisation des clefs (Dominik, Vincent)
        • +
        • Nouveaux boutons Android plats (Dominik, Vincent)
        • +
        • Correctifs de l'API (Dominik)
        • +
        • Importation de Keybase.io (Tim Bray)

        2.6.1

          diff --git a/OpenKeychain/src/main/res/raw-fr/help_start.html b/OpenKeychain/src/main/res/raw-fr/help_start.html index 114bc3d81..01a4baa81 100644 --- a/OpenKeychain/src/main/res/raw-fr/help_start.html +++ b/OpenKeychain/src/main/res/raw-fr/help_start.html @@ -4,12 +4,10 @@

          Commencer

          Il vous faut d'abord une clef personnelle secrète. Créez-en une avec l'option du menu dans « Clefs » ou importer des clefs secrètes existantes. Ensuite vous pourrez télécharger les clefs de vos amis ou les échanger avec des codes QR ou par la NFC.

          -

          Il vous est recommendé d'installer le gestionnaire de fichiers OI pour sa fonction améliorée de séléction des fichiers et le lecteur de codes à barres pour balayer les codes QR générés. Cliquer sur les liens ouvrira Google Play Store ou F-Droid pour l'installation.

          +

          Il vous est recommandé d'installer le gestionnaire de fichiers OI pour sa fonction améliorée de sélection des fichiers et le lecteur de codes à barres pour balayer les codes QR générés. Cliquer sur les liens ouvrira Google Play Store ou F-Droid pour l'installation.

          Applications

          -

          Plusieurs applications prennent en charge OpenKeychain pour chiffrer/signer vos communications privées :

          -

          Conversations : un client Jabber/XMPP

          -

          K-9 Mail : la prise en charge d'OpenKeychain est disponible dans la version alpha actuelle !

          +

          Plusieurs applications prennent en charge OpenKeychain pour chiffrer/signer vos communications privées :

          K-9 Mail : OpenKeychain est pris en charge dans la version alphaactuelle !

          Conversations
          : clilent Jabber/XMPP

          PGPAuth
          : appli pour envoyer une demande signée par PGP à un serveur pour ouvrir ou fermer quelque chose, par exemple une porte

          J'ai trouvé un bogue dans OpenKeychain !

          Veuillez rapporter le bogue en utilisant le gestionnaire de bogue d'OpenKeychain.

          diff --git a/OpenKeychain/src/main/res/raw-fr/help_wot.html b/OpenKeychain/src/main/res/raw-fr/help_wot.html new file mode 100644 index 000000000..4162c9b1b --- /dev/null +++ b/OpenKeychain/src/main/res/raw-fr/help_wot.html @@ -0,0 +1,17 @@ + + + +

          Toile confiance

          +

          La toile de confiance décrit la partie de PGP qui s'occupe de la création et du suivi des certifications. Elle fournit des mécanismes pour aider l'utilisateur à suivre à qui appartient une clef publique, et partager cette information avec les autres. Pour assurer la confidentialité d'une communication chiffrée, il est essentiel de savoir que la clef publique vers laquelle vous chiffrez appartient à la personne à qui vous croyez qu'elle appartient.

          + +

          Prise en charge dans OpenKeychain

          +

          OpenKeychain offre seulement une prise en charge de base de la toile de confiance. Un travail important est en cours et ceci pourrait changer dans les versions à venir.

          + +

          Modèle de confiance

          +

          L'évaluation de la confiance est fondée sur la simple supposition que toutes les clefs ayant des clefs secrètes disponibles sont de confiance. Les clefs publiques contenant au moins un ID d'utilisateur certifié par une clef de confiance seront marquées par un point vert dans le listage des clefs. Il n'est pas (encore) possible de spécifier les niveaux de confiance pour les certificats d'autres clefs publiques inconnues.

          + +

          Certifications des clefs

          +

          La prise en charge de la certification des clefs est disponible et les ID d'utilisateur peuvent être certifiées individuellement. Il n'est pas encore possible de spécifier le niveau de confiance ou de créer des certificats locaux et d'autres types spéciaux.

          + + + diff --git a/OpenKeychain/src/main/res/raw-it-rIT/help_about.html b/OpenKeychain/src/main/res/raw-it-rIT/help_about.html deleted file mode 100644 index 8644d3fc6..000000000 --- a/OpenKeychain/src/main/res/raw-it-rIT/help_about.html +++ /dev/null @@ -1,49 +0,0 @@ - - - -

          http://www.openkeychain.org

          -

          OpenKeychain un implementazione OpenPGP per Android.

          -

          Licenza: GPLv3+

          - -

          Sviluppatori OpenKeychain

          -
            -
          • Dominik Schürmann (Capo Sviluppatore)
          • -
          • Ash Hughes (Patch crittografia)
          • -
          • Brian C. Barnes
          • -
          • Bahtiar 'kalkin' Gadimov (Interfaccia Utente)
          • -
          • Daniel Hammann
          • -
          • Daniel Haß
          • -
          • Greg Witczak
          • -
          • Miroojin Bakshi
          • -
          • Nikhil Peter Raj
          • -
          • Paul Sarbinowski
          • -
          • Sreeram Boyapati
          • -
          • Vincent Breitmoser
          • -
          -

          Sviluppatori APG 1.x

          -
            -
          • Thialfihar (Capo Sviluppatore)
          • -
          • 'Senecaso' (QRCode, firma chiavi, caricamento chiavi)
          • -
          • Markus Doits
          • -
          -

          Librerie

          - - - diff --git a/OpenKeychain/src/main/res/raw-it-rIT/help_changelog.html b/OpenKeychain/src/main/res/raw-it-rIT/help_changelog.html deleted file mode 100644 index b2d67ca80..000000000 --- a/OpenKeychain/src/main/res/raw-it-rIT/help_changelog.html +++ /dev/null @@ -1,156 +0,0 @@ - - - -

          2.7

          -
            -
          • Purple! (Dominik, Vincent)
          • -
          • New key view design (Dominik, Vincent)
          • -
          • New flat Android buttons (Dominik, Vincent)
          • -
          • API fixes (Dominik)
          • -
          • Keybase.io import (Tim Bray)
          • -
          -

          2.6.1

          -
            -
          • alcune correzioni per i bug di regressione
          • -
          -

          2.6

          -
            -
          • certificazioni chiave (grazie a Vincent Breitmoser)
          • -
          • supporto per chiavi segrete parziali GnuPG (grazie a Vincent Breitmoser)
          • -
          • nuovo design per la verifica della firma
          • -
          • lunghezza chiave personalizzata (grazie a Greg Witczak)
          • -
          • fix funzionalità di condivisione da altre app
          • -
          -

          2.5

          -
            -
          • Corretta la decodifica di messaggi PGP / file simmetrici
          • -
          • Refactoring della schermata di modifica chiave (grazie a Ash Hughes)
          • -
          • nuovo design moderno per le schermate di codifica / decodifica
          • -
          • OpenPGP API versione 3 (api account multipli, correzioni interne, ricerca chiavi)
          • -
          -

          2.4

          -

          Grazie a tutti i partecipanti di Google Summer of Code 2014 che hanno reso questo rilascio ricco di caratteristiche e privo di bug! -Oltre a numerose piccole correzioni, un notevole numero di patch sono state fatte dalle seguenti persone (in ordine alfabetico): -Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paolo Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.

          -
            -
          • nuova lista chiave unificata
          • -
          • impronta chiave colorata
          • -
          • supporto per porte
          • -
          • disattiva la possibilità di generare chiavi deboli
          • -
          • molto più lavoro interno sulle API
          • -
          • certificazione ID utente
          • -
          • interrogazione keyserver basate su output leggibile a livello macchina
          • -
          • blocco del menu di navigazione sui tablet
          • -
          • suggerimenti per e-mail sulla creazione di chiavi
          • -
          • ricerca nelle liste di chiavi pubbliche
          • -
          • e molti altri miglioramenti e correzioni ...
          • -
          -

          2.3.1

          -
            -
          • correzione del crash quando si aggiorna da versioni precedenti
          • -
          -

          2.3

          -
            -
          • rimossa esportazione non necessaria delle chiavi pubbliche quando si esportano le chiavi private (grazie a Ash Hughes)
          • -
          • corretto impostazione data di scadenza delle chiavi (grazie a Ash Hughes)
          • -
          • altre correzioni interne quando si modificano le chiavi (grazie a Ash Hughes)
          • -
          • interrogazione server delle chiavi direttamente dalla schermata di importazione
          • -
          • corretto layout e dialog style su Android 2.2-3.0
          • -
          • corretto crash su chiavi con id utente vuoto
          • -
          • corretto crash e liste vuote quando si torna dalla schermata di firma
          • -
          • Bouncy Castle (libreria crittografica) aggiornata da 1.47 a 1.50 e compilata da sorgente
          • -
          • corretto upload delle chiavi dalla schermata di firma
          • -
          -

          2.2

          -
            -
          • nuovo design con drawer di navigazione
          • -
          • nuovo design per la lista chiavi pubbliche
          • -
          • nuova visuale chiavi pubbliche
          • -
          • correzione bug per importazione chiavi
          • -
          • Chiave certificazione incrociata (grazie a Ash Hughes)
          • -
          • password UTF-8 gestite correttamente (grazie a Ash Hughes)
          • -
          • Prima versione con nuove lingue (grazie ai contributori su Transifex)
          • -
          • condivisione di chiavi via Codici QR corretta e migliorata
          • -
          • Verifica firma pacchetto per API
          • -
          -

          2.1.1

          -
            -
          • Aggiornamenti API, preparazione per integrazione con K-9 Mail
          • -
          -

          2.1

          -
            -
          • molte correzioni di bug
          • -
          • nuove API per sviluppatori
          • -
          • PRNG bug fix by Google
          • -
          -

          2.0

          -
            -
          • completo restyle
          • -
          • condivisione chiavi pubbliche via codici qr, nfc beam
          • -
          • firma chiavi
          • -
          • Carica chiavi sul server
          • -
          • corrette caratteristiche di importazione
          • -
          • nuova AIDL API
          • -
          -

          1.0.8

          -
            -
          • supporto base per server delle chiavi
          • -
          • app2sd
          • -
          • Aggiunte opzioni per la cache della frase di accesso: 1, 2, 4, 8 ore
          • -
          • Traduzioni: Norvegese (grazie, Sander Danielsen), Cinese (grazie, Zhang Fredrick)
          • -
          • correzione bug
          • -
          • ottimizzazioni
          • -
          -

          1.0.7

          -
            -
          • corretto problema con la verifica firma di testi con capo finale
          • -
          • maggiori opzioni per il tempo di mantenimento della cache della frase di accesso (20, 40, 60 minuti)
          • -
          -

          1.0.6

          -
            -
          • crash della aggiunta degli account risolto su Froyo
          • -
          • Cancellazione sicura dei file
          • -
          • opzione per cancellare file delle chiavi dopo l'importazione
          • -
          • flusso codifica/decodifica (galleria, ecc.)
          • -
          • nuove opzioni (lingua, forza firme v3)
          • -
          • cambiamenti interfaccia
          • -
          • correzione bug
          • -
          -

          1.0.5

          -
            -
          • Traduzione Italiana e Tedesca
          • -
          • dimensioni pacchetto ridotte, a causa della riduzione dei sorgenti BC
          • -
          • Nuove preferenze GUI
          • -
          • Regolazione layout per la localizzazione
          • -
          • correzione bug firma
          • -
          -

          1.0.4

          -
            -
          • corretto altro crash causato da alcuni bug SDK con query builder
          • -
          -

          1.0.3

          -
            -
          • corretto crash durante codifica/firma e possibilita' di esportare chiave
          • -
          -

          1.0.2

          -
            -
          • liste chiavi filtrabili
          • -
          • preselezione di chiavi di codifica intelligente
          • -
          • nuovo gestore intent per VIEW e SEND, permette la codifica/decodifica file all'infuori di file manager
          • -
          • caratteristiche corrette e aggiunte (preselezione chiavi) per K-9 Mail. nuova build beta disponibile
          • -
          -

          1.0.1

          -
            -
          • elencazione account GMail corrotta in 1.0.0, corretta nuovamente
          • -
          -

          1.0.0

          -
            -
          • integrazione K-9 Mail, APG supporto beta build di K-9 Mail
          • -
          • supporto per altri file manager (incluso ASTRO)
          • -
          • traduzione Slovena
          • -
          • Nuovo database, piu' veloce, utilizzo memoria ridotto
          • -
          • Definiti Intent e ContentProvider per le altre app
          • -
          • correzione bug
          • -
          - - diff --git a/OpenKeychain/src/main/res/raw-it-rIT/help_nfc_beam.html b/OpenKeychain/src/main/res/raw-it-rIT/help_nfc_beam.html deleted file mode 100644 index 6ff56194e..000000000 --- a/OpenKeychain/src/main/res/raw-it-rIT/help_nfc_beam.html +++ /dev/null @@ -1,12 +0,0 @@ - - - -

          Come ricevere le chiavi

          -
            -
          1. Vai ai contatti dei tuoi partner e apri il contatto che si desidera condividere.
          2. -
          3. Mantieni i due dispositivi vicini (devono quasi toccarsi) e sentirai una vibrazione.
          4. -
          5. Dopo che ha vibrato, vedrai il contenuto del tuo dispositivo diventare come una scheda e nello sfondo apparirà una animazione come la propulsione a curvatura di Star Trek.
          6. -
          7. Tocca la scheda e il contenuto dopo si trasferira' nel dispositivo dell'altra persona.
          8. -
          - - diff --git a/OpenKeychain/src/main/res/raw-it-rIT/help_start.html b/OpenKeychain/src/main/res/raw-it-rIT/help_start.html deleted file mode 100644 index 77866bc8c..000000000 --- a/OpenKeychain/src/main/res/raw-it-rIT/help_start.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -

          Per iniziare

          -

          In primo luogo è necessaria una chiave segreta personale. Creane una tramite il menu opzioni sotto la voce "Chiavi" o importa chiavi segrete già esistenti. Successivamente, è possibile scaricare le chiavi dei vostri amici o scambiarle con i codici QR o NFC.

          - -

          Si raccomanda di installare OI File Manager per una migliore selezione dei file e Barcode Scanner per scansionare i codici QR. I collegamenti verranno aperti in Google Play Store o F-Droid per l'installazione.

          - -

          Applications

          -

          Several applications support OpenKeychain to encrypt/sign your private communication:

          -

          Conversations: Jabber/XMPP client

          -

          K-9 Mail: OpenKeychain support available in current alpha build!

          - -

          Ho trovato un bug in OpenKeychain!

          -

          Per favore riporta i bug usando il issue tracker di OpenKeychain.

          - -

          Contribuire

          -

          Se vuoi aiutarci nello sviluppo di OpenKeychain contribuendo al codice segui la nostra breve guida su Github.

          - -

          Traduzioni

          -

          Aiutaci a tradurre OpenKeychain! Tutti possono collaborare a OpenKeychain su Transifex.

          - - - diff --git a/OpenKeychain/src/main/res/raw-it-rIT/nfc_beam_share.html b/OpenKeychain/src/main/res/raw-it-rIT/nfc_beam_share.html deleted file mode 100644 index e75877efe..000000000 --- a/OpenKeychain/src/main/res/raw-it-rIT/nfc_beam_share.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
            -
          1. Assicurati che NFC sia acceso in Impostazioni > Altro > NFC a assicurati che Android Beam sia pure su On nella stessa sezione.
          2. -
          3. Mantieni i due dispositivi vicini (devono quasi toccarsi) e sentirai una vibrazione.
          4. -
          5. Dopo che ha vibrato, vedrai il contenuto del tuo dispositivo diventare come una scheda e nello sfondo apparirà una animazione come la propulsione a curvatura di Star Trek.
          6. -
          7. Tocca la scheda e il contenuto dopo si trasferira' nel dispositivo dell'altra persona.
          8. -
          - - diff --git a/OpenKeychain/src/main/res/raw-it/help_about.html b/OpenKeychain/src/main/res/raw-it/help_about.html new file mode 100644 index 000000000..4c8c0af07 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-it/help_about.html @@ -0,0 +1,50 @@ + + + +

          http://www.openkeychain.org

          +

          OpenKeychain un implementazione OpenPGP per Android.

          +

          Licenza: GPLv3+

          + +

          Sviluppatori OpenKeychain

          +
            +
          • Dominik Schürmann (Capo Sviluppatore)
          • +
          • Ash Hughes (Patch crittografia)
          • +
          • Brian C. Barnes
          • +
          • Bahtiar 'kalkin' Gadimov (Interfaccia Utente)
          • +
          • Daniel Hammann
          • +
          • Daniel Haß
          • +
          • Greg Witczak
          • +
          • Miroojin Bakshi
          • +
          • Nikhil Peter Raj
          • +
          • Paul Sarbinowski
          • +
          • Sreeram Boyapati
          • +
          • Vincent Breitmoser
          • +
          • Tim Bray
          • +
          +

          Sviluppatori APG 1.x

          +
            +
          • Thialfihar (Capo Sviluppatore)
          • +
          • 'Senecaso' (QRCode, firma chiavi, caricamento chiavi)
          • +
          • Markus Doits
          • +
          +

          Librerie

          + + + diff --git a/OpenKeychain/src/main/res/raw-it/help_changelog.html b/OpenKeychain/src/main/res/raw-it/help_changelog.html new file mode 100644 index 000000000..ee6a56e15 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-it/help_changelog.html @@ -0,0 +1,156 @@ + + + +

          2.7

          +
            +
          • Porpora! (Dominik, Vincent)
          • +
          • Nuovo design della schermata chiavi (Dominik, Vincent)
          • +
          • Nuovi pulsanti piatti Android (Dominik, Vincent)
          • +
          • Correzioni API (Dominik)
          • +
          • Importazione Keybase.io (Tim Bray)
          • +
          +

          2.6.1

          +
            +
          • alcune correzioni per i bug di regressione
          • +
          +

          2.6

          +
            +
          • certificazioni chiave (grazie a Vincent Breitmoser)
          • +
          • supporto per chiavi segrete parziali GnuPG (grazie a Vincent Breitmoser)
          • +
          • nuovo design per la verifica della firma
          • +
          • lunghezza chiave personalizzata (grazie a Greg Witczak)
          • +
          • fix funzionalità di condivisione da altre app
          • +
          +

          2.5

          +
            +
          • Corretta la decodifica di messaggi PGP / file simmetrici
          • +
          • Refactoring della schermata di modifica chiave (grazie a Ash Hughes)
          • +
          • nuovo design moderno per le schermate di codifica / decodifica
          • +
          • OpenPGP API versione 3 (api account multipli, correzioni interne, ricerca chiavi)
          • +
          +

          2.4

          +

          Grazie a tutti i partecipanti di Google Summer of Code 2014 che hanno reso questo rilascio ricco di caratteristiche e privo di bug! +Oltre a numerose piccole correzioni, un notevole numero di patch sono state fatte dalle seguenti persone (in ordine alfabetico): +Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paolo Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.

          +
            +
          • nuova lista chiave unificata
          • +
          • impronta chiave colorata
          • +
          • supporto per porte
          • +
          • disattiva la possibilità di generare chiavi deboli
          • +
          • molto più lavoro interno sulle API
          • +
          • certificazione ID utente
          • +
          • interrogazione keyserver basate su output leggibile a livello macchina
          • +
          • blocco del menu di navigazione sui tablet
          • +
          • suggerimenti per e-mail sulla creazione di chiavi
          • +
          • ricerca nelle liste di chiavi pubbliche
          • +
          • e molti altri miglioramenti e correzioni ...
          • +
          +

          2.3.1

          +
            +
          • correzione del crash quando si aggiorna da versioni precedenti
          • +
          +

          2.3

          +
            +
          • rimossa esportazione non necessaria delle chiavi pubbliche quando si esportano le chiavi private (grazie a Ash Hughes)
          • +
          • corretto impostazione data di scadenza delle chiavi (grazie a Ash Hughes)
          • +
          • altre correzioni interne quando si modificano le chiavi (grazie a Ash Hughes)
          • +
          • interrogazione server delle chiavi direttamente dalla schermata di importazione
          • +
          • corretto layout e dialog style su Android 2.2-3.0
          • +
          • corretto crash su chiavi con id utente vuoto
          • +
          • corretto crash e liste vuote quando si torna dalla schermata di firma
          • +
          • Bouncy Castle (libreria crittografica) aggiornata da 1.47 a 1.50 e compilata da sorgente
          • +
          • corretto upload delle chiavi dalla schermata di firma
          • +
          +

          2.2

          +
            +
          • nuovo design con drawer di navigazione
          • +
          • nuovo design per la lista chiavi pubbliche
          • +
          • nuova visuale chiavi pubbliche
          • +
          • correzione bug per importazione chiavi
          • +
          • Chiave certificazione incrociata (grazie a Ash Hughes)
          • +
          • password UTF-8 gestite correttamente (grazie a Ash Hughes)
          • +
          • Prima versione con nuove lingue (grazie ai contributori su Transifex)
          • +
          • condivisione di chiavi via Codici QR corretta e migliorata
          • +
          • Verifica firma pacchetto per API
          • +
          +

          2.1.1

          +
            +
          • Aggiornamenti API, preparazione per integrazione con K-9 Mail
          • +
          +

          2.1

          +
            +
          • molte correzioni di bug
          • +
          • nuove API per sviluppatori
          • +
          • PRNG bug fix by Google
          • +
          +

          2.0

          +
            +
          • completo restyle
          • +
          • condivisione chiavi pubbliche via codici qr, nfc beam
          • +
          • firma chiavi
          • +
          • Carica chiavi sul server
          • +
          • corrette caratteristiche di importazione
          • +
          • nuova AIDL API
          • +
          +

          1.0.8

          +
            +
          • supporto base per server delle chiavi
          • +
          • app2sd
          • +
          • Aggiunte opzioni per la cache della frase di accesso: 1, 2, 4, 8 ore
          • +
          • Traduzioni: Norvegese (grazie, Sander Danielsen), Cinese (grazie, Zhang Fredrick)
          • +
          • correzione bug
          • +
          • ottimizzazioni
          • +
          +

          1.0.7

          +
            +
          • corretto problema con la verifica firma di testi con capo finale
          • +
          • maggiori opzioni per il tempo di mantenimento della cache della frase di accesso (20, 40, 60 minuti)
          • +
          +

          1.0.6

          +
            +
          • crash della aggiunta degli account risolto su Froyo
          • +
          • Cancellazione sicura dei file
          • +
          • opzione per cancellare file delle chiavi dopo l'importazione
          • +
          • flusso codifica/decodifica (galleria, ecc.)
          • +
          • nuove opzioni (lingua, forza firme v3)
          • +
          • cambiamenti interfaccia
          • +
          • correzione bug
          • +
          +

          1.0.5

          +
            +
          • Traduzione Italiana e Tedesca
          • +
          • dimensioni pacchetto ridotte, a causa della riduzione dei sorgenti BC
          • +
          • Nuove preferenze GUI
          • +
          • Regolazione layout per la localizzazione
          • +
          • correzione bug firma
          • +
          +

          1.0.4

          +
            +
          • corretto altro crash causato da alcuni bug SDK con query builder
          • +
          +

          1.0.3

          +
            +
          • corretto crash durante codifica/firma e possibilita' di esportare chiave
          • +
          +

          1.0.2

          +
            +
          • liste chiavi filtrabili
          • +
          • preselezione di chiavi di codifica intelligente
          • +
          • nuovo gestore intent per VIEW e SEND, permette la codifica/decodifica file all'infuori di file manager
          • +
          • caratteristiche corrette e aggiunte (preselezione chiavi) per K-9 Mail. nuova build beta disponibile
          • +
          +

          1.0.1

          +
            +
          • elencazione account GMail corrotta in 1.0.0, corretta nuovamente
          • +
          +

          1.0.0

          +
            +
          • integrazione K-9 Mail, APG supporto beta build di K-9 Mail
          • +
          • supporto per altri file manager (incluso ASTRO)
          • +
          • traduzione Slovena
          • +
          • Nuovo database, piu' veloce, utilizzo memoria ridotto
          • +
          • Definiti Intent e ContentProvider per le altre app
          • +
          • correzione bug
          • +
          + + diff --git a/OpenKeychain/src/main/res/raw-it/help_nfc_beam.html b/OpenKeychain/src/main/res/raw-it/help_nfc_beam.html new file mode 100644 index 000000000..6ff56194e --- /dev/null +++ b/OpenKeychain/src/main/res/raw-it/help_nfc_beam.html @@ -0,0 +1,12 @@ + + + +

          Come ricevere le chiavi

          +
            +
          1. Vai ai contatti dei tuoi partner e apri il contatto che si desidera condividere.
          2. +
          3. Mantieni i due dispositivi vicini (devono quasi toccarsi) e sentirai una vibrazione.
          4. +
          5. Dopo che ha vibrato, vedrai il contenuto del tuo dispositivo diventare come una scheda e nello sfondo apparirà una animazione come la propulsione a curvatura di Star Trek.
          6. +
          7. Tocca la scheda e il contenuto dopo si trasferira' nel dispositivo dell'altra persona.
          8. +
          + + diff --git a/OpenKeychain/src/main/res/raw-it/help_start.html b/OpenKeychain/src/main/res/raw-it/help_start.html new file mode 100644 index 000000000..138e0ece2 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-it/help_start.html @@ -0,0 +1,22 @@ + + + +

          Per iniziare

          +

          In primo luogo è necessaria una chiave segreta personale. Creane una tramite il menu opzioni sotto la voce "Chiavi" o importa chiavi segrete già esistenti. Successivamente, è possibile scaricare le chiavi dei vostri amici o scambiarle con i codici QR o NFC.

          + +

          Si raccomanda di installare OI File Manager per una migliore selezione dei file e Barcode Scanner per scansionare i codici QR. I collegamenti verranno aperti in Google Play Store o F-Droid per l'installazione.

          + +

          Applicazioni

          +

          Diverse applicazioni supportano OpenKeychain per codificare/firmare le tue comunicazioni private:

          K-9 Mail: Supporto per OpenKeychain disponibile nella attuale versione alpha!

          Conversations
          : Client Jabber/XMPP

          App per inviare una richiesta firmata PGP a un server per aprire o chiudere qualcosa, ad esempio, una porta

          + +

          Ho trovato un bug in OpenKeychain!

          +

          Per favore riporta i bug usando il issue tracker di OpenKeychain.

          + +

          Contribuire

          +

          Se vuoi aiutarci nello sviluppo di OpenKeychain contribuendo al codice segui la nostra breve guida su Github.

          + +

          Traduzioni

          +

          Aiutaci a tradurre OpenKeychain! Tutti possono collaborare a OpenKeychain su Transifex.

          + + + diff --git a/OpenKeychain/src/main/res/raw-it/help_wot.html b/OpenKeychain/src/main/res/raw-it/help_wot.html new file mode 100644 index 000000000..98e3aafea --- /dev/null +++ b/OpenKeychain/src/main/res/raw-it/help_wot.html @@ -0,0 +1,17 @@ + + + +

          Rete di Fiducia

          +

          La Rete di Fiducia descrive la parte del PGP che si occupa di creazione e gestione delle certificazioni. Essa fornisce meccanismi per aiutare l'utente a tenere traccia di chi appartiene una chiave pubblica, e condividere queste informazioni con gli altri; Per garantire la privacy della comunicazione crittografata, è essenziale sapere che la chiave pubblica per crittografare appartiene alla persona che si pensa.

          + +

          Supporto in OpenKeychain

          +

          Esiste solo un supporto di base per le Reti di Fiducia in OpenKeychain. Questo è un grosso lavoro in corso e soggetto a modifiche nei prossimi rilasci.

          + +

          Modello di Fiducia

          +

          La valutazione di fiducia si basa sul semplice presupposto che tutte le chiavi che hanno chiavi segrete disponibili sono attendibili. Le chiavi pubbliche che contengono almeno un id utente certificato da una chiave di fiducia saranno contrassegnati con un punto verde negli elenchi principali. Non è (ancora) possibile specificare livelli di attendibilità per i certificati di altre chiavi pubbliche conosciute.

          + +

          Chiavi di certificazione

          +

          Il supporto per la certificazione chiave è disponibile, e gli id utenti possono essere certificati singolarmente. Non è ancora possibile specificare il livello di fiducia o creare certificati locali e altro di tipo speciale.

          + + + diff --git a/OpenKeychain/src/main/res/raw-it/nfc_beam_share.html b/OpenKeychain/src/main/res/raw-it/nfc_beam_share.html new file mode 100644 index 000000000..e75877efe --- /dev/null +++ b/OpenKeychain/src/main/res/raw-it/nfc_beam_share.html @@ -0,0 +1,11 @@ + + + +
            +
          1. Assicurati che NFC sia acceso in Impostazioni > Altro > NFC a assicurati che Android Beam sia pure su On nella stessa sezione.
          2. +
          3. Mantieni i due dispositivi vicini (devono quasi toccarsi) e sentirai una vibrazione.
          4. +
          5. Dopo che ha vibrato, vedrai il contenuto del tuo dispositivo diventare come una scheda e nello sfondo apparirà una animazione come la propulsione a curvatura di Star Trek.
          6. +
          7. Tocca la scheda e il contenuto dopo si trasferira' nel dispositivo dell'altra persona.
          8. +
          + + diff --git a/OpenKeychain/src/main/res/raw-ja/help_about.html b/OpenKeychain/src/main/res/raw-ja/help_about.html index e60add867..a4670e103 100644 --- a/OpenKeychain/src/main/res/raw-ja/help_about.html +++ b/OpenKeychain/src/main/res/raw-ja/help_about.html @@ -19,6 +19,7 @@
        • Paul Sarbinowski
        • Sreeram Boyapati
        • Vincent Breitmoser
        • +
        • Tim Bray

        APG 1.xの開発者達

          diff --git a/OpenKeychain/src/main/res/raw-ja/help_changelog.html b/OpenKeychain/src/main/res/raw-ja/help_changelog.html index 4bf40cbc3..0aae03ba6 100644 --- a/OpenKeychain/src/main/res/raw-ja/help_changelog.html +++ b/OpenKeychain/src/main/res/raw-ja/help_changelog.html @@ -4,10 +4,10 @@

          2.7

          • Purple! (Dominik, Vincent)
          • -
          • New key view design (Dominik, Vincent)
          • -
          • New flat Android buttons (Dominik, Vincent)
          • -
          • API fixes (Dominik)
          • -
          • Keybase.io import (Tim Bray)
          • +
          • 新しい鍵のビューのデザイン (Dominik, Vincent)
          • +
          • 新しいフラットな Android ボタン (Dominik, Vincent)
          • +
          • API のフィックス (Dominik)
          • +
          • Keybase.io からのインポート (Tim Bray)

          2.6.1

            diff --git a/OpenKeychain/src/main/res/raw-ja/help_start.html b/OpenKeychain/src/main/res/raw-ja/help_start.html index 502d4adb8..1e522cc74 100644 --- a/OpenKeychain/src/main/res/raw-ja/help_start.html +++ b/OpenKeychain/src/main/res/raw-ja/help_start.html @@ -2,14 +2,12 @@

            入門

            -

            最初にあなたの個人用秘密鍵が必要になります。オプションメニューの"鍵"で生成するか、既存の秘密鍵をインポートします。その後、あなたの友人の鍵をダウンロード、もしくはQRコードやNFCで交換します。

            +

            最初にあなたの個人用秘密鍵が必要になります。オプションメニューの"鍵"で生成するか、既存の秘密鍵をインポートします。その後、あなたの友人の鍵をダウンロード、もしくはQRコードやNFCで交換します。

            ファイルの選択を拡張するにはOI File ManagerBarcode Scannerを生成したQRコードのスキャンのため、それぞれのインストールを必要とします。 リンクをクリックして、Google Play Store上かF-Droidからインストールしてください。

            -

            Applications

            -

            Several applications support OpenKeychain to encrypt/sign your private communication:

            -

            Conversations: Jabber/XMPP client

            -

            K-9 Mail: OpenKeychain support available in current alpha build!

            +

            アプリケーション

            +

            OpenKeychainはプライベートな通信での暗号化/署名をいくつかのアプリケーションでサポートしています:

            K-9 Mail: 現在のOpenKeychain alpha build からサポートが有効です!

            やりとり
            : Jabber/XMPP クライアント

            PGPAuth
            : このアプリはPGP署名されたリクエストをサーバに送り、なにかしらを開けたり閉じたりします、たとえばドアとか

            OpenKeychainでバグを見付けた!

            OpenKeychainのIssueトラッカーを使ってバグレポートを送ってください。

            diff --git a/OpenKeychain/src/main/res/raw-ja/help_wot.html b/OpenKeychain/src/main/res/raw-ja/help_wot.html new file mode 100644 index 000000000..3675b6258 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-ja/help_wot.html @@ -0,0 +1,17 @@ + + + +

            信頼の輪

            +

            信頼の輪はPGPが証明の作成と維持する一面を説明します。ユーザが公開鍵が属する者の追跡を維持し、他のユーザーとその情報を共有する手助けになるメカニズムを提供します。暗号化通信のプライバシーを確保するためには、あなたが暗号化したいという相手の公開鍵が必要な要素となります

            + +

            OpenKeychainでサポート

            +

            OpenKeychainで信頼の輪の基本のみサポートされます。とても重い作業を進めており今後やってくるリリースにおいて状態が変更されていきます。

            + +

            信頼モデル

            +

            信頼の評価はシンプルな仮定に基づいています、それはすべての鍵は秘密鍵が信頼できるというものです。公開鍵は信頼された鍵で検証された最低1つのユーザIDを含んでおり、それは鍵リストにおいて、緑でマークされます。ただしそれは他の既知の公開鍵の信頼レベルを特別なものには(まだ)しません。

            + +

            鍵の検証

            +

            鍵検証のサポートが提供されており、ユーザIDは個別に検証できます。ただしそれは他の既知の公開鍵の信頼レベルを特別なものにはまだしないか他の特別なタイプの証明です。

            + + + diff --git a/OpenKeychain/src/main/res/raw-ko/help_about.html b/OpenKeychain/src/main/res/raw-ko/help_about.html index ae7e16aae..ab3c19375 100644 --- a/OpenKeychain/src/main/res/raw-ko/help_about.html +++ b/OpenKeychain/src/main/res/raw-ko/help_about.html @@ -19,6 +19,7 @@
          • Paul Sarbinowski
          • Sreeram Boyapati
          • Vincent Breitmoser
          • +
          • Tim Bray

          Developers APG 1.x

            diff --git a/OpenKeychain/src/main/res/raw-ko/help_start.html b/OpenKeychain/src/main/res/raw-ko/help_start.html index 6ded872ea..3a681f8fa 100644 --- a/OpenKeychain/src/main/res/raw-ko/help_start.html +++ b/OpenKeychain/src/main/res/raw-ko/help_start.html @@ -2,14 +2,12 @@

            Getting started

            -

            First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

            +

            First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

            It is recommended that you install OI File Manager for enhanced file selection and Barcode Scanner to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.

            Applications

            -

            Several applications support OpenKeychain to encrypt/sign your private communication:

            -

            Conversations: Jabber/XMPP client

            -

            K-9 Mail: OpenKeychain support available in current alpha build!

            +

            Several applications support OpenKeychain to encrypt/sign your private communication:

            K-9 Mail: OpenKeychain support available in current alpha build!

            Conversations
            : Jabber/XMPP client

            PGPAuth
            : App to send a PGP-signed request to a server to open or close something, e.g. a door

            I found a bug in OpenKeychain!

            Please report the bug using the issue tracker of OpenKeychain.

            diff --git a/OpenKeychain/src/main/res/raw-ko/help_wot.html b/OpenKeychain/src/main/res/raw-ko/help_wot.html new file mode 100644 index 000000000..29790139b --- /dev/null +++ b/OpenKeychain/src/main/res/raw-ko/help_wot.html @@ -0,0 +1,17 @@ + + + +

            Web of Trust

            +

            The Web of Trust describes the part of PGP which deals with creation and bookkeeping of certifications. It provides mechanisms to help the user keep track of who a public key belongs to, and share this information with others; To ensure the privacy of encrypted communication, it is essential to know that the public key you encrypt to belongs to the person you think it does.

            + +

            Support in OpenKeychain

            +

            There is only basic support for Web of Trust in OpenKeychain. This is a heavy work in progress and subject to changes in upcoming releases.

            + +

            Trust Model

            +

            Trust evaluation is based on the simple assumption that all keys which have secret keys available are trusted. Public keys which contain at least one user id certified by a trusted key will be marked with a green dot in the key listings. It is not (yet) possible to specify trust levels for certificates of other known public keys.

            + +

            Certifying keys

            +

            Support for key certification is available, and user ids can be certified individually. It is not yet possible to specify the level of trust or create local and other special types of certificates.

            + + + diff --git a/OpenKeychain/src/main/res/raw-nl-rNL/help_about.html b/OpenKeychain/src/main/res/raw-nl-rNL/help_about.html deleted file mode 100644 index ae7e16aae..000000000 --- a/OpenKeychain/src/main/res/raw-nl-rNL/help_about.html +++ /dev/null @@ -1,49 +0,0 @@ - - - -

            http://www.openkeychain.org

            -

            OpenKeychain is an OpenPGP implementation for Android.

            -

            License: GPLv3+

            - -

            Developers OpenKeychain

            -
              -
            • Dominik Schürmann (Lead developer)
            • -
            • Ash Hughes (crypto patches)
            • -
            • Brian C. Barnes
            • -
            • Bahtiar 'kalkin' Gadimov (UI)
            • -
            • Daniel Hammann
            • -
            • Daniel Haß
            • -
            • Greg Witczak
            • -
            • Miroojin Bakshi
            • -
            • Nikhil Peter Raj
            • -
            • Paul Sarbinowski
            • -
            • Sreeram Boyapati
            • -
            • Vincent Breitmoser
            • -
            -

            Developers APG 1.x

            -
              -
            • Thialfihar (Lead developer)
            • -
            • 'Senecaso' (QRCode, sign key, upload key)
            • -
            • Markus Doits
            • -
            -

            Libraries

            - - - diff --git a/OpenKeychain/src/main/res/raw-nl-rNL/help_changelog.html b/OpenKeychain/src/main/res/raw-nl-rNL/help_changelog.html deleted file mode 100644 index ebada67f9..000000000 --- a/OpenKeychain/src/main/res/raw-nl-rNL/help_changelog.html +++ /dev/null @@ -1,156 +0,0 @@ - - - -

            2.7

            -
              -
            • Purple! (Dominik, Vincent)
            • -
            • New key view design (Dominik, Vincent)
            • -
            • New flat Android buttons (Dominik, Vincent)
            • -
            • API fixes (Dominik)
            • -
            • Keybase.io import (Tim Bray)
            • -
            -

            2.6.1

            -
              -
            • some fixes for regression bugs
            • -
            -

            2.6

            -
              -
            • key certifications (thanks to Vincent Breitmoser)
            • -
            • support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
            • -
            • new design for signature verification
            • -
            • custom key length (thanks to Greg Witczak)
            • -
            • fix share-functionality from other apps
            • -
            -

            2.5

            -
              -
            • fix decryption of symmetric pgp messages/files
            • -
            • refactored edit key screen (thanks to Ash Hughes)
            • -
            • new modern design for encrypt/decrypt screens
            • -
            • OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
            • -
            -

            2.4

            -

            Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free! -Besides several small patches, a notable number of patches are made by the following people (in alphabetical order): -Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.

            -
              -
            • new unified key list
            • -
            • colorized key fingerprint
            • -
            • support for keyserver ports
            • -
            • deactivate possibility to generate weak keys
            • -
            • much more internal work on the API
            • -
            • certify user ids
            • -
            • keyserver query based on machine-readable output
            • -
            • lock navigation drawer on tablets
            • -
            • suggestions for emails on creation of keys
            • -
            • search in public key lists
            • -
            • and much more improvements and fixes…
            • -
            -

            2.3.1

            -
              -
            • hotfix for crash when upgrading from old versions
            • -
            -

            2.3

            -
              -
            • remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
            • -
            • fix setting expiry dates on keys (thanks to Ash Hughes)
            • -
            • more internal fixes when editing keys (thanks to Ash Hughes)
            • -
            • querying keyservers directly from the import screen
            • -
            • fix layout and dialog style on Android 2.2-3.0
            • -
            • fix crash on keys with empty user ids
            • -
            • fix crash and empty lists when coming back from signing screen
            • -
            • Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
            • -
            • fix upload of key from signing screen
            • -
            -

            2.2

            -
              -
            • new design with navigation drawer
            • -
            • new public key list design
            • -
            • new public key view
            • -
            • bug fixes for importing of keys
            • -
            • key cross-certification (thanks to Ash Hughes)
            • -
            • handle UTF-8 passwords properly (thanks to Ash Hughes)
            • -
            • first version with new languages (thanks to the contributors on Transifex)
            • -
            • sharing of keys via QR Codes fixed and improved
            • -
            • package signature verification for API
            • -
            -

            2.1.1

            -
              -
            • API Updates, preparation for K-9 Mail integration
            • -
            -

            2.1

            -
              -
            • lots of bug fixes
            • -
            • new API for developers
            • -
            • PRNG bug fix by Google
            • -
            -

            2.0

            -
              -
            • complete redesign
            • -
            • share public keys via qr codes, nfc beam
            • -
            • sign keys
            • -
            • upload keys to server
            • -
            • fixes import issues
            • -
            • new AIDL API
            • -
            -

            1.0.8

            -
              -
            • basic keyserver support
            • -
            • app2sd
            • -
            • more choices for pass phrase cache: 1, 2, 4, 8, hours
            • -
            • translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
            • -
            • bugfixes
            • -
            • optimizations
            • -
            -

            1.0.7

            -
              -
            • fixed problem with signature verification of texts with trailing newline
            • -
            • more options for pass phrase cache time to live (20, 40, 60 mins)
            • -
            -

            1.0.6

            -
              -
            • account adding crash on Froyo fixed
            • -
            • secure file deletion
            • -
            • option to delete key file after import
            • -
            • stream encryption/decryption (gallery, etc.)
            • -
            • new options (language, force v3 signatures)
            • -
            • interface changes
            • -
            • bugfixes
            • -
            -

            1.0.5

            -
              -
            • German and Italian translation
            • -
            • much smaller package, due to reduced BC sources
            • -
            • new preferences GUI
            • -
            • layout adjustment for localization
            • -
            • signature bugfix
            • -
            -

            1.0.4

            -
              -
            • fixed another crash caused by some SDK bug with query builder
            • -
            -

            1.0.3

            -
              -
            • fixed crashes during encryption/signing and possibly key export
            • -
            -

            1.0.2

            -
              -
            • filterable key lists
            • -
            • smarter pre-selection of encryption keys
            • -
            • new Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
            • -
            • fixes and additional features (key preselection) for K-9 Mail, new beta build available
            • -
            -

            1.0.1

            -
              -
            • GMail account listing was broken in 1.0.0, fixed again
            • -
            -

            1.0.0

            -
              -
            • K-9 Mail integration, APG supporting beta build of K-9 Mail
            • -
            • support of more file managers (including ASTRO)
            • -
            • Slovenian translation
            • -
            • new database, much faster, less memory usage
            • -
            • defined Intents and content provider for other apps
            • -
            • bugfixes
            • -
            - - diff --git a/OpenKeychain/src/main/res/raw-nl-rNL/help_nfc_beam.html b/OpenKeychain/src/main/res/raw-nl-rNL/help_nfc_beam.html deleted file mode 100644 index 88492731c..000000000 --- a/OpenKeychain/src/main/res/raw-nl-rNL/help_nfc_beam.html +++ /dev/null @@ -1,12 +0,0 @@ - - - -

            How to receive keys

            -
              -
            1. Go to your partners contacts and open the contact you want to share.
            2. -
            3. Hold the two devices back to back (they have to be almost touching) and you’ll feel a vibration.
            4. -
            5. After it vibrates you’ll see the content on your partners device turn into a card-like object with Star Trek warp speed-looking animation in the background.
            6. -
            7. Tap the card and the content will then load on the your device.
            8. -
            - - diff --git a/OpenKeychain/src/main/res/raw-nl-rNL/help_start.html b/OpenKeychain/src/main/res/raw-nl-rNL/help_start.html deleted file mode 100644 index 6ded872ea..000000000 --- a/OpenKeychain/src/main/res/raw-nl-rNL/help_start.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -

            Getting started

            -

            First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

            - -

            It is recommended that you install OI File Manager for enhanced file selection and Barcode Scanner to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.

            - -

            Applications

            -

            Several applications support OpenKeychain to encrypt/sign your private communication:

            -

            Conversations: Jabber/XMPP client

            -

            K-9 Mail: OpenKeychain support available in current alpha build!

            - -

            I found a bug in OpenKeychain!

            -

            Please report the bug using the issue tracker of OpenKeychain.

            - -

            Contribute

            -

            If you want to help us developing OpenKeychain by contributing code follow our small guide on Github.

            - -

            Translations

            -

            Help translating OpenKeychain! Everybody can participate at OpenKeychain on Transifex.

            - - - diff --git a/OpenKeychain/src/main/res/raw-nl-rNL/nfc_beam_share.html b/OpenKeychain/src/main/res/raw-nl-rNL/nfc_beam_share.html deleted file mode 100644 index 083e055c7..000000000 --- a/OpenKeychain/src/main/res/raw-nl-rNL/nfc_beam_share.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
              -
            1. Make sure that NFC is turned on in Settings > More > NFC and make sure that Android Beam is also on in the same section.
            2. -
            3. Hold the two devices back to back (they have to be almost touching) and you'll feel a vibration.
            4. -
            5. After it vibrates you'll see the content on your device turn into a card-like object with Star Trek warp speed-looking animation in the background.
            6. -
            7. Tap the card and the content will then load on the other person’s device.
            8. -
            - - diff --git a/OpenKeychain/src/main/res/raw-nl/help_about.html b/OpenKeychain/src/main/res/raw-nl/help_about.html new file mode 100644 index 000000000..0ac14d919 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-nl/help_about.html @@ -0,0 +1,50 @@ + + + +

            http://www.openkeychain.org

            +

            OpenKeychain is een OpenPGP implementatie voor Android.

            +

            Licentie: GPLv3+

            + +

            Ontwikkelaars OpenKeychain

            +
              +
            • Dominik Schürmann (hoofdontwikkelaar)
            • +
            • Ash Hughes (crypto patches)
            • +
            • Brian C. Barnes
            • +
            • Bahtiar 'kalkin' Gadimov (UI)
            • +
            • Daniel Hammann
            • +
            • Daniel Haß
            • +
            • Greg Witczak
            • +
            • Miroojin Bakshi
            • +
            • Nikhil Peter Raj
            • +
            • Paul Sarbinowski
            • +
            • Sreeram Boyapati
            • +
            • Vincent Breitmoser
            • +
            • Tim Bray
            • +
            +

            Ontwikkelaars APG 1.x

            +
              +
            • Thialfihar (Hoofdontwikkelaar)
            • +
            • 'Senecaso' (QRCode, signeersleutel, uploadsleutel)
            • +
            • Markus Doits
            • +
            +

            Bibliotheken

            + + + diff --git a/OpenKeychain/src/main/res/raw-nl/help_changelog.html b/OpenKeychain/src/main/res/raw-nl/help_changelog.html new file mode 100644 index 000000000..38da3d57c --- /dev/null +++ b/OpenKeychain/src/main/res/raw-nl/help_changelog.html @@ -0,0 +1,156 @@ + + + +

            2.7

            +
              +
            • Paars! (Dominik, Vincent)
            • +
            • Nieuw sleutel scherm design (Dominik, Vincent)
            • +
            • Nieuwe platte Android toetsen (Dominik, Vincent)
            • +
            • API fixes (Dominik)
            • +
            • Keybase.io import (Tim Bray)
            • +
            +

            2.6.1

            +
              +
            • enige fixes voor regressie bugs
            • +
            +

            2.6

            +
              +
            • sleutel certificaties (dank aan Vincent Breitmoser)
            • +
            • support voor GnuPG deel geheime sleutels (dank aan Vincent Breitmoser)
            • +
            • nieuw design voor handtekeningsverificatie
            • +
            • aangepaste sleutellengte (dank aan Greg Witczak)
            • +
            • fix deel-functionaliteit van andere apps
            • +
            +

            2.5

            +
              +
            • fix decodering van symmetrische pgp berichten/bestanden
            • +
            • bewerk sleutel scherm opnieuw gedaan (dank aan Ash Hughes)
            • +
            • nieuw modern design voor codeer/decodeer schermen
            • +
            • OpenPGP API versie 3 (meerdere api accounts, interne fixes, sleutel lookup)
            • +
            +

            2.4

            +

            Bedankt aan alle gegadigden van Google Summer of Code 2014 die deze release feature groot en zonder bugs maakten! +Naast meerdere kleine patches zijn een redelijk aantal patches gemaakt door de volgende mensen (in alfabetische volgorde): +Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.

            +
              +
            • nieuwe verenigde sleutellijst
            • +
            • gekleurde sleutel vingerafdruk
            • +
            • support voor sleutelserver ports
            • +
            • deactiveer mogelijkheid om zwakke sleutels te genereren
            • +
            • veel meer intern werk aan het API
            • +
            • certificeer gebruiker ids
            • +
            • sleutelserver opdracht gebaseerd op machine-leesbare output
            • +
            • Versleutel navigatiemenu op tablets
            • +
            • suggesties voor e-mails bij aanmaken van sleutels
            • +
            • zoek in publieke sleutel lijsten
            • +
            • en veel meer verbeteringen en fixes...
            • +
            +

            2.3.1

            +
              +
            • hotfix voor crash bij het upgraden van oude versies
            • +
            +

            2.3

            +
              +
            • verwijder onnodige export van publieke sleutels bij het exporteren van de geheime sleutel (dank aan Ash Hughes)
            • +
            • fix instellingen verloopdata op sleutels (dank aan Ash Hughes)
            • +
            • meer interne fixes tijdens het bewerken van sleutels (dank aan Ash Hughes)
            • +
            • sleutelservers direct van het importeerscherm zoeken
            • +
            • fix layout en dialoog stijl op Android 2.2-3.0
            • +
            • fix crash op sleutels met lege gebruiker id's
            • +
            • fix crash en lege lijsten bij het terugkomen van het ondertekenscherm
            • +
            • Bouncy Castle (cryptografie bibliotheek) bijgewerkt van 1.47 naar 1.50 en versie van bron
            • +
            • fix uploaden van sleutel van ondertekenscherm
            • +
            +

            2.2

            +
              +
            • nieuw design met navigatiemenu
            • +
            • nieuw publieke sleutel lijst design
            • +
            • nieuw publieke sleutel uiterlijk
            • +
            • bug fixes voor importeren van sleutels
            • +
            • sleutel kruis-certificatie (dank aan Ash Hughes)
            • +
            • behandelt UTF-8 wachtwoorden goed (dank aan Ash Hughes)
            • +
            • eerste versie met nieuwe talen (dank aan de medewerkers bij Transifex)
            • +
            • delen van sleutels via QR Codes gefixt en verbeterd
            • +
            • pakket handtekening verificatie voor API
            • +
            +

            2.1.1

            +
              +
            • API Updates, voorbereiding voor K-9 Mail integratie
            • +
            +

            2.1

            +
              +
            • veel bugfixes
            • +
            • nieuwe API voor ontwikkelaars
            • +
            • PRNG bug fix door Google
            • +
            +

            2.0

            +
              +
            • complete herdesign
            • +
            • deel publieke sleutels via qr codes, nfc beam
            • +
            • sleutels ondertekenen
            • +
            • upload sleutels naar server
            • +
            • fixt importeerfouten
            • +
            • nieuwe AIDL API
            • +
            +

            1.0.8

            +
              +
            • basis sleutelserver support
            • +
            • app2sd
            • +
            • meer keuzes voor wachtwoord cache: 1, 2, 4, 8, uren
            • +
            • vertalingen: Noors (bedankt, Sander Danielsen), Chinees (bedankt, Zhang Fredrick)
            • +
            • bugfixes
            • +
            • optimalisaties
            • +
            +

            1.0.7

            +
              +
            • probleem met handtekeningverificatie van teksten met nieuwe trailing newline gefixt
            • +
            • meer opties voor wachtwoord cache tijd te leven (20, 40, 60 minuten)
            • +
            +

            1.0.6

            +
              +
            • account toevoegen crash op Froyo gefixt
            • +
            • veilige bestandsverwijdering
            • +
            • optie om sleutel te verwijderen na importeren
            • +
            • stream codering/decodering (gallery, etc.)
            • +
            • nieuwe opties (taal, force v3 handtekeningen)
            • +
            • interface veranderingen
            • +
            • bugfixes
            • +
            +

            1.0.5

            +
              +
            • Duitse en Italiaanse vertaling
            • +
            • veel kleiner pakket, door verminderde BC bronnen
            • +
            • nieuwe voorkeuren GUI
            • +
            • layout aanpassing voor plaatsbepaling
            • +
            • handtekening bugfix
            • +
            +

            1.0.4

            +
              +
            • nog een crash gefixt veroorzaakt door een SDK bug met query builder
            • +
            +

            1.0.3

            +
              +
            • crashes tijdens codering/signering en mogelijk sleutel importeren gefixt
            • +
            +

            1.0.2

            +
              +
            • filterbare sleutellijsten
            • +
            • slimmere voor-selectie van codeersleutels
            • +
            • nieuwe Intent behandeling voor VIEW en SEND, maakt het mogelijk om bestanden te coderen/decoderen uit bestandsmanagers
            • +
            • fixes en meer functies (sleutel voorselectie) voor K-9 Mail, nieuwe beta versie beschikbaar
            • +
            +

            1.0.1

            +
              +
            • GMail account lijsten was stuk in 1.0.0, weer gefixt
            • +
            +

            1.0.0

            +
              +
            • K-9 Mail integratie, APG ondersteunende beta versie van K-9 Mail
            • +
            • support voor meer bestandsmanagers (inclusief ASTRO)
            • +
            • Slovenische vertaling
            • +
            • nieuwe database, veel sneller, minder geheugenverbruik
            • +
            • gedefinieerde Intents en inhoudsprovider voor andere apps
            • +
            • bugfixes
            • +
            + + diff --git a/OpenKeychain/src/main/res/raw-nl/help_nfc_beam.html b/OpenKeychain/src/main/res/raw-nl/help_nfc_beam.html new file mode 100644 index 000000000..ac5cebb4b --- /dev/null +++ b/OpenKeychain/src/main/res/raw-nl/help_nfc_beam.html @@ -0,0 +1,12 @@ + + + +

            Hoe sleutels te ontvangen

            +
              +
            1. Ga naar uw partners contacten en open het contact dat u wilt delen.
            2. +
            3. Houd de twee apparaten met de achterkant tegen elkaar (ze moeten elkaar bijna aanraken) en u zult een trilling voelen.
            4. +
            5. Nadat het trilt zult u de inhoud op uw partners apparaat in een soort kaart zien veranderen met Star Trek warp snelheid-eruitziende animatie op de achtergrond.
            6. +
            7. Druk op de kaart en de inhoud zal dan laden op het apparaat.
            8. +
            + + diff --git a/OpenKeychain/src/main/res/raw-nl/help_start.html b/OpenKeychain/src/main/res/raw-nl/help_start.html new file mode 100644 index 000000000..40c79e95f --- /dev/null +++ b/OpenKeychain/src/main/res/raw-nl/help_start.html @@ -0,0 +1,22 @@ + + + +

            Aan de slag

            +

            Eerst heeft u een persoonlijke geheime sleutel nodig. Maak er een via het opties menu in "Sleutels" of importeer bestaande geheime sleutels. Daarna kunt u de sleutels van uw vrienden importeren of ze uitwisselen via QR Codes of NFC.

            + +

            Het is aanbevolen dat u OI Bestandsmanager installeert voor betere bestandsselectie en Barcode Scanner om gegenereerde QR codes te scannen. Door op de links te klikken zullen de Google Play Store of F-Droid openen voor installatie.

            + +

            Applicaties

            +

            Verschillende applicaties ondersteunen OpenKeychain om uw privécommunicatie te coderen/signeren

            K-9 Mail: OpenKeychain ondersteuning beschikbaar in huidige alpha build!

            Conversaties
            : Jabber/XMPP client

            PGPAuth
            : App to send a PGP-signed request to a server to open or close something, e.g. a door

            + +

            Ik heb een bug in OpenKeychain gevonden!

            +

            Rapporteer de bug met de problemen tracker van OpenKeychain.

            + +

            Bijdragen

            +

            Als u ons wilt helpen om OpenKeychain te ontwikkelen door code bij te dragen, volg onze kleine gids op Github.

            + +

            Vertalingen

            +

            Help OpenKeychain te vertalen! Iedereen kan deelnemen op OpenKeychain op Transifex.

            + + + diff --git a/OpenKeychain/src/main/res/raw-nl/help_wot.html b/OpenKeychain/src/main/res/raw-nl/help_wot.html new file mode 100644 index 000000000..efaac3c1e --- /dev/null +++ b/OpenKeychain/src/main/res/raw-nl/help_wot.html @@ -0,0 +1,17 @@ + + + +

            Web van Vertrouwen

            +

            het Web of Trust beschrijft het deel van PGP dat te maken heeft met aanmaken en boekhouden van certificaten. Het voorziet van mechanismes zodat de gebruiker bij kan houden van aan wie een publieke sleutel toebehoort, en deze informatie met anderen kan delen; om de privacy van versleutelde communicatie te verzekeren, is het essentiëel om te weten dat de publieke sleutel die u versleutelt, toebehoort aan de persoon aan wie u denkt dat het toebehoort.

            + +

            Support in OpenKeychain

            +

            Er is alleen basissupport voor Web van Vertrouwen in OpenKeychain. Dit is een zware 'werk in uitvoering' en onderwerp voor veranderingen in toekomstige releases.

            + +

            Vertrouwen Model

            +

            Vertrouwen evaluatie is gebaseerd om de simpele aanname dat alle sleutels die beschikbare geheime sleutels hebben, vertrouwd zijn. Publieke sleutels die minstens een gebruikers-id bevatten, gecertificeerd door een vertrouwde sleutel, zullen gemarkeerd worden met een groene stip in de sleutel lijsten. Het is (nog) niet mogelijk om vertrouwen niveaus voor certificaten van andere bekende publieke sleutels te specifiëren.

            + +

            Sleutels certificeren

            +

            Support voor sleutelcertificatie is beschikbaar, en gebruikers-id's kunnen individueel gecertificeerd worden. Het is nog niet mogelijk om het niveau van vertrouwen te specifiëren om locale en andere speciale typen van certificaten te maken.

            + + + diff --git a/OpenKeychain/src/main/res/raw-nl/nfc_beam_share.html b/OpenKeychain/src/main/res/raw-nl/nfc_beam_share.html new file mode 100644 index 000000000..5f7a63050 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-nl/nfc_beam_share.html @@ -0,0 +1,11 @@ + + + +
              +
            1. Zorg ervoor dat NFC ingeschakeld is in Instellingen > Meer > NFC en zorg ervoor dat Android Beam ook in dezelfde sectie ingeschakeld is.
            2. +
            3. Houd de twee apparaten met de achterkant tegen elkaar (ze moeten elkaar bijna aanraken) en u zult een trilling voelen.
            4. +
            5. Nadat het trilt zult u de inhoud op uw partners apparaat in een soort kaart zien veranderen met Star Trek warp snelheid-eruitziende animatie op de achtergrond.
            6. +
            7. Druk op de kaart en de inhoud zal dan laden op het apparaat van de andere persoon.
            8. +
            + + diff --git a/OpenKeychain/src/main/res/raw-pl/help_about.html b/OpenKeychain/src/main/res/raw-pl/help_about.html index a033c084a..68cc2810e 100644 --- a/OpenKeychain/src/main/res/raw-pl/help_about.html +++ b/OpenKeychain/src/main/res/raw-pl/help_about.html @@ -19,6 +19,7 @@
          • Paul Sarbinowski
          • Sreeram Boyapati
          • Vincent Breitmoser
          • +
          • Tim Bray

          Deweloperzy APG 1.x

            diff --git a/OpenKeychain/src/main/res/raw-pl/help_changelog.html b/OpenKeychain/src/main/res/raw-pl/help_changelog.html index 8fce6c475..d94ac3c0f 100644 --- a/OpenKeychain/src/main/res/raw-pl/help_changelog.html +++ b/OpenKeychain/src/main/res/raw-pl/help_changelog.html @@ -136,7 +136,7 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
            • dodano możliwość filtrowania listy kluczy
            • sprytniejsze automatyczne wybieranie kluczy szyfrujących
            • -
            • dodano nowy sposób obsługi intencji "wyświetl" i "wyślij", umożliwia szyfrowanie/deszyfrowanie plików wprost z menadżera plików.
            • +
            • dodano nowy sposób obsługi intencji "wyświetl" i "wyślij", umożliwia szyfrowanie/deszyfrowanie plików wprost z menadżera plików.
            • poprawki i dodatkowe funkcje (podpowiedź wyboru klucza) dla K-9 Mail, nowe wydanie beta dostępne

            1.0.1

            diff --git a/OpenKeychain/src/main/res/raw-pl/help_start.html b/OpenKeychain/src/main/res/raw-pl/help_start.html index ca10ec4b1..36ff31548 100644 --- a/OpenKeychain/src/main/res/raw-pl/help_start.html +++ b/OpenKeychain/src/main/res/raw-pl/help_start.html @@ -2,14 +2,12 @@

            Pierwsze kroki

            -

            First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

            +

            First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

            Zalecana jest instalacja menadżera plików OI File Manager w celu zapewnienia wygodniejszego wyboru plików oraz programu Barcode Scanner, który jest w stanie skanować wygenerowane kody QR. Kliknięcie na powyższe linki przekieruje Cię do sklepu Google Play / F-Droid.

            Applications

            -

            Several applications support OpenKeychain to encrypt/sign your private communication:

            -

            Conversations: Jabber/XMPP client

            -

            K-9 Mail: OpenKeychain support available in current alpha build!

            +

            Several applications support OpenKeychain to encrypt/sign your private communication:

            K-9 Mail: OpenKeychain support available in current alpha build!

            Conversations
            : Jabber/XMPP client

            PGPAuth
            : App to send a PGP-signed request to a server to open or close something, e.g. a door

            Znalazłem błąd w OpenKeychain!

            Zgłoś błąd korzystając z systemu śledzenia błędów OpenKeychain.

            diff --git a/OpenKeychain/src/main/res/raw-pl/help_wot.html b/OpenKeychain/src/main/res/raw-pl/help_wot.html new file mode 100644 index 000000000..29790139b --- /dev/null +++ b/OpenKeychain/src/main/res/raw-pl/help_wot.html @@ -0,0 +1,17 @@ + + + +

            Web of Trust

            +

            The Web of Trust describes the part of PGP which deals with creation and bookkeeping of certifications. It provides mechanisms to help the user keep track of who a public key belongs to, and share this information with others; To ensure the privacy of encrypted communication, it is essential to know that the public key you encrypt to belongs to the person you think it does.

            + +

            Support in OpenKeychain

            +

            There is only basic support for Web of Trust in OpenKeychain. This is a heavy work in progress and subject to changes in upcoming releases.

            + +

            Trust Model

            +

            Trust evaluation is based on the simple assumption that all keys which have secret keys available are trusted. Public keys which contain at least one user id certified by a trusted key will be marked with a green dot in the key listings. It is not (yet) possible to specify trust levels for certificates of other known public keys.

            + +

            Certifying keys

            +

            Support for key certification is available, and user ids can be certified individually. It is not yet possible to specify the level of trust or create local and other special types of certificates.

            + + + diff --git a/OpenKeychain/src/main/res/raw-ru/help_about.html b/OpenKeychain/src/main/res/raw-ru/help_about.html index 29cc1af83..4ffd2ba18 100644 --- a/OpenKeychain/src/main/res/raw-ru/help_about.html +++ b/OpenKeychain/src/main/res/raw-ru/help_about.html @@ -19,6 +19,7 @@
          • Paul Sarbinowski
          • Sreeram Boyapati
          • Vincent Breitmoser
          • +
          • Tim Bray

          Разработчики APG 1.x

            diff --git a/OpenKeychain/src/main/res/raw-ru/help_changelog.html b/OpenKeychain/src/main/res/raw-ru/help_changelog.html index cbd689629..fc258a623 100644 --- a/OpenKeychain/src/main/res/raw-ru/help_changelog.html +++ b/OpenKeychain/src/main/res/raw-ru/help_changelog.html @@ -3,11 +3,11 @@

            2.7

              -
            • Purple! (Dominik, Vincent)
            • -
            • New key view design (Dominik, Vincent)
            • -
            • New flat Android buttons (Dominik, Vincent)
            • -
            • API fixes (Dominik)
            • -
            • Keybase.io import (Tim Bray)
            • +
            • Пурпурный! (Dominik, Vincent)
            • +
            • Новый вид просмотра ключей (Dominik, Vincent)
            • +
            • Новый вид кнопок в стиле Android (Dominik, Vincent)
            • +
            • Исправления API (Dominik)
            • +
            • Импорт Keybase.io (Tim Bray)

            2.6.1

              diff --git a/OpenKeychain/src/main/res/raw-ru/help_start.html b/OpenKeychain/src/main/res/raw-ru/help_start.html index 022b80afc..9534acead 100644 --- a/OpenKeychain/src/main/res/raw-ru/help_start.html +++ b/OpenKeychain/src/main/res/raw-ru/help_start.html @@ -2,14 +2,12 @@

              Приступая

              -

              Для начала Вас нужен свой секретный ключ. Создайте его в меню раздела "Ключи" или импортируйте ранее созданный ключ. Позже вы сможете поделиться данными своего ключа с друзьями с помощью QR кода или NFC.

              +

              Для начала Вас нужен свой секретный ключ. Создайте его в меню раздела "Ключи" или импортируйте ранее созданный ключ. Позже вы сможете поделиться данными своего ключа с друзьями с помощью QR кода или NFC.

              Рекомендуется установить OI File Manager для удобного выбора файлов и Barcode Scanner для распознавания QR кодов. Перейдите по ссылкам на соответствующие страницы Google Play или F-Droid для дальнейшей установки.

              -

              Applications

              -

              Several applications support OpenKeychain to encrypt/sign your private communication:

              -

              Conversations: Jabber/XMPP client

              -

              K-9 Mail: OpenKeychain support available in current alpha build!

              +

              Приложения

              +

              Некоторые приложения, поддерживающие интеграцию с OpenKeychain для шифрования:

              K-9 Mail: поддержка OpenKeychain доступна в текущей альфа-версии!

              Conversations
              : клиент Jabber/XMPP

              PGPAuth
              : Приложение PGP-подписанных запросов на сервер для открытия или закрытия чего-либо.

              Я нашел ошибку в OpenKeychain!

              Пожалуйста, сообщайте о возникших проблемах и найденных ошибках в разделе Решение проблем OpenKeychain.

              diff --git a/OpenKeychain/src/main/res/raw-ru/help_wot.html b/OpenKeychain/src/main/res/raw-ru/help_wot.html new file mode 100644 index 000000000..53c862cbc --- /dev/null +++ b/OpenKeychain/src/main/res/raw-ru/help_wot.html @@ -0,0 +1,17 @@ + + + +

              Сеть доверия (WoT)

              +

              Сеть доверия (The Web of Trust) предоставляет механизм, определения принадлежности ключа именно тому пользователю, который в нём указан. Основа этой модели строится на знакомстве людей и сертификации своей подписью ключей своих знакомых. Не менее важно распространение этой информации среди других пользователей WoT.

              + +

              Поддержка в OpenKeychain

              +

              В настоящее время реализованы только базовые возможности WoT. Работа в самом разгаре и в будущих версиях OpenKeychain будут появляться дополнительные возможности.

              + +

              Модель доверия

              +

              Проверка доверия основана на простом принципе, что если доступен секретный ключ, то доверие к нему абсолютное. Однако, публичные должны содержать подписи кого-то, кому вы доверяете, что бы подпись, сделанная таким ключом, была отмечена зелёным индикатором. К сожалению, (пока) нельзя определять степень доверия к другим известным публичным ключам.

              + +

              Сертификация ключей

              +

              Поддержка сертификации ключей уже реализована, и Вы можете сертифицировать отдельные ID пользователя. Пока нельзя выбирать степень доверия, создавать локальные или специальные типы сертификатов.

              + + + diff --git a/OpenKeychain/src/main/res/raw-sl/help_about.html b/OpenKeychain/src/main/res/raw-sl/help_about.html index a57b0e26f..40c487265 100644 --- a/OpenKeychain/src/main/res/raw-sl/help_about.html +++ b/OpenKeychain/src/main/res/raw-sl/help_about.html @@ -19,6 +19,7 @@
            • Paul Sarbinowski
            • Sreeram Boyapati
            • Vincent Breitmoser
            • +
            • Tim Bray

            Razvijalci APG 1.x

              diff --git a/OpenKeychain/src/main/res/raw-sl/help_changelog.html b/OpenKeychain/src/main/res/raw-sl/help_changelog.html index bc282fc66..1b48552ab 100644 --- a/OpenKeychain/src/main/res/raw-sl/help_changelog.html +++ b/OpenKeychain/src/main/res/raw-sl/help_changelog.html @@ -3,11 +3,11 @@

              2.7

                -
              • Purple! (Dominik, Vincent)
              • -
              • New key view design (Dominik, Vincent)
              • -
              • New flat Android buttons (Dominik, Vincent)
              • -
              • API fixes (Dominik)
              • -
              • Keybase.io import (Tim Bray)
              • +
              • Vijolična! (Dominik, Vincent)
              • +
              • Nova podoba za ključe (Dominik, Vincent)
              • +
              • Nova podoba - ploski androiidni gumbi (Dominik, Vincent)
              • +
              • Popravki API (Dominik)
              • +
              • Uboz iz Keybase.io (Tim Bray)

              2.6.1

                diff --git a/OpenKeychain/src/main/res/raw-sl/help_start.html b/OpenKeychain/src/main/res/raw-sl/help_start.html index 2b78e289a..4b02415d5 100644 --- a/OpenKeychain/src/main/res/raw-sl/help_start.html +++ b/OpenKeychain/src/main/res/raw-sl/help_start.html @@ -6,10 +6,8 @@

                Priporočamo, da namestite aplikaciji OI File Manager za boljše delo z datotekami in Barcode Scanner za skeniranje kod QR. Klik na povezavi bo odprl trgovino Google Play Store ali F-Droid za namestitev.

                -

                Applications

                -

                Several applications support OpenKeychain to encrypt/sign your private communication:

                -

                Conversations: Jabber/XMPP client

                -

                K-9 Mail: OpenKeychain support available in current alpha build!

                +

                Aplikacije

                +

                Razne aplikacije podpirajo OpenKeychain za šifriranje/podpisovanje vaših zasebnih komunikacij:

                K-9 Mail: Podpora za OpenKeychain je na voljo v trenutni alfa različici!

                Conversations
                : Odjemalec za Jabber/XMPP

                PGPAuth
                : Aplikacija za pošiljanje PGP-podpisanih zahtevkov strežnikom za odpiranje ali zapiranje česa, npr vrat

                Našel sem 'hrošča' v aplikaciji OpenKeychain!

                Za poročanje o 'hroščih' uporabite sledilnik težav za OpenKeychain.

                diff --git a/OpenKeychain/src/main/res/raw-sl/help_wot.html b/OpenKeychain/src/main/res/raw-sl/help_wot.html new file mode 100644 index 000000000..62cdf8094 --- /dev/null +++ b/OpenKeychain/src/main/res/raw-sl/help_wot.html @@ -0,0 +1,17 @@ + + + +

                Omrežje zaupanja

                +

                Omrežje zaupanja je del PGP-ja, ki se dotika ustvarjanja, urejanja in hranjenja ključev. Ponuja nam orodja za vodenje evidence ključev in njihovih lastnikov, ter deljenje teh informacij z drugimi. Za zagotavljanje zasebnosti šifrirane komunikacije je bistvenega pomena, da vemo, da ključ s katerim šifriramo določeno vsebino resnično pripada osebi, ki ji je ta vsebina namenjena.

                + +

                Podpora v OpenKeychain

                +

                OpenKeychain ponuja zgolj osnovno podporo za 'Omrežje zaupanja'. V prihodnjih različicah bomo to podporo še nadgrajevali in izboljševali.

                + +

                Model zaupanja

                +

                Ocena zaupanja temelji na predpostavki, da so vsi ključi, ki vsebujejo tudi zasebne ključe, vredni zaupanja. Javni ključi, ki vsebujejo vsaj en uporabniški ID, ki je overjen z zaupanja vrednim ključem, so na seznamu ključev označeni z zeleno piko. Zaenkrat (še) ni možno natančneje določiti stopnje zaupanja potrdil drugih znanih javnih ključev.

                + +

                Overjanje ključev

                +

                Overjanje ključev je na voljo. Uporabniške ID-je ključev overjamo individualno. Zaenkrat ni možno natančneje določiti stopnje zaupanja ali ustvarjati lokalne ali druge posebne vrste potrdil.

                + + + diff --git a/OpenKeychain/src/main/res/raw-tr/help_about.html b/OpenKeychain/src/main/res/raw-tr/help_about.html index 7d2c24f9c..db577c6a3 100644 --- a/OpenKeychain/src/main/res/raw-tr/help_about.html +++ b/OpenKeychain/src/main/res/raw-tr/help_about.html @@ -19,6 +19,7 @@
              • Paul Sarbinowski
              • Sreeram Boyapati
              • Vincent Breitmoser
              • +
              • Tim Bray

              Geliştiriciler APG 1.x

                diff --git a/OpenKeychain/src/main/res/raw-tr/help_start.html b/OpenKeychain/src/main/res/raw-tr/help_start.html index 6ded872ea..3a681f8fa 100644 --- a/OpenKeychain/src/main/res/raw-tr/help_start.html +++ b/OpenKeychain/src/main/res/raw-tr/help_start.html @@ -2,14 +2,12 @@

                Getting started

                -

                First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

                +

                First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

                It is recommended that you install OI File Manager for enhanced file selection and Barcode Scanner to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.

                Applications

                -

                Several applications support OpenKeychain to encrypt/sign your private communication:

                -

                Conversations: Jabber/XMPP client

                -

                K-9 Mail: OpenKeychain support available in current alpha build!

                +

                Several applications support OpenKeychain to encrypt/sign your private communication:

                K-9 Mail: OpenKeychain support available in current alpha build!

                Conversations
                : Jabber/XMPP client

                PGPAuth
                : App to send a PGP-signed request to a server to open or close something, e.g. a door

                I found a bug in OpenKeychain!

                Please report the bug using the issue tracker of OpenKeychain.

                diff --git a/OpenKeychain/src/main/res/raw-tr/help_wot.html b/OpenKeychain/src/main/res/raw-tr/help_wot.html new file mode 100644 index 000000000..29790139b --- /dev/null +++ b/OpenKeychain/src/main/res/raw-tr/help_wot.html @@ -0,0 +1,17 @@ + + + +

                Web of Trust

                +

                The Web of Trust describes the part of PGP which deals with creation and bookkeeping of certifications. It provides mechanisms to help the user keep track of who a public key belongs to, and share this information with others; To ensure the privacy of encrypted communication, it is essential to know that the public key you encrypt to belongs to the person you think it does.

                + +

                Support in OpenKeychain

                +

                There is only basic support for Web of Trust in OpenKeychain. This is a heavy work in progress and subject to changes in upcoming releases.

                + +

                Trust Model

                +

                Trust evaluation is based on the simple assumption that all keys which have secret keys available are trusted. Public keys which contain at least one user id certified by a trusted key will be marked with a green dot in the key listings. It is not (yet) possible to specify trust levels for certificates of other known public keys.

                + +

                Certifying keys

                +

                Support for key certification is available, and user ids can be certified individually. It is not yet possible to specify the level of trust or create local and other special types of certificates.

                + + + diff --git a/OpenKeychain/src/main/res/raw-uk/help_about.html b/OpenKeychain/src/main/res/raw-uk/help_about.html index b51b80617..f6e65071c 100644 --- a/OpenKeychain/src/main/res/raw-uk/help_about.html +++ b/OpenKeychain/src/main/res/raw-uk/help_about.html @@ -19,6 +19,7 @@
              • Пауль Сарбіновський
              • Срірам Вояпаті
              • Вінсент Брейтмозер
              • +
              • Тім Брей

              Розробники APG 1.x

                diff --git a/OpenKeychain/src/main/res/raw-uk/help_changelog.html b/OpenKeychain/src/main/res/raw-uk/help_changelog.html index e47c6bf98..b40eca76e 100644 --- a/OpenKeychain/src/main/res/raw-uk/help_changelog.html +++ b/OpenKeychain/src/main/res/raw-uk/help_changelog.html @@ -3,20 +3,20 @@

                2.7

                  -
                • Purple! (Dominik, Vincent)
                • -
                • New key view design (Dominik, Vincent)
                • -
                • New flat Android buttons (Dominik, Vincent)
                • -
                • API fixes (Dominik)
                • -
                • Keybase.io import (Tim Bray)
                • +
                • Багряний! (Домінік, Вінсент)
                • +
                • Новий дизайн огляду ключа (Домінік, Вінсент)
                • +
                • Нові плоскі кнопки Андроїд(Домінік, Вінсент)
                • +
                • виправлення API (Домінік)
                • +
                • Імпорт Keybase.io (Тім Брей)

                2.6.1

                  -
                • some fixes for regression bugs
                • +
                • деякі виправлення для накопичених вад

                2.6

                • сертифікації ключів (завдяки Вінсенту Бреймозеру)
                • -
                • support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
                • +
                • підтримка часткових секретних ключів для GnuPG (завдяки Вінсенту Брейтмозеру)
                • новий дизайн для перевірки підпису
                • власна довжина ключа (завдяки Ґреґу Вітчаку)
                • виправлено функцію поширення з інших програм
                • diff --git a/OpenKeychain/src/main/res/raw-uk/help_start.html b/OpenKeychain/src/main/res/raw-uk/help_start.html index 1a4a7fab0..5caf05cc0 100644 --- a/OpenKeychain/src/main/res/raw-uk/help_start.html +++ b/OpenKeychain/src/main/res/raw-uk/help_start.html @@ -2,14 +2,12 @@

                  Приступаючи до роботи

                  -

                  First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

                  +

                  Спершу вам потрібний особистий секретний ключ. Створіть один через меню параметрів у „Ключі" або імпортуйте наявні секретні ключі через "Імпорт ключів". Після цього ви зможете завантажувати ключі ваших друзів чи обміняти їх через штрих-коди або NFC.

                  Рекомендуємо вам встановити OI File Manager для поліпшеного виділення файлів та Barcode Scanner для сканування згенерованих штрих-кодів. Натискання посилань відкриє Google Play або F-Droid для встановлення.

                  -

                  Applications

                  -

                  Several applications support OpenKeychain to encrypt/sign your private communication:

                  -

                  Conversations: Jabber/XMPP client

                  -

                  K-9 Mail: OpenKeychain support available in current alpha build!

                  +

                  Програми

                  +

                  Окремі програми підтримують OpenKeychain для шифрування/підписування вашо спілкування:

                  K-9 Mail: підтримка OpenKeychain доступна у поточній альфа-збірці!

                  Спілкування
                  : клієнт Jabber/XMPP

                  PGPAuth
                  : програма надіслала запит, підписаний PGP, на сервер для відкриття чи закриття чогось на кшталт дверей

                  Я знайшов помилку в OpenPGP Keychain!

                  Будь ласка, повідомте про ваду за допомогою відстежувача проблем OpenPGP Keychain.

                  diff --git a/OpenKeychain/src/main/res/raw-uk/help_wot.html b/OpenKeychain/src/main/res/raw-uk/help_wot.html new file mode 100644 index 000000000..e1296472e --- /dev/null +++ b/OpenKeychain/src/main/res/raw-uk/help_wot.html @@ -0,0 +1,17 @@ + + + +

                  Мережа довіри

                  +

                  Мережа довіри - The Web of Trust - надає механізм визначення приналежності ключа саме тому користувачеві, який в ньому зазначений. Основа цієї моделі будується на знайомстві людей та сертифікації своїм підписом ключів своїх знайомих. Не менш важливо поширення цієї інформації серед інших користувачів WoT.

                  + +

                  Підтримка у OpenKeychain

                  +

                  Наразі реалізовані тільки базові можливості WoT. Робота в самому розпалі, і в майбутніх версіях OpenKeychain будуть з'являтися додаткові можливості.

                  + +

                  Модель довіри

                  +

                  Перевірка довіри заснована на простому принципі, що якщо доступний секретний ключ, то довіра до нього абсолютна. Однак, публічні повинні містити підписи когось, кому ви довіряєте, що б підпис, зроблений таким ключем, був відзначений зеленим індикатором. На жаль, (поки що) не можна визначати ступінь довіри до інших відомих публічних ключів.

                  + +

                  Сертифікація ключів

                  +

                  Підтримка сертифікації ключів вже реалізована, і Ви можете сертифікувати окремі ID користувача. Наразі не можна вибирати ступінь довіри, створювати локальні або спеціальні типи сертифікатів.

                  + + + diff --git a/OpenKeychain/src/main/res/raw-zh/help_about.html b/OpenKeychain/src/main/res/raw-zh/help_about.html index 813676ea2..c9f76dd7c 100644 --- a/OpenKeychain/src/main/res/raw-zh/help_about.html +++ b/OpenKeychain/src/main/res/raw-zh/help_about.html @@ -19,6 +19,7 @@
                • Paul Sarbinowski
                • Sreeram Boyapati
                • Vincent Breitmoser
                • +
                • Tim Bray

                Developers APG 1.x

                  diff --git a/OpenKeychain/src/main/res/raw-zh/help_start.html b/OpenKeychain/src/main/res/raw-zh/help_start.html index 7abb144a0..705bbcceb 100644 --- a/OpenKeychain/src/main/res/raw-zh/help_start.html +++ b/OpenKeychain/src/main/res/raw-zh/help_start.html @@ -2,14 +2,12 @@

                  快速上手

                  -

                  First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

                  +

                  First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.

                  It is recommended that you install OI File Manager for enhanced file selection and Barcode Scanner to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.

                  Applications

                  -

                  Several applications support OpenKeychain to encrypt/sign your private communication:

                  -

                  Conversations: Jabber/XMPP client

                  -

                  K-9 Mail: OpenKeychain support available in current alpha build!

                  +

                  Several applications support OpenKeychain to encrypt/sign your private communication:

                  K-9 Mail: OpenKeychain support available in current alpha build!

                  Conversations
                  : Jabber/XMPP client

                  PGPAuth
                  : App to send a PGP-signed request to a server to open or close something, e.g. a door

                  我在OpenKeychain發現問題!

                  請利用 OpenKeychain 項目回報系統回報問題。

                  diff --git a/OpenKeychain/src/main/res/raw-zh/help_wot.html b/OpenKeychain/src/main/res/raw-zh/help_wot.html new file mode 100644 index 000000000..29790139b --- /dev/null +++ b/OpenKeychain/src/main/res/raw-zh/help_wot.html @@ -0,0 +1,17 @@ + + + +

                  Web of Trust

                  +

                  The Web of Trust describes the part of PGP which deals with creation and bookkeeping of certifications. It provides mechanisms to help the user keep track of who a public key belongs to, and share this information with others; To ensure the privacy of encrypted communication, it is essential to know that the public key you encrypt to belongs to the person you think it does.

                  + +

                  Support in OpenKeychain

                  +

                  There is only basic support for Web of Trust in OpenKeychain. This is a heavy work in progress and subject to changes in upcoming releases.

                  + +

                  Trust Model

                  +

                  Trust evaluation is based on the simple assumption that all keys which have secret keys available are trusted. Public keys which contain at least one user id certified by a trusted key will be marked with a green dot in the key listings. It is not (yet) possible to specify trust levels for certificates of other known public keys.

                  + +

                  Certifying keys

                  +

                  Support for key certification is available, and user ids can be certified individually. It is not yet possible to specify the level of trust or create local and other special types of certificates.

                  + + + diff --git a/OpenKeychain/src/main/res/raw-zh/nfc_beam_share.html b/OpenKeychain/src/main/res/raw-zh/nfc_beam_share.html index 99ffe4c12..78f00c9f7 100644 --- a/OpenKeychain/src/main/res/raw-zh/nfc_beam_share.html +++ b/OpenKeychain/src/main/res/raw-zh/nfc_beam_share.html @@ -2,7 +2,7 @@
                    -
                  1. 確定在 "設定" > "更多內容…" > "NFC" 裡面已經開啟 NFC 和 Android Beam。
                  2. +
                  3. 確定在 "設定" > "更多內容…" > "NFC" 裡面已經開啟 NFC 和 Android Beam。
                  4. 將兩部裝置背對背貼近(幾乎接觸),你會感覺到一股震動。
                  5. 震動之後你會看見你夥伴的畫面變成卡片狀,並且背景帶有如 Star Trek 般的特效。
                  6. 輕觸卡片,內容隨即顯示在你的裝置上。
                  7. diff --git a/OpenKeychain/src/main/res/values-ar/strings.xml b/OpenKeychain/src/main/res/values-ar/strings.xml new file mode 100644 index 000000000..e3d3a6493 --- /dev/null +++ b/OpenKeychain/src/main/res/values-ar/strings.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OpenKeychain/src/main/res/values-cs-rCZ/strings.xml b/OpenKeychain/src/main/res/values-cs-rCZ/strings.xml deleted file mode 100644 index c3d7cc4c9..000000000 --- a/OpenKeychain/src/main/res/values-cs-rCZ/strings.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - Zvolit veřejný klíč - Zvolit tajný klíč - Zašifrovat - Dešifrovat - Heslo - Vytvořit klíč - Upravit klíč - Nastavení - Registrované aplikace - Nastavení serveru s klíči - Zadat heslo - Importovat klíče - Exportovat klíč - Exportovat klíče - Klíč nenalezen - Nahrát na server s klíči - Nápověda - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OpenKeychain/src/main/res/values-cs/strings.xml b/OpenKeychain/src/main/res/values-cs/strings.xml new file mode 100644 index 000000000..e3d3a6493 --- /dev/null +++ b/OpenKeychain/src/main/res/values-cs/strings.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OpenKeychain/src/main/res/values-de/strings.xml b/OpenKeychain/src/main/res/values-de/strings.xml index 61d4fc642..e2dfa196b 100644 --- a/OpenKeychain/src/main/res/values-de/strings.xml +++ b/OpenKeychain/src/main/res/values-de/strings.xml @@ -273,9 +273,6 @@ Android 4.1 wird benötigt um Androids NFC Beam nutzen zu können! NFC steht auf diesem Gerät nicht zur Verfügung! Nichts zu importieren! - Unzureichende Serveranfrage - Anfrage fehlgeschlagen - Zu viele mögliche Schlüssel. Verfeinere deine Suchanfrage! Datei ist leer Ein allgemeiner Fehler trat auf, bitte schreiben Sie einen neuen Bugreport für OpenKeychain. @@ -330,6 +327,7 @@ Öffentliche Schlüssel suchen Private Schlüssel suchen Teile Schlüssel über… + Durchsuche Keybase.io 512 768 @@ -369,12 +367,14 @@ Um Schlüssel über NFC zu erhalten muss das Gerät entsperrt sein. Hilfe Schlüssel aus der Zwischenablage einfügen + Schlüssel von Keybase.io erhalten Datei entschlüsseln mit OpenKeychain Schlüssel importieren mit OpenKeychain Verschlüsseln mit OpenKeychain Entschlüsseln mit OpenKeychain + Keine verknüpften Apps vorhanden\n\nEine Liste von unterstützten Drittanbieter-Apps finden Sie unter \"Hilfe\"! Erweiterte Informationen anzeigen Erweiterte Informationen ausblenden Erweiterte Einstellungen anzeigen @@ -385,6 +385,7 @@ Speichern Abbrechen Zugriff widerufen + Starte Anwendung Account löschen Paketname SHA-256 der Paketsignatur diff --git a/OpenKeychain/src/main/res/values-es/strings.xml b/OpenKeychain/src/main/res/values-es/strings.xml index dd628f87a..45d3d565b 100644 --- a/OpenKeychain/src/main/res/values-es/strings.xml +++ b/OpenKeychain/src/main/res/values-es/strings.xml @@ -273,9 +273,9 @@ ¡Necesita Android 4.1 para usar la característica NFC Beam (haz NFC) de Android! ¡NFC no está disponible en tu dispositivo! ¡Nada que importar! - Consulta al servidor insuficiente - La consulta al servidor de claves ha fallado - Demasiadas claves posibles. Por favor ¡refine su consulta! + Petición de búsqueda de clave demasiado corta + Error irrecuperable buscando claves en el servidor + La petición de búsqueda de clave devolvió demasiados candidatos; por favor refine su petición El archivo está vacio Ha ocurrido un error genérico, por favor, informa de este bug a OpenKeychain diff --git a/OpenKeychain/src/main/res/values-fa-rIR/strings.xml b/OpenKeychain/src/main/res/values-fa-rIR/strings.xml deleted file mode 100644 index e3d3a6493..000000000 --- a/OpenKeychain/src/main/res/values-fa-rIR/strings.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OpenKeychain/src/main/res/values-fr/strings.xml b/OpenKeychain/src/main/res/values-fr/strings.xml index 575ce8085..f49127b6f 100644 --- a/OpenKeychain/src/main/res/values-fr/strings.xml +++ b/OpenKeychain/src/main/res/values-fr/strings.xml @@ -273,9 +273,9 @@ Il vous faut Android 4.1 pour utiliser la fonction Beam NFC d\'Android ! La NFC n\'est pas disponible sur votre appareil ! Rien à importer ! - Requête serveur insuffisante - Échec lors de l\'interrogation du serveur de clefs - Il y a trop de clefs possibles. Veuillez affiner votre requête ! + La requête de recherche de clef est trop courte + Erreur irrécupérable lors de la recherche de clef sur le serveur + La requête de recherche de clef a retourné trop de candidats. Veuillez raffiner la requête Le fichier n\'a pas de contenu Une erreur générique est survenue, veuillez créer un nouveau rapport de bogue pour OpenKeychain. diff --git a/OpenKeychain/src/main/res/values-it-rIT/strings.xml b/OpenKeychain/src/main/res/values-it-rIT/strings.xml deleted file mode 100644 index b951bcf71..000000000 --- a/OpenKeychain/src/main/res/values-it-rIT/strings.xml +++ /dev/null @@ -1,475 +0,0 @@ - - - - Seleziona Chiave Pubblica - Seleziona Chiave Privata - Codifica - Decodifica - Frase di accesso - Crea Chiave - Modifica Chiave - Preferenze - App Registrate - Preferenze Server delle Chiavi - Cambia Frase Di Accesso - Imposta Frase di Accesso - Condividi con... - Condivi impronta con... - Condividi chiave con... - Condividi file con... - Codifica File - Decodifica File - Importa Chiavi - Esporta Chiave - Esporta Chiavi - Chiave Non Trovata - Carica sul Server delle Chiavi - Certifica identità - Dettagli Chiave - Aiuto - - Identità - Sottochiavi - Generale - Predefiniti - Avanzato - Chiave Principale - Identità Primaria - Azioni - Intera chiave - La Tua Chiave usata per la certificazione - Carica Chiave - Server delle Chiavi - Codifica e/o Firma - Decodifica e Verifica - Impronta - Chiave da certificare - - Certifica - Decodifica, verifica e salva su file - Decodifica e verifica messaggio - Dagli Appunti - Codifica e salva file - Salva - Annulla - Elimina - Nessuno - OK - Cambia Nuova Frase di Accesso - Imposta Nuova Frase di Accesso - Carica sul Server delle Chiavi - Prossimo - Precedente - Appunti - Condividi... - Chiave di ricerca - Mostra impostazioni avanzate - Nascondi impostazioni avanzate - Condividi messaggio codificato/firmato... - Mostra chiave di certificazione - - Impostazioni - Aiuto - Importa da file - Importa da Codice QR - Importa tramite NFC - Esporta su un file - Cancella chiave - Crea chiave - Crea chiave (avanzato) - Cerca - Server delle Chiavi - Importa da Keybase.io - Server delle Chiavi... - Aggiorna dal server delle chiavi - Carica chiave nel server - Condividi... - Condivi impronta... - Condividi intera chiave... - con.. - con... - con Codice QR - con Codice QR - con NFC - Copia negli appunti - Impostazioni Beam - Annulla - Codifica su... - Seleziona tutto - Aggiungi chiavi - Esporta tutte le chiavi - - Firma - Messaggio - File - Nessuna Frase di Accesso - Frase di Accesso - Di nuovo - Algortimo - Armatura ASCII - Destinatari - Cancella Dopo Codifica - Cancella Dopo Decodifica - Condividi Dopo la Codifica - Algoritmo di Codifica - Algoritmo di Hash - con Chiave Pubblica - con Frase di Accesso - Cache Frase di Accesso - Compressione Messaggio - Compressione File - Forza vecchie Firme OpenPGPv3 - Server Chiavi - ID Chiave - Creazione - Scadenza - Utilizzo - Dimensione Chiave - Identità Primaria - Nome - Commento - Email - Carica chiave nel server delle chiavi selezionati dopo la certificazione - Impronta - Seleziona - Impostare la data di scadenza - - %d selezionato - %d selezionati - - <nessun nome> - <nessuno> - <nessuna chiave> - puo\' codificare - puo\' firmare - può certificare - non può certificare - scaduto - revocato - - 1 chiave - %d chiavi - - - %d server delle chiavi - %d server delle chiavi - - Chiave Privata: - - Nessuno - 15 sec - 1 min - 3 min - 5 min - 10 min - 20 min - 40 min - 1 ora - 2 ore - 4 ore - 8 ore - sempre - DSA - ElGamal - RSA - Apri... - Attenzione - Errore - Errore: %s - - Certifica - Firma - Codifica - Convalida - - Frase di Accesso errata - Imposta prima una frase di accesso. - Nessun gestore file compatibile installato. - Le frasi di accesso non corrispondono. - Si prega di inserire una frase di accesso. - Codifica Simmetrica. - Inserisci la frase di accesso per \'%s\' - Sei sicuro di voler cancellare\n%s? - Eliminato correttamente. - Seleziona un file prima. - Firmato e/o codificato con successo. - Firmato e/o codificato con successo negli appunti. - Inserisci la frase di accesso due volte. - Seleziona almeno una chiave di codifica. - Seleziona almeno una chiave di codifica o di firma. - Perfavore specifica quale file codificare.\nATTENZIONE: Il file sara\' sovrascritto se esistente. - Perfavore specifica quale file decodificare.\nATTENZIONE: Il file sara\' sovrascritto se esistente. - Perfavore specifica su quale file esportare.\nATTENZIONE: Il file sara\' sovrascritto se esistente. - Vuoi veramente eliminare tutte le chiavi pubbliche selezionate?\nNon potrai annullare! - Vuoi veramente eliminare la chiave PRIVATA \'%s\'?\nNon potrai annullare! - Hai apportato modifiche al tuo portachiavi, vuoi salvarlo? - Hai aggiunto una identità vuota, sei sicuro di voler continuare? - Vuoi veramente eliminare la chiave pubblica \'%s\'?\nNon potrai annullare! - Esportare anche le chiavi segrete? - - %d chiave aggiunta correttamente - %d chiavi aggiunte correttamente - - - e %d chiave aggiornata. - e %d chiavi aggiornate. - - - %d chiave aggiunta correttamente. - %d chiavi aggiunte correttamente. - - - %d chiave aggiornata correttamente. - %d chiavi aggiornate correttamente. - - Nessuna chiave aggiunta o aggiornata. - 1 chiave esportata correttamente. - %d chiavi esportate correttamente. - Nessuna chiave esportata. - Nota: supporto sottochiavi solo per ElGamal. - Nota: la generazione di chiavi RSA con lunghezza pari a 1024 bit o inferiore è considerata non sicura ed è disabilitata per la generazione di nuove chiavi. - Impossibile trovare la chiave %08X. - - Trovata %d chiave. - Trovate %d chiavi. - - - %d chiave segreta non valida ignorata. Forse hai esportato con opzione\n--export-secret-subkeys\nAssicurati di esportare con\n--export-secret-keys\ninvece. - %d chiavi private non valide ignorate. Forse hai esportato con opzione\n--export-secret-subkeys\nAssicurati di esportare con\n--export-secret-keys\ninvece. - - Chiave caricata con successo sul server - Identità certificata correttamente - Lista vuota! - Chiave correttamente inviata tramite NFC Beam! - Chiave copiata negli appunti! - Impronta copiata negli appunti! - La chiave è già certificata! - Per favore seleziona una chiave per la certificazione! - Chiave troppo grande per essere condivisa in questo modo! - - Cancellazione di \'%s\' fallita - File non trovato - nessuna chiave privata adatta trovata - memoria esterna non pronta - La grandezza della chiave deve essere almeno di 512bit - La chiave principale non puo\' essere ElGamal - opzione algoritmo sconosciuta - Nessuna email trovata - neccessaria almeno una identità - L\'identità primaria non può essere vuota - necessaria almeno una chiave principale - nessuna frase di accesso inserita - nessuna chiave di firma inserita - dati di codifica non validi - Controllo di integrita\' fallito! I dati sono stati modificati! - frase di accesso errata - errore nel salvataggio di alcune chiavi - impossibile estrarre la chiave privata - La data di scadenza deve essere postuma quella di creazione - - Flusso di dati diretto senza file corrispettivo nel filesystem non e\' supportato. - Devi avere Android 4.1 per usare Android NFC Beam! - NFC non disponibile nel tuo dispositivo! - Niente da importare! - Query di server insufficiente - Interrogazione del server delle chiavi fallita - Troppe chiavi corrispondenti. Riformula meglio la ricerca! - Il File non ha contenuti - Si è verificato un errore generico, si prega di creare una nuova segnalazione di errore per OpenKeychain. - - parte del file caricato e\' un oggetto OpenPGP valido, ma non una chave OpenPGP - parti del file caricato sono oggetti OpenPGP validi, ma non chavi OpenPGP - - È necessario apportare modifiche al portachiavi prima prima che sia possibile salvarlo - - Firma non valida! - Chiave pubblica sconosciuta - Firma valida (non certificata) - Firma valida (certificata) - Decodificato correttamente - Decodificata correttamente ma chiave pubblica sconosciuta - Decodifcato correttamente e firma valida (non certificata) - Decodifcato correttamente e firma valida (certificata) - - Fatto. - Annulla - salvataggio... - importazione... - esportazione... - fabbricazione chiave... - certificazione chiave principale... - fabbricazione portachiavi principale... - aggiunta sottochiavi... - salvataggio chiavi... - - esportazione chiave... - esportazione chiavi... - - - generazione chiave, sono necessari fino a 3 minuti... - generazione chiavi, sono necessari fino a 3 minuti... - - estrazione chiavi di firma... - estrazione chiave... - preparazione flussi... - codifica dati... - decodifica dati... - preparazione firma... - generazione firma... - elaborazione firma... - verifica firma... - firma... - lettura dati... - ricerca chiave... - decompressione dati... - verifica integrita\'... - eliminazione sicura di \'%s\'... - - Ricerca Chiavi Pubbliche - Cerca Chiave Privata - Condividi chiave con... - Cerca Keybase.io - - 512 - 768 - 1024 - 1536 - 2048 - 3072 - 4096 - 8192 - Lunghezza chiave peronalizzata - Digita lunghezza chiave personalizzata (in bit): - La lunghezza della chiave RSA deve essere maggiore di 1024 e al massimo 8192. Inoltre, deve essere multipla di 8. - La lunghezza della chiave DSA deve essere almeno 512 e al massimo 1024. Inoltre, deve essere multipla di 64. - - veloce - molto lento - - Inizia - FAQ - Rete di Fiducia - NFC Beam - Novita\' - Info - Versione: - - Importa chiavi selezionate - Importa dagli appunti - - Codice QR con ID %s mancante - Codici QR con ID %s mancanti - - Perfavore inizia col Codice QR con ID 1 - Codica QR deformato! Prova di nuovo! - Scansione codice QR completata! - Impronta troppo corta (< 16 caratteri) - Scansiona il Codice QR con \'Barcode Scanner\' - Per ricevere le chiavi via NFC, il dispositivo deve essere sbloccato. - Aiuto - Ottieni chiave dagli appunti - Ottieni chiave da Keybase.io - - Decodifica File con OpenKeychain - Importa Chiave con OpenKeychain - Codifica con OpenKeychain - Decodifica con OpenKeychain - - Mostra informazioni dettagliate - Nascondi informazioni dettagliate - Mostra impostazioni avanzate - Nascondi impostazioni avanzate - Nessuna chiave selezionata - Seleziona chiave - Crea una nuova chiave per questo account - Salva - Annulla - Revoca accesso - Cancella account - Nome Pacchetto - SHA-256 della Firma del Pacchetto - Account - Nessun account collegato a questa applicazione - L\'applicazione richiede la creazione di un nuovo account. Si prega di selezionare una chiave privata esistente o crearne una nuova.\nLe applicazioni sono limitate all\'utilizzo delle chiavi selezionate qui! - Le app visualizzate hanno richiesto l\'accesso a OpenKeychain.\nPermetti accesso?\n\nATTENZIONE: Se non sai perche\' questo schermata e\' apparsa, nega l\'accesso! Puoi revocare l\'accesso dopo, usando la schermata \'App Registrate\'. - Permetti accesso - Nega accesso - Per favore selezionare una chiave! - Nessuna chiave pubblica trovata per queste identità: - Esistono piu\' di una chiave pubblica per queste identità: - Per favore ricontrolla la lista destinatari! - Controllo della firma fallito! Hai installato questa app da una fonte diversa? Se sei sicuro che non sia un attacco, revoca la registrazione di questa app in OpenKeychain e dopo registra di nuovo l\'app. - - Condividi tramite Codice QR - Scorri tutti i Codici QR usando \'Prossimo\', a scansionali uno ad uno. - Impronta: - Codice QR con ID %1$d di %2$d - Condividi tramite NFC - - - 1 chiave selezionata. - %d chiavi selezionate. - - Nessuna chiave disponibile... - Puoi iniziare da - o - creazione della tua chiave - importazione chiavi. - - Modifica chiave - Codifica con questa chiave - Certifica identità - Condividi con... - Condividi con NFC tenendo i dispositivi a stretto contatto - Info Principale - Condividi - Sottochiavi - Certificati - - Chiavi - Firma e Codifica - Decodifica e Verifica - Importa Chiavi - App Registrate - Apri drawer di navigazione - Chiudi drawer di navigazione - Modifica - Le Mie Chiavi - Chiave Segreta - disponibile - non disponibile - - Scrivi qui il messaggio da codificare e/o firmare... - Inserisci il testo cifrato qui per la decodifica e/o verifica... - - predefiniti - nessuno - casuale - positivo - revocato - ok - fallito! - errore! - chiave non disponibile - - Certificatore - Dettagli Certificato - Identit - <sconosciuto> - Nessun certificato per questa chiave - Identità da certificare - Ragione della Revoca - Stato Verifica - Tipo - Chiave non trovata! - Errore di elaborazione chiave! - sottochiave non disponibile - ripulito - Le chiavi segrete possono essere cancellate solo individualmente! - Visualizza Dettagli Certificati - sconosciuto - non può firmare - Nessuna sottochiave di codifica disponibile! - diff --git a/OpenKeychain/src/main/res/values-it/strings.xml b/OpenKeychain/src/main/res/values-it/strings.xml new file mode 100644 index 000000000..eae4dd4af --- /dev/null +++ b/OpenKeychain/src/main/res/values-it/strings.xml @@ -0,0 +1,474 @@ + + + + Seleziona Chiave Pubblica + Seleziona Chiave Privata + Codifica + Decodifica + Frase di accesso + Crea Chiave + Modifica Chiave + Preferenze + App Registrate + Preferenze Server delle Chiavi + Cambia Frase Di Accesso + Imposta Frase di Accesso + Condividi con... + Condivi impronta con... + Condividi chiave con... + Condividi file con... + Codifica File + Decodifica File + Importa Chiavi + Esporta Chiave + Esporta Chiavi + Chiave Non Trovata + Carica sul Server delle Chiavi + Certifica identità + Dettagli Chiave + Aiuto + + Identità + Sottochiavi + Generale + Predefiniti + Avanzato + Chiave Principale + Identità Primaria + Azioni + Intera chiave + La Tua Chiave usata per la certificazione + Carica Chiave + Server delle Chiavi + Codifica e/o Firma + Decodifica e Verifica + Impronta + Chiave da certificare + + Certifica + Decodifica, verifica e salva su file + Decodifica e verifica messaggio + Dagli Appunti + Codifica e salva file + Salva + Annulla + Elimina + Nessuno + OK + Cambia Nuova Frase di Accesso + Imposta Nuova Frase di Accesso + Carica sul Server delle Chiavi + Prossimo + Precedente + Appunti + Condividi... + Chiave di ricerca + Mostra impostazioni avanzate + Nascondi impostazioni avanzate + Condividi messaggio codificato/firmato... + Mostra chiave di certificazione + + Impostazioni + Aiuto + Importa da file + Importa da Codice QR + Importa tramite NFC + Esporta su un file + Cancella chiave + Crea chiave + Crea chiave (avanzato) + Cerca + Server delle Chiavi + Importa da Keybase.io + Server delle Chiavi... + Aggiorna dal server delle chiavi + Carica chiave nel server + Condividi... + Condivi impronta... + Condividi intera chiave... + con.. + con... + con Codice QR + con Codice QR + con NFC + Copia negli appunti + Impostazioni Beam + Annulla + Codifica su... + Seleziona tutto + Aggiungi chiavi + Esporta tutte le chiavi + + Firma + Messaggio + File + Nessuna Frase di Accesso + Frase di Accesso + Di nuovo + Algortimo + Armatura ASCII + Destinatari + Cancella Dopo Codifica + Cancella Dopo Decodifica + Condividi Dopo la Codifica + Algoritmo di Codifica + Algoritmo di Hash + con Chiave Pubblica + con Frase di Accesso + Cache Frase di Accesso + Compressione Messaggio + Compressione File + Forza vecchie Firme OpenPGPv3 + Server Chiavi + ID Chiave + Creazione + Scadenza + Utilizzo + Dimensione Chiave + Identità Primaria + Nome + Commento + Email + Carica chiave nel server delle chiavi selezionati dopo la certificazione + Impronta + Seleziona + Impostare la data di scadenza + + %d selezionato + %d selezionati + + <nessun nome> + <nessuno> + <nessuna chiave> + puo\' codificare + puo\' firmare + può certificare + non può certificare + scaduto + revocato + + 1 chiave + %d chiavi + + + %d server delle chiavi + %d server delle chiavi + + Chiave Privata: + + Nessuno + 15 sec + 1 min + 3 min + 5 min + 10 min + 20 min + 40 min + 1 ora + 2 ore + 4 ore + 8 ore + sempre + DSA + ElGamal + RSA + Apri... + Attenzione + Errore + Errore: %s + + Certifica + Firma + Codifica + Convalida + + Frase di Accesso errata + Imposta prima una frase di accesso. + Nessun gestore file compatibile installato. + Le frasi di accesso non corrispondono. + Si prega di inserire una frase di accesso. + Codifica Simmetrica. + Inserisci la frase di accesso per \'%s\' + Sei sicuro di voler cancellare\n%s? + Eliminato correttamente. + Seleziona un file prima. + Firmato e/o codificato con successo. + Firmato e/o codificato con successo negli appunti. + Inserisci la frase di accesso due volte. + Seleziona almeno una chiave di codifica. + Seleziona almeno una chiave di codifica o di firma. + Perfavore specifica quale file codificare.\nATTENZIONE: Il file sara\' sovrascritto se esistente. + Perfavore specifica quale file decodificare.\nATTENZIONE: Il file sara\' sovrascritto se esistente. + Perfavore specifica su quale file esportare.\nATTENZIONE: Il file sara\' sovrascritto se esistente. + Vuoi veramente eliminare tutte le chiavi pubbliche selezionate?\nNon potrai annullare! + Vuoi veramente eliminare la chiave PRIVATA \'%s\'?\nNon potrai annullare! + Hai apportato modifiche al tuo portachiavi, vuoi salvarlo? + Hai aggiunto una identità vuota, sei sicuro di voler continuare? + Vuoi veramente eliminare la chiave pubblica \'%s\'?\nNon potrai annullare! + Esportare anche le chiavi segrete? + + %d chiave aggiunta correttamente + %d chiavi aggiunte correttamente + + + e %d chiave aggiornata. + e %d chiavi aggiornate. + + + %d chiave aggiunta correttamente. + %d chiavi aggiunte correttamente. + + + %d chiave aggiornata correttamente. + %d chiavi aggiornate correttamente. + + Nessuna chiave aggiunta o aggiornata. + 1 chiave esportata correttamente. + %d chiavi esportate correttamente. + Nessuna chiave esportata. + Nota: supporto sottochiavi solo per ElGamal. + Nota: la generazione di chiavi RSA con lunghezza pari a 1024 bit o inferiore è considerata non sicura ed è disabilitata per la generazione di nuove chiavi. + Impossibile trovare la chiave %08X. + + Trovata %d chiave. + Trovate %d chiavi. + + + %d chiave segreta non valida ignorata. Forse hai esportato con opzione\n--export-secret-subkeys\nAssicurati di esportare con\n--export-secret-keys\ninvece. + %d chiavi private non valide ignorate. Forse hai esportato con opzione\n--export-secret-subkeys\nAssicurati di esportare con\n--export-secret-keys\ninvece. + + Chiave caricata con successo sul server + Identità certificata correttamente + Lista vuota! + Chiave correttamente inviata tramite NFC Beam! + Chiave copiata negli appunti! + Impronta copiata negli appunti! + La chiave è già certificata! + Per favore seleziona una chiave per la certificazione! + Chiave troppo grande per essere condivisa in questo modo! + + Cancellazione di \'%s\' fallita + File non trovato + nessuna chiave privata adatta trovata + memoria esterna non pronta + La grandezza della chiave deve essere almeno di 512bit + La chiave principale non puo\' essere ElGamal + opzione algoritmo sconosciuta + Nessuna email trovata + neccessaria almeno una identità + L\'identità primaria non può essere vuota + necessaria almeno una chiave principale + nessuna frase di accesso inserita + nessuna chiave di firma inserita + dati di codifica non validi + Controllo di integrita\' fallito! I dati sono stati modificati! + frase di accesso errata + errore nel salvataggio di alcune chiavi + impossibile estrarre la chiave privata + La data di scadenza deve essere postuma quella di creazione + + Flusso di dati diretto senza file corrispettivo nel filesystem non e\' supportato. + Devi avere Android 4.1 per usare Android NFC Beam! + NFC non disponibile nel tuo dispositivo! + Niente da importare! + Il File non ha contenuti + Si è verificato un errore generico, si prega di creare una nuova segnalazione di errore per OpenKeychain. + + parte del file caricato e\' un oggetto OpenPGP valido, ma non una chave OpenPGP + parti del file caricato sono oggetti OpenPGP validi, ma non chavi OpenPGP + + È necessario apportare modifiche al portachiavi prima prima che sia possibile salvarlo + + Firma non valida! + Chiave pubblica sconosciuta + Firma valida (non certificata) + Firma valida (certificata) + Decodificato correttamente + Decodificata correttamente ma chiave pubblica sconosciuta + Decodifcato correttamente e firma valida (non certificata) + Decodifcato correttamente e firma valida (certificata) + + Fatto. + Annulla + salvataggio... + importazione... + esportazione... + fabbricazione chiave... + certificazione chiave principale... + fabbricazione portachiavi principale... + aggiunta sottochiavi... + salvataggio chiavi... + + esportazione chiave... + esportazione chiavi... + + + generazione chiave, sono necessari fino a 3 minuti... + generazione chiavi, sono necessari fino a 3 minuti... + + estrazione chiavi di firma... + estrazione chiave... + preparazione flussi... + codifica dati... + decodifica dati... + preparazione firma... + generazione firma... + elaborazione firma... + verifica firma... + firma... + lettura dati... + ricerca chiave... + decompressione dati... + verifica integrita\'... + eliminazione sicura di \'%s\'... + + Ricerca Chiavi Pubbliche + Cerca Chiave Privata + Condividi chiave con... + Cerca Keybase.io + + 512 + 768 + 1024 + 1536 + 2048 + 3072 + 4096 + 8192 + Lunghezza chiave peronalizzata + Digita lunghezza chiave personalizzata (in bit): + La lunghezza della chiave RSA deve essere maggiore di 1024 e al massimo 8192. Inoltre, deve essere multipla di 8. + La lunghezza della chiave DSA deve essere almeno 512 e al massimo 1024. Inoltre, deve essere multipla di 64. + + veloce + molto lento + + Inizia + FAQ + Rete di Fiducia + NFC Beam + Novita\' + Info + Versione: + + Importa chiavi selezionate + Importa dagli appunti + + Codice QR con ID %s mancante + Codici QR con ID %s mancanti + + Perfavore inizia col Codice QR con ID 1 + Codica QR deformato! Prova di nuovo! + Scansione codice QR completata! + Impronta troppo corta (< 16 caratteri) + Scansiona il Codice QR con \'Barcode Scanner\' + Per ricevere le chiavi via NFC, il dispositivo deve essere sbloccato. + Aiuto + Ottieni chiave dagli appunti + Ottieni chiave da Keybase.io + + Decodifica File con OpenKeychain + Importa Chiave con OpenKeychain + Codifica con OpenKeychain + Decodifica con OpenKeychain + + Nessuna applicazione registrata!\n\nUna lista di applicazioni di terze parti supportate è disponibile in \'Aiuto\'! + Mostra informazioni dettagliate + Nascondi informazioni dettagliate + Mostra impostazioni avanzate + Nascondi impostazioni avanzate + Nessuna chiave selezionata + Seleziona chiave + Crea una nuova chiave per questo account + Salva + Annulla + Revoca accesso + Avvia applicazione + Cancella account + Nome Pacchetto + SHA-256 della Firma del Pacchetto + Account + Nessun account collegato a questa applicazione + L\'applicazione richiede la creazione di un nuovo account. Si prega di selezionare una chiave privata esistente o crearne una nuova.\nLe applicazioni sono limitate all\'utilizzo delle chiavi selezionate qui! + Le app visualizzate hanno richiesto l\'accesso a OpenKeychain.\nPermetti accesso?\n\nATTENZIONE: Se non sai perche\' questo schermata e\' apparsa, nega l\'accesso! Puoi revocare l\'accesso dopo, usando la schermata \'App Registrate\'. + Permetti accesso + Nega accesso + Per favore selezionare una chiave! + Nessuna chiave pubblica trovata per queste identità: + Esistono piu\' di una chiave pubblica per queste identità: + Per favore ricontrolla la lista destinatari! + Controllo della firma fallito! Hai installato questa app da una fonte diversa? Se sei sicuro che non sia un attacco, revoca la registrazione di questa app in OpenKeychain e dopo registra di nuovo l\'app. + + Condividi tramite Codice QR + Scorri tutti i Codici QR usando \'Prossimo\', a scansionali uno ad uno. + Impronta: + Codice QR con ID %1$d di %2$d + Condividi tramite NFC + + + 1 chiave selezionata. + %d chiavi selezionate. + + Nessuna chiave disponibile... + Puoi iniziare da + o + creazione della tua chiave + importazione chiavi. + + Modifica chiave + Codifica con questa chiave + Certifica identità + Condividi con... + Condividi con NFC tenendo i dispositivi a stretto contatto + Info Principale + Condividi + Sottochiavi + Certificati + + Chiavi + Firma e Codifica + Decodifica e Verifica + Importa Chiavi + App Registrate + Apri drawer di navigazione + Chiudi drawer di navigazione + Modifica + Le Mie Chiavi + Chiave Segreta + disponibile + non disponibile + + Scrivi qui il messaggio da codificare e/o firmare... + Inserisci il testo cifrato qui per la decodifica e/o verifica... + + predefiniti + nessuno + casuale + positivo + revocato + ok + fallito! + errore! + chiave non disponibile + + Certificatore + Dettagli Certificato + Identit + <sconosciuto> + Nessun certificato per questa chiave + Identità da certificare + Ragione della Revoca + Stato Verifica + Tipo + Chiave non trovata! + Errore di elaborazione chiave! + sottochiave non disponibile + ripulito + Le chiavi segrete possono essere cancellate solo individualmente! + Visualizza Dettagli Certificati + sconosciuto + non può firmare + Nessuna sottochiave di codifica disponibile! + diff --git a/OpenKeychain/src/main/res/values-ja/strings.xml b/OpenKeychain/src/main/res/values-ja/strings.xml index 1bcf4553b..c40e9dbdc 100644 --- a/OpenKeychain/src/main/res/values-ja/strings.xml +++ b/OpenKeychain/src/main/res/values-ja/strings.xml @@ -264,9 +264,9 @@ Android NFC Beam機能を使うにはAndroid 4.1 が必要です! あなたのデバイスにはNFCが存在しません! インポートするものがありません! - サーバへのクエリーが不足しています - 鍵サーバへのクエリーが失敗 - 鍵が多すぎます。クエリーを整えてください! + 鍵検索のクエリが短かすぎます + サーバでの鍵の検索が回復不可能なエラーになりました + 鍵検索のクエリが沢山の候補を返しました; クエリを精密化してください ファイルに内容がありません 一般エラーが発生しました、この新しいバグの情報をOpenKeychainプロジェクトに送ってください diff --git a/OpenKeychain/src/main/res/values-nl-rNL/strings.xml b/OpenKeychain/src/main/res/values-nl-rNL/strings.xml deleted file mode 100644 index bf6d7f911..000000000 --- a/OpenKeychain/src/main/res/values-nl-rNL/strings.xml +++ /dev/null @@ -1,198 +0,0 @@ - - - - Publieke sleutel selecteren - Privésleutel selecteren - Versleutelen - Ontsleutelen - Wachtwoord - Sleutel aanmaken - Sleutel bewerken - Instellingen - Geregistreerde apps - Wachtwoord instellen - Versleutelen naar bestand - Ontsleutelen naar bestand - Sleutels importeren - Sleutels exporteren - Sleutels exporteren - Sleutel niet gevonden - Help - - Algemeen - Standaard - Geavanceerd - - Opslaan - Annuleren - Verwijderen - Geen - OK - Volgende - Terug - - Instellingen - Importeren uit bestand - Importeren met QR-code - Importeren met NFC - Exporteren naar bestand - Sleutel verwijderen - Sleutel aanmaken - Sleutel aanmaken (expert) - Zoeken - Beam-instellingen - - Ondertekenen - Bericht - Bestand - Geen wachtwoord - Wachtwoord - Opnieuw - Algoritme - ASCII-armor - Verwijderen na versleuteling - Verwijderen na ontsleuteling - Versleutelingsalgoritme - Verificatie-algoritme - Wachtwoordcache - Berichtcompressie - Bestandscompressie - Sleutel-id - Aanmaak - Verlopen - Gebruik - Sleutelgrootte - Naam - Opmerking - E-mailadres - <geen> - <geen sleutel> - versleutelbaar - ondertekenbaar - verlopen - Privésleutel: - - Geen - 15 sec. - 1 min. - 3 min. - 5 min. - 10 min. - 20 min. - 40 min. - 1 uur - 2 uur - 4 uur - 8 uur - DSA - ElGamal - RSA - Openen... - Waarschuwing - Fout - Fout: %s - - - Wachtwoord verkeerd. - Stel eerst een wachtwoord in. - Geen compatibele bestandsbeheerder geïnstalleerd. - De wachtwoorden komen niet overeen. - Symmetrische versleuteling. - Voer het wachtwoord in voor \'%s\' - Weer u zeker dat u het volgende wilt verwijderen:\n%s? - Succesvol verwijderd. - Selecteer eerst een bestand. - Voer het wachtwoord tweemaal in. - Selecteer ten minste één versleutelingssleutel. - Selecter ten minste één versleutelings-/ondertekeningssleutel. - Weet u zeker dat u de privésleutel \'%s\' wilt verwijderen?\nDit kan niet ongedaan worden gemaakt. - Geen sleutels toegevoegd of bijgewerkt. - 1 sleutel succesvol geëxporteerd. - Geen sleutels geëxporteerd. - Kan de sleutel %08X niet vinden. - Lijst is leeg - - verwijderen \'%s\' mislukt - bestand niet gevonden - geen geschikte privésleutel gevonden - externe opslag niet gereed - sleutelgrootte moet minstens 512-bits zijn - de hoofdsleutel kan geen ElGamal-sleutel zijn - onbekende algoritmekeuze - ten minste een hoofdsleutel is vereist - geen wachtwoord opgegeven - geen ondertekeningssleutel opgegeven - geen geldige versleutelingsgegevens - wachtwoord verekerd - kan privésleutel niet uitpakken - - Uw apparaat biedt geen ondersteuning voor NFC - Niets te importeren - - - opslaan... - importeren... - exporteren... - sleutel maken... - hoofdsleutel certificeren... - hoofdsleutelbos maken... - sub-sleutels toevoegen... - ondertekeningssleutel uitpakken... - sleutel uitpakken... - streams voorbereiden... - gegevens versleutelen... - gegevens ontsleutelen... - handtekening voorbereiden... - handtekening genereren... - handtekening verwerken... - handtekening verifiëren... - ondertekenen... - gegevens lezen... - sleutel opzoeken... - gegevens decomprimeren... - integriteit verifiëren... - \'%s\' veilig verwijderen... - - Publieke sleutels zoeken - Privésleutels zoeken - Sleutel delen met... - - 512 - 1024 - 2048 - 4096 - - snel - zeer langzaam - - Beginnen - NFC Beam - Lijst van wijzigingen - Over - Versie: - - Geselecteerde sleutels importeren - QR-code ongeldig. Probeer het opnieuw - QR-code gescand - - - Geen sleutel geselecteerd - Sleutel selecteren - Opslaan - Annuleren - Toegang herroepen - Toegang toestaan - Toegang weigeren - Selecteert u a.u.b. een sleutel - Bekijkt u a.u.b. de ontvangers - - U gaat door alle QR-codes met \'Volgende\', en scant ze een voor een. - - - - - - - diff --git a/OpenKeychain/src/main/res/values-nl/strings.xml b/OpenKeychain/src/main/res/values-nl/strings.xml new file mode 100644 index 000000000..d35d83517 --- /dev/null +++ b/OpenKeychain/src/main/res/values-nl/strings.xml @@ -0,0 +1,474 @@ + + + + Publieke sleutel selecteren + Privésleutel selecteren + Versleutelen + Ontsleutelen + Wachtwoord + Sleutel aanmaken + Sleutel bewerken + Instellingen + Geregistreerde apps + Sleutelserver Voorkeur + Wachtwoord wijzigen + Wachtwoord instellen + Delen met... + Vingerafdruk delen met... + Sleutel delen met... + Bestand delen met... + Versleutelen naar bestand + Ontsleutelen naar bestand + Sleutels importeren + Sleutels exporteren + Sleutels exporteren + Sleutel niet gevonden + Upload naar Sleutelserver + Certifiëer Identiteiten + Sleutel Details + Help + + Identiteiten + Subsleutels + Algemeen + Standaard + Geavanceerd + Master Sleutel + Primaire Identiteit + Acties + Hele sleutel + Uw Sleutel die u gebruikt voor certificatie + Upload Sleutel + Sleutelserver + Versleutel en/of Signeer + Decodeer en Verifiëer + Vingerafdruk + Sleutel om te certificeren + + Certifiëer + Decodeer, verifiëer en sla bestand op + Decodeer en verifiëer bericht + Van Klembord + Codeer en sla bestanden op + Opslaan + Annuleren + Verwijderen + Geen + OK + Verander Nieuw Wachtwoord + Bepaal Nieuwe Wachtwoord + Upload Naar Sleutelserver + Volgende + Terug + Klembord + Delen met... + Opzoeksleutel + Toon geavanceerde instellingen + Verberg geavanceerde instellingen + Gecodeerd/ondertekend bericht delen... + Toon certificatiesleutel + + Instellingen + Help + Importeren uit bestand + Importeren met QR-code + Importeren met NFC + Exporteren naar bestand + Sleutel verwijderen + Sleutel aanmaken + Sleutel aanmaken (expert) + Zoeken + Sleutelserver + Importeren uit Keybase.io + Sleutelserver... + Update van sleutelserver + Upload naar sleutelserver + Delen... + Deel vingerafdruk... + Hele sleutel delen... + met... + met... + met QR Code + met QR Code + met NFC + Kopieer naar klembord + Beam-instellingen + Annuleren + Versleutelen naar... + Alles selecteren + Sleutels toevoegen + Alle sleutels exporteren + + Ondertekenen + Bericht + Bestand + Geen wachtwoord + Wachtwoord + Opnieuw + Algoritme + ASCII-armor + Ontvangers + Verwijderen na versleuteling + Verwijderen na ontsleuteling + Delen Na Versleuteling + Versleutelingsalgoritme + Verificatie-algoritme + met Publieke Sleutel + met Wachtwoord + Wachtwoordcache + Berichtcompressie + Bestandscompressie + Forceer oude OpenPGPv3 Handtekeningen + Sleutelservers + Sleutel-id + Aanmaak + Verlopen + Gebruik + Sleutelgrootte + Primaire identiteit + Naam + Opmerking + E-mailadres + Upload sleutel naar geselecteerde sleutelserver na bevestiging + Vingerafdruk + Selecteren + Bepaal verloopdatum + + %d geselecteerd + %d geselecteerd + + <no naam> + <geen> + <geen sleutel> + versleutelbaar + ondertekenbaar + kan certificeren + kan niet certificeren + verlopen + ingetrokken + + 1 sleutel + %d sleutels + + + %d sleutelserver + %d sleutelservers + + Privésleutel: + + Geen + 15 sec. + 1 min. + 3 min. + 5 min. + 10 min. + 20 min. + 40 min. + 1 uur + 2 uur + 4 uur + 8 uur + voor altijd + DSA + ElGamal + RSA + Openen... + Waarschuwing + Fout + Fout: %s + + Certificeer + Ondertekenen + Versleutelen + Legitimeren + + Wachtwoord verkeerd. + Stel eerst een wachtwoord in. + Geen compatibele bestandsbeheerder geïnstalleerd. + De wachtwoorden komen niet overeen. + Vul een wachtwoord in. + Symmetrische versleuteling. + Voer het wachtwoord in voor \'%s\' + Weer u zeker dat u het volgende wilt verwijderen:\n%s? + Succesvol verwijderd. + Selecteer eerst een bestand. + Succesvol gesigneerd en/of gecodeerd. + Succesvol gesigneerd en/of gecodeerd naar klembord. + Voer het wachtwoord tweemaal in. + Selecteer ten minste één versleutelingssleutel. + Selecter ten minste één versleutelings-/ondertekeningssleutel. + Specifieer naar welk bestand er gecodeerd moet worden.\nWAARSCHUWING: Bestand zal vervangen worden als het bestaat. + Specifieer naar welk bestand gedecodeerd moet worden.\nWAARSCHUWING: Bestand zal vervangen worden als het bestaat. + Specifieer naar welk bestand er geëxporteerd moet worden.\nWAARSCHUWING: Bestand zal vervangen worden als het bestaat. + Weet u zeker dat u alle weergegeven publieke sleutels wilt verwijderen?\nU kunt dit niet ongedaan maken! + Weet u zeker dat u de privésleutel \'%s\' wilt verwijderen?\nDit kan niet ongedaan worden gemaakt. + U heeft veranderingen aangebracht tot de sleutelring, wilt u deze opslaan? + U heeft een lege identiteit toegevoegd, weet u zeker dat u wilt doorgaan? + Wilt u echt de publieke sleutel \'%s\' verwijderen?\nDit kunt u niet ongedaan maken! + Ook geheime sleutels exporteren? + + Succesvol %d sleutel toegevoegd + Succesvol %d sleutels toegevoegd + + + en %d sleutel bijgewerkt. + en %d sleutels bijgewerkt. + + + Succesvol %d sleutel toegevoegd. + Succesvol %d sleutels toegevoegd. + + + Succesvol %d sleutel bijgewerkt. + Succesvol %d sleutels bijgewerkt. + + Geen sleutels toegevoegd of bijgewerkt. + 1 sleutel succesvol geëxporteerd. + Succesvol %d sleutels geëxporteerd. + Geen sleutels geëxporteerd. + Opmerking: alleen subsleutels ondersteunen ElGamal. + Opmerking: RSA sleutel met lengte 1024-bit en minder genereren wordt als onveilig beschouwd en is uitgeschakeld voor het genereren van nieuwe sleutels. + Kan de sleutel %08X niet vinden. + + %d sleutel gevonden. + %d sleutels gevonden. + + + %d slechte geheime sleutel genegeerd. Misschien heeft u geëxporteerd met de optie\n --export-secret-subkeys\nZorg ervoor dat u in plaats daarvan met\n --export-secret-keys\nexporteert. + %d slechte geheime sleutels genegeerd. Misschien heeft u geëxporteerd met de optie\n --export-secret-subkeys\nZorg ervoor dat u in plaats daarvan met\n --export-secret-keys\nexporteert. + + Succesvol sleutel naar server geüpload + Succesvol identiteiten gecertificeerd + Lijst is leeg + Succesvol sleutel verstuurd met NFC Beam! + Sleutel is gekopieerd naar het klembord! + Sleutel is gekopieerd naar het klembord! + Sleutel is al gecertificeerd! + Selecteer een sleutel die gebruikt moet worden voor certificatie! + Sleutel is te groot om op deze manier gedeeld te worden! + + verwijderen \'%s\' mislukt + bestand niet gevonden + geen geschikte privésleutel gevonden + externe opslag niet gereed + sleutelgrootte moet minstens 512-bits zijn + de hoofdsleutel kan geen ElGamal-sleutel zijn + onbekende algoritmekeuze + geen e-mail gevonden + minstens een identiteit vereist + primaire identiteit mag niet leeg zijn + ten minste een hoofdsleutel is vereist + geen wachtwoord opgegeven + geen ondertekeningssleutel opgegeven + geen geldige versleutelingsgegevens + integriteitcheck niet geslaagd! Data is bewerkt! + wachtwoord verekerd + fout bij het opslaan van bepaalde sleutels + kan privésleutel niet uitpakken + vervaldatum moet na de aanmaakdatum zijn + + Directe binaire data zonder eigenlijke bestand in bestandssysteem wordt niet ondersteund. + U heeft minstens Android 4.1 nodig om Androids NFC Beam eigenschap te gebruiken! + Uw apparaat biedt geen ondersteuning voor NFC + Niets te importeren + Bestand heeft geen inhoud + Een algemene fout is opgetreden, maak alstublieft een nieuwe bug report voor OpenKeychain. + + Deel van het geladen bestand is geldig OpenPGP object maar niet een OpenPGP sleutel + Delen van het geladen bestand zijn geldige OpenPGP objecten maar niet OpenPGP sleutels + + U moet veranderingen maken aan de sleutelring voor u het kunt opslaan. + + Ongeldige handtekening! + Onbekende publieke sleutel + Geldige handtekening (ongecertificeerd) + Geldige handtekening (gecertificeerd) + Succesvol gedecodeerd + Succesvol gedecodeerd maar onbekende publieke sleutel + Succesvol gedecodeerd en geldige handtekening (ongecertificeerd) + Succesvol gedecodeerd en geldige handtekening (gecertificeerd) + + Gereed. + Annuleren + opslaan... + importeren... + exporteren... + sleutel maken... + hoofdsleutel certificeren... + hoofdsleutelbos maken... + sub-sleutels toevoegen... + sleutel opslaan... + + sleutel exporteren... + sleutels exporteren... + + + sleutel genereren, dit kan tot 3 minuten duren... + sleutels genereren, dit kan tot 3 minuten duren... + + ondertekeningssleutel uitpakken... + sleutel uitpakken... + streams voorbereiden... + gegevens versleutelen... + gegevens ontsleutelen... + handtekening voorbereiden... + handtekening genereren... + handtekening verwerken... + handtekening verifiëren... + ondertekenen... + gegevens lezen... + sleutel opzoeken... + gegevens decomprimeren... + integriteit verifiëren... + \'%s\' veilig verwijderen... + + Publieke sleutels zoeken + Privésleutels zoeken + Sleutel delen met... + Doorzoek Keybase.io + + 512 + 768 + 1024 + 1536 + 2048 + 3072 + 4096 + 8192 + Aangepaste sleutelgrootte + Typ aangepaste sleutellengte (in bits): + RSA sleutel lengte moet groter zijn dan 1024 en maximaal 8192. Het moet ook deelbaar zijn door 8. + DSA sleutellengte moet minstens 512 zijn en maximaal 1024. Het moet ook deelbaar zijn door 64. + + snel + zeer langzaam + + Beginnen + FAQ + Web van Vertrouwen + NFC Beam + Lijst van wijzigingen + Over + Versie: + + Geselecteerde sleutels importeren + Importeren uit klembord + + Missende QR code met ID %s + Missende QR Codes met ID\'s %s + + Begin met QR Code met ID 1 + QR-code ongeldig. Probeer het opnieuw + QR-code gescand + Vingerafdruk is te kort (< 16 tekens) + Scan QR Code met \'Barcode Scanner\' + Om sleutels via NFC te ontvangen moet het apparaat ontgrendeld zijn. + Help + Verkrijg sleutel uit klembord + Verkrijg sleutel uit Keybase.io + + Decodeer bestand met OpenKeychain + Importeer Sleutel met OpenKeychain + Codeer met OpenKeychain + Decodeer met OpenKeychain + + Geen geregistreerde applicaties!\n\nEen lijst van ondersteunde derde-partij applicaties kan gevonden worden in \'Help\'! + Toon geavanceerde informatie + Verberg geavanceerde informatie + Toon geavanceerde instellingen + Verberg geavanceerde instellingen + Geen sleutel geselecteerd + Sleutel selecteren + Maak nieuwe sleutel voor dit account + Opslaan + Annuleren + Toegang herroepen + Start applicatie + Verwijder account + Pakketnaam + SHA-256 van Pakkethandtekening + Accounts + Geen accounts verbonden aan deze applicatie. + Deze applicatie vraagt de aanmaak van een nieuw account aan. Selecteer een bestaande privésleutel of maak een nieuwe.\nApplicaties zijn gelimiteerd tot het gebruik van sleutels die u hier selecteert! + De weergegeven applicatie vraagt toegang tot OpenKeychain.\nSta toegang toe?\n\nWAARSCHUWING: Als u niet weet waarom dit scherm verscheen, sta dan geen toegang toe! U kunt toegang later weghalen door het \'Geregistreerde Applicaties\' scherm te gebruiken. + Toegang toestaan + Toegang weigeren + Selecteert u a.u.b. een sleutel + Geen publieke sleutels zijn gevonden voor deze identiteiten: + Meer dan een publieke sleutel bestaat voor deze identiteiten: + Bekijkt u a.u.b. de ontvangers + Handtekening check mislukt! Hebt u deze app van een andere bron geïnstalleerd? Als u zeker weet dat dit geen aanval is, haal dan de registratie van deze app in OpenKeychain weg en registreer de app opnieuw. + + Delen met QR-code + U gaat door alle QR-codes met \'Volgende\', en scant ze een voor een. + Vingerafdruk: + QR Code met ID %1$d van %2$d + Deel met NFC + + + 1 sleutel geselecteerd. + %d sleutels geselecteerd. + + Nog geen sleutels beschikbaar... + U kunt beginnen door + of + uw eigen sleutel aanmaken + sleutels importeren. + + Sleutel bewerken + Codeer met deze sleutel + Certifiëer identiteiten + Delen met... + Delen via NFC door de apparaten met de achterkant tegen elkaar te houden + Hoofd Info + Delen + Subsleutels + Certificaten + + Sleutels + Ondertekenen en Versleutelen + Decoderen en Verifiëren + Importeer Sleutels + Geregistreerde apps + Open navigatiemenu + Sluit navigatiemenu + Bewerken + Mijn Sleutels + Geheime Sleutel + beschikbaar + onbeschikbaar + + Schrijf bericht hier om te versleutelen en/of ondertekenen... + Voer cijfertekst hier in om te decoderen en/of verifiëren... + + standaard + geen + eenvoudig + positief + ingetrokken + ok + mislukt! + fout! + sleutel onbeschikbaar + + Certificeer + Certificaat Details + Identiteit + <onbekend> + Geen certificaten voor deze sleutel + Identiteiten om te certificeren + Intrek Reden + Verificatie Status + Type + Sleutel niet gevonden! + Fout bij verwerken sleutel! + subsleutel onbeschikbaar + gestript + Geheime sleutels kunnen alleen individueel verwijderd worden! + Toon Certificaat Details + onbekend + kan niet ondertekenen + Geen codeer-subsleutel beschikbaar! + diff --git a/OpenKeychain/src/main/res/values-pl/strings.xml b/OpenKeychain/src/main/res/values-pl/strings.xml index 2f327c9bd..d1b7de393 100644 --- a/OpenKeychain/src/main/res/values-pl/strings.xml +++ b/OpenKeychain/src/main/res/values-pl/strings.xml @@ -259,9 +259,6 @@ Potrzebujesz Androida 4.1 aby korzystać z Android NFC Beam NCF jest niedostępne na twoim urządzeniu Nie ma nic do zaimportowania! - Niewystarczające zapytanie do serwera - Odpytywanie serwera zakończone niepowodzeniem - Zbyt wiele możliwych kluczy. Proszę zweryfikuj swoje zapytanie! Plik jest pusty Wystąpił błąd ogólny, proszę zgłoś go autorom OpenKeychain. diff --git a/OpenKeychain/src/main/res/values-ru/strings.xml b/OpenKeychain/src/main/res/values-ru/strings.xml index b51bcbde2..0becea0bc 100644 --- a/OpenKeychain/src/main/res/values-ru/strings.xml +++ b/OpenKeychain/src/main/res/values-ru/strings.xml @@ -13,6 +13,10 @@ Настройки сервера ключей Изменить пароль Задать пароль + Отправить... + Отправить отпечаток... + Отправить ключ... + Отправить файл... Зашифровать в файл Расшифровать в файл Импорт ключей @@ -20,22 +24,32 @@ Экспорт ключей Ключ не найден Загрузить на сервер ключей + Сертифицировать Сведения о ключе Помощь + Идентификаторы + Доп. ключи Приложение Алгоритмы Дополнительно Основной ключ + Основной идентификатор Действия + Ключ Ваш ключ для сертификации Загрузить ключ Сервер ключей Зашифровать и/или Подписать Расшифровать и проверить + Отпечаток ключа + Сертифицируемый ключ Сертифицировать + Расшифровать, проверить и сохранить файл + Расшифровать и проверить сообщение Из буфера обмена + Зашифровать и сохранить файл Сохранить Отмена Удалить @@ -51,6 +65,8 @@ Найти ключ Показать расширенные настройки Скрыть расширенные настройки + Отправить зашифрованное/подписанное сообщение... + Просмотр ключа Настройки Помощь @@ -63,6 +79,7 @@ Создать ключ (эксперт) Поиск Сервер ключей + Импорт с сервера Keybase.io Сервер ключей... Обновить с сервера ключей Загрузить на сервер ключей @@ -108,6 +125,7 @@ Годен до... Применение Размер ключа + Основной идентификатор Имя Комментарий Email @@ -174,6 +192,8 @@ Вы уверены, что хотите удалить\n%s ? Удалено. Сначала выберите файл. + Успешно подписано и/или зашифровано. + Успешно подписано и/или зашифровано в буфер обмена. Дважды введите пароль. Укажите хотя бы один ключ. Выберите хотя бы один ключ для шифрования или подписи. @@ -182,6 +202,8 @@ Пожалуйста, выберите файл для экспорта.\nВНИМАНИЕ! Если файл существует, он будет перезаписан. Вы уверены, что хотите удалить выбранные ключи?\nЭто действие нельзя отменить! Вы уверены, что ходите удалить СЕКРЕТНЫЙ ключ \'%s\'?\nЭто действие нельзя отменить! + Изменения внесены. Сохранить? + Вы добавили пустой идентификатор. Вы уверены, что хотите продолжить? Вы правда хотите удалить публичный ключ \'%s\'?\nЭто действие нельзя отменить! Экспортировать секретные ключи? @@ -222,10 +244,13 @@ %d плохих секретных ключей проигнорировано. Возможно, вы экспортируете с параметром\n--export-secret-subkeys\nВместо этого используйте\n--export-secret-keys\n Ключ успешно загружен на сервер + Подписанные идентификаторы Список пуст! Ключ успешно передан через NFC! Ключ скопирован в буфер обмена! + Отпечаток ключа скопирован в буфер обмена! Ключ уже был сертифицирован ранее! + Выберите ключ, используемый для сертификации! Ключ слишком большой для этого способа передачи! Неверная подпись! Неизвестный ключ Верная подпись (не сертифицирована) Верная подпись (сертифицирована) Успешно расшифровано + Успешно расшифровано, но публичный ключ не известен + Успешно расшифровано и подпись верна (не сертифицирована) + Успешно расшифровано и подпись верна (сертифицирована) Готово. Отмена @@ -308,6 +339,7 @@ Найти публичные ключи Найти секретные ключи Отправить... + Поиск на сервере Keybase.io 512 768 @@ -348,12 +380,14 @@ Разблокируйте устройство, что бы получить ключ через NFC. Помощь Получить ключ из буфера + Получить ключ с сервера Keybase.io OpenKeychain: Расшифровать файл OpenKeychain: Импортировать ключ OpenKeychain: Зашифровать OpenKeychain: Расшифровать + Нет связанных приложений!\n\nСписок приложений, поддерживающих интеграцию, доступен в разделе \'Помощь\'! Показать подробную информацию Скрыть подробную информацию Показать расширенные настройки @@ -364,6 +398,7 @@ Сохранить Отмена Отозвать доступ + Запустить приложение Удалить аккаунт Наименование пакета SHA-256 подписи пакета @@ -374,6 +409,8 @@ Разрешить доступ Запретить доступ Пожалуйста, выберите ключ! + Для этих идентификаторов не найдены публичные ключи: + Для этих идентификаторов найдено более одного публичного ключа: Пожалуйста, проверьте получателей! Проверка подписи пакета не удалась! Если вы установили программу из другого источника, отзовите для неё доступ к этой программе или обновите право доступа. @@ -394,7 +431,15 @@ создать свой ключ Импортировать ключи + Изменить ключ Зашифровать этим ключом + Сертифицировать + Отправить... + Отправить по NFC, удерживая устройства рядом + Основные данные + Отправить... + Доп. ключи + Сертификация Ключи Подписать и зашифровать @@ -414,14 +459,18 @@ по умолчанию нет + отозван ok сбой! ошибка! ключ не доступен + Кем подписан Детали сертификации + Идентификатор <неизв.> Этот ключ не сертифицирован + Идентификаторы Причина отзыва Статус верификации Тип @@ -431,4 +480,5 @@ Секретные ключи можно удалять только по одному! Просмотреть детали сертификации неизв. + Нет доп. ключа для шифрования! diff --git a/OpenKeychain/src/main/res/values-sl/strings.xml b/OpenKeychain/src/main/res/values-sl/strings.xml index f80db4b6c..8b12cdebe 100644 --- a/OpenKeychain/src/main/res/values-sl/strings.xml +++ b/OpenKeychain/src/main/res/values-sl/strings.xml @@ -291,9 +291,6 @@ Za uporabo storitve NFC Beam potrebujete najmanj Android 4.1! NFC ni na voljo na vaši napravi! Ni česa uvoziti! - Pomanjkljiva poizvedba na strežniku - Poizvedba na strežniku ni bila uspešna - Preveč možnih ključev. Redefinirajte svoje iskanje! Datoteka nima vsebine Pripetila se je splošna napaka, prosimo ustvarite poročilo o \'hrošču\'. @@ -403,6 +400,7 @@ Šifriraj z OpenKeychain Dešifriraj z OpenKeychain + Ni nobene prijavljene aplikacije!\n\nSeznam podprtih aplikacij drugih avtorjev lahko najdete v Pomoči! Pokaži dodatne informacije Skrij dodatne informacije Pokaži napredne nastavitve @@ -413,6 +411,7 @@ Shrani Prekliči Prekliči dostop + Zaženi aplikacijo Izbriši račun Ime paketa SHA-256 podpisa paketa diff --git a/OpenKeychain/src/main/res/values-uk/strings.xml b/OpenKeychain/src/main/res/values-uk/strings.xml index 54204a044..b27b6ffd3 100644 --- a/OpenKeychain/src/main/res/values-uk/strings.xml +++ b/OpenKeychain/src/main/res/values-uk/strings.xml @@ -13,6 +13,10 @@ Налаштування сервера ключів Змінити парольну фразу Задати парольну фразу + Поділитися через… + Поділитися відбитком із… + Поділитися ключем з… + Поширити файл з… Зашифрувати до файлу Розшифрувати до файлу Імпортувати ключі @@ -20,22 +24,32 @@ Експортувати ключі Ключ не знайдено Завантажити на сервер ключів + Сертифікувати сутності Подробиці про ключ Довідка + Сутності + Підключі Загальне Типове Додаткове Основний ключ + Первинна сутність Дії + Цілий ключ Ваш ключ використаний для сертифікації Завантажити ключ Сервер ключів Шифрувати і/або підписати Розшифрувати і Перевірити + Відбиток + Ключ для сертикації Сертифікувати + Розшифрувати, перевірити та зберегти файл + Розшифрувати і перевірити повідомлення З буфера обміну + Шифрувати і зберегти файл Зберегти Скасувати Вилучити @@ -51,6 +65,8 @@ Шукати ключ Показати додаткові налаштування Приховати додаткові налаштування + Поширити зашифроване/підписане повідомлення… + Переглянути ключ сертифікації Параметри Довідка @@ -63,6 +79,7 @@ Створити ключ (експерт) Пошук Сервер ключів + Імпорт із Keybase.io Сервер ключів… Оновити з сервера ключів Завантажити на сервер ключів @@ -102,11 +119,13 @@ Стиснення повідомлення Стиснення файлу Примусово старі підписи OpenPGPv3 + Сервери ключів ІД ключа Створення Закінчення Використання Розмір ключа + Первинна сутність Назва Коментар Ел. пошта @@ -128,6 +147,16 @@ не можна сертифікувати закінчився скасовано + + 1 ключ + %d ключі + %d ключів + + + %d сервер ключів + %d сервери ключів + %d серверів ключів + Секретний ключ: Жоден @@ -177,6 +206,7 @@ Ви справді хочете вилучити усі вибрані відкриті ключі?\nВи не зможете це відмінити! Ви справді хочете вилучити секретний ключ \'%s\'?\nВи не зможете це відмінити! Ви внесли зміни до в\'язки ключів, ви б хотіли. Волієте їх зберегти? + Ви вже додали порожню сутність. Ви справді хочете продовжити? Ви справді хочете вилучити відкритий ключ \'%s\'?\nВи не зможете це відмінити! Також експортувати секретні ключі? @@ -217,8 +247,13 @@ %d поганих секретних ключів проігноровано. Можливо ви експортували з параметром\n --export-secret-subkeys\nЗробіть ваш експорт з \n --export-secret-keys\nнатомість. Успішно завантажено ключ на сервер + Успішно сертифіковані сутності Цей список - порожній! + Успішно надіслано ключ через промінь NFC! Ключ вже скопійовано у буфер обміну! + Відбиток вже скопійовано до буфера обміну! + Ключ вже сертифіковано! + Будь ласка, виберіть ключ для використання у сертифікації! Ключ надто великий для цього способу поширення! + Пряма передача даних без використання файлу в пам\'яті пристрою не підтримується. + Вам потрібний Android 4.1 для використання функції Androids NFC промінь! NFC недоступний на вашому пристрої! Нема що імпортувати! - Запит обмеженого сервера - Збій сервера ключа запиту + Запит пошуку ключа надто короткий + Невиправна помилка пошуку ключів в сервері + Запит пошуку ключа видав надто багато варіантів. Уточніть пошуковий запит Файл не має вмісту Трапилася загальна помилка, будь ласка, створіть новий звіт про помилку для OpenKeychain. @@ -302,6 +342,7 @@ Пошук публічних ключів Пошук секретних ключів Поділитися ключем з… + Пошук Keybase.io 512 768 @@ -342,12 +383,14 @@ Розблокуйте пристрій, щоб отримати ключ через NFC. Довідка Отримати ключ з буфера обміну + Отримати ключ із Keybase.io Розшифрувати файл з OpenKeychain Імпортувати ключ з OpenKeychain Зашифрувати з OpenKeychain Розшифрувати з OpenKeychain + Немає зареєстрованих програм!\n\nСписок підтримуваних сторонніх програм можна знайти у „Довідці“! Показати додаткову інформацію Приховати додаткову інформацію Показати додаткові налаштування @@ -358,6 +401,7 @@ Зберегти Скасувати Відкликати доступ + Запустити програму Видалити профіль Назва пакунку SHA-256 підписку пакунку @@ -368,6 +412,8 @@ Дозволити доступ Не дозволити доступ Будь ласка, виберіть ключ! + Немає публічних ключів для цих сутностей: + Наявно більше одного публічного ключа для цих сутностей: Будь ласка, перевірте список одержувачів! Перевірка підпису пакету не вдалася! Може ви встановили програму з іншого джерела? Якщо ви впевнені, що це не атака, то відкличте реєстрацію програми у OpenKeychain та знову зареєструйте її. @@ -388,7 +434,17 @@ створюється ваш власний ключ імпортуюся ключі. + Редагувати ключ + Шифрувати з цим ключем + Сертифікувати сутності + Поділитися із… + Поширити через NFC, тримаючи пристрої пліч-о-пліч + Основна інформація + Поділитися + Підключі + Сертифікати + Ключі Підписати і зашифрувати Розшифрувати і Перевірити Імпортувати ключі @@ -408,13 +464,18 @@ жоден випадковий додатний + відкликано Гаразд Невдача! Помилка! Недоступний ключ + Ким підписаний Дані сертифікату + Сутність + <невідомо> Немає сертифікатів для цього ключа + Сутності для сертифікації Причина відхилення Стан перевірки Тип @@ -423,4 +484,7 @@ підключ недоступний Секретні ключі можна вилучити лише окремо! Переглянути дані сертифікату + невідомий + не можна підписати + Жодний підключ шифрування недоступний! -- cgit v1.2.3 From ed8b62c32b704ce2150bfdf7d4047c67648423a1 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 28 May 2014 21:52:45 +0200 Subject: wrapped-key-ring: no UncachedSecretKeyRing after all --- .../keychain/pgp/PgpImportExport.java | 6 ++-- .../keychain/pgp/UncachedKeyRing.java | 26 +++++++++++++++-- .../keychain/pgp/UncachedSecretKeyRing.java | 33 ---------------------- .../keychain/pgp/WrappedPublicKeyRing.java | 15 +++++++++- .../keychain/pgp/WrappedSecretKeyRing.java | 24 ++++++++++++---- .../keychain/provider/KeychainDatabase.java | 4 +-- .../keychain/provider/KeychainProvider.java | 2 +- .../keychain/provider/ProviderHelper.java | 17 ++++++----- .../keychain/service/KeychainIntentService.java | 9 +++--- 9 files changed, 75 insertions(+), 61 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKeyRing.java (limited to 'OpenKeychain') 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 268906037..91bb89995 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java @@ -168,7 +168,7 @@ public class PgpImportExport { status = storeKeyRingInCache(new UncachedKeyRing(newPubRing), new UncachedKeyRing(secretKeyRing)); } else { - status = storeKeyRingInCache(new UncachedKeyRing((PGPPublicKeyRing) keyring)); + status = storeKeyRingInCache(new UncachedKeyRing(keyring)); } if (status == RETURN_ERROR) { @@ -288,13 +288,13 @@ public class PgpImportExport { public int storeKeyRingInCache(UncachedKeyRing ring, UncachedKeyRing secretRing) { int status; try { - UncachedSecretKeyRing secretKeyRing = null; + UncachedKeyRing secretKeyRing = null; // see what type we have. we can either have a secret + public keyring, or just public if (secretKeyRing != null) { mProviderHelper.saveKeyRing(ring, secretRing); status = RETURN_OK; } else { - mProviderHelper.saveKeyRing(ring); + mProviderHelper.savePublicKeyRing(ring); status = RETURN_OK; } } catch (IOException e) { 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 8bacb32c0..e17d07390 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -1,13 +1,16 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.bcpg.ArmoredOutputStream; +import org.spongycastle.bcpg.S2K; import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPObjectFactory; import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.openpgp.PGPSecretKey; 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.IterableIterator; import org.sufficientlysecure.keychain.util.Log; import java.io.BufferedInputStream; @@ -15,6 +18,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Vector; @@ -70,7 +74,7 @@ public class UncachedKeyRing { return mRing.getPublicKey().getFingerprint(); } - public static UncachedKeyRing decodePubkeyFromData(byte[] data) + public static UncachedKeyRing decodePublicFromData(byte[] data) throws PgpGeneralException, IOException { UncachedKeyRing ring = decodeFromData(data); if(ring.isSecret()) { @@ -90,7 +94,6 @@ public class UncachedKeyRing { // get first object in block Object obj; if ((obj = objectFactory.nextObject()) != null && obj instanceof PGPKeyRing) { - // the constructor will take care of the public/secret part return new UncachedKeyRing((PGPKeyRing) obj); } else { throw new PgpGeneralException("Object not recognized as PGPKeyRing!"); @@ -128,4 +131,23 @@ public class UncachedKeyRing { aos.close(); } + public ArrayList getAvailableSubkeys() { + if(!isSecret()) { + throw new RuntimeException("Tried to find available subkeys from non-secret keys. " + + "This is a programming error and should never happen!"); + } + + ArrayList result = new ArrayList(); + // then, mark exactly the keys we have available + for (PGPSecretKey sub : new IterableIterator( + ((PGPSecretKeyRing) mRing).getSecretKeys())) { + S2K s2k = sub.getS2K(); + // Set to 1, except if the encryption type is GNU_DUMMY_S2K + if(s2k == null || s2k.getType() != S2K.GNU_DUMMY_S2K) { + result.add(sub.getKeyID()); + } + } + return result; + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKeyRing.java deleted file mode 100644 index ca784fbde..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedSecretKeyRing.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.sufficientlysecure.keychain.pgp; - -import org.spongycastle.bcpg.S2K; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.util.IterableIterator; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; - -public class UncachedSecretKeyRing extends UncachedKeyRing { - - UncachedSecretKeyRing(PGPSecretKeyRing secretRing) { - super(secretRing); - } - - public ArrayList getAvailableSubkeys() { - ArrayList result = new ArrayList(); - // then, mark exactly the keys we have available - for (PGPSecretKey sub : new IterableIterator( - ((PGPSecretKeyRing) mRing).getSecretKeys())) { - S2K s2k = sub.getS2K(); - // Set to 1, except if the encryption type is GNU_DUMMY_S2K - if(s2k == null || s2k.getType() != S2K.GNU_DUMMY_S2K) { - result.add(sub.getKeyID()); - } - } - return result; - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKeyRing.java index 624382165..99dc99436 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKeyRing.java @@ -3,6 +3,8 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.SignatureSubpacketTags; import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPKeyRing; +import org.spongycastle.openpgp.PGPObjectFactory; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPSignature; @@ -12,6 +14,7 @@ import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProv import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.util.IterableIterator; +import org.sufficientlysecure.keychain.util.Log; import java.io.IOException; import java.security.SignatureException; @@ -30,7 +33,17 @@ public class WrappedPublicKeyRing extends WrappedKeyRing { PGPPublicKeyRing getRing() { if(mRing == null) { - mRing = (PGPPublicKeyRing) PgpConversionHelper.BytesToPGPKeyRing(mPubKey); + PGPObjectFactory factory = new PGPObjectFactory(mPubKey); + PGPKeyRing keyRing = null; + try { + if ((keyRing = (PGPKeyRing) factory.nextObject()) == null) { + Log.e(Constants.TAG, "No keys given!"); + } + } catch (IOException e) { + Log.e(Constants.TAG, "Error while converting to PGPKeyRing!", e); + } + + mRing = (PGPPublicKeyRing) keyRing; } return mRing; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java index 656430969..91d4286f4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java @@ -1,7 +1,10 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPKeyRing; +import org.spongycastle.openpgp.PGPObjectFactory; import org.spongycastle.openpgp.PGPPrivateKey; +import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; @@ -11,6 +14,7 @@ import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.util.IterableIterator; +import org.sufficientlysecure.keychain.util.Log; import java.io.IOException; import java.security.NoSuchProviderException; @@ -23,7 +27,17 @@ public class WrappedSecretKeyRing extends WrappedKeyRing { public WrappedSecretKeyRing(byte[] blob, boolean isRevoked, int verified) { super(isRevoked, verified); - mRing = (PGPSecretKeyRing) PgpConversionHelper.BytesToPGPKeyRing(blob); + PGPObjectFactory factory = new PGPObjectFactory(blob); + PGPKeyRing keyRing = null; + try { + if ((keyRing = (PGPKeyRing) factory.nextObject()) == null) { + Log.e(Constants.TAG, "No keys given!"); + } + } catch (IOException e) { + Log.e(Constants.TAG, "Error while converting to PGPKeyRing!", e); + } + + mRing = (PGPSecretKeyRing) keyRing; } PGPSecretKeyRing getRing() { @@ -77,7 +91,7 @@ public class WrappedSecretKeyRing extends WrappedKeyRing { } } - public UncachedSecretKeyRing changeSecretKeyPassphrase(String oldPassphrase, + public UncachedKeyRing changeSecretKeyPassphrase(String oldPassphrase, String newPassphrase) throws IOException, PGPException, NoSuchProviderException { @@ -96,7 +110,7 @@ public class WrappedSecretKeyRing extends WrappedKeyRing { new JcePBESecretKeyEncryptorBuilder(mRing.getSecretKey() .getKeyEncryptionAlgorithm()).build(newPassphrase.toCharArray())); - return new UncachedSecretKeyRing(newKeyRing); + return new UncachedKeyRing(newKeyRing); } @@ -120,8 +134,8 @@ public class WrappedSecretKeyRing extends WrappedKeyRing { }); } - public UncachedSecretKeyRing getUncached() { - return new UncachedSecretKeyRing(mRing); + public UncachedKeyRing getUncached() { + return new UncachedKeyRing(mRing); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index ed8171587..ceaa93f9b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -268,7 +268,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { byte[] data = cursor.getBlob(0); try { UncachedKeyRing ring = UncachedKeyRing.decodeFromData(data); - providerHelper.saveKeyRing(ring); + providerHelper.savePublicKeyRing(ring); } catch(PgpGeneralException e) { Log.e(Constants.TAG, "Error decoding keyring blob!"); } @@ -292,7 +292,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { byte[] data = cursor.getBlob(0); try { UncachedKeyRing ring = UncachedKeyRing.decodeFromData(data); - providerHelper.saveKeyRing(ring); + providerHelper.savePublicKeyRing(ring); } catch(PgpGeneralException e) { Log.e(Constants.TAG, "Error decoding keyring blob!"); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 2f6cded91..b651069e9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -621,7 +621,7 @@ public class KeychainProvider extends ContentProvider { case KEY_RING_CERTS: // we replace here, keeping only the latest signature - // TODO this would be better handled in saveKeyRing directly! + // TODO this would be better handled in savePublicKeyRing directly! db.replaceOrThrow(Tables.CERTS, null, values); keyId = values.getAsLong(Certs.MASTER_KEY_ID); break; 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 b6f75e00d..55e8c77d1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -35,7 +35,6 @@ import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing; 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.pgp.WrappedSignature; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; @@ -151,7 +150,7 @@ public class ProviderHelper { if (data != null) { try { result.put(masterKeyId, - UncachedKeyRing.decodePubkeyFromData(data).getPublicKey()); + UncachedKeyRing.decodePublicFromData(data).getPublicKey()); } catch(PgpGeneralException e) { Log.e(Constants.TAG, "Error parsing keyring, skipping."); } catch(IOException e) { @@ -221,12 +220,12 @@ public class ProviderHelper { * Saves PGPPublicKeyRing with its keys and userIds in DB */ @SuppressWarnings("unchecked") - public void saveKeyRing(UncachedKeyRing keyRing) throws IOException { + public void savePublicKeyRing(UncachedKeyRing keyRing) throws IOException { UncachedPublicKey masterKey = keyRing.getPublicKey(); long masterKeyId = masterKey.getKeyId(); // IF there is a secret key, preserve it! - UncachedSecretKeyRing secretRing = null; + UncachedKeyRing secretRing = null; try { secretRing = getWrappedSecretKeyRing(masterKeyId).getUncached(); } catch (NotFoundException e) { @@ -343,7 +342,7 @@ public class ProviderHelper { // Save the saved keyring (if any) if (secretRing != null) { - saveKeyRing(secretRing); + saveSecretKeyRing(secretRing); } } @@ -373,7 +372,7 @@ 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 keyRing) throws IOException { + public void saveSecretKeyRing(UncachedKeyRing keyRing) throws IOException { long masterKeyId = keyRing.getMasterKeyId(); { @@ -413,12 +412,12 @@ public class ProviderHelper { public void saveKeyRing(UncachedKeyRing pubRing, UncachedKeyRing secRing) throws IOException { long masterKeyId = pubRing.getPublicKey().getKeyId(); - // delete secret keyring (so it isn't unnecessarily saved by public-saveKeyRing below) + // delete secret keyring (so it isn't unnecessarily saved by public-savePublicKeyRing below) mContentResolver.delete(KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId)), null, null); // save public keyring - saveKeyRing(pubRing); - saveKeyRing(secRing); + savePublicKeyRing(pubRing); + savePublicKeyRing(secRing); } /** 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 69eab9d4e..2655e9aa0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -45,7 +45,6 @@ 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; @@ -514,10 +513,10 @@ public class KeychainIntentService extends IntentService if (!canSign) { setProgress(R.string.progress_building_key, 0, 100); WrappedSecretKeyRing keyRing = providerHelper.getWrappedSecretKeyRing(masterKeyId); - UncachedSecretKeyRing newKeyRing = + UncachedKeyRing newKeyRing = keyRing.changeSecretKeyPassphrase(oldPassphrase, newPassphrase); setProgress(R.string.progress_saving_key_ring, 50, 100); - providerHelper.saveKeyRing(newKeyRing); + providerHelper.saveSecretKeyRing(newKeyRing); setProgress(R.string.progress_done, 100, 100); } else { PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 90, 100)); @@ -533,7 +532,7 @@ public class KeychainIntentService extends IntentService UncachedKeyRing ring = keyOperations.buildNewSecretKey(saveParcel); //new Keyring // save the pair setProgress(R.string.progress_saving_key_ring, 90, 100); - providerHelper.saveKeyRing(ring); + providerHelper.savePublicKeyRing(ring); } setProgress(R.string.progress_done, 100, 100); @@ -795,7 +794,7 @@ public class KeychainIntentService extends IntentService // create PGPKeyRing object based on downloaded armored key UncachedKeyRing downloadedKey = - UncachedKeyRing.decodePubkeyFromData(downloadedKeyBytes); + UncachedKeyRing.decodePublicFromData(downloadedKeyBytes); // verify downloaded key by comparing fingerprints if (entry.getFingerprintHex() != null) { -- cgit v1.2.3 From e27048fe73eab25561cd53e64e96960afeb37aac Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Fri, 30 May 2014 17:11:54 +0200 Subject: wrapped-key-ring: move key data around in ParcelableKeyRing instead of ImportKeysListEntry --- .../keychain/keyimport/ImportKeysListEntry.java | 24 ----- .../keychain/keyimport/ParcelableKeyRing.java | 51 +++++++++++ .../keychain/pgp/PgpConversionHelper.java | 20 ---- .../keychain/pgp/PgpImportExport.java | 102 +++++---------------- .../keychain/service/KeychainIntentService.java | 54 +++-------- .../keychain/ui/ImportKeysActivity.java | 9 +- .../keychain/ui/ImportKeysListFragment.java | 23 ++++- .../keychain/ui/adapter/ImportKeysAdapter.java | 3 +- .../keychain/ui/adapter/ImportKeysListLoader.java | 16 ++-- 9 files changed, 119 insertions(+), 183 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java index 0187fe52a..c43f72235 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java @@ -21,13 +21,10 @@ import android.content.Context; import android.os.Parcel; import android.os.Parcelable; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.UncachedPublicKey; -import org.sufficientlysecure.keychain.util.Log; -import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; @@ -50,8 +47,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable { private boolean mSelected; - private byte[] mBytes = new byte[]{}; - public int describeContents() { return 0; } @@ -69,8 +64,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable { dest.writeString(algorithm); dest.writeByte((byte) (secretKey ? 1 : 0)); dest.writeByte((byte) (mSelected ? 1 : 0)); - dest.writeInt(mBytes.length); - dest.writeByteArray(mBytes); dest.writeString(mExtraData); } @@ -89,8 +82,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable { vr.algorithm = source.readString(); vr.secretKey = source.readByte() == 1; vr.mSelected = source.readByte() == 1; - vr.mBytes = new byte[source.readInt()]; - source.readByteArray(vr.mBytes); vr.mExtraData = source.readString(); return vr; @@ -105,14 +96,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable { return keyIdHex; } - public byte[] getBytes() { - return mBytes; - } - - public void setBytes(byte[] bytes) { - this.mBytes = bytes; - } - public boolean isSelected() { return mSelected; } @@ -229,13 +212,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable { */ @SuppressWarnings("unchecked") public ImportKeysListEntry(Context context, UncachedKeyRing ring) { - // save actual key object into entry, used to import it later - try { - this.mBytes = ring.getEncoded(); - } catch (IOException e) { - Log.e(Constants.TAG, "IOException on pgpKeyRing.getEncoded()", e); - } - // selected is default this.mSelected = true; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java new file mode 100644 index 000000000..3d3b6339a --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java @@ -0,0 +1,51 @@ +package org.sufficientlysecure.keychain.keyimport; + +import android.os.Parcel; +import android.os.Parcelable; + +import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; + +import java.io.IOException; + +/** This is a trivial wrapper around UncachedKeyRing which implements Parcelable. It exists + * for the sole purpose of keeping spongycastle and android imports in separate packages. + */ +public class ParcelableKeyRing implements Parcelable { + + final byte[] mBytes; + final String mExpectedFingerprint; + + public ParcelableKeyRing(byte[] bytes) { + mBytes = bytes; + mExpectedFingerprint = null; + } + public ParcelableKeyRing(byte[] bytes, String expectedFingerprint) { + mBytes = bytes; + mExpectedFingerprint = expectedFingerprint; + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeByteArray(mBytes); + dest.writeString(mExpectedFingerprint); + } + + public static final Creator CREATOR = new Creator() { + public ParcelableKeyRing createFromParcel(final Parcel source) { + return new ParcelableKeyRing(source.createByteArray()); + } + + public ParcelableKeyRing[] newArray(final int size) { + return new ParcelableKeyRing[size]; + } + }; + + + public int describeContents() { + return 0; + } + + public UncachedKeyRing getUncachedKeyRing() throws PgpGeneralException, IOException { + return UncachedKeyRing.decodeFromData(mBytes); + } +} 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 ea3c72fd0..591ccdc8e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConversionHelper.java @@ -30,26 +30,6 @@ import java.util.Iterator; public class PgpConversionHelper { - /** - * Convert from byte[] to PGPKeyRing - * - * @param keysBytes - * @return - */ - public static PGPKeyRing BytesToPGPKeyRing(byte[] keysBytes) { - PGPObjectFactory factory = new PGPObjectFactory(keysBytes); - PGPKeyRing keyRing = null; - try { - if ((keyRing = (PGPKeyRing) factory.nextObject()) == null) { - Log.e(Constants.TAG, "No keys given!"); - } - } catch (IOException e) { - Log.e(Constants.TAG, "Error while converting to PGPKeyRing!", e); - } - - return keyRing; - } - /** * Convert from byte[] to ArrayList * 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 91bb89995..1e58c188f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java @@ -24,20 +24,14 @@ import android.os.Environment; import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPKeyRing; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; -import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.keyimport.Keyserver.AddKeyException; import org.sufficientlysecure.keychain.util.Log; @@ -62,7 +56,6 @@ public class PgpImportExport { private ProviderHelper mProviderHelper; public static final int RETURN_OK = 0; - public static final int RETURN_ERROR = -1; public static final int RETURN_BAD = -2; public static final int RETURN_UPDATED = 1; @@ -133,7 +126,7 @@ public class PgpImportExport { /** * Imports keys from given data. If keyIds is given only those are imported */ - public Bundle importKeyRings(List entries) + public Bundle importKeyRings(List entries) throws PgpGeneralException, PGPException, IOException { Bundle returnData = new Bundle(); @@ -144,55 +137,26 @@ public class PgpImportExport { int badKeys = 0; int position = 0; - try { - for (ImportKeysListEntry entry : entries) { - Object obj = PgpConversionHelper.BytesToPGPKeyRing(entry.getBytes()); - - if (obj instanceof PGPKeyRing) { - PGPKeyRing keyring = (PGPKeyRing) obj; - int status; - // TODO Better try to get this one from the db first! - if(keyring instanceof PGPSecretKeyRing) { - PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring; - // TODO: preserve certifications - // (http://osdir.com/ml/encryption.bouncy-castle.devel/2007-01/msg00054.html ?) - PGPPublicKeyRing newPubRing = null; - for (PGPPublicKey key : new IterableIterator( - secretKeyRing.getPublicKeys())) { - if (newPubRing == null) { - newPubRing = new PGPPublicKeyRing(key.getEncoded(), - new JcaKeyFingerprintCalculator()); - } - newPubRing = PGPPublicKeyRing.insertPublicKey(newPubRing, key); - } - status = storeKeyRingInCache(new UncachedKeyRing(newPubRing), - new UncachedKeyRing(secretKeyRing)); - } else { - status = storeKeyRingInCache(new UncachedKeyRing(keyring)); - } - - if (status == RETURN_ERROR) { - throw new PgpGeneralException( - mContext.getString(R.string.error_saving_keys)); - } - - // update the counts to display to the user at the end - if (status == RETURN_UPDATED) { - ++oldKeys; - } else if (status == RETURN_OK) { - ++newKeys; - } else if (status == RETURN_BAD) { - ++badKeys; - } - } else { - Log.e(Constants.TAG, "Object not recognized as PGPKeyRing!"); - } - - position++; - updateProgress(position / entries.size() * 100, 100); + for (ParcelableKeyRing entry : entries) { + try { + UncachedKeyRing key = entry.getUncachedKeyRing(); + + mProviderHelper.savePublicKeyRing(key); + /*switch(status) { + case RETURN_UPDATED: oldKeys++; break; + case RETURN_OK: newKeys++; break; + case RETURN_BAD: badKeys++; break; + }*/ + // TODO proper import feedback + newKeys += 1; + + } catch (PgpGeneralException e) { + Log.e(Constants.TAG, "Encountered bad key on import!", e); + ++badKeys; } - } catch (Exception e) { - Log.e(Constants.TAG, "Exception on parsing key file!", e); + // update progress + position++; + updateProgress(position / entries.size() * 100, 100); } returnData.putInt(KeychainIntentService.RESULT_IMPORT_ADDED, newKeys); @@ -280,28 +244,4 @@ public class PgpImportExport { return returnData; } - public int storeKeyRingInCache(UncachedKeyRing ring) { - return storeKeyRingInCache(ring, null); - } - - @SuppressWarnings("unchecked") - public int storeKeyRingInCache(UncachedKeyRing ring, UncachedKeyRing secretRing) { - int status; - try { - UncachedKeyRing secretKeyRing = null; - // see what type we have. we can either have a secret + public keyring, or just public - if (secretKeyRing != null) { - mProviderHelper.saveKeyRing(ring, secretRing); - status = RETURN_OK; - } else { - mProviderHelper.savePublicKeyRing(ring); - status = RETURN_OK; - } - } catch (IOException e) { - status = RETURN_ERROR; - } - - return status; - } - } 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 2655e9aa0..c1e7dddb5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -32,6 +32,7 @@ import org.sufficientlysecure.keychain.helper.FileHelper; import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; +import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.WrappedSecretKey; @@ -40,7 +41,6 @@ import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpImportExport; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyOperation; import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt; import org.sufficientlysecure.keychain.pgp.Progressable; @@ -56,7 +56,6 @@ import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserver; 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; @@ -645,7 +644,7 @@ public class KeychainIntentService extends IntentService } } else if (ACTION_IMPORT_KEYRING.equals(action)) { try { - List entries = data.getParcelableArrayList(IMPORT_KEY_LIST); + List entries = data.getParcelableArrayList(IMPORT_KEY_LIST); PgpImportExport pgpImportExport = new PgpImportExport(this, this); Bundle resultData = pgpImportExport.importKeyRings(entries); @@ -739,32 +738,21 @@ public class KeychainIntentService extends IntentService try { KeybaseKeyserver server = new KeybaseKeyserver(); + ArrayList keyRings = new ArrayList(entries.size()); for (ImportKeysListEntry entry : entries) { // the keybase handle is in userId(1) String keybaseId = entry.getExtraData(); byte[] downloadedKeyBytes = server.get(keybaseId).getBytes(); - // create PGPKeyRing object based on downloaded armored key - UncachedKeyRing downloadedKey = null; - BufferedInputStream bufferedInput = - new BufferedInputStream(new ByteArrayInputStream(downloadedKeyBytes)); - if (bufferedInput.available() > 0) { - List rings = UncachedKeyRing.fromStream(bufferedInput); - if(rings.isEmpty()) { - throw new PgpGeneralException("No keys in result!"); - } - downloadedKey = rings.get(0); - } - // save key bytes in entry object for doing the // actual import afterwards - entry.setBytes(downloadedKey.getEncoded()); + keyRings.add(new ParcelableKeyRing(downloadedKeyBytes)); } Intent importIntent = new Intent(this, KeychainIntentService.class); importIntent.setAction(ACTION_IMPORT_KEYRING); Bundle importData = new Bundle(); - importData.putParcelableArrayList(IMPORT_KEY_LIST, entries); + importData.putParcelableArrayList(IMPORT_KEY_LIST, keyRings); importIntent.putExtra(EXTRA_DATA, importData); importIntent.putExtra(EXTRA_MESSENGER, mMessenger); @@ -778,11 +766,12 @@ public class KeychainIntentService extends IntentService } else if (ACTION_DOWNLOAD_AND_IMPORT_KEYS.equals(action)) { try { ArrayList entries = data.getParcelableArrayList(DOWNLOAD_KEY_LIST); - String keyServer = data.getString(DOWNLOAD_KEY_SERVER); // this downloads the keys and places them into the ImportKeysListEntry entries + String keyServer = data.getString(DOWNLOAD_KEY_SERVER); HkpKeyserver server = new HkpKeyserver(keyServer); + ArrayList keyRings = new ArrayList(entries.size()); for (ImportKeysListEntry entry : entries) { // if available use complete fingerprint for get request byte[] downloadedKeyBytes; @@ -792,32 +781,15 @@ public class KeychainIntentService extends IntentService downloadedKeyBytes = server.get(entry.getKeyIdHex()).getBytes(); } - // create PGPKeyRing object based on downloaded armored key - UncachedKeyRing downloadedKey = - UncachedKeyRing.decodePublicFromData(downloadedKeyBytes); - - // verify downloaded key by comparing fingerprints - if (entry.getFingerprintHex() != null) { - String downloadedKeyFp = PgpKeyHelper.convertFingerprintToHex( - downloadedKey.getFingerprint()); - if (downloadedKeyFp.equals(entry.getFingerprintHex())) { - Log.d(Constants.TAG, "fingerprint of downloaded key is the same as " + - "the requested fingerprint!"); - } else { - throw new PgpGeneralException("fingerprint of downloaded key is " + - "NOT the same as the requested fingerprint!"); - } - } - // save key bytes in entry object for doing the // actual import afterwards - entry.setBytes(downloadedKeyBytes); + keyRings.add(new ParcelableKeyRing(downloadedKeyBytes, entry.getFingerprintHex())); } Intent importIntent = new Intent(this, KeychainIntentService.class); importIntent.setAction(ACTION_IMPORT_KEYRING); Bundle importData = new Bundle(); - importData.putParcelableArrayList(IMPORT_KEY_LIST, entries); + importData.putParcelableArrayList(IMPORT_KEY_LIST, keyRings); importIntent.putExtra(EXTRA_DATA, importData); importIntent.putExtra(EXTRA_MESSENGER, mMessenger); @@ -853,13 +825,9 @@ public class KeychainIntentService extends IntentService UncachedKeyRing newRing = certificationKey.certifyUserIds(publicRing, userIds); // store the signed key in our local cache - PgpImportExport pgpImportExport = new PgpImportExport(this, null); - int retval = pgpImportExport.storeKeyRingInCache(newRing); - if (retval != PgpImportExport.RETURN_OK && retval != PgpImportExport.RETURN_UPDATED) { - throw new PgpGeneralException("Failed to store signed key in local cache"); - } - + providerHelper.savePublicKeyRing(newRing); sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); + } catch (Exception e) { sendErrorToHandler(e); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index 35076287b..d33d450f9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -42,6 +42,7 @@ import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; @@ -415,8 +416,8 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O // fill values for this action Bundle data = new Bundle(); - // get selected key entries - ArrayList selectedEntries = mListFragment.getSelectedData(); + // get DATA from selected key entries + ArrayList selectedEntries = mListFragment.getSelectedData(); data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, selectedEntries); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); @@ -442,7 +443,7 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O data.putString(KeychainIntentService.DOWNLOAD_KEY_SERVER, mListFragment.getKeyServer()); // get selected key entries - ArrayList selectedEntries = mListFragment.getSelectedData(); + ArrayList selectedEntries = mListFragment.getSelectedEntries(); data.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST, selectedEntries); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); @@ -466,7 +467,7 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O Bundle data = new Bundle(); // get selected key entries - ArrayList selectedEntries = mListFragment.getSelectedData(); + ArrayList selectedEntries = mListFragment.getSelectedEntries(); data.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST, selectedEntries); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java index e93d717e1..8f0a715bf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java @@ -23,6 +23,7 @@ import android.os.Bundle; import android.support.v4.app.ListFragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; +import android.support.v4.util.LongSparseArray; import android.view.View; import android.widget.ListView; @@ -31,6 +32,7 @@ import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.ui.adapter.AsyncTaskResultWrapper; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; @@ -67,6 +69,8 @@ public class ImportKeysListFragment extends ListFragment implements private static final int LOADER_ID_SERVER_QUERY = 1; private static final int LOADER_ID_KEYBASE = 2; + private LongSparseArray mCachedKeyData; + public byte[] getKeyBytes() { return mKeyBytes; } @@ -91,8 +95,16 @@ public class ImportKeysListFragment extends ListFragment implements return mAdapter.getData(); } - public ArrayList getSelectedData() { - return mAdapter.getSelectedData(); + public ArrayList getSelectedData() { + ArrayList result = new ArrayList(); + for(ImportKeysListEntry entry : getSelectedEntries()) { + result.add(mCachedKeyData.get(entry.getKeyId())); + } + return result; + } + + public ArrayList getSelectedEntries() { + return mAdapter.getSelectedEntries(); } /** @@ -120,8 +132,7 @@ public class ImportKeysListFragment extends ListFragment implements mActivity = getActivity(); - // Give some text to display if there is no data. In a real - // application this would come from a resource. + // Give some text to display if there is no data. setEmptyText(mActivity.getString(R.string.error_nothing_import)); // Create an empty adapter we will use to display the loaded data. @@ -252,11 +263,15 @@ public class ImportKeysListFragment extends ListFragment implements Exception error = data.getError(); + // free old cached key data + mCachedKeyData = null; + switch (loader.getId()) { case LOADER_ID_BYTES: if (error == null) { // No error + mCachedKeyData = ((ImportKeysListLoader) loader).getParcelableRings(); } else if (error instanceof ImportKeysListLoader.FileHasNoContent) { AppMsg.makeText(getActivity(), R.string.error_import_file_no_content, AppMsg.STYLE_ALERT).show(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java index 9573efdfe..114c6afae 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java @@ -32,6 +32,7 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; +import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.util.Highlighter; @@ -83,7 +84,7 @@ public class ImportKeysAdapter extends ArrayAdapter { return mData; } - public ArrayList getSelectedData() { + public ArrayList getSelectedEntries() { ArrayList selectedData = new ArrayList(); for (ImportKeysListEntry entry : mData) { if (entry.isSelected()) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java index 46b50ac98..03a82696d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java @@ -19,9 +19,11 @@ package org.sufficientlysecure.keychain.ui.adapter; import android.content.Context; import android.support.v4.content.AsyncTaskLoader; +import android.support.v4.util.LongSparseArray; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; +import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; @@ -54,6 +56,7 @@ public class ImportKeysListLoader final InputData mInputData; ArrayList mData = new ArrayList(); + LongSparseArray mParcelableRings = new LongSparseArray(); AsyncTaskResultWrapper> mEntryListWrapper; public ImportKeysListLoader(Context context, InputData inputData) { @@ -105,6 +108,10 @@ public class ImportKeysListLoader super.deliverResult(data); } + public LongSparseArray getParcelableRings() { + return mParcelableRings; + } + /** * Reads all PGPKeyRing objects from input * @@ -129,7 +136,9 @@ public class ImportKeysListLoader // todo deal with non-keyring objects? List rings = UncachedKeyRing.fromStream(bufferedInput); for(UncachedKeyRing key : rings) { - addToData(key); + ImportKeysListEntry item = new ImportKeysListEntry(getContext(), key); + mData.add(item); + mParcelableRings.put(key.getMasterKeyId(), new ParcelableKeyRing(key.getEncoded())); isEmpty = false; } } @@ -145,9 +154,4 @@ public class ImportKeysListLoader } } - private void addToData(UncachedKeyRing keyring) { - ImportKeysListEntry item = new ImportKeysListEntry(getContext(), keyring); - mData.add(item); - } - } -- cgit v1.2.3 From d891f753393d26bbf3c1f766deddf71f6c9ce5ae Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 31 May 2014 12:58:35 +0200 Subject: make everything work again --- .../sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 5 +++-- .../keychain/provider/ProviderHelper.java | 16 ++++++++++++++-- .../keychain/service/KeychainIntentService.java | 9 +++++---- 3 files changed, 22 insertions(+), 8 deletions(-) (limited to 'OpenKeychain') 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 3e296edb9..44fc4c8c9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -197,7 +197,7 @@ public class PgpKeyOperation { } } - public UncachedKeyRing buildNewSecretKey( + public Pair buildNewSecretKey( OldSaveKeyringParcel saveParcel) throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException { @@ -336,8 +336,9 @@ public class PgpKeyOperation { } PGPSecretKeyRing secretKeyRing = keyGen.generateSecretKeyRing(); + PGPPublicKeyRing publicKeyRing = keyGen.generatePublicKeyRing(); - return new UncachedKeyRing(secretKeyRing); + return new Pair(new UncachedKeyRing(secretKeyRing), new UncachedKeyRing(publicKeyRing)); } 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 55e8c77d1..043c40b25 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -187,7 +187,6 @@ public class ProviderHelper { return (WrappedSecretKeyRing) getWrappedKeyRing(queryUri, true); } - private KeyRing getWrappedKeyRing(Uri queryUri, boolean secret) throws NotFoundException { Cursor cursor = mContentResolver.query(queryUri, new String[]{ @@ -203,6 +202,9 @@ public class ProviderHelper { boolean hasAnySecret = cursor.getInt(0) > 0; int verified = cursor.getInt(1); byte[] blob = cursor.getBlob(2); + if(secret &! hasAnySecret) { + throw new NotFoundException("Secret key not available!"); + } return secret ? new WrappedSecretKeyRing(blob, hasAnySecret, verified) : new WrappedPublicKeyRing(blob, hasAnySecret, verified); @@ -221,6 +223,11 @@ public class ProviderHelper { */ @SuppressWarnings("unchecked") public void savePublicKeyRing(UncachedKeyRing keyRing) throws IOException { + if (keyRing.isSecret()) { + throw new RuntimeException("Tried to save secret keyring as public! " + + "This is a bug, please file a bug report."); + } + UncachedPublicKey masterKey = keyRing.getPublicKey(); long masterKeyId = masterKey.getKeyId(); @@ -373,6 +380,11 @@ public class ProviderHelper { * is already in the database! */ public void saveSecretKeyRing(UncachedKeyRing keyRing) throws IOException { + if (!keyRing.isSecret()) { + throw new RuntimeException("Tried to save publkc keyring as secret! " + + "This is a bug, please file a bug report."); + } + long masterKeyId = keyRing.getMasterKeyId(); { @@ -417,7 +429,7 @@ public class ProviderHelper { // save public keyring savePublicKeyRing(pubRing); - savePublicKeyRing(secRing); + saveSecretKeyRing(secRing); } /** 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 c1e7dddb5..38f40db29 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -520,18 +520,19 @@ public class KeychainIntentService extends IntentService } else { PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 90, 100)); try { - WrappedSecretKeyRing privkey = providerHelper.getWrappedSecretKeyRing(masterKeyId); + WrappedSecretKeyRing seckey = providerHelper.getWrappedSecretKeyRing(masterKeyId); WrappedPublicKeyRing pubkey = providerHelper.getWrappedPublicKeyRing(masterKeyId); PgpKeyOperation.Pair pair = - keyOperations.buildSecretKey(privkey, pubkey, saveParcel); // edit existing + keyOperations.buildSecretKey(seckey, pubkey, saveParcel); // edit existing setProgress(R.string.progress_saving_key_ring, 90, 100); providerHelper.saveKeyRing(pair.first, pair.second); } catch (ProviderHelper.NotFoundException e) { - UncachedKeyRing ring = keyOperations.buildNewSecretKey(saveParcel); //new Keyring + PgpKeyOperation.Pair pair = + keyOperations.buildNewSecretKey(saveParcel); //new Keyring // save the pair setProgress(R.string.progress_saving_key_ring, 90, 100); - providerHelper.savePublicKeyRing(ring); + providerHelper.saveKeyRing(pair.first, pair.second); } setProgress(R.string.progress_done, 100, 100); -- cgit v1.2.3 From 58edc0af674f273578a76febd9dfaad95e3380f9 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 31 May 2014 13:10:41 +0200 Subject: wrapped-key-ring: add documentation --- .../org/sufficientlysecure/keychain/pgp/KeyRing.java | 11 +++++++++++ .../keychain/pgp/UncachedKeyRing.java | 18 ++++++++++++++++++ .../keychain/pgp/WrappedKeyRing.java | 9 +++++++++ .../keychain/pgp/WrappedPublicKey.java | 17 ++++++++++------- .../keychain/pgp/WrappedSecretKey.java | 11 +++++++++++ .../keychain/pgp/WrappedSignature.java | 8 ++++++++ .../keychain/provider/CachedPublicKeyRing.java | 16 ++++++++++++++++ 7 files changed, 83 insertions(+), 7 deletions(-) (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java index cfbad89b7..dc0c722b9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java @@ -2,6 +2,17 @@ package org.sufficientlysecure.keychain.pgp; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +/** An abstract KeyRing. + * + * This is an abstract class for all KeyRing constructs. It serves as a common + * denominator of available information, two implementations wrapping the same + * keyring should in all cases agree on the output of all methods described + * here. + * + * @see org.sufficientlysecure.keychain.pgp.WrappedKeyRing + * @see org.sufficientlysecure.keychain.provider.CachedPublicKeyRing + * + */ public abstract class KeyRing { abstract public long getMasterKeyId() throws PgpGeneralException; 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 e17d07390..02e5411ca 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -23,6 +23,23 @@ import java.util.Iterator; import java.util.List; import java.util.Vector; +/** Wrapper around PGPKeyRing class, to be constructed from bytes. + * + * This class and its relatives UncachedPublicKey and UncachedSecretKey are + * used to move around pgp key rings in non crypto related (UI, mostly) code. + * It should be used for simple inspection only until it saved in the database, + * all actual crypto operations should work with WrappedKeyRings exclusively. + * + * This class is also special in that it can hold either the PGPPublicKeyRing + * or PGPSecretKeyRing derivate of the PGPKeyRing class, since these are + * treated equally for most purposes in UI code. It is up to the programmer to + * take care of the differences. + * + * @see org.sufficientlysecure.keychain.pgp.WrappedKeyRing + * @see org.sufficientlysecure.keychain.pgp.UncachedPublicKey + * @see org.sufficientlysecure.keychain.pgp.UncachedSecretKey + * + */ public class UncachedKeyRing { final PGPKeyRing mRing; @@ -62,6 +79,7 @@ public class UncachedKeyRing { }; } + /** Returns the dynamic (though final) property if this is a secret keyring or not. */ public boolean isSecret() { return mIsSecret; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java index 6e7b2a49e..2b6049894 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java @@ -8,6 +8,15 @@ import org.sufficientlysecure.keychain.util.IterableIterator; import java.io.IOException; import java.io.OutputStream; +/** A generic wrapped PGPKeyRing object. + * + * This class provides implementations for all basic getters which both + * PublicKeyRing and SecretKeyRing have in common. To make the wrapped keyring + * class typesafe in implementing subclasses, the field is stored in the + * implementing class, providing properly typed access through the getRing + * getter method. + * + */ public abstract class WrappedKeyRing extends KeyRing { private final boolean mHasAnySecret; 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 32c6910be..69a4fbdee 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedPublicKey.java @@ -1,16 +1,19 @@ package org.sufficientlysecure.keychain.pgp; -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPOnePassSignature; import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPSignature; -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; - +/** Wrapper for a PGPPublicKey. + * + * The methods implemented in this class are a thin layer over + * UncachedPublicKey. The difference between the two classes is that objects of + * this class can only be obtained from a WrappedKeyRing, and that it stores a + * back reference to its parent as well. A method which works with + * WrappedPublicKey is therefore guaranteed to work on a KeyRing which is + * stored in the database. + * + */ public class WrappedPublicKey extends UncachedPublicKey { // this is the parent key ring diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKey.java index a03e10098..ef8044a9b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKey.java @@ -26,6 +26,17 @@ import java.security.NoSuchProviderException; import java.security.SignatureException; import java.util.List; +/** Wrapper for a PGPSecretKey. + * + * This object can only be obtained from a WrappedSecretKeyRing, and stores a + * back reference to its parent. + * + * This class represents known secret keys which are stored in the database. + * All "crypto operations using a known secret key" should be implemented in + * this class, to ensure on type level that these operations are performed on + * properly imported secret keys only. + * + */ public class WrappedSecretKey extends WrappedPublicKey { private final PGPSecretKey mSecretKey; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java index 9f26439d2..1b7a5e8ba 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java @@ -17,6 +17,14 @@ import java.io.IOException; import java.security.SignatureException; import java.util.Date; +/** OpenKeychain wrapper around PGPSignature objects. + * + * This is a mostly simple wrapper around a single bouncycastle PGPSignature + * object. It exposes high level getters for all relevant information, methods + * for verification of various signatures (uid binding, subkey binding, generic + * bytes), and a static method for construction from bytes. + * + */ public class WrappedSignature { public static final int DEFAULT_CERTIFICATION = PGPSignature.DEFAULT_CERTIFICATION; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java index ed1988336..48d40430a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java @@ -7,6 +7,22 @@ import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.util.Log; +/** This implementation of KeyRing provides a cached view of PublicKeyRing + * objects based on database queries exclusively. + * + * This class should be used where only few points of data but no actual + * cryptographic operations are required about a PublicKeyRing which is already + * in the database. This happens commonly in UI code, where parsing of a PGP + * key for examination would be a very expensive operation. + * + * Each getter method is implemented using a more or less expensive database + * query, while object construction is (almost) free. A common pattern is + * mProviderHelper.getCachedKeyRing(uri).getterMethod() + * + * TODO Ensure that the values returned here always match the ones returned by + * the parsed KeyRing! + * + */ public class CachedPublicKeyRing extends KeyRing { final ProviderHelper mProviderHelper; -- cgit v1.2.3 From 6cb791d567e5205f2ca41e1afbc1015864841ec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 4 Jun 2014 10:21:28 +0200 Subject: Use fixed gradle versions --- OpenKeychain/build.gradle | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'OpenKeychain') diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle index 11dd7f21c..c30de8de7 100644 --- a/OpenKeychain/build.gradle +++ b/OpenKeychain/build.gradle @@ -10,6 +10,8 @@ sourceSets { } dependencies { + // NOTE: Always use version codes not dynamic ones, e.g. 0.7.3 instead of 0.7.+, see README for more information + compile 'com.android.support:support-v4:19.1.0' compile 'com.android.support:appcompat-v7:19.1.0' compile project(':extern:openpgp-api-lib') @@ -27,8 +29,8 @@ dependencies { // Dependencies for the `instrumentTest` task, make sure to list all your global dependencies here as well androidTestCompile 'junit:junit:4.10' - androidTestCompile 'org.robolectric:robolectric:2.1.+' - androidTestCompile 'com.squareup:fest-android:1.0.+' + androidTestCompile 'org.robolectric:robolectric:2.3' + androidTestCompile 'com.squareup:fest-android:1.0.8' androidTestCompile 'com.google.android:android:4.1.1.4' androidTestCompile 'com.android.support:support-v4:19.1.0' androidTestCompile 'com.android.support:appcompat-v7:19.1.0' -- cgit v1.2.3 From 52f1f30846ad7efa6e6ae11ed96f5b68626bfb3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 4 Jun 2014 10:22:05 +0200 Subject: Use fixed gradle versions --- OpenKeychain/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain') diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle index c30de8de7..c8ef7b418 100644 --- a/OpenKeychain/build.gradle +++ b/OpenKeychain/build.gradle @@ -10,7 +10,7 @@ sourceSets { } dependencies { - // NOTE: Always use version codes not dynamic ones, e.g. 0.7.3 instead of 0.7.+, see README for more information + // NOTE: Always use fixed version codes not dynamic ones, e.g. 0.7.3 instead of 0.7.+, see README for more information compile 'com.android.support:support-v4:19.1.0' compile 'com.android.support:appcompat-v7:19.1.0' -- cgit v1.2.3