aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java197
1 files changed, 197 insertions, 0 deletions
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..e3db03bf6
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java
@@ -0,0 +1,197 @@
+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.Iterator;
+import java.util.List;
+
+public class UncachedPublicKey {
+ protected final PGPPublicKey mPublicKey;
+ private Integer mCacheUsage = null;
+
+ public UncachedPublicKey(PGPPublicKey key) {
+ mPublicKey = key;
+ }
+
+ public long getKeyId() {
+ return mPublicKey.getKeyID();
+ }
+
+ /** The revocation signature is NOT checked here, so this may be false! */
+ public boolean maybeRevoked() {
+ 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 int getBitStrength() {
+ return mPublicKey.getBitStrength();
+ }
+
+ public String getPrimaryUserId() {
+ for (String userId : new IterableIterator<String>(mPublicKey.getUserIDs())) {
+ for (PGPSignature sig : new IterableIterator<PGPSignature>(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 ArrayList<String> getUnorderedUserIds() {
+ ArrayList<String> userIds = new ArrayList<String>();
+ for (String userId : new IterableIterator<String>(mPublicKey.getUserIDs())) {
+ userIds.add(userId);
+ }
+ return userIds;
+ }
+
+ 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<PGPSignature>(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();
+ }
+
+ // 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<WrappedSignature> getSignaturesForId(String userId) {
+ final Iterator<PGPSignature> it = mPublicKey.getSignaturesForID(userId);
+ return new Iterator<WrappedSignature>() {
+ public void remove() {
+ it.remove();
+ }
+ public WrappedSignature next() {
+ return new WrappedSignature(it.next());
+ }
+ public boolean hasNext() {
+ return it.hasNext();
+ }
+ };
+ }
+}