mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-12-25 00:18:51 -05:00
wrapped-key-ring: move more helper methods into keys
This commit is contained in:
parent
1f8210f743
commit
2176e1ef1c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user