mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-27 11:12:15 -05:00
add support for certification of user attributes
This commit is contained in:
parent
443feef27a
commit
30ca8637ff
@ -101,18 +101,26 @@ public class CertifyOperation extends BaseOperation {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.mUserIds == null) {
|
|
||||||
log.add(LogType.MSG_CRT_CERTIFY_ALL, 2,
|
|
||||||
KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
|
|
||||||
} else {
|
|
||||||
log.add(LogType.MSG_CRT_CERTIFY_SOME, 2, action.mUserIds.size(),
|
|
||||||
KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
|
|
||||||
}
|
|
||||||
|
|
||||||
CanonicalizedPublicKeyRing publicRing =
|
CanonicalizedPublicKeyRing publicRing =
|
||||||
mProviderHelper.getCanonicalizedPublicKeyRing(action.mMasterKeyId);
|
mProviderHelper.getCanonicalizedPublicKeyRing(action.mMasterKeyId);
|
||||||
|
|
||||||
UncachedKeyRing certifiedKey = certificationKey.certifyUserIds(publicRing, action.mUserIds, null, null);
|
UncachedKeyRing certifiedKey = null;
|
||||||
|
if (action.mUserIds != null) {
|
||||||
|
log.add(LogType.MSG_CRT_CERTIFY_UIDS, 2, action.mUserIds.size(),
|
||||||
|
KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
|
||||||
|
|
||||||
|
certifiedKey = certificationKey.certifyUserIds(
|
||||||
|
publicRing, action.mUserIds, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.mUserAttributes != null) {
|
||||||
|
log.add(LogType.MSG_CRT_CERTIFY_UATS, 2, action.mUserAttributes.size(),
|
||||||
|
KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
|
||||||
|
|
||||||
|
certifiedKey = certificationKey.certifyUserAttributes(
|
||||||
|
publicRing, action.mUserAttributes, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
if (certifiedKey == null) {
|
if (certifiedKey == null) {
|
||||||
certifyError += 1;
|
certifyError += 1;
|
||||||
log.add(LogType.MSG_CRT_WARN_CERT_FAILED, 3);
|
log.add(LogType.MSG_CRT_WARN_CERT_FAILED, 3);
|
||||||
|
@ -691,8 +691,8 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_PSE_SYMMETRIC (LogLevel.INFO, R.string.msg_pse_symmetric),
|
MSG_PSE_SYMMETRIC (LogLevel.INFO, R.string.msg_pse_symmetric),
|
||||||
|
|
||||||
MSG_CRT_CERTIFYING (LogLevel.DEBUG, R.string.msg_crt_certifying),
|
MSG_CRT_CERTIFYING (LogLevel.DEBUG, R.string.msg_crt_certifying),
|
||||||
MSG_CRT_CERTIFY_ALL (LogLevel.DEBUG, R.string.msg_crt_certify_all),
|
MSG_CRT_CERTIFY_UIDS (LogLevel.DEBUG, R.plurals.msg_crt_certify_uids),
|
||||||
MSG_CRT_CERTIFY_SOME (LogLevel.DEBUG, R.plurals.msg_crt_certify_some),
|
MSG_CRT_CERTIFY_UATS (LogLevel.DEBUG, R.plurals.msg_crt_certify_uats),
|
||||||
MSG_CRT_ERROR_SELF (LogLevel.ERROR, R.string.msg_crt_error_self),
|
MSG_CRT_ERROR_SELF (LogLevel.ERROR, R.string.msg_crt_error_self),
|
||||||
MSG_CRT_ERROR_MASTER_NOT_FOUND (LogLevel.ERROR, R.string.msg_crt_error_master_not_found),
|
MSG_CRT_ERROR_MASTER_NOT_FOUND (LogLevel.ERROR, R.string.msg_crt_error_master_not_found),
|
||||||
MSG_CRT_ERROR_NOTHING (LogLevel.ERROR, R.string.msg_crt_error_nothing),
|
MSG_CRT_ERROR_NOTHING (LogLevel.ERROR, R.string.msg_crt_error_nothing),
|
||||||
|
@ -30,6 +30,7 @@ import org.spongycastle.openpgp.PGPSignature;
|
|||||||
import org.spongycastle.openpgp.PGPSignatureGenerator;
|
import org.spongycastle.openpgp.PGPSignatureGenerator;
|
||||||
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
|
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||||
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
|
import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector;
|
||||||
import org.spongycastle.openpgp.PGPUtil;
|
import org.spongycastle.openpgp.PGPUtil;
|
||||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||||
import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
|
import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
|
||||||
@ -268,7 +269,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
|||||||
* Certify the given pubkeyid with the given masterkeyid.
|
* Certify the given pubkeyid with the given masterkeyid.
|
||||||
*
|
*
|
||||||
* @param publicKeyRing Keyring to add certification to.
|
* @param publicKeyRing Keyring to add certification to.
|
||||||
* @param userIds User IDs to certify, or all if null
|
* @param userIds User IDs to certify
|
||||||
* @return A keyring with added certifications
|
* @return A keyring with added certifications
|
||||||
*/
|
*/
|
||||||
public UncachedKeyRing certifyUserIds(CanonicalizedPublicKeyRing publicKeyRing, List<String> userIds,
|
public UncachedKeyRing certifyUserIds(CanonicalizedPublicKeyRing publicKeyRing, List<String> userIds,
|
||||||
@ -313,10 +314,8 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
|||||||
PGPPublicKey publicKey = publicKeyRing.getPublicKey().getPublicKey();
|
PGPPublicKey publicKey = publicKeyRing.getPublicKey().getPublicKey();
|
||||||
|
|
||||||
// fetch public key ring, add the certification and return it
|
// fetch public key ring, add the certification and return it
|
||||||
Iterable<String> it = userIds != null ? userIds
|
|
||||||
: new IterableIterator<String>(publicKey.getUserIDs());
|
|
||||||
try {
|
try {
|
||||||
for (String userId : it) {
|
for (String userId : userIds) {
|
||||||
PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey);
|
PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey);
|
||||||
publicKey = PGPPublicKey.addCertification(publicKey, userId, sig);
|
publicKey = PGPPublicKey.addCertification(publicKey, userId, sig);
|
||||||
}
|
}
|
||||||
@ -330,6 +329,71 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
|||||||
return new UncachedKeyRing(ring);
|
return new UncachedKeyRing(ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Certify the given user attributes with the given masterkeyid.
|
||||||
|
*
|
||||||
|
* @param publicKeyRing Keyring to add certification to.
|
||||||
|
* @param userAttributes User IDs to certify, or all if null
|
||||||
|
* @return A keyring with added certifications
|
||||||
|
*/
|
||||||
|
public UncachedKeyRing certifyUserAttributes(CanonicalizedPublicKeyRing publicKeyRing,
|
||||||
|
List<WrappedUserAttribute> userAttributes, byte[] nfcSignedHash, Date nfcCreationTimestamp) {
|
||||||
|
if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) {
|
||||||
|
throw new PrivateKeyNotUnlockedException();
|
||||||
|
}
|
||||||
|
if (!isMasterKey()) {
|
||||||
|
throw new AssertionError("tried to certify with non-master key, this is a programming error!");
|
||||||
|
}
|
||||||
|
if (publicKeyRing.getMasterKeyId() == getKeyId()) {
|
||||||
|
throw new AssertionError("key tried to self-certify, this is a programming error!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a signatureGenerator from the supplied masterKeyId and passphrase
|
||||||
|
PGPSignatureGenerator signatureGenerator;
|
||||||
|
{
|
||||||
|
// TODO: SHA256 fixed?
|
||||||
|
PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(PGPUtil.SHA256,
|
||||||
|
nfcSignedHash, nfcCreationTimestamp);
|
||||||
|
|
||||||
|
signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
|
||||||
|
try {
|
||||||
|
signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, mPrivateKey);
|
||||||
|
} catch (PGPException e) {
|
||||||
|
Log.e(Constants.TAG, "signing error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // supply signatureGenerator with a SubpacketVector
|
||||||
|
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
|
||||||
|
if (nfcCreationTimestamp != null) {
|
||||||
|
spGen.setSignatureCreationTime(false, nfcCreationTimestamp);
|
||||||
|
Log.d(Constants.TAG, "For NFC: set sig creation time to " + nfcCreationTimestamp);
|
||||||
|
}
|
||||||
|
PGPSignatureSubpacketVector packetVector = spGen.generate();
|
||||||
|
signatureGenerator.setHashedSubpackets(packetVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the master subkey (which we certify for)
|
||||||
|
PGPPublicKey publicKey = publicKeyRing.getPublicKey().getPublicKey();
|
||||||
|
|
||||||
|
// fetch public key ring, add the certification and return it
|
||||||
|
try {
|
||||||
|
for (WrappedUserAttribute userAttribute : userAttributes) {
|
||||||
|
PGPUserAttributeSubpacketVector vector = userAttribute.getVector();
|
||||||
|
PGPSignature sig = signatureGenerator.generateCertification(vector, publicKey);
|
||||||
|
publicKey = PGPPublicKey.addCertification(publicKey, vector, sig);
|
||||||
|
}
|
||||||
|
} catch (PGPException e) {
|
||||||
|
Log.e(Constants.TAG, "signing error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PGPPublicKeyRing ring = PGPPublicKeyRing.insertPublicKey(publicKeyRing.getRing(), publicKey);
|
||||||
|
|
||||||
|
return new UncachedKeyRing(ring);
|
||||||
|
}
|
||||||
|
|
||||||
static class PrivateKeyNotUnlockedException extends RuntimeException {
|
static class PrivateKeyNotUnlockedException extends RuntimeException {
|
||||||
// this exception is a programming error which happens when an operation which requires
|
// this exception is a programming error which happens when an operation which requires
|
||||||
// the private key is called without a previous call to unlock()
|
// the private key is called without a previous call to unlock()
|
||||||
|
@ -24,6 +24,9 @@ import android.os.Parcelable;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is a a transferable representation for a number of keyrings to
|
* This class is a a transferable representation for a number of keyrings to
|
||||||
* be certified.
|
* be certified.
|
||||||
@ -76,14 +79,19 @@ public class CertifyActionsParcel implements Parcelable {
|
|||||||
final public long mMasterKeyId;
|
final public long mMasterKeyId;
|
||||||
|
|
||||||
final public ArrayList<String> mUserIds;
|
final public ArrayList<String> mUserIds;
|
||||||
|
final public ArrayList<WrappedUserAttribute> mUserAttributes;
|
||||||
public CertifyAction(long masterKeyId) {
|
|
||||||
this(masterKeyId, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CertifyAction(long masterKeyId, ArrayList<String> userIds) {
|
public CertifyAction(long masterKeyId, ArrayList<String> userIds) {
|
||||||
mMasterKeyId = masterKeyId;
|
mMasterKeyId = masterKeyId;
|
||||||
mUserIds = userIds;
|
mUserIds = userIds;
|
||||||
|
mUserAttributes = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CertifyAction(long masterKeyId, ArrayList<String> userIds,
|
||||||
|
ArrayList<WrappedUserAttribute> attributes) {
|
||||||
|
mMasterKeyId = masterKeyId;
|
||||||
|
mUserIds = userIds;
|
||||||
|
mUserAttributes = attributes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1071,11 +1071,14 @@
|
|||||||
<string name="msg_pse_symmetric">"Preparing symmetric encryption"</string>
|
<string name="msg_pse_symmetric">"Preparing symmetric encryption"</string>
|
||||||
|
|
||||||
<string name="msg_crt_certifying">"Generating certifications"</string>
|
<string name="msg_crt_certifying">"Generating certifications"</string>
|
||||||
<string name="msg_crt_certify_all">"Certifying all user IDs for key %s"</string>
|
<plurals name="msg_crt_certify_uids">
|
||||||
<plurals name="msg_crt_certify_some">
|
|
||||||
<item quantity="one">"Certifying one user ID for key %2$s"</item>
|
<item quantity="one">"Certifying one user ID for key %2$s"</item>
|
||||||
<item quantity="other">"Certifying %1$d user IDs for key %2$s"</item>
|
<item quantity="other">"Certifying %1$d user IDs for key %2$s"</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="msg_crt_certify_uats">
|
||||||
|
<item quantity="one">"Certifying one user attribute for key %2$s"</item>
|
||||||
|
<item quantity="other">"Certifying %1$d user attributes for key %2$s"</item>
|
||||||
|
</plurals>
|
||||||
<string name="msg_crt_error_self">"Cannot issue self-certificate like this!"</string>
|
<string name="msg_crt_error_self">"Cannot issue self-certificate like this!"</string>
|
||||||
<string name="msg_crt_error_master_not_found">"Master key not found!"</string>
|
<string name="msg_crt_error_master_not_found">"Master key not found!"</string>
|
||||||
<string name="msg_crt_error_nothing">"No keys certified!"</string>
|
<string name="msg_crt_error_nothing">"No keys certified!"</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user