mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-12-25 00:18:51 -05:00
yubikey certifications!
This commit is contained in:
parent
aca54e31ea
commit
d46fc3740b
@ -30,6 +30,8 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpCertifyOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpCertifyOperation.PgpCertifyResult;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
@ -38,6 +40,8 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
|
||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||
import org.sufficientlysecure.keychain.service.input.NfcOperationsParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.NfcOperationsParcel.NfcSignOperationsBuilder;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
@ -73,10 +77,6 @@ public class CertifyOperation extends BaseOperation {
|
||||
mProviderHelper.getCanonicalizedSecretKeyRing(parcel.mMasterKeyId);
|
||||
log.add(LogType.MSG_CRT_UNLOCK, 1);
|
||||
certificationKey = secretKeyRing.getSecretKey();
|
||||
if (certificationKey.getSecretKeyType() == SecretKeyType.DIVERT_TO_CARD) {
|
||||
log.add(LogType.MSG_CRT_ERROR_DIVERT, 2);
|
||||
return new CertifyResult(CertifyResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
||||
// certification is always with the master key id, so use that one
|
||||
String passphrase = getCachedPassphrase(parcel.mMasterKeyId, parcel.mMasterKeyId);
|
||||
@ -102,6 +102,8 @@ public class CertifyOperation extends BaseOperation {
|
||||
|
||||
int certifyOk = 0, certifyError = 0, uploadOk = 0, uploadError = 0;
|
||||
|
||||
NfcSignOperationsBuilder allRequiredInput = new NfcSignOperationsBuilder(parcel.getSignatureTime());
|
||||
|
||||
// Work through all requested certifications
|
||||
for (CertifyAction action : parcel.mCertifyActions) {
|
||||
|
||||
@ -122,28 +124,21 @@ public class CertifyOperation extends BaseOperation {
|
||||
CanonicalizedPublicKeyRing publicRing =
|
||||
mProviderHelper.getCanonicalizedPublicKeyRing(action.mMasterKeyId);
|
||||
|
||||
UncachedKeyRing certifiedKey = null;
|
||||
if (action.mUserIds != null) {
|
||||
log.add(LogType.MSG_CRT_CERTIFY_UIDS, 2, action.mUserIds.size(),
|
||||
KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
|
||||
PgpCertifyOperation op = new PgpCertifyOperation();
|
||||
PgpCertifyResult result = op.certify(certificationKey, publicRing,
|
||||
log, 2, action, parcel.getSignatureData(), parcel.getSignatureTime());
|
||||
|
||||
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 (!result.success()) {
|
||||
certifyError += 1;
|
||||
log.add(LogType.MSG_CRT_WARN_CERT_FAILED, 3);
|
||||
continue;
|
||||
}
|
||||
certifiedKeys.add(certifiedKey);
|
||||
if (result.nfcInputRequired()) {
|
||||
NfcOperationsParcel requiredInput = result.getRequiredInput();
|
||||
allRequiredInput.addAll(requiredInput);
|
||||
continue;
|
||||
}
|
||||
|
||||
certifiedKeys.add(result.getCertifiedRing());
|
||||
|
||||
} catch (NotFoundException e) {
|
||||
certifyError += 1;
|
||||
@ -152,6 +147,11 @@ public class CertifyOperation extends BaseOperation {
|
||||
|
||||
}
|
||||
|
||||
if ( ! allRequiredInput.isEmpty()) {
|
||||
log.add(LogType.MSG_CRT_NFC_RETURN, 1);
|
||||
return new CertifyResult(log, allRequiredInput.build());
|
||||
}
|
||||
|
||||
log.add(LogType.MSG_CRT_SAVING, 1);
|
||||
|
||||
// Check if we were cancelled
|
||||
|
@ -23,6 +23,7 @@ import android.content.Intent;
|
||||
import android.os.Parcel;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.service.input.NfcOperationsParcel;
|
||||
import org.sufficientlysecure.keychain.ui.LogDisplayActivity;
|
||||
import org.sufficientlysecure.keychain.ui.LogDisplayFragment;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||
@ -30,16 +31,19 @@ import org.sufficientlysecure.keychain.ui.util.Notify.ActionListener;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify.Showable;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
||||
|
||||
public class CertifyResult extends OperationResult {
|
||||
|
||||
public class CertifyResult extends InputPendingResult {
|
||||
int mCertifyOk, mCertifyError, mUploadOk, mUploadError;
|
||||
|
||||
public CertifyResult(int result, OperationLog log) {
|
||||
super(result, log);
|
||||
}
|
||||
|
||||
public CertifyResult(OperationLog log, NfcOperationsParcel requiredInput) {
|
||||
super(log, requiredInput);
|
||||
}
|
||||
|
||||
public CertifyResult(int result, OperationLog log, int certifyOk, int certifyError, int uploadOk, int uploadError) {
|
||||
this(result, log);
|
||||
super(result, log);
|
||||
mCertifyOk = certifyOk;
|
||||
mCertifyError = certifyError;
|
||||
mUploadOk = uploadOk;
|
||||
|
@ -0,0 +1,76 @@
|
||||
package org.sufficientlysecure.keychain.operations.results;
|
||||
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
import org.sufficientlysecure.keychain.service.input.NfcOperationsParcel;
|
||||
|
||||
|
||||
public class InputPendingResult extends OperationResult {
|
||||
|
||||
// the fourth bit indicates a "data pending" result! (it's also a form of non-success)
|
||||
public static final int RESULT_PENDING = RESULT_ERROR + 8;
|
||||
|
||||
public static final int RESULT_PENDING_PASSPHRASE = RESULT_PENDING + 16;
|
||||
public static final int RESULT_PENDING_NFC = RESULT_PENDING + 32;
|
||||
|
||||
final NfcOperationsParcel mRequiredInput;
|
||||
final Long mKeyIdPassphraseNeeded;
|
||||
|
||||
public InputPendingResult(int result, OperationLog log) {
|
||||
super(result, log);
|
||||
mRequiredInput = null;
|
||||
mKeyIdPassphraseNeeded = null;
|
||||
}
|
||||
|
||||
public InputPendingResult(OperationLog log, NfcOperationsParcel requiredInput) {
|
||||
super(RESULT_PENDING_NFC, log);
|
||||
mRequiredInput = requiredInput;
|
||||
mKeyIdPassphraseNeeded = null;
|
||||
}
|
||||
|
||||
public InputPendingResult(OperationLog log, long keyIdPassphraseNeeded) {
|
||||
super(RESULT_PENDING_PASSPHRASE, log);
|
||||
mRequiredInput = null;
|
||||
mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
|
||||
}
|
||||
|
||||
public InputPendingResult(Parcel source) {
|
||||
super(source);
|
||||
mRequiredInput = source.readParcelable(getClass().getClassLoader());
|
||||
mKeyIdPassphraseNeeded = source.readInt() != 0 ? source.readLong() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeParcelable(mRequiredInput, 0);
|
||||
if (mKeyIdPassphraseNeeded != null) {
|
||||
dest.writeInt(1);
|
||||
dest.writeLong(mKeyIdPassphraseNeeded);
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPending() {
|
||||
return (mResult & RESULT_PENDING) == RESULT_PENDING;
|
||||
}
|
||||
|
||||
public boolean isNfcPending() {
|
||||
return (mResult & RESULT_PENDING_NFC) == RESULT_PENDING_NFC;
|
||||
}
|
||||
|
||||
public boolean isPassphrasePending() {
|
||||
return (mResult & RESULT_PENDING_PASSPHRASE) == RESULT_PENDING_PASSPHRASE;
|
||||
}
|
||||
|
||||
public NfcOperationsParcel getNfcOperationsParcel() {
|
||||
return mRequiredInput;
|
||||
}
|
||||
|
||||
public long getPassphraseKeyId() {
|
||||
return mKeyIdPassphraseNeeded;
|
||||
}
|
||||
|
||||
}
|
@ -697,9 +697,9 @@ public abstract class OperationResult implements Parcelable {
|
||||
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_UNLOCK (LogLevel.ERROR, R.string.msg_crt_error_unlock),
|
||||
MSG_CRT_ERROR_DIVERT (LogLevel.ERROR, R.string.msg_crt_error_divert),
|
||||
MSG_CRT (LogLevel.START, R.string.msg_crt),
|
||||
MSG_CRT_MASTER_FETCH (LogLevel.DEBUG, R.string.msg_crt_master_fetch),
|
||||
MSG_CRT_NFC_RETURN (LogLevel.OK, R.string.msg_crt_nfc_return),
|
||||
MSG_CRT_SAVE (LogLevel.DEBUG, R.string.msg_crt_save),
|
||||
MSG_CRT_SAVING (LogLevel.DEBUG, R.string.msg_crt_saving),
|
||||
MSG_CRT_SUCCESS (LogLevel.OK, R.string.msg_crt_success),
|
||||
|
@ -31,6 +31,7 @@ public class SignEncryptResult extends OperationResult {
|
||||
|
||||
public static final int RESULT_PENDING = RESULT_ERROR + 8;
|
||||
|
||||
|
||||
public PgpSignEncryptResult getPending() {
|
||||
for (PgpSignEncryptResult sub : mResults) {
|
||||
if (sub.isPending()) {
|
||||
|
@ -202,8 +202,26 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
||||
}
|
||||
}
|
||||
|
||||
public PGPSignatureGenerator getSignatureGenerator(int hashAlgo, boolean cleartext,
|
||||
Map<ByteBuffer,byte[]> signedHashes, Date creationTimestamp)
|
||||
public PGPSignatureGenerator getCertSignatureGenerator(Map<ByteBuffer, byte[]> signedHashes) {
|
||||
PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(
|
||||
PgpConstants.CERTIFY_HASH_ALGO, signedHashes);
|
||||
|
||||
if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) {
|
||||
throw new PrivateKeyNotUnlockedException();
|
||||
}
|
||||
|
||||
PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
|
||||
try {
|
||||
signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, mPrivateKey);
|
||||
return signatureGenerator;
|
||||
} catch (PGPException e) {
|
||||
Log.e(Constants.TAG, "signing error", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public PGPSignatureGenerator getDataSignatureGenerator(int hashAlgo, boolean cleartext,
|
||||
Map<ByteBuffer, byte[]> signedHashes, Date creationTimestamp)
|
||||
throws PgpGeneralException {
|
||||
if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) {
|
||||
throw new PrivateKeyNotUnlockedException();
|
||||
@ -259,135 +277,6 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Certify the given pubkeyid with the given masterkeyid.
|
||||
*
|
||||
* @param publicKeyRing Keyring to add certification to.
|
||||
* @param userIds User IDs to certify
|
||||
* @return A keyring with added certifications
|
||||
*/
|
||||
public UncachedKeyRing certifyUserIds(CanonicalizedPublicKeyRing publicKeyRing,
|
||||
List<String> userIds,
|
||||
HashMap<ByteBuffer,byte[]> signedHashes, Date creationTimestamp) {
|
||||
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;
|
||||
{
|
||||
PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(
|
||||
PgpConstants.CERTIFY_HASH_ALGO, signedHashes);
|
||||
|
||||
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 (creationTimestamp != null) {
|
||||
spGen.setSignatureCreationTime(false, creationTimestamp);
|
||||
Log.d(Constants.TAG, "For NFC: set sig creation time to " + creationTimestamp);
|
||||
}
|
||||
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 (String userId : userIds) {
|
||||
PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey);
|
||||
publicKey = PGPPublicKey.addCertification(publicKey, userId, sig);
|
||||
}
|
||||
} catch (PGPException e) {
|
||||
Log.e(Constants.TAG, "signing error", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
PGPPublicKeyRing ring = PGPPublicKeyRing.insertPublicKey(publicKeyRing.getRing(), publicKey);
|
||||
|
||||
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,
|
||||
HashMap<ByteBuffer,byte[]> signedHashes, Date creationTimestamp) {
|
||||
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;
|
||||
{
|
||||
PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(
|
||||
PgpConstants.CERTIFY_HASH_ALGO, signedHashes);
|
||||
|
||||
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 (creationTimestamp != null) {
|
||||
spGen.setSignatureCreationTime(false, creationTimestamp);
|
||||
Log.d(Constants.TAG, "For NFC: set sig creation time to " + creationTimestamp);
|
||||
}
|
||||
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 {
|
||||
// this exception is a programming error which happens when an operation which requires
|
||||
// the private key is called without a previous call to unlock()
|
||||
|
@ -0,0 +1,149 @@
|
||||
package org.sufficientlysecure.keychain.pgp;
|
||||
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.spongycastle.openpgp.PGPException;
|
||||
import org.spongycastle.openpgp.PGPPublicKey;
|
||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.spongycastle.openpgp.PGPSignature;
|
||||
import org.spongycastle.openpgp.PGPSignatureGenerator;
|
||||
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
||||
import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector;
|
||||
import org.spongycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
|
||||
import org.sufficientlysecure.keychain.service.input.NfcOperationsParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.NfcOperationsParcel.NfcSignOperationsBuilder;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
|
||||
public class PgpCertifyOperation {
|
||||
|
||||
public PgpCertifyResult certify(
|
||||
CanonicalizedSecretKey secretKey,
|
||||
CanonicalizedPublicKeyRing publicRing,
|
||||
OperationLog log,
|
||||
int indent,
|
||||
CertifyAction action,
|
||||
Map<ByteBuffer,byte[]> signedHashes,
|
||||
Date creationTimestamp) {
|
||||
|
||||
if (!secretKey.isMasterKey()) {
|
||||
throw new AssertionError("tried to certify with non-master key, this is a programming error!");
|
||||
}
|
||||
if (publicRing.getMasterKeyId() == secretKey.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 = secretKey.getCertSignatureGenerator(signedHashes);
|
||||
|
||||
{ // supply signatureGenerator with a SubpacketVector
|
||||
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
|
||||
if (creationTimestamp != null) {
|
||||
spGen.setSignatureCreationTime(false, creationTimestamp);
|
||||
Log.d(Constants.TAG, "For NFC: set sig creation time to " + creationTimestamp);
|
||||
}
|
||||
PGPSignatureSubpacketVector packetVector = spGen.generate();
|
||||
signatureGenerator.setHashedSubpackets(packetVector);
|
||||
}
|
||||
|
||||
// get the master subkey (which we certify for)
|
||||
PGPPublicKey publicKey = publicRing.getPublicKey().getPublicKey();
|
||||
|
||||
NfcSignOperationsBuilder requiredInput = new NfcSignOperationsBuilder(creationTimestamp);
|
||||
|
||||
try {
|
||||
if (action.mUserIds != null) {
|
||||
log.add(LogType.MSG_CRT_CERTIFY_UIDS, 2, action.mUserIds.size(),
|
||||
KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
|
||||
|
||||
// fetch public key ring, add the certification and return it
|
||||
for (String userId : action.mUserIds) {
|
||||
try {
|
||||
PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey);
|
||||
publicKey = PGPPublicKey.addCertification(publicKey, userId, sig);
|
||||
} catch (NfcInteractionNeeded e) {
|
||||
requiredInput.addHash(e.hashToSign, e.hashAlgo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (action.mUserAttributes != null) {
|
||||
log.add(LogType.MSG_CRT_CERTIFY_UATS, 2, action.mUserAttributes.size(),
|
||||
KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
|
||||
|
||||
// fetch public key ring, add the certification and return it
|
||||
for (WrappedUserAttribute userAttribute : action.mUserAttributes) {
|
||||
PGPUserAttributeSubpacketVector vector = userAttribute.getVector();
|
||||
try {
|
||||
PGPSignature sig = signatureGenerator.generateCertification(vector, publicKey);
|
||||
publicKey = PGPPublicKey.addCertification(publicKey, vector, sig);
|
||||
} catch (NfcInteractionNeeded e) {
|
||||
requiredInput.addHash(e.hashToSign, e.hashAlgo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} catch (PGPException e) {
|
||||
Log.e(Constants.TAG, "signing error", e);
|
||||
return new PgpCertifyResult();
|
||||
}
|
||||
|
||||
if (!requiredInput.isEmpty()) {
|
||||
return new PgpCertifyResult(requiredInput.build());
|
||||
}
|
||||
|
||||
PGPPublicKeyRing ring = PGPPublicKeyRing.insertPublicKey(publicRing.getRing(), publicKey);
|
||||
return new PgpCertifyResult(new UncachedKeyRing(ring));
|
||||
|
||||
}
|
||||
|
||||
public static class PgpCertifyResult {
|
||||
|
||||
final NfcOperationsParcel mRequiredInput;
|
||||
final UncachedKeyRing mCertifiedRing;
|
||||
|
||||
PgpCertifyResult() {
|
||||
mRequiredInput = null;
|
||||
mCertifiedRing = null;
|
||||
}
|
||||
|
||||
PgpCertifyResult(NfcOperationsParcel requiredInput) {
|
||||
mRequiredInput = requiredInput;
|
||||
mCertifiedRing = null;
|
||||
}
|
||||
|
||||
PgpCertifyResult(UncachedKeyRing certifiedRing) {
|
||||
mRequiredInput = null;
|
||||
mCertifiedRing = certifiedRing;
|
||||
}
|
||||
|
||||
public boolean success() {
|
||||
return mCertifiedRing != null || mRequiredInput != null;
|
||||
}
|
||||
|
||||
public boolean nfcInputRequired() {
|
||||
return mRequiredInput != null;
|
||||
}
|
||||
|
||||
public UncachedKeyRing getCertifiedRing() {
|
||||
return mCertifiedRing;
|
||||
}
|
||||
|
||||
public NfcOperationsParcel getRequiredInput() {
|
||||
return mRequiredInput;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -44,8 +44,6 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.NfcOperationsParcel;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.util.InputData;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
@ -283,7 +281,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
|
||||
|
||||
try {
|
||||
boolean cleartext = input.isCleartextSignature() && input.isEnableAsciiArmorOutput() && !enableEncryption;
|
||||
signatureGenerator = signingKey.getSignatureGenerator(
|
||||
signatureGenerator = signingKey.getDataSignatureGenerator(
|
||||
input.getSignatureHashAlgorithm(), cleartext,
|
||||
input.getCryptoData(), input.getSignatureTime());
|
||||
} catch (PgpGeneralException e) {
|
||||
|
@ -22,8 +22,10 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
@ -42,9 +44,9 @@ public class CertifyActionsParcel implements Parcelable {
|
||||
public ArrayList<CertifyAction> mCertifyActions = new ArrayList<>();
|
||||
public CryptoInputParcel mCryptoInput;
|
||||
|
||||
public CertifyActionsParcel(Date operationTime, long masterKeyId) {
|
||||
public CertifyActionsParcel(CryptoInputParcel cryptoInput, long masterKeyId) {
|
||||
mMasterKeyId = masterKeyId;
|
||||
mCryptoInput = new CryptoInputParcel(operationTime);
|
||||
mCryptoInput = cryptoInput != null ? cryptoInput : new CryptoInputParcel(new Date());
|
||||
mLevel = CertifyLevel.DEFAULT;
|
||||
}
|
||||
|
||||
@ -70,6 +72,14 @@ public class CertifyActionsParcel implements Parcelable {
|
||||
destination.writeSerializable(mCertifyActions);
|
||||
}
|
||||
|
||||
public Map<ByteBuffer, byte[]> getSignatureData() {
|
||||
return mCryptoInput.getCryptoData();
|
||||
}
|
||||
|
||||
public Date getSignatureTime() {
|
||||
return mCryptoInput.getSignatureTime();
|
||||
}
|
||||
|
||||
public static final Creator<CertifyActionsParcel> CREATOR = new Creator<CertifyActionsParcel>() {
|
||||
public CertifyActionsParcel createFromParcel(final Parcel source) {
|
||||
return new CertifyActionsParcel(source);
|
||||
|
@ -18,6 +18,7 @@
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
@ -26,6 +27,7 @@ import android.support.v4.app.FragmentManager;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.operations.results.CertifyResult;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
@ -1,5 +1,7 @@
|
||||
package org.sufficientlysecure.keychain.service.input;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import android.os.Parcel;
|
||||
@ -14,13 +16,14 @@ public class NfcOperationsParcel implements Parcelable {
|
||||
|
||||
public Date mSignatureTime;
|
||||
public final NfcOperationType mType;
|
||||
public final byte[][] mInputHash;
|
||||
public final int[] mSignAlgo;
|
||||
public final byte[][] mInputHashes;
|
||||
public final int[] mSignAlgos;
|
||||
|
||||
private NfcOperationsParcel(NfcOperationType type, byte[] inputHash, int signAlgo, Date signatureTime) {
|
||||
private NfcOperationsParcel(NfcOperationType type, byte[][] inputHashes,
|
||||
int[] signAlgos, Date signatureTime) {
|
||||
mType = type;
|
||||
mInputHash = new byte[][] { inputHash };
|
||||
mSignAlgo = new int[] { signAlgo };
|
||||
mInputHashes = inputHashes;
|
||||
mSignAlgos = signAlgos;
|
||||
mSignatureTime = signatureTime;
|
||||
}
|
||||
|
||||
@ -29,11 +32,11 @@ public class NfcOperationsParcel implements Parcelable {
|
||||
|
||||
{
|
||||
int count = source.readInt();
|
||||
mInputHash = new byte[count][];
|
||||
mSignAlgo = new int[count];
|
||||
mInputHashes = new byte[count][];
|
||||
mSignAlgos = new int[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
mInputHash[i] = source.createByteArray();
|
||||
mSignAlgo[i] = source.readInt();
|
||||
mInputHashes[i] = source.createByteArray();
|
||||
mSignAlgos[i] = source.readInt();
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,11 +46,13 @@ public class NfcOperationsParcel implements Parcelable {
|
||||
|
||||
public static NfcOperationsParcel createNfcSignOperation(
|
||||
byte[] inputHash, int signAlgo, Date signatureTime) {
|
||||
return new NfcOperationsParcel(NfcOperationType.NFC_SIGN, inputHash, signAlgo, signatureTime);
|
||||
return new NfcOperationsParcel(NfcOperationType.NFC_SIGN,
|
||||
new byte[][] { inputHash }, new int[] { signAlgo }, signatureTime);
|
||||
}
|
||||
|
||||
public static NfcOperationsParcel createNfcDecryptOperation(byte[] inputHash) {
|
||||
return new NfcOperationsParcel(NfcOperationType.NFC_DECRYPT, inputHash, 0, null);
|
||||
return new NfcOperationsParcel(NfcOperationType.NFC_DECRYPT,
|
||||
new byte[][] { inputHash }, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -58,10 +63,10 @@ public class NfcOperationsParcel implements Parcelable {
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mType.ordinal());
|
||||
dest.writeInt(mInputHash.length);
|
||||
for (int i = 0; i < mInputHash.length; i++) {
|
||||
dest.writeByteArray(mInputHash[i]);
|
||||
dest.writeInt(mSignAlgo[i]);
|
||||
dest.writeInt(mInputHashes.length);
|
||||
for (int i = 0; i < mInputHashes.length; i++) {
|
||||
dest.writeByteArray(mInputHashes[i]);
|
||||
dest.writeInt(mSignAlgos[i]);
|
||||
}
|
||||
if (mSignatureTime != null) {
|
||||
dest.writeInt(1);
|
||||
@ -82,4 +87,50 @@ public class NfcOperationsParcel implements Parcelable {
|
||||
}
|
||||
};
|
||||
|
||||
public static class NfcSignOperationsBuilder {
|
||||
Date mSignatureTime;
|
||||
ArrayList<Integer> mSignAlgos = new ArrayList<>();
|
||||
ArrayList<byte[]> mInputHashes = new ArrayList<>();
|
||||
|
||||
public NfcSignOperationsBuilder(Date signatureTime) {
|
||||
mSignatureTime = signatureTime;
|
||||
}
|
||||
|
||||
public NfcOperationsParcel build() {
|
||||
byte[][] inputHashes = new byte[mInputHashes.size()][];
|
||||
mInputHashes.toArray(inputHashes);
|
||||
int[] signAlgos = new int[mSignAlgos.size()];
|
||||
for (int i = 0; i < mSignAlgos.size(); i++) {
|
||||
signAlgos[i] = mSignAlgos.get(i);
|
||||
}
|
||||
|
||||
return new NfcOperationsParcel(NfcOperationType.NFC_SIGN,
|
||||
inputHashes, signAlgos, mSignatureTime);
|
||||
}
|
||||
|
||||
public void addHash(byte[] hash, int algo) {
|
||||
mInputHashes.add(hash);
|
||||
mSignAlgos.add(algo);
|
||||
}
|
||||
|
||||
public void addAll(NfcOperationsParcel input) {
|
||||
if (!mSignatureTime.equals(input.mSignatureTime)) {
|
||||
throw new AssertionError("input times must match, this is a programming error!");
|
||||
}
|
||||
if (input.mType != NfcOperationType.NFC_SIGN) {
|
||||
throw new AssertionError("operation types must match, this is a progrmming error!");
|
||||
}
|
||||
|
||||
Collections.addAll(mInputHashes, input.mInputHashes);
|
||||
for (int signAlgo : input.mSignAlgos) {
|
||||
mSignAlgos.add(signAlgo);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return mInputHashes.isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.MultiUserIdsAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||
import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
|
||||
@ -66,14 +66,11 @@ import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
public class CertifyKeyFragment extends LoaderFragment
|
||||
public class CertifyKeyFragment extends CryptoOperationFragment
|
||||
implements LoaderManager.LoaderCallbacks<Cursor> {
|
||||
|
||||
public static final int REQUEST_CODE_PASSPHRASE = 0x00008001;
|
||||
|
||||
private CheckBox mUploadKeyCheckbox;
|
||||
ListView mUserIds;
|
||||
|
||||
@ -102,9 +99,6 @@ public class CertifyKeyFragment extends LoaderFragment
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
// Start out with a progress indicator.
|
||||
setContentShown(false);
|
||||
|
||||
mPubMasterKeyIds = getActivity().getIntent().getLongArrayExtra(CertifyKeyActivity.EXTRA_KEY_IDS);
|
||||
if (mPubMasterKeyIds == null) {
|
||||
Log.e(Constants.TAG, "List of key ids to certify missing!");
|
||||
@ -114,6 +108,7 @@ public class CertifyKeyFragment extends LoaderFragment
|
||||
|
||||
mPassthroughMessenger = getActivity().getIntent().getParcelableExtra(
|
||||
KeychainIntentService.EXTRA_MESSENGER);
|
||||
mPassthroughMessenger = null; // TODO remove, development hack
|
||||
|
||||
// preselect certify key id if given
|
||||
long certifyKeyId = getActivity().getIntent().getLongExtra(CertifyKeyActivity.EXTRA_CERTIFY_KEY_ID, Constants.key.none);
|
||||
@ -143,9 +138,7 @@ public class CertifyKeyFragment extends LoaderFragment
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
|
||||
View root = super.onCreateView(inflater, superContainer, savedInstanceState);
|
||||
|
||||
View view = inflater.inflate(R.layout.certify_key_fragment, getContainer());
|
||||
View view = inflater.inflate(R.layout.certify_key_fragment, null);
|
||||
|
||||
mCertifyKeySpinner = (CertifyKeySpinner) view.findViewById(R.id.certify_key_spinner);
|
||||
mUploadKeyCheckbox = (CheckBox) view.findViewById(R.id.sign_key_upload_checkbox);
|
||||
@ -173,7 +166,7 @@ public class CertifyKeyFragment extends LoaderFragment
|
||||
Notify.showNotify(getActivity(), getString(R.string.select_key_to_certify),
|
||||
Notify.Style.ERROR);
|
||||
} else {
|
||||
initiateCertifying();
|
||||
cryptoOperation();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -183,7 +176,7 @@ public class CertifyKeyFragment extends LoaderFragment
|
||||
mUploadKeyCheckbox.setChecked(false);
|
||||
}
|
||||
|
||||
return root;
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -307,7 +300,6 @@ public class CertifyKeyFragment extends LoaderFragment
|
||||
}
|
||||
|
||||
mUserIdsAdapter.swapCursor(matrix);
|
||||
setContentShown(true, isResumed());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -315,50 +307,17 @@ public class CertifyKeyFragment extends LoaderFragment
|
||||
mUserIdsAdapter.swapCursor(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* handles the UI bits of the signing process on the UI thread
|
||||
*/
|
||||
private void initiateCertifying() {
|
||||
// get the user's passphrase for this key (if required)
|
||||
String passphrase;
|
||||
try {
|
||||
passphrase = PassphraseCacheService.getCachedPassphrase(getActivity(), mSignMasterKeyId, mSignMasterKeyId);
|
||||
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||
Log.e(Constants.TAG, "Key not found!", e);
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
if (passphrase == null) {
|
||||
Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class);
|
||||
intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, mSignMasterKeyId);
|
||||
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
|
||||
// bail out; need to wait until the user has entered the passphrase before trying again
|
||||
} else {
|
||||
startCertifying();
|
||||
}
|
||||
protected void cryptoOperation() {
|
||||
cryptoOperation((CryptoInputParcel) null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_PASSPHRASE: {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
String passphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
||||
startCertifying();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
default: {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
protected void cryptoOperation(String passphrase) {
|
||||
cryptoOperation((CryptoInputParcel) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* kicks off the actual signing process on a background thread
|
||||
*/
|
||||
private void startCertifying() {
|
||||
@Override
|
||||
protected void cryptoOperation(CryptoInputParcel cryptoInput) {
|
||||
// Bail out if there is not at least one user id selected
|
||||
ArrayList<CertifyAction> certifyActions = mUserIdsAdapter.getSelectedCertifyActions();
|
||||
if (certifyActions.isEmpty()) {
|
||||
@ -370,7 +329,7 @@ public class CertifyKeyFragment extends LoaderFragment
|
||||
Bundle data = new Bundle();
|
||||
{
|
||||
// fill values for this action
|
||||
CertifyActionsParcel parcel = new CertifyActionsParcel(new Date(), mSignMasterKeyId);
|
||||
CertifyActionsParcel parcel = new CertifyActionsParcel(cryptoInput, mSignMasterKeyId);
|
||||
parcel.mCertifyActions.addAll(certifyActions);
|
||||
|
||||
data.putParcelable(KeychainIntentService.CERTIFY_PARCEL, parcel);
|
||||
@ -390,14 +349,21 @@ public class CertifyKeyFragment extends LoaderFragment
|
||||
} else {
|
||||
|
||||
// Message is received after signing is done in KeychainIntentService
|
||||
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(getActivity(),
|
||||
getString(R.string.progress_certifying), ProgressDialog.STYLE_SPINNER, true) {
|
||||
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
|
||||
getActivity(), getString(R.string.progress_certifying),
|
||||
ProgressDialog.STYLE_SPINNER, true) {
|
||||
public void handleMessage(Message message) {
|
||||
// handle messages by standard KeychainIntentServiceHandler first
|
||||
// handle messages by KeychainIntentCryptoServiceHandler first
|
||||
super.handleMessage(message);
|
||||
|
||||
// handle pending messages
|
||||
if (handlePendingMessage(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.arg1 == MessageStatus.OKAY.ordinal()) {
|
||||
Bundle data = message.getData();
|
||||
|
||||
CertifyResult result = data.getParcelable(CertifyResult.EXTRA_RESULT);
|
||||
|
||||
Intent intent = new Intent();
|
||||
|
@ -0,0 +1,89 @@
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import org.sufficientlysecure.keychain.operations.results.CertifyResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.InputPendingResult;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler.MessageStatus;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.NfcOperationsParcel;
|
||||
|
||||
|
||||
public abstract class CryptoOperationFragment extends Fragment {
|
||||
|
||||
public static final int REQUEST_CODE_PASSPHRASE = 0x00008001;
|
||||
public static final int REQUEST_CODE_NFC = 0x00008002;
|
||||
|
||||
private void startPassphraseDialog(long subkeyId) {
|
||||
Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class);
|
||||
intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, subkeyId);
|
||||
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
|
||||
}
|
||||
|
||||
private void initiateNfcInput(NfcOperationsParcel nfcOps) {
|
||||
Intent intent = new Intent(getActivity(), NfcOperationActivity.class);
|
||||
intent.putExtra(NfcOperationActivity.EXTRA_PIN, "123456");
|
||||
intent.putExtra(NfcOperationActivity.EXTRA_NFC_OPS, nfcOps);
|
||||
startActivityForResult(intent, REQUEST_CODE_NFC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_PASSPHRASE: {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
String passphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
||||
cryptoOperation(passphrase);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case REQUEST_CODE_NFC: {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
CryptoInputParcel cryptoInput =
|
||||
data.getParcelableExtra(NfcOperationActivity.RESULT_DATA);
|
||||
cryptoOperation(cryptoInput);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean handlePendingMessage(Message message) {
|
||||
|
||||
if (message.arg1 == MessageStatus.OKAY.ordinal()) {
|
||||
Bundle data = message.getData();
|
||||
|
||||
InputPendingResult result = data.getParcelable(CertifyResult.EXTRA_RESULT);
|
||||
|
||||
if (result != null && result.isPending()) {
|
||||
if (result.isPassphrasePending()) {
|
||||
startPassphraseDialog(result.getPassphraseKeyId());
|
||||
return true;
|
||||
} else if (result.isNfcPending()) {
|
||||
NfcOperationsParcel requiredInput = result.getNfcOperationsParcel();
|
||||
initiateNfcInput(requiredInput);
|
||||
return true;
|
||||
} else {
|
||||
throw new RuntimeException("Unhandled pending result!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract void cryptoOperation(CryptoInputParcel cryptoInput);
|
||||
protected abstract void cryptoOperation(String passphrase);
|
||||
|
||||
}
|
@ -182,17 +182,17 @@ public class NfcOperationActivity extends BaseActivity {
|
||||
|
||||
case NFC_DECRYPT:
|
||||
|
||||
for (int i = 0; i < mNfcOperations.mInputHash.length; i++) {
|
||||
byte[] hash = mNfcOperations.mInputHash[i];
|
||||
for (int i = 0; i < mNfcOperations.mInputHashes.length; i++) {
|
||||
byte[] hash = mNfcOperations.mInputHashes[i];
|
||||
byte[] decryptedSessionKey = nfcDecryptSessionKey(hash);
|
||||
resultData.addCryptoData(hash, decryptedSessionKey);
|
||||
}
|
||||
break;
|
||||
|
||||
case NFC_SIGN:
|
||||
for (int i = 0; i < mNfcOperations.mInputHash.length; i++) {
|
||||
byte[] hash = mNfcOperations.mInputHash[i];
|
||||
int algo = mNfcOperations.mSignAlgo[i];
|
||||
for (int i = 0; i < mNfcOperations.mInputHashes.length; i++) {
|
||||
byte[] hash = mNfcOperations.mInputHashes[i];
|
||||
int algo = mNfcOperations.mSignAlgos[i];
|
||||
byte[] signedHash = nfcCalculateSignature(hash, algo);
|
||||
resultData.addCryptoData(hash, signedHash);
|
||||
}
|
||||
|
@ -1099,9 +1099,9 @@
|
||||
<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_unlock">"Error unlocking master key!"</string>
|
||||
<string name="msg_crt_error_divert">"Certification with NFC is not (yet) supported!"</string>
|
||||
<string name="msg_crt">"Certifying keyrings"</string>
|
||||
<string name="msg_crt_master_fetch">"Fetching certifying master key"</string>
|
||||
<string name="msg_crt_nfc_return">"Returning for NFC input"</string>
|
||||
<string name="msg_crt_save">"Saving certified key %s"</string>
|
||||
<string name="msg_crt_saving">"Saving keyrings"</string>
|
||||
<string name="msg_crt_unlock">"Unlocking master key"</string>
|
||||
|
Loading…
Reference in New Issue
Block a user