mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-27 19:22:14 -05:00
wrapped-key-ring: introduce Uncached*Key objects
This commit is contained in:
parent
411b4cfeb2
commit
8cf0638f54
@ -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<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;
|
||||
return new IterableIterator<String>(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;
|
||||
}
|
||||
}
|
||||
|
@ -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())) {
|
||||
|
@ -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<String>(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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<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();
|
||||
}
|
||||
|
||||
// Note that this method has package visibility - no access outside the pgp package!
|
||||
PGPPublicKey getPublicKey() {
|
||||
return mPublicKey;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user