private void shareKey(Uri dataUri, boolean fingerprintOnly) { String content; if (fingerprintOnly) { byte[] fingerprintBlob = ProviderHelper.getFingerprint(this, dataUri); String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob, false); content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; } else { // get public keyring as ascii armored string long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri); ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(this, dataUri, new long[] {masterKeyId}); content = keyringArmored.get(0); // Android will fail with android.os.TransactionTooLargeException if key is too big // see http://www.lonestarprod.com/?p=34 if (content.length() >= 86389) { Toast.makeText(getApplicationContext(), R.string.key_too_big_for_sharing, Toast.LENGTH_LONG) .show(); return; } } // let user choose application Intent sendIntent = new Intent(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, content); sendIntent.setType("text/plain"); startActivity( Intent.createChooser(sendIntent, getResources().getText(R.string.action_share_key_with))); }
private void copyToClipboard(Uri dataUri) { // get public keyring as ascii armored string long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri); ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(this, dataUri, new long[] {masterKeyId}); ClipboardReflection.copyToClipboard(this, keyringArmored.get(0)); Toast.makeText(getApplicationContext(), R.string.key_copied_to_clipboard, Toast.LENGTH_LONG) .show(); }
@Before public void setUp() throws Exception { ProviderHelper providerHelper = new ProviderHelper(RuntimeEnvironment.application); // don't log verbosely here, we're not here to test imports ShadowLog.stream = oldShadowStream; providerHelper.savePublicKeyRing( mStaticRing.extractPublicKeyRing(), new ProgressScaler(), null); // ok NOW log verbosely! ShadowLog.stream = System.out; }
public static String getFingerPrint(Context context, long keyId) { PGPPublicKey key = ProviderHelper.getPGPPublicKeyByKeyId(context, keyId); // if it is no public key get it from your own keys... if (key == null) { PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, keyId); if (secretKey == null) { Log.e(Constants.TAG, "Key could not be found!"); return null; } key = secretKey.getPublicKey(); } return convertFingerprintToHex(key.getFingerprint(), true); }
/** * If an Intent gives a signatureMasterKeyId and/or encryptionMasterKeyIds, preselect those! * * @param preselectedSignatureKeyId * @param preselectedEncryptionKeyIds */ private void preselectKeys( long preselectedSignatureKeyId, long[] preselectedEncryptionKeyIds, ProviderHelper providerHelper) { if (preselectedSignatureKeyId != 0) { // TODO: don't use bouncy castle objects! try { PGPSecretKeyRing keyRing = providerHelper.getPGPSecretKeyRingWithKeyId(preselectedSignatureKeyId); PGPSecretKey masterKey = keyRing.getSecretKey(); if (masterKey != null) { PGPSecretKey signKey = PgpKeyHelper.getFirstSigningSubkey(keyRing); if (signKey != null) { setSignatureKeyId(masterKey.getKeyID()); } } } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "key not found!", e); } } if (preselectedEncryptionKeyIds != null) { Vector<Long> goodIds = new Vector<Long>(); for (int i = 0; i < preselectedEncryptionKeyIds.length; ++i) { // TODO One query per selected key?! wtf try { long id = providerHelper.getMasterKeyId( KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( Long.toString(preselectedEncryptionKeyIds[i]))); goodIds.add(id); } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "key not found!", e); } } if (goodIds.size() > 0) { long[] keyIds = new long[goodIds.size()]; for (int i = 0; i < goodIds.size(); ++i) { keyIds[i] = goodIds.get(i); } setEncryptionKeyIds(keyIds); } } }
private void encryptToContact(Uri dataUri) { long keyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri); long[] encryptionKeyIds = new long[] {keyId}; Intent intent = new Intent(getActivity(), EncryptActivity.class); intent.setAction(EncryptActivity.ACTION_ENCRYPT); intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds); // used instead of startActivity set actionbar based on callingPackage startActivityForResult(intent, 0); }
@Override public Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException { try { if (subKeyId != key.symmetric) { long masterKeyId = mProviderHelper.getMasterKeyId(subKeyId); return getCachedPassphrase(masterKeyId, subKeyId); } return getCachedPassphrase(key.symmetric, key.symmetric); } catch (NotFoundException e) { throw new PassphraseCacheInterface.NoSecretKeyException(); } }
public static PGPSecretKey getSigningKey(Context context, long masterKeyId) { PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context, masterKeyId); if (keyRing == null) { return null; } Vector<PGPSecretKey> signingKeys = getUsableSigningKeys(keyRing); if (signingKeys.size() == 0) { return null; } return signingKeys.get(0); }
public static PGPPublicKey getEncryptPublicKey(Context context, long masterKeyId) { PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(context, masterKeyId); if (keyRing == null) { Log.e(Constants.TAG, "keyRing is null!"); return null; } Vector<PGPPublicKey> encryptKeys = getUsableEncryptKeys(keyRing); if (encryptKeys.size() == 0) { Log.e(Constants.TAG, "encryptKeys is null!"); return null; } return encryptKeys.get(0); }
private void updateFromKeyserver(Uri dataUri) { long updateKeyId = ProviderHelper.getMasterKeyId(ViewKeyActivity.this, dataUri); if (updateKeyId == 0) { Log.e(Constants.TAG, "this shouldn't happen. KeyId == 0!"); return; } Intent queryIntent = new Intent(this, ImportKeysActivity.class); queryIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER); queryIntent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, updateKeyId); // TODO: lookup with onactivityresult! startActivityForResult(queryIntent, RESULT_CODE_LOOKUP_KEY); }
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); String fingerprint = PgpKeyHelper.convertFingerprintToHex(blob); Intent queryIntent = new Intent(getActivity(), ImportKeysActivity.class); queryIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT); queryIntent.putExtra(ImportKeysActivity.EXTRA_FINGERPRINT, fingerprint); startActivityForResult(queryIntent, 0); }
public void drawPublicKey() { PGPPublicKeyRing pubring = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(this, mPubKeyId); if (pubring != null) { PGPPublicKey key = PgpKeyHelper.getMasterKey(pubring); String masterKeyIdHex = PgpKeyHelper.convertKeyIdToHex(mPubKeyId); // get relevant UI elements TextView keyIdHex = (TextView) findViewById(R.id.public_key_master_key_hex); TextView keyUserId = (TextView) findViewById(R.id.public_key_user_id); TextView keyUserIdRest = (TextView) findViewById(R.id.public_key_user_id_rest); if (key != null) { String userId = PgpKeyHelper.getMainUserIdSafe(this, key); String[] userIdSplit = PgpKeyHelper.splitUserId(userId); String userName, userEmail; if (userIdSplit[0] != null) { userName = userIdSplit[0]; } else { userName = getResources().getString(R.string.user_id_no_name); } if (userIdSplit[1] != null) { userEmail = userIdSplit[1]; } else { userEmail = getResources().getString(R.string.error_user_id_no_email); } keyIdHex.setText(masterKeyIdHex); keyUserId.setText(userName); keyUserIdRest.setText(userEmail); keyUserId.setVisibility(View.VISIBLE); keyUserIdRest.setVisibility(View.VISIBLE); } else { Log.e(Constants.TAG, "this shouldn't happen. key == 0!"); finish(); return; } } else { Log.e(Constants.TAG, "this shouldn't happen. pubring == 0!"); finish(); return; } }
public void initValid(CanonicalizedPublicKey signingKey) { setSignatureAvailable(true); setKnownKey(true); CanonicalizedKeyRing signingRing = signingKey.getKeyRing(); // from RING setKeyId(signingRing.getMasterKeyId()); try { setPrimaryUserId(signingRing.getPrimaryUserIdWithFallback()); } catch (PgpKeyNotFoundException e) { Log.d( Constants.TAG, "No primary user id in keyring with master key id " + signingRing.getMasterKeyId()); } setSignatureKeyCertified(signingRing.getVerified() > 0); try { ArrayList<String> allUserIds = signingRing.getUnorderedUserIds(); ArrayList<String> confirmedUserIds = mProviderHelper.getConfirmedUserIds(signingRing.getMasterKeyId()); setUserIds(allUserIds, confirmedUserIds); if (mSenderAddress != null) { if (userIdListContainsAddress(mSenderAddress, confirmedUserIds)) { mSenderStatusResult = SenderStatusResult.USER_ID_CONFIRMED; } else if (userIdListContainsAddress(mSenderAddress, allUserIds)) { mSenderStatusResult = SenderStatusResult.USER_ID_UNCONFIRMED; } else { mSenderStatusResult = SenderStatusResult.USER_ID_MISSING; } } else { mSenderStatusResult = SenderStatusResult.UNKNOWN; } } catch (NotFoundException e) { throw new IllegalStateException("Key didn't exist anymore for user id query!", e); } // either master key is expired/revoked or this specific subkey is expired/revoked setKeyExpired(signingRing.isExpired() || signingKey.isExpired()); setKeyRevoked(signingRing.isRevoked() || signingKey.isRevoked()); }
private void updateView() { if (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0) { mSelectKeysButton.setText(getString(R.string.select_keys_button_default)); } else { mSelectKeysButton.setText( getResources() .getQuantityString( R.plurals.select_keys_button, mEncryptionKeyIds.length, mEncryptionKeyIds.length)); } if (mSecretKeyId == Constants.key.none) { mSign.setChecked(false); mMainUserId.setText(""); mMainUserIdRest.setText(""); } else { // See if we can get a user_id from a unified query 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 != null && userId[1] != null) { mMainUserIdRest.setText(userId[1]); } else { mMainUserIdRest.setText(""); } mSign.setChecked(true); } }
/** handles the UI bits of the signing process on the UI thread */ private void initiateSigning() { PGPPublicKeyRing pubring = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(this, mPubKeyId); if (pubring != null) { // if we have already signed this key, dont bother doing it again boolean alreadySigned = false; @SuppressWarnings("unchecked") Iterator<PGPSignature> itr = pubring.getPublicKey(mPubKeyId).getSignatures(); while (itr.hasNext()) { PGPSignature sig = itr.next(); if (sig.getKeyID() == mMasterKeyId) { alreadySigned = true; break; } } if (!alreadySigned) { /* * get the user's passphrase for this key (if required) */ String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId); if (passphrase == null) { showPassphraseDialog(mMasterKeyId); // bail out; need to wait until the user has entered the passphrase before trying again return; } else { startSigning(); } } else { Toast.makeText(this, R.string.key_has_already_been_signed, Toast.LENGTH_SHORT).show(); setResult(RESULT_CANCELED); finish(); } } }
private void loadData(Uri dataUri) { if (dataUri.equals(mDataUri)) { Log.d(Constants.TAG, "Same URI, no need to load the data again!"); return; } mDataUri = dataUri; Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString()); { // label whether secret key is available, and edit button if it is final long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), mDataUri); if (ProviderHelper.hasSecretKeyByMasterKeyId(getActivity(), masterKeyId)) { // set this attribute. this is a LITTLE unclean, but we have the info available // right here, so why not. mSecretKey.setTextColor(getResources().getColor(R.color.emphasis)); mSecretKey.setText(R.string.secret_key_yes); // certify button // TODO this button MIGHT be useful if the user wants to // certify a private key with another... // mActionCertify.setVisibility(View.GONE); // edit button mActionEdit.setVisibility(View.VISIBLE); mActionEdit.setOnClickListener( new View.OnClickListener() { public void onClick(View view) { Intent editIntent = new Intent(getActivity(), EditKeyActivity.class); editIntent.setData( KeychainContract.KeyRings.buildSecretKeyRingsByMasterKeyIdUri( Long.toString(masterKeyId))); editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY); startActivityForResult(editIntent, 0); } }); } else { mSecretKey.setTextColor(Color.BLACK); mSecretKey.setText(getResources().getString(R.string.secret_key_no)); // certify button mActionCertify.setVisibility(View.VISIBLE); // edit button mActionEdit.setVisibility(View.GONE); } // TODO see todo note above, doing this here for now mActionCertify.setOnClickListener( new View.OnClickListener() { public void onClick(View view) { certifyKey( KeychainContract.KeyRings.buildPublicKeyRingsByMasterKeyIdUri( Long.toString(masterKeyId))); } }); } mActionEncrypt.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { encryptToContact(mDataUri); } }); mUserIdsAdapter = new ViewKeyUserIdsAdapter(getActivity(), null, 0); mUserIds.setAdapter(mUserIdsAdapter); mKeysAdapter = new ViewKeyKeysAdapter(getActivity(), null, 0); mKeys.setAdapter(mKeysAdapter); // Prepare the loaders. Either re-connect with an existing ones, // or start new ones. getActivity().getSupportLoaderManager().initLoader(LOADER_ID_KEYRING, null, this); getActivity().getSupportLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); getActivity().getSupportLoaderManager().initLoader(LOADER_ID_KEYS, null, this); }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.certify_key_activity); final ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayShowTitleEnabled(true); actionBar.setDisplayHomeAsUpEnabled(false); actionBar.setHomeButtonEnabled(false); mSelectKeyFragment = (SelectSecretKeyLayoutFragment) getSupportFragmentManager().findFragmentById(R.id.sign_key_select_key_fragment); mSelectKeyFragment.setCallback(this); mSelectKeyFragment.setFilterCertify(true); mSelectKeyserverSpinner = (Spinner) findViewById(R.id.sign_key_keyserver); ArrayAdapter<String> adapter = new ArrayAdapter<String>( this, android.R.layout.simple_spinner_item, Preferences.getPreferences(this).getKeyServers()); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mSelectKeyserverSpinner.setAdapter(adapter); mUploadKeyCheckbox = (CheckBox) findViewById(R.id.sign_key_upload_checkbox); if (!mUploadKeyCheckbox.isChecked()) { mSelectKeyserverSpinner.setEnabled(false); } else { mSelectKeyserverSpinner.setEnabled(true); } mUploadKeyCheckbox.setOnCheckedChangeListener( new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (!isChecked) { mSelectKeyserverSpinner.setEnabled(false); } else { mSelectKeyserverSpinner.setEnabled(true); } } }); mSignButton = (BootstrapButton) findViewById(R.id.sign_key_sign_button); mSignButton.setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { if (mPubKeyId != 0) { if (mMasterKeyId == 0) { mSelectKeyFragment.setError(getString(R.string.select_key_to_sign)); } else { initiateSigning(); } } } }); mDataUri = getIntent().getData(); if (mDataUri == null) { Log.e(Constants.TAG, "Intent data missing. Should be Uri of key!"); finish(); return; } PGPPublicKeyRing signKey = (PGPPublicKeyRing) ProviderHelper.getPGPKeyRing(this, mDataUri); if (signKey != null) { mPubKeyId = PgpKeyHelper.getMasterKey(signKey).getKeyID(); drawPublicKey(); } if (mPubKeyId == 0) { Log.e(Constants.TAG, "this shouldn't happen. KeyId == 0!"); finish(); return; } }
@NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Activity activity = getActivity(); ContextThemeWrapper theme = ThemeChanger.getDialogThemeWrapper(activity); mRequiredInput = getArguments().getParcelable(EXTRA_REQUIRED_INPUT); CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(theme); // No title, see http://www.google.com/design/spec/components/dialogs.html#dialogs-alerts // alert.setTitle() if (mRequiredInput.mType == RequiredInputType.BACKUP_CODE) { LayoutInflater inflater = LayoutInflater.from(theme); View view = inflater.inflate(R.layout.passphrase_dialog_backup_code, null); alert.setView(view); mBackupCodeEditText = new EditText[4]; mBackupCodeEditText[0] = (EditText) view.findViewById(R.id.backup_code_1); mBackupCodeEditText[1] = (EditText) view.findViewById(R.id.backup_code_2); mBackupCodeEditText[2] = (EditText) view.findViewById(R.id.backup_code_3); mBackupCodeEditText[3] = (EditText) view.findViewById(R.id.backup_code_4); setupEditTextFocusNext(mBackupCodeEditText); AlertDialog dialog = alert.create(); dialog.setButton( DialogInterface.BUTTON_POSITIVE, activity.getString(R.string.btn_unlock), (DialogInterface.OnClickListener) null); return dialog; } long subKeyId = mRequiredInput.getSubKeyId(); LayoutInflater inflater = LayoutInflater.from(theme); mLayout = (ViewAnimator) inflater.inflate(R.layout.passphrase_dialog, null); alert.setView(mLayout); mPassphraseText = (TextView) mLayout.findViewById(R.id.passphrase_text); mPassphraseEditText = (EditText) mLayout.findViewById(R.id.passphrase_passphrase); View vTimeToLiveLayout = mLayout.findViewById(R.id.remember_layout); vTimeToLiveLayout.setVisibility(mRequiredInput.mSkipCaching ? View.GONE : View.VISIBLE); mTimeToLiveSpinner = (CacheTTLSpinner) mLayout.findViewById(R.id.ttl_spinner); alert.setNegativeButton( android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); String userId; CanonicalizedSecretKey.SecretKeyType keyType = CanonicalizedSecretKey.SecretKeyType.PASSPHRASE; String message; String hint; if (mRequiredInput.mType == RequiredInputType.PASSPHRASE_SYMMETRIC) { message = getString(R.string.passphrase_for_symmetric_encryption); hint = getString(R.string.label_passphrase); } else { try { ProviderHelper helper = new ProviderHelper(activity); mSecretRing = helper.getCanonicalizedSecretKeyRing( KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(subKeyId)); // yes the inner try/catch block is necessary, otherwise the final variable // above can't be statically verified to have been set in all cases because // the catch clause doesn't return. try { String mainUserId = mSecretRing.getPrimaryUserIdWithFallback(); KeyRing.UserId mainUserIdSplit = KeyRing.splitUserId(mainUserId); if (mainUserIdSplit.name != null) { userId = mainUserIdSplit.name; } else { userId = getString(R.string.user_id_no_name); } } catch (PgpKeyNotFoundException e) { userId = null; } keyType = mSecretRing.getSecretKey(subKeyId).getSecretKeyType(); switch (keyType) { case PASSPHRASE: message = getString(R.string.passphrase_for, userId); hint = getString(R.string.label_passphrase); break; case PIN: message = getString(R.string.pin_for, userId); hint = getString(R.string.label_pin); break; case DIVERT_TO_CARD: message = getString(R.string.yubikey_pin_for, userId); hint = getString(R.string.label_pin); break; // special case: empty passphrase just returns the empty passphrase case PASSPHRASE_EMPTY: finishCaching(new Passphrase("")); default: throw new AssertionError("Unhandled SecretKeyType (should not happen)"); } } catch (ProviderHelper.NotFoundException e) { alert.setTitle(R.string.title_key_not_found); alert.setMessage(getString(R.string.key_not_found, mRequiredInput.getSubKeyId())); alert.setPositiveButton( android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dismiss(); } }); alert.setCancelable(false); return alert.create(); } } mPassphraseText.setText(message); mPassphraseEditText.setHint(hint); // Hack to open keyboard. // This is the only method that I found to work across all Android versions // http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/ // Notes: * onCreateView can't be used because we want to add buttons to the dialog // * opening in onActivityCreated does not work on Android 4.4 mPassphraseEditText.setOnFocusChangeListener( new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { mPassphraseEditText.post( new Runnable() { @Override public void run() { if (getActivity() == null || mPassphraseEditText == null) { return; } InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(mPassphraseEditText, InputMethodManager.SHOW_IMPLICIT); } }); } }); mPassphraseEditText.requestFocus(); mPassphraseEditText.setImeActionLabel( getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE); mPassphraseEditText.setOnEditorActionListener(this); if ((keyType == CanonicalizedSecretKey.SecretKeyType.DIVERT_TO_CARD && Preferences.getPreferences(activity).useNumKeypadForYubiKeyPin()) || keyType == CanonicalizedSecretKey.SecretKeyType.PIN) { mPassphraseEditText.setInputType(InputType.TYPE_CLASS_NUMBER); mPassphraseEditText.setTransformationMethod(PasswordTransformationMethod.getInstance()); } else { mPassphraseEditText.setRawInputType( InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); } mPassphraseEditText.setTransformationMethod(PasswordTransformationMethod.getInstance()); AlertDialog dialog = alert.create(); dialog.setButton( DialogInterface.BUTTON_POSITIVE, activity.getString(R.string.btn_unlock), (DialogInterface.OnClickListener) null); return dialog; }
public void onLoadFinished(Loader<Cursor> loader, Cursor data) { // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) switch (loader.getId()) { case LOADER_ID_KEYRING: if (data.moveToFirst()) { // get name, email, and comment from USER_ID String[] mainUserId = PgpKeyHelper.splitUserId(data.getString(KEYRING_INDEX_USER_ID)); if (mainUserId[0] != null) { getActivity().setTitle(mainUserId[0]); mName.setText(mainUserId[0]); } else { getActivity().setTitle(R.string.user_id_no_name); mName.setText(R.string.user_id_no_name); } mEmail.setText(mainUserId[1]); mComment.setText(mainUserId[2]); } break; case LOADER_ID_USER_IDS: mUserIdsAdapter.swapCursor(data); break; case LOADER_ID_KEYS: // the first key here is our master key if (data.moveToFirst()) { // get key id from MASTER_KEY_ID long keyId = data.getLong(KEYS_INDEX_KEY_ID); String keyIdStr = PgpKeyHelper.convertKeyIdToHex(keyId); mKeyId.setText(keyIdStr); // get creation date from CREATION if (data.isNull(KEYS_INDEX_CREATION)) { mCreation.setText(R.string.none); } else { Date creationDate = new Date(data.getLong(KEYS_INDEX_CREATION) * 1000); mCreation.setText( DateFormat.getDateFormat(getActivity().getApplicationContext()) .format(creationDate)); } // get expiry date from EXPIRY if (data.isNull(KEYS_INDEX_EXPIRY)) { mExpiry.setText(R.string.none); } else { Date expiryDate = new Date(data.getLong(KEYS_INDEX_EXPIRY) * 1000); mExpiry.setText( DateFormat.getDateFormat(getActivity().getApplicationContext()).format(expiryDate)); } String algorithmStr = PgpKeyHelper.getAlgorithmInfo( data.getInt(KEYS_INDEX_ALGORITHM), data.getInt(KEYS_INDEX_KEY_SIZE)); mAlgorithm.setText(algorithmStr); byte[] fingerprintBlob = data.getBlob(KEYS_INDEX_FINGERPRINT); if (fingerprintBlob == null) { // FALLBACK for old database entries fingerprintBlob = ProviderHelper.getFingerprint(getActivity(), mDataUri); } String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob, true); mFingerprint.setText(OtherHelper.colorizeFingerprint(fingerprint)); } mKeysAdapter.swapCursor(data); break; default: break; } }
private void share(boolean fingerprintOnly, boolean toClipboard) { Activity activity = getActivity(); if (activity == null || mFingerprint == null) { return; } ProviderHelper providerHelper = new ProviderHelper(activity); try { String content; if (fingerprintOnly) { String fingerprint = KeyFormattingUtils.convertFingerprintToHex(mFingerprint); if (!toClipboard) { content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; } else { content = fingerprint; } } else { content = providerHelper.getKeyRingAsArmoredString( KeychainContract.KeyRingData.buildPublicKeyRingUri(mDataUri)); } if (toClipboard) { ClipboardManager clipMan = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE); if (clipMan == null) { Notify.create(activity, R.string.error_clipboard_copy, Style.ERROR); return; } ClipData clip = ClipData.newPlainText(Constants.CLIPBOARD_LABEL, content); clipMan.setPrimaryClip(clip); Notify.create( activity, fingerprintOnly ? R.string.fingerprint_copied_to_clipboard : R.string.key_copied_to_clipboard, Notify.Style.OK) .show(); return; } // Android will fail with android.os.TransactionTooLargeException if key is too big // see http://www.lonestarprod.com/?p=34 if (content.length() >= 86389) { Notify.create(activity, R.string.key_too_big_for_sharing, Notify.Style.ERROR).show(); return; } // let user choose application Intent sendIntent = new Intent(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, content); sendIntent.setType("text/plain"); // Bluetooth Share will convert text/plain sent via EXTRA_TEXT to HTML // Add replacement extra to send a text/plain file instead. try { TemporaryStorageProvider shareFileProv = new TemporaryStorageProvider(); Uri contentUri = TemporaryStorageProvider.createFile( activity, KeyFormattingUtils.convertFingerprintToHex(mFingerprint) + Constants.FILE_EXTENSION_ASC); BufferedWriter contentWriter = new BufferedWriter( new OutputStreamWriter( new ParcelFileDescriptor.AutoCloseOutputStream( shareFileProv.openFile(contentUri, "w")))); contentWriter.write(content); contentWriter.close(); sendIntent.putExtra(Intent.EXTRA_STREAM, contentUri); } catch (FileNotFoundException e) { Log.e(Constants.TAG, "error creating temporary Bluetooth key share file!", e); // no need for a snackbar because one sharing option doesn't work // Notify.create(getActivity(), R.string.error_temp_file, Notify.Style.ERROR).show(); } String title = getString( fingerprintOnly ? R.string.title_share_fingerprint_with : R.string.title_share_key); Intent shareChooser = Intent.createChooser(sendIntent, title); startActivity(shareChooser); } catch (PgpGeneralException | IOException e) { Log.e(Constants.TAG, "error processing key!", e); Notify.create(activity, R.string.error_key_processing, Notify.Style.ERROR).show(); } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "key not found!", e); Notify.create(activity, R.string.error_key_not_found, Notify.Style.ERROR).show(); } }