wrapped-key-ring: UncachedKeyRing wraps only one ring of dynamic type

This commit is contained in:
Vincent Breitmoser
2014-05-23 16:44:50 +02:00
parent cd0aba9d43
commit 10ad7be46b
8 changed files with 125 additions and 100 deletions

View File

@@ -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);

View File

@@ -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<UncachedKeyRing, UncachedKeyRing> 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<UncachedKeyRing,UncachedKeyRing>(new UncachedKeyRing(pKR),
new UncachedKeyRing(mKR));
}

View File

@@ -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<UncachedKeyRing> fromStream(InputStream stream)
throws PgpGeneralException, IOException {
PGPObjectFactory objectFactory = new PGPObjectFactory(PGPUtil.getDecoderStream(stream));
List<UncachedKeyRing> result = new Vector<UncachedKeyRing>();
// 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;
}
}

View File

@@ -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<String> userIds = new ArrayList<String>();
for (String userId : new IterableIterator<String>(mPublicKey.getUserIDs())) {
userIds.add(userId);
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 boolean isElGamalEncrypt() {
return getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT;
}

View File

@@ -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);
}
}
}