aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedPublicKey.java108
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java22
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKeyRing.java35
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java2
5 files changed, 153 insertions, 15 deletions
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<String> getUserIds() {
+ return new IterableIterator<String>(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<PGPSignature>(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<CachedSecretKey> iterator() {
+ return new IterableIterator<CachedSecretKey>(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<PGPSecretKey> 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 {