mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-05 08:45:08 -05:00
parent
6f558add35
commit
ebcd243e97
@ -52,6 +52,7 @@ import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType;
|
|||||||
import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog;
|
import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog;
|
||||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
|
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
|
||||||
|
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
import org.sufficientlysecure.keychain.util.Primes;
|
import org.sufficientlysecure.keychain.util.Primes;
|
||||||
|
|
||||||
@ -66,6 +67,7 @@ import java.security.SignatureException;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -289,14 +291,42 @@ public class PgpKeyOperation {
|
|||||||
// 2a. Add certificates for new user ids
|
// 2a. Add certificates for new user ids
|
||||||
for (String userId : saveParcel.addUserIds) {
|
for (String userId : saveParcel.addUserIds) {
|
||||||
log.add(LogLevel.INFO, LogType.MSG_MF_UID_ADD, indent);
|
log.add(LogLevel.INFO, LogType.MSG_MF_UID_ADD, indent);
|
||||||
|
|
||||||
|
// this operation supersedes all previous binding and revocation certificates,
|
||||||
|
// so remove those to retain assertions from canonicalization for later operations
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Iterator<PGPSignature> it = modifiedPublicKey.getSignaturesForID(userId);
|
||||||
|
if (it != null) {
|
||||||
|
for (PGPSignature cert : new IterableIterator<PGPSignature>(it)) {
|
||||||
|
// if it's not a self cert, never mind
|
||||||
|
if (cert.getKeyID() != masterPublicKey.getKeyID()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION
|
||||||
|
|| cert.getSignatureType() == PGPSignature.NO_CERTIFICATION
|
||||||
|
|| cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION
|
||||||
|
|| cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION
|
||||||
|
|| cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) {
|
||||||
|
modifiedPublicKey = PGPPublicKey.removeCertification(
|
||||||
|
modifiedPublicKey, userId, cert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's supposed to be primary, we can do that here as well
|
||||||
|
boolean isPrimary = saveParcel.changePrimaryUserId != null
|
||||||
|
&& userId.equals(saveParcel.changePrimaryUserId);
|
||||||
|
// generate and add new certificate
|
||||||
PGPSignature cert = generateUserIdSignature(masterPrivateKey,
|
PGPSignature cert = generateUserIdSignature(masterPrivateKey,
|
||||||
masterPublicKey, userId, false);
|
masterPublicKey, userId, isPrimary);
|
||||||
modifiedPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, cert);
|
modifiedPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2b. Add revocations for revoked user ids
|
// 2b. Add revocations for revoked user ids
|
||||||
for (String userId : saveParcel.revokeUserIds) {
|
for (String userId : saveParcel.revokeUserIds) {
|
||||||
log.add(LogLevel.INFO, LogType.MSG_MF_UID_REVOKE, indent);
|
log.add(LogLevel.INFO, LogType.MSG_MF_UID_REVOKE, indent);
|
||||||
|
// a duplicate revocatin will be removed during canonicalization, so no need to
|
||||||
|
// take care of that here.
|
||||||
PGPSignature cert = generateRevocationSignature(masterPrivateKey,
|
PGPSignature cert = generateRevocationSignature(masterPrivateKey,
|
||||||
masterPublicKey, userId);
|
masterPublicKey, userId);
|
||||||
modifiedPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, cert);
|
modifiedPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, cert);
|
||||||
@ -305,7 +335,84 @@ public class PgpKeyOperation {
|
|||||||
// 3. If primary user id changed, generate new certificates for both old and new
|
// 3. If primary user id changed, generate new certificates for both old and new
|
||||||
if (saveParcel.changePrimaryUserId != null) {
|
if (saveParcel.changePrimaryUserId != null) {
|
||||||
log.add(LogLevel.INFO, LogType.MSG_MF_UID_PRIMARY, indent);
|
log.add(LogLevel.INFO, LogType.MSG_MF_UID_PRIMARY, indent);
|
||||||
// todo
|
|
||||||
|
// we work on the modifiedPublicKey here, to respect new or newly revoked uids
|
||||||
|
// noinspection unchecked
|
||||||
|
for (String userId : new IterableIterator<String>(modifiedPublicKey.getUserIDs())) {
|
||||||
|
boolean isRevoked = false;
|
||||||
|
PGPSignature currentCert = null;
|
||||||
|
// noinspection unchecked
|
||||||
|
for (PGPSignature cert : new IterableIterator<PGPSignature>(
|
||||||
|
masterPublicKey.getSignaturesForID(userId))) {
|
||||||
|
// if it's not a self cert, never mind
|
||||||
|
if (cert.getKeyID() != masterPublicKey.getKeyID()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// we know from canonicalization that if there is any revocation here, it
|
||||||
|
// is valid and not superseded by a newer certification.
|
||||||
|
if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION) {
|
||||||
|
isRevoked = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// we know from canonicalization that there is only one binding
|
||||||
|
// certification here, so we can just work with the first one.
|
||||||
|
if (cert.getSignatureType() == PGPSignature.NO_CERTIFICATION ||
|
||||||
|
cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION ||
|
||||||
|
cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION ||
|
||||||
|
cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) {
|
||||||
|
currentCert = cert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentCert == null) {
|
||||||
|
// no certificate found?! error error error
|
||||||
|
log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_INTEGRITY, indent);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we definitely should not update certifications of revoked keys, so just leave it.
|
||||||
|
if (isRevoked) {
|
||||||
|
// revoked user ids cannot be primary!
|
||||||
|
if (userId.equals(saveParcel.changePrimaryUserId)) {
|
||||||
|
log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_REVOKED_PRIMARY, indent);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this is~ the/a primary user id
|
||||||
|
if (currentCert.hasSubpackets() && currentCert.getHashedSubPackets().isPrimaryUserID()) {
|
||||||
|
// if it's the one we want, just leave it as is
|
||||||
|
if (userId.equals(saveParcel.changePrimaryUserId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// otherwise, generate new non-primary certification
|
||||||
|
modifiedPublicKey = PGPPublicKey.removeCertification(
|
||||||
|
modifiedPublicKey, userId, currentCert);
|
||||||
|
PGPSignature newCert = generateUserIdSignature(
|
||||||
|
masterPrivateKey, masterPublicKey, userId, false);
|
||||||
|
modifiedPublicKey = PGPPublicKey.addCertification(
|
||||||
|
modifiedPublicKey, userId, newCert);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we are here, this is not currently a primary user id
|
||||||
|
|
||||||
|
// if it should be
|
||||||
|
if (userId.equals(saveParcel.changePrimaryUserId)) {
|
||||||
|
// add shiny new primary user id certificate
|
||||||
|
modifiedPublicKey = PGPPublicKey.removeCertification(
|
||||||
|
modifiedPublicKey, userId, currentCert);
|
||||||
|
PGPSignature newCert = generateUserIdSignature(
|
||||||
|
masterPrivateKey, masterPublicKey, userId, true);
|
||||||
|
modifiedPublicKey = PGPPublicKey.addCertification(
|
||||||
|
modifiedPublicKey, userId, newCert);
|
||||||
|
}
|
||||||
|
|
||||||
|
// user id is not primary and is not supposed to be - nothing to do here.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the secret key ring
|
// Update the secret key ring
|
||||||
@ -315,7 +422,6 @@ public class PgpKeyOperation {
|
|||||||
sKR = PGPSecretKeyRing.insertSecretKey(sKR, masterSecretKey);
|
sKR = PGPSecretKeyRing.insertSecretKey(sKR, masterSecretKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 4a. For each subkey change, generate new subkey binding certificate
|
// 4a. For each subkey change, generate new subkey binding certificate
|
||||||
for (SaveKeyringParcel.SubkeyChange change : saveParcel.changeSubKeys) {
|
for (SaveKeyringParcel.SubkeyChange change : saveParcel.changeSubKeys) {
|
||||||
log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_CHANGE,
|
log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_CHANGE,
|
||||||
@ -334,7 +440,8 @@ public class PgpKeyOperation {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate and add new signature
|
// generate and add new signature. we can be sloppy here and just leave the old one,
|
||||||
|
// it will be removed during canonicalization
|
||||||
PGPSignature sig = generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey,
|
PGPSignature sig = generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey,
|
||||||
sKey, pKey, change.mFlags, change.mExpiry, passphrase);
|
sKey, pKey, change.mFlags, change.mExpiry, passphrase);
|
||||||
pKey = PGPPublicKey.addCertification(pKey, sig);
|
pKey = PGPPublicKey.addCertification(pKey, sig);
|
||||||
|
@ -241,6 +241,8 @@ public class OperationResultParcel implements Parcelable {
|
|||||||
MSG_MF_ERROR_ENCODE (R.string.msg_mf_error_encode),
|
MSG_MF_ERROR_ENCODE (R.string.msg_mf_error_encode),
|
||||||
MSG_MF_ERROR_FINGERPRINT (R.string.msg_mf_error_fingerprint),
|
MSG_MF_ERROR_FINGERPRINT (R.string.msg_mf_error_fingerprint),
|
||||||
MSG_MF_ERROR_KEYID (R.string.msg_mf_error_keyid),
|
MSG_MF_ERROR_KEYID (R.string.msg_mf_error_keyid),
|
||||||
|
MSG_MF_ERROR_INTEGRITY (R.string.msg_mf_error_integrity),
|
||||||
|
MSG_MF_ERROR_REVOKED_PRIMARY (R.string.msg_mf_error_revoked_primary),
|
||||||
MSG_MF_ERROR_PGP (R.string.msg_mf_error_pgp),
|
MSG_MF_ERROR_PGP (R.string.msg_mf_error_pgp),
|
||||||
MSG_MF_ERROR_SIG (R.string.msg_mf_error_sig),
|
MSG_MF_ERROR_SIG (R.string.msg_mf_error_sig),
|
||||||
MSG_MF_PASSPHRASE (R.string.msg_mf_passphrase),
|
MSG_MF_PASSPHRASE (R.string.msg_mf_passphrase),
|
||||||
|
@ -628,6 +628,8 @@
|
|||||||
<string name="msg_mf_error_encode">Encoding exception!</string>
|
<string name="msg_mf_error_encode">Encoding exception!</string>
|
||||||
<string name="msg_mf_error_fingerprint">Actual key fingerprint does not match expected!</string>
|
<string name="msg_mf_error_fingerprint">Actual key fingerprint does not match expected!</string>
|
||||||
<string name="msg_mf_error_keyid">No keyid. This is a programming error, please file a bug report!</string>
|
<string name="msg_mf_error_keyid">No keyid. This is a programming error, please file a bug report!</string>
|
||||||
|
<string name="msg_mf_error_integrity">Internal error, integrity check failed!</string>
|
||||||
|
<string name="msg_mf_error_revoked_primary">Revoked user ids cannot be primary!</string>
|
||||||
<string name="msg_mf_error_pgp">PGP internal exception!</string>
|
<string name="msg_mf_error_pgp">PGP internal exception!</string>
|
||||||
<string name="msg_mf_error_sig">Signature exception!</string>
|
<string name="msg_mf_error_sig">Signature exception!</string>
|
||||||
<string name="msg_mf_passphrase">Changing passphrase</string>
|
<string name="msg_mf_passphrase">Changing passphrase</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user