Use specialized query exclusively to select authentication key
This commit is contained in:
parent
5d28cef81a
commit
400db49e75
|
@ -48,7 +48,7 @@ import timber.log.Timber;
|
||||||
*/
|
*/
|
||||||
public class KeychainDatabase {
|
public class KeychainDatabase {
|
||||||
private static final String DATABASE_NAME = "openkeychain.db";
|
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 final SupportSQLiteOpenHelper supportSQLiteOpenHelper;
|
||||||
|
|
||||||
private static KeychainDatabase sInstance;
|
private static KeychainDatabase sInstance;
|
||||||
|
@ -118,6 +118,7 @@ public class KeychainDatabase {
|
||||||
db.execSQL(ApiAllowedKeysModel.CREATE_TABLE);
|
db.execSQL(ApiAllowedKeysModel.CREATE_TABLE);
|
||||||
db.execSQL(KeysModel.UNIFIEDKEYVIEW);
|
db.execSQL(KeysModel.UNIFIEDKEYVIEW);
|
||||||
db.execSQL(KeysModel.VALIDKEYSVIEW);
|
db.execSQL(KeysModel.VALIDKEYSVIEW);
|
||||||
|
db.execSQL(KeysModel.VALIDMASTERKEYSVIEW);
|
||||||
db.execSQL(UserPacketsModel.UIDSTATUS);
|
db.execSQL(UserPacketsModel.UIDSTATUS);
|
||||||
|
|
||||||
db.execSQL("CREATE INDEX keys_by_rank ON keys (" + KeysModel.RANK + ", " + KeysModel.MASTER_KEY_ID + ");");
|
db.execSQL("CREATE INDEX keys_by_rank ON keys (" + KeysModel.RANK + ", " + KeysModel.MASTER_KEY_ID + ");");
|
||||||
|
@ -351,6 +352,9 @@ public class KeychainDatabase {
|
||||||
|
|
||||||
case 31:
|
case 31:
|
||||||
addSubkeyValidFromField(db);
|
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("DROP VIEW IF EXISTS " + KeysModel.UNIFIEDKEYVIEW_VIEW_NAME);
|
||||||
db.execSQL(KeysModel.UNIFIEDKEYVIEW);
|
db.execSQL(KeysModel.UNIFIEDKEYVIEW);
|
||||||
// noinspection deprecation
|
// 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);
|
db.execSQL(KeysModel.VALIDKEYSVIEW);
|
||||||
// noinspection deprecation
|
// 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("DROP VIEW IF EXISTS " + UserPacketsModel.UIDSTATUS_VIEW_NAME);
|
||||||
db.execSQL(UserPacketsModel.UIDSTATUS);
|
db.execSQL(UserPacketsModel.UIDSTATUS);
|
||||||
|
|
||||||
|
|
|
@ -242,7 +242,7 @@ public class KeyRepository extends AbstractDao {
|
||||||
return mapSingleRowOrThrow(query, SubKey.FACTORY.selectEffectiveSignKeyIdByMasterKeyIdMapper());
|
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);
|
SqlDelightQuery query = SubKey.FACTORY.selectEffectiveAuthKeyIdByMasterKeyId(masterKeyId);
|
||||||
return mapSingleRowOrThrow(query, SubKey.FACTORY.selectEffectiveAuthKeyIdByMasterKeyIdMapper());
|
return mapSingleRowOrThrow(query, SubKey.FACTORY.selectEffectiveAuthKeyIdByMasterKeyIdMapper());
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ public class SshAuthenticationService extends Service {
|
||||||
String authSubKeyCurveOid = null;
|
String authSubKeyCurveOid = null;
|
||||||
try {
|
try {
|
||||||
// get first usable subkey capable of authentication
|
// get first usable subkey capable of authentication
|
||||||
authSubKeyId = mKeyRepository.getSecretAuthenticationId(masterKeyId);
|
authSubKeyId = mKeyRepository.getEffectiveAuthenticationKeyId(masterKeyId);
|
||||||
// needed for encoding the resulting signature
|
// needed for encoding the resulting signature
|
||||||
authSubKeyAlgorithm = getPublicKey(masterKeyId).getAlgorithm();
|
authSubKeyAlgorithm = getPublicKey(masterKeyId).getAlgorithm();
|
||||||
if (authSubKeyAlgorithm == PublicKeyAlgorithmTags.ECDSA) {
|
if (authSubKeyAlgorithm == PublicKeyAlgorithmTags.ECDSA) {
|
||||||
|
@ -350,12 +350,11 @@ public class SshAuthenticationService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Intent getSSHPublicKey(long masterKeyId) throws KeyRepository.NotFoundException, PgpKeyNotFoundException {
|
private Intent getSSHPublicKey(long masterKeyId) throws KeyRepository.NotFoundException {
|
||||||
String sshPublicKeyBlob;
|
|
||||||
|
|
||||||
CanonicalizedPublicKey publicKey = getPublicKey(masterKeyId);
|
CanonicalizedPublicKey publicKey = getPublicKey(masterKeyId);
|
||||||
|
|
||||||
SshPublicKey sshPublicKey = new SshPublicKey(publicKey);
|
SshPublicKey sshPublicKey = new SshPublicKey(publicKey);
|
||||||
|
String sshPublicKeyBlob;
|
||||||
try {
|
try {
|
||||||
sshPublicKeyBlob = sshPublicKey.getEncodedKey();
|
sshPublicKeyBlob = sshPublicKey.getEncodedKey();
|
||||||
} catch (PgpGeneralException | NoSuchAlgorithmException e) {
|
} catch (PgpGeneralException | NoSuchAlgorithmException e) {
|
||||||
|
@ -368,18 +367,15 @@ public class SshAuthenticationService extends Service {
|
||||||
|
|
||||||
private CanonicalizedPublicKey getPublicKey(long masterKeyId) throws NotFoundException {
|
private CanonicalizedPublicKey getPublicKey(long masterKeyId) throws NotFoundException {
|
||||||
KeyRepository keyRepository = KeyRepository.create(getApplicationContext());
|
KeyRepository keyRepository = KeyRepository.create(getApplicationContext());
|
||||||
UnifiedKeyInfo unifiedKeyInfo = keyRepository.getUnifiedKeyInfo(masterKeyId);
|
long authKeyId = keyRepository.getEffectiveAuthenticationKeyId(masterKeyId);
|
||||||
if (unifiedKeyInfo == null) {
|
return keyRepository.getCanonicalizedPublicKeyRing(masterKeyId).getPublicKey(authKeyId);
|
||||||
throw new NotFoundException();
|
|
||||||
}
|
|
||||||
return keyRepository.getCanonicalizedPublicKeyRing(masterKeyId).getPublicKey(unifiedKeyInfo.has_auth_key_int());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getDescription(long masterKeyId) throws NotFoundException {
|
private String getDescription(long masterKeyId) throws NotFoundException {
|
||||||
UnifiedKeyInfo unifiedKeyInfo = mKeyRepository.getUnifiedKeyInfo(masterKeyId);
|
UnifiedKeyInfo unifiedKeyInfo = mKeyRepository.getUnifiedKeyInfo(masterKeyId);
|
||||||
|
|
||||||
String description = "";
|
String description = "";
|
||||||
long authSubKeyId = mKeyRepository.getSecretAuthenticationId(masterKeyId);
|
long authSubKeyId = mKeyRepository.getEffectiveAuthenticationKeyId(masterKeyId);
|
||||||
description += unifiedKeyInfo.user_id();
|
description += unifiedKeyInfo.user_id();
|
||||||
description += " (" + Long.toHexString(authSubKeyId) + ")";
|
description += " (" + Long.toHexString(authSubKeyId) + ")";
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ public class AuthenticationOperation extends BaseOperation<AuthenticationParcel>
|
||||||
Long authSubKeyId = data.getAuthenticationSubKeyId();
|
Long authSubKeyId = data.getAuthenticationSubKeyId();
|
||||||
if (authSubKeyId == null) {
|
if (authSubKeyId == null) {
|
||||||
try { // Get the key id of the authentication key belonging to the master key id
|
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) {
|
} catch (NotFoundException e) {
|
||||||
log.add(LogType.MSG_AUTH_ERROR_KEY_AUTH, indent);
|
log.add(LogType.MSG_AUTH_ERROR_KEY_AUTH, indent);
|
||||||
return new AuthenticationResult(AuthenticationResult.RESULT_ERROR, log);
|
return new AuthenticationResult(AuthenticationResult.RESULT_ERROR, log);
|
||||||
|
|
|
@ -109,14 +109,14 @@ public class ViewKeyAdvShareFragment extends Fragment {
|
||||||
vFingerprintShareButton.setOnClickListener(v -> shareFingerprint(false));
|
vFingerprintShareButton.setOnClickListener(v -> shareFingerprint(false));
|
||||||
vFingerprintClipboardButton.setOnClickListener(v -> shareFingerprint(true));
|
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());
|
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());
|
vKeyUploadButton.setOnClickListener(v -> uploadToKeyserver());
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
|
|
|
@ -67,6 +67,8 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
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.HkpKeyserverAddress;
|
||||||
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
||||||
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
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.ImportKeyResult;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
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.securitytoken.SecurityTokenConnection;
|
||||||
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
|
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
|
||||||
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
|
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
|
||||||
|
@ -263,8 +263,8 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
||||||
|
|
||||||
actionEncryptFile.setOnClickListener(v -> encrypt(false));
|
actionEncryptFile.setOnClickListener(v -> encrypt(false));
|
||||||
actionEncryptText.setOnClickListener(v -> encrypt(true));
|
actionEncryptText.setOnClickListener(v -> encrypt(true));
|
||||||
actionShare.setOnClickListener(v -> ShareKeyHelper.shareKey(this, unifiedKeyInfo));
|
actionShare.setOnClickListener(v -> ShareKeyHelper.shareKey(this, masterKeyId));
|
||||||
actionShareClipboard.setOnClickListener(v -> ShareKeyHelper.shareKeyToClipboard(this, unifiedKeyInfo));
|
actionShareClipboard.setOnClickListener(v -> ShareKeyHelper.shareKeyToClipboard(this, masterKeyId));
|
||||||
|
|
||||||
floatingActionButton.setOnClickListener(v -> {
|
floatingActionButton.setOnClickListener(v -> {
|
||||||
if (unifiedKeyInfo.has_any_secret()) {
|
if (unifiedKeyInfo.has_any_secret()) {
|
||||||
|
|
|
@ -18,6 +18,12 @@
|
||||||
package org.sufficientlysecure.keychain.util;
|
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.app.Activity;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
|
@ -25,9 +31,12 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.daos.KeyRepository;
|
import org.sufficientlysecure.keychain.daos.KeyRepository;
|
||||||
|
import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException;
|
||||||
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey;
|
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey;
|
||||||
import org.sufficientlysecure.keychain.pgp.SshPublicKey;
|
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 org.sufficientlysecure.keychain.ui.util.Notify;
|
||||||
import timber.log.Timber;
|
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 {
|
public class ShareKeyHelper {
|
||||||
|
|
||||||
private static String getKeyContent(UnifiedKeyInfo unifiedKeyInfo, KeyRepository keyRepository)
|
@Nullable
|
||||||
throws KeyRepository.NotFoundException, IOException {
|
private static String getKeyContent(long masterKeyId, KeyRepository keyRepository) throws IOException {
|
||||||
|
try {
|
||||||
return keyRepository.getPublicKeyRingAsArmoredString(unifiedKeyInfo.master_key_id());
|
return keyRepository.getPublicKeyRingAsArmoredString(masterKeyId);
|
||||||
|
} catch (NotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getSshKeyContent(UnifiedKeyInfo unifiedKeyInfo, KeyRepository keyRepository)
|
@Nullable
|
||||||
throws KeyRepository.NotFoundException, PgpGeneralException, NoSuchAlgorithmException {
|
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();
|
return sshPublicKey.getEncodedKey();
|
||||||
CanonicalizedPublicKey publicKey = keyRepository.getCanonicalizedPublicKeyRing(unifiedKeyInfo.master_key_id())
|
} catch (NotFoundException e) {
|
||||||
.getPublicKey(authSubKeyId);
|
return null;
|
||||||
SshPublicKey sshPublicKey = new SshPublicKey(publicKey);
|
}
|
||||||
|
|
||||||
return sshPublicKey.getEncodedKey();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// let user choose application
|
||||||
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
||||||
sendIntent.setType(Constants.MIME_TYPE_KEYS);
|
sendIntent.setType(Constants.MIME_TYPE_KEYS);
|
||||||
|
@ -73,6 +83,8 @@ public class ShareKeyHelper {
|
||||||
try {
|
try {
|
||||||
TemporaryFileProvider shareFileProv = new TemporaryFileProvider();
|
TemporaryFileProvider shareFileProv = new TemporaryFileProvider();
|
||||||
|
|
||||||
|
UnifiedKeyInfo unifiedKeyInfo = KeyRepository.create(activity).getUnifiedKeyInfo(masterKeyId);
|
||||||
|
|
||||||
String filename;
|
String filename;
|
||||||
if (unifiedKeyInfo.name() != null) {
|
if (unifiedKeyInfo.name() != null) {
|
||||||
filename = unifiedKeyInfo.name();
|
filename = unifiedKeyInfo.name();
|
||||||
|
@ -113,63 +125,63 @@ public class ShareKeyHelper {
|
||||||
Notify.create(activity, R.string.key_copied_to_clipboard, Notify.Style.OK).show();
|
Notify.create(activity, R.string.key_copied_to_clipboard, Notify.Style.OK).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void shareKey(Activity activity, UnifiedKeyInfo unifiedKeyInfo, boolean toClipboard) {
|
private static void shareKey(Activity activity, long masterKeyId, boolean toClipboard) {
|
||||||
if (activity == null || unifiedKeyInfo == null) {
|
if (activity == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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) {
|
if (toClipboard) {
|
||||||
shareKeyToClipBoard(activity, content);
|
shareKeyToClipBoard(activity, content);
|
||||||
} else {
|
} else {
|
||||||
shareKeyIntent(activity, unifiedKeyInfo, content);
|
shareKeyIntent(activity, masterKeyId, content);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Timber.e(e, "error processing key!");
|
Timber.e(e, "error processing key!");
|
||||||
Notify.create(activity, R.string.error_key_processing, Notify.Style.ERROR).show();
|
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) {
|
private static void shareSshKey(Activity activity, long masterKeyId, boolean toClipboard) {
|
||||||
if (activity == null || unifiedKeyInfo == null) {
|
if (activity == null) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!unifiedKeyInfo.has_auth_key()) {
|
|
||||||
Notify.create(activity, R.string.authentication_subkey_not_found, Notify.Style.ERROR).show();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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) {
|
if (toClipboard) {
|
||||||
shareKeyToClipBoard(activity, content);
|
shareKeyToClipBoard(activity, content);
|
||||||
} else {
|
} else {
|
||||||
shareKeyIntent(activity, unifiedKeyInfo, content);
|
shareKeyIntent(activity, masterKeyId, content);
|
||||||
}
|
}
|
||||||
} catch (PgpGeneralException | IOException | NoSuchAlgorithmException e) {
|
} catch (PgpGeneralException | IOException | NoSuchAlgorithmException e) {
|
||||||
Timber.e(e, "error processing key!");
|
Timber.e(e, "error processing key!");
|
||||||
Notify.create(activity, R.string.error_key_processing, Notify.Style.ERROR).show();
|
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) {
|
public static void shareKeyToClipboard(Activity activity, long masterKeyId) {
|
||||||
shareKey(activity, unifiedKeyInfo, true);
|
shareKey(activity, masterKeyId, true);
|
||||||
}
|
}
|
||||||
public static void shareKey(Activity activity, UnifiedKeyInfo unifiedKeyInfo) {
|
public static void shareKey(Activity activity, long masterKeyId) {
|
||||||
shareKey(activity, unifiedKeyInfo, false);
|
shareKey(activity, masterKeyId, false);
|
||||||
}
|
}
|
||||||
public static void shareSshKey(Activity activity, UnifiedKeyInfo unifiedKeyInfo) {
|
public static void shareSshKey(Activity activity, long masterKeyId) {
|
||||||
shareSshKey(activity, unifiedKeyInfo, false);
|
shareSshKey(activity, masterKeyId, false);
|
||||||
}
|
}
|
||||||
public static void shareSshKeyToClipboard(Activity activity, UnifiedKeyInfo unifiedKeyInfo) {
|
public static void shareSshKeyToClipboard(Activity activity, long masterKeyId) {
|
||||||
shareSshKey(activity, unifiedKeyInfo, true);
|
shareSshKey(activity, masterKeyId, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,11 +41,17 @@ UPDATE keys
|
||||||
SET has_secret = ?2
|
SET has_secret = ?2
|
||||||
WHERE key_id = ?1;
|
WHERE key_id = ?1;
|
||||||
|
|
||||||
validKeysView:
|
validMasterKeysView:
|
||||||
CREATE VIEW validMasterKeys AS
|
CREATE VIEW validMasterKeys AS
|
||||||
|
SELECT *
|
||||||
|
FROM validKeys
|
||||||
|
WHERE rank = 0;
|
||||||
|
|
||||||
|
validKeysView:
|
||||||
|
CREATE VIEW validKeys AS
|
||||||
SELECT master_key_id, rank, key_id, key_size, key_curve_oid, algorithm, fingerprint, can_certify, can_sign, can_encrypt, can_authenticate, is_revoked, has_secret, is_secure, creation, expiry
|
SELECT master_key_id, rank, key_id, key_size, key_curve_oid, algorithm, fingerprint, can_certify, can_sign, can_encrypt, can_authenticate, is_revoked, has_secret, is_secure, creation, expiry
|
||||||
FROM keys
|
FROM keys
|
||||||
WHERE rank = 0 AND is_revoked = 0 AND is_secure = 1 AND (expiry IS NULL OR expiry >= strftime('%s', 'now'));
|
WHERE is_revoked = 0 AND is_secure = 1 AND (expiry IS NULL OR expiry >= strftime('%s', 'now')) AND validFrom <= strftime('%s', 'now');
|
||||||
|
|
||||||
unifiedKeyView:
|
unifiedKeyView:
|
||||||
CREATE VIEW unifiedKeyView AS
|
CREATE VIEW unifiedKeyView AS
|
||||||
|
@ -109,18 +115,17 @@ SELECT fingerprint
|
||||||
|
|
||||||
selectEffectiveEncryptionKeyIdsByMasterKeyId:
|
selectEffectiveEncryptionKeyIdsByMasterKeyId:
|
||||||
SELECT key_id
|
SELECT key_id
|
||||||
FROM keys
|
FROM validKeys
|
||||||
WHERE is_revoked = 0 AND is_secure = 1 AND ( expiry IS NULL OR expiry >= strftime('%s', 'now') ) AND validFrom <= strftime('%s', 'now')
|
WHERE has_secret > 1 AND can_encrypt = 1 AND master_key_id = ?;
|
||||||
AND can_encrypt = 1 AND master_key_id = ?;
|
|
||||||
|
|
||||||
selectEffectiveSignKeyIdByMasterKeyId:
|
selectEffectiveSignKeyIdByMasterKeyId:
|
||||||
SELECT key_id
|
SELECT key_id
|
||||||
FROM keys
|
FROM validKeys
|
||||||
WHERE is_revoked = 0 AND is_secure = 1 AND has_secret > 1 AND ( expiry IS NULL OR expiry >= strftime('%s', 'now') )
|
WHERE has_secret > 1 AND can_sign = 1 AND master_key_id = ?;
|
||||||
AND can_sign = 1 AND master_key_id = ?;
|
|
||||||
|
|
||||||
selectEffectiveAuthKeyIdByMasterKeyId:
|
selectEffectiveAuthKeyIdByMasterKeyId:
|
||||||
SELECT key_id
|
SELECT key_id
|
||||||
FROM keys
|
FROM validKeys
|
||||||
WHERE is_revoked = 0 AND is_secure = 1 AND has_secret > 1 AND ( expiry IS NULL OR expiry >= strftime('%s', 'now') )
|
WHERE can_authenticate = 1 AND master_key_id = ?
|
||||||
AND can_authenticate = 1 AND master_key_id = ?;
|
ORDER BY has_secret > 1 DESC, creation DESC
|
||||||
|
LIMIT 1;
|
|
@ -160,7 +160,7 @@ public class AuthenticationOperationTest {
|
||||||
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
||||||
|
|
||||||
long masterKeyId = mStaticRingRsa.getMasterKeyId();
|
long masterKeyId = mStaticRingRsa.getMasterKeyId();
|
||||||
Long authSubKeyId = keyRepository.getSecretAuthenticationId(masterKeyId);
|
Long authSubKeyId = keyRepository.getEffectiveAuthenticationKeyId(masterKeyId);
|
||||||
|
|
||||||
{ // sign challenge
|
{ // sign challenge
|
||||||
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
||||||
|
@ -206,7 +206,7 @@ public class AuthenticationOperationTest {
|
||||||
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
||||||
|
|
||||||
long masterKeyId = mStaticRingEcDsa.getMasterKeyId();
|
long masterKeyId = mStaticRingEcDsa.getMasterKeyId();
|
||||||
Long authSubKeyId = keyRepository.getSecretAuthenticationId(masterKeyId);
|
Long authSubKeyId = keyRepository.getEffectiveAuthenticationKeyId(masterKeyId);
|
||||||
|
|
||||||
{ // sign challenge
|
{ // sign challenge
|
||||||
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
||||||
|
@ -252,7 +252,7 @@ public class AuthenticationOperationTest {
|
||||||
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
||||||
|
|
||||||
long masterKeyId = mStaticRingEdDsa.getMasterKeyId();
|
long masterKeyId = mStaticRingEdDsa.getMasterKeyId();
|
||||||
Long authSubKeyId = keyRepository.getSecretAuthenticationId(masterKeyId);
|
Long authSubKeyId = keyRepository.getEffectiveAuthenticationKeyId(masterKeyId);
|
||||||
|
|
||||||
{ // sign challenge
|
{ // sign challenge
|
||||||
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
||||||
|
@ -300,7 +300,7 @@ public class AuthenticationOperationTest {
|
||||||
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
||||||
|
|
||||||
long masterKeyId = mStaticRingDsa.getMasterKeyId();
|
long masterKeyId = mStaticRingDsa.getMasterKeyId();
|
||||||
Long authSubKeyId = keyRepository.getSecretAuthenticationId(masterKeyId);
|
Long authSubKeyId = keyRepository.getEffectiveAuthenticationKeyId(masterKeyId);
|
||||||
|
|
||||||
{ // sign challenge
|
{ // sign challenge
|
||||||
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
||||||
|
@ -345,7 +345,7 @@ public class AuthenticationOperationTest {
|
||||||
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
||||||
|
|
||||||
long masterKeyId = mStaticRingEcDsa.getMasterKeyId();
|
long masterKeyId = mStaticRingEcDsa.getMasterKeyId();
|
||||||
Long authSubKeyId = keyRepository.getSecretAuthenticationId(masterKeyId);
|
Long authSubKeyId = keyRepository.getEffectiveAuthenticationKeyId(masterKeyId);
|
||||||
|
|
||||||
{ // sign challenge - should succeed with selected key allowed
|
{ // sign challenge - should succeed with selected key allowed
|
||||||
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class SshPublicKeyTest {
|
||||||
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
||||||
|
|
||||||
long masterKeyId = mStaticRingEcDsa.getMasterKeyId();
|
long masterKeyId = mStaticRingEcDsa.getMasterKeyId();
|
||||||
long authSubKeyId = keyRepository.getSecretAuthenticationId(masterKeyId);
|
long authSubKeyId = keyRepository.getEffectiveAuthenticationKeyId(masterKeyId);
|
||||||
CanonicalizedPublicKey canonicalizedPublicKey = keyRepository.getCanonicalizedPublicKeyRing(masterKeyId)
|
CanonicalizedPublicKey canonicalizedPublicKey = keyRepository.getCanonicalizedPublicKeyRing(masterKeyId)
|
||||||
.getPublicKey(authSubKeyId);
|
.getPublicKey(authSubKeyId);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue