mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-12-24 07:58:50 -05:00
Get certificates by raw user ids, be more liberal about accepted user id encodings
This commit is contained in:
parent
974dc47d69
commit
9e37522bdd
@ -59,6 +59,10 @@ public abstract class CanonicalizedKeyRing extends KeyRing {
|
||||
return getPublicKey().getPrimaryUserIdWithFallback();
|
||||
}
|
||||
|
||||
public ArrayList<byte[]> getUnorderedRawUserIds() {
|
||||
return getPublicKey().getUnorderedRawUserIds();
|
||||
}
|
||||
|
||||
public ArrayList<String> getUnorderedUserIds() {
|
||||
return getPublicKey().getUnorderedUserIds();
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import org.spongycastle.openpgp.PGPSignature;
|
||||
import org.spongycastle.openpgp.PGPSignatureList;
|
||||
import org.spongycastle.openpgp.PGPUtil;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
|
||||
import org.spongycastle.util.Strings;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.service.results.OperationResultParcel.LogLevel;
|
||||
@ -361,23 +362,25 @@ public class UncachedKeyRing {
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<String> processedUserIds = new ArrayList<String>();
|
||||
for (String userId : new IterableIterator<String>(masterKey.getUserIDs())) {
|
||||
ArrayList<byte[]> processedUserIds = new ArrayList<byte[]>();
|
||||
for (byte[] rawUserId : new IterableIterator<byte[]>(masterKey.getRawUserIDs())) {
|
||||
String userId = Strings.fromUTF8ByteArray(rawUserId);
|
||||
|
||||
// check for duplicate user ids
|
||||
if (processedUserIds.contains(userId)) {
|
||||
if (processedUserIds.contains(rawUserId)) {
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_UID_DUP,
|
||||
indent, userId);
|
||||
// strip out the first found user id with this name
|
||||
modified = PGPPublicKey.removeCertification(modified, userId);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId);
|
||||
}
|
||||
processedUserIds.add(userId);
|
||||
processedUserIds.add(rawUserId);
|
||||
|
||||
PGPSignature selfCert = null;
|
||||
revocation = null;
|
||||
|
||||
// look through signatures for this specific user id
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<PGPSignature> signaturesIt = masterKey.getSignaturesForID(userId);
|
||||
Iterator<PGPSignature> signaturesIt = masterKey.getSignaturesForID(rawUserId);
|
||||
if (signaturesIt != null) {
|
||||
for (PGPSignature zert : new IterableIterator<PGPSignature>(signaturesIt)) {
|
||||
WrappedSignature cert = new WrappedSignature(zert);
|
||||
@ -391,7 +394,7 @@ public class UncachedKeyRing {
|
||||
&& type != PGPSignature.CERTIFICATION_REVOCATION) {
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_UID_BAD_TYPE,
|
||||
indent, "0x" + Integer.toString(zert.getSignatureType(), 16));
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, zert);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId, zert);
|
||||
badCerts += 1;
|
||||
continue;
|
||||
}
|
||||
@ -399,7 +402,7 @@ public class UncachedKeyRing {
|
||||
if (cert.getCreationTime().after(now)) {
|
||||
// Creation date in the future? No way!
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_UID_BAD_TIME, indent);
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, zert);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId, zert);
|
||||
badCerts += 1;
|
||||
continue;
|
||||
}
|
||||
@ -407,7 +410,7 @@ public class UncachedKeyRing {
|
||||
if (cert.isLocal()) {
|
||||
// Creation date in the future? No way!
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_UID_BAD_LOCAL, indent);
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, zert);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId, zert);
|
||||
badCerts += 1;
|
||||
continue;
|
||||
}
|
||||
@ -418,7 +421,7 @@ public class UncachedKeyRing {
|
||||
if (isSecret()) {
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_UID_FOREIGN,
|
||||
indent, PgpKeyHelper.convertKeyIdToHex(certId));
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, zert);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId, zert);
|
||||
badCerts += 1;
|
||||
}
|
||||
continue;
|
||||
@ -427,17 +430,17 @@ public class UncachedKeyRing {
|
||||
// Otherwise, first make sure it checks out
|
||||
try {
|
||||
cert.init(masterKey);
|
||||
if (!cert.verifySignature(masterKey, userId)) {
|
||||
if (!cert.verifySignature(masterKey, rawUserId)) {
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_UID_BAD,
|
||||
indent, userId);
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, zert);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId, zert);
|
||||
badCerts += 1;
|
||||
continue;
|
||||
}
|
||||
} catch (PgpGeneralException e) {
|
||||
log.add(LogLevel.WARN, LogType.MSG_KC_UID_BAD_ERR,
|
||||
indent, userId);
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, zert);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId, zert);
|
||||
badCerts += 1;
|
||||
continue;
|
||||
}
|
||||
@ -452,13 +455,13 @@ public class UncachedKeyRing {
|
||||
} else if (selfCert.getCreationTime().before(cert.getCreationTime())) {
|
||||
log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_CERT_DUP,
|
||||
indent, userId);
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, selfCert);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId, selfCert);
|
||||
redundantCerts += 1;
|
||||
selfCert = zert;
|
||||
} else {
|
||||
log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_CERT_DUP,
|
||||
indent, userId);
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, zert);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId, zert);
|
||||
redundantCerts += 1;
|
||||
}
|
||||
// If there is a revocation certificate, and it's older than this, drop it
|
||||
@ -466,7 +469,7 @@ public class UncachedKeyRing {
|
||||
&& revocation.getCreationTime().before(selfCert.getCreationTime())) {
|
||||
log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_REVOKE_OLD,
|
||||
indent, userId);
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, revocation);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId, revocation);
|
||||
revocation = null;
|
||||
redundantCerts += 1;
|
||||
}
|
||||
@ -477,7 +480,7 @@ public class UncachedKeyRing {
|
||||
if (selfCert != null && selfCert.getCreationTime().after(zert.getCreationTime())) {
|
||||
log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_REVOKE_OLD,
|
||||
indent, userId);
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, zert);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId, zert);
|
||||
redundantCerts += 1;
|
||||
continue;
|
||||
}
|
||||
@ -488,13 +491,13 @@ public class UncachedKeyRing {
|
||||
} else if (revocation.getCreationTime().before(cert.getCreationTime())) {
|
||||
log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_REVOKE_DUP,
|
||||
indent, userId);
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, revocation);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId, revocation);
|
||||
redundantCerts += 1;
|
||||
revocation = zert;
|
||||
} else {
|
||||
log.add(LogLevel.DEBUG, LogType.MSG_KC_UID_REVOKE_DUP,
|
||||
indent, userId);
|
||||
modified = PGPPublicKey.removeCertification(modified, userId, zert);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId, zert);
|
||||
redundantCerts += 1;
|
||||
}
|
||||
break;
|
||||
@ -506,7 +509,7 @@ public class UncachedKeyRing {
|
||||
if (selfCert == null && revocation == null) {
|
||||
log.add(LogLevel.ERROR, LogType.MSG_KC_UID_REMOVE,
|
||||
indent, userId);
|
||||
modified = PGPPublicKey.removeCertification(modified, userId);
|
||||
modified = PGPPublicKey.removeCertification(modified, rawUserId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -817,9 +820,9 @@ public class UncachedKeyRing {
|
||||
}
|
||||
|
||||
// Copy over all user id certificates
|
||||
for (String userId : new IterableIterator<String>(key.getUserIDs())) {
|
||||
for (byte[] rawUserId : new IterableIterator<byte[]>(key.getRawUserIDs())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<PGPSignature> signaturesIt = key.getSignaturesForID(userId);
|
||||
Iterator<PGPSignature> signaturesIt = key.getSignaturesForID(rawUserId);
|
||||
// no signatures for this User ID, skip it
|
||||
if (signaturesIt == null) {
|
||||
continue;
|
||||
@ -836,7 +839,7 @@ public class UncachedKeyRing {
|
||||
}
|
||||
newCerts += 1;
|
||||
certs.add(encoded);
|
||||
modified = PGPPublicKey.addCertification(modified, userId, cert);
|
||||
modified = PGPPublicKey.addCertification(modified, rawUserId, cert);
|
||||
}
|
||||
}
|
||||
// If anything changed, save the updated (sub)key
|
||||
|
@ -28,11 +28,13 @@ 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.util.Strings;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
@ -126,14 +128,14 @@ public class UncachedPublicKey {
|
||||
*
|
||||
*/
|
||||
public String getPrimaryUserId() {
|
||||
String found = null;
|
||||
byte[] found = null;
|
||||
PGPSignature foundSig = null;
|
||||
// noinspection unchecked
|
||||
for (String userId : new IterableIterator<String>(mPublicKey.getUserIDs())) {
|
||||
for (byte[] rawUserId : new IterableIterator<byte[]>(mPublicKey.getRawUserIDs())) {
|
||||
PGPSignature revocation = null;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<PGPSignature> signaturesIt = mPublicKey.getSignaturesForID(userId);
|
||||
Iterator<PGPSignature> signaturesIt = mPublicKey.getSignaturesForID(rawUserId);
|
||||
// no signatures for this User ID
|
||||
if (signaturesIt == null) {
|
||||
continue;
|
||||
@ -147,10 +149,10 @@ public class UncachedPublicKey {
|
||||
// make sure it's actually valid
|
||||
sig.init(new JcaPGPContentVerifierBuilderProvider().setProvider(
|
||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME), mPublicKey);
|
||||
if (!sig.verifyCertification(userId, mPublicKey)) {
|
||||
if (!sig.verifyCertification(rawUserId, mPublicKey)) {
|
||||
continue;
|
||||
}
|
||||
if (found != null && found.equals(userId)) {
|
||||
if (found != null && Arrays.equals(found, rawUserId)) {
|
||||
found = null;
|
||||
}
|
||||
revocation = sig;
|
||||
@ -169,8 +171,8 @@ public class UncachedPublicKey {
|
||||
// make sure it's actually valid
|
||||
sig.init(new JcaPGPContentVerifierBuilderProvider().setProvider(
|
||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME), mPublicKey);
|
||||
if (sig.verifyCertification(userId, mPublicKey)) {
|
||||
found = userId;
|
||||
if (sig.verifyCertification(rawUserId, mPublicKey)) {
|
||||
found = rawUserId;
|
||||
foundSig = sig;
|
||||
// this one can't be relevant anymore at this point
|
||||
revocation = null;
|
||||
@ -182,7 +184,11 @@ public class UncachedPublicKey {
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
if (found != null) {
|
||||
return Strings.fromUTF8ByteArray(found);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -204,6 +210,14 @@ public class UncachedPublicKey {
|
||||
return userIds;
|
||||
}
|
||||
|
||||
public ArrayList<byte[]> getUnorderedRawUserIds() {
|
||||
ArrayList<byte[]> userIds = new ArrayList<byte[]>();
|
||||
for (byte[] userId : new IterableIterator<byte[]>(mPublicKey.getRawUserIDs())) {
|
||||
userIds.add(userId);
|
||||
}
|
||||
return userIds;
|
||||
}
|
||||
|
||||
public boolean isElGamalEncrypt() {
|
||||
return getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT;
|
||||
}
|
||||
@ -320,8 +334,8 @@ public class UncachedPublicKey {
|
||||
};
|
||||
}
|
||||
|
||||
public Iterator<WrappedSignature> getSignaturesForId(String userId) {
|
||||
final Iterator<PGPSignature> it = mPublicKey.getSignaturesForID(userId);
|
||||
public Iterator<WrappedSignature> getSignaturesForRawId(byte[] rawUserId) {
|
||||
final Iterator<PGPSignature> it = mPublicKey.getSignaturesForID(rawUserId);
|
||||
if (it != null) {
|
||||
return new Iterator<WrappedSignature>() {
|
||||
public void remove() {
|
||||
|
@ -187,8 +187,16 @@ public class WrappedSignature {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean verifySignature(UncachedPublicKey key, String uid) throws PgpGeneralException {
|
||||
return verifySignature(key.getPublicKey(), uid);
|
||||
boolean verifySignature(PGPPublicKey key, byte[] rawUserId) throws PgpGeneralException {
|
||||
try {
|
||||
return mSig.verifyCertification(rawUserId, key);
|
||||
} catch (PGPException e) {
|
||||
throw new PgpGeneralException("Error!", e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean verifySignature(UncachedPublicKey key, byte[] rawUserId) throws PgpGeneralException {
|
||||
return verifySignature(key.getPublicKey(), rawUserId);
|
||||
}
|
||||
public boolean verifySignature(CanonicalizedPublicKey key, String uid) throws PgpGeneralException {
|
||||
return verifySignature(key.getPublicKey(), uid);
|
||||
|
@ -28,6 +28,7 @@ import android.net.Uri;
|
||||
import android.os.RemoteException;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
|
||||
import org.spongycastle.util.Strings;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
@ -434,8 +435,11 @@ public class ProviderHelper {
|
||||
}
|
||||
mIndent += 1;
|
||||
List<UserIdItem> uids = new ArrayList<UserIdItem>();
|
||||
for (String userId : new IterableIterator<String>(
|
||||
masterKey.getUnorderedUserIds().iterator())) {
|
||||
for (byte[] rawUserId : new IterableIterator<byte[]>(
|
||||
masterKey.getUnorderedRawUserIds().iterator())) {
|
||||
String userId = Strings.fromUTF8ByteArray(rawUserId);
|
||||
Log.d(Constants.TAG, "userId: "+userId);
|
||||
|
||||
UserIdItem item = new UserIdItem();
|
||||
uids.add(item);
|
||||
item.userId = userId;
|
||||
@ -446,7 +450,7 @@ public class ProviderHelper {
|
||||
mIndent += 1;
|
||||
// look through signatures for this specific key
|
||||
for (WrappedSignature cert : new IterableIterator<WrappedSignature>(
|
||||
masterKey.getSignaturesForId(userId))) {
|
||||
masterKey.getSignaturesForRawId(rawUserId))) {
|
||||
long certId = cert.getKeyId();
|
||||
try {
|
||||
// self signature
|
||||
@ -469,7 +473,7 @@ public class ProviderHelper {
|
||||
if (trustedKeys.indexOfKey(certId) >= 0) {
|
||||
CanonicalizedPublicKey trustedKey = trustedKeys.get(certId);
|
||||
cert.init(trustedKey);
|
||||
if (cert.verifySignature(masterKey, userId)) {
|
||||
if (cert.verifySignature(masterKey, rawUserId)) {
|
||||
item.trustedCerts.add(cert);
|
||||
log(LogLevel.INFO, LogType.MSG_IP_UID_CERT_GOOD,
|
||||
PgpKeyHelper.convertKeyIdToHexShort(trustedKey.getKeyId())
|
||||
|
Loading…
Reference in New Issue
Block a user