Merge branch 'master' of github.com:open-keychain/open-keychain

This commit is contained in:
Dominik Schürmann 2014-04-17 17:55:52 +02:00
commit a67854ca6a
9 changed files with 182 additions and 155 deletions

View File

@ -67,6 +67,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.security.SignatureException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
@ -410,11 +411,18 @@ public class PgpDecryptVerify {
// go through all signatures
// and find out for which signature we have a key in our database
Long masterKeyId = null;
String primaryUserId = null;
for (int i = 0; i < sigList.size(); ++i) {
try {
Uri uri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(
Long.toString(sigList.get(i).getKeyID()));
masterKeyId = mProviderHelper.getMasterKeyId(uri);
Map<String, Object> data = mProviderHelper.getGenericData(uri,
new String[] { KeyRings.MASTER_KEY_ID, KeyRings.USER_ID },
new int[] { ProviderHelper.FIELD_TYPE_INTEGER,
ProviderHelper.FIELD_TYPE_STRING }
);
masterKeyId = (Long) data.get(KeyRings.MASTER_KEY_ID);
primaryUserId = (String) data.get(KeyRings.USER_ID);
signatureIndex = i;
} catch (ProviderHelper.NotFoundException e) {
Log.d(Constants.TAG, "key not found!");
@ -439,9 +447,8 @@ public class PgpDecryptVerify {
signatureResultBuilder.signatureAvailable(true);
signatureResultBuilder.knownKey(true);
// TODO: uses the first user id not primary user id
signatureResultBuilder.userId(PgpKeyHelper.getMainUserId(publicKeyRing.getPublicKey()));
signatureResultBuilder.keyId(publicKeyRing.getPublicKey().getKeyID());
signatureResultBuilder.userId(primaryUserId);
signatureResultBuilder.keyId(masterKeyId);
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider()
@ -449,11 +456,16 @@ public class PgpDecryptVerify {
signature.init(contentVerifierBuilderProvider, signatureKey);
// get certification status of this key
Object data = mProviderHelper.getGenericData(
KeychainContract.KeyRings.buildUnifiedKeyRingUri(Long.toString(masterKeyId)),
KeyRings.VERIFIED,
ProviderHelper.FIELD_TYPE_INTEGER);
boolean isSignatureKeyCertified = ((Long) data > 0);
boolean isSignatureKeyCertified;
try {
Object data = mProviderHelper.getGenericData(
KeychainContract.KeyRings.buildUnifiedKeyRingUri(Long.toString(masterKeyId)),
KeyRings.VERIFIED,
ProviderHelper.FIELD_TYPE_INTEGER);
isSignatureKeyCertified = ((Long) data > 0);
} catch (ProviderHelper.NotFoundException e) {
isSignatureKeyCertified = false;
}
signatureResultBuilder.signatureKeyCertified(isSignatureKeyCertified);
} else {
// no key in our database -> return "unknown pub key" status including the first key id
@ -608,12 +620,19 @@ public class PgpDecryptVerify {
// go through all signatures
// and find out for which signature we have a key in our database
Long masterKeyId = null;
String primaryUserId = null;
int signatureIndex = 0;
for (int i = 0; i < sigList.size(); ++i) {
try {
Uri uri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(
Long.toString(sigList.get(i).getKeyID()));
masterKeyId = mProviderHelper.getMasterKeyId(uri);
Map<String, Object> data = mProviderHelper.getGenericData(uri,
new String[] { KeyRings.MASTER_KEY_ID, KeyRings.USER_ID },
new int[] { ProviderHelper.FIELD_TYPE_INTEGER,
ProviderHelper.FIELD_TYPE_STRING }
);
masterKeyId = (Long) data.get(KeyRings.MASTER_KEY_ID);
primaryUserId = (String) data.get(KeyRings.USER_ID);
signatureIndex = i;
} catch (ProviderHelper.NotFoundException e) {
Log.d(Constants.TAG, "key not found!");
@ -640,9 +659,8 @@ public class PgpDecryptVerify {
signatureResultBuilder.signatureAvailable(true);
signatureResultBuilder.knownKey(true);
// TODO: uses the first user id not primary user id
signatureResultBuilder.userId(PgpKeyHelper.getMainUserId(publicKeyRing.getPublicKey()));
signatureResultBuilder.keyId(publicKeyRing.getPublicKey().getKeyID());
signatureResultBuilder.userId(primaryUserId);
signatureResultBuilder.keyId(masterKeyId);
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider()
@ -650,11 +668,16 @@ public class PgpDecryptVerify {
signature.init(contentVerifierBuilderProvider, signatureKey);
// get certification status of this key
Object data = mProviderHelper.getGenericData(
KeychainContract.KeyRings.buildUnifiedKeyRingUri(Long.toString(masterKeyId)),
KeyRings.VERIFIED,
ProviderHelper.FIELD_TYPE_INTEGER);
boolean isSignatureKeyCertified = ((Long) data > 0);
boolean isSignatureKeyCertified;
try {
Object data = mProviderHelper.getGenericData(
KeychainContract.KeyRings.buildUnifiedKeyRingUri(Long.toString(masterKeyId)),
KeyRings.VERIFIED,
ProviderHelper.FIELD_TYPE_INTEGER);
isSignatureKeyCertified = ((Long) data > 0);
} catch (ProviderHelper.NotFoundException e) {
isSignatureKeyCertified = false;
}
signatureResultBuilder.signatureKeyCertified(isSignatureKeyCertified);
} else {
// no key in our database -> return "unknown pub key" status including the first key id

View File

@ -225,38 +225,6 @@ public class PgpKeyHelper {
return signingKeys.get(0);
}
@SuppressWarnings("unchecked")
public static String getMainUserId(PGPPublicKey key) {
for (String userId : new IterableIterator<String>(key.getUserIDs())) {
return userId;
}
return null;
}
@SuppressWarnings("unchecked")
public static String getMainUserId(PGPSecretKey key) {
for (String userId : new IterableIterator<String>(key.getUserIDs())) {
return userId;
}
return null;
}
public static String getMainUserIdSafe(Context context, PGPPublicKey key) {
String userId = getMainUserId(key);
if (userId == null || userId.equals("")) {
userId = context.getString(R.string.user_id_no_name);
}
return userId;
}
public static String getMainUserIdSafe(Context context, PGPSecretKey key) {
String userId = getMainUserId(key);
if (userId == null || userId.equals("")) {
userId = context.getString(R.string.user_id_no_name);
}
return userId;
}
public static int getKeyUsage(PGPSecretKey key) {
return getKeyUsage(key.getPublicKey());
}

View File

@ -42,6 +42,7 @@ import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
@ -281,9 +282,12 @@ public class PgpSignEncrypt {
PGPSecretKey signingKey = null;
PGPSecretKeyRing signingKeyRing = null;
PGPPrivateKey signaturePrivateKey = null;
String signingUserId = null;
if (enableSignature) {
try {
signingKeyRing = mProviderHelper.getPGPSecretKeyRing(mSignatureMasterKeyId);
signingUserId = (String) mProviderHelper.getUnifiedData(mSignatureMasterKeyId,
KeychainContract.KeyRings.USER_ID, ProviderHelper.FIELD_TYPE_STRING);
} catch (ProviderHelper.NotFoundException e) {
throw new NoSigningKeyException();
}
@ -369,9 +373,8 @@ public class PgpSignEncrypt {
signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
signatureGenerator.init(signatureType, signaturePrivateKey);
String userId = PgpKeyHelper.getMainUserId(signingKeyRing.getSecretKey());
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
spGen.setSignerUserID(false, userId);
spGen.setSignerUserID(false, signingUserId);
signatureGenerator.setHashedSubpackets(spGen.generate());
}
}

View File

@ -91,11 +91,12 @@ public class ProviderHelper {
public static final int FIELD_TYPE_STRING = 4;
public static final int FIELD_TYPE_BLOB = 5;
public Object getGenericData(Uri uri, String column, int type) {
public Object getGenericData(Uri uri, String column, int type) throws NotFoundException {
return getGenericData(uri, new String[]{column}, new int[]{type}).get(column);
}
public HashMap<String, Object> getGenericData(Uri uri, String[] proj, int[] types) {
public HashMap<String, Object> getGenericData(Uri uri, String[] proj, int[] types)
throws NotFoundException {
Cursor cursor = mContentResolver.query(uri, proj, null, null, null);
HashMap<String, Object> result = new HashMap<String, Object>(proj.length);
@ -130,11 +131,13 @@ public class ProviderHelper {
return result;
}
public Object getUnifiedData(long masterKeyId, String column, int type) {
public Object getUnifiedData(long masterKeyId, String column, int type)
throws NotFoundException {
return getUnifiedData(masterKeyId, new String[]{column}, new int[]{type}).get(column);
}
public HashMap<String, Object> getUnifiedData(long masterKeyId, String[] proj, int[] types) {
public HashMap<String, Object> getUnifiedData(long masterKeyId, String[] proj, int[] types)
throws NotFoundException {
return getGenericData(KeyRings.buildUnifiedKeyRingUri(Long.toString(masterKeyId)), proj, types);
}

View File

@ -201,15 +201,20 @@ public class EncryptAsymmetricFragment extends Fragment {
mMainUserIdRest.setText("");
} else {
// See if we can get a user_id from a unified query
String userIdResult = (String) mProviderHelper.getUnifiedData(
mSecretKeyId, KeyRings.USER_ID, ProviderHelper.FIELD_TYPE_STRING);
String[] userId = PgpKeyHelper.splitUserId(userIdResult);
if (userId[0] != null) {
String[] userId;
try {
String userIdResult = (String) mProviderHelper.getUnifiedData(
mSecretKeyId, KeyRings.USER_ID, ProviderHelper.FIELD_TYPE_STRING);
userId = PgpKeyHelper.splitUserId(userIdResult);
} catch (ProviderHelper.NotFoundException e) {
userId = null;
}
if (userId != null && userId[0] != null) {
mMainUserId.setText(userId[0]);
} else {
mMainUserId.setText(getResources().getString(R.string.user_id_no_name));
}
if (userId[1] != null) {
if (userId != null && userId[1] != null) {
mMainUserIdRest.setText(userId[1]);
} else {
mMainUserIdRest.setText("");

View File

@ -127,48 +127,54 @@ public class ViewKeyActivity extends ActionBarActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent homeIntent = new Intent(this, KeyListActivity.class);
homeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(homeIntent);
return true;
case R.id.menu_key_view_update:
updateFromKeyserver(mDataUri, mProviderHelper);
return true;
case R.id.menu_key_view_export_keyserver:
uploadToKeyserver(mDataUri);
return true;
case R.id.menu_key_view_export_file:
exportToFile(mDataUri, mExportHelper, mProviderHelper);
return true;
case R.id.menu_key_view_share_default_fingerprint:
shareKey(mDataUri, true, mProviderHelper);
return true;
case R.id.menu_key_view_share_default:
shareKey(mDataUri, false, mProviderHelper);
return true;
case R.id.menu_key_view_share_qr_code_fingerprint:
shareKeyQrCode(mDataUri, true);
return true;
case R.id.menu_key_view_share_qr_code:
shareKeyQrCode(mDataUri, false);
return true;
case R.id.menu_key_view_share_nfc:
shareNfc();
return true;
case R.id.menu_key_view_share_clipboard:
copyToClipboard(mDataUri, mProviderHelper);
return true;
case R.id.menu_key_view_delete: {
deleteKey(mDataUri, mExportHelper);
return true;
try {
switch (item.getItemId()) {
case android.R.id.home:
Intent homeIntent = new Intent(this, KeyListActivity.class);
homeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(homeIntent);
return true;
case R.id.menu_key_view_update:
updateFromKeyserver(mDataUri, mProviderHelper);
return true;
case R.id.menu_key_view_export_keyserver:
uploadToKeyserver(mDataUri);
return true;
case R.id.menu_key_view_export_file:
exportToFile(mDataUri, mExportHelper, mProviderHelper);
return true;
case R.id.menu_key_view_share_default_fingerprint:
shareKey(mDataUri, true, mProviderHelper);
return true;
case R.id.menu_key_view_share_default:
shareKey(mDataUri, false, mProviderHelper);
return true;
case R.id.menu_key_view_share_qr_code_fingerprint:
shareKeyQrCode(mDataUri, true);
return true;
case R.id.menu_key_view_share_qr_code:
shareKeyQrCode(mDataUri, false);
return true;
case R.id.menu_key_view_share_nfc:
shareNfc();
return true;
case R.id.menu_key_view_share_clipboard:
copyToClipboard(mDataUri, mProviderHelper);
return true;
case R.id.menu_key_view_delete: {
deleteKey(mDataUri, mExportHelper);
return true;
}
}
} catch (ProviderHelper.NotFoundException e) {
AppMsg.makeText(this, R.string.error_key_not_found, AppMsg.STYLE_ALERT).show();
Log.e(Constants.TAG, "Key not found", e);
}
return super.onOptionsItemSelected(item);
}
private void exportToFile(Uri dataUri, ExportHelper exportHelper, ProviderHelper providerHelper) {
private void exportToFile(Uri dataUri, ExportHelper exportHelper, ProviderHelper providerHelper)
throws ProviderHelper.NotFoundException {
Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri);
HashMap<String, Object> data = providerHelper.getGenericData(
@ -183,13 +189,14 @@ public class ViewKeyActivity extends ActionBarActivity {
);
}
private void uploadToKeyserver(Uri dataUri) {
private void uploadToKeyserver(Uri dataUri) throws ProviderHelper.NotFoundException {
Intent uploadIntent = new Intent(this, UploadKeyActivity.class);
uploadIntent.setData(dataUri);
startActivityForResult(uploadIntent, 0);
}
private void updateFromKeyserver(Uri dataUri, ProviderHelper providerHelper) {
private void updateFromKeyserver(Uri dataUri, ProviderHelper providerHelper)
throws ProviderHelper.NotFoundException {
byte[] blob = (byte[]) providerHelper.getGenericData(
KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri),
KeychainContract.Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB);
@ -202,7 +209,8 @@ public class ViewKeyActivity extends ActionBarActivity {
startActivityForResult(queryIntent, REQUEST_CODE_LOOKUP_KEY);
}
private void shareKey(Uri dataUri, boolean fingerprintOnly, ProviderHelper providerHelper) {
private void shareKey(Uri dataUri, boolean fingerprintOnly, ProviderHelper providerHelper)
throws ProviderHelper.NotFoundException {
String content = null;
if (fingerprintOnly) {
byte[] data = (byte[]) providerHelper.getGenericData(

View File

@ -89,18 +89,30 @@ public class DeleteKeyDialogFragment extends DialogFragment {
if (masterKeyIds.length == 1) {
long masterKeyId = masterKeyIds[0];
HashMap<String, Object> data = new ProviderHelper(activity).getUnifiedData(masterKeyId, new String[]{
KeyRings.USER_ID,
KeyRings.HAS_ANY_SECRET
}, new int[]{ProviderHelper.FIELD_TYPE_STRING, ProviderHelper.FIELD_TYPE_INTEGER});
String userId = (String) data.get(KeyRings.USER_ID);
boolean hasSecret = ((Long) data.get(KeyRings.HAS_ANY_SECRET)) == 1;
try {
HashMap<String, Object> data = new ProviderHelper(activity).getUnifiedData(
masterKeyId, new String[]{
KeyRings.USER_ID,
KeyRings.HAS_ANY_SECRET
}, new int[]{
ProviderHelper.FIELD_TYPE_STRING,
ProviderHelper.FIELD_TYPE_INTEGER
}
);
String userId = (String) data.get(KeyRings.USER_ID);
boolean hasSecret = ((Long) data.get(KeyRings.HAS_ANY_SECRET)) == 1;
// Set message depending on which key it is.
mMainMessage.setText(getString(
hasSecret ? R.string.secret_key_deletion_confirmation
: R.string.public_key_deletetion_confirmation,
userId));
// Set message depending on which key it is.
mMainMessage.setText(getString(
hasSecret ? R.string.secret_key_deletion_confirmation
: R.string.public_key_deletetion_confirmation,
userId
));
} catch (ProviderHelper.NotFoundException e) {
sendMessageToHandler(MESSAGE_ERROR, null);
dismiss();
return null;
}
} else {
mMainMessage.setText(R.string.key_deletion_confirmation_multi);
}

View File

@ -50,6 +50,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.util.Log;
@ -134,13 +135,17 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
alert.setTitle(R.string.title_authentication);
final PGPSecretKey secretKey;
final String userId;
if (secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none) {
secretKey = null;
alert.setMessage(R.string.passphrase_for_symmetric_encryption);
} else {
try {
secretKey = new ProviderHelper(activity).getPGPSecretKeyRing(secretKeyId).getSecretKey();
ProviderHelper helper = new ProviderHelper(activity);
secretKey = helper.getPGPSecretKeyRing(secretKeyId).getSecretKey();
userId = (String) helper.getUnifiedData(secretKeyId,
KeychainContract.KeyRings.USER_ID, ProviderHelper.FIELD_TYPE_STRING);
} catch (ProviderHelper.NotFoundException e) {
alert.setTitle(R.string.title_key_not_found);
alert.setMessage(getString(R.string.key_not_found, secretKeyId));
@ -154,8 +159,6 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
return alert.create();
}
String userId = PgpKeyHelper.getMainUserIdSafe(activity, secretKey);
Log.d(Constants.TAG, "User id: '" + userId + "'");
alert.setMessage(getString(R.string.passphrase_for, userId));
}

View File

@ -93,48 +93,50 @@ public class ShareQrCodeDialogFragment extends DialogFragment {
ProviderHelper providerHelper = new ProviderHelper(getActivity());
String content = null;
if (mFingerprintOnly) {
alert.setPositiveButton(R.string.btn_okay, null);
try {
if (mFingerprintOnly) {
alert.setPositiveButton(R.string.btn_okay, null);
byte[] blob = (byte[]) providerHelper.getGenericData(
KeyRings.buildUnifiedKeyRingUri(dataUri),
KeyRings.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB);
if (blob == null) {
Log.e(Constants.TAG, "key not found!");
AppMsg.makeText(getActivity(), R.string.error_key_not_found, AppMsg.STYLE_ALERT).show();
return null;
byte[] blob = (byte[]) providerHelper.getGenericData(
KeyRings.buildUnifiedKeyRingUri(dataUri),
KeyRings.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB);
if (blob == null) {
Log.e(Constants.TAG, "key not found!");
AppMsg.makeText(getActivity(), R.string.error_key_not_found, AppMsg.STYLE_ALERT).show();
return null;
}
String fingerprint = PgpKeyHelper.convertFingerprintToHex(blob);
mText.setText(getString(R.string.share_qr_code_dialog_fingerprint_text) + " " + fingerprint);
content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint;
setQrCode(content);
} else {
mText.setText(R.string.share_qr_code_dialog_start);
try {
Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri);
content = providerHelper.getKeyRingAsArmoredString(uri);
} catch (IOException e) {
Log.e(Constants.TAG, "error processing key!", e);
AppMsg.makeText(getActivity(), R.string.error_invalid_data, AppMsg.STYLE_ALERT).show();
return null;
}
// OnClickListener are set in onResume to prevent automatic dismissing of Dialogs
// http://bit.ly/O5vfaR
alert.setPositiveButton(R.string.btn_next, null);
alert.setNegativeButton(android.R.string.cancel, null);
mContentList = splitString(content, 1000);
// start with first
mCounter = 0;
updatePartsQrCode();
}
String fingerprint = PgpKeyHelper.convertFingerprintToHex(blob);
mText.setText(getString(R.string.share_qr_code_dialog_fingerprint_text) + " " + fingerprint);
content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint;
setQrCode(content);
} else {
mText.setText(R.string.share_qr_code_dialog_start);
try {
Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri);
content = providerHelper.getKeyRingAsArmoredString(uri);
} catch (IOException e) {
Log.e(Constants.TAG, "error processing key!", e);
AppMsg.makeText(getActivity(), R.string.error_invalid_data, AppMsg.STYLE_ALERT).show();
return null;
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
AppMsg.makeText(getActivity(), R.string.error_key_not_found, AppMsg.STYLE_ALERT).show();
return null;
}
// OnClickListener are set in onResume to prevent automatic dismissing of Dialogs
// http://bit.ly/O5vfaR
alert.setPositiveButton(R.string.btn_next, null);
alert.setNegativeButton(android.R.string.cancel, null);
mContentList = splitString(content, 1000);
// start with first
mCounter = 0;
updatePartsQrCode();
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
AppMsg.makeText(getActivity(), R.string.error_key_not_found, AppMsg.STYLE_ALERT).show();
return null;
}
return alert.create();