Merge pull request #2397 from open-keychain/effective-authkey
Use specialized query exclusively to select authentication key
This commit is contained in:
@@ -48,7 +48,7 @@ import timber.log.Timber;
|
||||
*/
|
||||
public class KeychainDatabase {
|
||||
private static final String DATABASE_NAME = "openkeychain.db";
|
||||
private static final int DATABASE_VERSION = 32;
|
||||
private static final int DATABASE_VERSION = 33;
|
||||
private final SupportSQLiteOpenHelper supportSQLiteOpenHelper;
|
||||
|
||||
private static KeychainDatabase sInstance;
|
||||
@@ -118,6 +118,7 @@ public class KeychainDatabase {
|
||||
db.execSQL(ApiAllowedKeysModel.CREATE_TABLE);
|
||||
db.execSQL(KeysModel.UNIFIEDKEYVIEW);
|
||||
db.execSQL(KeysModel.VALIDKEYSVIEW);
|
||||
db.execSQL(KeysModel.VALIDMASTERKEYSVIEW);
|
||||
db.execSQL(UserPacketsModel.UIDSTATUS);
|
||||
|
||||
db.execSQL("CREATE INDEX keys_by_rank ON keys (" + KeysModel.RANK + ", " + KeysModel.MASTER_KEY_ID + ");");
|
||||
@@ -351,6 +352,9 @@ public class KeychainDatabase {
|
||||
|
||||
case 31:
|
||||
addSubkeyValidFromField(db);
|
||||
|
||||
case 32:
|
||||
recreateUnifiedKeyView(db);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,9 +382,12 @@ public class KeychainDatabase {
|
||||
db.execSQL("DROP VIEW IF EXISTS " + KeysModel.UNIFIEDKEYVIEW_VIEW_NAME);
|
||||
db.execSQL(KeysModel.UNIFIEDKEYVIEW);
|
||||
// noinspection deprecation
|
||||
db.execSQL("DROP VIEW IF EXISTS " + KeysModel.VALIDMASTERKEYS_VIEW_NAME);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + KeysModel.VALIDKEYS_VIEW_NAME);
|
||||
db.execSQL(KeysModel.VALIDKEYSVIEW);
|
||||
// noinspection deprecation
|
||||
db.execSQL("DROP VIEW IF EXISTS " + KeysModel.VALIDMASTERKEYS_VIEW_NAME);
|
||||
db.execSQL(KeysModel.VALIDMASTERKEYSVIEW);
|
||||
// noinspection deprecation
|
||||
db.execSQL("DROP VIEW IF EXISTS " + UserPacketsModel.UIDSTATUS_VIEW_NAME);
|
||||
db.execSQL(UserPacketsModel.UIDSTATUS);
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ public class KeyRepository extends AbstractDao {
|
||||
return mapSingleRowOrThrow(query, SubKey.FACTORY.selectEffectiveSignKeyIdByMasterKeyIdMapper());
|
||||
}
|
||||
|
||||
public long getSecretAuthenticationId(long masterKeyId) throws NotFoundException {
|
||||
public long getEffectiveAuthenticationKeyId(long masterKeyId) throws NotFoundException {
|
||||
SqlDelightQuery query = SubKey.FACTORY.selectEffectiveAuthKeyIdByMasterKeyId(masterKeyId);
|
||||
return mapSingleRowOrThrow(query, SubKey.FACTORY.selectEffectiveAuthKeyIdByMasterKeyIdMapper());
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ public class SshAuthenticationService extends Service {
|
||||
String authSubKeyCurveOid = null;
|
||||
try {
|
||||
// get first usable subkey capable of authentication
|
||||
authSubKeyId = mKeyRepository.getSecretAuthenticationId(masterKeyId);
|
||||
authSubKeyId = mKeyRepository.getEffectiveAuthenticationKeyId(masterKeyId);
|
||||
// needed for encoding the resulting signature
|
||||
authSubKeyAlgorithm = getPublicKey(masterKeyId).getAlgorithm();
|
||||
if (authSubKeyAlgorithm == PublicKeyAlgorithmTags.ECDSA) {
|
||||
@@ -350,12 +350,11 @@ public class SshAuthenticationService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
private Intent getSSHPublicKey(long masterKeyId) throws KeyRepository.NotFoundException, PgpKeyNotFoundException {
|
||||
String sshPublicKeyBlob;
|
||||
|
||||
private Intent getSSHPublicKey(long masterKeyId) throws KeyRepository.NotFoundException {
|
||||
CanonicalizedPublicKey publicKey = getPublicKey(masterKeyId);
|
||||
|
||||
SshPublicKey sshPublicKey = new SshPublicKey(publicKey);
|
||||
String sshPublicKeyBlob;
|
||||
try {
|
||||
sshPublicKeyBlob = sshPublicKey.getEncodedKey();
|
||||
} catch (PgpGeneralException | NoSuchAlgorithmException e) {
|
||||
@@ -368,18 +367,15 @@ public class SshAuthenticationService extends Service {
|
||||
|
||||
private CanonicalizedPublicKey getPublicKey(long masterKeyId) throws NotFoundException {
|
||||
KeyRepository keyRepository = KeyRepository.create(getApplicationContext());
|
||||
UnifiedKeyInfo unifiedKeyInfo = keyRepository.getUnifiedKeyInfo(masterKeyId);
|
||||
if (unifiedKeyInfo == null) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return keyRepository.getCanonicalizedPublicKeyRing(masterKeyId).getPublicKey(unifiedKeyInfo.has_auth_key_int());
|
||||
long authKeyId = keyRepository.getEffectiveAuthenticationKeyId(masterKeyId);
|
||||
return keyRepository.getCanonicalizedPublicKeyRing(masterKeyId).getPublicKey(authKeyId);
|
||||
}
|
||||
|
||||
private String getDescription(long masterKeyId) throws NotFoundException {
|
||||
UnifiedKeyInfo unifiedKeyInfo = mKeyRepository.getUnifiedKeyInfo(masterKeyId);
|
||||
|
||||
String description = "";
|
||||
long authSubKeyId = mKeyRepository.getSecretAuthenticationId(masterKeyId);
|
||||
long authSubKeyId = mKeyRepository.getEffectiveAuthenticationKeyId(masterKeyId);
|
||||
description += unifiedKeyInfo.user_id();
|
||||
description += " (" + Long.toHexString(authSubKeyId) + ")";
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ public class AuthenticationOperation extends BaseOperation<AuthenticationParcel>
|
||||
Long authSubKeyId = data.getAuthenticationSubKeyId();
|
||||
if (authSubKeyId == null) {
|
||||
try { // Get the key id of the authentication key belonging to the master key id
|
||||
authSubKeyId = mKeyRepository.getSecretAuthenticationId(authMasterKeyId);
|
||||
authSubKeyId = mKeyRepository.getEffectiveAuthenticationKeyId(authMasterKeyId);
|
||||
} catch (NotFoundException e) {
|
||||
log.add(LogType.MSG_AUTH_ERROR_KEY_AUTH, indent);
|
||||
return new AuthenticationResult(AuthenticationResult.RESULT_ERROR, log);
|
||||
|
||||
@@ -109,14 +109,14 @@ public class ViewKeyAdvShareFragment extends Fragment {
|
||||
vFingerprintShareButton.setOnClickListener(v -> shareFingerprint(false));
|
||||
vFingerprintClipboardButton.setOnClickListener(v -> shareFingerprint(true));
|
||||
|
||||
vKeyShareButton.setOnClickListener(v -> ShareKeyHelper.shareKey(getActivity(), unifiedKeyInfo));
|
||||
vKeyShareButton.setOnClickListener(v -> ShareKeyHelper.shareKey(getActivity(), unifiedKeyInfo.master_key_id()));
|
||||
|
||||
vKeyClipboardButton.setOnClickListener(v -> ShareKeyHelper.shareKeyToClipboard(getActivity(), unifiedKeyInfo));
|
||||
vKeyClipboardButton.setOnClickListener(v -> ShareKeyHelper.shareKeyToClipboard(getActivity(), unifiedKeyInfo.master_key_id()));
|
||||
|
||||
vKeySafeSlingerButton.setOnClickListener(v -> startSafeSlinger());
|
||||
vKeySshShareButton.setOnClickListener(v -> ShareKeyHelper.shareSshKey(getActivity(), unifiedKeyInfo));
|
||||
vKeySshShareButton.setOnClickListener(v -> ShareKeyHelper.shareSshKey(getActivity(), unifiedKeyInfo.master_key_id()));
|
||||
|
||||
vKeySshClipboardButton.setOnClickListener(v -> ShareKeyHelper.shareSshKeyToClipboard(getActivity(), unifiedKeyInfo));
|
||||
vKeySshClipboardButton.setOnClickListener(v -> ShareKeyHelper.shareSshKeyToClipboard(getActivity(), unifiedKeyInfo.master_key_id()));
|
||||
vKeyUploadButton.setOnClickListener(v -> uploadToKeyserver());
|
||||
|
||||
return view;
|
||||
|
||||
@@ -67,6 +67,8 @@ import android.widget.Toast;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
||||
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||
@@ -74,8 +76,6 @@ import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenConnection;
|
||||
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
|
||||
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
|
||||
@@ -263,8 +263,8 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
||||
|
||||
actionEncryptFile.setOnClickListener(v -> encrypt(false));
|
||||
actionEncryptText.setOnClickListener(v -> encrypt(true));
|
||||
actionShare.setOnClickListener(v -> ShareKeyHelper.shareKey(this, unifiedKeyInfo));
|
||||
actionShareClipboard.setOnClickListener(v -> ShareKeyHelper.shareKeyToClipboard(this, unifiedKeyInfo));
|
||||
actionShare.setOnClickListener(v -> ShareKeyHelper.shareKey(this, masterKeyId));
|
||||
actionShareClipboard.setOnClickListener(v -> ShareKeyHelper.shareKeyToClipboard(this, masterKeyId));
|
||||
|
||||
floatingActionButton.setOnClickListener(v -> {
|
||||
if (unifiedKeyInfo.has_any_secret()) {
|
||||
|
||||
@@ -18,6 +18,12 @@
|
||||
package org.sufficientlysecure.keychain.util;
|
||||
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
@@ -25,9 +31,12 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey;
|
||||
import org.sufficientlysecure.keychain.pgp.SshPublicKey;
|
||||
@@ -37,32 +46,33 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class ShareKeyHelper {
|
||||
|
||||
private static String getKeyContent(UnifiedKeyInfo unifiedKeyInfo, KeyRepository keyRepository)
|
||||
throws KeyRepository.NotFoundException, IOException {
|
||||
|
||||
return keyRepository.getPublicKeyRingAsArmoredString(unifiedKeyInfo.master_key_id());
|
||||
@Nullable
|
||||
private static String getKeyContent(long masterKeyId, KeyRepository keyRepository) throws IOException {
|
||||
try {
|
||||
return keyRepository.getPublicKeyRingAsArmoredString(masterKeyId);
|
||||
} catch (NotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getSshKeyContent(UnifiedKeyInfo unifiedKeyInfo, KeyRepository keyRepository)
|
||||
throws KeyRepository.NotFoundException, PgpGeneralException, NoSuchAlgorithmException {
|
||||
@Nullable
|
||||
private static String getSshKeyContent(long masterKeyId, KeyRepository keyRepository)
|
||||
throws PgpGeneralException, NoSuchAlgorithmException {
|
||||
try {
|
||||
long authSubKeyId = keyRepository.getEffectiveAuthenticationKeyId(masterKeyId);
|
||||
CanonicalizedPublicKey publicKey = keyRepository.getCanonicalizedPublicKeyRing(masterKeyId)
|
||||
.getPublicKey(authSubKeyId);
|
||||
SshPublicKey sshPublicKey = new SshPublicKey(publicKey);
|
||||
|
||||
long authSubKeyId = unifiedKeyInfo.has_auth_key_int();
|
||||
CanonicalizedPublicKey publicKey = keyRepository.getCanonicalizedPublicKeyRing(unifiedKeyInfo.master_key_id())
|
||||
.getPublicKey(authSubKeyId);
|
||||
SshPublicKey sshPublicKey = new SshPublicKey(publicKey);
|
||||
|
||||
return sshPublicKey.getEncodedKey();
|
||||
return sshPublicKey.getEncodedKey();
|
||||
} catch (NotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void shareKeyIntent(Activity activity, UnifiedKeyInfo unifiedKeyInfo, String content) throws IOException {
|
||||
private static void shareKeyIntent(Activity activity, long masterKeyId, String content) throws IOException {
|
||||
// let user choose application
|
||||
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
||||
sendIntent.setType(Constants.MIME_TYPE_KEYS);
|
||||
@@ -73,6 +83,8 @@ public class ShareKeyHelper {
|
||||
try {
|
||||
TemporaryFileProvider shareFileProv = new TemporaryFileProvider();
|
||||
|
||||
UnifiedKeyInfo unifiedKeyInfo = KeyRepository.create(activity).getUnifiedKeyInfo(masterKeyId);
|
||||
|
||||
String filename;
|
||||
if (unifiedKeyInfo.name() != null) {
|
||||
filename = unifiedKeyInfo.name();
|
||||
@@ -113,63 +125,63 @@ public class ShareKeyHelper {
|
||||
Notify.create(activity, R.string.key_copied_to_clipboard, Notify.Style.OK).show();
|
||||
}
|
||||
|
||||
private static void shareKey(Activity activity, UnifiedKeyInfo unifiedKeyInfo, boolean toClipboard) {
|
||||
if (activity == null || unifiedKeyInfo == null) {
|
||||
private static void shareKey(Activity activity, long masterKeyId, boolean toClipboard) {
|
||||
if (activity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String content = getKeyContent(unifiedKeyInfo, KeyRepository.create(activity));
|
||||
String content = getKeyContent(masterKeyId, KeyRepository.create(activity));
|
||||
if (content == null) {
|
||||
Notify.create(activity, R.string.error_key_not_found, Notify.Style.ERROR).show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (toClipboard) {
|
||||
shareKeyToClipBoard(activity, content);
|
||||
} else {
|
||||
shareKeyIntent(activity, unifiedKeyInfo, content);
|
||||
shareKeyIntent(activity, masterKeyId, content);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Timber.e(e, "error processing key!");
|
||||
Notify.create(activity, R.string.error_key_processing, Notify.Style.ERROR).show();
|
||||
} catch (KeyRepository.NotFoundException e) {
|
||||
Timber.e(e, "key not found!");
|
||||
Notify.create(activity, R.string.error_key_not_found, Notify.Style.ERROR).show();
|
||||
}
|
||||
}
|
||||
|
||||
private static void shareSshKey(Activity activity, UnifiedKeyInfo unifiedKeyInfo, boolean toClipboard) {
|
||||
if (activity == null || unifiedKeyInfo == null) {
|
||||
return;
|
||||
}
|
||||
if (!unifiedKeyInfo.has_auth_key()) {
|
||||
Notify.create(activity, R.string.authentication_subkey_not_found, Notify.Style.ERROR).show();
|
||||
private static void shareSshKey(Activity activity, long masterKeyId, boolean toClipboard) {
|
||||
if (activity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String content = getSshKeyContent(unifiedKeyInfo, KeyRepository.create(activity));
|
||||
String content = getSshKeyContent(masterKeyId, KeyRepository.create(activity));
|
||||
if (content == null) {
|
||||
Notify.create(activity, R.string.authentication_subkey_not_found, Notify.Style.ERROR).show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (toClipboard) {
|
||||
shareKeyToClipBoard(activity, content);
|
||||
} else {
|
||||
shareKeyIntent(activity, unifiedKeyInfo, content);
|
||||
shareKeyIntent(activity, masterKeyId, content);
|
||||
}
|
||||
} catch (PgpGeneralException | IOException | NoSuchAlgorithmException e) {
|
||||
Timber.e(e, "error processing key!");
|
||||
Notify.create(activity, R.string.error_key_processing, Notify.Style.ERROR).show();
|
||||
} catch (KeyRepository.NotFoundException e) {
|
||||
Timber.e(e, "key not found!");
|
||||
Notify.create(activity, R.string.error_key_not_found, Notify.Style.ERROR).show();
|
||||
}
|
||||
}
|
||||
|
||||
public static void shareKeyToClipboard(Activity activity, UnifiedKeyInfo unifiedKeyInfo) {
|
||||
shareKey(activity, unifiedKeyInfo, true);
|
||||
public static void shareKeyToClipboard(Activity activity, long masterKeyId) {
|
||||
shareKey(activity, masterKeyId, true);
|
||||
}
|
||||
public static void shareKey(Activity activity, UnifiedKeyInfo unifiedKeyInfo) {
|
||||
shareKey(activity, unifiedKeyInfo, false);
|
||||
public static void shareKey(Activity activity, long masterKeyId) {
|
||||
shareKey(activity, masterKeyId, false);
|
||||
}
|
||||
public static void shareSshKey(Activity activity, UnifiedKeyInfo unifiedKeyInfo) {
|
||||
shareSshKey(activity, unifiedKeyInfo, false);
|
||||
public static void shareSshKey(Activity activity, long masterKeyId) {
|
||||
shareSshKey(activity, masterKeyId, false);
|
||||
}
|
||||
public static void shareSshKeyToClipboard(Activity activity, UnifiedKeyInfo unifiedKeyInfo) {
|
||||
shareSshKey(activity, unifiedKeyInfo, true);
|
||||
public static void shareSshKeyToClipboard(Activity activity, long masterKeyId) {
|
||||
shareSshKey(activity, masterKeyId, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user