aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-04-24 14:18:01 +0200
committerVincent Breitmoser <valodim@mugenguild.com>2015-04-24 14:18:01 +0200
commitb4aec3114d9911cf9aef0d14ee697e5131b2853f (patch)
tree7237de5955ec34d8849737b2f9229bfbb37d0c45 /OpenKeychain/src/main
parentc2163460971cc01e65d7dfd18eec491f01ebc744 (diff)
parentbaac30508d24dcda6135bf8ae338c99d8c3b8ad8 (diff)
downloadopen-keychain-b4aec3114d9911cf9aef0d14ee697e5131b2853f.tar.gz
open-keychain-b4aec3114d9911cf9aef0d14ee697e5131b2853f.tar.bz2
open-keychain-b4aec3114d9911cf9aef0d14ee697e5131b2853f.zip
Merge branch 'development' into linked-identities
Conflicts: Graphics/update-drawables.sh OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java OpenKeychain/build.gradle OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
Diffstat (limited to 'OpenKeychain/src/main')
-rw-r--r--OpenKeychain/src/main/AndroidManifest.xml8
-rw-r--r--OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/NfcSyncPGPContentSignerBuilder.java30
-rw-r--r--OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/NfcSyncPublicKeyDataDecryptorFactoryBuilder.java21
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java58
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java15
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java48
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/CertifyResult.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java58
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java63
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java120
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpEditKeyResult.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java81
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PromoteKeyResult.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java182
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java149
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java80
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java327
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java)129
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java121
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java56
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/CryptoInputParcelCacheService.java246
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java355
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java62
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java134
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ServiceProgressHandler.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java141
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java214
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java88
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java81
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java25
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java261
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiWaitFragment.java58
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java203
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java37
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java81
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java86
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java188
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java62
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java442
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java664
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java)84
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeSymmetricFragment.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java)35
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java412
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java306
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java26
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java18
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java313
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java121
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java55
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java28
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java180
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java236
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java232
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SpacesItemDecoration.java93
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java)6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java)465
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java131
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java21
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java38
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java93
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java51
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/DatabaseUtil.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FabContainer.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableCache.java94
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ProgressFixedScaler.java17
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/yubi_icon.pngbin0 -> 2517 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/yubi_icon_24dp.pngbin0 -> 1203 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/yubi_icon.pngbin0 -> 1715 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/yubi_icon_24dp.pngbin0 -> 753 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/yubi_icon.pngbin0 -> 4078 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/yubi_icon_24dp.pngbin0 -> 1715 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/yubi_icon.pngbin0 -> 5808 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/yubi_icon_24dp.pngbin0 -> 2854 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/yubi_icon_24dp.pngbin0 -> 4078 bytes
-rw-r--r--OpenKeychain/src/main/res/layout/create_key_start_fragment.xml34
-rw-r--r--OpenKeychain/src/main/res/layout/create_yubikey_import_fragment.xml126
-rw-r--r--OpenKeychain/src/main/res/layout/create_yubikey_wait_fragment.xml83
-rw-r--r--OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml8
-rw-r--r--OpenKeychain/src/main/res/layout/encrypt_files_activity.xml10
-rw-r--r--OpenKeychain/src/main/res/layout/encrypt_files_fragment.xml14
-rw-r--r--OpenKeychain/src/main/res/layout/encrypt_text_activity.xml10
-rw-r--r--OpenKeychain/src/main/res/layout/file_list_entry.xml90
-rw-r--r--OpenKeychain/src/main/res/layout/file_list_entry_add.xml25
-rw-r--r--OpenKeychain/src/main/res/layout/passphrase_dialog.xml1
-rw-r--r--OpenKeychain/src/main/res/layout/view_key_fragment.xml1
-rw-r--r--OpenKeychain/src/main/res/layout/view_key_yubikey.xml103
-rw-r--r--OpenKeychain/src/main/res/menu/encrypt_file_fragment.xml (renamed from OpenKeychain/src/main/res/menu/encrypt_file_activity.xml)0
-rw-r--r--OpenKeychain/src/main/res/menu/encrypt_text_fragment.xml (renamed from OpenKeychain/src/main/res/menu/encrypt_text_activity.xml)0
-rw-r--r--OpenKeychain/src/main/res/raw-bg/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-bg/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-bg/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-bg/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-cs/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-cs/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-cs/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-cs/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-de/help_about.md41
-rw-r--r--OpenKeychain/src/main/res/raw-de/help_certification.md9
-rw-r--r--OpenKeychain/src/main/res/raw-de/help_changelog.md81
-rw-r--r--OpenKeychain/src/main/res/raw-de/help_start.md17
-rw-r--r--OpenKeychain/src/main/res/raw-es/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-es/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-es/help_changelog.md265
-rw-r--r--OpenKeychain/src/main/res/raw-es/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-et/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-et/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-et/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-et/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-eu/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-eu/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-eu/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-eu/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-fi/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-fi/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-fi/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-fi/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-fr/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-fr/help_certification.md1
-rw-r--r--OpenKeychain/src/main/res/raw-fr/help_changelog.md299
-rw-r--r--OpenKeychain/src/main/res/raw-fr/help_start.md3
-rw-r--r--OpenKeychain/src/main/res/raw-is/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-is/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-is/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-is/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-it/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-it/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-it/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-it/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-ja/help_about.md13
-rw-r--r--OpenKeychain/src/main/res/raw-ja/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-ja/help_changelog.md119
-rw-r--r--OpenKeychain/src/main/res/raw-ja/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-nl/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-nl/help_certification.md37
-rw-r--r--OpenKeychain/src/main/res/raw-nl/help_changelog.md225
-rw-r--r--OpenKeychain/src/main/res/raw-nl/help_start.md3
-rw-r--r--OpenKeychain/src/main/res/raw-pl/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-pl/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-pl/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-pl/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-pt/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-pt/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-pt/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-pt/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-ro/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-ro/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-ro/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-ro/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-ru/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-ru/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-ru/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-ru/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-sl/help_about.md41
-rw-r--r--OpenKeychain/src/main/res/raw-sl/help_certification.md37
-rw-r--r--OpenKeychain/src/main/res/raw-sl/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-sl/help_start.md23
-rw-r--r--OpenKeychain/src/main/res/raw-sr/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-sr/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-sr/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-sr/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-sv/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-sv/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-sv/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-sv/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-tr/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-tr/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-tr/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-tr/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-uk/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-uk/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-uk/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-uk/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-zh-rTW/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-zh-rTW/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-zh-rTW/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-zh-rTW/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw-zh/help_about.md1
-rw-r--r--OpenKeychain/src/main/res/raw-zh/help_certification.md3
-rw-r--r--OpenKeychain/src/main/res/raw-zh/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-zh/help_start.md5
-rw-r--r--OpenKeychain/src/main/res/raw/help_changelog.md10
-rw-r--r--OpenKeychain/src/main/res/values-cs/strings.xml38
-rw-r--r--OpenKeychain/src/main/res/values-de/strings.xml39
-rw-r--r--OpenKeychain/src/main/res/values-es/strings.xml85
-rw-r--r--OpenKeychain/src/main/res/values-et/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-eu/strings.xml19
-rw-r--r--OpenKeychain/src/main/res/values-fi/strings.xml18
-rw-r--r--OpenKeychain/src/main/res/values-fr/strings.xml35
-rw-r--r--OpenKeychain/src/main/res/values-it/strings.xml23
-rw-r--r--OpenKeychain/src/main/res/values-ja/strings.xml42
-rw-r--r--OpenKeychain/src/main/res/values-nl/strings.xml35
-rw-r--r--OpenKeychain/src/main/res/values-pl/strings.xml21
-rw-r--r--OpenKeychain/src/main/res/values-ru/strings.xml69
-rw-r--r--OpenKeychain/src/main/res/values-sl/strings.xml480
-rw-r--r--OpenKeychain/src/main/res/values-sv/strings.xml23
-rw-r--r--OpenKeychain/src/main/res/values-tr/strings.xml20
-rw-r--r--OpenKeychain/src/main/res/values-uk/strings.xml20
-rw-r--r--OpenKeychain/src/main/res/values-zh-rTW/strings.xml170
-rw-r--r--OpenKeychain/src/main/res/values-zh/strings.xml14
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml140
235 files changed, 6836 insertions, 4742 deletions
diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml
index 876d34cf4..f72506144 100644
--- a/OpenKeychain/src/main/AndroidManifest.xml
+++ b/OpenKeychain/src/main/AndroidManifest.xml
@@ -90,6 +90,8 @@
android:name=".ui.CreateKeyActivity"
android:windowSoftInputMode="adjustResize"
android:label="@string/title_manage_my_keys"
+ android:launchMode="singleTop"
+ android:allowTaskReparenting="true"
android:parentActivityName=".ui.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
@@ -673,7 +675,7 @@
taskAffinity and allowTaskReparenting somehow prevents this from happening!
-->
<activity
- android:name=".ui.NfcActivity"
+ android:name=".ui.NfcOperationActivity"
android:launchMode="singleTop"
android:taskAffinity=":Nfc"
android:allowTaskReparenting="true" />
@@ -699,6 +701,10 @@
android:exported="false"
android:process=":passphrase_cache" />
<service
+ android:name=".remote.CryptoInputParcelCacheService"
+ android:exported="false"
+ android:process=":remote_api" />
+ <service
android:name=".service.KeychainIntentService"
android:exported="false" />
<service
diff --git a/OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/NfcSyncPGPContentSignerBuilder.java b/OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/NfcSyncPGPContentSignerBuilder.java
index e0286ec15..0344b2173 100644
--- a/OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/NfcSyncPGPContentSignerBuilder.java
+++ b/OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/NfcSyncPGPContentSignerBuilder.java
@@ -14,8 +14,12 @@ import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
import org.spongycastle.openpgp.operator.PGPDigestCalculator;
import java.io.OutputStream;
+import java.nio.ByteBuffer;
import java.security.Provider;
import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* This class is based on JcaPGPContentSignerBuilder.
@@ -31,31 +35,27 @@ public class NfcSyncPGPContentSignerBuilder
private int keyAlgorithm;
private long keyID;
- private byte[] signedHash;
- private Date creationTimestamp;
+ private Map signedHashes;
public static class NfcInteractionNeeded extends RuntimeException
{
public byte[] hashToSign;
- public Date creationTimestamp;
public int hashAlgo;
- public NfcInteractionNeeded(byte[] hashToSign, int hashAlgo, Date creationTimestamp)
+ public NfcInteractionNeeded(byte[] hashToSign, int hashAlgo)
{
super("NFC interaction required!");
this.hashToSign = hashToSign;
this.hashAlgo = hashAlgo;
- this.creationTimestamp = creationTimestamp;
}
}
- public NfcSyncPGPContentSignerBuilder(int keyAlgorithm, int hashAlgorithm, long keyID, byte[] signedHash, Date creationTimestamp)
+ public NfcSyncPGPContentSignerBuilder(int keyAlgorithm, int hashAlgorithm, long keyID, Map signedHashes)
{
this.keyAlgorithm = keyAlgorithm;
this.hashAlgorithm = hashAlgorithm;
this.keyID = keyID;
- this.signedHash = signedHash;
- this.creationTimestamp = creationTimestamp;
+ this.signedHashes = signedHashes;
}
public NfcSyncPGPContentSignerBuilder setProvider(Provider provider)
@@ -125,14 +125,14 @@ public class NfcSyncPGPContentSignerBuilder
}
public byte[] getSignature() {
- if (signedHash != null) {
- // we already have the signed hash from a previous execution, return this!
- return signedHash;
- } else {
- // catch this when signatureGenerator.generate() is executed and divert digest to card,
- // when doing the operation again reuse creationTimestamp (this will be hashed)
- throw new NfcInteractionNeeded(digestCalculator.getDigest(), getHashAlgorithm(), creationTimestamp);
+ byte[] digest = digestCalculator.getDigest();
+ ByteBuffer buf = ByteBuffer.wrap(digest);
+ if (signedHashes.containsKey(buf)) {
+ return (byte[]) signedHashes.get(buf);
}
+ // catch this when signatureGenerator.generate() is executed and divert digest to card,
+ // when doing the operation again reuse creationTimestamp (this will be hashed)
+ throw new NfcInteractionNeeded(digest, getHashAlgorithm());
}
public byte[] getDigest()
diff --git a/OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/NfcSyncPublicKeyDataDecryptorFactoryBuilder.java b/OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/NfcSyncPublicKeyDataDecryptorFactoryBuilder.java
index ffa154876..067bb3e19 100644
--- a/OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/NfcSyncPublicKeyDataDecryptorFactoryBuilder.java
+++ b/OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/NfcSyncPublicKeyDataDecryptorFactoryBuilder.java
@@ -15,7 +15,10 @@ import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.operator.PGPDataDecryptor;
import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
+import java.nio.ByteBuffer;
import java.security.Provider;
+import java.util.Map;
+
/**
* This class is based on JcePublicKeyDataDecryptorFactoryBuilder
@@ -88,7 +91,7 @@ public class NfcSyncPublicKeyDataDecryptorFactoryBuilder
return this;
}
- public PublicKeyDataDecryptorFactory build(final byte[] nfcDecrypted) {
+ public PublicKeyDataDecryptorFactory build(final Map<ByteBuffer,byte[]> nfcDecryptedMap) {
return new PublicKeyDataDecryptorFactory()
{
public byte[] recoverSessionData(int keyAlgorithm, byte[][] secKeyData)
@@ -99,7 +102,7 @@ public class NfcSyncPublicKeyDataDecryptorFactoryBuilder
throw new PGPException("ECDH not supported!");
}
- return decryptSessionData(keyAlgorithm, secKeyData, nfcDecrypted);
+ return decryptSessionData(keyAlgorithm, secKeyData, nfcDecryptedMap);
}
public PGPDataDecryptor createDataDecryptor(boolean withIntegrityPacket, int encAlgorithm, byte[] key)
@@ -197,8 +200,9 @@ public class NfcSyncPublicKeyDataDecryptorFactoryBuilder
// }
// }
- private byte[] decryptSessionData(int keyAlgorithm, byte[][] secKeyData, byte[] nfcDecrypted)
- throws PGPException
+ private byte[] decryptSessionData(int keyAlgorithm, byte[][] secKeyData,
+ Map<ByteBuffer,byte[]> nfcDecryptedMap)
+ throws PGPException
{
// Cipher c1 = helper.createPublicKeyCipher(keyAlgorithm);
//
@@ -214,15 +218,14 @@ public class NfcSyncPublicKeyDataDecryptorFactoryBuilder
if (keyAlgorithm == PGPPublicKey.RSA_ENCRYPT
|| keyAlgorithm == PGPPublicKey.RSA_GENERAL)
{
- byte[] bi = secKeyData[0]; // encoded MPI
+ ByteBuffer bi = ByteBuffer.wrap(secKeyData[0]); // encoded MPI
- if (nfcDecrypted != null) {
- // we already have the decrypted bytes from a previous execution, return this!
- return nfcDecrypted;
+ if (nfcDecryptedMap.containsKey(bi)) {
+ return nfcDecryptedMap.get(bi);
} else {
// catch this when decryptSessionData() is executed and divert digest to card,
// when doing the operation again reuse nfcDecrypted
- throw new NfcInteractionNeeded(bi);
+ throw new NfcInteractionNeeded(bi.array());
}
// c1.update(bi, 2, bi.length - 2);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
index 4ceb34722..051517abd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
@@ -28,8 +28,9 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.Operat
import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult;
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
-import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
+import org.sufficientlysecure.keychain.pgp.PgpCertifyOperation;
+import org.sufficientlysecure.keychain.pgp.PgpCertifyOperation.PgpCertifyResult;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
@@ -38,6 +39,9 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException
import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase;
@@ -60,7 +64,7 @@ public class CertifyOperation extends BaseOperation {
super(context, providerHelper, progressable, cancelled);
}
- public CertifyResult certify(CertifyActionsParcel parcel, String keyServerUri) {
+ public CertifyResult certify(CertifyActionsParcel parcel, CryptoInputParcel cryptoInput, String keyServerUri) {
OperationLog log = new OperationLog();
log.add(LogType.MSG_CRT, 0);
@@ -74,13 +78,14 @@ public class CertifyOperation extends BaseOperation {
mProviderHelper.getCanonicalizedSecretKeyRing(parcel.mMasterKeyId);
log.add(LogType.MSG_CRT_UNLOCK, 1);
certificationKey = secretKeyRing.getSecretKey();
- if (certificationKey.getSecretKeyType() == SecretKeyType.DIVERT_TO_CARD) {
- log.add(LogType.MSG_CRT_ERROR_DIVERT, 2);
- return new CertifyResult(CertifyResult.RESULT_ERROR, log);
+
+ if (!cryptoInput.hasPassphrase()) {
+ return new CertifyResult(log, RequiredInputParcel.createRequiredSignPassphrase(
+ certificationKey.getKeyId(), certificationKey.getKeyId(), null));
}
// certification is always with the master key id, so use that one
- Passphrase passphrase = getCachedPassphrase(parcel.mMasterKeyId, parcel.mMasterKeyId);
+ Passphrase passphrase = cryptoInput.getPassphrase();
if (!certificationKey.unlock(passphrase)) {
log.add(LogType.MSG_CRT_ERROR_UNLOCK, 2);
@@ -92,9 +97,6 @@ public class CertifyOperation extends BaseOperation {
} catch (NotFoundException e) {
log.add(LogType.MSG_CRT_ERROR_MASTER_NOT_FOUND, 2);
return new CertifyResult(CertifyResult.RESULT_ERROR, log);
- } catch (NoSecretKeyException e) {
- log.add(LogType.MSG_CRT_ERROR_MASTER_NOT_FOUND, 2);
- return new CertifyResult(CertifyResult.RESULT_ERROR, log);
}
ArrayList<UncachedKeyRing> certifiedKeys = new ArrayList<>();
@@ -103,6 +105,10 @@ public class CertifyOperation extends BaseOperation {
int certifyOk = 0, certifyError = 0, uploadOk = 0, uploadError = 0;
+ NfcSignOperationsBuilder allRequiredInput = new NfcSignOperationsBuilder(
+ cryptoInput.getSignatureTime(), certificationKey.getKeyId(),
+ certificationKey.getKeyId());
+
// Work through all requested certifications
for (CertifyAction action : parcel.mCertifyActions) {
@@ -123,28 +129,21 @@ public class CertifyOperation extends BaseOperation {
CanonicalizedPublicKeyRing publicRing =
mProviderHelper.getCanonicalizedPublicKeyRing(action.mMasterKeyId);
- UncachedKeyRing certifiedKey = null;
- if (action.mUserIds != null) {
- log.add(LogType.MSG_CRT_CERTIFY_UIDS, 2, action.mUserIds.size(),
- KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
+ PgpCertifyOperation op = new PgpCertifyOperation();
+ PgpCertifyResult result = op.certify(certificationKey, publicRing,
+ log, 2, action, cryptoInput.getCryptoData(), cryptoInput.getSignatureTime());
- certifiedKey = certificationKey.certifyUserIds(
- publicRing, action.mUserIds, null, null);
+ if (!result.success()) {
+ certifyError += 1;
+ continue;
}
-
- if (action.mUserAttributes != null) {
- log.add(LogType.MSG_CRT_CERTIFY_UATS, 2, action.mUserAttributes.size(),
- KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
-
- certifiedKey = certificationKey.certifyUserAttributes(
- publicRing, action.mUserAttributes, null, null);
+ if (result.nfcInputRequired()) {
+ RequiredInputParcel requiredInput = result.getRequiredInput();
+ allRequiredInput.addAll(requiredInput);
+ continue;
}
- if (certifiedKey == null) {
- certifyError += 1;
- log.add(LogType.MSG_CRT_WARN_CERT_FAILED, 3);
- }
- certifiedKeys.add(certifiedKey);
+ certifiedKeys.add(result.getCertifiedRing());
} catch (NotFoundException e) {
certifyError += 1;
@@ -153,6 +152,11 @@ public class CertifyOperation extends BaseOperation {
}
+ if ( ! allRequiredInput.isEmpty()) {
+ log.add(LogType.MSG_CRT_NFC_RETURN, 1);
+ return new CertifyResult(log, allRequiredInput.build());
+ }
+
log.add(LogType.MSG_CRT_SAVING, 1);
// Check if we were cancelled
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java
index a179b53ee..4072d91c5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java
@@ -21,6 +21,7 @@ import android.content.Context;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
+import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
@@ -34,6 +35,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
@@ -56,7 +58,7 @@ public class EditKeyOperation extends BaseOperation {
super(context, providerHelper, progressable, cancelled);
}
- public EditKeyResult execute(SaveKeyringParcel saveParcel, Passphrase passphrase) {
+ public OperationResult execute(SaveKeyringParcel saveParcel, CryptoInputParcel cryptoInput) {
OperationLog log = new OperationLog();
log.add(LogType.MSG_ED, 0);
@@ -81,7 +83,10 @@ public class EditKeyOperation extends BaseOperation {
CanonicalizedSecretKeyRing secRing =
mProviderHelper.getCanonicalizedSecretKeyRing(saveParcel.mMasterKeyId);
- modifyResult = keyOperations.modifySecretKeyRing(secRing, saveParcel, passphrase);
+ modifyResult = keyOperations.modifySecretKeyRing(secRing, cryptoInput, saveParcel);
+ if (modifyResult.isPending()) {
+ return modifyResult;
+ }
} catch (NotFoundException e) {
log.add(LogType.MSG_ED_ERROR_KEY_NOT_FOUND, 2);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java
index f2516f1bd..ff0b545cd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java
@@ -230,7 +230,7 @@ public class ImportExportOperation extends BaseOperation {
}
} catch (Keyserver.QueryFailedException e) {
Log.e(Constants.TAG, "query failed", e);
- log.add(LogType.MSG_IMPORT_FETCH_KEYSERVER_ERROR, 3);
+ log.add(LogType.MSG_IMPORT_FETCH_KEYSERVER_ERROR, 3, e.getMessage());
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java
index fd86d4b92..ef08b0b77 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java
@@ -50,7 +50,7 @@ public class PromoteKeyOperation extends BaseOperation {
super(context, providerHelper, progressable, cancelled);
}
- public PromoteKeyResult execute(long masterKeyId) {
+ public PromoteKeyResult execute(long masterKeyId, byte[] cardAid) {
OperationLog log = new OperationLog();
log.add(LogType.MSG_PR, 0);
@@ -58,27 +58,16 @@ public class PromoteKeyOperation extends BaseOperation {
// Perform actual type change
UncachedKeyRing promotedRing;
{
-
try {
- // This operation is only allowed for pure public keys
- // TODO delete secret keys if they are stripped, or have been moved to the card?
- if (mProviderHelper.getCachedPublicKeyRing(masterKeyId).hasAnySecret()) {
- log.add(LogType.MSG_PR_ERROR_ALREADY_SECRET, 2);
- return new PromoteKeyResult(PromoteKeyResult.RESULT_ERROR, log, null);
- }
-
log.add(LogType.MSG_PR_FETCHING, 1,
KeyFormattingUtils.convertKeyIdToHex(masterKeyId));
CanonicalizedPublicKeyRing pubRing =
mProviderHelper.getCanonicalizedPublicKeyRing(masterKeyId);
// create divert-to-card secret key from public key
- promotedRing = pubRing.createDummySecretRing();
+ promotedRing = pubRing.createDivertSecretRing(cardAid);
- } catch (PgpKeyNotFoundException e) {
- log.add(LogType.MSG_PR_ERROR_KEY_NOT_FOUND, 2);
- return new PromoteKeyResult(PromoteKeyResult.RESULT_ERROR, log, null);
} catch (NotFoundException e) {
log.add(LogType.MSG_PR_ERROR_KEY_NOT_FOUND, 2);
return new PromoteKeyResult(PromoteKeyResult.RESULT_ERROR, log, null);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java
index b5552a40d..651d15e8f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java
@@ -20,14 +20,21 @@ package org.sufficientlysecure.keychain.operations;
import android.content.Context;
import android.net.Uri;
+import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
+import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
+import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType;
import org.sufficientlysecure.keychain.util.FileHelper;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.ProgressScaler;
@@ -55,7 +62,7 @@ public class SignEncryptOperation extends BaseOperation {
super(context, providerHelper, progressable, cancelled);
}
- public SignEncryptResult execute(SignEncryptParcel input) {
+ public SignEncryptResult execute(SignEncryptParcel input, CryptoInputParcel cryptoInput) {
OperationLog log = new OperationLog();
log.add(LogType.MSG_SE, 0);
@@ -68,6 +75,21 @@ public class SignEncryptOperation extends BaseOperation {
int total = inputBytes != null ? 1 : inputUris.size(), count = 0;
ArrayList<PgpSignEncryptResult> results = new ArrayList<>();
+ NfcSignOperationsBuilder pendingInputBuilder = null;
+
+ // if signing subkey has not explicitly been set, get first usable subkey capable of signing
+ if (input.getSignatureMasterKeyId() != Constants.key.none
+ && input.getSignatureSubKeyId() == null) {
+ try {
+ long signKeyId = mProviderHelper.getCachedPublicKeyRing(
+ input.getSignatureMasterKeyId()).getSecretSignId();
+ input.setSignatureSubKeyId(signKeyId);
+ } catch (PgpKeyNotFoundException e) {
+ e.printStackTrace();
+ return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results);
+ }
+ }
+
do {
if (checkCancelled()) {
@@ -123,15 +145,22 @@ public class SignEncryptOperation extends BaseOperation {
PgpSignEncryptOperation op = new PgpSignEncryptOperation(mContext, mProviderHelper,
new ProgressScaler(mProgressable, 100 * count / total, 100 * ++count / total, 100), mCancelled);
- PgpSignEncryptResult result = op.execute(input, inputData, outStream);
+ PgpSignEncryptResult result = op.execute(input, cryptoInput, inputData, outStream);
results.add(result);
log.add(result, 2);
if (result.isPending()) {
- return new SignEncryptResult(SignEncryptResult.RESULT_PENDING, log, results);
- }
-
- if (!result.success()) {
+ RequiredInputParcel requiredInput = result.getRequiredInputParcel();
+ // Passphrase returns immediately, nfc are aggregated
+ if (requiredInput.mType == RequiredInputType.PASSPHRASE) {
+ return new SignEncryptResult(log, requiredInput, results);
+ }
+ if (pendingInputBuilder == null) {
+ pendingInputBuilder = new NfcSignOperationsBuilder(requiredInput.mSignatureTime,
+ input.getSignatureMasterKeyId(), input.getSignatureSubKeyId());
+ }
+ pendingInputBuilder.addAll(requiredInput);
+ } else if (!result.success()) {
return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results);
}
@@ -141,9 +170,12 @@ public class SignEncryptOperation extends BaseOperation {
} while (!inputUris.isEmpty());
+ if (pendingInputBuilder != null && !pendingInputBuilder.isEmpty()) {
+ return new SignEncryptResult(log, pendingInputBuilder.build(), results);
+ }
+
if (!outputUris.isEmpty()) {
- // Any output URIs left are indicative of a programming error
- log.add(LogType.MSG_SE_WARN_OUTPUT_LEFT, 1);
+ throw new AssertionError("Got outputs left but no inputs. This is a programming error, please report!");
}
log.add(LogType.MSG_SE_SUCCESS, 1);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/CertifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/CertifyResult.java
index f56fe4bb9..0a0e63330 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/CertifyResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/CertifyResult.java
@@ -23,6 +23,7 @@ import android.content.Intent;
import android.os.Parcel;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.ui.LogDisplayActivity;
import org.sufficientlysecure.keychain.ui.LogDisplayFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
@@ -30,16 +31,19 @@ import org.sufficientlysecure.keychain.ui.util.Notify.ActionListener;
import org.sufficientlysecure.keychain.ui.util.Notify.Showable;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
-public class CertifyResult extends OperationResult {
-
+public class CertifyResult extends InputPendingResult {
int mCertifyOk, mCertifyError, mUploadOk, mUploadError;
public CertifyResult(int result, OperationLog log) {
super(result, log);
}
+ public CertifyResult(OperationLog log, RequiredInputParcel requiredInput) {
+ super(log, requiredInput);
+ }
+
public CertifyResult(int result, OperationLog log, int certifyOk, int certifyError, int uploadOk, int uploadError) {
- this(result, log);
+ super(result, log);
mCertifyOk = certifyOk;
mCertifyError = certifyError;
mUploadOk = uploadOk;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java
index 7df37cd9b..917b3415f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java
@@ -22,23 +22,10 @@ import android.os.Parcel;
import org.openintents.openpgp.OpenPgpMetadata;
import org.openintents.openpgp.OpenPgpSignatureResult;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.util.Passphrase;
-public class DecryptVerifyResult extends OperationResult {
-
- // the fourth bit indicates a "data pending" result! (it's also a form of non-success)
- public static final int RESULT_PENDING = RESULT_ERROR + 8;
-
- // fifth to sixth bit in addition indicate specific type of pending
- public static final int RESULT_PENDING_ASYM_PASSPHRASE = RESULT_PENDING + 16;
- public static final int RESULT_PENDING_SYM_PASSPHRASE = RESULT_PENDING + 32;
- public static final int RESULT_PENDING_NFC = RESULT_PENDING + 64;
-
- long mKeyIdPassphraseNeeded;
-
- long mNfcSubKeyId;
- byte[] mNfcSessionKey;
- Passphrase mNfcPassphrase;
+public class DecryptVerifyResult extends InputPendingResult {
OpenPgpSignatureResult mSignatureResult;
OpenPgpMetadata mDecryptMetadata;
@@ -46,32 +33,6 @@ public class DecryptVerifyResult extends OperationResult {
// https://tools.ietf.org/html/rfc4880#page56
String mCharset;
- public long getKeyIdPassphraseNeeded() {
- return mKeyIdPassphraseNeeded;
- }
-
- public void setKeyIdPassphraseNeeded(long keyIdPassphraseNeeded) {
- mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
- }
-
- public void setNfcState(long subKeyId, byte[] sessionKey, Passphrase passphrase) {
- mNfcSubKeyId = subKeyId;
- mNfcSessionKey = sessionKey;
- mNfcPassphrase = passphrase;
- }
-
- public long getNfcSubKeyId() {
- return mNfcSubKeyId;
- }
-
- public byte[] getNfcEncryptedSessionKey() {
- return mNfcSessionKey;
- }
-
- public Passphrase getNfcPassphrase() {
- return mNfcPassphrase;
- }
-
public OpenPgpSignatureResult getSignatureResult() {
return mSignatureResult;
}
@@ -104,13 +65,14 @@ public class DecryptVerifyResult extends OperationResult {
super(result, log);
}
+ public DecryptVerifyResult(OperationLog log, RequiredInputParcel requiredInput) {
+ super(log, requiredInput);
+ }
+
public DecryptVerifyResult(Parcel source) {
super(source);
- mKeyIdPassphraseNeeded = source.readLong();
mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader());
- mNfcSessionKey = source.readInt() != 0 ? source.createByteArray() : null;
- mNfcPassphrase = source.readParcelable(Passphrase.class.getClassLoader());
}
public int describeContents() {
@@ -119,16 +81,8 @@ public class DecryptVerifyResult extends OperationResult {
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
- dest.writeLong(mKeyIdPassphraseNeeded);
dest.writeParcelable(mSignatureResult, 0);
dest.writeParcelable(mDecryptMetadata, 0);
- if (mNfcSessionKey != null) {
- dest.writeInt(1);
- dest.writeByteArray(mNfcSessionKey);
- } else {
- dest.writeInt(0);
- }
- dest.writeParcelable(mNfcPassphrase, flags);
}
public static final Creator<DecryptVerifyResult> CREATOR = new Creator<DecryptVerifyResult>() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java
index abcf575af..842b75c3b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java
@@ -31,13 +31,18 @@ public class EditKeyResult extends OperationResult {
public EditKeyResult(Parcel source) {
super(source);
- mMasterKeyId = source.readLong();
+ mMasterKeyId = source.readInt() != 0 ? source.readLong() : null;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
- dest.writeLong(mMasterKeyId);
+ if (mMasterKeyId != null) {
+ dest.writeInt(1);
+ dest.writeLong(mMasterKeyId);
+ } else {
+ dest.writeInt(0);
+ }
}
public static Creator<EditKeyResult> CREATOR = new Creator<EditKeyResult>() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java
new file mode 100644
index 000000000..0b7aa6d03
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.operations.results;
+
+import java.util.ArrayList;
+
+import android.os.Parcel;
+
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
+
+public class InputPendingResult extends OperationResult {
+
+ // the fourth bit indicates a "data pending" result! (it's also a form of non-success)
+ public static final int RESULT_PENDING = RESULT_ERROR + 8;
+
+ final RequiredInputParcel mRequiredInput;
+
+ public InputPendingResult(int result, OperationLog log) {
+ super(result, log);
+ mRequiredInput = null;
+ }
+
+ public InputPendingResult(OperationLog log, RequiredInputParcel requiredInput) {
+ super(RESULT_PENDING, log);
+ mRequiredInput = requiredInput;
+ }
+
+ public InputPendingResult(Parcel source) {
+ super(source);
+ mRequiredInput = source.readParcelable(getClass().getClassLoader());
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeParcelable(mRequiredInput, 0);
+ }
+
+ public boolean isPending() {
+ return (mResult & RESULT_PENDING) == RESULT_PENDING;
+ }
+
+ public RequiredInputParcel getRequiredInputParcel() {
+ return mRequiredInput;
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java
index 3270d12d5..c93db5c39 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java
@@ -33,75 +33,33 @@ import org.sufficientlysecure.keychain.ui.util.Notify.Showable;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.ParcelableCache;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-/** Represent the result of an operation.
+/**
+ * Represent the result of an operation.
*
* This class holds a result and the log of an operation. It can be subclassed
* to include typed additional information specific to the operation. To keep
* the class structure (somewhat) simple, this class contains an exhaustive
* list (ie, enum) of all possible log types, which should in all cases be tied
* to string resource ids.
- *
*/
public abstract class OperationResult implements Parcelable {
public static final String EXTRA_RESULT = "operation_result";
- public static final UUID NULL_UUID = new UUID(0,0);
/**
- * A HashMap of UUID:OperationLog which contains logs that we don't need
- * to care about. This is used such that when we become parceled, we are
- * well below the 1Mbit boundary that is specified.
+ * Instead of parceling the logs, they are cached to overcome the 1 MB boundary of
+ * Android's Binder. See ParcelableCache
*/
- private static ConcurrentHashMap<UUID, OperationLog> dehydratedLogs;
+ private static ParcelableCache<OperationLog> logCache;
static {
- // Static initializer for ConcurrentHashMap
- dehydratedLogs = new ConcurrentHashMap<UUID,OperationLog>();
- }
-
- /**
- * Dehydrate a log (such that it is available after deparcelization)
- *
- * Returns the NULL uuid (0) if you hand it null.
- * @param log An OperationLog to dehydrate
- * @return a UUID, the ticket for your dehydrated log
- *
- */
- private static UUID dehydrateLog(OperationLog log) {
- if(log == null) {
- return NULL_UUID;
- }
- else {
- UUID ticket = UUID.randomUUID();
- dehydratedLogs.put(ticket, log);
- return ticket;
- }
- }
-
- /***
- * Rehydrate a log after going through parcelization, invalidating its place in the
- * dehydration pool.
- * This is used such that when parcelized, the parcel is no larger than 1mbit.
- * @param ticket A UUID ticket that identifies the log in question.
- * @return An OperationLog.
- */
- private static OperationLog rehydrateLog(UUID ticket) {
- // UUID.equals isn't well documented; we use compareTo instead.
- if( NULL_UUID.compareTo(ticket) == 0 ) {
- return null;
- }
- else {
- OperationLog log = dehydratedLogs.get(ticket);
- dehydratedLogs.remove(ticket);
- return log;
- }
+ logCache = new ParcelableCache<>();
}
/** Holds the overall result, the number specifying varying degrees of success:
@@ -126,11 +84,8 @@ public abstract class OperationResult implements Parcelable {
public OperationResult(Parcel source) {
mResult = source.readInt();
- long mostSig = source.readLong();
- long leastSig = source.readLong();
- UUID mTicket = new UUID(mostSig, leastSig);
- // fetch the dehydrated log out of storage (this removes it from the dehydration pool)
- mLog = rehydrateLog(mTicket);
+ // get log out of cache based on UUID from source
+ mLog = logCache.readFromParcelAndGetFromCache(source);
}
public int getResult() {
@@ -250,12 +205,20 @@ public abstract class OperationResult implements Parcelable {
public Showable createNotify(final Activity activity) {
- Log.d(Constants.TAG, "mLog.getLast()"+mLog.getLast());
- Log.d(Constants.TAG, "mLog.getLast().mType"+mLog.getLast().mType);
- Log.d(Constants.TAG, "mLog.getLast().mType.getMsgId()"+mLog.getLast().mType.getMsgId());
-
// Take the last message as string
- int msgId = mLog.getLast().mType.getMsgId();
+ String logText;
+
+ LogEntryParcel entryParcel = mLog.getLast();
+ // special case: first parameter may be a quantity
+ if (entryParcel.mParameters != null && entryParcel.mParameters.length > 0
+ && entryParcel.mParameters[0] instanceof Integer) {
+ logText = activity.getResources().getQuantityString(entryParcel.mType.getMsgId(),
+ (Integer) entryParcel.mParameters[0],
+ entryParcel.mParameters);
+ } else {
+ logText = activity.getString(entryParcel.mType.getMsgId(),
+ entryParcel.mParameters);
+ }
Style style;
@@ -273,19 +236,19 @@ public abstract class OperationResult implements Parcelable {
}
if (getLog() == null || getLog().isEmpty()) {
- return Notify.create(activity, msgId, Notify.LENGTH_LONG, style);
+ return Notify.create(activity, logText, Notify.LENGTH_LONG, style);
}
- return Notify.create(activity, msgId, Notify.LENGTH_LONG, style,
- new ActionListener() {
- @Override
- public void onAction() {
- Intent intent = new Intent(
- activity, LogDisplayActivity.class);
- intent.putExtra(LogDisplayFragment.EXTRA_RESULT, OperationResult.this);
- activity.startActivity(intent);
- }
- }, R.string.view_log);
+ return Notify.create(activity, logText, Notify.LENGTH_LONG, style,
+ new ActionListener() {
+ @Override
+ public void onAction() {
+ Intent intent = new Intent(
+ activity, LogDisplayActivity.class);
+ intent.putExtra(LogDisplayFragment.EXTRA_RESULT, OperationResult.this);
+ activity.startActivity(intent);
+ }
+ }, R.string.view_log);
}
@@ -512,6 +475,7 @@ public abstract class OperationResult implements Parcelable {
// secret key modify
MSG_MF (LogLevel.START, R.string.msg_mr),
+ MSG_MF_DIVERT (LogLevel.DEBUG, R.string.msg_mf_divert),
MSG_MF_ERROR_DIVERT_SERIAL (LogLevel.ERROR, R.string.msg_mf_error_divert_serial),
MSG_MF_ERROR_ENCODE (LogLevel.ERROR, R.string.msg_mf_error_encode),
MSG_MF_ERROR_FINGERPRINT (LogLevel.ERROR, R.string.msg_mf_error_fingerprint),
@@ -521,6 +485,7 @@ public abstract class OperationResult implements Parcelable {
MSG_MF_ERROR_NO_CERTIFY (LogLevel.ERROR, R.string.msg_cr_error_no_certify),
MSG_MF_ERROR_NOEXIST_PRIMARY (LogLevel.ERROR, R.string.msg_mf_error_noexist_primary),
MSG_MF_ERROR_NOEXIST_REVOKE (LogLevel.ERROR, R.string.msg_mf_error_noexist_revoke),
+ MSG_MF_ERROR_NOOP (LogLevel.ERROR, R.string.msg_mf_error_noop),
MSG_MF_ERROR_NULL_EXPIRY (LogLevel.ERROR, R.string.msg_mf_error_null_expiry),
MSG_MF_ERROR_PASSPHRASE_MASTER(LogLevel.ERROR, R.string.msg_mf_error_passphrase_master),
MSG_MF_ERROR_PAST_EXPIRY(LogLevel.ERROR, R.string.msg_mf_error_past_expiry),
@@ -538,6 +503,9 @@ public abstract class OperationResult implements Parcelable {
MSG_MF_PASSPHRASE_FAIL (LogLevel.WARN, R.string.msg_mf_passphrase_fail),
MSG_MF_PRIMARY_REPLACE_OLD (LogLevel.DEBUG, R.string.msg_mf_primary_replace_old),
MSG_MF_PRIMARY_NEW (LogLevel.DEBUG, R.string.msg_mf_primary_new),
+ MSG_MF_RESTRICTED_MODE (LogLevel.INFO, R.string.msg_mf_restricted_mode),
+ MSG_MF_REQUIRE_DIVERT (LogLevel.OK, R.string.msg_mf_require_divert),
+ MSG_MF_REQUIRE_PASSPHRASE (LogLevel.OK, R.string.msg_mf_require_passphrase),
MSG_MF_SUBKEY_CHANGE (LogLevel.INFO, R.string.msg_mf_subkey_change),
MSG_MF_SUBKEY_NEW_ID (LogLevel.DEBUG, R.string.msg_mf_subkey_new_id),
MSG_MF_SUBKEY_NEW (LogLevel.INFO, R.string.msg_mf_subkey_new),
@@ -590,13 +558,11 @@ public abstract class OperationResult implements Parcelable {
// promote key
MSG_PR (LogLevel.START, R.string.msg_pr),
- MSG_PR_ERROR_ALREADY_SECRET (LogLevel.ERROR, R.string.msg_pr_error_already_secret),
MSG_PR_ERROR_KEY_NOT_FOUND (LogLevel.ERROR, R.string.msg_pr_error_key_not_found),
MSG_PR_FETCHING (LogLevel.DEBUG, R.string.msg_pr_fetching),
MSG_PR_SUCCESS (LogLevel.OK, R.string.msg_pr_success),
// messages used in UI code
- MSG_EK_ERROR_DIVERT (LogLevel.ERROR, R.string.msg_ek_error_divert),
MSG_EK_ERROR_DUMMY (LogLevel.ERROR, R.string.msg_ek_error_dummy),
MSG_EK_ERROR_NOT_FOUND (LogLevel.ERROR, R.string.msg_ek_error_not_found),
@@ -660,7 +626,6 @@ public abstract class OperationResult implements Parcelable {
MSG_SE_ERROR_INPUT_URI_NOT_FOUND (LogLevel.ERROR, R.string.msg_se_error_input_uri_not_found),
MSG_SE_ERROR_OUTPUT_URI_NOT_FOUND (LogLevel.ERROR, R.string.msg_se_error_output_uri_not_found),
MSG_SE_ERROR_TOO_MANY_INPUTS (LogLevel.ERROR, R.string.msg_se_error_too_many_inputs),
- MSG_SE_WARN_OUTPUT_LEFT (LogLevel.WARN, R.string.msg_se_warn_output_left),
MSG_SE_SUCCESS (LogLevel.OK, R.string.msg_se_success),
// pgpsignencrypt
@@ -697,9 +662,9 @@ public abstract class OperationResult implements Parcelable {
MSG_CRT_ERROR_MASTER_NOT_FOUND (LogLevel.ERROR, R.string.msg_crt_error_master_not_found),
MSG_CRT_ERROR_NOTHING (LogLevel.ERROR, R.string.msg_crt_error_nothing),
MSG_CRT_ERROR_UNLOCK (LogLevel.ERROR, R.string.msg_crt_error_unlock),
- MSG_CRT_ERROR_DIVERT (LogLevel.ERROR, R.string.msg_crt_error_divert),
MSG_CRT (LogLevel.START, R.string.msg_crt),
MSG_CRT_MASTER_FETCH (LogLevel.DEBUG, R.string.msg_crt_master_fetch),
+ MSG_CRT_NFC_RETURN (LogLevel.OK, R.string.msg_crt_nfc_return),
MSG_CRT_SAVE (LogLevel.DEBUG, R.string.msg_crt_save),
MSG_CRT_SAVING (LogLevel.DEBUG, R.string.msg_crt_saving),
MSG_CRT_SUCCESS (LogLevel.OK, R.string.msg_crt_success),
@@ -823,11 +788,8 @@ public abstract class OperationResult implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mResult);
- // Get a ticket for our log.
- UUID mTicket = dehydrateLog(mLog);
- // And write out the UUID most and least significant bits.
- dest.writeLong(mTicket.getMostSignificantBits());
- dest.writeLong(mTicket.getLeastSignificantBits());
+ // cache log and write UUID to dest
+ logCache.cacheAndWriteToParcel(mLog, dest);
}
public static class OperationLog implements Iterable<LogEntryParcel> {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpEditKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpEditKeyResult.java
index 611353ac9..38edbf6ee 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpEditKeyResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpEditKeyResult.java
@@ -22,8 +22,10 @@ import android.os.Parcel;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
-public class PgpEditKeyResult extends OperationResult {
+
+public class PgpEditKeyResult extends InputPendingResult {
private transient UncachedKeyRing mRing;
public final long mRingMasterKeyId;
@@ -35,6 +37,11 @@ public class PgpEditKeyResult extends OperationResult {
mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : Constants.key.none;
}
+ public PgpEditKeyResult(OperationLog log, RequiredInputParcel requiredInput) {
+ super(log, requiredInput);
+ mRingMasterKeyId = Constants.key.none;
+ }
+
public UncachedKeyRing getRing() {
return mRing;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java
index cf40001b3..acb265462 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java
@@ -19,85 +19,31 @@ package org.sufficientlysecure.keychain.operations.results;
import android.os.Parcel;
-import org.sufficientlysecure.keychain.util.Passphrase;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
-import java.util.Date;
-public class PgpSignEncryptResult extends OperationResult {
+public class PgpSignEncryptResult extends InputPendingResult {
- // the fourth bit indicates a "data pending" result! (it's also a form of non-success)
- public static final int RESULT_PENDING = RESULT_ERROR + 8;
-
- // fifth to sixth bit in addition indicate specific type of pending
- public static final int RESULT_PENDING_PASSPHRASE = RESULT_PENDING + 16;
- public static final int RESULT_PENDING_NFC = RESULT_PENDING + 32;
-
- long mKeyIdPassphraseNeeded;
-
- long mNfcKeyId;
- byte[] mNfcHash;
- int mNfcAlgo;
- Date mNfcTimestamp;
- Passphrase mNfcPassphrase;
byte[] mDetachedSignature;
- public long getKeyIdPassphraseNeeded() {
- return mKeyIdPassphraseNeeded;
- }
-
- public void setKeyIdPassphraseNeeded(long keyIdPassphraseNeeded) {
- mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
- }
-
- public void setNfcData(long nfcKeyId, byte[] nfcHash, int nfcAlgo, Date nfcTimestamp, Passphrase passphrase) {
- mNfcKeyId = nfcKeyId;
- mNfcHash = nfcHash;
- mNfcAlgo = nfcAlgo;
- mNfcTimestamp = nfcTimestamp;
- mNfcPassphrase = passphrase;
- }
-
public void setDetachedSignature(byte[] detachedSignature) {
mDetachedSignature = detachedSignature;
}
- public long getNfcKeyId() {
- return mNfcKeyId;
- }
-
- public byte[] getNfcHash() {
- return mNfcHash;
- }
-
- public int getNfcAlgo() {
- return mNfcAlgo;
- }
-
- public Date getNfcTimestamp() {
- return mNfcTimestamp;
- }
-
- public Passphrase getNfcPassphrase() {
- return mNfcPassphrase;
- }
-
public byte[] getDetachedSignature() {
return mDetachedSignature;
}
- public boolean isPending() {
- return (mResult & RESULT_PENDING) == RESULT_PENDING;
- }
-
public PgpSignEncryptResult(int result, OperationLog log) {
super(result, log);
}
+ public PgpSignEncryptResult(OperationLog log, RequiredInputParcel requiredInput) {
+ super(log, requiredInput);
+ }
+
public PgpSignEncryptResult(Parcel source) {
super(source);
- mNfcHash = source.readInt() != 0 ? source.createByteArray() : null;
- mNfcAlgo = source.readInt();
- mNfcTimestamp = source.readInt() != 0 ? new Date(source.readLong()) : null;
mDetachedSignature = source.readInt() != 0 ? source.createByteArray() : null;
}
@@ -107,19 +53,6 @@ public class PgpSignEncryptResult extends OperationResult {
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
- if (mNfcHash != null) {
- dest.writeInt(1);
- dest.writeByteArray(mNfcHash);
- } else {
- dest.writeInt(0);
- }
- dest.writeInt(mNfcAlgo);
- if (mNfcTimestamp != null) {
- dest.writeInt(1);
- dest.writeLong(mNfcTimestamp.getTime());
- } else {
- dest.writeInt(0);
- }
if (mDetachedSignature != null) {
dest.writeInt(1);
dest.writeByteArray(mDetachedSignature);
@@ -138,4 +71,4 @@ public class PgpSignEncryptResult extends OperationResult {
}
};
-} \ No newline at end of file
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PromoteKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PromoteKeyResult.java
index af9aff84a..d6c7a1ee0 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PromoteKeyResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PromoteKeyResult.java
@@ -31,13 +31,18 @@ public class PromoteKeyResult extends OperationResult {
public PromoteKeyResult(Parcel source) {
super(source);
- mMasterKeyId = source.readLong();
+ mMasterKeyId = source.readInt() != 0 ? source.readLong() : null;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
- dest.writeLong(mMasterKeyId);
+ if (mMasterKeyId != null) {
+ dest.writeInt(1);
+ dest.writeLong(mMasterKeyId);
+ } else {
+ dest.writeInt(0);
+ }
}
public static Creator<PromoteKeyResult> CREATOR = new Creator<PromoteKeyResult>() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java
index ed0de65b0..b05921b0d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java
@@ -21,20 +21,17 @@ import android.os.Parcel;
import java.util.ArrayList;
-public class SignEncryptResult extends OperationResult {
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
+
+
+public class SignEncryptResult extends InputPendingResult {
ArrayList<PgpSignEncryptResult> mResults;
byte[] mResultBytes;
- public static final int RESULT_PENDING = RESULT_ERROR + 8;
-
- public PgpSignEncryptResult getPending() {
- for (PgpSignEncryptResult sub : mResults) {
- if (sub.isPending()) {
- return sub;
- }
- }
- return null;
+ public SignEncryptResult(OperationLog log, RequiredInputParcel requiredInput, ArrayList<PgpSignEncryptResult> results) {
+ super(log, requiredInput);
+ mResults = results;
}
public SignEncryptResult(int result, OperationLog log, ArrayList<PgpSignEncryptResult> results) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java
index c2506685d..8432b8f9f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java
@@ -98,11 +98,14 @@ public class CanonicalizedPublicKeyRing extends CanonicalizedKeyRing {
/** Create a dummy secret ring from this key */
public UncachedKeyRing createDummySecretRing () {
-
- PGPSecretKeyRing secRing = PGPSecretKeyRing.constructDummyFromPublic(getRing(),
- S2K.GNU_PROTECTION_MODE_NO_PRIVATE_KEY);
+ PGPSecretKeyRing secRing = PGPSecretKeyRing.constructDummyFromPublic(getRing(), null);
return new UncachedKeyRing(secRing);
+ }
+ /** Create a dummy secret ring from this key */
+ public UncachedKeyRing createDivertSecretRing (byte[] cardAid) {
+ PGPSecretKeyRing secRing = PGPSecretKeyRing.constructDummyFromPublic(getRing(), cardAid);
+ return new UncachedKeyRing(secRing);
}
} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
index 6ce77394c..39d0a2f1d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
@@ -40,13 +40,17 @@ import org.spongycastle.openpgp.operator.jcajce.NfcSyncPublicKeyDataDecryptorFac
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+
/**
* Wrapper for a PGPSecretKey.
@@ -184,13 +188,13 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
return PgpConstants.sPreferredHashAlgorithms;
}
- private PGPContentSignerBuilder getContentSignerBuilder(int hashAlgo, byte[] nfcSignedHash,
- Date nfcCreationTimestamp) {
+ private PGPContentSignerBuilder getContentSignerBuilder(int hashAlgo,
+ Map<ByteBuffer,byte[]> signedHashes) {
if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) {
// use synchronous "NFC based" SignerBuilder
return new NfcSyncPGPContentSignerBuilder(
mSecretKey.getPublicKey().getAlgorithm(), hashAlgo,
- mSecretKey.getKeyID(), nfcSignedHash, nfcCreationTimestamp)
+ mSecretKey.getKeyID(), signedHashes)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
} else {
// content signer based on signing key algorithm and chosen hash algorithm
@@ -200,29 +204,43 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
}
}
- public PGPSignatureGenerator getSignatureGenerator(int hashAlgo, boolean cleartext,
- byte[] nfcSignedHash, Date nfcCreationTimestamp)
- throws PgpGeneralException {
+ public PGPSignatureGenerator getCertSignatureGenerator(Map<ByteBuffer, byte[]> signedHashes) {
+ PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(
+ PgpConstants.CERTIFY_HASH_ALGO, signedHashes);
+
if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) {
throw new PrivateKeyNotUnlockedException();
}
- if (nfcSignedHash != null && nfcCreationTimestamp == null) {
- throw new PgpGeneralException("Got nfc hash without timestamp!!");
+
+ PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
+ try {
+ signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, mPrivateKey);
+ return signatureGenerator;
+ } catch (PGPException e) {
+ Log.e(Constants.TAG, "signing error", e);
+ return null;
+ }
+ }
+
+ public PGPSignatureGenerator getDataSignatureGenerator(int hashAlgo, boolean cleartext,
+ Map<ByteBuffer, byte[]> signedHashes, Date creationTimestamp)
+ throws PgpGeneralException {
+ if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) {
+ throw new PrivateKeyNotUnlockedException();
}
// We explicitly create a signature creation timestamp in this place.
// That way, we can inject an artificial one from outside, ie the one
// used in previous runs of this function.
- if (nfcCreationTimestamp == null) {
+ if (creationTimestamp == null) {
// to sign using nfc PgpSignEncrypt is executed two times.
// the first time it stops to return the PendingIntent for nfc connection and signing the hash
// the second time the signed hash is used.
// to get the same hash we cache the timestamp for the second round!
- nfcCreationTimestamp = new Date();
+ creationTimestamp = new Date();
}
- PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(hashAlgo,
- nfcSignedHash, nfcCreationTimestamp);
+ PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(hashAlgo, signedHashes);
int signatureType;
if (cleartext) {
@@ -238,7 +256,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
spGen.setSignerUserID(false, mRing.getPrimaryUserIdWithFallback());
- spGen.setSignatureCreationTime(false, nfcCreationTimestamp);
+ spGen.setSignatureCreationTime(false, creationTimestamp);
signatureGenerator.setHashedSubpackets(spGen.generate());
return signatureGenerator;
} catch (PgpKeyNotFoundException | PGPException e) {
@@ -247,145 +265,24 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
}
}
- public PublicKeyDataDecryptorFactory getDecryptorFactory(byte[] nfcDecryptedSessionKey) {
+ public PublicKeyDataDecryptorFactory getDecryptorFactory(CryptoInputParcel cryptoInput) {
if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) {
throw new PrivateKeyNotUnlockedException();
}
if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) {
return new NfcSyncPublicKeyDataDecryptorFactoryBuilder()
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(nfcDecryptedSessionKey);
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ cryptoInput.getCryptoData()
+ );
} else {
return new JcePublicKeyDataDecryptorFactoryBuilder()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(mPrivateKey);
}
}
- /**
- * Certify the given pubkeyid with the given masterkeyid.
- *
- * @param publicKeyRing Keyring to add certification to.
- * @param userIds User IDs to certify
- * @return A keyring with added certifications
- */
- public UncachedKeyRing certifyUserIds(CanonicalizedPublicKeyRing publicKeyRing, List<String> userIds,
- byte[] nfcSignedHash, Date nfcCreationTimestamp) {
- if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) {
- throw new PrivateKeyNotUnlockedException();
- }
- if (!isMasterKey()) {
- throw new AssertionError("tried to certify with non-master key, this is a programming error!");
- }
- if (publicKeyRing.getMasterKeyId() == getKeyId()) {
- throw new AssertionError("key tried to self-certify, this is a programming error!");
- }
-
- // create a signatureGenerator from the supplied masterKeyId and passphrase
- PGPSignatureGenerator signatureGenerator;
- {
- PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(
- PgpConstants.CERTIFY_HASH_ALGO, nfcSignedHash, nfcCreationTimestamp);
-
- signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
- try {
- signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, mPrivateKey);
- } catch (PGPException e) {
- Log.e(Constants.TAG, "signing error", e);
- return null;
- }
- }
-
- { // supply signatureGenerator with a SubpacketVector
- PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
- if (nfcCreationTimestamp != null) {
- spGen.setSignatureCreationTime(false, nfcCreationTimestamp);
- Log.d(Constants.TAG, "For NFC: set sig creation time to " + nfcCreationTimestamp);
- }
- PGPSignatureSubpacketVector packetVector = spGen.generate();
- signatureGenerator.setHashedSubpackets(packetVector);
- }
-
- // get the master subkey (which we certify for)
- PGPPublicKey publicKey = publicKeyRing.getPublicKey().getPublicKey();
-
- // fetch public key ring, add the certification and return it
- try {
- for (String userId : userIds) {
- PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey);
- publicKey = PGPPublicKey.addCertification(publicKey, userId, sig);
- }
- } catch (PGPException e) {
- Log.e(Constants.TAG, "signing error", e);
- return null;
- }
-
- PGPPublicKeyRing ring = PGPPublicKeyRing.insertPublicKey(publicKeyRing.getRing(), publicKey);
-
- return new UncachedKeyRing(ring);
- }
-
- /**
- * Certify the given user attributes with the given masterkeyid.
- *
- * @param publicKeyRing Keyring to add certification to.
- * @param userAttributes User IDs to certify, or all if null
- * @return A keyring with added certifications
- */
- public UncachedKeyRing certifyUserAttributes(CanonicalizedPublicKeyRing publicKeyRing,
- List<WrappedUserAttribute> userAttributes, byte[] nfcSignedHash, Date nfcCreationTimestamp) {
- if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) {
- throw new PrivateKeyNotUnlockedException();
- }
- if (!isMasterKey()) {
- throw new AssertionError("tried to certify with non-master key, this is a programming error!");
- }
- if (publicKeyRing.getMasterKeyId() == getKeyId()) {
- throw new AssertionError("key tried to self-certify, this is a programming error!");
- }
-
- // create a signatureGenerator from the supplied masterKeyId and passphrase
- PGPSignatureGenerator signatureGenerator;
- {
- PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(
- PgpConstants.CERTIFY_HASH_ALGO, nfcSignedHash, nfcCreationTimestamp);
-
- signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
- try {
- signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, mPrivateKey);
- } catch (PGPException e) {
- Log.e(Constants.TAG, "signing error", e);
- return null;
- }
- }
-
- { // supply signatureGenerator with a SubpacketVector
- PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
- if (nfcCreationTimestamp != null) {
- spGen.setSignatureCreationTime(false, nfcCreationTimestamp);
- Log.d(Constants.TAG, "For NFC: set sig creation time to " + nfcCreationTimestamp);
- }
- PGPSignatureSubpacketVector packetVector = spGen.generate();
- signatureGenerator.setHashedSubpackets(packetVector);
- }
-
- // get the master subkey (which we certify for)
- PGPPublicKey publicKey = publicKeyRing.getPublicKey().getPublicKey();
-
- // fetch public key ring, add the certification and return it
- try {
- for (WrappedUserAttribute userAttribute : userAttributes) {
- PGPUserAttributeSubpacketVector vector = userAttribute.getVector();
- PGPSignature sig = signatureGenerator.generateCertification(vector, publicKey);
- publicKey = PGPPublicKey.addCertification(publicKey, vector, sig);
- }
- } catch (PGPException e) {
- Log.e(Constants.TAG, "signing error", e);
- return null;
- }
-
- PGPPublicKeyRing ring = PGPPublicKeyRing.insertPublicKey(publicKeyRing.getRing(), publicKey);
-
- return new UncachedKeyRing(ring);
+ public byte[] getIv() {
+ return mSecretKey.getIV();
}
static class PrivateKeyNotUnlockedException extends RuntimeException {
@@ -402,4 +299,9 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
return mPrivateKey;
}
+ // HACK, for TESTING ONLY!!
+ PGPSecretKey getSecretKey() {
+ return mSecretKey;
+ }
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java
new file mode 100644
index 000000000..90ec3053f
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java
@@ -0,0 +1,149 @@
+package org.sufficientlysecure.keychain.pgp;
+
+
+import java.nio.ByteBuffer;
+import java.util.Date;
+import java.util.Map;
+
+import org.spongycastle.openpgp.PGPException;
+import org.spongycastle.openpgp.PGPPublicKey;
+import org.spongycastle.openpgp.PGPPublicKeyRing;
+import org.spongycastle.openpgp.PGPSignature;
+import org.spongycastle.openpgp.PGPSignatureGenerator;
+import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
+import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
+import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector;
+import org.spongycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
+import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.Log;
+
+
+public class PgpCertifyOperation {
+
+ public PgpCertifyResult certify(
+ CanonicalizedSecretKey secretKey,
+ CanonicalizedPublicKeyRing publicRing,
+ OperationLog log,
+ int indent,
+ CertifyAction action,
+ Map<ByteBuffer,byte[]> signedHashes,
+ Date creationTimestamp) {
+
+ if (!secretKey.isMasterKey()) {
+ throw new AssertionError("tried to certify with non-master key, this is a programming error!");
+ }
+ if (publicRing.getMasterKeyId() == secretKey.getKeyId()) {
+ throw new AssertionError("key tried to self-certify, this is a programming error!");
+ }
+
+ // create a signatureGenerator from the supplied masterKeyId and passphrase
+ PGPSignatureGenerator signatureGenerator = secretKey.getCertSignatureGenerator(signedHashes);
+
+ { // supply signatureGenerator with a SubpacketVector
+ PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
+ if (creationTimestamp != null) {
+ spGen.setSignatureCreationTime(false, creationTimestamp);
+ Log.d(Constants.TAG, "For NFC: set sig creation time to " + creationTimestamp);
+ }
+ PGPSignatureSubpacketVector packetVector = spGen.generate();
+ signatureGenerator.setHashedSubpackets(packetVector);
+ }
+
+ // get the master subkey (which we certify for)
+ PGPPublicKey publicKey = publicRing.getPublicKey().getPublicKey();
+
+ NfcSignOperationsBuilder requiredInput = new NfcSignOperationsBuilder(creationTimestamp,
+ publicKey.getKeyID(), publicKey.getKeyID());
+
+ try {
+ if (action.mUserIds != null) {
+ log.add(LogType.MSG_CRT_CERTIFY_UIDS, 2, action.mUserIds.size(),
+ KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
+
+ // fetch public key ring, add the certification and return it
+ for (String userId : action.mUserIds) {
+ try {
+ PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey);
+ publicKey = PGPPublicKey.addCertification(publicKey, userId, sig);
+ } catch (NfcInteractionNeeded e) {
+ requiredInput.addHash(e.hashToSign, e.hashAlgo);
+ }
+ }
+
+ }
+
+ if (action.mUserAttributes != null) {
+ log.add(LogType.MSG_CRT_CERTIFY_UATS, 2, action.mUserAttributes.size(),
+ KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
+
+ // fetch public key ring, add the certification and return it
+ for (WrappedUserAttribute userAttribute : action.mUserAttributes) {
+ PGPUserAttributeSubpacketVector vector = userAttribute.getVector();
+ try {
+ PGPSignature sig = signatureGenerator.generateCertification(vector, publicKey);
+ publicKey = PGPPublicKey.addCertification(publicKey, vector, sig);
+ } catch (NfcInteractionNeeded e) {
+ requiredInput.addHash(e.hashToSign, e.hashAlgo);
+ }
+ }
+
+ }
+ } catch (PGPException e) {
+ Log.e(Constants.TAG, "signing error", e);
+ return new PgpCertifyResult();
+ }
+
+ if (!requiredInput.isEmpty()) {
+ return new PgpCertifyResult(requiredInput.build());
+ }
+
+ PGPPublicKeyRing ring = PGPPublicKeyRing.insertPublicKey(publicRing.getRing(), publicKey);
+ return new PgpCertifyResult(new UncachedKeyRing(ring));
+
+ }
+
+ public static class PgpCertifyResult {
+
+ final RequiredInputParcel mRequiredInput;
+ final UncachedKeyRing mCertifiedRing;
+
+ PgpCertifyResult() {
+ mRequiredInput = null;
+ mCertifiedRing = null;
+ }
+
+ PgpCertifyResult(RequiredInputParcel requiredInput) {
+ mRequiredInput = requiredInput;
+ mCertifiedRing = null;
+ }
+
+ PgpCertifyResult(UncachedKeyRing certifiedRing) {
+ mRequiredInput = null;
+ mCertifiedRing = certifiedRing;
+ }
+
+ public boolean success() {
+ return mCertifiedRing != null || mRequiredInput != null;
+ }
+
+ public boolean nfcInputRequired() {
+ return mRequiredInput != null;
+ }
+
+ public UncachedKeyRing getCertifiedRing() {
+ return mCertifiedRing;
+ }
+
+ public RequiredInputParcel getRequiredInput() {
+ return mRequiredInput;
+ }
+
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
index 364a1067d..f6580b85a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
@@ -47,16 +47,15 @@ import org.spongycastle.openpgp.operator.jcajce.NfcSyncPublicKeyDataDecryptorFac
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.BaseOperation;
+import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
-import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
@@ -84,10 +83,8 @@ public class PgpDecryptVerify extends BaseOperation {
private OutputStream mOutStream;
private boolean mAllowSymmetricDecryption;
- private Passphrase mPassphrase;
private Set<Long> mAllowedKeyIds;
private boolean mDecryptMetadataOnly;
- private byte[] mDecryptedSessionKey;
private byte[] mDetachedSignature;
private String mRequiredSignerFingerprint;
private boolean mSignedLiteralData;
@@ -100,10 +97,8 @@ public class PgpDecryptVerify extends BaseOperation {
this.mOutStream = builder.mOutStream;
this.mAllowSymmetricDecryption = builder.mAllowSymmetricDecryption;
- this.mPassphrase = builder.mPassphrase;
this.mAllowedKeyIds = builder.mAllowedKeyIds;
this.mDecryptMetadataOnly = builder.mDecryptMetadataOnly;
- this.mDecryptedSessionKey = builder.mDecryptedSessionKey;
this.mDetachedSignature = builder.mDetachedSignature;
this.mSignedLiteralData = builder.mSignedLiteralData;
this.mRequiredSignerFingerprint = builder.mRequiredSignerFingerprint;
@@ -119,10 +114,8 @@ public class PgpDecryptVerify extends BaseOperation {
private OutputStream mOutStream = null;
private Progressable mProgressable = null;
private boolean mAllowSymmetricDecryption = true;
- private Passphrase mPassphrase = null;
private Set<Long> mAllowedKeyIds = null;
private boolean mDecryptMetadataOnly = false;
- private byte[] mDecryptedSessionKey = null;
private byte[] mDetachedSignature = null;
private String mRequiredSignerFingerprint = null;
private boolean mSignedLiteralData = false;
@@ -160,11 +153,6 @@ public class PgpDecryptVerify extends BaseOperation {
return this;
}
- public Builder setPassphrase(Passphrase passphrase) {
- mPassphrase = passphrase;
- return this;
- }
-
/**
* Allow these key ids alone for decryption.
* This means only ciphertexts encrypted for one of these private key can be decrypted.
@@ -183,11 +171,6 @@ public class PgpDecryptVerify extends BaseOperation {
return this;
}
- public Builder setNfcState(byte[] decryptedSessionKey) {
- mDecryptedSessionKey = decryptedSessionKey;
- return this;
- }
-
/**
* If detachedSignature != null, it will be used exclusively to verify the signature
*/
@@ -204,7 +187,7 @@ public class PgpDecryptVerify extends BaseOperation {
/**
* Decrypts and/or verifies data based on parameters of class
*/
- public DecryptVerifyResult execute() {
+ public DecryptVerifyResult execute(CryptoInputParcel cryptoInput) {
try {
if (mDetachedSignature != null) {
Log.d(Constants.TAG, "Detached signature present, verifying with this signature only");
@@ -226,10 +209,10 @@ public class PgpDecryptVerify extends BaseOperation {
return verifyCleartextSignature(aIn, 0);
} else {
// else: ascii armored encryption! go on...
- return decryptVerify(in, 0);
+ return decryptVerify(cryptoInput, in, 0);
}
} else {
- return decryptVerify(in, 0);
+ return decryptVerify(cryptoInput, in, 0);
}
}
} catch (PGPException e) {
@@ -248,7 +231,8 @@ public class PgpDecryptVerify extends BaseOperation {
/**
* Verify Keybase.io style signed literal data
*/
- private DecryptVerifyResult verifySignedLiteralData(InputStream in, int indent) throws IOException, PGPException {
+ private DecryptVerifyResult verifySignedLiteralData(InputStream in, int indent)
+ throws IOException, PGPException {
OperationLog log = new OperationLog();
log.add(LogType.MSG_VL, indent);
@@ -378,7 +362,8 @@ public class PgpDecryptVerify extends BaseOperation {
/**
* Decrypt and/or verifies binary or ascii armored pgp
*/
- private DecryptVerifyResult decryptVerify(InputStream in, int indent) throws IOException, PGPException {
+ private DecryptVerifyResult decryptVerify(CryptoInputParcel cryptoInput,
+ InputStream in, int indent) throws IOException, PGPException {
OperationLog log = new OperationLog();
@@ -433,6 +418,8 @@ public class PgpDecryptVerify extends BaseOperation {
}
}
+ Passphrase passphrase = null;
+
// go through all objects and find one we can decrypt
while (it.hasNext()) {
Object obj = it.next();
@@ -492,11 +479,15 @@ public class PgpDecryptVerify extends BaseOperation {
encryptedDataAsymmetric = encData;
- // if no passphrase was explicitly set try to get it from the cache service
- if (mPassphrase == null) {
+ if (secretEncryptionKey.getSecretKeyType() == SecretKeyType.DIVERT_TO_CARD) {
+ passphrase = null;
+ } else if (cryptoInput.hasPassphrase()) {
+ passphrase = cryptoInput.getPassphrase();
+ } else {
+ // if no passphrase was explicitly set try to get it from the cache service
try {
// returns "" if key has no passphrase
- mPassphrase = getCachedPassphrase(subKeyId);
+ passphrase = getCachedPassphrase(subKeyId);
log.add(LogType.MSG_DC_PASS_CACHED, indent + 1);
} catch (PassphraseCacheInterface.NoSecretKeyException e) {
log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1);
@@ -504,12 +495,11 @@ public class PgpDecryptVerify extends BaseOperation {
}
// if passphrase was not cached, return here indicating that a passphrase is missing!
- if (mPassphrase == null) {
+ if (passphrase == null) {
log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1);
- DecryptVerifyResult result =
- new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE, log);
- result.setKeyIdPassphraseNeeded(subKeyId);
- return result;
+ return new DecryptVerifyResult(log,
+ RequiredInputParcel.createRequiredDecryptPassphrase(
+ secretKeyRing.getMasterKeyId(), secretEncryptionKey.getKeyId()));
}
}
@@ -536,11 +526,14 @@ public class PgpDecryptVerify extends BaseOperation {
// if no passphrase is given, return here
// indicating that a passphrase is missing!
- if (mPassphrase == null) {
+ if (!cryptoInput.hasPassphrase()) {
log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1);
- return new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE, log);
+ return new DecryptVerifyResult(log,
+ RequiredInputParcel.createRequiredSymmetricPassphrase());
}
+ passphrase = cryptoInput.getPassphrase();
+
// break out of while, only decrypt the first packet
break;
}
@@ -573,7 +566,7 @@ public class PgpDecryptVerify extends BaseOperation {
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build();
PBEDataDecryptorFactory decryptorFactory = new JcePBEDataDecryptorFactoryBuilder(
digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
- mPassphrase.getCharArray());
+ passphrase.getCharArray());
clear = encryptedDataSymmetric.getDataStream(decryptorFactory);
encryptedData = encryptedDataSymmetric;
@@ -585,7 +578,7 @@ public class PgpDecryptVerify extends BaseOperation {
try {
log.add(LogType.MSG_DC_UNLOCKING, indent + 1);
- if (!secretEncryptionKey.unlock(mPassphrase)) {
+ if (!secretEncryptionKey.unlock(passphrase)) {
log.add(LogType.MSG_DC_ERROR_BAD_PASSPHRASE, indent + 1);
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
}
@@ -599,16 +592,15 @@ public class PgpDecryptVerify extends BaseOperation {
try {
PublicKeyDataDecryptorFactory decryptorFactory
- = secretEncryptionKey.getDecryptorFactory(mDecryptedSessionKey);
+ = secretEncryptionKey.getDecryptorFactory(cryptoInput);
clear = encryptedDataAsymmetric.getDataStream(decryptorFactory);
symmetricEncryptionAlgo = encryptedDataAsymmetric.getSymmetricAlgorithm(decryptorFactory);
} catch (NfcSyncPublicKeyDataDecryptorFactoryBuilder.NfcInteractionNeeded e) {
log.add(LogType.MSG_DC_PENDING_NFC, indent + 1);
- DecryptVerifyResult result =
- new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_NFC, log);
- result.setNfcState(secretEncryptionKey.getKeyId(), e.encryptedSessionKey, mPassphrase);
- return result;
+ return new DecryptVerifyResult(log, RequiredInputParcel.createNfcDecryptOperation(
+ e.encryptedSessionKey, secretEncryptionKey.getKeyId()
+ ));
}
encryptedData = encryptedDataAsymmetric;
} else {
@@ -878,8 +870,8 @@ public class PgpDecryptVerify extends BaseOperation {
* The method is heavily based on
* pg/src/main/java/org/spongycastle/openpgp/examples/ClearSignedFileProcessor.java
*/
- private DecryptVerifyResult verifyCleartextSignature(ArmoredInputStream aIn, int indent)
- throws IOException, PGPException {
+ private DecryptVerifyResult verifyCleartextSignature(
+ ArmoredInputStream aIn, int indent) throws IOException, PGPException {
OperationLog log = new OperationLog();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
index b3bf92364..89db378a9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
@@ -18,7 +18,7 @@
package org.sufficientlysecure.keychain.pgp;
-import org.spongycastle.bcpg.HashAlgorithmTags;
+import org.spongycastle.bcpg.S2K;
import org.spongycastle.bcpg.sig.Features;
import org.spongycastle.bcpg.sig.KeyFlags;
import org.spongycastle.jce.spec.ElGamalParameterSpec;
@@ -43,6 +43,8 @@ import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBu
import org.spongycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
+import org.spongycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder;
+import org.spongycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
@@ -54,6 +56,9 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
@@ -86,6 +91,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* This indicator may be null.
*/
public class PgpKeyOperation {
+
private Stack<Progressable> mProgress;
private AtomicBoolean mCancelled;
@@ -317,7 +323,8 @@ public class PgpKeyOperation {
masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator());
subProgressPush(50, 100);
- return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, saveParcel, new Passphrase(), log);
+ CryptoInputParcel cryptoInput = new CryptoInputParcel(new Date(), new Passphrase(""));
+ return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, cryptoInput, saveParcel, log);
} catch (PGPException e) {
log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent);
@@ -348,8 +355,9 @@ public class PgpKeyOperation {
* namely stripping of subkeys and changing the protection mode of dummy keys.
*
*/
- public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR, SaveKeyringParcel saveParcel,
- Passphrase passphrase) {
+ public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR,
+ CryptoInputParcel cryptoInput,
+ SaveKeyringParcel saveParcel) {
OperationLog log = new OperationLog();
int indent = 0;
@@ -387,11 +395,24 @@ public class PgpKeyOperation {
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
- // If we have no passphrase, only allow restricted operation
- if (passphrase == null) {
+ if (saveParcel.isEmpty()) {
+ log.add(LogType.MSG_MF_ERROR_NOOP, indent);
+ return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
+ }
+
+ if (isDummy(masterSecretKey) || saveParcel.isRestrictedOnly()) {
+ log.add(LogType.MSG_MF_RESTRICTED_MODE, indent);
return internalRestricted(sKR, saveParcel, log);
}
+ // Do we require a passphrase? If so, pass it along
+ if (!isDivertToCard(masterSecretKey) && !cryptoInput.hasPassphrase()) {
+ log.add(LogType.MSG_MF_REQUIRE_PASSPHRASE, indent);
+ return new PgpEditKeyResult(log, RequiredInputParcel.createRequiredSignPassphrase(
+ masterSecretKey.getKeyID(), masterSecretKey.getKeyID(),
+ cryptoInput.getSignatureTime()));
+ }
+
// read masterKeyFlags, and use the same as before.
// since this is the master key, this contains at least CERTIFY_OTHER
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
@@ -399,33 +420,45 @@ public class PgpKeyOperation {
Date expiryTime = wsKR.getPublicKey().getExpiryTime();
long masterKeyExpiry = expiryTime != null ? expiryTime.getTime() / 1000 : 0L;
- return internal(sKR, masterSecretKey, masterKeyFlags, masterKeyExpiry, saveParcel, passphrase, log);
+ return internal(sKR, masterSecretKey, masterKeyFlags, masterKeyExpiry, cryptoInput, saveParcel, log);
}
private PgpEditKeyResult internal(PGPSecretKeyRing sKR, PGPSecretKey masterSecretKey,
int masterKeyFlags, long masterKeyExpiry,
- SaveKeyringParcel saveParcel, Passphrase passphrase,
+ CryptoInputParcel cryptoInput,
+ SaveKeyringParcel saveParcel,
OperationLog log) {
int indent = 1;
+ NfcSignOperationsBuilder nfcSignOps = new NfcSignOperationsBuilder(
+ cryptoInput.getSignatureTime(), masterSecretKey.getKeyID(),
+ masterSecretKey.getKeyID());
+
progress(R.string.progress_modify, 0);
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
- // 1. Unlock private key
- progress(R.string.progress_modify_unlock, 10);
- log.add(LogType.MSG_MF_UNLOCK, indent);
PGPPrivateKey masterPrivateKey;
- {
- try {
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
- masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
- } catch (PGPException e) {
- log.add(LogType.MSG_MF_UNLOCK_ERROR, indent + 1);
- return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
+
+ if (isDivertToCard(masterSecretKey)) {
+ masterPrivateKey = null;
+ log.add(LogType.MSG_MF_DIVERT, indent);
+ } else {
+
+ // 1. Unlock private key
+ progress(R.string.progress_modify_unlock, 10);
+ log.add(LogType.MSG_MF_UNLOCK, indent);
+ {
+ try {
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(cryptoInput.getPassphrase().getCharArray());
+ masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
+ } catch (PGPException e) {
+ log.add(LogType.MSG_MF_UNLOCK_ERROR, indent + 1);
+ return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
+ }
}
}
@@ -449,7 +482,7 @@ public class PgpKeyOperation {
String userId = saveParcel.mAddUserIds.get(i);
log.add(LogType.MSG_MF_UID_ADD, indent, userId);
- if (userId.equals("")) {
+ if ("".equals(userId)) {
log.add(LogType.MSG_MF_UID_ERROR_EMPTY, indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
@@ -480,9 +513,16 @@ public class PgpKeyOperation {
boolean isPrimary = saveParcel.mChangePrimaryUserId != null
&& userId.equals(saveParcel.mChangePrimaryUserId);
// generate and add new certificate
- PGPSignature cert = generateUserIdSignature(masterPrivateKey,
- masterPublicKey, userId, isPrimary, masterKeyFlags, masterKeyExpiry);
- modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert);
+ try {
+ PGPSignature cert = generateUserIdSignature(
+ getSignatureGenerator(masterSecretKey, cryptoInput),
+ cryptoInput.getSignatureTime(),
+ masterPrivateKey, masterPublicKey, userId,
+ isPrimary, masterKeyFlags, masterKeyExpiry);
+ modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert);
+ } catch (NfcInteractionNeeded e) {
+ nfcSignOps.addHash(e.hashToSign, e.hashAlgo);
+ }
}
subProgressPop();
@@ -509,9 +549,15 @@ public class PgpKeyOperation {
PGPUserAttributeSubpacketVector vector = attribute.getVector();
// generate and add new certificate
- PGPSignature cert = generateUserAttributeSignature(masterPrivateKey,
- masterPublicKey, vector);
- modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, vector, cert);
+ try {
+ PGPSignature cert = generateUserAttributeSignature(
+ getSignatureGenerator(masterSecretKey, cryptoInput),
+ cryptoInput.getSignatureTime(),
+ masterPrivateKey, masterPublicKey, vector);
+ modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, vector, cert);
+ } catch (NfcInteractionNeeded e) {
+ nfcSignOps.addHash(e.hashToSign, e.hashAlgo);
+ }
}
subProgressPop();
@@ -539,9 +585,15 @@ public class PgpKeyOperation {
// a duplicate revocation will be removed during canonicalization, so no need to
// take care of that here.
- PGPSignature cert = generateRevocationSignature(masterPrivateKey,
- masterPublicKey, userId);
- modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert);
+ try {
+ PGPSignature cert = generateRevocationSignature(
+ getSignatureGenerator(masterSecretKey, cryptoInput),
+ cryptoInput.getSignatureTime(),
+ masterPrivateKey, masterPublicKey, userId);
+ modifiedPublicKey = PGPPublicKey.addCertification(modifiedPublicKey, userId, cert);
+ } catch (NfcInteractionNeeded e) {
+ nfcSignOps.addHash(e.hashToSign, e.hashAlgo);
+ }
}
subProgressPop();
@@ -611,11 +663,18 @@ public class PgpKeyOperation {
log.add(LogType.MSG_MF_PRIMARY_REPLACE_OLD, indent);
modifiedPublicKey = PGPPublicKey.removeCertification(
modifiedPublicKey, userId, currentCert);
- PGPSignature newCert = generateUserIdSignature(
- masterPrivateKey, masterPublicKey, userId, false,
- masterKeyFlags, masterKeyExpiry);
- modifiedPublicKey = PGPPublicKey.addCertification(
- modifiedPublicKey, userId, newCert);
+ try {
+ PGPSignature newCert = generateUserIdSignature(
+ getSignatureGenerator(masterSecretKey, cryptoInput),
+ cryptoInput.getSignatureTime(),
+ masterPrivateKey, masterPublicKey, userId, false,
+ masterKeyFlags, masterKeyExpiry);
+ modifiedPublicKey = PGPPublicKey.addCertification(
+ modifiedPublicKey, userId, newCert);
+ } catch (NfcInteractionNeeded e) {
+ nfcSignOps.addHash(e.hashToSign, e.hashAlgo);
+ }
+
continue;
}
@@ -627,11 +686,17 @@ public class PgpKeyOperation {
log.add(LogType.MSG_MF_PRIMARY_NEW, indent);
modifiedPublicKey = PGPPublicKey.removeCertification(
modifiedPublicKey, userId, currentCert);
- PGPSignature newCert = generateUserIdSignature(
- masterPrivateKey, masterPublicKey, userId, true,
- masterKeyFlags, masterKeyExpiry);
- modifiedPublicKey = PGPPublicKey.addCertification(
- modifiedPublicKey, userId, newCert);
+ try {
+ PGPSignature newCert = generateUserIdSignature(
+ getSignatureGenerator(masterSecretKey, cryptoInput),
+ cryptoInput.getSignatureTime(),
+ masterPrivateKey, masterPublicKey, userId, true,
+ masterKeyFlags, masterKeyExpiry);
+ modifiedPublicKey = PGPPublicKey.addCertification(
+ modifiedPublicKey, userId, newCert);
+ } catch (NfcInteractionNeeded e) {
+ nfcSignOps.addHash(e.hashToSign, e.hashAlgo);
+ }
ok = true;
}
@@ -718,8 +783,9 @@ public class PgpKeyOperation {
}
PGPPublicKey pKey =
- updateMasterCertificates(masterPrivateKey, masterPublicKey,
- flags, expiry, indent, log);
+ updateMasterCertificates(
+ masterSecretKey, masterPrivateKey, masterPublicKey,
+ flags, expiry, cryptoInput, nfcSignOps, indent, log);
if (pKey == null) {
// error log entry has already been added by updateMasterCertificates itself
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
@@ -756,9 +822,16 @@ public class PgpKeyOperation {
pKey = PGPPublicKey.removeCertification(pKey, sig);
}
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ cryptoInput.getPassphrase().getCharArray());
+ PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
+ PGPSignature sig = generateSubkeyBindingSignature(
+ getSignatureGenerator(masterSecretKey, cryptoInput),
+ cryptoInput.getSignatureTime(),
+ masterPublicKey, masterPrivateKey, subPrivateKey, pKey, flags, expiry);
+
// generate and add new signature
- PGPSignature sig = generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey,
- sKey, pKey, flags, expiry, passphrase);
pKey = PGPPublicKey.addCertification(pKey, sig);
sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey));
}
@@ -782,10 +855,17 @@ public class PgpKeyOperation {
PGPPublicKey pKey = sKey.getPublicKey();
// generate and add new signature
- PGPSignature sig = generateRevocationSignature(masterPublicKey, masterPrivateKey, pKey);
-
- pKey = PGPPublicKey.addCertification(pKey, sig);
- sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey));
+ try {
+ PGPSignature sig = generateRevocationSignature(
+ getSignatureGenerator(masterSecretKey, cryptoInput),
+ cryptoInput.getSignatureTime(),
+ masterPublicKey, masterPrivateKey, pKey);
+
+ pKey = PGPPublicKey.addCertification(pKey, sig);
+ sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey));
+ } catch (NfcInteractionNeeded e) {
+ nfcSignOps.addHash(e.hashToSign, e.hashAlgo);
+ }
}
subProgressPop();
@@ -828,10 +908,16 @@ public class PgpKeyOperation {
// add subkey binding signature (making this a sub rather than master key)
PGPPublicKey pKey = keyPair.getPublicKey();
- PGPSignature cert = generateSubkeyBindingSignature(
- masterPublicKey, masterPrivateKey, keyPair.getPrivateKey(), pKey,
- add.mFlags, add.mExpiry);
- pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert);
+ try {
+ PGPSignature cert = generateSubkeyBindingSignature(
+ getSignatureGenerator(masterSecretKey, cryptoInput),
+ cryptoInput.getSignatureTime(),
+ masterPublicKey, masterPrivateKey, keyPair.getPrivateKey(), pKey,
+ add.mFlags, add.mExpiry);
+ pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert);
+ } catch (NfcInteractionNeeded e) {
+ nfcSignOps.addHash(e.hashToSign, e.hashAlgo);
+ }
PGPSecretKey sKey; {
// Build key encrypter and decrypter based on passphrase
@@ -840,7 +926,8 @@ public class PgpKeyOperation {
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ cryptoInput.getPassphrase().getCharArray());
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
.build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
@@ -868,7 +955,7 @@ public class PgpKeyOperation {
indent += 1;
sKR = applyNewUnlock(sKR, masterPublicKey, masterPrivateKey,
- passphrase, saveParcel.mNewUnlock, log, indent);
+ cryptoInput.getPassphrase(), saveParcel.mNewUnlock, log, indent);
if (sKR == null) {
// The error has been logged above, just return a bad state
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
@@ -892,6 +979,12 @@ public class PgpKeyOperation {
}
progress(R.string.progress_done, 100);
+
+ if (!nfcSignOps.isEmpty()) {
+ log.add(LogType.MSG_MF_REQUIRE_DIVERT, indent);
+ return new PgpEditKeyResult(log, nfcSignOps.build());
+ }
+
log.add(LogType.MSG_MF_SUCCESS, indent);
return new PgpEditKeyResult(OperationResult.RESULT_OK, log, new UncachedKeyRing(sKR));
@@ -1064,8 +1157,7 @@ public class PgpKeyOperation {
PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder(
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
- newPassphrase.getCharArray());
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(newPassphrase.getCharArray());
// noinspection unchecked
for (PGPSecretKey sKey : new IterableIterator<PGPSecretKey>(sKR.getSecretKeys())) {
@@ -1116,9 +1208,13 @@ public class PgpKeyOperation {
}
/** Update all (non-revoked) uid signatures with new flags and expiry time. */
- private static PGPPublicKey updateMasterCertificates(
- PGPPrivateKey masterPrivateKey, PGPPublicKey masterPublicKey,
- int flags, long expiry, int indent, OperationLog log)
+ private PGPPublicKey updateMasterCertificates(
+ PGPSecretKey masterSecretKey, PGPPrivateKey masterPrivateKey,
+ PGPPublicKey masterPublicKey,
+ int flags, long expiry,
+ CryptoInputParcel cryptoInput,
+ NfcSignOperationsBuilder nfcSignOps,
+ int indent, OperationLog log)
throws PGPException, IOException, SignatureException {
// keep track if we actually changed one
@@ -1173,10 +1269,16 @@ public class PgpKeyOperation {
currentCert.getHashedSubPackets().isPrimaryUserID();
modifiedPublicKey = PGPPublicKey.removeCertification(
modifiedPublicKey, userId, currentCert);
- PGPSignature newCert = generateUserIdSignature(
- masterPrivateKey, masterPublicKey, userId, isPrimary, flags, expiry);
- modifiedPublicKey = PGPPublicKey.addCertification(
- modifiedPublicKey, userId, newCert);
+ try {
+ PGPSignature newCert = generateUserIdSignature(
+ getSignatureGenerator(masterSecretKey, cryptoInput),
+ cryptoInput.getSignatureTime(),
+ masterPrivateKey, masterPublicKey, userId, isPrimary, flags, expiry);
+ modifiedPublicKey = PGPPublicKey.addCertification(
+ modifiedPublicKey, userId, newCert);
+ } catch (NfcInteractionNeeded e) {
+ nfcSignOps.addHash(e.hashToSign, e.hashAlgo);
+ }
ok = true;
}
@@ -1191,15 +1293,37 @@ public class PgpKeyOperation {
}
- private static PGPSignature generateUserIdSignature(
+ static PGPSignatureGenerator getSignatureGenerator(
+ PGPSecretKey secretKey, CryptoInputParcel cryptoInput) {
+
+ PGPContentSignerBuilder builder;
+
+ S2K s2k = secretKey.getS2K();
+ if (s2k != null && s2k.getType() == S2K.GNU_DUMMY_S2K
+ && s2k.getProtectionMode() == S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD) {
+ // use synchronous "NFC based" SignerBuilder
+ builder = new NfcSyncPGPContentSignerBuilder(
+ secretKey.getPublicKey().getAlgorithm(),
+ PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO,
+ secretKey.getKeyID(), cryptoInput.getCryptoData())
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+ } else {
+ // content signer based on signing key algorithm and chosen hash algorithm
+ builder = new JcaPGPContentSignerBuilder(
+ secretKey.getPublicKey().getAlgorithm(),
+ PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+ }
+
+ return new PGPSignatureGenerator(builder);
+
+ }
+
+ private PGPSignature generateUserIdSignature(
+ PGPSignatureGenerator sGen, Date creationTime,
PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId, boolean primary,
int flags, long expiry)
throws IOException, PGPException, SignatureException {
- PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
- masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
- PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
- PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
{
@@ -1223,7 +1347,7 @@ public class PgpKeyOperation {
hashedPacketsGen.setPrimaryUserID(false, primary);
/* critical subpackets: we consider those important for a modern pgp implementation */
- hashedPacketsGen.setSignatureCreationTime(true, new Date());
+ hashedPacketsGen.setSignatureCreationTime(true, creationTime);
// Request that senders add the MDC to the message (authenticate unsigned messages)
hashedPacketsGen.setFeature(true, Features.FEATURE_MODIFICATION_DETECTION);
hashedPacketsGen.setKeyFlags(true, flags);
@@ -1239,19 +1363,15 @@ public class PgpKeyOperation {
}
private static PGPSignature generateUserAttributeSignature(
+ PGPSignatureGenerator sGen, Date creationTime,
PGPPrivateKey masterPrivateKey, PGPPublicKey pKey,
PGPUserAttributeSubpacketVector vector)
throws IOException, PGPException, SignatureException {
- PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
- masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
- PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
- PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
{
/* critical subpackets: we consider those important for a modern pgp implementation */
- hashedPacketsGen.setSignatureCreationTime(true, new Date());
+ hashedPacketsGen.setSignatureCreationTime(true, creationTime);
}
sGen.setHashedSubpackets(hashedPacketsGen.generate());
@@ -1260,29 +1380,24 @@ public class PgpKeyOperation {
}
private static PGPSignature generateRevocationSignature(
+ PGPSignatureGenerator sGen, Date creationTime,
PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId)
+
throws IOException, PGPException, SignatureException {
- PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
- masterPrivateKey.getPublicKeyPacket().getAlgorithm(),
- PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
- PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
- subHashedPacketsGen.setSignatureCreationTime(true, new Date());
+ subHashedPacketsGen.setSignatureCreationTime(true, creationTime);
sGen.setHashedSubpackets(subHashedPacketsGen.generate());
sGen.init(PGPSignature.CERTIFICATION_REVOCATION, masterPrivateKey);
return sGen.generateCertification(userId, pKey);
}
private static PGPSignature generateRevocationSignature(
+ PGPSignatureGenerator sGen, Date creationTime,
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey, PGPPublicKey pKey)
throws IOException, PGPException, SignatureException {
- PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
- masterPublicKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
- PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
+
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
- subHashedPacketsGen.setSignatureCreationTime(true, new Date());
+ subHashedPacketsGen.setSignatureCreationTime(true, creationTime);
sGen.setHashedSubpackets(subHashedPacketsGen.generate());
// Generate key revocation or subkey revocation, depending on master/subkey-ness
if (masterPublicKey.getKeyID() == pKey.getKeyID()) {
@@ -1294,26 +1409,12 @@ public class PgpKeyOperation {
}
}
- private static PGPSignature generateSubkeyBindingSignature(
- PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
- PGPSecretKey sKey, PGPPublicKey pKey, int flags, long expiry, Passphrase passphrase)
- throws IOException, PGPException, SignatureException {
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
- passphrase.getCharArray());
- PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
- return generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey, subPrivateKey,
- pKey, flags, expiry);
- }
-
static PGPSignature generateSubkeyBindingSignature(
+ PGPSignatureGenerator sGen, Date creationTime,
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
PGPPrivateKey subPrivateKey, PGPPublicKey pKey, int flags, long expiry)
throws IOException, PGPException, SignatureException {
- // date for signing
- Date creationTime = new Date();
-
PGPSignatureSubpacketGenerator unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
// If this key can sign, we need a primary key binding signature
@@ -1324,10 +1425,10 @@ public class PgpKeyOperation {
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
pKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
- PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
- sGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey);
- sGen.setHashedSubpackets(subHashedPacketsGen.generate());
- PGPSignature certification = sGen.generateCertification(masterPublicKey, pKey);
+ PGPSignatureGenerator subSigGen = new PGPSignatureGenerator(signerBuilder);
+ subSigGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey);
+ subSigGen.setHashedSubpackets(subHashedPacketsGen.generate());
+ PGPSignature certification = subSigGen.generateCertification(masterPublicKey, pKey);
unhashedPacketsGen.setEmbeddedSignature(true, certification);
}
@@ -1342,10 +1443,6 @@ public class PgpKeyOperation {
}
}
- PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
- masterPublicKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
- PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
sGen.init(PGPSignature.SUBKEY_BINDING, masterPrivateKey);
sGen.setHashedSubpackets(hashedPacketsGen.generate());
sGen.setUnhashedSubpackets(unhashedPacketsGen.generate());
@@ -1372,4 +1469,16 @@ public class PgpKeyOperation {
return flags;
}
+ private static boolean isDummy(PGPSecretKey secretKey) {
+ S2K s2k = secretKey.getS2K();
+ return s2k.getType() == S2K.GNU_DUMMY_S2K
+ && s2k.getProtectionMode() == S2K.GNU_PROTECTION_MODE_NO_PRIVATE_KEY;
+ }
+
+ private static boolean isDivertToCard(PGPSecretKey secretKey) {
+ S2K s2k = secretKey.getS2K();
+ return s2k.getType() == S2K.GNU_DUMMY_S2K
+ && s2k.getProtectionMode() == S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD;
+ }
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java
index 4a920685a..fd3c4910c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java
@@ -20,11 +20,18 @@ package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.util.Passphrase;
+import java.nio.ByteBuffer;
import java.util.Date;
+import java.util.Map;
-public class PgpSignEncryptInput {
+import android.os.Parcel;
+import android.os.Parcelable;
+
+
+public class PgpSignEncryptInputParcel implements Parcelable {
protected String mVersionHeader = null;
protected boolean mEnableAsciiArmorOutput = false;
@@ -35,16 +42,68 @@ public class PgpSignEncryptInput {
protected long mSignatureMasterKeyId = Constants.key.none;
protected Long mSignatureSubKeyId = null;
protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED;
- protected Passphrase mSignaturePassphrase = null;
protected long mAdditionalEncryptId = Constants.key.none;
- protected byte[] mNfcSignedHash = null;
- protected Date mNfcCreationTimestamp = null;
protected boolean mFailOnMissingEncryptionKeyIds = false;
protected String mCharset;
protected boolean mCleartextSignature;
protected boolean mDetachedSignature = false;
protected boolean mHiddenRecipients = false;
+ public PgpSignEncryptInputParcel() {
+
+ }
+
+ PgpSignEncryptInputParcel(Parcel source) {
+
+ ClassLoader loader = getClass().getClassLoader();
+
+ // we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable
+ mVersionHeader = source.readString();
+ mEnableAsciiArmorOutput = source.readInt() == 1;
+ mCompressionId = source.readInt();
+ mEncryptionMasterKeyIds = source.createLongArray();
+ mSymmetricPassphrase = source.readParcelable(loader);
+ mSymmetricEncryptionAlgorithm = source.readInt();
+ mSignatureMasterKeyId = source.readLong();
+ mSignatureSubKeyId = source.readInt() == 1 ? source.readLong() : null;
+ mSignatureHashAlgorithm = source.readInt();
+ mAdditionalEncryptId = source.readLong();
+ mFailOnMissingEncryptionKeyIds = source.readInt() == 1;
+ mCharset = source.readString();
+ mCleartextSignature = source.readInt() == 1;
+ mDetachedSignature = source.readInt() == 1;
+ mHiddenRecipients = source.readInt() == 1;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mVersionHeader);
+ dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
+ dest.writeInt(mCompressionId);
+ dest.writeLongArray(mEncryptionMasterKeyIds);
+ dest.writeParcelable(mSymmetricPassphrase, 0);
+ dest.writeInt(mSymmetricEncryptionAlgorithm);
+ dest.writeLong(mSignatureMasterKeyId);
+ if (mSignatureSubKeyId != null) {
+ dest.writeInt(1);
+ dest.writeLong(mSignatureSubKeyId);
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeInt(mSignatureHashAlgorithm);
+ dest.writeLong(mAdditionalEncryptId);
+ dest.writeInt(mFailOnMissingEncryptionKeyIds ? 1 : 0);
+ dest.writeString(mCharset);
+ dest.writeInt(mCleartextSignature ? 1 : 0);
+ dest.writeInt(mDetachedSignature ? 1 : 0);
+ dest.writeInt(mHiddenRecipients ? 1 : 0);
+ }
+
public String getCharset() {
return mCharset;
}
@@ -57,37 +116,20 @@ public class PgpSignEncryptInput {
return mFailOnMissingEncryptionKeyIds;
}
- public Date getNfcCreationTimestamp() {
- return mNfcCreationTimestamp;
- }
-
- public byte[] getNfcSignedHash() {
- return mNfcSignedHash;
- }
-
public long getAdditionalEncryptId() {
return mAdditionalEncryptId;
}
- public PgpSignEncryptInput setAdditionalEncryptId(long additionalEncryptId) {
+ public PgpSignEncryptInputParcel setAdditionalEncryptId(long additionalEncryptId) {
mAdditionalEncryptId = additionalEncryptId;
return this;
}
- public Passphrase getSignaturePassphrase() {
- return mSignaturePassphrase;
- }
-
- public PgpSignEncryptInput setSignaturePassphrase(Passphrase signaturePassphrase) {
- mSignaturePassphrase = signaturePassphrase;
- return this;
- }
-
public int getSignatureHashAlgorithm() {
return mSignatureHashAlgorithm;
}
- public PgpSignEncryptInput setSignatureHashAlgorithm(int signatureHashAlgorithm) {
+ public PgpSignEncryptInputParcel setSignatureHashAlgorithm(int signatureHashAlgorithm) {
mSignatureHashAlgorithm = signatureHashAlgorithm;
return this;
}
@@ -96,7 +138,7 @@ public class PgpSignEncryptInput {
return mSignatureSubKeyId;
}
- public PgpSignEncryptInput setSignatureSubKeyId(long signatureSubKeyId) {
+ public PgpSignEncryptInputParcel setSignatureSubKeyId(long signatureSubKeyId) {
mSignatureSubKeyId = signatureSubKeyId;
return this;
}
@@ -105,7 +147,7 @@ public class PgpSignEncryptInput {
return mSignatureMasterKeyId;
}
- public PgpSignEncryptInput setSignatureMasterKeyId(long signatureMasterKeyId) {
+ public PgpSignEncryptInputParcel setSignatureMasterKeyId(long signatureMasterKeyId) {
mSignatureMasterKeyId = signatureMasterKeyId;
return this;
}
@@ -114,7 +156,7 @@ public class PgpSignEncryptInput {
return mSymmetricEncryptionAlgorithm;
}
- public PgpSignEncryptInput setSymmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm) {
+ public PgpSignEncryptInputParcel setSymmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm) {
mSymmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm;
return this;
}
@@ -123,7 +165,7 @@ public class PgpSignEncryptInput {
return mSymmetricPassphrase;
}
- public PgpSignEncryptInput setSymmetricPassphrase(Passphrase symmetricPassphrase) {
+ public PgpSignEncryptInputParcel setSymmetricPassphrase(Passphrase symmetricPassphrase) {
mSymmetricPassphrase = symmetricPassphrase;
return this;
}
@@ -132,7 +174,7 @@ public class PgpSignEncryptInput {
return mEncryptionMasterKeyIds;
}
- public PgpSignEncryptInput setEncryptionMasterKeyIds(long[] encryptionMasterKeyIds) {
+ public PgpSignEncryptInputParcel setEncryptionMasterKeyIds(long[] encryptionMasterKeyIds) {
mEncryptionMasterKeyIds = encryptionMasterKeyIds;
return this;
}
@@ -141,7 +183,7 @@ public class PgpSignEncryptInput {
return mCompressionId;
}
- public PgpSignEncryptInput setCompressionId(int compressionId) {
+ public PgpSignEncryptInputParcel setCompressionId(int compressionId) {
mCompressionId = compressionId;
return this;
}
@@ -154,28 +196,22 @@ public class PgpSignEncryptInput {
return mVersionHeader;
}
- public PgpSignEncryptInput setVersionHeader(String versionHeader) {
+ public PgpSignEncryptInputParcel setVersionHeader(String versionHeader) {
mVersionHeader = versionHeader;
return this;
}
- public PgpSignEncryptInput setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput) {
+ public PgpSignEncryptInputParcel setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput) {
mEnableAsciiArmorOutput = enableAsciiArmorOutput;
return this;
}
- public PgpSignEncryptInput setFailOnMissingEncryptionKeyIds(boolean failOnMissingEncryptionKeyIds) {
+ public PgpSignEncryptInputParcel setFailOnMissingEncryptionKeyIds(boolean failOnMissingEncryptionKeyIds) {
mFailOnMissingEncryptionKeyIds = failOnMissingEncryptionKeyIds;
return this;
}
- public PgpSignEncryptInput setNfcState(byte[] signedHash, Date creationTimestamp) {
- mNfcSignedHash = signedHash;
- mNfcCreationTimestamp = creationTimestamp;
- return this;
- }
-
- public PgpSignEncryptInput setCleartextSignature(boolean cleartextSignature) {
+ public PgpSignEncryptInputParcel setCleartextSignature(boolean cleartextSignature) {
this.mCleartextSignature = cleartextSignature;
return this;
}
@@ -184,7 +220,7 @@ public class PgpSignEncryptInput {
return mCleartextSignature;
}
- public PgpSignEncryptInput setDetachedSignature(boolean detachedSignature) {
+ public PgpSignEncryptInputParcel setDetachedSignature(boolean detachedSignature) {
this.mDetachedSignature = detachedSignature;
return this;
}
@@ -193,7 +229,7 @@ public class PgpSignEncryptInput {
return mDetachedSignature;
}
- public PgpSignEncryptInput setHiddenRecipients(boolean hiddenRecipients) {
+ public PgpSignEncryptInputParcel setHiddenRecipients(boolean hiddenRecipients) {
this.mHiddenRecipients = hiddenRecipients;
return this;
}
@@ -201,5 +237,16 @@ public class PgpSignEncryptInput {
public boolean isHiddenRecipients() {
return mHiddenRecipients;
}
+
+ public static final Creator<PgpSignEncryptInputParcel> CREATOR = new Creator<PgpSignEncryptInputParcel>() {
+ public PgpSignEncryptInputParcel createFromParcel(final Parcel source) {
+ return new PgpSignEncryptInputParcel(source);
+ }
+
+ public PgpSignEncryptInputParcel[] newArray(final int size) {
+ return new PgpSignEncryptInputParcel[size];
+ }
+ };
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
index 16a09e77b..8ecb30cdd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
@@ -33,7 +33,6 @@ import org.spongycastle.openpgp.PGPSignatureGenerator;
import org.spongycastle.openpgp.operator.jcajce.JcePBEKeyEncryptionMethodGenerator;
import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;
import org.spongycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder;
-import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.BaseOperation;
@@ -44,11 +43,15 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
+import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -72,7 +75,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* <p/>
* For a high-level operation based on URIs, see SignEncryptOperation.
*
- * @see org.sufficientlysecure.keychain.pgp.PgpSignEncryptInput
+ * @see PgpSignEncryptInputParcel
* @see org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult
* @see org.sufficientlysecure.keychain.operations.SignEncryptOperation
*/
@@ -99,8 +102,8 @@ public class PgpSignEncryptOperation extends BaseOperation {
/**
* Signs and/or encrypts data based on parameters of class
*/
- public PgpSignEncryptResult execute(PgpSignEncryptInput input,
- InputData inputData, OutputStream outputStream) {
+ public PgpSignEncryptResult execute(PgpSignEncryptInputParcel input, CryptoInputParcel cryptoInput,
+ InputData inputData, OutputStream outputStream) {
int indent = 0;
OperationLog log = new OperationLog();
@@ -128,7 +131,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
ArmoredOutputStream armorOut = null;
OutputStream out;
if (input.isEnableAsciiArmorOutput()) {
- armorOut = new ArmoredOutputStream(outputStream);
+ armorOut = new ArmoredOutputStream(new BufferedOutputStream(outputStream, 1 << 16));
if (input.getVersionHeader() != null) {
armorOut.setHeader("Version", input.getVersionHeader());
}
@@ -145,62 +148,62 @@ public class PgpSignEncryptOperation extends BaseOperation {
CanonicalizedSecretKey signingKey = null;
if (enableSignature) {
+ updateProgress(R.string.progress_extracting_signature_key, 0, 100);
+
try {
// fetch the indicated master key id (the one whose name we sign in)
CanonicalizedSecretKeyRing signingKeyRing =
mProviderHelper.getCanonicalizedSecretKeyRing(input.getSignatureMasterKeyId());
- long signKeyId;
- // use specified signing subkey, or find the one to use
- if (input.getSignatureSubKeyId() == null) {
- signKeyId = signingKeyRing.getSecretSignId();
- } else {
- signKeyId = input.getSignatureSubKeyId();
- }
-
// fetch the specific subkey to sign with, or just use the master key if none specified
- signingKey = signingKeyRing.getSecretKey(signKeyId);
+ signingKey = signingKeyRing.getSecretKey(input.getSignatureSubKeyId());
- } catch (ProviderHelper.NotFoundException | PgpGeneralException e) {
- log.add(LogType.MSG_PSE_ERROR_SIGN_KEY, indent);
- return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
- }
-
- // Make sure we are allowed to sign here!
- if (!signingKey.canSign()) {
- log.add(LogType.MSG_PSE_ERROR_KEY_SIGN, indent);
- return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
- }
-
- // if no passphrase was explicitly set try to get it from the cache service
- if (input.getSignaturePassphrase() == null) {
- try {
- // returns "" if key has no passphrase
- input.setSignaturePassphrase(getCachedPassphrase(signingKey.getKeyId()));
- // TODO
-// log.add(LogType.MSG_DC_PASS_CACHED, indent + 1);
- } catch (PassphraseCacheInterface.NoSecretKeyException e) {
- // TODO
-// log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1);
+ // Make sure we are allowed to sign here!
+ if (!signingKey.canSign()) {
+ log.add(LogType.MSG_PSE_ERROR_KEY_SIGN, indent);
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
}
- // if passphrase was not cached, return here indicating that a passphrase is missing!
- if (input.getSignaturePassphrase() == null) {
- log.add(LogType.MSG_PSE_PENDING_PASSPHRASE, indent + 1);
- PgpSignEncryptResult result = new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE, log);
- result.setKeyIdPassphraseNeeded(signingKey.getKeyId());
- return result;
- }
- }
+ switch (signingKey.getSecretKeyType()) {
+ case DIVERT_TO_CARD:
+ case PASSPHRASE_EMPTY: {
+ if (!signingKey.unlock(new Passphrase())) {
+ throw new AssertionError(
+ "PASSPHRASE_EMPTY/DIVERT_TO_CARD keyphrase not unlocked with empty passphrase."
+ + " This is a programming error!");
+ }
+ break;
+ }
- updateProgress(R.string.progress_extracting_signature_key, 0, 100);
+ case PIN:
+ case PATTERN:
+ case PASSPHRASE: {
+ if (cryptoInput.getPassphrase() == null) {
+ log.add(LogType.MSG_PSE_PENDING_PASSPHRASE, indent + 1);
+ return new PgpSignEncryptResult(log, RequiredInputParcel.createRequiredSignPassphrase(
+ signingKeyRing.getMasterKeyId(), signingKey.getKeyId(),
+ cryptoInput.getSignatureTime()));
+ }
+ if (!signingKey.unlock(cryptoInput.getPassphrase())) {
+ log.add(LogType.MSG_PSE_ERROR_BAD_PASSPHRASE, indent);
+ return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
+ }
+ break;
+ }
+
+ case GNU_DUMMY: {
+ log.add(LogType.MSG_PSE_ERROR_UNLOCK, indent);
+ return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
+ }
+ default: {
+ throw new AssertionError("Unhandled SecretKeyType! (should not happen)");
+ }
- try {
- if (!signingKey.unlock(input.getSignaturePassphrase())) {
- log.add(LogType.MSG_PSE_ERROR_BAD_PASSPHRASE, indent);
- return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
}
+
+ } catch (ProviderHelper.NotFoundException e) {
+ log.add(LogType.MSG_PSE_ERROR_SIGN_KEY, indent);
+ return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
} catch (PgpGeneralException e) {
log.add(LogType.MSG_PSE_ERROR_UNLOCK, indent);
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
@@ -281,8 +284,9 @@ public class PgpSignEncryptOperation extends BaseOperation {
try {
boolean cleartext = input.isCleartextSignature() && input.isEnableAsciiArmorOutput() && !enableEncryption;
- signatureGenerator = signingKey.getSignatureGenerator(
- input.getSignatureHashAlgorithm(), cleartext, input.getNfcSignedHash(), input.getNfcCreationTimestamp());
+ signatureGenerator = signingKey.getDataSignatureGenerator(
+ input.getSignatureHashAlgorithm(), cleartext,
+ cryptoInput.getCryptoData(), cryptoInput.getSignatureTime());
} catch (PgpGeneralException e) {
log.add(LogType.MSG_PSE_ERROR_NFC, indent);
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
@@ -405,7 +409,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
detachedByteOut = new ByteArrayOutputStream();
OutputStream detachedOut = detachedByteOut;
if (input.isEnableAsciiArmorOutput()) {
- detachedArmorOut = new ArmoredOutputStream(detachedOut);
+ detachedArmorOut = new ArmoredOutputStream(new BufferedOutputStream(detachedOut, 1 << 16));
if (input.getVersionHeader() != null) {
detachedArmorOut.setHeader("Version", input.getVersionHeader());
}
@@ -485,19 +489,8 @@ public class PgpSignEncryptOperation extends BaseOperation {
} catch (NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded e) {
// this secret key diverts to a OpenPGP card, throw exception with hash that will be signed
log.add(LogType.MSG_PSE_PENDING_NFC, indent);
- PgpSignEncryptResult result =
- new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_PENDING_NFC, log);
-
- // SignatureSubKeyId can be null.
- if (input.getSignatureSubKeyId() == null) {
- return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
- }
-
- // Note that the checked key here is the master key, not the signing key
- // (although these are always the same on Yubikeys)
- result.setNfcData(input.getSignatureSubKeyId(), e.hashToSign, e.hashAlgo, e.creationTimestamp, input.getSignaturePassphrase());
- Log.d(Constants.TAG, "e.hashToSign" + Hex.toHexString(e.hashToSign));
- return result;
+ return new PgpSignEncryptResult(log, RequiredInputParcel.createNfcSignOperation(
+ e.hashToSign, e.hashAlgo, cryptoInput.getSignatureTime()));
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java
index 975548c95..464de37f5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java
@@ -20,14 +20,10 @@ package org.sufficientlysecure.keychain.pgp;
import android.net.Uri;
import android.os.Parcel;
-import android.os.Parcelable;
-
-import org.sufficientlysecure.keychain.util.Passphrase;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Date;
import java.util.List;
/** This parcel stores the input of one or more PgpSignEncrypt operations.
@@ -42,7 +38,7 @@ import java.util.List;
* left, which will be returned in a byte array as part of the result parcel.
*
*/
-public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable {
+public class SignEncryptParcel extends PgpSignEncryptInputParcel {
public ArrayList<Uri> mInputUris = new ArrayList<>();
public ArrayList<Uri> mOutputUris = new ArrayList<>();
@@ -53,26 +49,7 @@ public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable
}
public SignEncryptParcel(Parcel src) {
-
- // we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable
- mVersionHeader = src.readString();
- mEnableAsciiArmorOutput = src.readInt() == 1;
- mCompressionId = src.readInt();
- mEncryptionMasterKeyIds = src.createLongArray();
- mSymmetricPassphrase = src.readParcelable(Passphrase.class.getClassLoader());
- mSymmetricEncryptionAlgorithm = src.readInt();
- mSignatureMasterKeyId = src.readLong();
- mSignatureSubKeyId = src.readInt() == 1 ? src.readLong() : null;
- mSignatureHashAlgorithm = src.readInt();
- mSignaturePassphrase = src.readParcelable(Passphrase.class.getClassLoader());
- mAdditionalEncryptId = src.readLong();
- mNfcSignedHash = src.createByteArray();
- mNfcCreationTimestamp = src.readInt() == 1 ? new Date(src.readLong()) : null;
- mFailOnMissingEncryptionKeyIds = src.readInt() == 1;
- mCharset = src.readString();
- mCleartextSignature = src.readInt() == 1;
- mDetachedSignature = src.readInt() == 1;
- mHiddenRecipients = src.readInt() == 1;
+ super(src);
mInputUris = src.createTypedArrayList(Uri.CREATOR);
mOutputUris = src.createTypedArrayList(Uri.CREATOR);
@@ -110,34 +87,7 @@ public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable
}
public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mVersionHeader);
- dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
- dest.writeInt(mCompressionId);
- dest.writeLongArray(mEncryptionMasterKeyIds);
- dest.writeParcelable(mSymmetricPassphrase, flags);
- dest.writeInt(mSymmetricEncryptionAlgorithm);
- dest.writeLong(mSignatureMasterKeyId);
- if (mSignatureSubKeyId != null) {
- dest.writeInt(1);
- dest.writeLong(mSignatureSubKeyId);
- } else {
- dest.writeInt(0);
- }
- dest.writeInt(mSignatureHashAlgorithm);
- dest.writeParcelable(mSignaturePassphrase, flags);
- dest.writeLong(mAdditionalEncryptId);
- dest.writeByteArray(mNfcSignedHash);
- if (mNfcCreationTimestamp != null) {
- dest.writeInt(1);
- dest.writeLong(mNfcCreationTimestamp.getTime());
- } else {
- dest.writeInt(0);
- }
- dest.writeInt(mFailOnMissingEncryptionKeyIds ? 1 : 0);
- dest.writeString(mCharset);
- dest.writeInt(mCleartextSignature ? 1 : 0);
- dest.writeInt(mDetachedSignature ? 1 : 0);
- dest.writeInt(mHiddenRecipients ? 1 : 0);
+ super.writeToParcel(dest, flags);
dest.writeTypedList(mInputUris);
dest.writeTypedList(mOutputUris);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
index 681aff56d..b86618a9a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
@@ -1165,7 +1165,7 @@ public class UncachedKeyRing {
}
}
- // If anything changed, save the updated (sub)key
+ // If anything change, save the updated (sub)key
if (modified != resultKey) {
result = replacePublicKey(result, modified);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/CryptoInputParcelCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/CryptoInputParcelCacheService.java
new file mode 100644
index 000000000..e3e39417a
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/CryptoInputParcelCacheService.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.remote;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+
+import org.openintents.openpgp.util.OpenPgpApi;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+
+public class CryptoInputParcelCacheService extends Service {
+
+ public static final String ACTION_ADD = Constants.INTENT_PREFIX + "ADD";
+ public static final String ACTION_GET = Constants.INTENT_PREFIX + "GET";
+
+ public static final String EXTRA_CRYPTO_INPUT_PARCEL = "crypto_input_parcel";
+ public static final String EXTRA_UUID1 = "uuid1";
+ public static final String EXTRA_UUID2 = "uuid2";
+ public static final String EXTRA_MESSENGER = "messenger";
+
+ private static final int MSG_GET_OKAY = 1;
+ private static final int MSG_GET_NOT_FOUND = 2;
+
+ Context mContext;
+
+ private static final UUID NULL_UUID = new UUID(0, 0);
+
+ private ConcurrentHashMap<UUID, CryptoInputParcel> mCache = new ConcurrentHashMap<>();
+
+ public static class InputParcelNotFound extends Exception {
+ public InputParcelNotFound() {
+ }
+
+ public InputParcelNotFound(String name) {
+ super(name);
+ }
+ }
+
+ public static void addCryptoInputParcel(Context context, Intent data, CryptoInputParcel inputParcel) {
+ UUID mTicket = addCryptoInputParcel(context, inputParcel);
+ // And write out the UUID most and least significant bits.
+ data.putExtra(OpenPgpApi.EXTRA_CALL_UUID1, mTicket.getMostSignificantBits());
+ data.putExtra(OpenPgpApi.EXTRA_CALL_UUID2, mTicket.getLeastSignificantBits());
+ }
+
+ public static CryptoInputParcel getCryptoInputParcel(Context context, Intent data) {
+ if (!data.getExtras().containsKey(OpenPgpApi.EXTRA_CALL_UUID1)
+ || !data.getExtras().containsKey(OpenPgpApi.EXTRA_CALL_UUID2)) {
+ return null;
+ }
+ long mostSig = data.getLongExtra(OpenPgpApi.EXTRA_CALL_UUID1, 0);
+ long leastSig = data.getLongExtra(OpenPgpApi.EXTRA_CALL_UUID2, 0);
+ UUID uuid = new UUID(mostSig, leastSig);
+ try {
+ return getCryptoInputParcel(context, uuid);
+ } catch (InputParcelNotFound inputParcelNotFound) {
+ return null;
+ }
+ }
+
+ private static UUID addCryptoInputParcel(Context context, CryptoInputParcel inputParcel) {
+ UUID uuid = UUID.randomUUID();
+
+ Intent intent = new Intent(context, CryptoInputParcelCacheService.class);
+ intent.setAction(ACTION_ADD);
+ intent.putExtra(EXTRA_CRYPTO_INPUT_PARCEL, inputParcel);
+ intent.putExtra(EXTRA_UUID1, uuid.getMostSignificantBits());
+ intent.putExtra(EXTRA_UUID2, uuid.getLeastSignificantBits());
+ context.startService(intent);
+ return uuid;
+ }
+
+ private static CryptoInputParcel getCryptoInputParcel(Context context, UUID uuid) throws InputParcelNotFound {
+ Intent intent = new Intent(context, CryptoInputParcelCacheService.class);
+ intent.setAction(ACTION_GET);
+
+ final Object mutex = new Object();
+ final Message returnMessage = Message.obtain();
+
+ HandlerThread handlerThread = new HandlerThread("getParcelableThread");
+ handlerThread.start();
+ Handler returnHandler = new Handler(handlerThread.getLooper()) {
+ @Override
+ public void handleMessage(Message message) {
+ // copy over result to handle after mutex.wait
+ returnMessage.what = message.what;
+ returnMessage.copyFrom(message);
+ synchronized (mutex) {
+ mutex.notify();
+ }
+ // quit handlerThread
+ getLooper().quit();
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(returnHandler);
+ intent.putExtra(EXTRA_UUID1, uuid.getMostSignificantBits());
+ intent.putExtra(EXTRA_UUID2, uuid.getLeastSignificantBits());
+ intent.putExtra(EXTRA_MESSENGER, messenger);
+ // send intent to this service
+ context.startService(intent);
+
+ // Wait on mutex until parcelable is returned to handlerThread. Note that this local
+ // variable is used in the handler closure above, so it does make sense here!
+ // noinspection SynchronizationOnLocalVariableOrMethodParameter
+ synchronized (mutex) {
+ try {
+ mutex.wait(3000);
+ } catch (InterruptedException e) {
+ // don't care
+ }
+ }
+
+ switch (returnMessage.what) {
+ case MSG_GET_OKAY:
+ Bundle returnData = returnMessage.getData();
+ returnData.setClassLoader(context.getClassLoader());
+ return returnData.getParcelable(EXTRA_CRYPTO_INPUT_PARCEL);
+ case MSG_GET_NOT_FOUND:
+ throw new InputParcelNotFound();
+ default:
+ Log.e(Constants.TAG, "timeout!");
+ throw new InputParcelNotFound("should not happen!");
+ }
+ }
+
+ /**
+ * Executed when service is started by intent
+ */
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+
+ if (intent == null || intent.getAction() == null) {
+ return START_NOT_STICKY;
+ }
+
+ String action = intent.getAction();
+ switch (action) {
+ case ACTION_ADD: {
+ long uuid1 = intent.getLongExtra(EXTRA_UUID1, 0);
+ long uuid2 = intent.getLongExtra(EXTRA_UUID2, 0);
+ UUID uuid = new UUID(uuid1, uuid2);
+ CryptoInputParcel inputParcel = intent.getParcelableExtra(EXTRA_CRYPTO_INPUT_PARCEL);
+ mCache.put(uuid, inputParcel);
+
+ break;
+ }
+ case ACTION_GET: {
+ long uuid1 = intent.getLongExtra(EXTRA_UUID1, 0);
+ long uuid2 = intent.getLongExtra(EXTRA_UUID2, 0);
+ UUID uuid = new UUID(uuid1, uuid2);
+ Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER);
+
+ Message msg = Message.obtain();
+ // UUID.equals isn't well documented; we use compareTo instead.
+ if (NULL_UUID.compareTo(uuid) == 0) {
+ msg.what = MSG_GET_NOT_FOUND;
+ } else {
+ CryptoInputParcel inputParcel = mCache.get(uuid);
+ mCache.remove(uuid);
+ msg.what = MSG_GET_OKAY;
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(EXTRA_CRYPTO_INPUT_PARCEL, inputParcel);
+ msg.setData(bundle);
+ }
+
+ try {
+ messenger.send(msg);
+ } catch (RemoteException e) {
+ Log.e(Constants.TAG, "CryptoInputParcelCacheService: Sending message failed", e);
+ }
+ break;
+ }
+ default: {
+ Log.e(Constants.TAG, "CryptoInputParcelCacheService: Intent or Intent Action not supported!");
+ break;
+ }
+ }
+
+ if (mCache.size() <= 0) {
+ // stop whole service if cache is empty
+ Log.d(Constants.TAG, "CryptoInputParcelCacheService: No passphrases remaining in memory, stopping service!");
+ stopSelf();
+ }
+
+ return START_NOT_STICKY;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mContext = this;
+ Log.d(Constants.TAG, "CryptoInputParcelCacheService, onCreate()");
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ Log.d(Constants.TAG, "CryptoInputParcelCacheService, onDestroy()");
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ public class CryptoInputParcelCacheServiceBinder extends Binder {
+ public CryptoInputParcelCacheService getService() {
+ return CryptoInputParcelCacheService.this;
+ }
+ }
+
+ private final IBinder mBinder = new CryptoInputParcelCacheServiceBinder();
+
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
index bd2866985..c51edf59c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
@@ -18,6 +18,7 @@
package org.sufficientlysecure.keychain.remote;
import android.app.PendingIntent;
+import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
@@ -31,16 +32,15 @@ import org.openintents.openpgp.OpenPgpMetadata;
import org.openintents.openpgp.OpenPgpSignatureResult;
import org.openintents.openpgp.util.OpenPgpApi;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
-import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel;
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
import org.sufficientlysecure.keychain.pgp.PgpConstants;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
-import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInput;
+import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
+import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
@@ -48,8 +48,10 @@ import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity;
import org.sufficientlysecure.keychain.remote.ui.SelectSignKeyIdActivity;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.ui.ImportKeysActivity;
-import org.sufficientlysecure.keychain.ui.NfcActivity;
+import org.sufficientlysecure.keychain.ui.NfcOperationActivity;
import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
import org.sufficientlysecure.keychain.ui.ViewKeyActivity;
import org.sufficientlysecure.keychain.util.InputData;
@@ -60,7 +62,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
-import java.util.Date;
import java.util.Set;
public class OpenPgpService extends RemoteService {
@@ -78,9 +79,6 @@ public class OpenPgpService extends RemoteService {
/**
* Search database for key ids based on emails.
- *
- * @param encryptionUserIds
- * @return
*/
private Intent returnKeyIdsFromEmails(Intent data, String[] encryptionUserIds) {
boolean noUserIdsCheck = (encryptionUserIds == null || encryptionUserIds.length == 0);
@@ -163,52 +161,35 @@ public class OpenPgpService extends RemoteService {
}
}
- private Intent returnPassphraseIntent(Intent data, long keyId) {
- // build PendingIntent for passphrase input
- Intent intent = new Intent(getBaseContext(), PassphraseDialogActivity.class);
- intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, keyId);
- // pass params through to activity that it can be returned again later to repeat pgp operation
- intent.putExtra(PassphraseDialogActivity.EXTRA_DATA, data);
- PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0,
- intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
-
- // return PendingIntent to be executed by client
- Intent result = new Intent();
- result.putExtra(OpenPgpApi.RESULT_INTENT, pi);
- result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
- return result;
- }
+ private static PendingIntent getRequiredInputPendingIntent(Context context,
+ Intent data, RequiredInputParcel requiredInput) {
+
+ switch (requiredInput.mType) {
+ case NFC_DECRYPT:
+ case NFC_SIGN: {
+ // build PendingIntent for YubiKey NFC operations
+ Intent intent = new Intent(context, NfcOperationActivity.class);
+ // pass params through to activity that it can be returned again later to repeat pgp operation
+ intent.putExtra(NfcOperationActivity.EXTRA_SERVICE_INTENT, data);
+ intent.putExtra(NfcOperationActivity.EXTRA_REQUIRED_INPUT, requiredInput);
+ return PendingIntent.getActivity(context, 0, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ }
- private PendingIntent getNfcSignPendingIntent(Intent data, long keyId, Passphrase pin, byte[] hashToSign, int hashAlgo) {
- // build PendingIntent for Yubikey NFC operations
- Intent intent = new Intent(getBaseContext(), NfcActivity.class);
- intent.setAction(NfcActivity.ACTION_SIGN_HASH);
- // pass params through to activity that it can be returned again later to repeat pgp operation
- intent.putExtra(NfcActivity.EXTRA_DATA, data);
- intent.putExtra(NfcActivity.EXTRA_PIN, pin);
- intent.putExtra(NfcActivity.EXTRA_KEY_ID, keyId);
-
- intent.putExtra(NfcActivity.EXTRA_NFC_HASH_TO_SIGN, hashToSign);
- intent.putExtra(NfcActivity.EXTRA_NFC_HASH_ALGO, hashAlgo);
- return PendingIntent.getActivity(getBaseContext(), 0,
- intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
- }
+ case PASSPHRASE: {
+ // build PendingIntent for Passphrase request
+ Intent intent = new Intent(context, PassphraseDialogActivity.class);
+ // pass params through to activity that it can be returned again later to repeat pgp operation
+ intent.putExtra(PassphraseDialogActivity.EXTRA_SERVICE_INTENT, data);
+ intent.putExtra(PassphraseDialogActivity.EXTRA_REQUIRED_INPUT, requiredInput);
+ return PendingIntent.getActivity(context, 0, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ }
- private PendingIntent getNfcDecryptPendingIntent(Intent data, long subKeyId, Passphrase pin, byte[] encryptedSessionKey) {
- // build PendingIntent for Yubikey NFC operations
- Intent intent = new Intent(getBaseContext(), NfcActivity.class);
- intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY);
- // pass params through to activity that it can be returned again later to repeat pgp operation
- intent.putExtra(NfcActivity.EXTRA_DATA, data);
- intent.putExtra(NfcActivity.EXTRA_PIN, pin);
- intent.putExtra(NfcActivity.EXTRA_KEY_ID, subKeyId);
+ default:
+ throw new AssertionError("Unhandled required input type!");
+ }
- intent.putExtra(NfcActivity.EXTRA_NFC_ENC_SESSION_KEY, encryptedSessionKey);
- return PendingIntent.getActivity(getBaseContext(), 0,
- intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
}
private PendingIntent getKeyserverPendingIntent(Intent data, long masterKeyId) {
@@ -240,17 +221,13 @@ public class OpenPgpService extends RemoteService {
try {
boolean asciiArmor = cleartextSign || data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
- Passphrase passphrase = null;
- if (data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE) != null) {
- passphrase = new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE));
- }
-
- byte[] nfcSignedHash = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_SIGNED_HASH);
- if (nfcSignedHash != null) {
- Log.d(Constants.TAG, "nfcSignedHash:" + Hex.toHexString(nfcSignedHash));
- } else {
- Log.d(Constants.TAG, "nfcSignedHash: null");
- }
+ // sign-only
+ PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel()
+ .setEnableAsciiArmorOutput(asciiArmor)
+ .setCleartextSignature(cleartextSign)
+ .setDetachedSignature(!cleartextSign)
+ .setVersionHeader(null)
+ .setSignatureHashAlgorithm(PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED);
Intent signKeyIdIntent = getSignKeyMasterId(data);
// NOTE: Fallback to return account settings (Old API)
@@ -258,17 +235,21 @@ public class OpenPgpService extends RemoteService {
== OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED) {
return signKeyIdIntent;
}
+
long signKeyId = signKeyIdIntent.getLongExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, Constants.key.none);
if (signKeyId == Constants.key.none) {
- Log.e(Constants.TAG, "No signing key given!");
- }
+ throw new Exception("No signing key given");
+ } else {
+ pseInput.setSignatureMasterKeyId(signKeyId);
- // carefully: only set if timestamp exists
- Date nfcCreationDate = null;
- long nfcCreationTimestamp = data.getLongExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, -1);
- Log.d(Constants.TAG, "nfcCreationTimestamp: " + nfcCreationTimestamp);
- if (nfcCreationTimestamp != -1) {
- nfcCreationDate = new Date(nfcCreationTimestamp);
+ // get first usable subkey capable of signing
+ try {
+ long signSubKeyId = mProviderHelper.getCachedPublicKeyRing(
+ pseInput.getSignatureMasterKeyId()).getSecretSignId();
+ pseInput.setSignatureSubKeyId(signSubKeyId);
+ } catch (PgpKeyNotFoundException e) {
+ throw new Exception("signing subkey not found!", e);
+ }
}
// Get Input- and OutputStream from ParcelFileDescriptor
@@ -281,42 +262,31 @@ public class OpenPgpService extends RemoteService {
long inputLength = is.available();
InputData inputData = new InputData(is, inputLength);
- // sign-only
- PgpSignEncryptInput pseInput = new PgpSignEncryptInput()
- .setSignaturePassphrase(passphrase)
- .setEnableAsciiArmorOutput(asciiArmor)
- .setCleartextSignature(cleartextSign)
- .setDetachedSignature(!cleartextSign)
- .setVersionHeader(null)
- .setSignatureHashAlgorithm(PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED)
- .setSignatureMasterKeyId(signKeyId)
- .setNfcState(nfcSignedHash, nfcCreationDate);
+ CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
+ if (inputParcel == null) {
+ inputParcel = new CryptoInputParcel();
+ }
+ // override passphrase in input parcel if given by API call
+ if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) {
+ inputParcel = new CryptoInputParcel(inputParcel.getSignatureTime(),
+ new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)));
+ }
// execute PGP operation!
PgpSignEncryptOperation pse = new PgpSignEncryptOperation(this, new ProviderHelper(getContext()), null);
- PgpSignEncryptResult pgpResult = pse.execute(pseInput, inputData, os);
+ PgpSignEncryptResult pgpResult = pse.execute(pseInput, inputParcel, inputData, os);
if (pgpResult.isPending()) {
- if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) ==
- PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) {
- return returnPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded());
- } else if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_NFC) ==
- PgpSignEncryptResult.RESULT_PENDING_NFC) {
- // return PendingIntent to execute NFC activity
- // pass through the signature creation timestamp to be used again on second execution
- // of PgpSignEncrypt when we have the signed hash!
- data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, pgpResult.getNfcTimestamp().getTime());
-
- // return PendingIntent to be executed by client
- Intent result = new Intent();
- result.putExtra(OpenPgpApi.RESULT_INTENT,
- getNfcSignPendingIntent(data, pgpResult.getNfcKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcHash(), pgpResult.getNfcAlgo()));
- result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
- return result;
- } else {
- throw new PgpGeneralException(
- "Encountered unhandled type of pending action not supported by API!");
- }
+
+ RequiredInputParcel requiredInput = pgpResult.getRequiredInputParcel();
+ PendingIntent pIntent = getRequiredInputPendingIntent(getBaseContext(), data, requiredInput);
+
+ // return PendingIntent to be executed by client
+ Intent result = new Intent();
+ result.putExtra(OpenPgpApi.RESULT_INTENT, pIntent);
+ result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
+ return result;
+
} else if (pgpResult.success()) {
Intent result = new Intent();
if (pgpResult.getDetachedSignature() != null && !cleartextSign) {
@@ -372,11 +342,6 @@ public class OpenPgpService extends RemoteService {
compressionId = CompressionAlgorithmTags.UNCOMPRESSED;
}
- Passphrase passphrase = null;
- if (data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE) != null) {
- passphrase = new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE));
- }
-
// first try to get key ids from non-ambiguous key id extra
long[] keyIds = data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS);
if (keyIds == null) {
@@ -401,9 +366,8 @@ public class OpenPgpService extends RemoteService {
long inputLength = is.available();
InputData inputData = new InputData(is, inputLength, originalFilename);
- PgpSignEncryptInput pseInput = new PgpSignEncryptInput();
- pseInput.setSignaturePassphrase(passphrase)
- .setEnableAsciiArmorOutput(asciiArmor)
+ PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel();
+ pseInput.setEnableAsciiArmorOutput(asciiArmor)
.setVersionHeader(null)
.setCompressionId(compressionId)
.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED)
@@ -420,49 +384,49 @@ public class OpenPgpService extends RemoteService {
}
long signKeyId = signKeyIdIntent.getLongExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, Constants.key.none);
if (signKeyId == Constants.key.none) {
- Log.e(Constants.TAG, "No signing key given!");
- }
+ throw new Exception("No signing key given");
+ } else {
+ pseInput.setSignatureMasterKeyId(signKeyId);
- byte[] nfcSignedHash = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_SIGNED_HASH);
- // carefully: only set if timestamp exists
- Date nfcCreationDate = null;
- long nfcCreationTimestamp = data.getLongExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, -1);
- if (nfcCreationTimestamp != -1) {
- nfcCreationDate = new Date(nfcCreationTimestamp);
+ // get first usable subkey capable of signing
+ try {
+ long signSubKeyId = mProviderHelper.getCachedPublicKeyRing(
+ pseInput.getSignatureMasterKeyId()).getSecretSignId();
+ pseInput.setSignatureSubKeyId(signSubKeyId);
+ } catch (PgpKeyNotFoundException e) {
+ throw new Exception("signing subkey not found!", e);
+ }
}
// sign and encrypt
pseInput.setSignatureHashAlgorithm(PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED)
- .setSignatureMasterKeyId(signKeyId)
- .setNfcState(nfcSignedHash, nfcCreationDate)
.setAdditionalEncryptId(signKeyId); // add sign key for encryption
}
+ CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
+ if (inputParcel == null) {
+ inputParcel = new CryptoInputParcel();
+ }
+ // override passphrase in input parcel if given by API call
+ if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) {
+ inputParcel = new CryptoInputParcel(inputParcel.getSignatureTime(),
+ new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)));
+ }
+
PgpSignEncryptOperation op = new PgpSignEncryptOperation(this, new ProviderHelper(getContext()), null);
// execute PGP operation!
- PgpSignEncryptResult pgpResult = op.execute(pseInput, inputData, os);
+ PgpSignEncryptResult pgpResult = op.execute(pseInput, inputParcel, inputData, os);
if (pgpResult.isPending()) {
- if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) ==
- PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) {
- return returnPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded());
- } else if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_NFC) ==
- PgpSignEncryptResult.RESULT_PENDING_NFC) {
- // return PendingIntent to execute NFC activity
- // pass through the signature creation timestamp to be used again on second execution
- // of PgpSignEncrypt when we have the signed hash!
- data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, pgpResult.getNfcTimestamp().getTime());
- // return PendingIntent to be executed by client
- Intent result = new Intent();
- result.putExtra(OpenPgpApi.RESULT_INTENT,
- getNfcSignPendingIntent(data, pgpResult.getNfcKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcHash(), pgpResult.getNfcAlgo()));
- result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
- return result;
- } else {
- throw new PgpGeneralException(
- "Encountered unhandled type of pending action not supported by API!");
- }
+ RequiredInputParcel requiredInput = pgpResult.getRequiredInputParcel();
+ PendingIntent pIntent = getRequiredInputPendingIntent(getBaseContext(), data, requiredInput);
+
+ // return PendingIntent to be executed by client
+ Intent result = new Intent();
+ result.putExtra(OpenPgpApi.RESULT_INTENT, pIntent);
+ result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
+ return result;
} else if (pgpResult.success()) {
Intent result = new Intent();
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
@@ -511,11 +475,6 @@ public class OpenPgpService extends RemoteService {
os = new ParcelFileDescriptor.AutoCloseOutputStream(output);
}
- Passphrase passphrase = null;
- if (data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE) != null) {
- passphrase = new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE));
- }
-
String currentPkg = getCurrentCallingPackage();
Set<Long> allowedKeyIds;
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 7) {
@@ -533,42 +492,37 @@ public class OpenPgpService extends RemoteService {
this, new ProviderHelper(getContext()), null, inputData, os
);
- byte[] nfcDecryptedSessionKey = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY);
+ CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
+ if (inputParcel == null) {
+ inputParcel = new CryptoInputParcel();
+ }
+ // override passphrase in input parcel if given by API call
+ if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) {
+ inputParcel = new CryptoInputParcel(inputParcel.getSignatureTime(),
+ new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)));
+ }
byte[] detachedSignature = data.getByteArrayExtra(OpenPgpApi.EXTRA_DETACHED_SIGNATURE);
// allow only private keys associated with accounts of this app
// no support for symmetric encryption
- builder.setPassphrase(passphrase)
- .setAllowSymmetricDecryption(false)
+ builder.setAllowSymmetricDecryption(false)
.setAllowedKeyIds(allowedKeyIds)
.setDecryptMetadataOnly(decryptMetadataOnly)
- .setNfcState(nfcDecryptedSessionKey)
.setDetachedSignature(detachedSignature);
- DecryptVerifyResult pgpResult = builder.build().execute();
+ DecryptVerifyResult pgpResult = builder.build().execute(inputParcel);
if (pgpResult.isPending()) {
- if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) ==
- DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) {
- return returnPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded());
- } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) ==
- DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) {
- throw new PgpGeneralException(
- "Decryption of symmetric content not supported by API!");
- } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) ==
- DecryptVerifyResult.RESULT_PENDING_NFC) {
-
- // return PendingIntent to be executed by client
- Intent result = new Intent();
- result.putExtra(OpenPgpApi.RESULT_INTENT,
- getNfcDecryptPendingIntent(data, pgpResult.getNfcSubKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey()));
- result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
- return result;
- } else {
- throw new PgpGeneralException(
- "Encountered unhandled type of pending action not supported by API!");
- }
+ // prepare and return PendingIntent to be executed by client
+ RequiredInputParcel requiredInput = pgpResult.getRequiredInputParcel();
+ PendingIntent pIntent = getRequiredInputPendingIntent(getBaseContext(), data, requiredInput);
+
+ Intent result = new Intent();
+ result.putExtra(OpenPgpApi.RESULT_INTENT, pIntent);
+ result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
+ return result;
+
} else if (pgpResult.success()) {
Intent result = new Intent();
@@ -754,7 +708,6 @@ public class OpenPgpService extends RemoteService {
* - has supported API version
* - is allowed to call the service (access has been granted)
*
- * @param data
* @return null if everything is okay, or a Bundle with an error/PendingIntent
*/
private Intent checkRequirements(Intent data) {
@@ -794,9 +747,7 @@ public class OpenPgpService extends RemoteService {
return null;
}
- // TODO: multi-threading
private final IOpenPgpService.Stub mBinder = new IOpenPgpService.Stub() {
-
@Override
public Intent execute(Intent data, ParcelFileDescriptor input, ParcelFileDescriptor output) {
try {
@@ -806,30 +757,42 @@ public class OpenPgpService extends RemoteService {
}
String action = data.getAction();
- if (OpenPgpApi.ACTION_CLEARTEXT_SIGN.equals(action)) {
- return signImpl(data, input, output, true);
- } else if (OpenPgpApi.ACTION_SIGN.equals(action)) {
- // DEPRECATED: same as ACTION_CLEARTEXT_SIGN
- Log.w(Constants.TAG, "You are using a deprecated API call, please use ACTION_CLEARTEXT_SIGN instead of ACTION_SIGN!");
- return signImpl(data, input, output, true);
- } else if (OpenPgpApi.ACTION_DETACHED_SIGN.equals(action)) {
- return signImpl(data, input, output, false);
- } else if (OpenPgpApi.ACTION_ENCRYPT.equals(action)) {
- return encryptAndSignImpl(data, input, output, false);
- } else if (OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(action)) {
- return encryptAndSignImpl(data, input, output, true);
- } else if (OpenPgpApi.ACTION_DECRYPT_VERIFY.equals(action)) {
- return decryptAndVerifyImpl(data, input, output, false);
- } else if (OpenPgpApi.ACTION_DECRYPT_METADATA.equals(action)) {
- return decryptAndVerifyImpl(data, input, output, true);
- } else if (OpenPgpApi.ACTION_GET_SIGN_KEY_ID.equals(action)) {
- return getSignKeyIdImpl(data);
- } else if (OpenPgpApi.ACTION_GET_KEY_IDS.equals(action)) {
- return getKeyIdsImpl(data);
- } else if (OpenPgpApi.ACTION_GET_KEY.equals(action)) {
- return getKeyImpl(data);
- } else {
- return null;
+ switch (action) {
+ case OpenPgpApi.ACTION_CLEARTEXT_SIGN: {
+ return signImpl(data, input, output, true);
+ }
+ case OpenPgpApi.ACTION_SIGN: {
+ // DEPRECATED: same as ACTION_CLEARTEXT_SIGN
+ Log.w(Constants.TAG, "You are using a deprecated API call, please use ACTION_CLEARTEXT_SIGN instead of ACTION_SIGN!");
+ return signImpl(data, input, output, true);
+ }
+ case OpenPgpApi.ACTION_DETACHED_SIGN: {
+ return signImpl(data, input, output, false);
+ }
+ case OpenPgpApi.ACTION_ENCRYPT: {
+ return encryptAndSignImpl(data, input, output, false);
+ }
+ case OpenPgpApi.ACTION_SIGN_AND_ENCRYPT: {
+ return encryptAndSignImpl(data, input, output, true);
+ }
+ case OpenPgpApi.ACTION_DECRYPT_VERIFY: {
+ return decryptAndVerifyImpl(data, input, output, false);
+ }
+ case OpenPgpApi.ACTION_DECRYPT_METADATA: {
+ return decryptAndVerifyImpl(data, input, output, true);
+ }
+ case OpenPgpApi.ACTION_GET_SIGN_KEY_ID: {
+ return getSignKeyIdImpl(data);
+ }
+ case OpenPgpApi.ACTION_GET_KEY_IDS: {
+ return getKeyIdsImpl(data);
+ }
+ case OpenPgpApi.ACTION_GET_KEY: {
+ return getKeyImpl(data);
+ }
+ default: {
+ return null;
+ }
}
} finally {
// always close input and output file descriptors even in error cases
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java
index 507d4dea5..e19757d65 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java
@@ -31,7 +31,7 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp
import org.sufficientlysecure.keychain.operations.results.SingletonResult;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.AccountSettings;
-import org.sufficientlysecure.keychain.ui.BaseActivity;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.util.Log;
public class AccountSettingsActivity extends BaseActivity {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java
index 407480c98..2b71d6dc1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java
@@ -40,9 +40,7 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.AppSettings;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
-import org.sufficientlysecure.keychain.ui.BaseActivity;
-import org.sufficientlysecure.keychain.ui.dialog.AddSubkeyDialogFragment;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.dialog.AdvancedAppSettingsDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
index e8c3e4511..f312c0d44 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
@@ -38,7 +38,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.AccountSettings;
import org.sufficientlysecure.keychain.remote.AppSettings;
-import org.sufficientlysecure.keychain.ui.BaseActivity;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.SelectPublicKeyFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java
index 98a44466d..cb9f46f7f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java
@@ -29,7 +29,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
-import org.sufficientlysecure.keychain.ui.BaseActivity;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity;
import org.sufficientlysecure.keychain.util.Log;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java
index 57a11de21..a7571a7ac 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java
@@ -22,10 +22,14 @@ import android.os.Parcel;
import android.os.Parcelable;
import java.io.Serializable;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
+import java.util.Date;
+import java.util.Map;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
/**
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
index e210536fd..63ea6285c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -46,7 +46,6 @@ import org.sufficientlysecure.keychain.operations.results.CertifyResult;
import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.operations.results.DeleteResult;
-import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
import org.sufficientlysecure.keychain.operations.results.ExportResult;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.operations.results.CertifyResult;
@@ -68,6 +67,7 @@ import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler.MessageStatus;
import org.sufficientlysecure.keychain.util.FileHelper;
import org.sufficientlysecure.keychain.util.InputData;
@@ -159,8 +159,6 @@ public class KeychainIntentService extends IntentService implements Progressable
// decrypt/verify
public static final String DECRYPT_CIPHERTEXT_BYTES = "ciphertext_bytes";
- public static final String DECRYPT_PASSPHRASE = "passphrase";
- public static final String DECRYPT_NFC_DECRYPTED_SESSION_KEY = "nfc_decrypted_session_key";
// keybase proof
public static final String KEYBASE_REQUIRED_FINGERPRINT = "keybase_required_fingerprint";
@@ -169,6 +167,7 @@ public class KeychainIntentService extends IntentService implements Progressable
// save keyring
public static final String EDIT_KEYRING_PARCEL = "save_parcel";
public static final String EDIT_KEYRING_PASSPHRASE = "passphrase";
+ public static final String EXTRA_CRYPTO_INPUT = "crypto_input";
// delete keyring(s)
public static final String DELETE_KEY_LIST = "delete_list";
@@ -193,7 +192,7 @@ public class KeychainIntentService extends IntentService implements Progressable
// promote key
public static final String PROMOTE_MASTER_KEY_ID = "promote_master_key_id";
- public static final String PROMOTE_TYPE = "promote_type";
+ public static final String PROMOTE_CARD_AID = "promote_card_aid";
// consolidate
public static final String CONSOLIDATE_RECOVERY = "consolidate_recovery";
@@ -260,11 +259,12 @@ public class KeychainIntentService extends IntentService implements Progressable
// Input
CertifyActionsParcel parcel = data.getParcelable(CERTIFY_PARCEL);
+ CryptoInputParcel cryptoInput = data.getParcelable(EXTRA_CRYPTO_INPUT);
String keyServerUri = data.getString(UPLOAD_KEY_SERVER);
// Operation
CertifyOperation op = new CertifyOperation(this, providerHelper, this, mActionCanceled);
- CertifyResult result = op.certify(parcel, keyServerUri);
+ CertifyResult result = op.certify(parcel, cryptoInput, keyServerUri);
// Result
sendMessageToHandler(MessageStatus.OKAY, result);
@@ -289,27 +289,20 @@ public class KeychainIntentService extends IntentService implements Progressable
case ACTION_DECRYPT_METADATA: {
try {
- /* Input */
- Passphrase passphrase = data.getParcelable(DECRYPT_PASSPHRASE);
- byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
+ /* Input */
+ CryptoInputParcel cryptoInput = data.getParcelable(EXTRA_CRYPTO_INPUT);
InputData inputData = createDecryptInputData(data);
- /* Operation */
-
- Bundle resultData = new Bundle();
-
// verifyText and decrypt returning additional resultData values for the
// verification of signatures
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
this, new ProviderHelper(this), this, inputData, null
);
builder.setAllowSymmetricDecryption(true)
- .setPassphrase(passphrase)
- .setDecryptMetadataOnly(true)
- .setNfcState(nfcDecryptedSessionKey);
+ .setDecryptMetadataOnly(true);
- DecryptVerifyResult decryptVerifyResult = builder.build().execute();
+ DecryptVerifyResult decryptVerifyResult = builder.build().execute(cryptoInput);
sendMessageToHandler(MessageStatus.OKAY, decryptVerifyResult);
} catch (Exception e) {
@@ -384,7 +377,8 @@ public class KeychainIntentService extends IntentService implements Progressable
);
builder.setSignedLiteralData(true).setRequiredSignerFingerprint(requiredFingerprint);
- DecryptVerifyResult decryptVerifyResult = builder.build().execute();
+ DecryptVerifyResult decryptVerifyResult = builder.build().execute(
+ new CryptoInputParcel());
outStream.close();
if (!decryptVerifyResult.success()) {
@@ -419,15 +413,13 @@ public class KeychainIntentService extends IntentService implements Progressable
case ACTION_DECRYPT_VERIFY: {
try {
- /* Input */
- Passphrase passphrase = data.getParcelable(DECRYPT_PASSPHRASE);
- byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
+ /* Input */
+ CryptoInputParcel cryptoInput = data.getParcelable(EXTRA_CRYPTO_INPUT);
InputData inputData = createDecryptInputData(data);
OutputStream outStream = createCryptOutputStream(data);
- /* Operation */
-
+ /* Operation */
Bundle resultData = new Bundle();
// verifyText and decrypt returning additional resultData values for the
@@ -436,24 +428,22 @@ public class KeychainIntentService extends IntentService implements Progressable
this, new ProviderHelper(this), this,
inputData, outStream
);
- builder.setAllowSymmetricDecryption(true)
- .setPassphrase(passphrase)
- .setNfcState(nfcDecryptedSessionKey);
+ builder.setAllowSymmetricDecryption(true);
- DecryptVerifyResult decryptVerifyResult = builder.build().execute();
+ DecryptVerifyResult decryptVerifyResult = builder.build().execute(cryptoInput);
outStream.close();
resultData.putParcelable(DecryptVerifyResult.EXTRA_RESULT, decryptVerifyResult);
- /* Output */
-
+ /* Output */
finalizeDecryptOutputStream(data, resultData, outStream);
-
Log.logDebugBundle(resultData, "resultData");
sendMessageToHandler(MessageStatus.OKAY, resultData);
- } catch (Exception e) {
+
+ } catch (IOException | PgpGeneralException e) {
+ // TODO get rid of this!
sendErrorToHandler(e);
}
@@ -478,11 +468,11 @@ public class KeychainIntentService extends IntentService implements Progressable
// Input
SaveKeyringParcel saveParcel = data.getParcelable(EDIT_KEYRING_PARCEL);
- Passphrase passphrase = data.getParcelable(EDIT_KEYRING_PASSPHRASE);
+ CryptoInputParcel cryptoInput = data.getParcelable(EXTRA_CRYPTO_INPUT);
// Operation
EditKeyOperation op = new EditKeyOperation(this, providerHelper, this, mActionCanceled);
- EditKeyResult result = op.execute(saveParcel, passphrase);
+ OperationResult result = op.execute(saveParcel, cryptoInput);
// Result
sendMessageToHandler(MessageStatus.OKAY, result);
@@ -492,11 +482,12 @@ public class KeychainIntentService extends IntentService implements Progressable
case ACTION_PROMOTE_KEYRING: {
// Input
- long keyRingId = data.getInt(EXPORT_KEY_RING_MASTER_KEY_ID);
+ long keyRingId = data.getLong(PROMOTE_MASTER_KEY_ID);
+ byte[] cardAid = data.getByteArray(PROMOTE_CARD_AID);
// Operation
PromoteKeyOperation op = new PromoteKeyOperation(this, providerHelper, this, mActionCanceled);
- PromoteKeyResult result = op.execute(keyRingId);
+ PromoteKeyResult result = op.execute(keyRingId, cardAid);
// Result
sendMessageToHandler(MessageStatus.OKAY, result);
@@ -553,11 +544,12 @@ public class KeychainIntentService extends IntentService implements Progressable
// Input
SignEncryptParcel inputParcel = data.getParcelable(SIGN_ENCRYPT_PARCEL);
+ CryptoInputParcel cryptoInput = data.getParcelable(EXTRA_CRYPTO_INPUT);
// Operation
SignEncryptOperation op = new SignEncryptOperation(
this, new ProviderHelper(this), this, mActionCanceled);
- SignEncryptResult result = op.execute(inputParcel);
+ SignEncryptResult result = op.execute(inputParcel, cryptoInput);
// Result
sendMessageToHandler(MessageStatus.OKAY, result);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
index 93a2bee23..78137170d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
@@ -60,18 +60,18 @@ import java.util.Date;
*
* Caching behavior for subkeys depends on the cacheSubs preference:
*
- * - If cacheSubs is NOT set, passphrases will be cached and retrieved by master key id. The
- * checks for special subkeys will still be done, but otherwise it is assumed that all subkeys
- * from the same master key will use the same passphrase. This can lead to bad passphrase
- * errors if two subkeys are encrypted differently. This is the default behavior.
+ * - If cacheSubs is NOT set, passphrases will be cached and retrieved by master key id. The
+ * checks for special subkeys will still be done, but otherwise it is assumed that all subkeys
+ * from the same master key will use the same passphrase. This can lead to bad passphrase
+ * errors if two subkeys are encrypted differently. This is the default behavior.
*
- * - If cacheSubs IS set, passphrases will be cached per subkey id. This means that if a keyring
- * has two subkeys for different purposes, passphrases will be cached independently and the
- * user will be asked for a passphrase once per subkey even if it is the same one. This mode
- * of operation is more precise, since we can assume that all passphrases returned from cache
- * will be correct without fail. Since keyrings with differently encrypted subkeys are a very
- * rare occurrence, and caching by keyring is what the user expects in the vast majority of
- * cases, this is not the default behavior.
+ * - If cacheSubs IS set, passphrases will be cached per subkey id. This means that if a keyring
+ * has two subkeys for different purposes, passphrases will be cached independently and the
+ * user will be asked for a passphrase once per subkey even if it is the same one. This mode
+ * of operation is more precise, since we can assume that all passphrases returned from cache
+ * will be correct without fail. Since keyrings with differently encrypted subkeys are a very
+ * rare occurrence, and caching by keyring is what the user expects in the vast majority of
+ * cases, this is not the default behavior.
*
*/
public class PassphraseCacheService extends Service {
@@ -123,7 +123,7 @@ public class PassphraseCacheService extends Service {
public static void addCachedPassphrase(Context context, long masterKeyId, long subKeyId,
Passphrase passphrase,
String primaryUserId) {
- Log.d(Constants.TAG, "PassphraseCacheService.cacheNewPassphrase() for " + masterKeyId);
+ Log.d(Constants.TAG, "PassphraseCacheService.addCachedPassphrase() for " + masterKeyId);
Intent intent = new Intent(context, PassphraseCacheService.class);
intent.setAction(ACTION_PASSPHRASE_CACHE_ADD);
@@ -137,10 +137,23 @@ public class PassphraseCacheService extends Service {
context.startService(intent);
}
+ public static void clearCachedPassphrase(Context context, long masterKeyId, long subKeyId) {
+ Log.d(Constants.TAG, "PassphraseCacheService.clearCachedPassphrase() for " + masterKeyId);
+
+ Intent intent = new Intent(context, PassphraseCacheService.class);
+ intent.setAction(ACTION_PASSPHRASE_CACHE_CLEAR);
+
+ intent.putExtra(EXTRA_KEY_ID, masterKeyId);
+ intent.putExtra(EXTRA_SUBKEY_ID, subKeyId);
+
+ context.startService(intent);
+ }
+
+
/**
* Gets a cached passphrase from memory by sending an intent to the service. This method is
* designed to wait until the service returns the passphrase.
-
+ *
* @return passphrase or null (if no passphrase is cached for this keyId)
*/
public static Passphrase getCachedPassphrase(Context context, long masterKeyId, long subKeyId) throws KeyNotFoundException {
@@ -218,7 +231,7 @@ public class PassphraseCacheService extends Service {
}
// on "none" key, just do nothing
- if(masterKeyId == Constants.key.none) {
+ if (masterKeyId == Constants.key.none) {
return null;
}
@@ -232,11 +245,11 @@ public class PassphraseCacheService extends Service {
switch (keyType) {
case DIVERT_TO_CARD:
- if (Preferences.getPreferences(this).useDefaultYubikeyPin()) {
- Log.d(Constants.TAG, "PassphraseCacheService: Using default Yubikey PIN: 123456");
- return new Passphrase("123456"); // default Yubikey PIN, see http://www.yubico.com/2012/12/yubikey-neo-openpgp/
+ if (Preferences.getPreferences(this).useDefaultYubiKeyPin()) {
+ Log.d(Constants.TAG, "PassphraseCacheService: Using default YubiKey PIN: 123456");
+ return new Passphrase("123456"); // default YubiKey PIN, see http://www.yubico.com/2012/12/yubikey-neo-openpgp/
} else {
- Log.d(Constants.TAG, "PassphraseCacheService: NOT using default Yubikey PIN");
+ Log.d(Constants.TAG, "PassphraseCacheService: NOT using default YubiKey PIN");
break;
}
case PASSPHRASE_EMPTY:
@@ -310,11 +323,11 @@ public class PassphraseCacheService extends Service {
/**
* Build pending intent that is executed by alarm manager to time out a specific passphrase
*/
- private static PendingIntent buildIntent(Context context, long keyId) {
+ private static PendingIntent buildIntent(Context context, long referenceKeyId) {
Intent intent = new Intent(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE);
- intent.putExtra(EXTRA_KEY_ID, keyId);
+ intent.putExtra(EXTRA_KEY_ID, referenceKeyId);
// request code should be unique for each PendingIntent, thus keyId is used
- return PendingIntent.getBroadcast(context, (int) keyId, intent,
+ return PendingIntent.getBroadcast(context, (int) referenceKeyId, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
}
@@ -325,11 +338,17 @@ public class PassphraseCacheService extends Service {
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(Constants.TAG, "PassphraseCacheService.onStartCommand()");
+ if (intent == null || intent.getAction() == null) {
+ updateService();
+ return START_STICKY;
+ }
+
// register broadcastreceiver
registerReceiver();
- if (intent != null && intent.getAction() != null) {
- if (ACTION_PASSPHRASE_CACHE_ADD.equals(intent.getAction())) {
+ String action = intent.getAction();
+ switch (action) {
+ case ACTION_PASSPHRASE_CACHE_ADD: {
long ttl = intent.getLongExtra(EXTRA_TTL, DEFAULT_TTL);
long masterKeyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
long subKeyId = intent.getLongExtra(EXTRA_SUBKEY_ID, -1);
@@ -343,28 +362,19 @@ public class PassphraseCacheService extends Service {
);
// if we don't cache by specific subkey id, or the requested subkey is the master key,
- // just add master key id to the cache
- if (subKeyId == masterKeyId || !Preferences.getPreferences(mContext).getPassphraseCacheSubs()) {
- mPassphraseCache.put(masterKeyId, new CachedPassphrase(passphrase, primaryUserID));
- if (ttl > 0) {
- // register new alarm with keyId for this passphrase
- long triggerTime = new Date().getTime() + (ttl * 1000);
- AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
- am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, masterKeyId));
- }
- } else {
- // otherwise, add this specific subkey to the cache
- mPassphraseCache.put(subKeyId, new CachedPassphrase(passphrase, primaryUserID));
- if (ttl > 0) {
- // register new alarm with keyId for this passphrase
- long triggerTime = new Date().getTime() + (ttl * 1000);
- AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
- am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, subKeyId));
- }
+ // just add master key id to the cache, otherwise, add this specific subkey to the cache
+ long referenceKeyId =
+ Preferences.getPreferences(mContext).getPassphraseCacheSubs() ? subKeyId : masterKeyId;
+ mPassphraseCache.put(referenceKeyId, new CachedPassphrase(passphrase, primaryUserID));
+ if (ttl > 0) {
+ // register new alarm with keyId for this passphrase
+ long triggerTime = new Date().getTime() + (ttl * 1000);
+ AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
+ am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, referenceKeyId));
}
-
- updateService();
- } else if (ACTION_PASSPHRASE_CACHE_GET.equals(intent.getAction())) {
+ break;
+ }
+ case ACTION_PASSPHRASE_CACHE_GET: {
long masterKeyId = intent.getLongExtra(EXTRA_KEY_ID, Constants.key.symmetric);
long subKeyId = intent.getLongExtra(EXTRA_SUBKEY_ID, Constants.key.symmetric);
Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER);
@@ -392,22 +402,42 @@ public class PassphraseCacheService extends Service {
} catch (RemoteException e) {
Log.e(Constants.TAG, "PassphraseCacheService: Sending message failed", e);
}
- } else if (ACTION_PASSPHRASE_CACHE_CLEAR.equals(intent.getAction())) {
+ break;
+ }
+ case ACTION_PASSPHRASE_CACHE_CLEAR: {
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
- // Stop all ttl alarms
- for (int i = 0; i < mPassphraseCache.size(); i++) {
- am.cancel(buildIntent(this, mPassphraseCache.keyAt(i)));
- }
+ if (intent.hasExtra(EXTRA_SUBKEY_ID) && intent.hasExtra(EXTRA_KEY_ID)) {
- mPassphraseCache.clear();
+ long referenceKeyId;
+ if (Preferences.getPreferences(mContext).getPassphraseCacheSubs()) {
+ referenceKeyId = intent.getLongExtra(EXTRA_KEY_ID, 0L);
+ } else {
+ referenceKeyId = intent.getLongExtra(EXTRA_SUBKEY_ID, 0L);
+ }
+ // Stop specific ttl alarm and
+ am.cancel(buildIntent(this, referenceKeyId));
+ mPassphraseCache.delete(referenceKeyId);
- updateService();
- } else {
+ } else {
+
+ // Stop all ttl alarms
+ for (int i = 0; i < mPassphraseCache.size(); i++) {
+ am.cancel(buildIntent(this, mPassphraseCache.keyAt(i)));
+ }
+ mPassphraseCache.clear();
+
+ }
+ break;
+ }
+ default: {
Log.e(Constants.TAG, "PassphraseCacheService: Intent or Intent Action not supported!");
+ break;
}
}
+ updateService();
+
return START_STICKY;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
index 9fd278c13..2e0524141 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
@@ -82,10 +82,14 @@ public class SaveKeyringParcel implements Parcelable {
mRevokeSubKeys = new ArrayList<>();
}
+ public boolean isEmpty() {
+ return isRestrictedOnly() && mChangeSubKeys.isEmpty();
+ }
+
/** Returns true iff this parcel does not contain any operations which require a passphrase. */
public boolean isRestrictedOnly() {
if (mNewUnlock != null || !mAddUserIds.isEmpty() || !mAddUserAttribute.isEmpty()
- || !mAddSubKeys.isEmpty() || mChangePrimaryUserId != null || !mRevokeSubKeys .isEmpty()
+ || !mAddSubKeys.isEmpty() || mChangePrimaryUserId != null || !mRevokeUserIds.isEmpty()
|| !mRevokeSubKeys.isEmpty()) {
return false;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ServiceProgressHandler.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ServiceProgressHandler.java
index 4bd3481e6..430d8a49b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ServiceProgressHandler.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ServiceProgressHandler.java
@@ -18,6 +18,7 @@
package org.sufficientlysecure.keychain.service;
import android.app.Activity;
+import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -26,6 +27,7 @@ import android.support.v4.app.FragmentManager;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.CertifyResult;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java
new file mode 100644
index 000000000..3d1ccaca1
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.service.input;
+
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import org.sufficientlysecure.keychain.util.Passphrase;
+
+/**
+ * This is a base class for the input of crypto operations.
+ */
+public class CryptoInputParcel implements Parcelable {
+
+ final Date mSignatureTime;
+ final Passphrase mPassphrase;
+
+ // this map contains both decrypted session keys and signed hashes to be
+ // used in the crypto operation described by this parcel.
+ private HashMap<ByteBuffer, byte[]> mCryptoData = new HashMap<>();
+
+ public CryptoInputParcel() {
+ mSignatureTime = new Date();
+ mPassphrase = null;
+ }
+
+ public CryptoInputParcel(Date signatureTime, Passphrase passphrase) {
+ mSignatureTime = signatureTime == null ? new Date() : signatureTime;
+ mPassphrase = passphrase;
+ }
+
+ public CryptoInputParcel(Passphrase passphrase) {
+ mSignatureTime = new Date();
+ mPassphrase = passphrase;
+ }
+
+ public CryptoInputParcel(Date signatureTime) {
+ mSignatureTime = signatureTime == null ? new Date() : signatureTime;
+ mPassphrase = null;
+ }
+
+ protected CryptoInputParcel(Parcel source) {
+ mSignatureTime = new Date(source.readLong());
+ mPassphrase = source.readParcelable(getClass().getClassLoader());
+
+ {
+ int count = source.readInt();
+ mCryptoData = new HashMap<>(count);
+ for (int i = 0; i < count; i++) {
+ byte[] key = source.createByteArray();
+ byte[] value = source.createByteArray();
+ mCryptoData.put(ByteBuffer.wrap(key), value);
+ }
+ }
+
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(mSignatureTime.getTime());
+ dest.writeParcelable(mPassphrase, 0);
+
+ dest.writeInt(mCryptoData.size());
+ for (HashMap.Entry<ByteBuffer, byte[]> entry : mCryptoData.entrySet()) {
+ dest.writeByteArray(entry.getKey().array());
+ dest.writeByteArray(entry.getValue());
+ }
+ }
+
+ public void addCryptoData(byte[] hash, byte[] signedHash) {
+ mCryptoData.put(ByteBuffer.wrap(hash), signedHash);
+ }
+
+ public Map<ByteBuffer, byte[]> getCryptoData() {
+ return Collections.unmodifiableMap(mCryptoData);
+ }
+
+ public Date getSignatureTime() {
+ return mSignatureTime;
+ }
+
+ public boolean hasPassphrase() {
+ return mPassphrase != null;
+ }
+
+ public Passphrase getPassphrase() {
+ return mPassphrase;
+ }
+
+ public static final Creator<CryptoInputParcel> CREATOR = new Creator<CryptoInputParcel>() {
+ public CryptoInputParcel createFromParcel(final Parcel source) {
+ return new CryptoInputParcel(source);
+ }
+
+ public CryptoInputParcel[] newArray(final int size) {
+ return new CryptoInputParcel[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ StringBuilder b = new StringBuilder();
+ b.append("CryptoInput: { ");
+ b.append(mSignatureTime).append(" ");
+ if (mPassphrase != null) {
+ b.append("passphrase");
+ }
+ if (mCryptoData != null) {
+ b.append(mCryptoData.size());
+ b.append(" hashes ");
+ }
+ b.append("}");
+ return b.toString();
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java
new file mode 100644
index 000000000..535c1e735
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java
@@ -0,0 +1,214 @@
+package org.sufficientlysecure.keychain.service.input;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import org.sufficientlysecure.keychain.Constants.key;
+
+
+public class RequiredInputParcel implements Parcelable {
+
+ public enum RequiredInputType {
+ PASSPHRASE, PASSPHRASE_SYMMETRIC, NFC_SIGN, NFC_DECRYPT
+ }
+
+ public Date mSignatureTime;
+
+ public final RequiredInputType mType;
+
+ public final byte[][] mInputHashes;
+ public final int[] mSignAlgos;
+
+ private Long mMasterKeyId;
+ private Long mSubKeyId;
+
+ private RequiredInputParcel(RequiredInputType type, byte[][] inputHashes,
+ int[] signAlgos, Date signatureTime, Long masterKeyId, Long subKeyId) {
+ mType = type;
+ mInputHashes = inputHashes;
+ mSignAlgos = signAlgos;
+ mSignatureTime = signatureTime;
+ mMasterKeyId = masterKeyId;
+ mSubKeyId = subKeyId;
+ }
+
+ public RequiredInputParcel(Parcel source) {
+ mType = RequiredInputType.values()[source.readInt()];
+
+ // 0 = none, 1 = both, 2 = only hashes (decrypt)
+ int hashTypes = source.readInt();
+ if (hashTypes != 0) {
+ int count = source.readInt();
+ mInputHashes = new byte[count][];
+ if (hashTypes == 1) {
+ mSignAlgos = new int[count];
+ for (int i = 0; i < count; i++) {
+ mInputHashes[i] = source.createByteArray();
+ mSignAlgos[i] = source.readInt();
+ }
+ } else {
+ mSignAlgos = null;
+ for (int i = 0; i < count; i++) {
+ mInputHashes[i] = source.createByteArray();
+ }
+ }
+ } else {
+ mInputHashes = null;
+ mSignAlgos = null;
+ }
+
+ mSignatureTime = source.readInt() != 0 ? new Date(source.readLong()) : null;
+ mMasterKeyId = source.readInt() != 0 ? source.readLong() : null;
+ mSubKeyId = source.readInt() != 0 ? source.readLong() : null;
+
+ }
+
+ public Long getMasterKeyId() {
+ return mMasterKeyId;
+ }
+
+ public Long getSubKeyId() {
+ return mSubKeyId;
+ }
+
+ public static RequiredInputParcel createNfcSignOperation(
+ byte[] inputHash, int signAlgo, Date signatureTime) {
+ return new RequiredInputParcel(RequiredInputType.NFC_SIGN,
+ new byte[][] { inputHash }, new int[] { signAlgo },
+ signatureTime, null, null);
+ }
+
+ public static RequiredInputParcel createNfcDecryptOperation(byte[] inputHash, long subKeyId) {
+ return new RequiredInputParcel(RequiredInputType.NFC_DECRYPT,
+ new byte[][] { inputHash }, null, null, null, subKeyId);
+ }
+
+ public static RequiredInputParcel createRequiredSignPassphrase(
+ long masterKeyId, long subKeyId, Date signatureTime) {
+ return new RequiredInputParcel(RequiredInputType.PASSPHRASE,
+ null, null, signatureTime, masterKeyId, subKeyId);
+ }
+
+ public static RequiredInputParcel createRequiredDecryptPassphrase(
+ long masterKeyId, long subKeyId) {
+ return new RequiredInputParcel(RequiredInputType.PASSPHRASE,
+ null, null, null, masterKeyId, subKeyId);
+ }
+
+ public static RequiredInputParcel createRequiredSymmetricPassphrase() {
+ return new RequiredInputParcel(RequiredInputType.PASSPHRASE_SYMMETRIC,
+ null, null, null, null, null);
+ }
+
+ public static RequiredInputParcel createRequiredPassphrase(
+ RequiredInputParcel req) {
+ return new RequiredInputParcel(RequiredInputType.PASSPHRASE,
+ null, null, req.mSignatureTime, req.mMasterKeyId, req.mSubKeyId);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mType.ordinal());
+ if (mInputHashes != null) {
+ dest.writeInt(mSignAlgos != null ? 1 : 2);
+ dest.writeInt(mInputHashes.length);
+ for (int i = 0; i < mInputHashes.length; i++) {
+ dest.writeByteArray(mInputHashes[i]);
+ if (mSignAlgos != null) {
+ dest.writeInt(mSignAlgos[i]);
+ }
+ }
+ } else {
+ dest.writeInt(0);
+ }
+ if (mSignatureTime != null) {
+ dest.writeInt(1);
+ dest.writeLong(mSignatureTime.getTime());
+ } else {
+ dest.writeInt(0);
+ }
+ if (mMasterKeyId != null) {
+ dest.writeInt(1);
+ dest.writeLong(mMasterKeyId);
+ } else {
+ dest.writeInt(0);
+ }
+ if (mSubKeyId != null) {
+ dest.writeInt(1);
+ dest.writeLong(mSubKeyId);
+ } else {
+ dest.writeInt(0);
+ }
+
+ }
+
+ public static final Creator<RequiredInputParcel> CREATOR = new Creator<RequiredInputParcel>() {
+ public RequiredInputParcel createFromParcel(final Parcel source) {
+ return new RequiredInputParcel(source);
+ }
+
+ public RequiredInputParcel[] newArray(final int size) {
+ return new RequiredInputParcel[size];
+ }
+ };
+
+ public static class NfcSignOperationsBuilder {
+ Date mSignatureTime;
+ ArrayList<Integer> mSignAlgos = new ArrayList<>();
+ ArrayList<byte[]> mInputHashes = new ArrayList<>();
+ Long mMasterKeyId;
+ Long mSubKeyId;
+
+ public NfcSignOperationsBuilder(Date signatureTime, Long masterKeyId, Long subKeyId) {
+ mSignatureTime = signatureTime;
+ mMasterKeyId = masterKeyId;
+ mSubKeyId = subKeyId;
+ }
+
+ public RequiredInputParcel build() {
+ byte[][] inputHashes = new byte[mInputHashes.size()][];
+ mInputHashes.toArray(inputHashes);
+ int[] signAlgos = new int[mSignAlgos.size()];
+ for (int i = 0; i < mSignAlgos.size(); i++) {
+ signAlgos[i] = mSignAlgos.get(i);
+ }
+
+ return new RequiredInputParcel(RequiredInputType.NFC_SIGN,
+ inputHashes, signAlgos, mSignatureTime, mMasterKeyId, mSubKeyId);
+ }
+
+ public void addHash(byte[] hash, int algo) {
+ mInputHashes.add(hash);
+ mSignAlgos.add(algo);
+ }
+
+ public void addAll(RequiredInputParcel input) {
+ if (!mSignatureTime.equals(input.mSignatureTime)) {
+ throw new AssertionError("input times must match, this is a programming error!");
+ }
+ if (input.mType != RequiredInputType.NFC_SIGN) {
+ throw new AssertionError("operation types must match, this is a progrmming error!");
+ }
+
+ Collections.addAll(mInputHashes, input.mInputHashes);
+ for (int signAlgo : input.mSignAlgos) {
+ mSignAlgos.add(signAlgo);
+ }
+ }
+
+ public boolean isEmpty() {
+ return mInputHashes.isEmpty();
+ }
+
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintActivity.java
index b7c80c1ed..016ab5f3c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintActivity.java
@@ -23,6 +23,7 @@ import android.view.View;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.util.Log;
public class CertifyFingerprintActivity extends BaseActivity {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java
index 1fb88b182..3845e07cb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java
@@ -19,6 +19,8 @@
package org.sufficientlysecure.keychain.ui;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
+
/**
* Signs the specified public key with the specified secret master key
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
index 9b6e8d8f9..59623a610 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
@@ -25,8 +25,6 @@ import android.database.Cursor;
import android.database.MatrixCursor;
import android.graphics.PorterDuff;
import android.net.Uri;
-import android.os.Build.VERSION;
-import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
@@ -56,23 +54,21 @@ import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
-import org.sufficientlysecure.keychain.service.PassphraseCacheService;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.adapter.MultiUserIdsAdapter;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
import org.sufficientlysecure.keychain.ui.widget.KeySpinner;
import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
-import java.lang.reflect.Method;
import java.util.ArrayList;
-public class CertifyKeyFragment extends LoaderFragment
- implements LoaderManager.LoaderCallbacks<Cursor> {
- public static final int REQUEST_CODE_PASSPHRASE = 0x00008001;
+public class CertifyKeyFragment extends CryptoOperationFragment
+ implements LoaderManager.LoaderCallbacks<Cursor> {
private CheckBox mUploadKeyCheckbox;
ListView mUserIds;
@@ -102,9 +98,6 @@ public class CertifyKeyFragment extends LoaderFragment
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- // Start out with a progress indicator.
- setContentShown(false);
-
mPubMasterKeyIds = getActivity().getIntent().getLongArrayExtra(CertifyKeyActivity.EXTRA_KEY_IDS);
if (mPubMasterKeyIds == null) {
Log.e(Constants.TAG, "List of key ids to certify missing!");
@@ -114,6 +107,7 @@ public class CertifyKeyFragment extends LoaderFragment
mPassthroughMessenger = getActivity().getIntent().getParcelableExtra(
KeychainIntentService.EXTRA_MESSENGER);
+ mPassthroughMessenger = null; // TODO remove, development hack
// preselect certify key id if given
long certifyKeyId = getActivity().getIntent().getLongExtra(CertifyKeyActivity.EXTRA_CERTIFY_KEY_ID, Constants.key.none);
@@ -143,9 +137,7 @@ public class CertifyKeyFragment extends LoaderFragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
- View root = super.onCreateView(inflater, superContainer, savedInstanceState);
-
- View view = inflater.inflate(R.layout.certify_key_fragment, getContainer());
+ View view = inflater.inflate(R.layout.certify_key_fragment, null);
mCertifyKeySpinner = (CertifyKeySpinner) view.findViewById(R.id.certify_key_spinner);
mUploadKeyCheckbox = (CheckBox) view.findViewById(R.id.sign_key_upload_checkbox);
@@ -173,7 +165,7 @@ public class CertifyKeyFragment extends LoaderFragment
Notify.create(getActivity(), getString(R.string.select_key_to_certify),
Notify.Style.ERROR).show();
} else {
- initiateCertifying();
+ cryptoOperation(new CryptoInputParcel());
}
}
});
@@ -183,7 +175,7 @@ public class CertifyKeyFragment extends LoaderFragment
mUploadKeyCheckbox.setChecked(false);
}
- return root;
+ return view;
}
@Override
@@ -222,17 +214,6 @@ public class CertifyKeyFragment extends LoaderFragment
}) {
@Override
public byte[] getBlob(int column) {
- // For some reason, getBlob was not implemented before ICS
- if (VERSION.SDK_INT < VERSION_CODES.ICE_CREAM_SANDWICH) {
- try {
- // haha, yes there is int.class
- Method m = MatrixCursor.class.getDeclaredMethod("get", new Class[]{int.class});
- m.setAccessible(true);
- return (byte[]) m.invoke(this, 1);
- } catch (Exception e) {
- throw new UnsupportedOperationException(e);
- }
- }
return super.getBlob(column);
}
};
@@ -307,7 +288,6 @@ public class CertifyKeyFragment extends LoaderFragment
}
mUserIdsAdapter.swapCursor(matrix);
- setContentShown(true, isResumed());
}
@Override
@@ -315,49 +295,8 @@ public class CertifyKeyFragment extends LoaderFragment
mUserIdsAdapter.swapCursor(null);
}
- /**
- * handles the UI bits of the signing process on the UI thread
- */
- private void initiateCertifying() {
- // get the user's passphrase for this key (if required)
- Passphrase passphrase;
- try {
- passphrase = PassphraseCacheService.getCachedPassphrase(getActivity(), mSignMasterKeyId, mSignMasterKeyId);
- } catch (PassphraseCacheService.KeyNotFoundException e) {
- Log.e(Constants.TAG, "Key not found!", e);
- getActivity().finish();
- return;
- }
- if (passphrase == null) {
- Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class);
- intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, mSignMasterKeyId);
- startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
- // bail out; need to wait until the user has entered the passphrase before trying again
- } else {
- startCertifying();
- }
- }
-
@Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case REQUEST_CODE_PASSPHRASE: {
- if (resultCode == Activity.RESULT_OK && data != null) {
- startCertifying();
- }
- return;
- }
-
- default: {
- super.onActivityResult(requestCode, resultCode, data);
- }
- }
- }
-
- /**
- * kicks off the actual signing process on a background thread
- */
- private void startCertifying() {
+ protected void cryptoOperation(CryptoInputParcel cryptoInput) {
// Bail out if there is not at least one user id selected
ArrayList<CertifyAction> certifyActions = mUserIdsAdapter.getSelectedCertifyActions();
if (certifyActions.isEmpty()) {
@@ -372,6 +311,7 @@ public class CertifyKeyFragment extends LoaderFragment
CertifyActionsParcel parcel = new CertifyActionsParcel(mSignMasterKeyId);
parcel.mCertifyActions.addAll(certifyActions);
+ data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
data.putParcelable(KeychainIntentService.CERTIFY_PARCEL, parcel);
if (mUploadKeyCheckbox.isChecked()) {
String keyserver = Preferences.getPreferences(getActivity()).getPreferredKeyserver();
@@ -396,11 +336,17 @@ public class CertifyKeyFragment extends LoaderFragment
true,
ProgressDialogFragment.ServiceType.KEYCHAIN_INTENT) {
public void handleMessage(Message message) {
- // handle messages by standard KeychainIntentServiceHandler first
+ // handle messages by KeychainIntentCryptoServiceHandler first
super.handleMessage(message);
+ // handle pending messages
+ if (handlePendingMessage(message)) {
+ return;
+ }
+
if (message.arg1 == MessageStatus.OKAY.ordinal()) {
Bundle data = message.getData();
+
CertifyResult result = data.getParcelable(CertifyResult.EXTRA_RESULT);
Intent intent = new Intent();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
index ab76f693e..0b203614b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
@@ -17,17 +17,25 @@
package org.sufficientlysecure.keychain.ui;
+import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
-import android.view.View;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
+import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Passphrase;
+import java.io.IOException;
import java.util.ArrayList;
-public class CreateKeyActivity extends BaseActivity {
+public class CreateKeyActivity extends BaseNfcActivity {
public static final String EXTRA_NAME = "name";
public static final String EXTRA_EMAIL = "email";
@@ -35,6 +43,10 @@ public class CreateKeyActivity extends BaseActivity {
public static final String EXTRA_ADDITIONAL_EMAILS = "additional_emails";
public static final String EXTRA_PASSPHRASE = "passphrase";
+ public static final String EXTRA_NFC_USER_ID = "nfc_user_id";
+ public static final String EXTRA_NFC_AID = "nfc_aid";
+ public static final String EXTRA_NFC_FINGERPRINTS = "nfc_fingerprints";
+
public static final String FRAGMENT_TAG = "currentFragment";
String mName;
@@ -60,14 +72,29 @@ public class CreateKeyActivity extends BaseActivity {
mCurrentFragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
} else {
+
+ Intent intent = getIntent();
// Initialize members with default values for a new instance
- mName = getIntent().getStringExtra(EXTRA_NAME);
- mEmail = getIntent().getStringExtra(EXTRA_EMAIL);
- mFirstTime = getIntent().getBooleanExtra(EXTRA_FIRST_TIME, false);
+ mName = intent.getStringExtra(EXTRA_NAME);
+ mEmail = intent.getStringExtra(EXTRA_EMAIL);
+ mFirstTime = intent.getBooleanExtra(EXTRA_FIRST_TIME, false);
+
+ if (intent.hasExtra(EXTRA_NFC_FINGERPRINTS)) {
+ byte[] nfcFingerprints = intent.getByteArrayExtra(EXTRA_NFC_FINGERPRINTS);
+ String nfcUserId = intent.getStringExtra(EXTRA_NFC_USER_ID);
+ byte[] nfcAid = intent.getByteArrayExtra(EXTRA_NFC_AID);
+
+ Fragment frag2 = CreateKeyYubiImportFragment.createInstance(
+ nfcFingerprints, nfcAid, nfcUserId);
+ loadFragment(frag2, FragAction.START);
+
+ setTitle(R.string.title_import_keys);
+ return;
+ } else {
+ CreateKeyStartFragment frag = CreateKeyStartFragment.newInstance();
+ loadFragment(frag, FragAction.START);
+ }
- // Start with first fragment of wizard
- CreateKeyStartFragment frag = CreateKeyStartFragment.newInstance();
- loadFragment(frag, FragAction.START);
}
if (mFirstTime) {
@@ -80,6 +107,38 @@ public class CreateKeyActivity extends BaseActivity {
}
@Override
+ protected void onNfcPerform() throws IOException {
+ if (mCurrentFragment instanceof NfcListenerFragment) {
+ ((NfcListenerFragment) mCurrentFragment).onNfcPerform();
+ return;
+ }
+
+ byte[] scannedFingerprints = nfcGetFingerprints();
+ byte[] nfcAid = nfcGetAid();
+ String userId = nfcGetUserId();
+
+ try {
+ long masterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(scannedFingerprints);
+ CachedPublicKeyRing ring = new ProviderHelper(this).getCachedPublicKeyRing(masterKeyId);
+ ring.getMasterKeyId();
+
+ Intent intent = new Intent(this, ViewKeyActivity.class);
+ intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId));
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, nfcAid);
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_USER_ID, userId);
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_FINGERPRINTS, scannedFingerprints);
+ startActivity(intent);
+ finish();
+
+ } catch (PgpKeyNotFoundException e) {
+ Fragment frag = CreateKeyYubiImportFragment.createInstance(
+ scannedFingerprints, nfcAid, userId);
+ loadFragment(frag, FragAction.TO_RIGHT);
+ }
+
+ }
+
+ @Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
@@ -125,8 +184,14 @@ public class CreateKeyActivity extends BaseActivity {
break;
}
+
// do it immediately!
getSupportFragmentManager().executePendingTransactions();
+
+ }
+
+ interface NfcListenerFragment {
+ public void onNfcPerform() throws IOException;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java
index 7e2e1c31c..85e2f8e9d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java
@@ -126,7 +126,7 @@ public class CreateKeyEmailFragment extends Fragment {
if (mAdditionalEmailModels == null) {
mAdditionalEmailModels = new ArrayList<>();
if (mCreateKeyActivity.mAdditionalEmails != null) {
- setAdditionalEmails(mCreateKeyActivity.mAdditionalEmails);
+ mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails);
}
}
@@ -209,12 +209,6 @@ public class CreateKeyEmailFragment extends Fragment {
return emails;
}
- private void setAdditionalEmails(ArrayList<String> emails) {
- for (String email : emails) {
- mAdditionalEmailModels.add(new EmailAdapter.ViewModel(email));
- }
- }
-
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
@@ -244,8 +238,7 @@ public class CreateKeyEmailFragment extends Fragment {
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
- public static class ViewHolder extends RecyclerView.ViewHolder {
- // each data item is just a string in this case
+ class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ImageButton mDeleteButton;
@@ -289,7 +282,10 @@ public class CreateKeyEmailFragment extends Fragment {
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
- if (holder instanceof ViewHolder) {
+ if (holder instanceof FooterHolder) {
+ FooterHolder thisHolder = (FooterHolder) holder;
+ thisHolder.mAddButton.setOnClickListener(mFooterOnClickListener);
+ } else if (holder instanceof ViewHolder) {
ViewHolder thisHolder = (ViewHolder) holder;
// - get element from your dataset at this position
// - replace the contents of the view with that element
@@ -302,9 +298,6 @@ public class CreateKeyEmailFragment extends Fragment {
remove(model);
}
});
- } else if (holder instanceof FooterHolder) {
- FooterHolder thisHolder = (FooterHolder) holder;
- thisHolder.mAddButton.setOnClickListener(mFooterOnClickListener);
}
}
@@ -332,6 +325,12 @@ public class CreateKeyEmailFragment extends Fragment {
notifyItemInserted(mDataset.size() - 1);
}
+ private void addAll(ArrayList<String> emails) {
+ for (String email : emails) {
+ mDataset.add(new EmailAdapter.ViewModel(email));
+ }
+ }
+
public void remove(ViewModel model) {
int position = mDataset.indexOf(model);
mDataset.remove(position);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java
index 180a52a1c..3f56949f5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java
@@ -78,7 +78,7 @@ public class CreateKeyStartFragment extends Fragment {
mCreateKey = view.findViewById(R.id.create_key_create_key_button);
mImportKey = view.findViewById(R.id.create_key_import_button);
-// mYubiKey = view.findViewById(R.id.create_key_yubikey_button);
+ mYubiKey = view.findViewById(R.id.create_key_yubikey_button);
mCancel = (TextView) view.findViewById(R.id.create_key_cancel);
if (mCreateKeyActivity.mFirstTime) {
@@ -95,6 +95,14 @@ public class CreateKeyStartFragment extends Fragment {
}
});
+ mYubiKey.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ CreateKeyYubiWaitFragment frag = new CreateKeyYubiWaitFragment();
+ mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
+ }
+ });
+
mImportKey.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java
new file mode 100644
index 000000000..1cd0aaf2f
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Message;
+import android.os.Messenger;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import org.spongycastle.util.encoders.Hex;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
+import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
+import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
+import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
+import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
+import org.sufficientlysecure.keychain.ui.CreateKeyActivity.NfcListenerFragment;
+import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.Preferences;
+
+
+public class CreateKeyYubiImportFragment extends Fragment implements NfcListenerFragment {
+
+ private static final String ARG_FINGERPRINT = "fingerprint";
+ public static final String ARG_AID = "aid";
+ public static final String ARG_USER_ID = "user_ids";
+
+ CreateKeyActivity mCreateKeyActivity;
+
+ private byte[] mNfcFingerprints;
+ private long mNfcMasterKeyId;
+ private byte[] mNfcAid;
+ private String mNfcUserId;
+ private String mNfcFingerprint;
+ private ImportKeysListFragment mListFragment;
+ private TextView vSerNo;
+ private TextView vUserId;
+
+ public static Fragment createInstance(byte[] scannedFingerprints, byte[] nfcAid, String userId) {
+
+ CreateKeyYubiImportFragment frag = new CreateKeyYubiImportFragment();
+
+ Bundle args = new Bundle();
+ args.putByteArray(ARG_FINGERPRINT, scannedFingerprints);
+ args.putByteArray(ARG_AID, nfcAid);
+ args.putString(ARG_USER_ID, userId);
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Bundle args = savedInstanceState != null ? savedInstanceState : getArguments();
+
+ mNfcFingerprints = args.getByteArray(ARG_FINGERPRINT);
+ mNfcAid = args.getByteArray(ARG_AID);
+ mNfcUserId = args.getString(ARG_USER_ID);
+
+ mNfcMasterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mNfcFingerprints);
+ mNfcFingerprint = KeyFormattingUtils.convertFingerprintToHex(mNfcFingerprints);
+
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.create_yubikey_import_fragment, container, false);
+
+ vSerNo = (TextView) view.findViewById(R.id.yubikey_serno);
+ vUserId = (TextView) view.findViewById(R.id.yubikey_userid);
+
+ {
+ View mBackButton = view.findViewById(R.id.create_key_back_button);
+ mBackButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (getFragmentManager().getBackStackEntryCount() == 0) {
+ getActivity().setResult(Activity.RESULT_CANCELED);
+ getActivity().finish();
+ } else {
+ mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
+ }
+ }
+ });
+
+ View mNextButton = view.findViewById(R.id.create_key_next_button);
+ mNextButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ importKey();
+ }
+ });
+ }
+
+ mListFragment = ImportKeysListFragment.newInstance(null, null, "0x" + mNfcFingerprint, true);
+
+ view.findViewById(R.id.button_search).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ refreshSearch();
+ }
+ });
+
+ setData();
+
+ getFragmentManager().beginTransaction()
+ .replace(R.id.yubikey_import_fragment, mListFragment, "yubikey_import")
+ .commit();
+
+ return view;
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle args) {
+ super.onSaveInstanceState(args);
+
+ args.putByteArray(ARG_FINGERPRINT, mNfcFingerprints);
+ args.putByteArray(ARG_AID, mNfcAid);
+ args.putString(ARG_USER_ID, mNfcUserId);
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mCreateKeyActivity = (CreateKeyActivity) getActivity();
+ }
+
+ public void setData() {
+ String serno = Hex.toHexString(mNfcAid, 10, 4);
+ vSerNo.setText(getString(R.string.yubikey_serno, serno));
+
+ if (!mNfcUserId.isEmpty()) {
+ vUserId.setText(getString(R.string.yubikey_key_holder, mNfcUserId));
+ } else {
+ vUserId.setText(getString(R.string.yubikey_key_holder_unset));
+ }
+ }
+
+ public void refreshSearch() {
+ mListFragment.loadNew(new ImportKeysListFragment.CloudLoaderState("0x" + mNfcFingerprint,
+ Preferences.getPreferences(getActivity()).getCloudSearchPrefs()));
+ }
+
+ public void importKey() {
+
+ // Message is received after decrypting is done in KeychainIntentService
+ ServiceProgressHandler saveHandler = new ServiceProgressHandler(
+ getActivity(),
+ getString(R.string.progress_importing),
+ ProgressDialog.STYLE_HORIZONTAL,
+ ProgressDialogFragment.ServiceType.KEYCHAIN_INTENT
+ ) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ if (message.arg1 == MessageStatus.OKAY.ordinal()) {
+ // get returned data bundle
+ Bundle returnData = message.getData();
+
+ ImportKeyResult result =
+ returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT);
+
+ if (!result.success()) {
+ result.createNotify(getActivity()).show();
+ return;
+ }
+
+ Intent intent = new Intent(getActivity(), ViewKeyActivity.class);
+ intent.setData(KeyRings.buildGenericKeyRingUri(mNfcMasterKeyId));
+ intent.putExtra(ViewKeyActivity.EXTRA_DISPLAY_RESULT, result);
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, mNfcAid);
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_USER_ID, mNfcUserId);
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_FINGERPRINTS, mNfcFingerprints);
+ startActivity(intent);
+ getActivity().finish();
+
+ }
+
+ }
+ };
+
+ // Send all information needed to service to decrypt in other thread
+ Intent intent = new Intent(getActivity(), KeychainIntentService.class);
+
+ // fill values for this action
+ Bundle data = new Bundle();
+
+ intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING);
+
+ String hexFp = KeyFormattingUtils.convertFingerprintToHex(mNfcFingerprints);
+ ArrayList<ParcelableKeyRing> keyList = new ArrayList<>();
+ keyList.add(new ParcelableKeyRing(hexFp, null, null));
+ data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, keyList);
+
+ {
+ Preferences prefs = Preferences.getPreferences(getActivity());
+ Preferences.CloudSearchPrefs cloudPrefs =
+ new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver());
+ data.putString(KeychainIntentService.IMPORT_KEY_SERVER, cloudPrefs.keyserver);
+ }
+
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(saveHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ saveHandler.showProgressDialog(getActivity());
+
+ // start service with intent
+ getActivity().startService(intent);
+
+ }
+
+ @Override
+ public void onNfcPerform() throws IOException {
+
+ mNfcFingerprints = mCreateKeyActivity.nfcGetFingerprints();
+ mNfcAid = mCreateKeyActivity.nfcGetAid();
+ mNfcUserId = mCreateKeyActivity.nfcGetUserId();
+
+ mNfcMasterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mNfcFingerprints);
+ mNfcFingerprint = KeyFormattingUtils.convertFingerprintToHex(mNfcFingerprints);
+
+ setData();
+ refreshSearch();
+
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiWaitFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiWaitFragment.java
new file mode 100644
index 000000000..579dddf79
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiWaitFragment.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
+
+
+public class CreateKeyYubiWaitFragment extends Fragment {
+
+ CreateKeyActivity mCreateKeyActivity;
+ View mBackButton;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.create_yubikey_wait_fragment, container, false);
+
+ mBackButton = view.findViewById(R.id.create_key_back_button);
+
+ mBackButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
+ }
+ });
+
+ return view;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mCreateKeyActivity = (CreateKeyActivity) getActivity();
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
index 162b10eca..dce2386b5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
@@ -21,12 +21,12 @@ import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.os.PersistableBundle;
import android.view.View;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.util.Log;
public class DecryptFilesActivity extends BaseActivity {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
index c75e28145..766e65e8b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
@@ -17,6 +17,7 @@
package org.sufficientlysecure.keychain.ui;
+import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
@@ -32,13 +33,13 @@ import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.TextView;
-import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentService.IOType;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
@@ -63,6 +64,8 @@ public class DecryptFilesFragment extends DecryptFragment {
private Uri mInputUri = null;
private Uri mOutputUri = null;
+ private String mCurrentCryptoOperation;
+
/**
* Creates new instance of this fragment
*/
@@ -90,9 +93,6 @@ public class DecryptFilesFragment extends DecryptFragment {
mDecryptButton = view.findViewById(R.id.decrypt_file_action_decrypt);
view.findViewById(R.id.decrypt_file_browse).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
- // reset state
- mPassphrase = null;
- mNfcDecryptedSessionKey = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
FileHelper.openDocument(DecryptFilesFragment.this, "*/*", REQUEST_CODE_INPUT);
} else {
@@ -144,7 +144,7 @@ public class DecryptFilesFragment extends DecryptFragment {
return;
}
- decryptOriginalFilename();
+ startDecryptFilenames();
}
private String removeEncryptedAppend(String name) {
@@ -157,110 +157,45 @@ public class DecryptFilesFragment extends DecryptFragment {
}
private void askForOutputFilename(String originalFilename) {
- String targetName;
- if (!TextUtils.isEmpty(originalFilename)) {
- targetName = originalFilename;
- } else {
- targetName = removeEncryptedAppend(FileHelper.getFilename(getActivity(), mInputUri));
+ if (TextUtils.isEmpty(originalFilename)) {
+ originalFilename = removeEncryptedAppend(FileHelper.getFilename(getActivity(), mInputUri));
}
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
File file = new File(mInputUri.getPath());
File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR;
- File targetFile = new File(parentDir, targetName);
+ File targetFile = new File(parentDir, originalFilename);
FileHelper.saveFile(this, getString(R.string.title_decrypt_to_file),
getString(R.string.specify_file_to_decrypt_to), targetFile, REQUEST_CODE_OUTPUT);
} else {
- FileHelper.saveDocument(this, "*/*", targetName, REQUEST_CODE_OUTPUT);
+ FileHelper.saveDocument(this, "*/*", originalFilename, REQUEST_CODE_OUTPUT);
}
}
- private void decryptOriginalFilename() {
- Log.d(Constants.TAG, "decryptOriginalFilename");
-
- Intent intent = new Intent(getActivity(), KeychainIntentService.class);
-
- // fill values for this action
- Bundle data = new Bundle();
- intent.setAction(KeychainIntentService.ACTION_DECRYPT_METADATA);
-
- // data
- Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri);
-
- data.putInt(KeychainIntentService.SOURCE, IOType.URI.ordinal());
- data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_INPUT_URI, mInputUri);
-
- data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal());
- data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri);
-
- data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
- data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
-
- intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
-
- // Message is received after decrypting is done in KeychainIntentService
- ServiceProgressHandler saveHandler = new ServiceProgressHandler(
- getActivity(),
- getString(R.string.progress_decrypting),
- ProgressDialog.STYLE_HORIZONTAL,
- ProgressDialogFragment.ServiceType.KEYCHAIN_INTENT) {
- public void handleMessage(Message message) {
- // handle messages by standard KeychainIntentServiceHandler first
- super.handleMessage(message);
-
- if (message.arg1 == MessageStatus.OKAY.ordinal()) {
- // get returned data bundle
- Bundle returnData = message.getData();
-
- DecryptVerifyResult pgpResult =
- returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT);
-
- if (pgpResult.isPending()) {
- if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) ==
- DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) {
- startPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded());
- } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) ==
- DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) {
- startPassphraseDialog(Constants.key.symmetric);
- } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) ==
- DecryptVerifyResult.RESULT_PENDING_NFC) {
- startNfcDecrypt(pgpResult.getNfcSubKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey());
- } else {
- throw new RuntimeException("Unhandled pending result!");
- }
- } else if (pgpResult.success()) {
- // go on...
- askForOutputFilename(pgpResult.getDecryptMetadata().getFilename());
- } else {
- pgpResult.createNotify(getActivity()).show();
- }
- }
- }
- };
-
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(saveHandler);
- intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
-
- // show progress dialog
- saveHandler.showProgressDialog(getActivity());
+ private void startDecrypt() {
+ mCurrentCryptoOperation = KeychainIntentService.ACTION_DECRYPT_VERIFY;
+ cryptoOperation(new CryptoInputParcel());
+ }
- // start service with intent
- getActivity().startService(intent);
+ private void startDecryptFilenames() {
+ mCurrentCryptoOperation = KeychainIntentService.ACTION_DECRYPT_METADATA;
+ cryptoOperation(new CryptoInputParcel());
}
@Override
- protected void decryptStart() {
- Log.d(Constants.TAG, "decryptStart");
-
+ @SuppressLint("HandlerLeak")
+ protected void cryptoOperation(CryptoInputParcel cryptoInput) {
// Send all information needed to service to decrypt in other thread
Intent intent = new Intent(getActivity(), KeychainIntentService.class);
// fill values for this action
Bundle data = new Bundle();
-
- intent.setAction(KeychainIntentService.ACTION_DECRYPT_VERIFY);
+ // use current operation, either decrypt metadata or decrypt payload
+ intent.setAction(mCurrentCryptoOperation);
// data
+ data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
+
Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri);
data.putInt(KeychainIntentService.SOURCE, IOType.URI.ordinal());
@@ -269,8 +204,7 @@ public class DecryptFilesFragment extends DecryptFragment {
data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal());
data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri);
- data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
- data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
+ data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@@ -280,10 +214,16 @@ public class DecryptFilesFragment extends DecryptFragment {
getString(R.string.progress_decrypting),
ProgressDialog.STYLE_HORIZONTAL,
ProgressDialogFragment.ServiceType.KEYCHAIN_INTENT) {
+ @Override
public void handleMessage(Message message) {
// handle messages by standard KeychainIntentServiceHandler first
super.handleMessage(message);
+ // handle pending messages
+ if (handlePendingMessage(message)) {
+ return;
+ }
+
if (message.arg1 == MessageStatus.OKAY.ordinal()) {
// get returned data bundle
Bundle returnData = message.getData();
@@ -291,39 +231,39 @@ public class DecryptFilesFragment extends DecryptFragment {
DecryptVerifyResult pgpResult =
returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT);
- if (pgpResult.isPending()) {
- if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) ==
- DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) {
- startPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded());
- } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) ==
- DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) {
- startPassphraseDialog(Constants.key.symmetric);
- } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) ==
- DecryptVerifyResult.RESULT_PENDING_NFC) {
- startNfcDecrypt(pgpResult.getNfcSubKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey());
- } else {
- throw new RuntimeException("Unhandled pending result!");
- }
- } else if (pgpResult.success()) {
-
- // display signature result in activity
- onResult(pgpResult);
-
- if (mDeleteAfter.isChecked()) {
- // Create and show dialog to delete original file
- DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri);
- deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog");
- setInputUri(null);
- }
-
- /*
- // A future open after decryption feature
- if () {
- Intent viewFile = new Intent(Intent.ACTION_VIEW);
- viewFile.setInputData(mOutputUri);
- startActivity(viewFile);
+ if (pgpResult.success()) {
+
+ switch (mCurrentCryptoOperation) {
+ case KeychainIntentService.ACTION_DECRYPT_METADATA: {
+ askForOutputFilename(pgpResult.getDecryptMetadata().getFilename());
+ break;
+ }
+ case KeychainIntentService.ACTION_DECRYPT_VERIFY: {
+ // display signature result in activity
+ onResult(pgpResult);
+
+ if (mDeleteAfter.isChecked()) {
+ // Create and show dialog to delete original file
+ DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri);
+ deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog");
+ setInputUri(null);
+ }
+
+ /*
+ // A future open after decryption feature
+ if () {
+ Intent viewFile = new Intent(Intent.ACTION_VIEW);
+ viewFile.setInputData(mOutputUri);
+ startActivity(viewFile);
+ }
+ */
+ break;
+ }
+ default: {
+ Log.e(Constants.TAG, "Bug: not supported operation!");
+ break;
+ }
}
- */
} else {
pgpResult.createNotify(getActivity()).show();
}
@@ -346,22 +286,6 @@ public class DecryptFilesFragment extends DecryptFragment {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
- case REQUEST_CODE_PASSPHRASE: {
- if (resultCode == Activity.RESULT_OK && data != null) {
- mPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
- decryptOriginalFilename();
- }
- return;
- }
-
- case REQUEST_CODE_NFC_DECRYPT: {
- if (resultCode == Activity.RESULT_OK && data != null) {
- mNfcDecryptedSessionKey = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY);
- decryptOriginalFilename();
- }
- return;
- }
-
case REQUEST_CODE_INPUT: {
if (resultCode == Activity.RESULT_OK && data != null) {
setInputUri(data.getData());
@@ -373,7 +297,7 @@ public class DecryptFilesFragment extends DecryptFragment {
// This happens after output file was selected, so start our operation
if (resultCode == Activity.RESULT_OK && data != null) {
mOutputUri = data.getData();
- decryptStart();
+ startDecrypt();
}
return;
}
@@ -383,4 +307,5 @@ public class DecryptFilesFragment extends DecryptFragment {
}
}
}
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
index 63508e530..33209be86 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
@@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.app.Fragment;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -30,16 +29,13 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
-import org.sufficientlysecure.keychain.util.Passphrase;
-public abstract class DecryptFragment extends Fragment {
+public abstract class DecryptFragment extends CryptoOperationFragment {
private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006;
- public static final int REQUEST_CODE_PASSPHRASE = 0x00008001;
- public static final int REQUEST_CODE_NFC_DECRYPT = 0x00008002;
-
protected long mSignatureKeyId = 0;
protected LinearLayout mResultLayout;
@@ -56,11 +52,6 @@ public abstract class DecryptFragment extends Fragment {
protected TextView mSignatureEmail;
protected TextView mSignatureAction;
-
- // State
- protected Passphrase mPassphrase;
- protected byte[] mNfcDecryptedSessionKey;
-
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
@@ -95,25 +86,6 @@ public abstract class DecryptFragment extends Fragment {
startActivity(viewKeyIntent);
}
- protected void startPassphraseDialog(long subkeyId) {
- Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class);
- intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, subkeyId);
- startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
- }
-
- protected void startNfcDecrypt(long subKeyId, Passphrase pin, byte[] encryptedSessionKey) {
- // build PendingIntent for Yubikey NFC operations
- Intent intent = new Intent(getActivity(), NfcActivity.class);
- intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY);
- intent.putExtra(NfcActivity.EXTRA_DATA, new Intent()); // not used, only relevant to OpenPgpService
- intent.putExtra(NfcActivity.EXTRA_KEY_ID, subKeyId);
- intent.putExtra(NfcActivity.EXTRA_PIN, pin);
-
- intent.putExtra(NfcActivity.EXTRA_NFC_ENC_SESSION_KEY, encryptedSessionKey);
-
- startActivityForResult(intent, REQUEST_CODE_NFC_DECRYPT);
- }
-
/**
*
* @return returns false if signature is invalid, key is revoked or expired.
@@ -253,9 +225,4 @@ public abstract class DecryptFragment extends Fragment {
});
}
- /**
- * Should be overridden by MessageFragment and FileFragment to start actual decryption
- */
- protected abstract void decryptStart();
-
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
index bc2ec014a..728e3ba41 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
@@ -31,6 +31,7 @@ import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.SingletonResult;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
index f6e21937d..9c6c89c43 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
@@ -17,7 +17,6 @@
package org.sufficientlysecure.keychain.ui;
-import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
@@ -30,7 +29,6 @@ import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
-import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
@@ -38,6 +36,7 @@ import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentService.IOType;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
@@ -51,10 +50,7 @@ public class DecryptTextFragment extends DecryptFragment {
// view
private LinearLayout mValidLayout;
private LinearLayout mInvalidLayout;
- private Button mInvalidButton;
private TextView mText;
- private View mShareButton;
- private View mCopyButton;
// model
private String mCiphertext;
@@ -81,23 +77,26 @@ public class DecryptTextFragment extends DecryptFragment {
View view = inflater.inflate(R.layout.decrypt_text_fragment, container, false);
mValidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_valid);
mInvalidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_invalid);
- mInvalidButton = (Button) view.findViewById(R.id.decrypt_text_invalid_button);
mText = (TextView) view.findViewById(R.id.decrypt_text_plaintext);
- mShareButton = view.findViewById(R.id.action_decrypt_share_plaintext);
- mCopyButton = view.findViewById(R.id.action_decrypt_copy_plaintext);
- mShareButton.setOnClickListener(new View.OnClickListener() {
+
+ View vShareButton = view.findViewById(R.id.action_decrypt_share_plaintext);
+ vShareButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(sendWithChooserExcludingEncrypt(mText.getText().toString()));
}
});
- mCopyButton.setOnClickListener(new View.OnClickListener() {
+
+ View vCopyButton = view.findViewById(R.id.action_decrypt_copy_plaintext);
+ vCopyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
copyToClipboard(mText.getText().toString());
}
});
- mInvalidButton.setOnClickListener(new View.OnClickListener() {
+
+ Button vInvalidButton = (Button) view.findViewById(R.id.decrypt_text_invalid_button);
+ vInvalidButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mInvalidLayout.setVisibility(View.GONE);
@@ -143,14 +142,12 @@ public class DecryptTextFragment extends DecryptFragment {
String ciphertext = getArguments().getString(ARG_CIPHERTEXT);
if (ciphertext != null) {
mCiphertext = ciphertext;
- decryptStart();
+ cryptoOperation(new CryptoInputParcel());
}
}
@Override
- protected void decryptStart() {
- Log.d(Constants.TAG, "decryptStart");
-
+ protected void cryptoOperation(CryptoInputParcel cryptoInput) {
// Send all information needed to service to decrypt in other thread
Intent intent = new Intent(getActivity(), KeychainIntentService.class);
@@ -160,10 +157,10 @@ public class DecryptTextFragment extends DecryptFragment {
intent.setAction(KeychainIntentService.ACTION_DECRYPT_VERIFY);
// data
+ data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
data.putInt(KeychainIntentService.TARGET, IOType.BYTES.ordinal());
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, mCiphertext.getBytes());
- data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
- data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
+ data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@@ -177,6 +174,11 @@ public class DecryptTextFragment extends DecryptFragment {
// handle messages by standard KeychainIntentServiceHandler first
super.handleMessage(message);
+ // handle pending messages
+ if (handlePendingMessage(message)) {
+ return;
+ }
+
if (message.arg1 == MessageStatus.OKAY.ordinal()) {
// get returned data bundle
Bundle returnData = message.getData();
@@ -184,20 +186,7 @@ public class DecryptTextFragment extends DecryptFragment {
DecryptVerifyResult pgpResult =
returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT);
- if (pgpResult.isPending()) {
- if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) ==
- DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) {
- startPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded());
- } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) ==
- DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) {
- startPassphraseDialog(Constants.key.symmetric);
- } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) ==
- DecryptVerifyResult.RESULT_PENDING_NFC) {
- startNfcDecrypt(pgpResult.getNfcSubKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey());
- } else {
- throw new RuntimeException("Unhandled pending result!");
- }
- } else if (pgpResult.success()) {
+ if (pgpResult.success()) {
byte[] decryptedMessage = returnData
.getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES);
@@ -245,34 +234,4 @@ public class DecryptTextFragment extends DecryptFragment {
getActivity().startService(intent);
}
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
-
- case REQUEST_CODE_PASSPHRASE: {
- if (resultCode == Activity.RESULT_OK && data != null) {
- mPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
- decryptStart();
- } else {
- getActivity().finish();
- }
- return;
- }
-
- case REQUEST_CODE_NFC_DECRYPT: {
- if (resultCode == Activity.RESULT_OK && data != null) {
- mNfcDecryptedSessionKey = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY);
- decryptStart();
- } else {
- getActivity().finish();
- }
- return;
- }
-
- default: {
- super.onActivityResult(requestCode, resultCode, data);
- }
- }
- }
-
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
index 6dc2994cf..b607ba9f4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
@@ -23,6 +23,7 @@ import android.os.Bundle;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.util.Log;
public class EditKeyActivity extends BaseActivity {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
index 1e4b506d4..897de8490 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
@@ -51,27 +51,27 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
-import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter;
import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.dialog.*;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase;
-public class EditKeyFragment extends LoaderFragment implements
+
+public class EditKeyFragment extends CryptoOperationFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
public static final String ARG_DATA_URI = "uri";
public static final String ARG_SAVE_KEYRING_PARCEL = "save_keyring_parcel";
- public static final int REQUEST_CODE_PASSPHRASE = 0x00008001;
-
private ListView mUserIdsList;
private ListView mSubkeysList;
private ListView mUserIdsAddedList;
@@ -96,7 +96,6 @@ public class EditKeyFragment extends LoaderFragment implements
private SaveKeyringParcel mSaveKeyringParcel;
private String mPrimaryUserId;
- private Passphrase mCurrentPassphrase;
/**
* Creates new instance of this fragment
@@ -125,8 +124,7 @@ public class EditKeyFragment extends LoaderFragment implements
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
- View root = super.onCreateView(inflater, superContainer, savedInstanceState);
- View view = inflater.inflate(R.layout.edit_key_fragment, getContainer());
+ View view = inflater.inflate(R.layout.edit_key_fragment, null);
mUserIdsList = (ListView) view.findViewById(R.id.edit_key_user_ids);
mSubkeysList = (ListView) view.findViewById(R.id.edit_key_keys);
@@ -136,7 +134,7 @@ public class EditKeyFragment extends LoaderFragment implements
mAddUserId = view.findViewById(R.id.edit_key_action_add_user_id);
mAddSubkey = view.findViewById(R.id.edit_key_action_add_key);
- return root;
+ return view;
}
@Override
@@ -151,7 +149,7 @@ public class EditKeyFragment extends LoaderFragment implements
if (mDataUri == null) {
returnKeyringParcel();
} else {
- saveInDatabase(mCurrentPassphrase);
+ cryptoOperation(new CryptoInputParcel());
}
}
}, new OnClickListener() {
@@ -181,18 +179,12 @@ public class EditKeyFragment extends LoaderFragment implements
private void loadSaveKeyringParcel(SaveKeyringParcel saveKeyringParcel) {
mSaveKeyringParcel = saveKeyringParcel;
mPrimaryUserId = saveKeyringParcel.mChangePrimaryUserId;
- if (saveKeyringParcel.mNewUnlock != null) {
- mCurrentPassphrase = saveKeyringParcel.mNewUnlock.mNewPassphrase;
- }
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSaveKeyringParcel.mAddUserIds, true);
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSaveKeyringParcel.mAddSubKeys, true);
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
-
- // show directly
- setContentShown(true);
}
private void loadData(Uri dataUri) {
@@ -212,9 +204,6 @@ public class EditKeyFragment extends LoaderFragment implements
case GNU_DUMMY:
finishWithError(LogType.MSG_EK_ERROR_DUMMY);
return;
- case DIVERT_TO_CARD:
- finishWithError(LogType.MSG_EK_ERROR_DIVERT);
- break;
}
mSaveKeyringParcel = new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint());
@@ -225,24 +214,10 @@ public class EditKeyFragment extends LoaderFragment implements
return;
}
- try {
- mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase(getActivity(),
- mSaveKeyringParcel.mMasterKeyId, mSaveKeyringParcel.mMasterKeyId);
- } catch (PassphraseCacheService.KeyNotFoundException e) {
- finishWithError(LogType.MSG_EK_ERROR_NOT_FOUND);
- return;
- }
-
- if (mCurrentPassphrase == null) {
- Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class);
- intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, mSaveKeyringParcel.mMasterKeyId);
- startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
- } else {
- // Prepare the loaders. Either re-connect with an existing ones,
- // or start new ones.
- getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditKeyFragment.this);
- getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, EditKeyFragment.this);
- }
+ // Prepare the loaders. Either re-connect with an existing ones,
+ // or start new ones.
+ getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditKeyFragment.this);
+ getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, EditKeyFragment.this);
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, mSaveKeyringParcel);
mUserIdsList.setAdapter(mUserIdsAdapter);
@@ -258,28 +233,6 @@ public class EditKeyFragment extends LoaderFragment implements
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
}
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case REQUEST_CODE_PASSPHRASE: {
- if (resultCode == Activity.RESULT_OK && data != null) {
- mCurrentPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
- // Prepare the loaders. Either re-connect with an existing ones,
- // or start new ones.
- getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditKeyFragment.this);
- getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, EditKeyFragment.this);
- } else {
- getActivity().finish();
- }
- return;
- }
-
- default: {
- super.onActivityResult(requestCode, resultCode, data);
- }
- }
- }
-
private void initView() {
mChangePassphrase.setOnClickListener(new View.OnClickListener() {
@Override
@@ -318,7 +271,6 @@ public class EditKeyFragment extends LoaderFragment implements
}
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
- setContentShown(false);
switch (id) {
case LOADER_ID_USER_IDS: {
@@ -351,7 +303,6 @@ public class EditKeyFragment extends LoaderFragment implements
break;
}
- setContentShown(true);
}
/**
@@ -393,7 +344,7 @@ public class EditKeyFragment extends LoaderFragment implements
Messenger messenger = new Messenger(returnHandler);
SetPassphraseDialogFragment setPassphraseDialog = SetPassphraseDialogFragment.newInstance(
- messenger, mCurrentPassphrase, R.string.title_change_passphrase);
+ messenger, R.string.title_change_passphrase);
setPassphraseDialog.show(getActivity().getSupportFragmentManager(), "setPassphraseDialog");
}
@@ -589,8 +540,11 @@ public class EditKeyFragment extends LoaderFragment implements
getActivity().finish();
}
- private void saveInDatabase(Passphrase passphrase) {
- Log.d(Constants.TAG, "mSaveKeyringParcel:\n" + mSaveKeyringParcel.toString());
+ @Override
+ protected void cryptoOperation(CryptoInputParcel cryptoInput) {
+
+ Log.d(Constants.TAG, "cryptoInput:\n" + cryptoInput);
+ Log.d(Constants.TAG, "mSaveKeyringParcel:\n" + mSaveKeyringParcel);
ServiceProgressHandler saveHandler = new ServiceProgressHandler(
getActivity(),
@@ -602,6 +556,10 @@ public class EditKeyFragment extends LoaderFragment implements
// handle messages by standard KeychainIntentServiceHandler first
super.handleMessage(message);
+ if (handlePendingMessage(message)) {
+ return;
+ }
+
if (message.arg1 == MessageStatus.OKAY.ordinal()) {
// get returned data bundle
@@ -637,7 +595,7 @@ public class EditKeyFragment extends LoaderFragment implements
// fill values for this action
Bundle data = new Bundle();
- data.putParcelable(KeychainIntentService.EDIT_KEYRING_PASSPHRASE, passphrase);
+ data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
data.putParcelable(KeychainIntentService.EDIT_KEYRING_PARCEL, mSaveKeyringParcel);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
deleted file mode 100644
index cd1028de4..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.app.Activity;
-import android.app.ProgressDialog;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Message;
-import android.os.Messenger;
-import android.view.View;
-
-import org.openintents.openpgp.util.OpenPgpApi;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
-import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
-import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
-import org.sufficientlysecure.keychain.service.KeychainIntentService;
-import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
-import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
-import org.sufficientlysecure.keychain.util.Passphrase;
-
-import java.util.Date;
-
-public abstract class EncryptActivity extends BaseActivity {
-
- public static final int REQUEST_CODE_PASSPHRASE = 0x00008001;
- public static final int REQUEST_CODE_NFC = 0x00008002;
-
- // For NFC data
- protected Passphrase mSigningKeyPassphrase = null;
- protected Date mNfcTimestamp = null;
- protected byte[] mNfcHash = null;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setFullScreenDialogClose(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- setResult(Activity.RESULT_CANCELED);
- finish();
- }
- }, false);
- }
-
- protected void startPassphraseDialog(long subkeyId) {
- Intent intent = new Intent(this, PassphraseDialogActivity.class);
- intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, subkeyId);
- startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
- }
-
- protected void startNfcSign(long keyId, Passphrase pin, byte[] hashToSign, int hashAlgo) {
- // build PendingIntent for Yubikey NFC operations
- Intent intent = new Intent(this, NfcActivity.class);
- intent.setAction(NfcActivity.ACTION_SIGN_HASH);
-
- // pass params through to activity that it can be returned again later to repeat pgp operation
- intent.putExtra(NfcActivity.EXTRA_DATA, new Intent()); // not used, only relevant to OpenPgpService
- intent.putExtra(NfcActivity.EXTRA_KEY_ID, keyId);
- intent.putExtra(NfcActivity.EXTRA_PIN, pin);
- intent.putExtra(NfcActivity.EXTRA_NFC_HASH_TO_SIGN, hashToSign);
- intent.putExtra(NfcActivity.EXTRA_NFC_HASH_ALGO, hashAlgo);
-
- startActivityForResult(intent, REQUEST_CODE_NFC);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case REQUEST_CODE_PASSPHRASE: {
- if (resultCode == RESULT_OK && data != null) {
- mSigningKeyPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
- startEncrypt();
- return;
- }
- break;
- }
-
- case REQUEST_CODE_NFC: {
- if (resultCode == RESULT_OK && data != null) {
- mNfcHash = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_SIGNED_HASH);
- startEncrypt();
- return;
- }
- break;
- }
-
- default: {
- super.onActivityResult(requestCode, resultCode, data);
- break;
- }
- }
- }
-
- public void startEncrypt() {
- if (!inputIsValid()) {
- // Notify was created by inputIsValid.
- return;
- }
-
- // Send all information needed to service to edit key in other thread
- Intent intent = new Intent(this, KeychainIntentService.class);
- intent.setAction(KeychainIntentService.ACTION_SIGN_ENCRYPT);
-
- Bundle data = new Bundle();
- data.putParcelable(KeychainIntentService.SIGN_ENCRYPT_PARCEL, createEncryptBundle());
- intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
-
- // Message is received after encrypting is done in KeychainIntentService
- ServiceProgressHandler serviceHandler = new ServiceProgressHandler(
- this,
- getString(R.string.progress_encrypting),
- ProgressDialog.STYLE_HORIZONTAL,
- ProgressDialogFragment.ServiceType.KEYCHAIN_INTENT) {
- public void handleMessage(Message message) {
- // handle messages by standard KeychainIntentServiceHandler first
- super.handleMessage(message);
-
- if (message.arg1 == MessageStatus.OKAY.ordinal()) {
- SignEncryptResult result =
- message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT);
-
- PgpSignEncryptResult pgpResult = result.getPending();
-
- if (pgpResult != null && pgpResult.isPending()) {
- if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) ==
- PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) {
- startPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded());
- } else if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_NFC) ==
- PgpSignEncryptResult.RESULT_PENDING_NFC) {
-
- mNfcTimestamp = pgpResult.getNfcTimestamp();
- startNfcSign(pgpResult.getNfcKeyId(), pgpResult.getNfcPassphrase(),
- pgpResult.getNfcHash(), pgpResult.getNfcAlgo());
- } else {
- throw new RuntimeException("Unhandled pending result!");
- }
- return;
- }
-
- if (result.success()) {
- onEncryptSuccess(result);
- } else {
- result.createNotify(EncryptActivity.this).show();
- }
-
- // no matter the result, reset parameters
- mSigningKeyPassphrase = null;
- mNfcHash = null;
- mNfcTimestamp = null;
- }
- }
- };
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(serviceHandler);
- intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
-
- // show progress dialog
- serviceHandler.showProgressDialog(this);
-
- // start service with intent
- startService(intent);
- }
-
- protected abstract boolean inputIsValid();
-
- protected abstract void onEncryptSuccess(SignEncryptResult result);
-
- protected abstract SignEncryptParcel createEncryptBundle();
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java
deleted file mode 100644
index 2a102c6c4..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.net.Uri;
-
-import org.sufficientlysecure.keychain.util.Passphrase;
-
-import java.util.ArrayList;
-
-public interface EncryptActivityInterface {
-
- public interface UpdateListener {
- void onNotifyUpdate();
- }
-
- public boolean isUseArmor();
- public boolean isUseCompression();
- public boolean isEncryptFilenames();
- public boolean isHiddenRecipients();
-
- public long getSignatureKey();
- public long[] getEncryptionKeys();
- public String[] getEncryptionUsers();
- public void setSignatureKey(long signatureKey);
- public void setEncryptionKeys(long[] encryptionKeys);
- public void setEncryptionUsers(String[] encryptionUsers);
-
- public void setPassphrase(Passphrase passphrase);
-
- // ArrayList on purpose as only those are parcelable
- public ArrayList<Uri> getInputUris();
- public ArrayList<Uri> getOutputUris();
- public void setInputUris(ArrayList<Uri> uris);
- public void setOutputUris(ArrayList<Uri> uris);
-
- public String getMessage();
- public void setMessage(String message);
-
- /**
- * Call this to notify the UI for changes done on the array lists or arrays,
- * automatically called if setter is used
- */
- public void notifyUpdate();
-
- public void startEncrypt(boolean share);
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java
index a498d0763..a6fad8881 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java
@@ -37,10 +37,6 @@ import java.util.regex.Matcher;
public class EncryptDecryptOverviewFragment extends Fragment {
- View mEncryptFile;
- View mEncryptText;
- View mDecryptFile;
- View mDecryptFromClipboard;
View mClipboardIcon;
@Override
@@ -53,10 +49,10 @@ public class EncryptDecryptOverviewFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.encrypt_decrypt_overview_fragment, container, false);
- mEncryptFile = view.findViewById(R.id.encrypt_files);
- mEncryptText = view.findViewById(R.id.encrypt_text);
- mDecryptFile = view.findViewById(R.id.decrypt_files);
- mDecryptFromClipboard = view.findViewById(R.id.decrypt_from_clipboard);
+ View mEncryptFile = view.findViewById(R.id.encrypt_files);
+ View mEncryptText = view.findViewById(R.id.encrypt_text);
+ View mDecryptFile = view.findViewById(R.id.decrypt_files);
+ View mDecryptFromClipboard = view.findViewById(R.id.decrypt_from_clipboard);
mClipboardIcon = view.findViewById(R.id.clipboard_icon);
mEncryptFile.setOnClickListener(new View.OnClickListener() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
index fe9b05226..64e908b1a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2012-2015 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010-2014 Thialfihar <thi@thialfihar.org>
*
* This program is free software: you can redistribute it and/or modify
@@ -18,32 +18,25 @@
package org.sufficientlysecure.keychain.ui;
+import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
-import android.view.Menu;
-import android.view.MenuItem;
+import android.support.v4.app.FragmentTransaction;
+import android.view.View;
-import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
-import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
-import org.sufficientlysecure.keychain.pgp.KeyRing;
-import org.sufficientlysecure.keychain.pgp.PgpConstants;
-import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
-import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
-import org.sufficientlysecure.keychain.ui.util.Notify;
-import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.util.Passphrase;
-import org.sufficientlysecure.keychain.util.ShareHelper;
import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-public class EncryptFilesActivity extends EncryptActivity implements EncryptActivityInterface {
+public class EncryptFilesActivity extends BaseActivity implements
+ EncryptModeAsymmetricFragment.IAsymmetric, EncryptModeSymmetricFragment.ISymmetric,
+ EncryptFilesFragment.IMode {
/* Intents */
public static final String ACTION_ENCRYPT_DATA = OpenKeychainIntents.ENCRYPT_DATA;
@@ -55,302 +48,22 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
public static final String EXTRA_SIGNATURE_KEY_ID = Constants.EXTRA_PREFIX + "EXTRA_SIGNATURE_KEY_ID";
public static final String EXTRA_ENCRYPTION_KEY_IDS = Constants.EXTRA_PREFIX + "EXTRA_ENCRYPTION_IDS";
- // view
- private int mCurrentMode = MODE_ASYMMETRIC;
-
- // tabs
- private static final int MODE_ASYMMETRIC = 0;
- private static final int MODE_SYMMETRIC = 1;
-
- // model used by fragments
- private boolean mUseArmor = false;
- private boolean mUseCompression = true;
- private boolean mDeleteAfterEncrypt = false;
- private boolean mShareAfterEncrypt = false;
- private boolean mEncryptFilenames = true;
- private boolean mHiddenRecipients = false;
-
- private long mEncryptionKeyIds[] = null;
- private String mEncryptionUserIds[] = null;
- private long mSigningKeyId = Constants.key.none;
- private Passphrase mPassphrase = new Passphrase();
-
- private ArrayList<Uri> mInputUris;
- private ArrayList<Uri> mOutputUris;
- private String mMessage = "";
-
- public boolean isModeSymmetric() {
- return MODE_SYMMETRIC == mCurrentMode;
- }
-
- @Override
- public boolean isUseArmor() {
- return mUseArmor;
- }
-
- @Override
- public boolean isUseCompression() {
- return mUseCompression;
- }
-
- @Override
- public boolean isEncryptFilenames() {
- return mEncryptFilenames;
- }
-
- @Override
- public boolean isHiddenRecipients() {
- return mHiddenRecipients;
- }
-
- @Override
- public long getSignatureKey() {
- return mSigningKeyId;
- }
-
- @Override
- public long[] getEncryptionKeys() {
- return mEncryptionKeyIds;
- }
-
- @Override
- public String[] getEncryptionUsers() {
- return mEncryptionUserIds;
- }
-
- @Override
- public void setSignatureKey(long signatureKey) {
- mSigningKeyId = signatureKey;
- notifyUpdate();
- }
-
- @Override
- public void setEncryptionKeys(long[] encryptionKeys) {
- mEncryptionKeyIds = encryptionKeys;
- notifyUpdate();
- }
-
- @Override
- public void setEncryptionUsers(String[] encryptionUsers) {
- mEncryptionUserIds = encryptionUsers;
- notifyUpdate();
- }
-
- @Override
- public void setPassphrase(Passphrase passphrase) {
- mPassphrase = passphrase;
- }
-
- @Override
- public ArrayList<Uri> getInputUris() {
- if (mInputUris == null) mInputUris = new ArrayList<>();
- return mInputUris;
- }
-
- @Override
- public ArrayList<Uri> getOutputUris() {
- if (mOutputUris == null) mOutputUris = new ArrayList<>();
- return mOutputUris;
- }
-
- @Override
- public void setInputUris(ArrayList<Uri> uris) {
- mInputUris = uris;
- notifyUpdate();
- }
-
- @Override
- public void setOutputUris(ArrayList<Uri> uris) {
- mOutputUris = uris;
- notifyUpdate();
- }
-
- @Override
- public String getMessage() {
- return mMessage;
- }
-
- @Override
- public void setMessage(String message) {
- mMessage = message;
- }
-
- @Override
- public void notifyUpdate() {
- for (Fragment fragment : getSupportFragmentManager().getFragments()) {
- if (fragment instanceof EncryptActivityInterface.UpdateListener) {
- ((UpdateListener) fragment).onNotifyUpdate();
- }
- }
- }
-
- @Override
- public void startEncrypt(boolean share) {
- mShareAfterEncrypt = share;
- startEncrypt();
- }
-
- @Override
- public void onEncryptSuccess(final SignEncryptResult result) {
- if (mDeleteAfterEncrypt) {
- final Uri[] inputUris = mInputUris.toArray(new Uri[mInputUris.size()]);
- DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(inputUris);
- deleteFileDialog.setOnDeletedListener(new DeleteFileDialogFragment.OnDeletedListener() {
-
- @Override
- public void onDeleted() {
- if (mShareAfterEncrypt) {
- // Share encrypted message/file
- startActivity(sendWithChooserExcludingEncrypt());
- } else {
- // Save encrypted file
- result.createNotify(EncryptFilesActivity.this).show();
- }
- }
-
- });
- deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog");
-
- mInputUris.clear();
- notifyUpdate();
- } else {
- if (mShareAfterEncrypt) {
- // Share encrypted message/file
- startActivity(sendWithChooserExcludingEncrypt());
- } else {
- // Save encrypted file
- result.createNotify(EncryptFilesActivity.this).show();
- }
- }
- }
-
- @Override
- protected SignEncryptParcel createEncryptBundle() {
- // fill values for this action
- SignEncryptParcel data = new SignEncryptParcel();
-
- data.addInputUris(mInputUris);
- data.addOutputUris(mOutputUris);
-
- if (mUseCompression) {
- data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.get(0));
- } else {
- data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED);
- }
- data.setHiddenRecipients(mHiddenRecipients);
- data.setEnableAsciiArmorOutput(mUseArmor);
- data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
- data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
-
- if (isModeSymmetric()) {
- Log.d(Constants.TAG, "Symmetric encryption enabled!");
- Passphrase passphrase = mPassphrase;
- if (passphrase.isEmpty()) {
- passphrase = null;
- }
- data.setSymmetricPassphrase(passphrase);
- } else {
- data.setEncryptionMasterKeyIds(mEncryptionKeyIds);
- data.setSignatureMasterKeyId(mSigningKeyId);
- data.setSignaturePassphrase(mSigningKeyPassphrase);
- data.setNfcState(mNfcHash, mNfcTimestamp);
- }
- return data;
- }
-
- /**
- * Create Intent Chooser but exclude OK's EncryptActivity.
- */
- private Intent sendWithChooserExcludingEncrypt() {
- Intent prototype = createSendIntent();
- String title = getString(R.string.title_share_file);
-
- // we don't want to encrypt the encrypted, no inception ;)
- String[] blacklist = new String[]{
- Constants.PACKAGE_NAME + ".ui.EncryptFileActivity",
- "org.thialfihar.android.apg.ui.EncryptActivity"
- };
-
- return new ShareHelper(this).createChooserExcluding(prototype, title, blacklist);
- }
-
- private Intent createSendIntent() {
- Intent sendIntent;
- // file
- if (mOutputUris.size() == 1) {
- sendIntent = new Intent(Intent.ACTION_SEND);
- sendIntent.putExtra(Intent.EXTRA_STREAM, mOutputUris.get(0));
- } else {
- sendIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
- sendIntent.putExtra(Intent.EXTRA_STREAM, mOutputUris);
- }
- sendIntent.setType(Constants.ENCRYPTED_FILES_MIME);
-
- if (!isModeSymmetric() && mEncryptionUserIds != null) {
- Set<String> users = new HashSet<>();
- for (String user : mEncryptionUserIds) {
- KeyRing.UserId userId = KeyRing.splitUserId(user);
- if (userId.email != null) {
- users.add(userId.email);
- }
- }
- sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()]));
- }
- return sendIntent;
- }
-
- protected boolean inputIsValid() {
- // file checks
-
- if (mInputUris.isEmpty()) {
- Notify.create(this, R.string.no_file_selected, Notify.Style.ERROR)
- .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_file_fragment));
- return false;
- } else if (mInputUris.size() > 1 && !mShareAfterEncrypt) {
- // This should be impossible...
- return false;
- } else if (mInputUris.size() != mOutputUris.size()) {
- // This as well
- return false;
- }
-
- if (isModeSymmetric()) {
- // symmetric encryption checks
-
- if (mPassphrase == null) {
- Notify.create(this, R.string.passphrases_do_not_match, Notify.Style.ERROR)
- .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_file_fragment));
- return false;
- }
- if (mPassphrase.isEmpty()) {
- Notify.create(this, R.string.passphrase_must_not_be_empty, Notify.Style.ERROR)
- .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_file_fragment));
- return false;
- }
-
- } else {
- // asymmetric encryption checks
-
- boolean gotEncryptionKeys = (mEncryptionKeyIds != null
- && mEncryptionKeyIds.length > 0);
-
- // Files must be encrypted, only text can be signed-only right now
- if (!gotEncryptionKeys) {
- Notify.create(this, R.string.select_encryption_key, Notify.Style.ERROR)
- .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_file_fragment));
- return false;
- }
- }
- return true;
- }
+ Fragment mModeFragment;
+ EncryptFilesFragment mEncryptFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setFullScreenDialogClose(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ }, false);
+
// Handle intent actions
- handleActions(getIntent());
- updateModeFragment();
+ handleActions(getIntent(), savedInstanceState);
}
@Override
@@ -358,73 +71,10 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
setContentView(R.layout.encrypt_files_activity);
}
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.encrypt_file_activity, menu);
- return super.onCreateOptionsMenu(menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (item.isCheckable()) {
- item.setChecked(!item.isChecked());
- }
- switch (item.getItemId()) {
- case R.id.check_use_symmetric: {
- mCurrentMode = item.isChecked() ? MODE_SYMMETRIC : MODE_ASYMMETRIC;
- updateModeFragment();
- notifyUpdate();
- break;
- }
- case R.id.check_use_armor: {
- mUseArmor = item.isChecked();
- notifyUpdate();
- break;
- }
- case R.id.check_delete_after_encrypt: {
- mDeleteAfterEncrypt = item.isChecked();
- notifyUpdate();
- break;
- }
- case R.id.check_enable_compression: {
- mUseCompression = item.isChecked();
- notifyUpdate();
- break;
- }
- case R.id.check_encrypt_filenames: {
- mEncryptFilenames = item.isChecked();
- notifyUpdate();
- break;
- }
-// case R.id.check_hidden_recipients: {
-// mHiddenRecipients = item.isChecked();
-// notifyUpdate();
-// break;
-// }
- default: {
- return super.onOptionsItemSelected(item);
- }
- }
- return true;
- }
-
- private void updateModeFragment() {
- getSupportFragmentManager().beginTransaction()
- .replace(R.id.encrypt_pager_mode,
- mCurrentMode == MODE_SYMMETRIC
- ? new EncryptSymmetricFragment()
- : new EncryptAsymmetricFragment()
- )
- .commitAllowingStateLoss();
- getSupportFragmentManager().executePendingTransactions();
- }
-
/**
* Handles all actions with this intent
- *
- * @param intent
*/
- private void handleActions(Intent intent) {
+ private void handleActions(Intent intent, Bundle savedInstanceState) {
String action = intent.getAction();
Bundle extras = intent.getExtras();
String type = intent.getType();
@@ -453,14 +103,56 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
}
- mUseArmor = extras.getBoolean(EXTRA_ASCII_ARMOR, false);
+ long mSigningKeyId = extras.getLong(EXTRA_SIGNATURE_KEY_ID);
+ long[] mEncryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS);
+ boolean useArmor = extras.getBoolean(EXTRA_ASCII_ARMOR, false);
+
+ if (savedInstanceState == null) {
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+
+ mModeFragment = EncryptModeAsymmetricFragment.newInstance(mSigningKeyId, mEncryptionKeyIds);
+ transaction.replace(R.id.encrypt_mode_container, mModeFragment, "mode");
+
+ mEncryptFragment = EncryptFilesFragment.newInstance(uris, useArmor);
+ transaction.replace(R.id.encrypt_file_container, mEncryptFragment, "files");
+
+ transaction.commit();
+
+ getSupportFragmentManager().executePendingTransactions();
+ }
+ }
+
+ @Override
+ public void onModeChanged(boolean symmetric) {
+ // switch fragments
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.encrypt_mode_container,
+ symmetric
+ ? EncryptModeSymmetricFragment.newInstance()
+ : EncryptModeAsymmetricFragment.newInstance(0, null)
+ )
+ .commitAllowingStateLoss();
+ getSupportFragmentManager().executePendingTransactions();
+ }
- // preselect keys given by intent
- mSigningKeyId = extras.getLong(EXTRA_SIGNATURE_KEY_ID);
- mEncryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS);
+ @Override
+ public void onSignatureKeyIdChanged(long signatureKeyId) {
+ mEncryptFragment.setSigningKeyId(signatureKeyId);
+ }
+
+ @Override
+ public void onEncryptionKeyIdsChanged(long[] encryptionKeyIds) {
+ mEncryptFragment.setEncryptionKeyIds(encryptionKeyIds);
+ }
- // Save uris
- mInputUris = uris;
+ @Override
+ public void onEncryptionUserIdsChanged(String[] encryptionUserIds) {
+ mEncryptFragment.setEncryptionUserIds(encryptionUserIds);
+ }
+
+ @Override
+ public void onPassphraseChanged(Passphrase passphrase) {
+ mEncryptFragment.setPassphrase(passphrase);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
index 4ba76d8ea..ccb4a6355 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,57 +17,130 @@
package org.sufficientlysecure.keychain.ui;
-import android.annotation.TargetApi;
import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.support.v4.app.Fragment;
+import android.os.Message;
+import android.os.Messenger;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.BaseAdapter;
+import android.widget.Button;
import android.widget.ImageView;
-import android.widget.ListView;
import android.widget.TextView;
+import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
+import org.sufficientlysecure.keychain.pgp.KeyRing;
+import org.sufficientlysecure.keychain.pgp.PgpConstants;
+import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
+import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.ui.adapter.SpacesItemDecoration;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
+import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
+import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.FileHelper;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
+import org.sufficientlysecure.keychain.util.ShareHelper;
import java.io.File;
-import java.util.HashMap;
+import java.io.IOException;
+import java.util.ArrayList;
import java.util.HashSet;
-import java.util.Map;
+import java.util.List;
+import java.util.Set;
-public class EncryptFilesFragment extends Fragment implements EncryptActivityInterface.UpdateListener {
+public class EncryptFilesFragment extends CryptoOperationFragment {
+
+ public interface IMode {
+ public void onModeChanged(boolean symmetric);
+ }
+
+ public static final String ARG_USE_ASCII_ARMOR = "use_ascii_armor";
public static final String ARG_URIS = "uris";
private static final int REQUEST_CODE_INPUT = 0x00007003;
private static final int REQUEST_CODE_OUTPUT = 0x00007007;
- private EncryptActivityInterface mEncryptInterface;
+ private IMode mModeInterface;
+
+ private boolean mSymmetricMode = false;
+ private boolean mUseArmor = false;
+ private boolean mUseCompression = true;
+ private boolean mDeleteAfterEncrypt = false;
+ private boolean mShareAfterEncrypt = false;
+ private boolean mEncryptFilenames = true;
+ private boolean mHiddenRecipients = false;
+
+ private long mEncryptionKeyIds[] = null;
+ private String mEncryptionUserIds[] = null;
+ private long mSigningKeyId = Constants.key.none;
+ private Passphrase mPassphrase = new Passphrase();
+
+ private ArrayList<Uri> mOutputUris = new ArrayList<>();
+
+ private RecyclerView mSelectedFiles;
+
+ ArrayList<FilesAdapter.ViewModel> mFilesModels;
+ FilesAdapter mFilesAdapter;
+
+ /**
+ * Creates new instance of this fragment
+ */
+ public static EncryptFilesFragment newInstance(ArrayList<Uri> uris, boolean useArmor) {
+ EncryptFilesFragment frag = new EncryptFilesFragment();
+
+ Bundle args = new Bundle();
+ args.putBoolean(ARG_USE_ASCII_ARMOR, useArmor);
+ args.putParcelableArrayList(ARG_URIS, uris);
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ public void setEncryptionKeyIds(long[] encryptionKeyIds) {
+ mEncryptionKeyIds = encryptionKeyIds;
+ }
- // view
- private View mAddView;
- private ListView mSelectedFiles;
- private SelectedFilesAdapter mAdapter = new SelectedFilesAdapter();
- private final Map<Uri, Bitmap> thumbnailCache = new HashMap<>();
+ public void setEncryptionUserIds(String[] encryptionUserIds) {
+ mEncryptionUserIds = encryptionUserIds;
+ }
+
+ public void setSigningKeyId(long signingKeyId) {
+ mSigningKeyId = signingKeyId;
+ }
+
+ public void setPassphrase(Passphrase passphrase) {
+ mPassphrase = passphrase;
+ }
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
- mEncryptInterface = (EncryptActivityInterface) activity;
+ mModeInterface = (IMode) activity;
} catch (ClassCastException e) {
- throw new ClassCastException(activity.toString() + " must implement EncryptActivityInterface");
+ throw new ClassCastException(activity + " must be IMode");
}
}
@@ -77,17 +150,28 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.encrypt_files_fragment, container, false);
+ mSelectedFiles = (RecyclerView) view.findViewById(R.id.selected_files_list);
+
+ mSelectedFiles.addItemDecoration(new SpacesItemDecoration(
+ FormattingUtils.dpToPx(getActivity(), 4)));
+ mSelectedFiles.setHasFixedSize(true);
+ mSelectedFiles.setLayoutManager(new LinearLayoutManager(getActivity()));
+ mSelectedFiles.setItemAnimator(new DefaultItemAnimator());
- mAddView = inflater.inflate(R.layout.file_list_entry_add, null);
- mAddView.setOnClickListener(new View.OnClickListener() {
+ mFilesModels = new ArrayList<>();
+ mFilesAdapter = new FilesAdapter(getActivity(), mFilesModels, new View.OnClickListener() {
@Override
public void onClick(View v) {
addInputUri();
}
});
- mSelectedFiles = (ListView) view.findViewById(R.id.selected_files_list);
- mSelectedFiles.addFooterView(mAddView);
- mSelectedFiles.setAdapter(mAdapter);
+
+ ArrayList<Uri> inputUris = getArguments().getParcelableArrayList(ARG_URIS);
+ if (inputUris != null) {
+ mFilesAdapter.addAll(inputUris);
+ }
+ mUseArmor = getArguments().getBoolean(ARG_USE_ASCII_ARMOR);
+ mSelectedFiles.setAdapter(mFilesAdapter);
return view;
}
@@ -95,7 +179,6 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
setHasOptionsMenu(true);
}
@@ -103,8 +186,8 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
FileHelper.openDocument(EncryptFilesFragment.this, "*/*", true, REQUEST_CODE_INPUT);
} else {
- FileHelper.openFile(EncryptFilesFragment.this, mEncryptInterface.getInputUris().isEmpty() ?
- null : mEncryptInterface.getInputUris().get(mEncryptInterface.getInputUris().size() - 1),
+ FileHelper.openFile(EncryptFilesFragment.this, mFilesModels.isEmpty() ?
+ null : mFilesModels.get(mFilesModels.size() - 1).inputUri,
"*/*", REQUEST_CODE_INPUT);
}
}
@@ -114,34 +197,27 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
return;
}
- if (mEncryptInterface.getInputUris().contains(inputUri)) {
+ try {
+ mFilesAdapter.add(inputUri);
+ } catch (IOException e) {
Notify.create(getActivity(),
getActivity().getString(R.string.error_file_added_already, FileHelper.getFilename(getActivity(), inputUri)),
- Notify.Style.ERROR).show(this);
+ Notify.Style.ERROR).show();
return;
}
-
- mEncryptInterface.getInputUris().add(inputUri);
- mEncryptInterface.notifyUpdate();
- mSelectedFiles.requestFocus();
- }
-
- private void delInputUri(int position) {
- mEncryptInterface.getInputUris().remove(position);
- mEncryptInterface.notifyUpdate();
mSelectedFiles.requestFocus();
}
private void showOutputFileDialog() {
- if (mEncryptInterface.getInputUris().size() > 1 || mEncryptInterface.getInputUris().isEmpty()) {
+ if (mFilesModels.size() > 1 || mFilesModels.isEmpty()) {
throw new IllegalStateException();
}
- Uri inputUri = mEncryptInterface.getInputUris().get(0);
+ FilesAdapter.ViewModel model = mFilesModels.get(0);
String targetName =
- (mEncryptInterface.isEncryptFilenames() ? "1" : FileHelper.getFilename(getActivity(), inputUri))
- + (mEncryptInterface.isUseArmor() ? Constants.FILE_EXTENSION_ASC : Constants.FILE_EXTENSION_PGP_MAIN);
+ (mEncryptFilenames ? "1" : FileHelper.getFilename(getActivity(), model.inputUri))
+ + (mUseArmor ? Constants.FILE_EXTENSION_ASC : Constants.FILE_EXTENSION_PGP_MAIN);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- File file = new File(inputUri.getPath());
+ File file = new File(model.inputUri.getPath());
File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR;
File targetFile = new File(parentDir, targetName);
FileHelper.saveFile(this, getString(R.string.title_encrypt_to_file),
@@ -152,44 +228,61 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
}
private void encryptClicked(boolean share) {
- if (mEncryptInterface.getInputUris().isEmpty()) {
- Notify.create(getActivity(), R.string.error_no_file_selected, Notify.Style.ERROR).show(this);
+ if (mFilesModels.isEmpty()) {
+ Notify.create(getActivity(), R.string.error_no_file_selected,
+ Notify.Style.ERROR).show();
return;
}
if (share) {
- mEncryptInterface.getOutputUris().clear();
+ mOutputUris.clear();
int filenameCounter = 1;
- for (Uri uri : mEncryptInterface.getInputUris()) {
+ for (FilesAdapter.ViewModel model : mFilesModels) {
String targetName =
- (mEncryptInterface.isEncryptFilenames() ? String.valueOf(filenameCounter) : FileHelper.getFilename(getActivity(), uri))
- + (mEncryptInterface.isUseArmor() ? Constants.FILE_EXTENSION_ASC : Constants.FILE_EXTENSION_PGP_MAIN);
- mEncryptInterface.getOutputUris().add(TemporaryStorageProvider.createFile(getActivity(), targetName));
+ (mEncryptFilenames ? String.valueOf(filenameCounter) : FileHelper.getFilename(getActivity(), model.inputUri))
+ + (mUseArmor ? Constants.FILE_EXTENSION_ASC : Constants.FILE_EXTENSION_PGP_MAIN);
+ mOutputUris.add(TemporaryStorageProvider.createFile(getActivity(), targetName));
filenameCounter++;
}
- mEncryptInterface.startEncrypt(true);
+ startEncrypt(true);
} else {
- if (mEncryptInterface.getInputUris().size() > 1) {
- Notify.create(getActivity(), R.string.error_multi_not_supported, Notify.Style.ERROR).show(this);
+ if (mFilesModels.size() > 1) {
+ Notify.create(getActivity(), R.string.error_multi_not_supported,
+ Notify.Style.ERROR).show();
return;
}
showOutputFileDialog();
}
}
- @TargetApi(Build.VERSION_CODES.KITKAT)
- public boolean handleClipData(Intent data) {
- if (data.getClipData() != null && data.getClipData().getItemCount() > 0) {
- for (int i = 0; i < data.getClipData().getItemCount(); i++) {
- Uri uri = data.getClipData().getItemAt(i).getUri();
- if (uri != null) addInputUri(uri);
+ public void addFile(Intent data) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ addInputUri(data.getData());
+ } else {
+ if (data.getClipData() != null && data.getClipData().getItemCount() > 0) {
+ for (int i = 0; i < data.getClipData().getItemCount(); i++) {
+ Uri uri = data.getClipData().getItemAt(i).getUri();
+ if (uri != null) {
+ addInputUri(uri);
+ }
+ }
+ } else {
+ // fallback, try old method to get single uri
+ addInputUri(data.getData());
}
- return true;
}
- return false;
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ inflater.inflate(R.menu.encrypt_file_fragment, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.isCheckable()) {
+ item.setChecked(!item.isChecked());
+ }
switch (item.getItemId()) {
case R.id.encrypt_save: {
encryptClicked(false);
@@ -199,6 +292,32 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
encryptClicked(true);
break;
}
+ case R.id.check_use_symmetric: {
+ mSymmetricMode = item.isChecked();
+ mModeInterface.onModeChanged(mSymmetricMode);
+ break;
+ }
+ case R.id.check_use_armor: {
+ mUseArmor = item.isChecked();
+ break;
+ }
+ case R.id.check_delete_after_encrypt: {
+ mDeleteAfterEncrypt = item.isChecked();
+ break;
+ }
+ case R.id.check_enable_compression: {
+ mUseCompression = item.isChecked();
+ break;
+ }
+ case R.id.check_encrypt_filenames: {
+ mEncryptFilenames = item.isChecked();
+ break;
+ }
+// case R.id.check_hidden_recipients: {
+// mHiddenRecipients = item.isChecked();
+// notifyUpdate();
+// break;
+// }
default: {
return super.onOptionsItemSelected(item);
}
@@ -206,24 +325,234 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
return true;
}
+ protected boolean inputIsValid() {
+ // file checks
+
+ if (mFilesModels.isEmpty()) {
+ Notify.create(getActivity(), R.string.no_file_selected, Notify.Style.ERROR)
+ .show();
+ return false;
+ } else if (mFilesModels.size() > 1 && !mShareAfterEncrypt) {
+ Log.e(Constants.TAG, "Aborting: mInputUris.size() > 1 && !mShareAfterEncrypt");
+ // This should be impossible...
+ return false;
+ } else if (mFilesModels.size() != mOutputUris.size()) {
+ Log.e(Constants.TAG, "Aborting: mInputUris.size() != mOutputUris.size()");
+ // This as well
+ return false;
+ }
+
+ if (mSymmetricMode) {
+ // symmetric encryption checks
+
+ if (mPassphrase == null) {
+ Notify.create(getActivity(), R.string.passphrases_do_not_match, Notify.Style.ERROR)
+ .show();
+ return false;
+ }
+ if (mPassphrase.isEmpty()) {
+ Notify.create(getActivity(), R.string.passphrase_must_not_be_empty, Notify.Style.ERROR)
+ .show();
+ return false;
+ }
+
+ } else {
+ // asymmetric encryption checks
+
+ boolean gotEncryptionKeys = (mEncryptionKeyIds != null
+ && mEncryptionKeyIds.length > 0);
+
+ // Files must be encrypted, only text can be signed-only right now
+ if (!gotEncryptionKeys) {
+ Notify.create(getActivity(), R.string.select_encryption_key, Notify.Style.ERROR)
+ .show();
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void onEncryptSuccess(final SignEncryptResult result) {
+ if (mDeleteAfterEncrypt) {
+ DeleteFileDialogFragment deleteFileDialog =
+ DeleteFileDialogFragment.newInstance(mFilesAdapter.getAsArrayList());
+ deleteFileDialog.setOnDeletedListener(new DeleteFileDialogFragment.OnDeletedListener() {
+
+ @Override
+ public void onDeleted() {
+ if (mShareAfterEncrypt) {
+ // Share encrypted message/file
+ startActivity(sendWithChooserExcludingEncrypt());
+ } else {
+ // Save encrypted file
+ result.createNotify(getActivity()).show();
+ }
+ }
+
+ });
+ deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog");
+ } else {
+ if (mShareAfterEncrypt) {
+ // Share encrypted message/file
+ startActivity(sendWithChooserExcludingEncrypt());
+ } else {
+ // Save encrypted file
+ result.createNotify(getActivity()).show();
+ }
+ }
+ }
+
+ protected SignEncryptParcel createEncryptBundle() {
+ // fill values for this action
+ SignEncryptParcel data = new SignEncryptParcel();
+
+ data.addInputUris(mFilesAdapter.getAsArrayList());
+ data.addOutputUris(mOutputUris);
+
+ if (mUseCompression) {
+ data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.get(0));
+ } else {
+ data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED);
+ }
+ data.setHiddenRecipients(mHiddenRecipients);
+ data.setEnableAsciiArmorOutput(mUseArmor);
+ data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
+ data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
+
+ if (mSymmetricMode) {
+ Log.d(Constants.TAG, "Symmetric encryption enabled!");
+ Passphrase passphrase = mPassphrase;
+ if (passphrase.isEmpty()) {
+ passphrase = null;
+ }
+ data.setSymmetricPassphrase(passphrase);
+ } else {
+ data.setEncryptionMasterKeyIds(mEncryptionKeyIds);
+ data.setSignatureMasterKeyId(mSigningKeyId);
+ }
+ return data;
+ }
+
+ /**
+ * Create Intent Chooser but exclude OK's EncryptActivity.
+ */
+ private Intent sendWithChooserExcludingEncrypt() {
+ Intent prototype = createSendIntent();
+ String title = getString(R.string.title_share_file);
+
+ // we don't want to encrypt the encrypted, no inception ;)
+ String[] blacklist = new String[]{
+ Constants.PACKAGE_NAME + ".ui.EncryptFileActivity",
+ "org.thialfihar.android.apg.ui.EncryptActivity"
+ };
+
+ return new ShareHelper(getActivity()).createChooserExcluding(prototype, title, blacklist);
+ }
+
+ private Intent createSendIntent() {
+ Intent sendIntent;
+ // file
+ if (mOutputUris.size() == 1) {
+ sendIntent = new Intent(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_STREAM, mOutputUris.get(0));
+ } else {
+ sendIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
+ sendIntent.putExtra(Intent.EXTRA_STREAM, mOutputUris);
+ }
+ sendIntent.setType(Constants.ENCRYPTED_FILES_MIME);
+
+ if (!mSymmetricMode && mEncryptionUserIds != null) {
+ Set<String> users = new HashSet<>();
+ for (String user : mEncryptionUserIds) {
+ KeyRing.UserId userId = KeyRing.splitUserId(user);
+ if (userId.email != null) {
+ users.add(userId.email);
+ }
+ }
+ sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()]));
+ }
+ return sendIntent;
+ }
+
+ public void startEncrypt(boolean share) {
+ mShareAfterEncrypt = share;
+ cryptoOperation();
+ }
+
+ @Override
+ protected void cryptoOperation(CryptoInputParcel cryptoInput) {
+
+ if (!inputIsValid()) {
+ // Notify was created by inputIsValid.
+ Log.d(Constants.TAG, "Input not valid!");
+ return;
+ }
+ Log.d(Constants.TAG, "Input valid!");
+
+ // Send all information needed to service to edit key in other thread
+ Intent intent = new Intent(getActivity(), KeychainIntentService.class);
+ intent.setAction(KeychainIntentService.ACTION_SIGN_ENCRYPT);
+
+ final SignEncryptParcel input = createEncryptBundle();
+
+ Bundle data = new Bundle();
+ data.putParcelable(KeychainIntentService.SIGN_ENCRYPT_PARCEL, input);
+ data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
+
+ // Message is received after encrypting is done in KeychainIntentService
+ ServiceProgressHandler serviceHandler = new ServiceProgressHandler(
+ getActivity(),
+ getString(R.string.progress_encrypting),
+ ProgressDialog.STYLE_HORIZONTAL,
+ true,
+ ProgressDialogFragment.ServiceType.KEYCHAIN_INTENT) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ // handle pending messages
+ if (handlePendingMessage(message)) {
+ return;
+ }
+
+ if (message.arg1 == MessageStatus.OKAY.ordinal()) {
+ SignEncryptResult result =
+ message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT);
+ if (result.success()) {
+ onEncryptSuccess(result);
+ } else {
+ result.createNotify(getActivity()).show();
+ }
+ }
+ }
+ };
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(serviceHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ // show progress dialog
+ serviceHandler.showProgressDialog(getActivity());
+
+ // start service with intent
+ getActivity().startService(intent);
+ }
+
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_INPUT: {
if (resultCode == Activity.RESULT_OK && data != null) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT || !handleClipData(data)) {
- addInputUri(data.getData());
- }
+ addFile(data);
}
return;
}
case REQUEST_CODE_OUTPUT: {
// This happens after output file was selected, so start our operation
if (resultCode == Activity.RESULT_OK && data != null) {
- mEncryptInterface.getOutputUris().clear();
- mEncryptInterface.getOutputUris().add(data.getData());
- mEncryptInterface.notifyUpdate();
- mEncryptInterface.startEncrypt(false);
+ mOutputUris.clear();
+ mOutputUris.add(data.getData());
+ startEncrypt(false);
}
return;
}
@@ -236,67 +565,190 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
}
}
- @Override
- public void onNotifyUpdate() {
- // Clear cache if needed
- for (Uri uri : new HashSet<>(thumbnailCache.keySet())) {
- if (!mEncryptInterface.getInputUris().contains(uri)) {
- thumbnailCache.remove(uri);
+ public static class FilesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+ private Activity mActivity;
+ private List<ViewModel> mDataset;
+ private View.OnClickListener mFooterOnClickListener;
+ private static final int TYPE_FOOTER = 0;
+ private static final int TYPE_ITEM = 1;
+
+ public static class ViewModel {
+ Uri inputUri;
+ Bitmap thumbnail;
+ String filename;
+ long fileSize;
+
+ ViewModel(Context context, Uri inputUri) {
+ this.inputUri = inputUri;
+ int px = FormattingUtils.dpToPx(context, 48);
+ this.thumbnail = FileHelper.getThumbnail(context, inputUri, new Point(px, px));
+ this.filename = FileHelper.getFilename(context, inputUri);
+ this.fileSize = FileHelper.getFileSize(context, inputUri);
+ }
+
+ /**
+ * Depends on inputUri only
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ViewModel viewModel = (ViewModel) o;
+ return !(inputUri != null ? !inputUri.equals(viewModel.inputUri)
+ : viewModel.inputUri != null);
+ }
+
+ /**
+ * Depends on inputUri only
+ */
+ @Override
+ public int hashCode() {
+ return inputUri != null ? inputUri.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return inputUri.toString();
}
}
- mAdapter.notifyDataSetChanged();
- }
+ // Provide a reference to the views for each data item
+ // Complex data items may need more than one view per item, and
+ // you provide access to all the views for a data item in a view holder
+ class ViewHolder extends RecyclerView.ViewHolder {
+ public TextView filename;
+ public TextView fileSize;
+ public View removeButton;
+ public ImageView thumbnail;
+
+ public ViewHolder(View itemView) {
+ super(itemView);
+ filename = (TextView) itemView.findViewById(R.id.filename);
+ fileSize = (TextView) itemView.findViewById(R.id.filesize);
+ removeButton = itemView.findViewById(R.id.action_remove_file_from_list);
+ thumbnail = (ImageView) itemView.findViewById(R.id.thumbnail);
+ }
+ }
- private class SelectedFilesAdapter extends BaseAdapter {
+ class FooterHolder extends RecyclerView.ViewHolder {
+ public Button mAddButton;
+
+ public FooterHolder(View itemView) {
+ super(itemView);
+ mAddButton = (Button) itemView.findViewById(R.id.file_list_entry_add);
+ }
+ }
+
+ // Provide a suitable constructor (depends on the kind of dataset)
+ public FilesAdapter(Activity activity, List<ViewModel> myDataset, View.OnClickListener onFooterClickListener) {
+ mActivity = activity;
+ mDataset = myDataset;
+ mFooterOnClickListener = onFooterClickListener;
+ }
+
+ // Create new views (invoked by the layout manager)
@Override
- public int getCount() {
- return mEncryptInterface.getInputUris().size();
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ if (viewType == TYPE_FOOTER) {
+ View v = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.file_list_entry_add, parent, false);
+ return new FooterHolder(v);
+ } else {
+ //inflate your layout and pass it to view holder
+ View v = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.file_list_entry, parent, false);
+ return new ViewHolder(v);
+ }
}
+ // Replace the contents of a view (invoked by the layout manager)
@Override
- public Object getItem(int position) {
- return mEncryptInterface.getInputUris().get(position);
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
+ if (holder instanceof FooterHolder) {
+ FooterHolder thisHolder = (FooterHolder) holder;
+ thisHolder.mAddButton.setOnClickListener(mFooterOnClickListener);
+ } else if (holder instanceof ViewHolder) {
+ ViewHolder thisHolder = (ViewHolder) holder;
+ // - get element from your dataset at this position
+ // - replace the contents of the view with that element
+ final ViewModel model = mDataset.get(position);
+
+ thisHolder.filename.setText(model.filename);
+ if (model.fileSize == -1) {
+ thisHolder.fileSize.setText("");
+ } else {
+ thisHolder.fileSize.setText(FileHelper.readableFileSize(model.fileSize));
+ }
+ thisHolder.removeButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ remove(model);
+ }
+ });
+ if (model.thumbnail != null) {
+ thisHolder.thumbnail.setImageBitmap(model.thumbnail);
+ } else {
+ thisHolder.thumbnail.setImageResource(R.drawable.ic_doc_generic_am);
+ }
+ }
}
+ // Return the size of your dataset (invoked by the layout manager)
@Override
- public long getItemId(int position) {
- return getItem(position).hashCode();
+ public int getItemCount() {
+ return mDataset.size() + 1;
}
@Override
- public View getView(final int position, View convertView, ViewGroup parent) {
- Uri inputUri = mEncryptInterface.getInputUris().get(position);
- View view;
- if (convertView == null) {
- view = getActivity().getLayoutInflater().inflate(R.layout.file_list_entry, null);
+ public int getItemViewType(int position) {
+ if (isPositionFooter(position)) {
+ return TYPE_FOOTER;
} else {
- view = convertView;
+ return TYPE_ITEM;
}
- ((TextView) view.findViewById(R.id.filename)).setText(FileHelper.getFilename(getActivity(), inputUri));
- long size = FileHelper.getFileSize(getActivity(), inputUri);
- if (size == -1) {
- ((TextView) view.findViewById(R.id.filesize)).setText("");
- } else {
- ((TextView) view.findViewById(R.id.filesize)).setText(FileHelper.readableFileSize(size));
+ }
+
+ private boolean isPositionFooter(int position) {
+ return position == mDataset.size();
+ }
+
+ public void add(Uri inputUri) throws IOException {
+ ViewModel newModel = new ViewModel(mActivity, inputUri);
+ if (mDataset.contains(newModel)) {
+ throw new IOException("Already added!");
}
- view.findViewById(R.id.action_remove_file_from_list).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- delInputUri(position);
+ mDataset.add(newModel);
+ notifyItemInserted(mDataset.size() - 1);
+ }
+
+ public void addAll(ArrayList<Uri> inputUris) {
+ if (inputUris != null) {
+ int startIndex = mDataset.size();
+ for (Uri inputUri : inputUris) {
+ ViewModel newModel = new ViewModel(mActivity, inputUri);
+ if (mDataset.contains(newModel)) {
+ Log.e(Constants.TAG, "Skipped duplicate " + inputUri.toString());
+ } else {
+ mDataset.add(newModel);
+ }
}
- });
- int px = FormattingUtils.dpToPx(getActivity(), 48);
- if (!thumbnailCache.containsKey(inputUri)) {
- thumbnailCache.put(inputUri, FileHelper.getThumbnail(getActivity(), inputUri, new Point(px, px)));
+ notifyItemRangeInserted(startIndex, mDataset.size() - startIndex);
}
- Bitmap bitmap = thumbnailCache.get(inputUri);
- if (bitmap != null) {
- ((ImageView) view.findViewById(R.id.thumbnail)).setImageBitmap(bitmap);
- } else {
- ((ImageView) view.findViewById(R.id.thumbnail)).setImageResource(R.drawable.ic_doc_generic_am);
+ }
+
+ public void remove(ViewModel model) {
+ int position = mDataset.indexOf(model);
+ mDataset.remove(position);
+ notifyItemRemoved(position);
+ }
+
+ public ArrayList<Uri> getAsArrayList() {
+ ArrayList<Uri> uris = new ArrayList<>();
+ for (ViewModel model : mDataset) {
+ uris.add(model.inputUri);
}
- return view;
+ return uris;
}
+
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java
index b242381b1..6f56f2dc4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -44,7 +44,17 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-public class EncryptAsymmetricFragment extends Fragment implements EncryptActivityInterface.UpdateListener {
+public class EncryptModeAsymmetricFragment extends Fragment {
+
+ public interface IAsymmetric {
+
+ public void onSignatureKeyIdChanged(long signatureKeyId);
+
+ public void onEncryptionKeyIdsChanged(long[] encryptionKeyIds);
+
+ public void onEncryptionUserIdsChanged(String[] encryptionUserIds);
+ }
+
ProviderHelper mProviderHelper;
// view
@@ -52,37 +62,43 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi
private EncryptKeyCompletionView mEncryptKeyView;
// model
- private EncryptActivityInterface mEncryptInterface;
+ private IAsymmetric mEncryptInterface;
- @Override
- public void onNotifyUpdate() {
- if (mSign != null) {
- mSign.setSelectedKeyId(mEncryptInterface.getSignatureKey());
- }
+// @Override
+// public void updateUi() {
+// if (mSign != null) {
+// mSign.setSelectedKeyId(mEncryptInterface.getSignatureKey());
+// }
+// }
+
+ public static final String ARG_SINGATURE_KEY_ID = "signature_key_id";
+ public static final String ARG_ENCRYPTION_KEY_IDS = "encryption_key_ids";
+
+
+ /**
+ * Creates new instance of this fragment
+ */
+ public static EncryptModeAsymmetricFragment newInstance(long signatureKey, long[] encryptionKeyIds) {
+ EncryptModeAsymmetricFragment frag = new EncryptModeAsymmetricFragment();
+
+ Bundle args = new Bundle();
+ args.putLong(ARG_SINGATURE_KEY_ID, signatureKey);
+ args.putLongArray(ARG_ENCRYPTION_KEY_IDS, encryptionKeyIds);
+ frag.setArguments(args);
+
+ return frag;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
- mEncryptInterface = (EncryptActivityInterface) activity;
+ mEncryptInterface = (IAsymmetric) activity;
} catch (ClassCastException e) {
- throw new ClassCastException(activity + " must implement EncryptActivityInterface");
+ throw new ClassCastException(activity + " must implement IAsymmetric");
}
}
- private void setSignatureKeyId(long signatureKeyId) {
- mEncryptInterface.setSignatureKey(signatureKeyId);
- }
-
- private void setEncryptionKeyIds(long[] encryptionKeyIds) {
- mEncryptInterface.setEncryptionKeys(encryptionKeyIds);
- }
-
- private void setEncryptionUserIds(String[] encryptionUserIds) {
- mEncryptInterface.setEncryptionUsers(encryptionUserIds);
- }
-
/**
* Inflate the layout for this fragment
*/
@@ -94,7 +110,7 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi
mSign.setOnKeyChangedListener(new KeySpinner.OnKeyChangedListener() {
@Override
public void onKeyChanged(long masterKeyId) {
- setSignatureKeyId(masterKeyId);
+ mEncryptInterface.onSignatureKeyIdChanged(masterKeyId);
}
});
mEncryptKeyView = (EncryptKeyCompletionView) view.findViewById(R.id.recipient_list);
@@ -109,7 +125,9 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi
mProviderHelper = new ProviderHelper(getActivity());
// preselect keys given
- preselectKeys();
+ long signatureKeyId = getArguments().getLong(ARG_SINGATURE_KEY_ID);
+ long[] encryptionKeyIds = getArguments().getLongArray(ARG_ENCRYPTION_KEY_IDS);
+ preselectKeys(signatureKeyId, encryptionKeyIds);
mEncryptKeyView.setTokenListener(new TokenCompleteTextView.TokenListener() {
@Override
@@ -131,24 +149,20 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi
/**
* If an Intent gives a signatureMasterKeyId and/or encryptionMasterKeyIds, preselect those!
*/
- private void preselectKeys() {
- // TODO all of this works under the assumption that the first suitable subkey is always used!
- // not sure if we need to distinguish between different subkeys here?
- long signatureKey = mEncryptInterface.getSignatureKey();
- if (signatureKey != Constants.key.none) {
+ private void preselectKeys(long signatureKeyId, long[] encryptionKeyIds) {
+ if (signatureKeyId != Constants.key.none) {
try {
CachedPublicKeyRing keyring = mProviderHelper.getCachedPublicKeyRing(
- KeyRings.buildUnifiedKeyRingUri(signatureKey));
+ KeyRings.buildUnifiedKeyRingUri(signatureKeyId));
if (keyring.hasAnySecret()) {
- setSignatureKeyId(keyring.getMasterKeyId());
- mSign.setSelectedKeyId(mEncryptInterface.getSignatureKey());
+ mEncryptInterface.onSignatureKeyIdChanged(keyring.getMasterKeyId());
+ mSign.setSelectedKeyId(signatureKeyId);
}
} catch (PgpKeyNotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
}
}
- long[] encryptionKeyIds = mEncryptInterface.getEncryptionKeys();
if (encryptionKeyIds != null) {
for (long preselectedId : encryptionKeyIds) {
try {
@@ -181,7 +195,7 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi
for (int i = 0; i < keyIds.size(); i++) {
keyIdsArr[i] = iterator.next();
}
- setEncryptionKeyIds(keyIdsArr);
- setEncryptionUserIds(userIds.toArray(new String[userIds.size()]));
+ mEncryptInterface.onEncryptionKeyIdsChanged(keyIdsArr);
+ mEncryptInterface.onEncryptionUserIdsChanged(userIds.toArray(new String[userIds.size()]));
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeSymmetricFragment.java
index 36b3c08f9..48b1f4983 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeSymmetricFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,20 +30,37 @@ import android.widget.EditText;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.Passphrase;
-public class EncryptSymmetricFragment extends Fragment implements EncryptActivityInterface.UpdateListener {
+public class EncryptModeSymmetricFragment extends Fragment {
- EncryptActivityInterface mEncryptInterface;
+ public interface ISymmetric {
+
+ public void onPassphraseChanged(Passphrase passphrase);
+ }
+
+ private ISymmetric mEncryptInterface;
private EditText mPassphrase;
private EditText mPassphraseAgain;
+ /**
+ * Creates new instance of this fragment
+ */
+ public static EncryptModeSymmetricFragment newInstance() {
+ EncryptModeSymmetricFragment frag = new EncryptModeSymmetricFragment();
+
+ Bundle args = new Bundle();
+ frag.setArguments(args);
+
+ return frag;
+ }
+
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
- mEncryptInterface = (EncryptActivityInterface) activity;
+ mEncryptInterface = (ISymmetric) activity;
} catch (ClassCastException e) {
- throw new ClassCastException(activity.toString() + " must implement EncryptActivityInterface");
+ throw new ClassCastException(activity.toString() + " must implement ISymmetric");
}
}
@@ -74,9 +91,9 @@ public class EncryptSymmetricFragment extends Fragment implements EncryptActivit
p1.removeFromMemory();
p2.removeFromMemory();
if (passesEquals) {
- mEncryptInterface.setPassphrase(new Passphrase(mPassphrase.getText()));
+ mEncryptInterface.onPassphraseChanged(new Passphrase(mPassphrase.getText()));
} else {
- mEncryptInterface.setPassphrase(null);
+ mEncryptInterface.onPassphraseChanged(null);
}
}
};
@@ -86,8 +103,4 @@ public class EncryptSymmetricFragment extends Fragment implements EncryptActivit
return view;
}
- @Override
- public void onNotifyUpdate() {
-
- }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
index dd09e62c3..03ab48e23 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2012-2015 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010-2014 Thialfihar <thi@thialfihar.org>
*
* This program is free software: you can redistribute it and/or modify
@@ -19,31 +19,21 @@
package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
-import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
-import android.view.Menu;
-import android.view.MenuItem;
+import android.support.v4.app.FragmentTransaction;
+import android.view.View;
-import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
-import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
-import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
-import org.sufficientlysecure.keychain.pgp.KeyRing;
-import org.sufficientlysecure.keychain.pgp.PgpConstants;
-import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
-import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase;
-import org.sufficientlysecure.keychain.util.ShareHelper;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-
-public class EncryptTextActivity extends EncryptActivity implements EncryptActivityInterface {
+public class EncryptTextActivity extends BaseActivity implements
+ EncryptModeAsymmetricFragment.IAsymmetric, EncryptModeSymmetricFragment.ISymmetric,
+ EncryptTextFragment.IMode {
/* Intents */
public static final String ACTION_ENCRYPT_TEXT = OpenKeychainIntents.ENCRYPT_TEXT;
@@ -55,285 +45,22 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
public static final String EXTRA_SIGNATURE_KEY_ID = Constants.EXTRA_PREFIX + "EXTRA_SIGNATURE_KEY_ID";
public static final String EXTRA_ENCRYPTION_KEY_IDS = Constants.EXTRA_PREFIX + "EXTRA_SIGNATURE_KEY_IDS";
- // view
- private int mCurrentMode = MODE_ASYMMETRIC;
-
- // tabs
- private static final int MODE_ASYMMETRIC = 0;
- private static final int MODE_SYMMETRIC = 1;
-
- // model used by fragments
- private boolean mShareAfterEncrypt = false;
- private boolean mUseCompression = true;
- private boolean mHiddenRecipients = false;
-
- private long mEncryptionKeyIds[] = null;
- private String mEncryptionUserIds[] = null;
- // TODO Constants.key.none? What's wrong with a null value?
- private long mSigningKeyId = Constants.key.none;
- private Passphrase mPassphrase = new Passphrase();
-
- private ArrayList<Uri> mInputUris;
- private ArrayList<Uri> mOutputUris;
- private String mMessage = "";
-
- public boolean isModeSymmetric() {
- return MODE_SYMMETRIC == mCurrentMode;
- }
-
- @Override
- public boolean isUseArmor() {
- return true;
- }
-
- @Override
- public boolean isEncryptFilenames() {
- return false;
- }
-
- @Override
- public boolean isUseCompression() {
- return mUseCompression;
- }
-
- @Override
- public boolean isHiddenRecipients() {
- return mHiddenRecipients;
- }
-
- @Override
- public long getSignatureKey() {
- return mSigningKeyId;
- }
-
- @Override
- public long[] getEncryptionKeys() {
- return mEncryptionKeyIds;
- }
-
- @Override
- public String[] getEncryptionUsers() {
- return mEncryptionUserIds;
- }
-
- @Override
- public void setSignatureKey(long signatureKey) {
- mSigningKeyId = signatureKey;
- notifyUpdate();
- }
-
- @Override
- public void setEncryptionKeys(long[] encryptionKeys) {
- mEncryptionKeyIds = encryptionKeys;
- notifyUpdate();
- }
-
- @Override
- public void setEncryptionUsers(String[] encryptionUsers) {
- mEncryptionUserIds = encryptionUsers;
- notifyUpdate();
- }
-
- @Override
- public void setPassphrase(Passphrase passphrase) {
- if (mPassphrase != null) {
- mPassphrase.removeFromMemory();
- }
- mPassphrase = passphrase;
- }
-
- @Override
- public ArrayList<Uri> getInputUris() {
- if (mInputUris == null) mInputUris = new ArrayList<>();
- return mInputUris;
- }
-
- @Override
- public ArrayList<Uri> getOutputUris() {
- if (mOutputUris == null) mOutputUris = new ArrayList<>();
- return mOutputUris;
- }
-
- @Override
- public void setInputUris(ArrayList<Uri> uris) {
- mInputUris = uris;
- notifyUpdate();
- }
-
- @Override
- public void setOutputUris(ArrayList<Uri> uris) {
- mOutputUris = uris;
- notifyUpdate();
- }
-
- @Override
- public String getMessage() {
- return mMessage;
- }
-
- @Override
- public void setMessage(String message) {
- mMessage = message;
- }
-
- @Override
- public void notifyUpdate() {
- for (Fragment fragment : getSupportFragmentManager().getFragments()) {
- if (fragment instanceof UpdateListener) {
- ((UpdateListener) fragment).onNotifyUpdate();
- }
- }
- }
-
- @Override
- public void startEncrypt(boolean share) {
- mShareAfterEncrypt = share;
- startEncrypt();
- }
-
- @Override
- protected void onEncryptSuccess(SignEncryptResult result) {
- if (mShareAfterEncrypt) {
- // Share encrypted message/file
- startActivity(sendWithChooserExcludingEncrypt(result.getResultBytes()));
- } else {
- // Copy to clipboard
- copyToClipboard(result.getResultBytes());
- result.createNotify(EncryptTextActivity.this).show();
- // Notify.create(EncryptTextActivity.this,
- // R.string.encrypt_sign_clipboard_successful, Notify.Style.OK)
- // .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_text_fragment));
- }
- }
-
- @Override
- protected SignEncryptParcel createEncryptBundle() {
- // fill values for this action
- SignEncryptParcel data = new SignEncryptParcel();
-
- data.setBytes(mMessage.getBytes());
- data.setCleartextSignature(true);
-
- if (mUseCompression) {
- data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.get(0));
- } else {
- data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED);
- }
- data.setHiddenRecipients(mHiddenRecipients);
- data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
- data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
-
- // Always use armor for messages
- data.setEnableAsciiArmorOutput(true);
-
- if (isModeSymmetric()) {
- Log.d(Constants.TAG, "Symmetric encryption enabled!");
- Passphrase passphrase = mPassphrase;
- if (passphrase.isEmpty()) {
- passphrase = null;
- }
- data.setSymmetricPassphrase(passphrase);
- } else {
- data.setEncryptionMasterKeyIds(mEncryptionKeyIds);
- data.setSignatureMasterKeyId(mSigningKeyId);
- data.setSignaturePassphrase(mSigningKeyPassphrase);
- data.setNfcState(mNfcHash, mNfcTimestamp);
- }
- return data;
- }
-
- private void copyToClipboard(byte[] resultBytes) {
- ClipboardReflection.copyToClipboard(this, new String(resultBytes));
- }
-
- /**
- * Create Intent Chooser but exclude OK's EncryptActivity.
- */
- private Intent sendWithChooserExcludingEncrypt(byte[] resultBytes) {
- Intent prototype = createSendIntent(resultBytes);
- String title = getString(R.string.title_share_message);
-
- // we don't want to encrypt the encrypted, no inception ;)
- String[] blacklist = new String[]{
- Constants.PACKAGE_NAME + ".ui.EncryptTextActivity",
- "org.thialfihar.android.apg.ui.EncryptActivity"
- };
-
- return new ShareHelper(this).createChooserExcluding(prototype, title, blacklist);
- }
-
- private Intent createSendIntent(byte[] resultBytes) {
- Intent sendIntent;
- sendIntent = new Intent(Intent.ACTION_SEND);
- sendIntent.setType(Constants.ENCRYPTED_TEXT_MIME);
- sendIntent.putExtra(Intent.EXTRA_TEXT, new String(resultBytes));
-
- if (!isModeSymmetric() && mEncryptionUserIds != null) {
- Set<String> users = new HashSet<>();
- for (String user : mEncryptionUserIds) {
- KeyRing.UserId userId = KeyRing.splitUserId(user);
- if (userId.email != null) {
- users.add(userId.email);
- }
- }
- // pass trough email addresses as extra for email applications
- sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()]));
- }
- return sendIntent;
- }
-
- protected boolean inputIsValid() {
- if (mMessage == null) {
- Notify.create(this, R.string.error_message, Notify.Style.ERROR)
- .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_text_fragment));
- return false;
- }
-
- if (isModeSymmetric()) {
- // symmetric encryption checks
-
- if (mPassphrase == null) {
- Notify.create(this, R.string.passphrases_do_not_match, Notify.Style.ERROR)
- .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_text_fragment));
- return false;
- }
- if (mPassphrase.isEmpty()) {
- Notify.create(this, R.string.passphrase_must_not_be_empty, Notify.Style.ERROR)
- .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_text_fragment));
- return false;
- }
-
- } else {
- // asymmetric encryption checks
-
- boolean gotEncryptionKeys = (mEncryptionKeyIds != null
- && mEncryptionKeyIds.length > 0);
-
- if (!gotEncryptionKeys && mSigningKeyId == 0) {
- Notify.create(this, R.string.select_encryption_or_signature_key, Notify.Style.ERROR)
- .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_text_fragment));
- return false;
- }
- }
- return true;
- }
+ Fragment mModeFragment;
+ EncryptTextFragment mEncryptFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // if called with an intent action, do not init drawer navigation
- if (ACTION_ENCRYPT_TEXT.equals(getIntent().getAction())) {
- // lock drawer
-// deactivateDrawerNavigation();
- // TODO: back button to key?
- } else {
-// activateDrawerNavigation(savedInstanceState);
- }
+ setFullScreenDialogClose(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ }, false);
// Handle intent actions
- handleActions(getIntent());
- updateModeFragment();
+ handleActions(getIntent(), savedInstanceState);
}
@Override
@@ -341,58 +68,13 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
setContentView(R.layout.encrypt_text_activity);
}
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.encrypt_text_activity, menu);
- return super.onCreateOptionsMenu(menu);
- }
-
- private void updateModeFragment() {
- getSupportFragmentManager().beginTransaction()
- .replace(R.id.encrypt_pager_mode,
- mCurrentMode == MODE_SYMMETRIC
- ? new EncryptSymmetricFragment()
- : new EncryptAsymmetricFragment()
- )
- .commitAllowingStateLoss();
- getSupportFragmentManager().executePendingTransactions();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (item.isCheckable()) {
- item.setChecked(!item.isChecked());
- }
- switch (item.getItemId()) {
- case R.id.check_use_symmetric: {
- mCurrentMode = item.isChecked() ? MODE_SYMMETRIC : MODE_ASYMMETRIC;
- updateModeFragment();
- notifyUpdate();
- break;
- }
- case R.id.check_enable_compression: {
- mUseCompression = item.isChecked();
- notifyUpdate();
- break;
- }
-// case R.id.check_hidden_recipients: {
-// mHiddenRecipients = item.isChecked();
-// notifyUpdate();
-// break;
-// }
- default: {
- return super.onOptionsItemSelected(item);
- }
- }
- return true;
- }
/**
* Handles all actions with this intent
*
* @param intent
*/
- private void handleActions(Intent intent) {
+ private void handleActions(Intent intent, Bundle savedInstanceState) {
String action = intent.getAction();
Bundle extras = intent.getExtras();
String type = intent.getType();
@@ -423,19 +105,61 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
}
String textData = extras.getString(EXTRA_TEXT);
+ if (ACTION_ENCRYPT_TEXT.equals(action) && textData == null) {
+ Log.e(Constants.TAG, "Include the extra 'text' in your Intent!");
+ return;
+ }
// preselect keys given by intent
- mSigningKeyId = extras.getLong(EXTRA_SIGNATURE_KEY_ID);
- mEncryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS);
+ long mSigningKeyId = extras.getLong(EXTRA_SIGNATURE_KEY_ID);
+ long[] mEncryptionKeyIds = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS);
- /**
- * Main Actions
- */
- if (ACTION_ENCRYPT_TEXT.equals(action) && textData != null) {
- mMessage = textData;
- } else if (ACTION_ENCRYPT_TEXT.equals(action)) {
- Log.e(Constants.TAG, "Include the extra 'text' in your Intent!");
+
+ if (savedInstanceState == null) {
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+
+ mModeFragment = EncryptModeAsymmetricFragment.newInstance(mSigningKeyId, mEncryptionKeyIds);
+ transaction.replace(R.id.encrypt_mode_container, mModeFragment, "mode");
+
+ mEncryptFragment = EncryptTextFragment.newInstance(textData);
+ transaction.replace(R.id.encrypt_text_container, mEncryptFragment, "text");
+
+ transaction.commit();
+
+ getSupportFragmentManager().executePendingTransactions();
}
}
+ @Override
+ public void onModeChanged(boolean symmetric) {
+ // switch fragments
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.encrypt_mode_container,
+ symmetric
+ ? EncryptModeSymmetricFragment.newInstance()
+ : EncryptModeAsymmetricFragment.newInstance(0, null)
+ )
+ .commitAllowingStateLoss();
+ getSupportFragmentManager().executePendingTransactions();
+ }
+
+ @Override
+ public void onSignatureKeyIdChanged(long signatureKeyId) {
+ mEncryptFragment.setSigningKeyId(signatureKeyId);
+ }
+
+ @Override
+ public void onEncryptionKeyIdsChanged(long[] encryptionKeyIds) {
+ mEncryptFragment.setEncryptionKeyIds(encryptionKeyIds);
+ }
+
+ @Override
+ public void onEncryptionUserIdsChanged(String[] encryptionUserIds) {
+ mEncryptFragment.setEncryptionUserIds(encryptionUserIds);
+ }
+
+ @Override
+ public void onPassphraseChanged(Passphrase passphrase) {
+ mEncryptFragment.setSymmetricPassphrase(passphrase);
+ }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java
index 5d9994c5c..b37a2ca79 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,32 +18,102 @@
package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.app.Fragment;
+import android.os.Message;
+import android.os.Messenger;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
+import org.spongycastle.bcpg.CompressionAlgorithmTags;
+import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
+import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
+import org.sufficientlysecure.keychain.pgp.KeyRing;
+import org.sufficientlysecure.keychain.pgp.PgpConstants;
+import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
+import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
+import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
+import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
+import org.sufficientlysecure.keychain.util.ShareHelper;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class EncryptTextFragment extends CryptoOperationFragment {
+
+ public interface IMode {
+ public void onModeChanged(boolean symmetric);
+ }
-public class EncryptTextFragment extends Fragment {
public static final String ARG_TEXT = "text";
+ private IMode mModeInterface;
+
+ private boolean mSymmetricMode = false;
+ private boolean mShareAfterEncrypt = false;
+ private boolean mUseCompression = true;
+ private boolean mHiddenRecipients = false;
+
+ private long mEncryptionKeyIds[] = null;
+ private String mEncryptionUserIds[] = null;
+ // TODO Constants.key.none? What's wrong with a null value?
+ private long mSigningKeyId = Constants.key.none;
+ private Passphrase mSymmetricPassphrase = new Passphrase();
+ private String mMessage = "";
+
private TextView mText;
- private EncryptActivityInterface mEncryptInterface;
+ public void setEncryptionKeyIds(long[] encryptionKeyIds) {
+ mEncryptionKeyIds = encryptionKeyIds;
+ }
+
+ public void setEncryptionUserIds(String[] encryptionUserIds) {
+ mEncryptionUserIds = encryptionUserIds;
+ }
+
+ public void setSigningKeyId(long signingKeyId) {
+ mSigningKeyId = signingKeyId;
+ }
+
+ public void setSymmetricPassphrase(Passphrase passphrase) {
+ mSymmetricPassphrase = passphrase;
+ }
+
+ /**
+ * Creates new instance of this fragment
+ */
+ public static EncryptTextFragment newInstance(String text) {
+ EncryptTextFragment frag = new EncryptTextFragment();
+
+ Bundle args = new Bundle();
+ args.putString(ARG_TEXT, text);
+ frag.setArguments(args);
+
+ return frag;
+ }
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
- mEncryptInterface = (EncryptActivityInterface) activity;
+ mModeInterface = (IMode) activity;
} catch (ClassCastException e) {
- throw new ClassCastException(activity.toString() + " must implement EncryptActivityInterface");
+ throw new ClassCastException(activity.toString() + " must implement IMode");
}
}
@@ -68,39 +138,58 @@ public class EncryptTextFragment extends Fragment {
@Override
public void afterTextChanged(Editable s) {
- mEncryptInterface.setMessage(s.toString());
+ mMessage = s.toString();
}
});
+ // set initial text
+ if (mMessage != null) {
+ mText.setText(mMessage);
+ }
+
return view;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mMessage = getArguments().getString(ARG_TEXT);
setHasOptionsMenu(true);
}
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- String text = mEncryptInterface.getMessage();
- if (text != null) {
- mText.setText(text);
- }
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ inflater.inflate(R.menu.encrypt_text_fragment, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.isCheckable()) {
+ item.setChecked(!item.isChecked());
+ }
switch (item.getItemId()) {
+ case R.id.check_use_symmetric: {
+ mSymmetricMode = item.isChecked();
+ mModeInterface.onModeChanged(mSymmetricMode);
+ break;
+ }
+ case R.id.check_enable_compression: {
+ mUseCompression = item.isChecked();
+ break;
+ }
+// case R.id.check_hidden_recipients: {
+// mHiddenRecipients = item.isChecked();
+// notifyUpdate();
+// break;
+// }
case R.id.encrypt_copy: {
- mEncryptInterface.startEncrypt(false);
+ startEncrypt(false);
break;
}
case R.id.encrypt_share: {
- mEncryptInterface.startEncrypt(true);
+ startEncrypt(true);
break;
}
default: {
@@ -109,4 +198,189 @@ public class EncryptTextFragment extends Fragment {
}
return true;
}
+
+
+ protected void onEncryptSuccess(SignEncryptResult result) {
+ if (mShareAfterEncrypt) {
+ // Share encrypted message/file
+ startActivity(sendWithChooserExcludingEncrypt(result.getResultBytes()));
+ } else {
+ // Copy to clipboard
+ copyToClipboard(result.getResultBytes());
+ result.createNotify(getActivity()).show();
+ // Notify.create(EncryptTextActivity.this,
+ // R.string.encrypt_sign_clipboard_successful, Notify.Style.OK)
+ // .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_text_fragment));
+ }
+ }
+
+ protected SignEncryptParcel createEncryptBundle() {
+ // fill values for this action
+ SignEncryptParcel data = new SignEncryptParcel();
+
+ data.setBytes(mMessage.getBytes());
+ data.setCleartextSignature(true);
+
+ if (mUseCompression) {
+ data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.get(0));
+ } else {
+ data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED);
+ }
+ data.setHiddenRecipients(mHiddenRecipients);
+ data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
+ data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
+
+ // Always use armor for messages
+ data.setEnableAsciiArmorOutput(true);
+
+ if (mSymmetricMode) {
+ Log.d(Constants.TAG, "Symmetric encryption enabled!");
+ Passphrase passphrase = mSymmetricPassphrase;
+ if (passphrase.isEmpty()) {
+ passphrase = null;
+ }
+ data.setSymmetricPassphrase(passphrase);
+ } else {
+ data.setEncryptionMasterKeyIds(mEncryptionKeyIds);
+ data.setSignatureMasterKeyId(mSigningKeyId);
+ }
+ return data;
+ }
+
+ private void copyToClipboard(byte[] resultBytes) {
+ ClipboardReflection.copyToClipboard(getActivity(), new String(resultBytes));
+ }
+
+ /**
+ * Create Intent Chooser but exclude OK's EncryptActivity.
+ */
+ private Intent sendWithChooserExcludingEncrypt(byte[] resultBytes) {
+ Intent prototype = createSendIntent(resultBytes);
+ String title = getString(R.string.title_share_message);
+
+ // we don't want to encrypt the encrypted, no inception ;)
+ String[] blacklist = new String[]{
+ Constants.PACKAGE_NAME + ".ui.EncryptTextActivity",
+ "org.thialfihar.android.apg.ui.EncryptActivity"
+ };
+
+ return new ShareHelper(getActivity()).createChooserExcluding(prototype, title, blacklist);
+ }
+
+ private Intent createSendIntent(byte[] resultBytes) {
+ Intent sendIntent;
+ sendIntent = new Intent(Intent.ACTION_SEND);
+ sendIntent.setType(Constants.ENCRYPTED_TEXT_MIME);
+ sendIntent.putExtra(Intent.EXTRA_TEXT, new String(resultBytes));
+
+ if (!mSymmetricMode && mEncryptionUserIds != null) {
+ Set<String> users = new HashSet<>();
+ for (String user : mEncryptionUserIds) {
+ KeyRing.UserId userId = KeyRing.splitUserId(user);
+ if (userId.email != null) {
+ users.add(userId.email);
+ }
+ }
+ // pass trough email addresses as extra for email applications
+ sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()]));
+ }
+ return sendIntent;
+ }
+
+ protected boolean inputIsValid() {
+ if (mMessage == null) {
+ Notify.create(getActivity(), R.string.error_message, Notify.Style.ERROR)
+ .show();
+ return false;
+ }
+
+ if (mSymmetricMode) {
+ // symmetric encryption checks
+
+ if (mSymmetricPassphrase == null) {
+ Notify.create(getActivity(), R.string.passphrases_do_not_match, Notify.Style.ERROR)
+ .show();
+ return false;
+ }
+ if (mSymmetricPassphrase.isEmpty()) {
+ Notify.create(getActivity(), R.string.passphrase_must_not_be_empty, Notify.Style.ERROR)
+ .show();
+ return false;
+ }
+
+ } else {
+ // asymmetric encryption checks
+
+ boolean gotEncryptionKeys = (mEncryptionKeyIds != null
+ && mEncryptionKeyIds.length > 0);
+
+ if (!gotEncryptionKeys && mSigningKeyId == 0) {
+ Notify.create(getActivity(), R.string.select_encryption_or_signature_key, Notify.Style.ERROR)
+ .show();
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ public void startEncrypt(boolean share) {
+ mShareAfterEncrypt = share;
+ cryptoOperation();
+ }
+
+ @Override
+ protected void cryptoOperation(CryptoInputParcel cryptoInput) {
+ if (!inputIsValid()) {
+ // Notify was created by inputIsValid.
+ return;
+ }
+
+ // Send all information needed to service to edit key in other thread
+ Intent intent = new Intent(getActivity(), KeychainIntentService.class);
+ intent.setAction(KeychainIntentService.ACTION_SIGN_ENCRYPT);
+
+ final SignEncryptParcel input = createEncryptBundle();
+ final Bundle data = new Bundle();
+ data.putParcelable(KeychainIntentService.SIGN_ENCRYPT_PARCEL, input);
+ data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
+
+ // Message is received after encrypting is done in KeychainIntentService
+ ServiceProgressHandler serviceHandler = new ServiceProgressHandler(
+ getActivity(),
+ getString(R.string.progress_encrypting),
+ ProgressDialog.STYLE_HORIZONTAL,
+ ProgressDialogFragment.ServiceType.KEYCHAIN_INTENT) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ if (handlePendingMessage(message)) {
+ return;
+ }
+
+ if (message.arg1 == MessageStatus.OKAY.ordinal()) {
+ SignEncryptResult result =
+ message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT);
+
+ if (result.success()) {
+ onEncryptSuccess(result);
+ } else {
+ result.createNotify(getActivity()).show();
+ }
+ }
+ }
+ };
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(serviceHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ // show progress dialog
+ serviceHandler.showProgressDialog(getActivity());
+
+ // start service with intent
+ getActivity().startService(intent);
+ }
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java
index 6c3336547..c757c8e88 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java
@@ -26,6 +26,8 @@ import com.astuetz.PagerSlidingTabStrip;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
+
public class HelpActivity extends BaseActivity {
public static final String EXTRA_SELECTED_TAB = "selected_tab";
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
index dc4a2eb10..7fe5be793 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -35,6 +35,7 @@ import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity;
import org.sufficientlysecure.keychain.service.CloudImportService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
@@ -47,7 +48,8 @@ import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize
import java.io.IOException;
import java.util.ArrayList;
-public class ImportKeysActivity extends BaseActivity {
+public class ImportKeysActivity extends BaseNfcActivity {
+
public static final String ACTION_IMPORT_KEY = OpenKeychainIntents.IMPORT_KEY;
public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER = OpenKeychainIntents.IMPORT_KEY_FROM_KEYSERVER;
public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT =
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
index 6a6140892..b9fdbea5c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
@@ -53,9 +53,11 @@ import java.util.List;
public class ImportKeysListFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
+
private static final String ARG_DATA_URI = "uri";
private static final String ARG_BYTES = "bytes";
- private static final String ARG_SERVER_QUERY = "query";
+ public static final String ARG_SERVER_QUERY = "query";
+ public static final String ARG_NON_INTERACTIVE = "non_interactive";
private Activity mActivity;
private ImportKeysAdapter mAdapter;
@@ -66,6 +68,7 @@ public class ImportKeysListFragment extends ListFragment implements
private static final int LOADER_ID_CLOUD = 1;
private LongSparseArray<ParcelableKeyRing> mCachedKeyData;
+ private boolean mNonInteractive;
public LoaderState getLoaderState() {
return mLoaderState;
@@ -118,16 +121,19 @@ public class ImportKeysListFragment extends ListFragment implements
}
- /**
- * Creates new instance of this fragment
- */
public static ImportKeysListFragment newInstance(byte[] bytes, Uri dataUri, String serverQuery) {
+ return newInstance(bytes, dataUri, serverQuery, false);
+ }
+
+ public static ImportKeysListFragment newInstance(byte[] bytes, Uri dataUri,
+ String serverQuery, boolean nonInteractive) {
ImportKeysListFragment frag = new ImportKeysListFragment();
Bundle args = new Bundle();
args.putByteArray(ARG_BYTES, bytes);
args.putParcelable(ARG_DATA_URI, dataUri);
args.putString(ARG_SERVER_QUERY, serverQuery);
+ args.putBoolean(ARG_NON_INTERACTIVE, nonInteractive);
frag.setArguments(args);
@@ -173,9 +179,11 @@ public class ImportKeysListFragment extends ListFragment implements
mAdapter = new ImportKeysAdapter(mActivity);
setListAdapter(mAdapter);
- Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
- byte[] bytes = getArguments().getByteArray(ARG_BYTES);
- String query = getArguments().getString(ARG_SERVER_QUERY);
+ Bundle args = getArguments();
+ Uri dataUri = args.containsKey(ARG_DATA_URI) ? args.<Uri>getParcelable(ARG_DATA_URI) : null;
+ byte[] bytes = args.containsKey(ARG_BYTES) ? args.getByteArray(ARG_BYTES) : null;
+ String query = args.containsKey(ARG_SERVER_QUERY) ? args.getString(ARG_SERVER_QUERY) : null;
+ mNonInteractive = args.containsKey(ARG_NON_INTERACTIVE) ? args.getBoolean(ARG_NON_INTERACTIVE) : false;
if (dataUri != null || bytes != null) {
mLoaderState = new BytesLoaderState(bytes, dataUri);
@@ -203,6 +211,10 @@ public class ImportKeysListFragment extends ListFragment implements
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
+ if (mNonInteractive) {
+ return;
+ }
+
// Select checkbox!
// Update underlying data and notify adapter of change. The adapter will
// update the view automatically.
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
index 21747f77b..b9f1bf870 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui;
import android.annotation.TargetApi;
import android.app.ProgressDialog;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NfcAdapter;
@@ -83,25 +84,22 @@ public class ImportKeysProxyActivity extends FragmentActivity {
returnResult = false;
processScannedContent(dataUri);
- } else if (ACTION_SCAN_IMPORT.equals(action)) {
+ } else if (ACTION_SCAN_IMPORT.equals(action) || ACTION_QR_CODE_API.equals(action)) {
returnResult = false;
IntentIntegrator integrator = new IntentIntegrator(this);
integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES)
.setPrompt(getString(R.string.import_qr_code_text))
- .setResultDisplayDuration(0)
- .initiateScan();
+ .setResultDisplayDuration(0);
+ integrator.setOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ integrator.initiateScan();
} else if (ACTION_SCAN_WITH_RESULT.equals(action)) {
returnResult = true;
IntentIntegrator integrator = new IntentIntegrator(this);
integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES)
.setPrompt(getString(R.string.import_qr_code_text))
- .setResultDisplayDuration(0)
- .initiateScan();
- } else if (ACTION_QR_CODE_API.equals(action)) {
- // scan using xzing's Barcode Scanner from outside OpenKeychain
-
- returnResult = false;
- new IntentIntegrator(this).initiateScan();
+ .setResultDisplayDuration(0);
+ integrator.setOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ integrator.initiateScan();
} else if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
// Check to see if the Activity started due to an Android Beam
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java
index 0de7bb391..df325d31d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java
@@ -22,6 +22,8 @@ import android.os.Bundle;
import android.view.View;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
+
public class LogDisplayActivity extends BaseActivity {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java
deleted file mode 100644
index 0ccb206d1..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/**
- * Copyright (c) 2013-2014 Philipp Jakubeit, Signe Rüsch, Dominik Schürmann
- *
- * Licensed under the Bouncy Castle License (MIT license). See LICENSE file for details.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.annotation.TargetApi;
-import android.app.PendingIntent;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.nfc.NfcAdapter;
-import android.nfc.Tag;
-import android.nfc.tech.IsoDep;
-import android.os.Build;
-import android.os.Bundle;
-import android.view.WindowManager;
-import android.widget.Toast;
-
-import org.spongycastle.util.encoders.Hex;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-import org.sufficientlysecure.keychain.util.Iso7816TLV;
-import org.sufficientlysecure.keychain.util.Log;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-/**
- * This class provides a communication interface to OpenPGP applications on ISO SmartCard compliant
- * NFC devices.
- *
- * For the full specs, see http://g10code.com/docs/openpgp-card-2.0.pdf
- */
-@TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)
-public class NfcIntentActivity extends BaseActivity {
-
- // special extra for OpenPgpService
- public static final String EXTRA_DATA = "data";
-
- private Intent mServiceIntent;
-
- private static final int TIMEOUT = 100000;
-
- private NfcAdapter mNfcAdapter;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Log.d(Constants.TAG, "NfcActivity.onCreate");
-
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-
- Intent intent = getIntent();
- Bundle data = intent.getExtras();
- String action = intent.getAction();
-
- Log.d(Constants.TAG, action);
- Log.d(Constants.TAG, intent.getDataString());
-
- // TODO check fingerprint
- // mFingerprint = data.getByteArray(EXTRA_FINGERPRINT);
-
- if (!NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
- Log.d(Constants.TAG, "Action not supported: " + action);
- finish();
- }
-
- try {
- Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
-
- // Connect to the detected tag, setting a couple of settings
- IsoDep isoDep = IsoDep.get(detectedTag);
- isoDep.setTimeout(TIMEOUT); // timeout is set to 100 seconds to avoid cancellation during calculation
- isoDep.connect();
-
- nfcGreet(isoDep);
- // nfcPin(isoDep, "yoloswag");
- nfcGetFingerprint(isoDep);
-
- } catch (IOException e) {
- Log.e(Constants.TAG, "IOException!", e);
- finish();
- }
- }
-
- @Override
- protected void initLayout() {
- setContentView(R.layout.nfc_activity);
- }
-
- /**
- * Called when the system is about to start resuming a previous activity,
- * disables NFC Foreground Dispatch
- */
- public void onPause() {
- super.onPause();
- Log.d(Constants.TAG, "NfcActivity.onPause");
-
- // disableNfcForegroundDispatch();
- }
-
- /**
- * Called when the activity will start interacting with the user,
- * enables NFC Foreground Dispatch
- */
- public void onResume() {
- super.onResume();
- Log.d(Constants.TAG, "NfcActivity.onResume");
-
- // enableNfcForegroundDispatch();
- }
-
- /** Handle NFC communication and return a result.
- *
- * This method is called by onNewIntent above upon discovery of an NFC tag.
- * It handles initialization and login to the application, subsequently
- * calls either nfcCalculateSignature() or nfcDecryptSessionKey(), then
- * finishes the activity with an appropiate result.
- *
- * On general communication, see also
- * http://www.cardwerk.com/smartcards/smartcard_standard_ISO7816-4_annex-a.aspx
- *
- * References to pages are generally related to the OpenPGP Application
- * on ISO SmartCard Systems specification.
- *
- */
- private void nfcGreet(IsoDep isoDep) throws IOException {
-
- // SW1/2 0x9000 is the generic "ok" response, which we expect most of the time.
- // See specification, page 51
- String accepted = "9000";
-
- // Command APDU (page 51) for SELECT FILE command (page 29)
- String opening =
- "00" // CLA
- + "A4" // INS
- + "04" // P1
- + "00" // P2
- + "06" // Lc (number of bytes)
- + "D27600012401" // Data (6 bytes)
- + "00"; // Le
- if (!card(isoDep, opening).equals(accepted)) { // activate connection
- toast("Opening Error!");
- setResult(RESULT_CANCELED, mServiceIntent);
- finish();
- }
- }
-
- private void nfcPin(IsoDep isoDep, String pin) throws IOException {
-
- String data = "00CA006E00";
- String fingerprint = card(isoDep, data);
-
- // Command APDU for VERIFY command (page 32)
- String login =
- "00" // CLA
- + "20" // INS
- + "00" // P1
- + "82" // P2 (PW1)
- + String.format("%02x", pin.length()) // Lc
- + Hex.toHexString(pin.getBytes());
- if ( ! card(isoDep, login).equals("9000")) { // login
- toast("Pin Error!");
- setResult(RESULT_CANCELED, mServiceIntent);
- finish();
- }
-
- }
-
- /**
- * Gets the user ID
- *
- * @return the user id as "name <email>"
- * @throws java.io.IOException
- */
- public static String getUserId(IsoDep isoDep) throws IOException {
- String info = "00CA006500";
- String data = "00CA005E00";
- return getName(card(isoDep, info)) + " <" + (new String(Hex.decode(getDataField(card(isoDep, data))))) + ">";
- }
-
- /**
- * Gets the long key ID
- *
- * @return the long key id (last 16 bytes of the fingerprint)
- * @throws java.io.IOException
- */
- public static long getKeyId(IsoDep isoDep) throws IOException {
- String keyId = nfcGetFingerprint(isoDep).substring(24);
- Log.d(Constants.TAG, "keyId: " + keyId);
- return Long.parseLong(keyId, 16);
- }
-
- /**
- * Gets the fingerprint of the signature key
- *
- * @return the fingerprint
- * @throws java.io.IOException
- */
- public static String nfcGetFingerprint(IsoDep isoDep) throws IOException {
- String data = "00CA006E00";
- byte[] buf = isoDep.transceive(Hex.decode(data));
-
- Iso7816TLV tlv = Iso7816TLV.readSingle(buf, true);
- Log.d(Constants.TAG, "nfc tlv data:\n" + tlv.prettyPrint());
-
- Iso7816TLV fptlv = Iso7816TLV.findRecursive(tlv, 0xc5);
- if (fptlv != null) {
- ByteBuffer fpbuf = ByteBuffer.wrap(fptlv.mV);
- byte[] fp = new byte[20];
- fpbuf.get(fp);
- Log.d(Constants.TAG, "fingerprint 1: " + KeyFormattingUtils.convertFingerprintToHex(fp));
- fpbuf.get(fp);
- Log.d(Constants.TAG, "fingerprint 2: " + KeyFormattingUtils.convertFingerprintToHex(fp));
- fpbuf.get(fp);
- Log.d(Constants.TAG, "fingerprint 3: " + KeyFormattingUtils.convertFingerprintToHex(fp));
- }
-
- return "nope";
- }
-
- /**
- * Prints a message to the screen
- *
- * @param text the text which should be contained within the toast
- */
- private void toast(String text) {
- Toast.makeText(this, text, Toast.LENGTH_LONG).show();
- }
-
- /**
- * Receive new NFC Intents to this activity only by enabling foreground dispatch.
- * This can only be done in onResume!
- */
- public void enableNfcForegroundDispatch() {
- mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
- Intent nfcI = new Intent(this, NfcIntentActivity.class)
- .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- PendingIntent nfcPendingIntent = PendingIntent.getActivity(this, 0, nfcI, 0);
- IntentFilter[] writeTagFilters = new IntentFilter[]{
- new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
- };
-
- // https://code.google.com/p/android/issues/detail?id=62918
- // maybe mNfcAdapter.enableReaderMode(); ?
- try {
- mNfcAdapter.enableForegroundDispatch(this, nfcPendingIntent, writeTagFilters, null);
- } catch (IllegalStateException e) {
- Log.i(Constants.TAG, "NfcForegroundDispatch Error!", e);
- }
- Log.d(Constants.TAG, "NfcForegroundDispatch has been enabled!");
- }
-
- /**
- * Disable foreground dispatch in onPause!
- */
- public void disableNfcForegroundDispatch() {
- mNfcAdapter.disableForegroundDispatch(this);
- Log.d(Constants.TAG, "NfcForegroundDispatch has been disabled!");
- }
-
- /**
- * Gets the name of the user out of the raw card output regarding card holder related data
- *
- * @param name the raw card holder related data from the card
- * @return the name given in this data
- */
- public static String getName(String name) {
- String slength;
- int ilength;
- name = name.substring(6);
- slength = name.substring(0, 2);
- ilength = Integer.parseInt(slength, 16) * 2;
- name = name.substring(2, ilength + 2);
- name = (new String(Hex.decode(name))).replace('<', ' ');
- return (name);
- }
-
- /**
- * Reduces the raw data from the card by four characters
- *
- * @param output the raw data from the card
- * @return the data field of that data
- */
- private static String getDataField(String output) {
- return output.substring(0, output.length() - 4);
- }
-
- /**
- * Communicates with the OpenPgpCard via the APDU
- *
- * @param hex the hexadecimal APDU
- * @return The answer from the card
- * @throws java.io.IOException throws an exception if something goes wrong
- */
- public static String card(IsoDep isoDep, String hex) throws IOException {
- return getHex(isoDep.transceive(Hex.decode(hex)));
- }
-
- /**
- * Converts a byte array into an hex string
- *
- * @param raw the byte array representation
- * @return the hexadecimal string representation
- */
- public static String getHex(byte[] raw) {
- return new String(Hex.encode(raw));
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
new file mode 100644
index 000000000..aa66053fa
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
@@ -0,0 +1,121 @@
+/**
+ * Copyright (c) 2013-2014 Philipp Jakubeit, Signe Rüsch, Dominik Schürmann
+ *
+ * Licensed under the Bouncy Castle License (MIT license). See LICENSE file for details.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.remote.CryptoInputParcelCacheService;
+import org.sufficientlysecure.keychain.service.PassphraseCacheService;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
+import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
+
+import java.io.IOException;
+
+/**
+ * This class provides a communication interface to OpenPGP applications on ISO SmartCard compliant
+ * NFC devices.
+ * <p/>
+ * For the full specs, see http://g10code.com/docs/openpgp-card-2.0.pdf
+ */
+public class NfcOperationActivity extends BaseNfcActivity {
+
+ public static final String EXTRA_REQUIRED_INPUT = "required_input";
+
+ // passthrough for OpenPgpService
+ public static final String EXTRA_SERVICE_INTENT = "data";
+
+ public static final String RESULT_DATA = "result_data";
+
+ private RequiredInputParcel mRequiredInput;
+ private Intent mServiceIntent;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.d(Constants.TAG, "NfcOperationActivity.onCreate");
+
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ Intent intent = getIntent();
+ Bundle data = intent.getExtras();
+
+ mRequiredInput = data.getParcelable(EXTRA_REQUIRED_INPUT);
+ mServiceIntent = data.getParcelable(EXTRA_SERVICE_INTENT);
+
+ // obtain passphrase for this subkey
+ obtainYubiKeyPin(RequiredInputParcel.createRequiredPassphrase(mRequiredInput));
+ }
+
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.nfc_activity);
+ }
+
+ @Override
+ protected void onNfcPerform() throws IOException {
+
+ CryptoInputParcel inputParcel = new CryptoInputParcel(mRequiredInput.mSignatureTime);
+
+ switch (mRequiredInput.mType) {
+ case NFC_DECRYPT: {
+ for (int i = 0; i < mRequiredInput.mInputHashes.length; i++) {
+ byte[] hash = mRequiredInput.mInputHashes[i];
+ byte[] decryptedSessionKey = nfcDecryptSessionKey(hash);
+ inputParcel.addCryptoData(hash, decryptedSessionKey);
+ }
+ break;
+ }
+ case NFC_SIGN: {
+ for (int i = 0; i < mRequiredInput.mInputHashes.length; i++) {
+ byte[] hash = mRequiredInput.mInputHashes[i];
+ int algo = mRequiredInput.mSignAlgos[i];
+ byte[] signedHash = nfcCalculateSignature(hash, algo);
+ inputParcel.addCryptoData(hash, signedHash);
+ }
+ break;
+ }
+ }
+
+ if (mServiceIntent != null) {
+ CryptoInputParcelCacheService.addCryptoInputParcel(this, mServiceIntent, inputParcel);
+ setResult(RESULT_OK, mServiceIntent);
+ } else {
+ Intent result = new Intent();
+ result.putExtra(NfcOperationActivity.RESULT_DATA, inputParcel);
+ setResult(RESULT_OK, result);
+ }
+
+ finish();
+ }
+
+ @Override
+ public void handlePinError() {
+
+ // avoid a loop
+ Preferences prefs = Preferences.getPreferences(this);
+ if (prefs.useDefaultYubiKeyPin()) {
+ toast(getString(R.string.error_pin_nodefault));
+ setResult(RESULT_CANCELED);
+ finish();
+ return;
+ }
+
+ // clear (invalid) passphrase
+ PassphraseCacheService.clearCachedPassphrase(
+ this, mRequiredInput.getMasterKeyId(), mRequiredInput.getSubKeyId());
+
+ obtainYubiKeyPin(RequiredInputParcel.createRequiredPassphrase(mRequiredInput));
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
index b77637696..c6431bfaf 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
@@ -52,7 +52,10 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.remote.CryptoInputParcelCacheService;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase;
@@ -63,13 +66,14 @@ import org.sufficientlysecure.keychain.util.Preferences;
* This activity encapsulates a DialogFragment to emulate a dialog.
*/
public class PassphraseDialogActivity extends FragmentActivity {
- public static final String MESSAGE_DATA_PASSPHRASE = "passphrase";
- public static final String EXTRA_KEY_ID = "key_id";
+ public static final String RESULT_CRYPTO_INPUT = "result_data";
+
+ public static final String EXTRA_REQUIRED_INPUT = "required_input";
public static final String EXTRA_SUBKEY_ID = "secret_key_id";
// special extra for OpenPgpService
- public static final String EXTRA_DATA = "data";
+ public static final String EXTRA_SERVICE_INTENT = "data";
private static final int REQUEST_CODE_ENTER_PATTERN = 2;
@@ -88,9 +92,27 @@ public class PassphraseDialogActivity extends FragmentActivity {
// this activity itself has no content view (see manifest)
- long keyId = getIntent().getLongExtra(EXTRA_SUBKEY_ID, 0);
+ long keyId;
+ if (getIntent().hasExtra(EXTRA_SUBKEY_ID)) {
+ keyId = getIntent().getLongExtra(EXTRA_SUBKEY_ID, 0);
+ } else {
+ RequiredInputParcel requiredInput = getIntent().getParcelableExtra(EXTRA_REQUIRED_INPUT);
+ switch (requiredInput.mType) {
+ case PASSPHRASE_SYMMETRIC: {
+ keyId = Constants.key.symmetric;
+ break;
+ }
+ case PASSPHRASE: {
+ keyId = requiredInput.getSubKeyId();
+ break;
+ }
+ default: {
+ throw new AssertionError("Unsupported required input type for PassphraseDialogActivity!");
+ }
+ }
+ }
- Intent serviceIntent = getIntent().getParcelableExtra(EXTRA_DATA);
+ Intent serviceIntent = getIntent().getParcelableExtra(EXTRA_SERVICE_INTENT);
show(this, keyId, serviceIntent);
}
@@ -141,7 +163,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
PassphraseDialogFragment frag = new PassphraseDialogFragment();
Bundle args = new Bundle();
args.putLong(EXTRA_SUBKEY_ID, keyId);
- args.putParcelable(EXTRA_DATA, serviceIntent);
+ args.putParcelable(EXTRA_SERVICE_INTENT, serviceIntent);
frag.setArguments(args);
@@ -174,11 +196,12 @@ public class PassphraseDialogActivity extends FragmentActivity {
R.style.Theme_AppCompat_Light_Dialog);
mSubKeyId = getArguments().getLong(EXTRA_SUBKEY_ID);
- mServiceIntent = getArguments().getParcelable(EXTRA_DATA);
+ mServiceIntent = getArguments().getParcelable(EXTRA_SERVICE_INTENT);
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(theme);
- alert.setTitle(R.string.title_unlock);
+ // No title, see http://www.google.com/design/spec/components/dialogs.html#dialogs-alerts
+ //alert.setTitle()
LayoutInflater inflater = LayoutInflater.from(theme);
View view = inflater.inflate(R.layout.passphrase_dialog, null);
@@ -243,8 +266,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
case PASSPHRASE_EMPTY:
finishCaching(new Passphrase(""));
default:
- message = "This should not happen!";
- break;
+ throw new AssertionError("Unhandled SecretKeyType (should not happen)");
}
} catch (ProviderHelper.NotFoundException e) {
@@ -296,7 +318,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
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()) {
+ if (keyType == CanonicalizedSecretKey.SecretKeyType.DIVERT_TO_CARD && Preferences.getPreferences(activity).useNumKeypadForYubiKeyPin()) {
mPassphraseEditText.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_TEXT_VARIATION_PASSWORD);
} else if (keyType == CanonicalizedSecretKey.SecretKeyType.PIN) {
mPassphraseEditText.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_TEXT_VARIATION_PASSWORD);
@@ -309,7 +331,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
AlertDialog dialog = alert.create();
dialog.setButton(DialogInterface.BUTTON_POSITIVE,
- activity.getString(android.R.string.ok), (DialogInterface.OnClickListener) null);
+ activity.getString(R.string.btn_unlock), (DialogInterface.OnClickListener) null);
return dialog;
}
@@ -406,17 +428,14 @@ public class PassphraseDialogActivity extends FragmentActivity {
return;
}
+ CryptoInputParcel inputParcel = new CryptoInputParcel(null, passphrase);
if (mServiceIntent != null) {
- // TODO: Not routing passphrase through OpenPGP API currently
- // due to security concerns...
- // BUT this means you need to _cache_ passphrases!
+ CryptoInputParcelCacheService.addCryptoInputParcel(getActivity(), mServiceIntent, inputParcel);
getActivity().setResult(RESULT_OK, mServiceIntent);
} else {
// also return passphrase back to activity
Intent returnIntent = new Intent();
- returnIntent.putExtra(MESSAGE_DATA_PASSPHRASE, passphrase);
- returnIntent.putExtra(EXTRA_KEY_ID, mSecretRing.getMasterKeyId());
- returnIntent.putExtra(EXTRA_SUBKEY_ID, mSubKeyId);
+ returnIntent.putExtra(RESULT_CRYPTO_INPUT, inputParcel);
getActivity().setResult(RESULT_OK, returnIntent);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java
index 43af07bbe..d4858ee5d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java
@@ -30,6 +30,7 @@ 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.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java
index c58a945d3..aa3c36d11 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java
@@ -39,6 +39,7 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
index 210960b65..442bdf8f7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
@@ -107,10 +107,10 @@ public class SettingsActivity extends PreferenceActivity {
values[i] = "" + valueIds[i];
}
- initializeUseDefaultYubikeyPin(
+ initializeUseDefaultYubiKeyPin(
(CheckBoxPreference) findPreference(Constants.Pref.USE_DEFAULT_YUBIKEY_PIN));
- initializeUseNumKeypadForYubikeyPin(
+ initializeUseNumKeypadForYubiKeyPin(
(CheckBoxPreference) findPreference(Constants.Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN));
}
@@ -262,10 +262,10 @@ public class SettingsActivity extends PreferenceActivity {
values[i] = "" + valueIds[i];
}
- initializeUseDefaultYubikeyPin(
+ initializeUseDefaultYubiKeyPin(
(CheckBoxPreference) findPreference(Constants.Pref.USE_DEFAULT_YUBIKEY_PIN));
- initializeUseNumKeypadForYubikeyPin(
+ initializeUseNumKeypadForYubiKeyPin(
(CheckBoxPreference) findPreference(Constants.Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN));
}
}
@@ -335,23 +335,23 @@ public class SettingsActivity extends PreferenceActivity {
return serverSummary + "; " + context.getString(R.string.label_preferred) + ": " + sPreferences.getPreferredKeyserver();
}
- private static void initializeUseDefaultYubikeyPin(final CheckBoxPreference mUseDefaultYubikeyPin) {
- mUseDefaultYubikeyPin.setChecked(sPreferences.useDefaultYubikeyPin());
- mUseDefaultYubikeyPin.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ private static void initializeUseDefaultYubiKeyPin(final CheckBoxPreference mUseDefaultYubiKeyPin) {
+ mUseDefaultYubiKeyPin.setChecked(sPreferences.useDefaultYubiKeyPin());
+ mUseDefaultYubiKeyPin.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
- mUseDefaultYubikeyPin.setChecked((Boolean) newValue);
- sPreferences.setUseDefaultYubikeyPin((Boolean) newValue);
+ mUseDefaultYubiKeyPin.setChecked((Boolean) newValue);
+ sPreferences.setUseDefaultYubiKeyPin((Boolean) newValue);
return false;
}
});
}
- private static void initializeUseNumKeypadForYubikeyPin(final CheckBoxPreference mUseNumKeypadForYubikeyPin) {
- mUseNumKeypadForYubikeyPin.setChecked(sPreferences.useNumKeypadForYubikeyPin());
- mUseNumKeypadForYubikeyPin.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ private static void initializeUseNumKeypadForYubiKeyPin(final CheckBoxPreference mUseNumKeypadForYubiKeyPin) {
+ mUseNumKeypadForYubiKeyPin.setChecked(sPreferences.useNumKeypadForYubiKeyPin());
+ mUseNumKeypadForYubiKeyPin.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
- mUseNumKeypadForYubikeyPin.setChecked((Boolean) newValue);
- sPreferences.setUseNumKeypadForYubikeyPin((Boolean) newValue);
+ mUseNumKeypadForYubiKeyPin.setChecked((Boolean) newValue);
+ sPreferences.setUseNumKeypadForYubiKeyPin((Boolean) newValue);
return false;
}
});
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java
index 080dc2495..9f2e46b38 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java
@@ -27,6 +27,7 @@ import android.view.ViewGroup;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.widget.Editor;
import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
import org.sufficientlysecure.keychain.ui.widget.KeyServerEditor;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java
index c518cbcdb..5c8e6bb5d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java
@@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java
index a80503591..8d876ba69 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java
@@ -40,6 +40,7 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index ad35d2833..4ec3c28da 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -61,18 +61,23 @@ import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
+import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.ui.linked.LinkedIdWizard;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler.MessageStatus;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
+import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity;
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.ui.util.Notify.ActionListener;
+import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.ExportHelper;
@@ -80,15 +85,21 @@ import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.NfcHelper;
import org.sufficientlysecure.keychain.util.Preferences;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
-public class ViewKeyActivity extends BaseActivity implements
+public class ViewKeyActivity extends BaseNfcActivity implements
LoaderManager.LoaderCallbacks<Cursor> {
+ public static final String EXTRA_NFC_USER_ID = "nfc_user_id";
+ public static final String EXTRA_NFC_AID = "nfc_aid";
+ public static final String EXTRA_NFC_FINGERPRINTS = "nfc_fingerprints";
+
static final int REQUEST_QR_FINGERPRINT = 1;
static final int REQUEST_DELETE = 2;
static final int REQUEST_EXPORT = 3;
+ public static final String EXTRA_DISPLAY_RESULT = "display_result";
ExportHelper mExportHelper;
ProviderHelper mProviderHelper;
@@ -108,6 +119,8 @@ public class ViewKeyActivity extends BaseActivity implements
private ImageView mQrCode;
private CardView mQrCodeLayout;
+ private String mQrCodeLoaded;
+
// NFC
private NfcHelper mNfcHelper;
@@ -257,6 +270,21 @@ public class ViewKeyActivity extends BaseActivity implements
mNfcHelper = new NfcHelper(this, mProviderHelper);
mNfcHelper.initNfc(mDataUri);
+ if (savedInstanceState == null && getIntent().hasExtra(EXTRA_DISPLAY_RESULT)) {
+ OperationResult result = getIntent().getParcelableExtra(EXTRA_DISPLAY_RESULT);
+ result.createNotify(this).show();
+ }
+
+ startFragment(savedInstanceState, mDataUri);
+
+ if (savedInstanceState == null && getIntent().hasExtra(EXTRA_NFC_AID)) {
+ Intent intent = getIntent();
+ byte[] nfcFingerprints = intent.getByteArrayExtra(EXTRA_NFC_FINGERPRINTS);
+ String nfcUserId = intent.getStringExtra(EXTRA_NFC_USER_ID);
+ byte[] nfcAid = intent.getByteArrayExtra(EXTRA_NFC_AID);
+ showYubiKeyFragment(nfcFingerprints, nfcUserId, nfcAid);
+ }
+
}
@Override
@@ -264,6 +292,35 @@ public class ViewKeyActivity extends BaseActivity implements
setContentView(R.layout.view_key_activity);
}
+ private void startFragment(Bundle savedInstanceState, final Uri dataUri) {
+ // If we're being restored from a previous state, then we don't
+ // need to do anything and should return or else we could end
+ // up with overlapping fragments.
+ if (savedInstanceState != null) {
+ return;
+ }
+
+ new Handler().post(new Runnable() {
+ @Override
+ public void run() {
+
+ FragmentManager manager = getSupportFragmentManager();
+ if (manager.getBackStackEntryCount() == 0) {
+ // Create an instance of the fragment
+ final ViewKeyFragment frag = ViewKeyFragment.newInstance(dataUri);
+ manager.beginTransaction()
+ .replace(R.id.view_key_fragment, frag)
+ .commit();
+ manager.popBackStack();
+ } else {
+ // not sure yet if we actually want this!
+ // manager.popBackStack();
+ }
+
+ }
+ });
+ }
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
@@ -507,6 +564,72 @@ public class ViewKeyActivity extends BaseActivity implements
}
}
+ @Override
+ protected void onNfcPerform() throws IOException {
+
+ final byte[] nfcFingerprints = nfcGetFingerprints();
+ final String nfcUserId = nfcGetUserId();
+ final byte[] nfcAid = nfcGetAid();
+
+ String fp = KeyFormattingUtils.convertFingerprintToHex(nfcFingerprints);
+ final long masterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(nfcFingerprints);
+
+ if (!mFingerprint.equals(fp)) {
+ try {
+ CachedPublicKeyRing ring = mProviderHelper.getCachedPublicKeyRing(masterKeyId);
+ ring.getMasterKeyId();
+
+ Notify.create(this, R.string.snack_yubi_other, Notify.LENGTH_LONG,
+ Style.WARN, new ActionListener() {
+ @Override
+ public void onAction() {
+ Intent intent = new Intent(
+ ViewKeyActivity.this, ViewKeyActivity.class);
+ intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId));
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, nfcAid);
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_USER_ID, nfcUserId);
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_FINGERPRINTS, nfcFingerprints);
+ startActivity(intent);
+ finish();
+ }
+ }, R.string.snack_yubikey_view).show();
+ return;
+
+ } catch (PgpKeyNotFoundException e) {
+ Notify.create(this, R.string.snack_yubi_other, Notify.LENGTH_LONG,
+ Style.WARN, new ActionListener() {
+ @Override
+ public void onAction() {
+ Intent intent = new Intent(
+ ViewKeyActivity.this, CreateKeyActivity.class);
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, nfcAid);
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_USER_ID, nfcUserId);
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_FINGERPRINTS, nfcFingerprints);
+ startActivity(intent);
+ finish();
+ }
+ }, R.string.snack_yubikey_import).show();
+ return;
+ }
+ }
+
+ showYubiKeyFragment(nfcFingerprints, nfcUserId, nfcAid);
+
+ }
+
+ public void showYubiKeyFragment(byte[] nfcFingerprints, String nfcUserId, byte[] nfcAid) {
+ ViewKeyYubiKeyFragment frag = ViewKeyYubiKeyFragment.newInstance(
+ nfcFingerprints, nfcUserId, nfcAid);
+
+ FragmentManager manager = getSupportFragmentManager();
+
+ manager.popBackStack("yubikey", FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ manager.beginTransaction()
+ .addToBackStack("yubikey")
+ .replace(R.id.view_key_fragment, frag)
+ .commit();
+ }
+
private void encrypt(Uri dataUri, boolean text) {
// If there is no encryption key, don't bother.
if (!mHasEncrypt) {
@@ -638,6 +761,7 @@ public class ViewKeyActivity extends BaseActivity implements
}
protected void onPostExecute(Bitmap qrCode) {
+ mQrCodeLoaded = fingerprint;
// scale the image up to our actual size. we do this in code rather
// than let the ImageView do this because we don't require filtering.
Bitmap scaled = Bitmap.createScaledBitmap(qrCode,
@@ -705,25 +829,13 @@ public class ViewKeyActivity extends BaseActivity implements
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
switch (loader.getId()) {
+
case LOADER_ID_UNIFIED: {
- // if there is no data, just break
+
if (!data.moveToFirst()) {
- break;
+ return;
}
- String oldFingerprint = mFingerprint;
- mMasterKeyId = data.getLong(INDEX_MASTER_KEY_ID);
- byte[] fpData = data.getBlob(INDEX_FINGERPRINT);
- mFingerprint = KeyFormattingUtils.convertFingerprintToHex(fpData);
-
- mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
- mHasEncrypt = data.getInt(INDEX_HAS_ENCRYPT) != 0;
- mIsRevoked = data.getInt(INDEX_IS_REVOKED) > 0;
- mIsExpired = data.getInt(INDEX_IS_EXPIRED) != 0;
- mIsVerified = data.getInt(INDEX_VERIFIED) > 0;
-
- startFragment(mIsSecret, fpData);
-
// get name, email, and comment from USER_ID
KeyRing.UserId mainUserId = KeyRing.splitUserId(data.getString(INDEX_USER_ID));
if (mainUserId.name != null) {
@@ -732,6 +844,15 @@ public class ViewKeyActivity extends BaseActivity implements
mName.setText(R.string.user_id_no_name);
}
+ mMasterKeyId = data.getLong(INDEX_MASTER_KEY_ID);
+ mFingerprint = KeyFormattingUtils.convertFingerprintToHex(data.getBlob(INDEX_FINGERPRINT));
+
+ mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
+ mHasEncrypt = data.getInt(INDEX_HAS_ENCRYPT) != 0;
+ mIsRevoked = data.getInt(INDEX_IS_REVOKED) > 0;
+ mIsExpired = data.getInt(INDEX_IS_EXPIRED) != 0;
+ mIsVerified = data.getInt(INDEX_VERIFIED) > 0;
+
// if the refresh animation isn't playing
if (!mRotate.hasStarted() && !mRotateSpin.hasStarted()) {
// re-create options menu based on mIsSecret, mIsVerified
@@ -768,7 +889,6 @@ public class ViewKeyActivity extends BaseActivity implements
} else if (mIsExpired) {
if (mIsSecret) {
mStatusText.setText(R.string.view_key_expired_secret);
- mName.setText(mainUserId.name);
} else {
mStatusText.setText(R.string.view_key_expired);
}
@@ -787,7 +907,7 @@ public class ViewKeyActivity extends BaseActivity implements
mStatusImage.setVisibility(View.GONE);
color = getResources().getColor(R.color.primary);
// reload qr code only if the fingerprint changed
- if (!mFingerprint.equals(oldFingerprint)) {
+ if (!mFingerprint.equals(mQrCodeLoaded)) {
loadQrCode(mFingerprint);
}
photoTask.execute(mMasterKeyId);
@@ -873,6 +993,7 @@ public class ViewKeyActivity extends BaseActivity implements
mStatusImage.setAlpha(80);
break;
+
}
}
}
@@ -882,27 +1003,4 @@ public class ViewKeyActivity extends BaseActivity implements
}
- private void startFragment(final boolean isSecret, final byte[] fingerprint) {
- new Handler().post(new Runnable() {
- @Override
- public void run() {
-
- FragmentManager manager = getSupportFragmentManager();
- if (manager.getBackStackEntryCount() == 0) {
- // Create an instance of the fragment
- final ViewKeyFragment frag = ViewKeyFragment.newInstance(
- mDataUri, isSecret, fingerprint);
- manager.beginTransaction()
- .replace(R.id.view_key_fragment, frag)
- .commit();
- manager.popBackStack();
- } else {
- // not sure yet if we actually want this!
- // manager.popBackStack();
- }
-
- }
- });
- }
-
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
index f17d6e0fd..9e8a12c8a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
@@ -38,6 +38,7 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.ExportHelper;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
index 8610b2fee..046de6c0c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
@@ -30,6 +30,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.provider.ContactsContract;
import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.widget.CardView;
import android.transition.Fade;
@@ -48,11 +49,11 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment;
import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment.OnIdentityLoadedListener;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.Log;
@@ -62,21 +63,26 @@ public class ViewKeyFragment extends LoaderFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
public static final String ARG_DATA_URI = "uri";
- private static final String ARG_FINGERPRINT = "fingerprint";
- private static final String ARG_IS_SECRET = "is_secret";
private ListView mUserIds;
//private ListView mLinkedSystemContact;
boolean mIsSecret = false;
- boolean mSystemContactLoaded = false;
+ CardView mSystemContactCard;
LinearLayout mSystemContactLayout;
ImageView mSystemContactPicture;
TextView mSystemContactName;
- private static final int LOADER_ID_USER_IDS = 0;
- private static final int LOADER_ID_LINKED_IDS = 1;
+ private static final int LOADER_ID_UNIFIED = 0;
+ private static final int LOADER_ID_USER_IDS = 1;
+ private static final int LOADER_ID_LINKED_CONTACT = 2;
+ private static final int LOADER_ID_LINKED_IDS = 3;
+
+ private static final String LOADER_EXTRA_LINKED_CONTACT_MASTER_KEY_ID
+ = "loader_linked_contact_master_key_id";
+ private static final String LOADER_EXTRA_LINKED_CONTACT_IS_SECRET
+ = "loader_linked_contact_is_secret";
private UserIdsAdapter mUserIdsAdapter;
private LinkedIdsAdapter mLinkedIdsAdapter;
@@ -90,12 +96,10 @@ public class ViewKeyFragment extends LoaderFragment implements
/**
* Creates new instance of this fragment
*/
- public static ViewKeyFragment newInstance(Uri dataUri, boolean isSecret, byte[] fingerprint) {
+ public static ViewKeyFragment newInstance(Uri dataUri) {
ViewKeyFragment frag = new ViewKeyFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_DATA_URI, dataUri);
- args.putBoolean(ARG_IS_SECRET, isSecret);
- args.putByteArray(ARG_FINGERPRINT, fingerprint);
frag.setArguments(args);
@@ -103,23 +107,6 @@ public class ViewKeyFragment extends LoaderFragment implements
}
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- Bundle args = getArguments();
- Uri dataUri = args.getParcelable(ARG_DATA_URI);
- if (dataUri == null) {
- Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
- getActivity().finish();
- return;
- }
- boolean isSecret = args.getBoolean(ARG_IS_SECRET);
- byte[] fingerprint = args.getByteArray(ARG_FINGERPRINT);
-
- loadData(dataUri, isSecret, fingerprint);
- }
-
- @Override
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
View root = super.onCreateView(inflater, superContainer, savedInstanceState);
View view = inflater.inflate(R.layout.view_key_fragment, getContainer());
@@ -144,6 +131,7 @@ public class ViewKeyFragment extends LoaderFragment implements
}
});
+ mSystemContactCard = (CardView) view.findViewById(R.id.linked_system_contact_card);
mSystemContactLayout = (LinearLayout) view.findViewById(R.id.system_contact_layout);
mSystemContactName = (TextView) view.findViewById(R.id.system_contact_name);
mSystemContactPicture = (ImageView) view.findViewById(R.id.system_contact_picture);
@@ -209,60 +197,64 @@ public class ViewKeyFragment extends LoaderFragment implements
}
/**
- * Checks if a system contact exists for given masterKeyId, and if it does, sets name, picture
- * and onClickListener for the linked system contact's layout
- * In the case of a secret key, "me" contact details are loaded
- *
- * @param masterKeyId
+ * Hides card if no linked system contact exists. Sets name, picture
+ * and onClickListener for the linked system contact's layout.
+ * In the case of a secret key, "me" (own profile) contact details are loaded.
*/
- private void loadLinkedSystemContact(final long masterKeyId) {
+ private void loadLinkedSystemContact(final long contactId) {
+
final Context context = mSystemContactName.getContext();
final ContentResolver resolver = context.getContentResolver();
- long contactId;
String contactName = null;
if (mIsSecret) {//all secret keys are linked to "me" profile in contacts
- contactId = ContactHelper.getMainProfileContactId(resolver);
List<String> mainProfileNames = ContactHelper.getMainProfileContactName(context);
if (mainProfileNames != null && mainProfileNames.size() > 0) {
contactName = mainProfileNames.get(0);
}
-
} else {
- contactId = ContactHelper.findContactId(resolver, masterKeyId);
contactName = ContactHelper.getContactName(resolver, contactId);
}
if (contactName != null) {//contact name exists for given master key
+ showLinkedSystemContact();
+
mSystemContactName.setText(contactName);
Bitmap picture;
if (mIsSecret) {
picture = ContactHelper.loadMainProfilePhoto(resolver, false);
} else {
- picture = ContactHelper.loadPhotoByMasterKeyId(resolver, masterKeyId, false);
+ picture = ContactHelper.loadPhotoByContactId(resolver, contactId, false);
}
if (picture != null) mSystemContactPicture.setImageBitmap(picture);
- final long finalContactId = contactId;
mSystemContactLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- launchContactActivity(finalContactId, context);
+ launchContactActivity(contactId, context);
}
});
- mSystemContactLoaded = true;
+ } else {
+ hideLinkedSystemContact();
}
}
+ private void hideLinkedSystemContact() {
+ mSystemContactCard.setVisibility(View.GONE);
+ }
+
+ private void showLinkedSystemContact() {
+ mSystemContactCard.setVisibility(View.VISIBLE);
+ }
+
/**
* launches the default android Contacts app to view a contact with the passed
* contactId (CONTACT_ID column from ContactsContract.RawContact table which is _ID column in
* ContactsContract.Contact table)
*
* @param contactId _ID for row in ContactsContract.Contacts table
- * @param context
*/
private void launchContactActivity(final long contactId, Context context) {
Intent intent = new Intent(Intent.ACTION_VIEW);
@@ -271,23 +263,61 @@ public class ViewKeyFragment extends LoaderFragment implements
context.startActivity(intent);
}
- private void loadData(Uri dataUri, boolean isSecret, byte[] fingerprint) {
- mDataUri = dataUri;
- mIsSecret = isSecret;
- mFingerprint = fingerprint;
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
- Log.i(Constants.TAG, "mDataUri: " + mDataUri);
+ Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
+ if (dataUri == null) {
+ Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
+ getActivity().finish();
+ return;
+ }
+
+ loadData(dataUri);
+ }
- // load user ids after we know if it's a secret key
- mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !mIsSecret, null);
- mUserIds.setAdapter(mUserIdsAdapter);
- getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
+ // These are the rows that we will retrieve.
+ static final String[] UNIFIED_PROJECTION = new String[]{
+ KeychainContract.KeyRings._ID,
+ KeychainContract.KeyRings.MASTER_KEY_ID,
+ KeychainContract.KeyRings.USER_ID,
+ KeychainContract.KeyRings.IS_REVOKED,
+ KeychainContract.KeyRings.IS_EXPIRED,
+ KeychainContract.KeyRings.VERIFIED,
+ KeychainContract.KeyRings.HAS_ANY_SECRET,
+ KeychainContract.KeyRings.FINGERPRINT,
+ KeychainContract.KeyRings.HAS_ENCRYPT
+ };
+
+ static final int INDEX_MASTER_KEY_ID = 1;
+ @SuppressWarnings("unused")
+ static final int INDEX_USER_ID = 2;
+ @SuppressWarnings("unused")
+ static final int INDEX_IS_REVOKED = 3;
+ @SuppressWarnings("unused")
+ static final int INDEX_IS_EXPIRED = 4;
+ @SuppressWarnings("unused")
+ static final int INDEX_VERIFIED = 5;
+ static final int INDEX_HAS_ANY_SECRET = 6;
+ static final int INDEX_FINGERPRINT = 7;
+ @SuppressWarnings("unused")
+ static final int INDEX_HAS_ENCRYPT = 8;
+
+ private static final String[] RAWCONTACT_PROJECTION = {
+ ContactsContract.RawContacts.CONTACT_ID
+ };
+
+ private static final int INDEX_CONTACT_ID = 0;
+
+ private void loadData(Uri dataUri) {
+ mDataUri = dataUri;
- mLinkedIdsAdapter = new LinkedIdsAdapter(getActivity(), null, 0,
- mIsSecret, mLinkedIdsExpander);
- mLinkedIds.setAdapter(mLinkedIdsAdapter);
- getLoaderManager().initLoader(LOADER_ID_LINKED_IDS, null, this);
+ Log.i(Constants.TAG, "mDataUri: " + mDataUri);
+ // Prepare the loaders. Either re-connect with an existing ones,
+ // or start new ones.
+ getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
}
@Override
@@ -295,11 +325,45 @@ public class ViewKeyFragment extends LoaderFragment implements
setContentShown(false);
switch (id) {
- case LOADER_ID_USER_IDS:
+ case LOADER_ID_UNIFIED: {
+ Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri);
+ return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null);
+ }
+
+ case LOADER_ID_USER_IDS: {
return UserIdsAdapter.createLoader(getActivity(), mDataUri);
+ }
- case LOADER_ID_LINKED_IDS:
+ case LOADER_ID_LINKED_IDS: {
return LinkedIdsAdapter.createLoader(getActivity(), mDataUri);
+ }
+
+ //we need a separate loader for linked contact to ensure refreshing on verification
+ case LOADER_ID_LINKED_CONTACT: {
+ //passed in args to explicitly specify their need
+ long masterKeyId = args.getLong(LOADER_EXTRA_LINKED_CONTACT_MASTER_KEY_ID);
+ boolean isSecret = args.getBoolean(LOADER_EXTRA_LINKED_CONTACT_IS_SECRET);
+
+ Uri baseUri;
+ if (isSecret)
+ baseUri = ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI;
+ else
+ baseUri = ContactsContract.RawContacts.CONTENT_URI;
+
+ return new CursorLoader(
+ getActivity(),
+ baseUri,
+ RAWCONTACT_PROJECTION,
+ ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " +
+ ContactsContract.RawContacts.SOURCE_ID + "=? AND " +
+ ContactsContract.RawContacts.DELETED + "=?",
+ new String[]{//"0" for "not deleted"
+ Constants.ACCOUNT_TYPE,
+ Long.toString(masterKeyId),
+ "0"
+ },
+ null);
+ }
default:
return null;
@@ -307,21 +371,71 @@ public class ViewKeyFragment extends LoaderFragment implements
}
@Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ /* TODO better error handling? May cause problems when a key is deleted,
+ * because the notification triggers faster than the activity closes.
+ */
+ // Avoid NullPointerExceptions...
+ if (data.getCount() == 0) {
+ return;
+ }
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
switch (loader.getId()) {
+ case LOADER_ID_UNIFIED: {
+ if (data.moveToFirst()) {
+
+ mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
+ mFingerprint = data.getBlob(INDEX_FINGERPRINT);
+
+ // load user ids after we know if it's a secret key
+ mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !mIsSecret, null);
+ mUserIds.setAdapter(mUserIdsAdapter);
+ getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
+
+ mLinkedIdsAdapter =
+ new LinkedIdsAdapter(getActivity(), null, 0, mIsSecret, mLinkedIdsExpander);
+ mLinkedIds.setAdapter(mLinkedIdsAdapter);
+ getLoaderManager().initLoader(LOADER_ID_LINKED_IDS, null, this);
+
+ long masterKeyId = data.getLong(INDEX_MASTER_KEY_ID);
+ // we need to load linked contact here to prevent lag introduced by loader
+ // for the linked contact
+ long contactId = ContactHelper.findContactId(
+ getActivity().getContentResolver(),
+ masterKeyId);
+ loadLinkedSystemContact(contactId);
+
+ Bundle linkedContactData = new Bundle();
+ linkedContactData.putLong(LOADER_EXTRA_LINKED_CONTACT_MASTER_KEY_ID, masterKeyId);
+ linkedContactData.putBoolean(LOADER_EXTRA_LINKED_CONTACT_IS_SECRET, mIsSecret);
+
+ // initialises loader for contact query so we can listen to any updates
+ getLoaderManager().initLoader(LOADER_ID_LINKED_CONTACT, linkedContactData, this);
+
+ break;
+ }
+ }
+
case LOADER_ID_USER_IDS: {
- mUserIdsAdapter.swapCursor(cursor);
- loadLinkedSystemContact(KeyFormattingUtils.convertFingerprintToKeyId(mFingerprint));
+ mUserIdsAdapter.swapCursor(data);
break;
}
case LOADER_ID_LINKED_IDS: {
- mLinkedIdsCard.setVisibility(cursor.getCount() > 0 ? View.VISIBLE : View.GONE);
- mLinkedIdsAdapter.swapCursor(cursor);
+ mLinkedIdsCard.setVisibility(data.getCount() > 0 ? View.VISIBLE : View.GONE);
+ mLinkedIdsAdapter.swapCursor(data);
+ break;
+ }
+
+ case LOADER_ID_LINKED_CONTACT: {
+ if (data.moveToFirst()) {// if we have a linked contact
+ long contactId = data.getLong(INDEX_CONTACT_ID);
+ loadLinkedSystemContact(contactId);
+ }
break;
}
+
}
setContentShown(true);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java
new file mode 100644
index 000000000..812874456
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.os.Message;
+import android.os.Messenger;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.LoaderManager.LoaderCallbacks;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+import org.spongycastle.util.encoders.Hex;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
+import org.sufficientlysecure.keychain.operations.results.PromoteKeyResult;
+import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
+import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+
+public class ViewKeyYubiKeyFragment extends Fragment
+ implements LoaderCallbacks<Cursor> {
+
+ public static final String ARG_FINGERPRINT = "fingerprint";
+ public static final String ARG_USER_ID = "user_id";
+ public static final String ARG_CARD_AID = "aid";
+ private byte[][] mFingerprints;
+ private String mUserId;
+ private byte[] mCardAid;
+ private long mMasterKeyId;
+ private Button vButton;
+ private TextView vStatus;
+
+ public static ViewKeyYubiKeyFragment newInstance(byte[] fingerprints, String userId, byte[] aid) {
+ ViewKeyYubiKeyFragment frag = new ViewKeyYubiKeyFragment();
+
+ Bundle args = new Bundle();
+ args.putByteArray(ARG_FINGERPRINT, fingerprints);
+ args.putString(ARG_USER_ID, userId);
+ args.putByteArray(ARG_CARD_AID, aid);
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Bundle args = getArguments();
+ ByteBuffer buf = ByteBuffer.wrap(args.getByteArray(ARG_FINGERPRINT));
+ mFingerprints = new byte[buf.remaining()/40][];
+ for (int i = 0; i < mFingerprints.length; i++) {
+ mFingerprints[i] = new byte[20];
+ buf.get(mFingerprints[i]);
+ }
+ mUserId = args.getString(ARG_USER_ID);
+ mCardAid = args.getByteArray(ARG_CARD_AID);
+
+ mMasterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mFingerprints[0]);
+
+ getLoaderManager().initLoader(0, null, this);
+
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.view_key_yubikey, null);
+
+ TextView vSerNo = (TextView) view.findViewById(R.id.yubikey_serno);
+ TextView vUserId = (TextView) view.findViewById(R.id.yubikey_userid);
+
+ String serno = Hex.toHexString(mCardAid, 10, 4);
+ vSerNo.setText(getString(R.string.yubikey_serno, serno));
+
+ if (!mUserId.isEmpty()) {
+ vUserId.setText(getString(R.string.yubikey_key_holder, mUserId));
+ } else {
+ vUserId.setText(getString(R.string.yubikey_key_holder_unset));
+ }
+
+ vButton = (Button) view.findViewById(R.id.button_bind);
+ vButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ promoteToSecretKey();
+ }
+ });
+
+ vStatus = (TextView) view.findViewById(R.id.yubikey_status);
+
+ return view;
+ }
+
+ public void promoteToSecretKey() {
+
+ ServiceProgressHandler saveHandler = new ServiceProgressHandler(getActivity()) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ if (message.arg1 == MessageStatus.OKAY.ordinal()) {
+ // get returned data bundle
+ Bundle returnData = message.getData();
+
+ PromoteKeyResult result =
+ returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT);
+
+ result.createNotify(getActivity()).show();
+ }
+
+ }
+ };
+
+ // Send all information needed to service to decrypt in other thread
+ Intent intent = new Intent(getActivity(), KeychainIntentService.class);
+
+ // fill values for this action
+
+ intent.setAction(KeychainIntentService.ACTION_PROMOTE_KEYRING);
+
+ Bundle data = new Bundle();
+ data.putLong(KeychainIntentService.PROMOTE_MASTER_KEY_ID, mMasterKeyId);
+ data.putByteArray(KeychainIntentService.PROMOTE_CARD_AID, mCardAid);
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(saveHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ // start service with intent
+ getActivity().startService(intent);
+
+ }
+
+ public static final String[] PROJECTION = new String[]{
+ Keys._ID,
+ Keys.KEY_ID,
+ Keys.RANK,
+ Keys.HAS_SECRET,
+ Keys.FINGERPRINT
+ };
+ private static final int INDEX_KEY_ID = 1;
+ private static final int INDEX_RANK = 2;
+ private static final int INDEX_HAS_SECRET = 3;
+ private static final int INDEX_FINGERPRINT = 4;
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ return new CursorLoader(getActivity(), Keys.buildKeysUri(mMasterKeyId),
+ PROJECTION, null, null, null);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ if (!data.moveToFirst()) {
+ // wut?
+ return;
+ }
+
+ boolean allBound = true;
+ boolean noneBound = true;
+
+ do {
+ SecretKeyType keyType = SecretKeyType.fromNum(data.getInt(INDEX_HAS_SECRET));
+ byte[] fingerprint = data.getBlob(INDEX_FINGERPRINT);
+ Integer index = naiveIndexOf(mFingerprints, fingerprint);
+ if (index == null) {
+ continue;
+ }
+ if (keyType == SecretKeyType.DIVERT_TO_CARD) {
+ noneBound = false;
+ } else {
+ allBound = false;
+ }
+ } while (data.moveToNext());
+
+ if (allBound) {
+ vButton.setVisibility(View.GONE);
+ vStatus.setText(R.string.yubikey_status_bound);
+ } else {
+ vButton.setVisibility(View.VISIBLE);
+ vStatus.setText(noneBound
+ ? R.string.yubikey_status_unbound
+ : R.string.yubikey_status_partly);
+ }
+
+ }
+
+ public Integer naiveIndexOf(byte[][] haystack, byte[] needle) {
+ for (int i = 0; i < haystack.length; i++) {
+ if (Arrays.equals(needle, haystack[i])) {
+ return i;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
index 9304b14f1..6f19fc6ed 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
@@ -147,6 +147,8 @@ public class KeyAdapter extends CursorAdapter {
mStatus.setVisibility(View.GONE);
if (mSlingerButton.hasOnClickListeners()) {
mSlinger.setVisibility(View.VISIBLE);
+ } else {
+ mSlinger.setVisibility(View.GONE);
}
mMainUserId.setTextColor(context.getResources().getColor(R.color.black));
mMainUserIdRest.setTextColor(context.getResources().getColor(R.color.black));
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SpacesItemDecoration.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SpacesItemDecoration.java
new file mode 100644
index 000000000..bc595803b
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SpacesItemDecoration.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import android.graphics.Rect;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+/**
+ * https://gist.github.com/yrom/3b4bcbc2370ca2290434
+ */
+public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
+ private int space;
+ private int spanCount;
+ private int lastItemInFirstLane = -1;
+
+ public SpacesItemDecoration(int space) {
+ this(space, 1);
+ }
+
+ /**
+ * @param space
+ * @param spanCount spans count of one lane
+ */
+ public SpacesItemDecoration(int space, int spanCount) {
+ this.space = space;
+ this.spanCount = spanCount;
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+ RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
+ final int position = params.getViewPosition();
+ final int spanSize;
+ final int index;
+ if (params instanceof GridLayoutManager.LayoutParams) {
+ GridLayoutManager.LayoutParams gridParams = (GridLayoutManager.LayoutParams) params;
+ spanSize = gridParams.getSpanSize();
+ index = gridParams.getSpanIndex();
+ } else {
+ spanSize = 1;
+ index = position % spanCount;
+ }
+ // invalid value
+ if (spanSize < 1 || index < 0) return;
+
+ if (spanSize == spanCount) { // full span
+ outRect.left = space;
+ outRect.right = space;
+ } else {
+ if (index == 0) { // left one
+ outRect.left = space;
+ }
+ // spanCount >= 1
+ if (index == spanCount - 1) { // right one
+ outRect.right = space;
+ }
+ if (outRect.left == 0) {
+ outRect.left = space / 2;
+ }
+ if (outRect.right == 0) {
+ outRect.right = space / 2;
+ }
+ }
+ // set top to all in first lane
+ if (position < spanCount && spanSize <= spanCount) {
+ if (lastItemInFirstLane < 0) { // lay out at first time
+ lastItemInFirstLane = position + spanSize == spanCount ? position : lastItemInFirstLane;
+ outRect.top = space;
+ } else if (position <= lastItemInFirstLane) { // scroll to first lane again
+ outRect.top = space;
+ }
+ }
+ outRect.bottom = space;
+
+ }
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java
index 41fa50705..07d2ef8c0 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java
@@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package org.sufficientlysecure.keychain.ui;
+package org.sufficientlysecure.keychain.ui.base;
import android.app.Activity;
import android.os.Bundle;
@@ -63,8 +63,8 @@ public abstract class BaseActivity extends ActionBarActivity {
* Inflate custom design to look like a full screen dialog, as specified in Material Design Guidelines
* see http://www.google.com/design/spec/components/dialogs.html#dialogs-full-screen-dialogs
*/
- protected void setFullScreenDialogDoneClose(int doneText, View.OnClickListener doneOnClickListener,
- View.OnClickListener cancelOnClickListener) {
+ public void setFullScreenDialogDoneClose(int doneText, View.OnClickListener doneOnClickListener,
+ View.OnClickListener cancelOnClickListener) {
setActionBarIcon(R.drawable.ic_close_white_24dp);
// Inflate the custom action bar view
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java
index 7311f4879..95c1690b1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java
@@ -1,131 +1,105 @@
-/**
- * Copyright (c) 2013-2014 Philipp Jakubeit, Signe Rüsch, Dominik Schürmann
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
*
- * Licensed under the Bouncy Castle License (MIT license). See LICENSE file for details.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package org.sufficientlysecure.keychain.ui;
+package org.sufficientlysecure.keychain.ui.base;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
-import android.annotation.TargetApi;
+import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.IsoDep;
-import android.os.Build;
import android.os.Bundle;
-import android.view.WindowManager;
import android.widget.Toast;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
+import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
+import org.sufficientlysecure.keychain.ui.CreateKeyActivity;
+import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
+import org.sufficientlysecure.keychain.ui.ViewKeyActivity;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.Iso7816TLV;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
+import org.sufficientlysecure.keychain.util.Preferences;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-/**
- * This class provides a communication interface to OpenPGP applications on ISO SmartCard compliant
- * NFC devices.
- *
- * For the full specs, see http://g10code.com/docs/openpgp-card-2.0.pdf
- */
-@TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)
-public class NfcActivity extends BaseActivity {
-
- // actions
- public static final String ACTION_SIGN_HASH = "sign_hash";
- public static final String ACTION_DECRYPT_SESSION_KEY = "decrypt_session_key";
-
- // always
- public static final String EXTRA_KEY_ID = "key_id";
- public static final String EXTRA_PIN = "pin";
- // special extra for OpenPgpService
- public static final String EXTRA_DATA = "data";
+public abstract class BaseNfcActivity extends BaseActivity {
- // sign
- public static final String EXTRA_NFC_HASH_TO_SIGN = "nfc_hash";
- public static final String EXTRA_NFC_HASH_ALGO = "nfc_hash_algo";
-
- // decrypt
- public static final String EXTRA_NFC_ENC_SESSION_KEY = "encrypted_session_key";
-
- private Intent mServiceIntent;
-
- private static final int TIMEOUT = 100000;
+ public static final int REQUEST_CODE_PASSPHRASE = 1;
+ protected Passphrase mPin;
private NfcAdapter mNfcAdapter;
private IsoDep mIsoDep;
- private String mAction;
- private String mPin;
- private Long mKeyId;
-
- // sign
- private byte[] mHashToSign;
- private int mHashAlgo;
-
- // decrypt
- private byte[] mEncryptedSessionKey;
+ private static final int TIMEOUT = 100000;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Log.d(Constants.TAG, "NfcActivity.onCreate");
-
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Intent intent = getIntent();
- Bundle data = intent.getExtras();
String action = intent.getAction();
-
- // if we get are passed a key id, save it for the check
- if (data.containsKey(EXTRA_KEY_ID)) {
- mKeyId = data.getLong(EXTRA_KEY_ID);
+ if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
+ throw new AssertionError("should not happen: NfcOperationActivity.onCreate is called instead of onNewIntent!");
}
- switch (action) {
- case ACTION_SIGN_HASH:
- mAction = action;
- mPin = data.getString(EXTRA_PIN);
- mHashToSign = data.getByteArray(EXTRA_NFC_HASH_TO_SIGN);
- mHashAlgo = data.getInt(EXTRA_NFC_HASH_ALGO);
- mServiceIntent = data.getParcelable(EXTRA_DATA);
-
- Log.d(Constants.TAG, "NfcActivity mAction: " + mAction);
- Log.d(Constants.TAG, "NfcActivity mPin: " + mPin);
- Log.d(Constants.TAG, "NfcActivity mHashToSign as hex: " + getHex(mHashToSign));
- Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString());
- break;
- case ACTION_DECRYPT_SESSION_KEY:
- mAction = action;
- mPin = data.getString(EXTRA_PIN);
- mEncryptedSessionKey = data.getByteArray(EXTRA_NFC_ENC_SESSION_KEY);
- mServiceIntent = data.getParcelable(EXTRA_DATA);
-
- Log.d(Constants.TAG, "NfcActivity mAction: " + mAction);
- Log.d(Constants.TAG, "NfcActivity mPin: " + mPin);
- Log.d(Constants.TAG, "NfcActivity mEncryptedSessionKey as hex: " + getHex(mEncryptedSessionKey));
- Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString());
- break;
- case NfcAdapter.ACTION_TAG_DISCOVERED:
- Log.e(Constants.TAG, "This should not happen! NfcActivity.onCreate() is being called instead of onNewIntent()!");
- toast("This should not happen! Please create a new bug report that the NFC screen is restarted!");
- finish();
- break;
- default:
- Log.d(Constants.TAG, "Action not supported: " + action);
- break;
- }
}
+ /**
+ * This activity is started as a singleTop activity.
+ * All new NFC Intents which are delivered to this activity are handled here
+ */
@Override
- protected void initLayout() {
- setContentView(R.layout.nfc_activity);
+ public void onNewIntent(Intent intent) {
+ if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
+ try {
+ handleNdefDiscoveredIntent(intent);
+ } catch (IOException e) {
+ handleNfcError(e);
+ }
+ }
+ }
+
+ public void handleNfcError(IOException e) {
+
+ Log.e(Constants.TAG, "nfc error", e);
+ Notify.create(this, getString(R.string.error_nfc, e.getMessage()), Style.WARN).show();
+
+ }
+
+ public void handlePinError() {
+ toast("Wrong PIN!");
+ setResult(RESULT_CANCELED);
+ finish();
}
/**
@@ -134,7 +108,7 @@ public class NfcActivity extends BaseActivity {
*/
public void onPause() {
super.onPause();
- Log.d(Constants.TAG, "NfcActivity.onPause");
+ Log.d(Constants.TAG, "BaseNfcActivity.onPause");
disableNfcForegroundDispatch();
}
@@ -145,25 +119,45 @@ public class NfcActivity extends BaseActivity {
*/
public void onResume() {
super.onResume();
- Log.d(Constants.TAG, "NfcActivity.onResume");
+ Log.d(Constants.TAG, "BaseNfcActivity.onResume");
enableNfcForegroundDispatch();
}
- /**
- * This activity is started as a singleTop activity.
- * All new NFC Intents which are delivered to this activity are handled here
- */
- public void onNewIntent(Intent intent) {
- if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
- try {
- handleNdefDiscoveredIntent(intent);
- } catch (IOException e) {
- Log.e(Constants.TAG, "Connection error!", e);
- toast("Connection Error: " + e.getMessage());
- setResult(RESULT_CANCELED, mServiceIntent);
- finish();
- }
+ protected void obtainYubiKeyPin(RequiredInputParcel requiredInput) {
+
+ Preferences prefs = Preferences.getPreferences(this);
+ if (prefs.useDefaultYubiKeyPin()) {
+ mPin = new Passphrase("123456");
+ return;
+ }
+
+ Intent intent = new Intent(this, PassphraseDialogActivity.class);
+ intent.putExtra(PassphraseDialogActivity.EXTRA_REQUIRED_INPUT,
+ RequiredInputParcel.createRequiredPassphrase(requiredInput));
+ startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
+
+ }
+
+ protected void setYubiKeyPin(Passphrase pin) {
+ mPin = pin;
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (requestCode) {
+ case REQUEST_CODE_PASSPHRASE:
+ if (resultCode != Activity.RESULT_OK) {
+ setResult(resultCode);
+ finish();
+ return;
+ }
+ CryptoInputParcel input = data.getParcelableExtra(PassphraseDialogActivity.RESULT_CRYPTO_INPUT);
+ mPin = input.getPassphrase();
+ break;
+
+ default:
+ super.onActivityResult(requestCode, resultCode, data);
}
}
@@ -181,7 +175,7 @@ public class NfcActivity extends BaseActivity {
* on ISO SmartCard Systems specification.
*
*/
- private void handleNdefDiscoveredIntent(Intent intent) throws IOException {
+ protected void handleNdefDiscoveredIntent(Intent intent) throws IOException {
Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
@@ -196,113 +190,64 @@ public class NfcActivity extends BaseActivity {
// Command APDU (page 51) for SELECT FILE command (page 29)
String opening =
- "00" // CLA
- + "A4" // INS
- + "04" // P1
- + "00" // P2
- + "06" // Lc (number of bytes)
- + "D27600012401" // Data (6 bytes)
- + "00"; // Le
- if ( ! card(opening).equals(accepted)) { // activate connection
- toast("Opening Error!");
- setResult(RESULT_CANCELED, mServiceIntent);
- finish();
- return;
+ "00" // CLA
+ + "A4" // INS
+ + "04" // P1
+ + "00" // P2
+ + "06" // Lc (number of bytes)
+ + "D27600012401" // Data (6 bytes)
+ + "00"; // Le
+ if ( ! nfcCommunicate(opening).equals(accepted)) { // activate connection
+ throw new IOException("Initialization failed!");
}
- // Command APDU for VERIFY command (page 32)
- String login =
- "00" // CLA
- + "20" // INS
- + "00" // P1
- + "82" // P2 (PW1)
- + String.format("%02x", mPin.length()) // Lc
- + Hex.toHexString(mPin.getBytes());
- if ( ! card(login).equals(accepted)) { // login
- toast("Wrong PIN!");
- setResult(RESULT_CANCELED, mServiceIntent);
- finish();
- return;
- }
+ onNfcPerform();
- if (ACTION_SIGN_HASH.equals(mAction)) {
+ mIsoDep.close();
+ mIsoDep = null;
- // If we were supplied with a key id for checking, do so
- if (mKeyId != null) {
- // For signing, we check the master key
- long keyId = nfcGetKeyId(mIsoDep, 0);
- // If it's wrong, just cancel
- if (keyId != mKeyId) {
- toast("NFC Tag has wrong signing key id!");
- setResult(RESULT_CANCELED, mServiceIntent);
- finish();
- return;
- }
- }
+ }
- // returns signed hash
- byte[] signedHash = nfcCalculateSignature(mHashToSign, mHashAlgo);
+ protected void onNfcPerform() throws IOException {
- if (signedHash == null) {
- setResult(RESULT_CANCELED, mServiceIntent);
- finish();
- return;
- }
+ final byte[] nfcFingerprints = nfcGetFingerprints();
+ final String nfcUserId = nfcGetUserId();
+ final byte[] nfcAid = nfcGetAid();
- Log.d(Constants.TAG, "NfcActivity signedHash as hex: " + getHex(signedHash));
+ final long masterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(nfcFingerprints);
- // give data through for new service call
- // OpenPgpApi.EXTRA_NFC_SIGNED_HASH
- mServiceIntent.putExtra("nfc_signed_hash", signedHash);
- setResult(RESULT_OK, mServiceIntent);
+ try {
+ CachedPublicKeyRing ring = new ProviderHelper(this).getCachedPublicKeyRing(masterKeyId);
+ ring.getMasterKeyId();
+
+ Intent intent = new Intent(
+ BaseNfcActivity.this, ViewKeyActivity.class);
+ intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId));
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, nfcAid);
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_USER_ID, nfcUserId);
+ intent.putExtra(ViewKeyActivity.EXTRA_NFC_FINGERPRINTS, nfcFingerprints);
+ startActivity(intent);
finish();
-
- } else if (ACTION_DECRYPT_SESSION_KEY.equals(mAction)) {
-
- // If we were supplied with a key id for checking, do so
- if (mKeyId != null) {
- // For decryption, we check the confidentiality key
- long keyId = nfcGetKeyId(mIsoDep, 1);
- // If it's wrong, just cancel
- if (keyId != mKeyId) {
- toast("NFC Tag has wrong encryption key id!");
- setResult(RESULT_CANCELED, mServiceIntent);
- finish();
- return;
- }
- }
-
- byte[] decryptedSessionKey = nfcDecryptSessionKey(mEncryptedSessionKey);
-
- // give data through for new service call
- // OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY
- mServiceIntent.putExtra("nfc_decrypted_session_key", decryptedSessionKey);
- setResult(RESULT_OK, mServiceIntent);
+ } catch (PgpKeyNotFoundException e) {
+ Intent intent = new Intent(
+ BaseNfcActivity.this, CreateKeyActivity.class);
+ intent.putExtra(CreateKeyActivity.EXTRA_NFC_AID, nfcAid);
+ intent.putExtra(CreateKeyActivity.EXTRA_NFC_USER_ID, nfcUserId);
+ intent.putExtra(CreateKeyActivity.EXTRA_NFC_FINGERPRINTS, nfcFingerprints);
+ startActivity(intent);
finish();
}
}
- /**
- * Gets the user ID
- *
- * @return the user id as "name <email>"
- * @throws java.io.IOException
- */
- public String getUserId() throws IOException {
- String info = "00CA006500";
- String data = "00CA005E00";
- return getName(card(info)) + " <" + (new String(Hex.decode(getDataField(card(data))))) + ">";
- }
-
/** Return the key id from application specific data stored on tag, or null
* if it doesn't exist.
*
* @param idx Index of the key to return the fingerprint from.
* @return The long key id of the requested key, or null if not found.
*/
- public static Long nfcGetKeyId(IsoDep isoDep, int idx) throws IOException {
- byte[] fp = nfcGetFingerprint(isoDep, idx);
+ public Long nfcGetKeyId(int idx) throws IOException {
+ byte[] fp = nfcGetFingerprint(idx);
if (fp == null) {
return null;
}
@@ -318,9 +263,9 @@ public class NfcActivity extends BaseActivity {
*
* @return The fingerprints of all subkeys in a contiguous byte array.
*/
- public static byte[] nfcGetFingerprints(IsoDep isoDep) throws IOException {
+ public byte[] nfcGetFingerprints() throws IOException {
String data = "00CA006E00";
- byte[] buf = isoDep.transceive(Hex.decode(data));
+ byte[] buf = mIsoDep.transceive(Hex.decode(data));
Iso7816TLV tlv = Iso7816TLV.readSingle(buf, true);
Log.d(Constants.TAG, "nfc tlv data:\n" + tlv.prettyPrint());
@@ -339,26 +284,39 @@ public class NfcActivity extends BaseActivity {
* @param idx Index of the key to return the fingerprint from.
* @return The fingerprint of the requested key, or null if not found.
*/
- public static byte[] nfcGetFingerprint(IsoDep isoDep, int idx) throws IOException {
- byte[] data = nfcGetFingerprints(isoDep);
+ public byte[] nfcGetFingerprint(int idx) throws IOException {
+ byte[] data = nfcGetFingerprints();
// return the master key fingerprint
ByteBuffer fpbuf = ByteBuffer.wrap(data);
byte[] fp = new byte[20];
- fpbuf.position(idx*20);
+ fpbuf.position(idx * 20);
fpbuf.get(fp, 0, 20);
return fp;
}
+ public byte[] nfcGetAid() throws IOException {
+
+ String info = "00CA004F00";
+ return mIsoDep.transceive(Hex.decode(info));
+
+ }
+
+ public String nfcGetUserId() throws IOException {
+
+ String info = "00CA006500";
+ return nfcGetHolderName(nfcCommunicate(info));
+ }
+
/**
* Calls to calculate the signature and returns the MPI value
*
* @param hash the hash for signing
* @return a big integer representing the MPI for the given hash
- * @throws java.io.IOException
*/
public byte[] nfcCalculateSignature(byte[] hash, int hashAlgo) throws IOException {
+ nfcVerifyPIN(0x81); // (Verify PW1 with mode 81 for signing)
// dsi, including Lc
String dsi;
@@ -367,7 +325,7 @@ public class NfcActivity extends BaseActivity {
switch (hashAlgo) {
case HashAlgorithmTags.SHA1:
if (hash.length != 20) {
- throw new RuntimeException("Bad hash length (" + hash.length + ", expected 10!");
+ throw new IOException("Bad hash length (" + hash.length + ", expected 10!");
}
dsi = "23" // Lc
+ "3021" // Tag/Length of Sequence, the 0x21 includes all following 33 bytes
@@ -378,45 +336,45 @@ public class NfcActivity extends BaseActivity {
break;
case HashAlgorithmTags.RIPEMD160:
if (hash.length != 20) {
- throw new RuntimeException("Bad hash length (" + hash.length + ", expected 20!");
+ throw new IOException("Bad hash length (" + hash.length + ", expected 20!");
}
dsi = "233021300906052B2403020105000414" + getHex(hash);
break;
case HashAlgorithmTags.SHA224:
if (hash.length != 28) {
- throw new RuntimeException("Bad hash length (" + hash.length + ", expected 28!");
+ throw new IOException("Bad hash length (" + hash.length + ", expected 28!");
}
dsi = "2F302D300D06096086480165030402040500041C" + getHex(hash);
break;
case HashAlgorithmTags.SHA256:
if (hash.length != 32) {
- throw new RuntimeException("Bad hash length (" + hash.length + ", expected 32!");
+ throw new IOException("Bad hash length (" + hash.length + ", expected 32!");
}
dsi = "333031300D060960864801650304020105000420" + getHex(hash);
break;
case HashAlgorithmTags.SHA384:
if (hash.length != 48) {
- throw new RuntimeException("Bad hash length (" + hash.length + ", expected 48!");
+ throw new IOException("Bad hash length (" + hash.length + ", expected 48!");
}
dsi = "433041300D060960864801650304020205000430" + getHex(hash);
break;
case HashAlgorithmTags.SHA512:
if (hash.length != 64) {
- throw new RuntimeException("Bad hash length (" + hash.length + ", expected 64!");
+ throw new IOException("Bad hash length (" + hash.length + ", expected 64!");
}
dsi = "533051300D060960864801650304020305000440" + getHex(hash);
break;
default:
- throw new RuntimeException("Not supported hash algo!");
+ throw new IOException("Not supported hash algo!");
}
// Command APDU for PERFORM SECURITY OPERATION: COMPUTE DIGITAL SIGNATURE (page 37)
String apdu =
- "002A9E9A" // CLA, INS, P1, P2
- + dsi // digital signature input
- + "00"; // Le
+ "002A9E9A" // CLA, INS, P1, P2
+ + dsi // digital signature input
+ + "00"; // Le
- String response = card(apdu);
+ String response = nfcCommunicate(apdu);
// split up response into signature and status
String status = response.substring(response.length()-4);
@@ -426,22 +384,20 @@ public class NfcActivity extends BaseActivity {
while (status.substring(0, 2).equals("61")) {
Log.d(Constants.TAG, "requesting more data, status " + status);
// Send GET RESPONSE command
- response = card("00C00000" + status.substring(2));
+ response = nfcCommunicate("00C00000" + status.substring(2));
status = response.substring(response.length()-4);
signature += response.substring(0, response.length()-4);
}
Log.d(Constants.TAG, "final response:" + status);
- if ( ! status.equals("9000")) {
- toast("Bad NFC response code: " + status);
- return null;
+ if ( ! "9000".equals(status)) {
+ throw new IOException("Bad NFC response code: " + status);
}
// Make sure the signature we received is actually the expected number of bytes long!
if (signature.length() != 256 && signature.length() != 512) {
- toast("Bad signature length! Expected 128 or 256 bytes, got " + signature.length() / 2);
- return null;
+ throw new IOException("Bad signature length! Expected 128 or 256 bytes, got " + signature.length() / 2);
}
return Hex.decode(signature);
@@ -452,9 +408,10 @@ public class NfcActivity extends BaseActivity {
*
* @param encryptedSessionKey the encoded session key
* @return the decoded session key
- * @throws java.io.IOException
*/
public byte[] nfcDecryptSessionKey(byte[] encryptedSessionKey) throws IOException {
+ nfcVerifyPIN(0x82); // (Verify PW1 with mode 82 for decryption)
+
String firstApdu = "102a8086fe";
String secondApdu = "002a808603";
String le = "00";
@@ -468,22 +425,48 @@ public class NfcActivity extends BaseActivity {
two[i] = encryptedSessionKey[i + one.length + 1];
}
- String first = card(firstApdu + getHex(one));
- String second = card(secondApdu + getHex(two) + le);
+ String first = nfcCommunicate(firstApdu + getHex(one));
+ String second = nfcCommunicate(secondApdu + getHex(two) + le);
- String decryptedSessionKey = getDataField(second);
+ String decryptedSessionKey = nfcGetDataField(second);
Log.d(Constants.TAG, "decryptedSessionKey: " + decryptedSessionKey);
return Hex.decode(decryptedSessionKey);
}
+ /** Verifies the user's PW1 with the appropriate mode.
+ *
+ * @param mode This is 0x81 for signing, 0x82 for everything else
+ */
+ public void nfcVerifyPIN(int mode) throws IOException {
+ if (mPin != null) {
+ byte[] pin = new String(mPin.getCharArray()).getBytes();
+ // SW1/2 0x9000 is the generic "ok" response, which we expect most of the time.
+ // See specification, page 51
+ String accepted = "9000";
+
+ // Command APDU for VERIFY command (page 32)
+ String login =
+ "00" // CLA
+ + "20" // INS
+ + "00" // P1
+ + String.format("%02x", mode) // P2
+ + String.format("%02x", pin.length) // Lc
+ + Hex.toHexString(pin);
+ if (!nfcCommunicate(login).equals(accepted)) { // login
+ handlePinError();
+ throw new IOException("Bad PIN!");
+ }
+ }
+ }
+
/**
* Prints a message to the screen
*
* @param text the text which should be contained within the toast
*/
- private void toast(String text) {
+ protected void toast(String text) {
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
}
@@ -493,7 +476,7 @@ public class NfcActivity extends BaseActivity {
*/
public void enableNfcForegroundDispatch() {
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
- Intent nfcI = new Intent(this, NfcActivity.class)
+ Intent nfcI = new Intent(this, getClass())
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent nfcPendingIntent = PendingIntent.getActivity(this, 0, nfcI, PendingIntent.FLAG_CANCEL_CURRENT);
IntentFilter[] writeTagFilters = new IntentFilter[]{
@@ -518,13 +501,7 @@ public class NfcActivity extends BaseActivity {
Log.d(Constants.TAG, "NfcForegroundDispatch has been disabled!");
}
- /**
- * Gets the name of the user out of the raw card output regarding card holder related data
- *
- * @param name the raw card holder related data from the card
- * @return the name given in this data
- */
- public String getName(String name) {
+ public String nfcGetHolderName(String name) {
String slength;
int ilength;
name = name.substring(6);
@@ -535,34 +512,16 @@ public class NfcActivity extends BaseActivity {
return (name);
}
- /**
- * Reduces the raw data from the card by four characters
- *
- * @param output the raw data from the card
- * @return the data field of that data
- */
- private String getDataField(String output) {
+ private String nfcGetDataField(String output) {
return output.substring(0, output.length() - 4);
}
- /**
- * Communicates with the OpenPgpCard via the APDU
- *
- * @param hex the hexadecimal APDU
- * @return The answer from the card
- * @throws java.io.IOException throws an exception if something goes wrong
- */
- public String card(String hex) throws IOException {
- return getHex(mIsoDep.transceive(Hex.decode(hex)));
+ public String nfcCommunicate(String apdu) throws IOException {
+ return getHex(mIsoDep.transceive(Hex.decode(apdu)));
}
- /**
- * Converts a byte array into an hex string
- *
- * @param raw the byte array representation
- * @return the hexadecimal string representation
- */
public static String getHex(byte[] raw) {
return new String(Hex.encode(raw));
}
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java
new file mode 100644
index 000000000..232a39f86
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.base;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Message;
+import android.support.v4.app.Fragment;
+
+import org.sufficientlysecure.keychain.operations.results.InputPendingResult;
+import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
+import org.sufficientlysecure.keychain.ui.NfcOperationActivity;
+import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
+
+/**
+ * All fragments executing crypto operations need to extend this class.
+ */
+public abstract class CryptoOperationFragment extends Fragment {
+
+ public static final int REQUEST_CODE_PASSPHRASE = 0x00008001;
+ public static final int REQUEST_CODE_NFC = 0x00008002;
+
+ private void initiateInputActivity(RequiredInputParcel requiredInput) {
+
+ switch (requiredInput.mType) {
+ case NFC_DECRYPT:
+ case NFC_SIGN: {
+ Intent intent = new Intent(getActivity(), NfcOperationActivity.class);
+ intent.putExtra(NfcOperationActivity.EXTRA_REQUIRED_INPUT, requiredInput);
+ startActivityForResult(intent, REQUEST_CODE_NFC);
+ return;
+ }
+
+ case PASSPHRASE:
+ case PASSPHRASE_SYMMETRIC: {
+ Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class);
+ intent.putExtra(PassphraseDialogActivity.EXTRA_REQUIRED_INPUT, requiredInput);
+ startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
+ return;
+ }
+ }
+
+ throw new RuntimeException("Unhandled pending result!");
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode == Activity.RESULT_CANCELED) {
+ onCryptoOperationCancelled();
+ return;
+ }
+
+ switch (requestCode) {
+ case REQUEST_CODE_PASSPHRASE: {
+ if (resultCode == Activity.RESULT_OK && data != null) {
+ CryptoInputParcel cryptoInput =
+ data.getParcelableExtra(PassphraseDialogActivity.RESULT_CRYPTO_INPUT);
+ cryptoOperation(cryptoInput);
+ return;
+ }
+ break;
+ }
+
+ case REQUEST_CODE_NFC: {
+ if (resultCode == Activity.RESULT_OK && data != null) {
+ CryptoInputParcel cryptoInput =
+ data.getParcelableExtra(NfcOperationActivity.RESULT_DATA);
+ cryptoOperation(cryptoInput);
+ return;
+ }
+ break;
+ }
+
+ default: {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+ }
+
+ public boolean handlePendingMessage(Message message) {
+
+ if (message.arg1 == ServiceProgressHandler.MessageStatus.OKAY.ordinal()) {
+ Bundle data = message.getData();
+
+ OperationResult result = data.getParcelable(OperationResult.EXTRA_RESULT);
+ if (result == null || !(result instanceof InputPendingResult)) {
+ return false;
+ }
+
+ InputPendingResult pendingResult = (InputPendingResult) result;
+ if (pendingResult.isPending()) {
+ RequiredInputParcel requiredInput = pendingResult.getRequiredInputParcel();
+ initiateInputActivity(requiredInput);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected void cryptoOperation() {
+ cryptoOperation(new CryptoInputParcel());
+ }
+
+ protected abstract void cryptoOperation(CryptoInputParcel cryptoInput);
+
+ protected void onCryptoOperationCancelled() {
+ // Nothing to do here, in most cases
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
index bd4e5577b..956171349 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
@@ -44,11 +44,24 @@ public class DeleteFileDialogFragment extends DialogFragment {
/**
* Creates new instance of this delete file dialog fragment
*/
- public static DeleteFileDialogFragment newInstance(Uri... deleteUris) {
+ public static DeleteFileDialogFragment newInstance(ArrayList<Uri> deleteUris) {
DeleteFileDialogFragment frag = new DeleteFileDialogFragment();
Bundle args = new Bundle();
- args.putParcelableArray(ARG_DELETE_URIS, deleteUris);
+ args.putParcelableArrayList(ARG_DELETE_URIS, deleteUris);
+
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ public static DeleteFileDialogFragment newInstance(Uri deleteUri) {
+ DeleteFileDialogFragment frag = new DeleteFileDialogFragment();
+ Bundle args = new Bundle();
+
+ ArrayList<Uri> list = new ArrayList<>();
+ list.add(deleteUri);
+ args.putParcelableArrayList(ARG_DELETE_URIS, list);
frag.setArguments(args);
@@ -62,7 +75,7 @@ public class DeleteFileDialogFragment extends DialogFragment {
public Dialog onCreateDialog(Bundle savedInstanceState) {
final FragmentActivity activity = getActivity();
- final Uri[] deleteUris = (Uri[]) getArguments().getParcelableArray(ARG_DELETE_URIS);
+ final ArrayList<Uri> deleteUris = getArguments().getParcelableArrayList(ARG_DELETE_URIS);
final StringBuilder deleteFileNames = new StringBuilder();
//Retrieving file names after deletion gives unexpected results
@@ -127,7 +140,7 @@ public class DeleteFileDialogFragment extends DialogFragment {
// NOTE: Use Toasts, not Snackbars. When sharing to another application snackbars
// would not show up!
Toast.makeText(getActivity(), getActivity().getString(R.string.file_delete_successful,
- deleteUris.length - failedFileNameList.size(), deleteUris.length, failedFileNames.toString()),
+ deleteUris.size() - failedFileNameList.size(), deleteUris.size(), failedFileNames.toString()),
Toast.LENGTH_LONG).show();
if (onDeletedListener != null) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
index 947c316e0..4eb253825 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
@@ -50,7 +50,6 @@ import org.sufficientlysecure.keychain.util.Passphrase;
public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
private static final String ARG_MESSENGER = "messenger";
private static final String ARG_TITLE = "title";
- private static final String ARG_OLD_PASSPHRASE = "old_passphrase";
public static final int MESSAGE_OKAY = 1;
@@ -68,12 +67,11 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
* @param messenger to communicate back after setting the passphrase
* @return
*/
- public static SetPassphraseDialogFragment newInstance(Messenger messenger, Passphrase oldPassphrase, int title) {
+ public static SetPassphraseDialogFragment newInstance(Messenger messenger, int title) {
SetPassphraseDialogFragment frag = new SetPassphraseDialogFragment();
Bundle args = new Bundle();
args.putInt(ARG_TITLE, title);
args.putParcelable(ARG_MESSENGER, messenger);
- args.putParcelable(ARG_OLD_PASSPHRASE, oldPassphrase);
frag.setArguments(args);
@@ -89,7 +87,6 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
int title = getArguments().getInt(ARG_TITLE);
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
- Passphrase oldPassphrase = getArguments().getParcelable(ARG_OLD_PASSPHRASE);
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
@@ -103,13 +100,6 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
mPassphraseAgainEditText = (EditText) view.findViewById(R.id.passphrase_passphrase_again);
mNoPassphraseCheckBox = (CheckBox) view.findViewById(R.id.passphrase_no_passphrase);
-
- if (oldPassphrase.isEmpty()) {
- mNoPassphraseCheckBox.setChecked(true);
- mPassphraseEditText.setEnabled(false);
- mPassphraseAgainEditText.setEnabled(false);
- }
-
mNoPassphraseCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java
index ac7dff9bd..0767aabd2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java
@@ -27,6 +27,7 @@ import org.sufficientlysecure.keychain.pgp.linked.LinkedIdentity;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment.ServiceType;
import org.sufficientlysecure.keychain.ui.util.Notify;
@@ -186,7 +187,7 @@ public abstract class LinkedIdCreateFinalFragment extends Fragment {
}
- private void certifyLinkedIdentity (Passphrase passphrase) {
+ private void certifyLinkedIdentity (CryptoInputParcel cryptoInput) {
ServiceProgressHandler saveHandler = new ServiceProgressHandler(
getActivity(),
getString(R.string.progress_saving),
@@ -235,7 +236,7 @@ public abstract class LinkedIdCreateFinalFragment extends Fragment {
// fill values for this action
Bundle data = new Bundle();
- data.putParcelable(KeychainIntentService.EDIT_KEYRING_PASSPHRASE, passphrase);
+ data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
data.putParcelable(KeychainIntentService.EDIT_KEYRING_PARCEL, skp);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@@ -257,9 +258,9 @@ public abstract class LinkedIdCreateFinalFragment extends Fragment {
switch (requestCode) {
case REQUEST_CODE_PASSPHRASE:
if (resultCode == Activity.RESULT_OK && data != null) {
- Passphrase passphrase =
- data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
- certifyLinkedIdentity(passphrase);
+ CryptoInputParcel cryptoInput =
+ data.getParcelableExtra(PassphraseDialogActivity.RESULT_CRYPTO_INPUT);
+ certifyLinkedIdentity(cryptoInput);
}
break;
default:
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java
index 0ef63f724..1944146dd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java
@@ -1,7 +1,7 @@
package org.sufficientlysecure.keychain.ui.linked;
import java.io.IOException;
-import java.util.Arrays;
+import java.util.Collections;
import android.animation.ObjectAnimator;
import android.app.Activity;
@@ -47,6 +47,7 @@ import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyActio
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
@@ -86,6 +87,7 @@ public class LinkedIdViewFragment extends Fragment implements
private ViewHolder mViewHolder;
private int mLidRank;
private OnIdentityLoadedListener mIdLoadedListener;
+ private long mCertifyKeyId;
public static LinkedIdViewFragment newInstance(Uri dataUri, int rank,
boolean isSecret, byte[] fingerprint) throws IOException {
@@ -183,7 +185,7 @@ public class LinkedIdViewFragment extends Fragment implements
}
public interface OnIdentityLoadedListener {
- public void onIdentityLoaded();
+ void onIdentityLoaded();
}
public void setOnIdentityLoadedListener(OnIdentityLoadedListener listener) {
@@ -500,8 +502,8 @@ public class LinkedIdViewFragment extends Fragment implements
}
// get the user's passphrase for this key (if required)
- long certifyKeyId = mViewHolder.vKeySpinner.getSelectedItemId();
- if (certifyKeyId == key.none || certifyKeyId == key.symmetric) {
+ mCertifyKeyId = mViewHolder.vKeySpinner.getSelectedItemId();
+ if (mCertifyKeyId == key.none || mCertifyKeyId == key.symmetric) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
SubtleAttentionSeeker.tint(mViewHolder.vKeySpinnerContainer, 600).start();
} else {
@@ -513,7 +515,7 @@ public class LinkedIdViewFragment extends Fragment implements
Passphrase passphrase;
try {
passphrase = PassphraseCacheService.getCachedPassphrase(
- getActivity(), certifyKeyId, certifyKeyId);
+ getActivity(), mCertifyKeyId, mCertifyKeyId);
} catch (PassphraseCacheService.KeyNotFoundException e) {
Log.e(Constants.TAG, "Key not found!", e);
getActivity().finish();
@@ -521,11 +523,11 @@ public class LinkedIdViewFragment extends Fragment implements
}
if (passphrase == null) {
Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class);
- intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, certifyKeyId);
+ intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, mCertifyKeyId);
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
// bail out; need to wait until the user has entered the passphrase before trying again
} else {
- certifyResource(certifyKeyId, "");
+ certifyResource(new CryptoInputParcel());
}
}
@@ -534,13 +536,9 @@ public class LinkedIdViewFragment extends Fragment implements
switch (requestCode) {
case REQUEST_CODE_PASSPHRASE: {
if (resultCode == Activity.RESULT_OK && data != null) {
- String passphrase = data.getStringExtra(
- PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
- long certifyKeyId = data.getLongExtra(PassphraseDialogActivity.EXTRA_KEY_ID, 0L);
- if (certifyKeyId == 0L) {
- throw new AssertionError("key id must not be 0");
- }
- certifyResource(certifyKeyId, passphrase);
+ CryptoInputParcel cryptoInput = data.getParcelableExtra(
+ PassphraseDialogActivity.RESULT_CRYPTO_INPUT);
+ certifyResource(cryptoInput);
}
return;
}
@@ -551,7 +549,7 @@ public class LinkedIdViewFragment extends Fragment implements
}
}
- private void certifyResource(long certifyKeyId, String passphrase) {
+ private void certifyResource(CryptoInputParcel cryptoInput) {
if (mIsSecret) {
return;
@@ -564,13 +562,15 @@ public class LinkedIdViewFragment extends Fragment implements
long masterKeyId = KeyFormattingUtils.convertFingerprintToKeyId(mFingerprint);
CertifyAction action = new CertifyAction(masterKeyId, null,
- Arrays.asList(mLinkedId.toUserAttribute()));
+ Collections.singletonList(mLinkedId.toUserAttribute()));
// fill values for this action
- CertifyActionsParcel parcel = new CertifyActionsParcel(certifyKeyId);
- parcel.mCertifyActions.addAll(Arrays.asList(action));
-
+ CertifyActionsParcel parcel = new CertifyActionsParcel(mCertifyKeyId);
+ parcel.mCertifyActions.addAll(Collections.singletonList(action));
data.putParcelable(KeychainIntentService.CERTIFY_PARCEL, parcel);
+
+ data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
+
/* if (mUploadKeyCheckbox.isChecked()) {
String keyserver = Preferences.getPreferences(getActivity()).getPreferredKeyserver();
data.putString(KeychainIntentService.UPLOAD_KEY_SERVER, keyserver);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
index 57a71b084..aaf127614 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
@@ -216,7 +216,15 @@ public class KeyFormattingUtils {
* @return
*/
public static String convertFingerprintToHex(byte[] fingerprint) {
- return Hex.toHexString(fingerprint).toLowerCase(Locale.ENGLISH);
+ return Hex.toHexString(fingerprint, 0, 20).toLowerCase(Locale.ENGLISH);
+ }
+
+ public static long getKeyIdFromFingerprint(byte[] fingerprint) {
+ ByteBuffer buf = ByteBuffer.wrap(fingerprint);
+ // skip first 12 bytes of the fingerprint
+ buf.position(12);
+ // the last eight bytes are the key id (big endian, which is default order in ByteBuffer)
+ return buf.getLong();
}
/**
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java
deleted file mode 100644
index c1955f75b..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.util;
-
-import android.annotation.SuppressLint;
-import android.app.Activity;
-
-import org.spongycastle.bcpg.CompressionAlgorithmTags;
-import org.spongycastle.bcpg.HashAlgorithmTags;
-import org.spongycastle.openpgp.PGPEncryptedData;
-import org.sufficientlysecure.keychain.R;
-
-import java.util.HashMap;
-
-@SuppressLint("UseSparseArrays")
-public class AlgorithmNames {
- Activity mActivity;
-
- HashMap<Integer, String> mEncryptionNames = new HashMap<>();
- HashMap<Integer, String> mHashNames = new HashMap<>();
- HashMap<Integer, String> mCompressionNames = new HashMap<>();
-
- public AlgorithmNames(Activity context) {
- super();
- this.mActivity = context;
-
- mEncryptionNames.put(PGPEncryptedData.AES_128, "AES-128");
- mEncryptionNames.put(PGPEncryptedData.AES_192, "AES-192");
- mEncryptionNames.put(PGPEncryptedData.AES_256, "AES-256");
- mEncryptionNames.put(PGPEncryptedData.BLOWFISH, "Blowfish");
- mEncryptionNames.put(PGPEncryptedData.TWOFISH, "Twofish");
- mEncryptionNames.put(PGPEncryptedData.CAST5, "CAST5");
- mEncryptionNames.put(PGPEncryptedData.DES, "DES");
- mEncryptionNames.put(PGPEncryptedData.TRIPLE_DES, "Triple DES");
- mEncryptionNames.put(PGPEncryptedData.IDEA, "IDEA");
-
- mHashNames.put(HashAlgorithmTags.RIPEMD160, "RIPEMD-160");
- mHashNames.put(HashAlgorithmTags.SHA1, "SHA-1");
- mHashNames.put(HashAlgorithmTags.SHA224, "SHA-224");
- mHashNames.put(HashAlgorithmTags.SHA256, "SHA-256");
- mHashNames.put(HashAlgorithmTags.SHA384, "SHA-384");
- mHashNames.put(HashAlgorithmTags.SHA512, "SHA-512");
-
- mCompressionNames.put(CompressionAlgorithmTags.UNCOMPRESSED, mActivity.getString(R.string.choice_none)
- + " (" + mActivity.getString(R.string.compression_fast) + ")");
- mCompressionNames.put(CompressionAlgorithmTags.ZIP,
- "ZIP (" + mActivity.getString(R.string.compression_fast) + ")");
- mCompressionNames.put(CompressionAlgorithmTags.ZLIB,
- "ZLIB (" + mActivity.getString(R.string.compression_fast) + ")");
- mCompressionNames.put(CompressionAlgorithmTags.BZIP2,
- "BZIP2 (" + mActivity.getString(R.string.compression_very_slow) + ")");
- }
-
- public HashMap<Integer, String> getEncryptionNames() {
- return mEncryptionNames;
- }
-
- public void setEncryptionNames(HashMap<Integer, String> encryptionNames) {
- this.mEncryptionNames = encryptionNames;
- }
-
- public HashMap<Integer, String> getHashNames() {
- return mHashNames;
- }
-
- public void setHashNames(HashMap<Integer, String> hashNames) {
- this.mHashNames = hashNames;
- }
-
- public HashMap<Integer, String> getCompressionNames() {
- return mCompressionNames;
- }
-
- public void setCompressionNames(HashMap<Integer, String> compressionNames) {
- this.mCompressionNames = compressionNames;
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
index c782d2507..609288bf1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
@@ -220,15 +220,14 @@ public class ContactHelper {
*/
public static long getMainProfileContactId(ContentResolver resolver) {
Cursor profileCursor = resolver.query(ContactsContract.Profile.CONTENT_URI,
- new String[]{ ContactsContract.Profile._ID}, null, null, null);
+ new String[]{ContactsContract.Profile._ID}, null, null, null);
- if(profileCursor != null && profileCursor.getCount() != 0 && profileCursor.moveToNext()) {
+ if (profileCursor != null && profileCursor.getCount() != 0 && profileCursor.moveToNext()) {
long contactId = profileCursor.getLong(0);
profileCursor.close();
return contactId;
- }
- else {
- if(profileCursor != null) {
+ } else {
+ if (profileCursor != null) {
profileCursor.close();
}
return -1;
@@ -330,7 +329,9 @@ public class ContactHelper {
ContactsContract.RawContacts.SOURCE_ID + "=? AND " +
ContactsContract.RawContacts.DELETED + "=?",
new String[]{//"0" for "not deleted"
- Constants.ACCOUNT_TYPE, Long.toString(masterKeyId), "0"
+ Constants.ACCOUNT_TYPE,
+ Long.toString(masterKeyId),
+ "0"
}, null);
if (raw != null) {
if (raw.moveToNext()) {
@@ -385,23 +386,37 @@ public class ContactHelper {
return null;
}
try {
- long rawContactId = findRawContactId(contentResolver, masterKeyId);
- if (rawContactId == -1) {
- return null;
- }
- Uri rawContactUri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId);
- Uri contactUri = ContactsContract.RawContacts.getContactLookupUri(contentResolver, rawContactUri);
- InputStream photoInputStream =
- ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, contactUri, highRes);
- if (photoInputStream == null) {
- return null;
- }
- return BitmapFactory.decodeStream(photoInputStream);
+ long contactId = findContactId(contentResolver, masterKeyId);
+ return loadPhotoByContactId(contentResolver, contactId, highRes);
+
} catch (Throwable ignored) {
return null;
}
}
+ public static Bitmap loadPhotoByContactId(ContentResolver contentResolver, long contactId,
+ boolean highRes) {
+ if (contactId == -1) {
+ return null;
+ }
+ Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
+ // older android versions (tested on API level 15) fail on lookupuris being passed to
+ // openContactPhotoInputStream
+ // http://stackoverflow.com/a/21214524/3000919
+ // Uri lookupUri = ContactsContract.Contacts.getLookupUri(contentResolver, contactUri);
+ // Also, we don't need a permanent shortcut to the contact since we load it afresh each time
+
+ InputStream photoInputStream = ContactsContract.Contacts.openContactPhotoInputStream(
+ contentResolver,
+ contactUri,
+ highRes);
+
+ if (photoInputStream == null) {
+ return null;
+ }
+ return BitmapFactory.decodeStream(photoInputStream);
+ }
+
public static final String[] KEYS_TO_CONTACT_PROJECTION = new String[]{
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.KeyRings.USER_ID,
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/DatabaseUtil.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/DatabaseUtil.java
index c18e5cabd..93b6a5697 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/DatabaseUtil.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/DatabaseUtil.java
@@ -1,3 +1,20 @@
+/*
+ * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
package org.sufficientlysecure.keychain.util;
import android.text.TextUtils;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FabContainer.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FabContainer.java
index 116b98d1e..ffc0484f7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FabContainer.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FabContainer.java
@@ -1,3 +1,20 @@
+/*
+ * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
package org.sufficientlysecure.keychain.util;
public interface FabContainer {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java
index 943b913d7..3bbd86d6a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java
@@ -57,7 +57,7 @@ public class KeyUpdateHelper {
Bundle importData = new Bundle();
importData.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST,
new ArrayList<ImportKeysListEntry>(keys));
- importIntent.putExtra(KeychainIntentService.EXTRA_DATA, importData);
+ importIntent.putExtra(KeychainIntentService.EXTRA_SERVICE_INTENT, importData);
importIntent.putExtra(KeychainIntentService.EXTRA_MESSENGER, new Messenger(mHandler));
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java
index e4e4e4d05..2b47fd623 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java
@@ -191,9 +191,6 @@ public class NfcHelper {
mNfcAdapter.invokeBeam(mActivity);
}
- /**
- * A static subclass of {@link Handler} with a {@link WeakReference} to an {@link Activity} to avoid memory leaks.
- */
private static class NfcHandler extends Handler {
private final WeakReference<Activity> mActivityReference;
@@ -203,12 +200,10 @@ public class NfcHelper {
@Override
public void handleMessage(Message msg) {
- Activity activity = mActivityReference.get();
-
- if (activity != null) {
+ if (mActivityReference.get() != null) {
switch (msg.what) {
case NFC_SENT:
- Notify.create(activity, R.string.nfc_successful, Notify.Style.OK).show();
+ Notify.create(mActivityReference.get(), R.string.nfc_successful, Notify.Style.OK).show();
break;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableCache.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableCache.java
new file mode 100644
index 000000000..75bdee00a
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableCache.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.util;
+
+import android.os.Parcel;
+
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * If Parcelables are above 1 MB, Android OS fails to send them via the Binder IPC:
+ * JavaBinder E !!! FAILED BINDER TRANSACTION !!!
+ * To overcome this issue this class allows to cache Parcelables, mapped by unique UUIDs,
+ * which are written to the parcel instead of the whole Parcelable.
+ */
+public class ParcelableCache<E> {
+
+ private static final UUID NULL_UUID = new UUID(0, 0);
+
+ /**
+ * A HashMap of UUID:Object
+ * This is used such that when we become parceled, we are
+ * well below the 1 MB boundary that is specified.
+ */
+ private ConcurrentHashMap<UUID, E> objectCache = new ConcurrentHashMap<>();
+
+ /**
+ * Dehydrate a Parcelable (such that it is available after deparcelization)
+ * Returns the NULL uuid (0) if you hand it null.
+ *
+ * @param parcelable A Parcelable to dehydrate
+ * @return a UUID, the ticket for your dehydrated Parcelable
+ */
+ private UUID dehydrateParcelable(E parcelable) {
+ if (parcelable == null) {
+ return NULL_UUID;
+ } else {
+ UUID uuid = UUID.randomUUID();
+ objectCache.put(uuid, parcelable);
+ return uuid;
+ }
+ }
+
+ /**
+ * Rehydrate a Parcelable after going through parcelization,
+ * invalidating its place in the dehydration pool.
+ * This is used such that when parcelized, the Parcelable is no larger than 1 MB.
+ *
+ * @param uuid A UUID ticket that identifies the log in question.
+ * @return An OperationLog.
+ */
+ private E rehydrateParcelable(UUID uuid) {
+ // UUID.equals isn't well documented; we use compareTo instead.
+ if (NULL_UUID.compareTo(uuid) == 0) {
+ return null;
+ } else {
+ E parcelable = objectCache.get(uuid);
+ objectCache.remove(uuid);
+ return parcelable;
+ }
+ }
+
+ public E readFromParcelAndGetFromCache(Parcel source) {
+ long mostSig = source.readLong();
+ long leastSig = source.readLong();
+ UUID mTicket = new UUID(mostSig, leastSig);
+ // fetch the dehydrated parcelable out of storage (this removes it from the dehydration pool)
+ return rehydrateParcelable(mTicket);
+ }
+
+ public void cacheAndWriteToParcel(E parcelable, Parcel dest) {
+ // Get a ticket for our parcelable.
+ UUID mTicket = dehydrateParcelable(parcelable);
+ // And write out the UUID most and least significant bits.
+ dest.writeLong(mTicket.getMostSignificantBits());
+ dest.writeLong(mTicket.getLeastSignificantBits());
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
index 44c1e6b6c..8a7638054 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
@@ -109,21 +109,21 @@ public class Preferences {
return mSharedPreferences.getBoolean(Constants.Pref.FIRST_TIME, true);
}
- public boolean useDefaultYubikeyPin() {
+ public boolean useDefaultYubiKeyPin() {
return mSharedPreferences.getBoolean(Pref.USE_DEFAULT_YUBIKEY_PIN, false);
}
- public void setUseDefaultYubikeyPin(boolean useDefaultYubikeyPin) {
+ public void setUseDefaultYubiKeyPin(boolean useDefaultYubikeyPin) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(Pref.USE_DEFAULT_YUBIKEY_PIN, useDefaultYubikeyPin);
editor.commit();
}
- public boolean useNumKeypadForYubikeyPin() {
+ public boolean useNumKeypadForYubiKeyPin() {
return mSharedPreferences.getBoolean(Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN, true);
}
- public void setUseNumKeypadForYubikeyPin(boolean useNumKeypadForYubikeyPin) {
+ public void setUseNumKeypadForYubiKeyPin(boolean useNumKeypadForYubikeyPin) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN, useNumKeypadForYubikeyPin);
editor.commit();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ProgressFixedScaler.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ProgressFixedScaler.java
index 4bb4ca5de..861298f56 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ProgressFixedScaler.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ProgressFixedScaler.java
@@ -1,3 +1,20 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
package org.sufficientlysecure.keychain.util;
import org.sufficientlysecure.keychain.pgp.Progressable;
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/yubi_icon.png b/OpenKeychain/src/main/res/drawable-hdpi/yubi_icon.png
new file mode 100644
index 000000000..428ad6fad
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/yubi_icon.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/yubi_icon_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/yubi_icon_24dp.png
new file mode 100644
index 000000000..6fb41223d
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/yubi_icon_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/yubi_icon.png b/OpenKeychain/src/main/res/drawable-mdpi/yubi_icon.png
new file mode 100644
index 000000000..05c21c052
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/yubi_icon.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/yubi_icon_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/yubi_icon_24dp.png
new file mode 100644
index 000000000..753f22607
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/yubi_icon_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/yubi_icon.png b/OpenKeychain/src/main/res/drawable-xhdpi/yubi_icon.png
new file mode 100644
index 000000000..cfa799e74
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/yubi_icon.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/yubi_icon_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/yubi_icon_24dp.png
new file mode 100644
index 000000000..05c21c052
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/yubi_icon_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/yubi_icon.png b/OpenKeychain/src/main/res/drawable-xxhdpi/yubi_icon.png
new file mode 100644
index 000000000..f20f562ec
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/yubi_icon.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/yubi_icon_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/yubi_icon_24dp.png
new file mode 100644
index 000000000..9bae15a02
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/yubi_icon_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/yubi_icon_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/yubi_icon_24dp.png
new file mode 100644
index 000000000..cfa799e74
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/yubi_icon_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/layout/create_key_start_fragment.xml b/OpenKeychain/src/main/res/layout/create_key_start_fragment.xml
index 79ffe58b1..2db147475 100644
--- a/OpenKeychain/src/main/res/layout/create_key_start_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/create_key_start_fragment.xml
@@ -50,22 +50,22 @@
android:clickable="true"
style="?android:attr/borderlessButtonStyle" />
- <!--<TextView-->
- <!--android:id="@+id/create_key_yubikey_button"-->
- <!--android:paddingLeft="16dp"-->
- <!--android:paddingRight="16dp"-->
- <!--android:textAppearance="?android:attr/textAppearanceMedium"-->
- <!--android:layout_width="match_parent"-->
- <!--android:layout_height="wrap_content"-->
- <!--android:layout_weight="1"-->
- <!--android:text="@string/first_time_yubikey"-->
- <!--android:textAllCaps="true"-->
- <!--android:minHeight="?android:attr/listPreferredItemHeight"-->
- <!--android:drawableRight="@drawable/ic_chevron_right_grey_24dp"-->
- <!--android:drawablePadding="8dp"-->
- <!--android:gravity="right|center_vertical"-->
- <!--android:clickable="true"-->
- <!--style="?android:attr/borderlessButtonStyle" />-->
+ <TextView
+ android:id="@+id/create_key_yubikey_button"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/first_time_yubikey"
+ android:textAllCaps="true"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:drawableRight="@drawable/ic_chevron_right_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="right|center_vertical"
+ android:clickable="true"
+ style="?android:attr/borderlessButtonStyle" />
<TextView
android:id="@+id/create_key_import_button"
@@ -101,4 +101,4 @@
android:clickable="true"
style="?android:attr/borderlessButtonStyle" />
</LinearLayout>
-</RelativeLayout> \ No newline at end of file
+</RelativeLayout>
diff --git a/OpenKeychain/src/main/res/layout/create_yubikey_import_fragment.xml b/OpenKeychain/src/main/res/layout/create_yubikey_import_fragment.xml
new file mode 100644
index 000000000..e70188e49
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/create_yubikey_import_fragment.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="4dp"
+ android:orientation="horizontal"
+ android:id="@+id/yubikey_status_layout" >
+
+ <ImageView
+ android:layout_margin="14dp"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:scaleType="centerCrop"
+ android:src="@drawable/yubi_icon"/>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/yubikey_serno"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="Yubikey #"
+ />
+
+ <TextView
+ android:id="@+id/yubikey_userid"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="User ID"
+ />
+
+ <TextView
+ android:id="@+id/yubikey_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="Unknown key, hit next to import"
+ />
+
+ </LinearLayout>
+
+ <ImageButton
+ android:id="@+id/button_search"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:padding="8dp"
+ android:src="@drawable/ic_search_grey_24dp"
+ android:layout_gravity="center_vertical"
+ android:background="?android:selectableItemBackground" />
+
+ </LinearLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_marginTop="4dp"
+ android:layout_height="1dip"
+ android:layout_below="@id/yubikey_status_layout"
+ android:background="?android:attr/listDivider" />
+
+ <FrameLayout
+ android:id="@+id/yubikey_import_fragment"
+ android:layout_marginTop="8dp"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/yubikey_status_layout"
+ android:layout_above="@id/create_key_buttons"
+ />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:background="@color/holo_gray_bright"
+ android:id="@+id/create_key_buttons">
+
+ <TextView
+ android:id="@+id/create_key_back_button"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_back"
+ android:textAllCaps="true"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:drawableLeft="@drawable/ic_chevron_left_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="left|center_vertical"
+ android:clickable="true"
+ style="?android:attr/borderlessButtonStyle" />
+
+ <TextView
+ android:id="@+id/create_key_next_button"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_import"
+ android:textAllCaps="true"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:drawableRight="@drawable/ic_key_plus_grey600_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="right|center_vertical"
+ android:clickable="true"
+ style="?android:attr/borderlessButtonStyle" />
+
+ </LinearLayout>
+
+</RelativeLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/create_yubikey_wait_fragment.xml b/OpenKeychain/src/main/res/layout/create_yubikey_wait_fragment.xml
new file mode 100644
index 000000000..c7f9821eb
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/create_yubikey_wait_fragment.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true"
+ android:layout_above="@+id/create_key_buttons">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:layout_marginLeft="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="Hold Yubikey against device dawg"
+ />
+
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:src="@drawable/yubikey_phone" />
+
+ </LinearLayout>
+
+ </ScrollView>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:background="@color/holo_gray_bright"
+ android:id="@+id/create_key_buttons">
+
+ <TextView
+ android:id="@+id/create_key_back_button"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_back"
+ android:textAllCaps="true"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:drawableLeft="@drawable/ic_chevron_left_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="left|center_vertical"
+ android:clickable="true"
+ style="?android:attr/borderlessButtonStyle" />
+
+ <TextView
+ android:id="@+id/create_key_next_button"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_next"
+ android:textAllCaps="true"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:drawableRight="@drawable/yubi_icon_24dp"
+ android:drawablePadding="16dp"
+ android:gravity="right|center_vertical"
+ android:clickable="false"
+ style="?android:attr/borderlessButtonStyle" />
+
+ </LinearLayout>
+
+</RelativeLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml b/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml
index fb01a5ef0..1d0873c96 100644
--- a/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@@ -11,7 +12,8 @@
android:id="@+id/decrypt_text_valid"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical">
+ android:orientation="vertical"
+ tools:visibility="visible">
<ScrollView
android:fillViewport="true"
@@ -86,12 +88,12 @@
</LinearLayout>
<LinearLayout
- android:visibility="gone"
android:id="@+id/decrypt_text_invalid"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
- android:gravity="center_vertical">
+ android:gravity="center_vertical"
+ android:visibility="gone">
<TextView
android:layout_width="wrap_content"
diff --git a/OpenKeychain/src/main/res/layout/encrypt_files_activity.xml b/OpenKeychain/src/main/res/layout/encrypt_files_activity.xml
index ce8b1302c..435ea96df 100644
--- a/OpenKeychain/src/main/res/layout/encrypt_files_activity.xml
+++ b/OpenKeychain/src/main/res/layout/encrypt_files_activity.xml
@@ -23,14 +23,12 @@
<include layout="@layout/notify_area" />
<FrameLayout
- android:id="@+id/encrypt_pager_mode"
+ android:id="@+id/encrypt_mode_container"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" />
+ android:layout_height="wrap_content" />
- <fragment
- android:id="@+id/encrypt_file_fragment"
- android:name="org.sufficientlysecure.keychain.ui.EncryptFilesFragment"
+ <FrameLayout
+ android:id="@+id/encrypt_file_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
diff --git a/OpenKeychain/src/main/res/layout/encrypt_files_fragment.xml b/OpenKeychain/src/main/res/layout/encrypt_files_fragment.xml
index 029e735b3..b75ec5022 100644
--- a/OpenKeychain/src/main/res/layout/encrypt_files_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/encrypt_files_fragment.xml
@@ -1,18 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
+ android:layout_height="match_parent"
android:orientation="vertical">
- <ListView
+ <android.support.v7.widget.RecyclerView
android:id="@+id/selected_files_list"
- android:dividerHeight="4dip"
- android:divider="@android:color/transparent"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:layout_marginTop="8dp"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
diff --git a/OpenKeychain/src/main/res/layout/encrypt_text_activity.xml b/OpenKeychain/src/main/res/layout/encrypt_text_activity.xml
index 809e64f02..64ce50b74 100644
--- a/OpenKeychain/src/main/res/layout/encrypt_text_activity.xml
+++ b/OpenKeychain/src/main/res/layout/encrypt_text_activity.xml
@@ -23,14 +23,12 @@
<include layout="@layout/notify_area" />
<FrameLayout
- android:id="@+id/encrypt_pager_mode"
+ android:id="@+id/encrypt_mode_container"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" />
+ android:layout_height="wrap_content" />
- <fragment
- android:id="@+id/encrypt_text_fragment"
- android:name="org.sufficientlysecure.keychain.ui.EncryptTextFragment"
+ <FrameLayout
+ android:id="@+id/encrypt_text_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
diff --git a/OpenKeychain/src/main/res/layout/file_list_entry.xml b/OpenKeychain/src/main/res/layout/file_list_entry.xml
index ca78ad161..7f0e1e89e 100644
--- a/OpenKeychain/src/main/res/layout/file_list_entry.xml
+++ b/OpenKeychain/src/main/res/layout/file_list_entry.xml
@@ -1,60 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
-
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="48dip"
- android:background="@drawable/attachment_bg_holo">
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="48dip"
+ android:background="@drawable/attachment_bg_holo">
<ImageView
- android:id="@+id/thumbnail"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:scaleType="center"
- android:layout_width="48dip"
- android:layout_height="48dip"/>
+ android:id="@+id/thumbnail"
+ android:layout_alignParentLeft="true"
+ android:layout_centerVertical="true"
+ android:scaleType="center"
+ android:layout_width="48dip"
+ android:layout_height="48dip" />
<LinearLayout
- android:orientation="vertical"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@+id/thumbnail"
- android:layout_centerVertical="true">
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@+id/thumbnail"
+ android:layout_centerVertical="true">
<TextView
- android:id="@+id/filename"
- android:layout_marginLeft="8dip"
- android:layout_marginRight="32dip"
- android:maxLines="1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="?android:attr/textColorSecondary"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:ellipsize="end"/>
+ android:id="@+id/filename"
+ android:layout_marginLeft="8dip"
+ android:layout_marginRight="32dip"
+ android:maxLines="1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:ellipsize="end" />
<TextView
- android:id="@+id/filesize"
- android:layout_marginLeft="8dip"
- android:layout_marginRight="32dip"
- android:maxLines="1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="?android:attr/textColorTertiary"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textSize="12sp"
- android:ellipsize="end"/>
+ android:id="@+id/filesize"
+ android:layout_marginLeft="8dip"
+ android:layout_marginRight="32dip"
+ android:maxLines="1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="?android:attr/textColorTertiary"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textSize="12sp"
+ android:ellipsize="end" />
</LinearLayout>
<ImageButton
- android:id="@+id/action_remove_file_from_list"
- android:layout_width="48dip"
- android:layout_height="48dip"
- android:layout_alignParentRight="true"
- android:paddingRight="16dip"
- android:paddingLeft="16dip"
- android:src="@drawable/ic_close_grey_24dp"
- android:clickable="true"
- android:layout_centerVertical="true"
- android:background="?android:selectableItemBackground"/>
+ android:id="@+id/action_remove_file_from_list"
+ android:layout_width="48dip"
+ android:layout_height="48dip"
+ android:layout_alignParentRight="true"
+ android:paddingRight="16dip"
+ android:paddingLeft="16dip"
+ android:src="@drawable/ic_close_grey_24dp"
+ android:clickable="true"
+ android:layout_centerVertical="true"
+ android:background="?android:selectableItemBackground" />
</RelativeLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/file_list_entry_add.xml b/OpenKeychain/src/main/res/layout/file_list_entry_add.xml
index d7f4513d9..e5eb4c44f 100644
--- a/OpenKeychain/src/main/res/layout/file_list_entry_add.xml
+++ b/OpenKeychain/src/main/res/layout/file_list_entry_add.xml
@@ -1,21 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:padding="4dp"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:clickable="true"
- android:minHeight="?android:attr/listPreferredItemHeight"
- style="?android:attr/borderlessButtonStyle">
+ android:minHeight="16dp"
+ android:orientation="horizontal"
+ android:singleLine="true">
- <TextView
+ <Button
+ android:id="@+id/file_list_entry_add"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
android:layout_gravity="center"
android:text="@string/btn_add_files"
+ style="?android:attr/borderlessButtonStyle"
android:drawableLeft="@drawable/ic_folder_grey_24dp"
- android:drawablePadding="8dp"
- android:gravity="center" />
-</FrameLayout> \ No newline at end of file
+ android:drawablePadding="16dp"
+ android:gravity="left|center_vertical" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/passphrase_dialog.xml b/OpenKeychain/src/main/res/layout/passphrase_dialog.xml
index d2e85633f..a2e6af27c 100644
--- a/OpenKeychain/src/main/res/layout/passphrase_dialog.xml
+++ b/OpenKeychain/src/main/res/layout/passphrase_dialog.xml
@@ -26,7 +26,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
- android:layout_marginBottom="8dp"
android:imeOptions="actionDone"
android:hint="@string/label_passphrase"
android:ems="10"
diff --git a/OpenKeychain/src/main/res/layout/view_key_fragment.xml b/OpenKeychain/src/main/res/layout/view_key_fragment.xml
index f842f764d..58b4b3d0f 100644
--- a/OpenKeychain/src/main/res/layout/view_key_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/view_key_fragment.xml
@@ -98,6 +98,7 @@
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:visibility="gone"
card_view:cardBackgroundColor="@android:color/white"
card_view:cardElevation="2dp"
card_view:cardUseCompatPadding="true"
diff --git a/OpenKeychain/src/main/res/layout/view_key_yubikey.xml b/OpenKeychain/src/main/res/layout/view_key_yubikey.xml
new file mode 100644
index 000000000..83272ef4e
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/view_key_yubikey.xml
@@ -0,0 +1,103 @@
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:card_view="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp">
+
+ <android.support.v7.widget.CardView
+ android:id="@+id/card_view"
+ android:layout_gravity="center"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:transitionName="card"
+ card_view:cardBackgroundColor="@android:color/white"
+ card_view:cardElevation="2dp"
+ card_view:cardUseCompatPadding="true"
+ card_view:cardCornerRadius="4dp"
+ android:animateLayoutChanges="true">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ style="@style/CardViewHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/section_yubikey"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:layout_margin="14dp"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:scaleType="centerCrop"
+ android:src="@drawable/yubi_icon"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/yubikey_serno"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="Yubikey #"
+ />
+
+ <TextView
+ android:id="@+id/yubikey_userid"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="User ID"
+ />
+
+ <TextView
+ android:id="@+id/yubikey_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="Key matches!"
+ />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <Button
+ android:id="@+id/button_bind"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right|end"
+ android:text="@string/button_bind_key"
+ android:textColor="@color/link_text_material_light"
+ style="?android:attr/borderlessButtonStyle"
+ android:visibility="gone"
+ />
+
+ </LinearLayout>
+
+ </android.support.v7.widget.CardView>
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml b/OpenKeychain/src/main/res/menu/encrypt_file_fragment.xml
index d6ed726fa..d6ed726fa 100644
--- a/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml
+++ b/OpenKeychain/src/main/res/menu/encrypt_file_fragment.xml
diff --git a/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml b/OpenKeychain/src/main/res/menu/encrypt_text_fragment.xml
index 5a262fdd8..5a262fdd8 100644
--- a/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml
+++ b/OpenKeychain/src/main/res/menu/encrypt_text_fragment.xml
diff --git a/OpenKeychain/src/main/res/raw-bg/help_about.md b/OpenKeychain/src/main/res/raw-bg/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-bg/help_about.md
+++ b/OpenKeychain/src/main/res/raw-bg/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-bg/help_certification.md b/OpenKeychain/src/main/res/raw-bg/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-bg/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-bg/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-bg/help_changelog.md b/OpenKeychain/src/main/res/raw-bg/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-bg/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-bg/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-bg/help_start.md b/OpenKeychain/src/main/res/raw-bg/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-bg/help_start.md
+++ b/OpenKeychain/src/main/res/raw-bg/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-cs/help_about.md b/OpenKeychain/src/main/res/raw-cs/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-cs/help_about.md
+++ b/OpenKeychain/src/main/res/raw-cs/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-cs/help_certification.md b/OpenKeychain/src/main/res/raw-cs/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-cs/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-cs/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-cs/help_changelog.md b/OpenKeychain/src/main/res/raw-cs/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-cs/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-cs/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-cs/help_start.md b/OpenKeychain/src/main/res/raw-cs/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-cs/help_start.md
+++ b/OpenKeychain/src/main/res/raw-cs/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-de/help_about.md b/OpenKeychain/src/main/res/raw-de/help_about.md
index d6a8eca93..ec2501ee6 100644
--- a/OpenKeychain/src/main/res/raw-de/help_about.md
+++ b/OpenKeychain/src/main/res/raw-de/help_about.md
@@ -1,12 +1,13 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
-[OpenKeychain](http://www.openkeychain.org) is an OpenPGP implementation for Android.
+[OpenKeychain](http://www.openkeychain.org) ist eine OpenPGP-Implementierung für Android.
-License: GPLv3+
+Lizenz: GPLv3+
-## Developers
- * Dominik Schürmann (Maintainer)
+## Entwickler
+ * Dominik Schürmann (Leitender Entwickler)
* Art O Cathain
* Ash Hughes
* Brian C. Barnes
@@ -27,19 +28,19 @@ License: GPLv3+
* Tim Bray
* Vincent Breitmoser
-## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
- * [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
- * [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
- * [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
- * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design)</a> (Apache License v2)
- * [MaterialNavigationDrawer](https://github.com/neokree/MaterialNavigationDrawer) (Apache License v2)
- * [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/dschuermann/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+## Bibliotheken
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11-Lizenz)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT-Lizenz)
+ * [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache-Lizenz v2)
+ * [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache-Lizenz v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache-Lizenz v2)
+ * [MiniDNS](https://github.com/rtreffer/minidns) (Apache-Lizenz v2)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache-Lizenz v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache-Lizenz v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache-Lizenz v2)
+ * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material-Design)</a> (Apache-Lizenz v2)
+ * [MaterialNavigationDrawer](https://github.com/neokree/MaterialNavigationDrawer) (Apache-Lizenz v2)
+ * [Snackbar](https://github.com/nispok/snackbar) (MIT-Lizenz)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache-Lizenz v2)
+ * [HtmlTextView](https://github.com/dschuermann/html-textview) (Apache-Lizenz v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache-Lizenz v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-de/help_certification.md b/OpenKeychain/src/main/res/raw-de/help_certification.md
index 8da27e8e0..5089301f3 100644
--- a/OpenKeychain/src/main/res/raw-de/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-de/help_certification.md
@@ -1,10 +1,11 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-## Key Confirmation
+## Schlüsselbestätigung
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
-## Key Status
+## Schlüsselstatus
<img src="status_signature_verified_cutout_24dp"/>
Confirmed: You have already confirmed this key, e.g., by scanning the QR Code.
@@ -15,7 +16,7 @@ Expired: This key is no longer valid. Only the owner can extend its validity.
<img src="status_signature_revoked_cutout_24dp"/>
Revoked: This key is no longer valid. It has been revoked by its owner.
-## Advanced Information
+## Erweiterte Informationen
A "key confirmation" in OpenKeychain is implemented by creating a certification according to the OpenPGP standard.
This certification is a ["generic certification (0x10)"](http://tools.ietf.org/html/rfc4880#section-5.2.1) described in the standard by:
"The issuer of this certification does not make any particular assertion as to how well the certifier has checked that the owner of the key is in fact the person described by the User ID."
diff --git a/OpenKeychain/src/main/res/raw-de/help_changelog.md b/OpenKeychain/src/main/res/raw-de/help_changelog.md
index e9d61d0f3..cd0a47f45 100644
--- a/OpenKeychain/src/main/res/raw-de/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-de/help_changelog.md
@@ -1,11 +1,12 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
- * Material design
- * Integration of QR Scanner (New permissions required)
- * Improved key creation wizard
- * Fix missing contacts after sync
- * Requires Android 4
+ * Material-Design
+ * QR-Scanner-Integration (benötigt neue Berechtigungen)
+ * Schlüsselerzeugungsassistent verbessert
+ * Fehlende Kontakte nach Synchronisierung behoben
+ * Benötigt Android 4
* Redesigned key screen
* Simplify crypto preferences, better selection of secure ciphers
* API: Detached signatures, free selection of signing key,...
@@ -22,17 +23,17 @@
## 3.1.1
* Fix key export to files (they were written partially)
- * Fix crash on Android 2.3
+ * Absturz unter Android 2.3 behoben
## 3.1
- * Fix crash on Android 5
- * New certify screen
+ * Absturz unter Android 5 behoben
+ * Neuer Beglaubigungsbildschirm
* Secure Exchange directly from key list (SafeSlinger library)
- * New QR Code program flow
+ * Neuer Programmablauf für QR-Codes
* Redesigned decrypt screen
- * New icon usage and colors
+ * Verwendung neuer Symbole und Farben
* Fix import of secret keys from Symantec Encryption Desktop
* Subkey IDs on Yubikeys are now checked correctly
@@ -70,7 +71,7 @@
* Key sharing via SafeSlinger
* Yubikey: preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
* Fix usage of stripped keys
- * SHA256 as default for compatibility
+ * Standardmäßig SHA256 aufgrund von Kompatibilität
* Intent API has changed, see https://github.com/open-keychain/open-keychain/wiki/Intent-API
* OpenPGP API now handles revoked/expired keys and returns all user ids
@@ -78,7 +79,7 @@
## 2.9
* Fixing crashes introduced in v2.8
- * Experimental ECC support
+ * Experimentelle ECC-Unterstützung
* Experimental Yubikey support (signing-only with imported keys)
@@ -87,7 +88,7 @@
* So many bugs have been fixed in this release that we focus on the main new features
* Key edit: awesome new design, key revocation
* Key import: awesome new design, secure keyserver connections via hkps, keyserver resolving via DNS SRV records
- * New first time screen
+ * Neuer Bildschirm bei der ersten Öffnung
* New key creation screen: autocompletion of name and email based on your personal Android accounts
* File encryption: awesome new design, support for encrypting multiple files
* New icons to show status of key (by Brennan Novak)
@@ -95,15 +96,15 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
- * Purple! (Dominik, Vincent)
+ * Lila! (Dominik, Vincent)
* New key view design (Dominik, Vincent)
* New flat Android buttons (Dominik, Vincent)
- * API fixes (Dominik)
- * Keybase.io import (Tim Bray)
+ * API-Korrekturen (Dominik)
+ * Import aus keybase.io (Tim Bray)
## 2.6.1
@@ -116,7 +117,7 @@
* Key certifications (thanks to Vincent Breitmoser)
* Support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
* New design for signature verification
- * Custom key length (thanks to Greg Witczak)
+ * Benutzerdefinierte Schlüssellänge (Dank an Greg Witczak)
* Fix share-functionality from other apps
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
@@ -142,7 +143,7 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
* Keyserver query based on machine-readable output
* Lock navigation drawer on tablets
* Suggestions for emails on creation of keys
- * Search in public key lists
+ * Suchen in öffentlichen Schlüssellisten
* And much more improvements and fixes…
@@ -168,7 +169,7 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
* New design with navigation drawer
* New public key list design
- * New public key view
+ * Neue Ansicht für öffentliche Schlüssel
* Bug fixes for importing of keys
* Key cross-certification (thanks to Ash Hughes)
* Handle UTF-8 passwords properly (thanks to Ash Hughes)
@@ -185,7 +186,7 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
## 2.1
* Lots of bug fixes
- * New API for developers
+ * Neue API für Entwickler
* PRNG bug fix by Google
@@ -193,20 +194,20 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
* Complete redesign
* Share public keys via QR codes, NFC beam
- * Sign keys
- * Upload keys to server
+ * Schlüssel unterschreiben
+ * Schlüssel auf den Server hochladen
* Fixes import issues
- * New AIDL API
+ * Neue AIDL-API
## 1.0.8
- * Basic keyserver support
+ * Grundlegende Schlüsselserverunterstützung
* App2sd
* More choices for passphrase cache: 1, 2, 4, 8, hours
* Translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
- * Bugfixes
- * Optimizations
+ * Fehlerbehebungen
+ * Optimierungen
## 1.0.7
@@ -218,19 +219,19 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
## 1.0.6
* Account adding crash on Froyo fixed
- * Secure file deletion
+ * Sichere Dateilöschung
* Option to delete key file after import
- * Stream encryption/decryption (gallery, etc.)
+ * Streamverschlüsselung/-entschlüsselung (Galerie, usw.)
* New options (language, force v3 signatures)
- * Interface changes
- * Bugfixes
+ * Oberflächenänderungen
+ * Fehlerbehebungen
## 1.0.5
- * German and Italian translation
+ * Deutsche und Italienische Übersetzung
* Much smaller package, due to reduced BC sources
- * New preferences GUI
+ * Neues Einstellungen-Benutzeroberfläche
* Layout adjustment for localization
* Signature bugfix
@@ -247,7 +248,7 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
## 1.0.2
- * Filterable key lists
+ * Filterbare Schlüsselliste
* Smarter pre-selection of encryption keys
* New Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
* Fixes and additional features (key preselection) for K-9 Mail, new beta build available
@@ -261,8 +262,8 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
## 1.0.0
* K-9 Mail integration, APG supporting beta build of K-9 Mail
- * Support of more file managers (including ASTRO)
- * Slovenian translation
- * New database, much faster, less memory usage
+ * Unterstützung von mehr Dateimanagern (einschließlich ASTRO)
+ * Slowenische Übersetzung
+ * Neue Datenbank, viel schneller, weniger Speicherbelegung
* Defined Intents and content provider for other apps
- * Bugfixes \ No newline at end of file
+ * Fehlerbehebungen \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-de/help_start.md b/OpenKeychain/src/main/res/raw-de/help_start.md
index 1641f913b..b51aebf62 100644
--- a/OpenKeychain/src/main/res/raw-de/help_start.md
+++ b/OpenKeychain/src/main/res/raw-de/help_start.md
@@ -1,15 +1,16 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-## How do I activate OpenKeychain in K-9 Mail?
-To use OpenKeychain with K-9 Mail, you want to follow these steps:
+## Wie kann ich OpenKeychain in K-9 Mail nutzen?
+Um OpenKeychain mit K-9 Mail zu nutzen, bitte folgenden Schritten folgen:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
- 3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
+ 3. Klick auf "OpenPGP Provider" und OpenKeychain in der Liste auswählen.
-## I found a bug in OpenKeychain!
+## Ich habe einen Fehler in OpenKeychail gefunden!
Please report the bug using the [issue tracker of OpenKeychain](https://github.com/openpgp-keychain/openpgp-keychain/issues).
-## Contribute
+## Unterstützen
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
-## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+## Übersetzungen
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-es/help_about.md b/OpenKeychain/src/main/res/raw-es/help_about.md
index 0435b2d5b..bb925e6bd 100644
--- a/OpenKeychain/src/main/res/raw-es/help_about.md
+++ b/OpenKeychain/src/main/res/raw-es/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTA: ¡Por favor ponga cada frase en su propia línea, Transifex pone cada línea en su propio campo de traducción!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-es/help_certification.md b/OpenKeychain/src/main/res/raw-es/help_certification.md
index 55e821498..412c13826 100644
--- a/OpenKeychain/src/main/res/raw-es/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-es/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTA: ¡Por favor ponga cada frase en su propia línea, Transifex pone cada línea en su propio campo de traducción!)
## Confirmación de clave
Sin confirmación, no puede estar seguro de si una clave corresponde realmente a una persona específica.
-La forma más simple de confirmar una clave es escanear el código QR o intercambiarlo vía NFC.
+La forma más sencilla de confirmar una clave es escaneando el código QR o intercambiándolo vía NFC.
Para confirmar claves entre más de dos personas, sugerimos usar el método de intercambio de claves disponible para sus claves.
## Estado de la clave
diff --git a/OpenKeychain/src/main/res/raw-es/help_changelog.md b/OpenKeychain/src/main/res/raw-es/help_changelog.md
index 753da969e..7c4367594 100644
--- a/OpenKeychain/src/main/res/raw-es/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-es/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTA: ¡Por favor ponga cada frase en su propia línea, Transifex pone cada línea en su propio campo de traducción!)
## 3.2beta2
@@ -8,10 +9,10 @@
* Requiere Android 4
* Pantalla de clave rediseñada
* Simplifica las preferencias de criptografía, mejor selección de algoritmos de cifrado seguro
- * API: Firmas desacopladas, selección libre de clave de firmado...
+ * API: Firmas desacopladas, selección libre de clave de firmado,...
* Reparación: Algunas claves válidas se mostraron revocadas o caducadas
* No acepte algo firmado por subclaves caducadas o revocadas
- * Soporte Keybase.io en la vista avanzada
+ * Soporte para Keybase.io en la vista avanzada
## 3.1.2
@@ -22,19 +23,19 @@
## 3.1.1
* Repara la exportación de claves a ficheros (se escribían parcialmente)
- * Repara un fallo con caída en Android 2.3
+ * Repara una caída en Android 2.3
## 3.1
- * Repara un fallo con caída en Android 5
+ * Repara una caída en Android 5
* Nueva pantalla de certificación
* Intercambio seguro directamente desde la lista de claves (librería SafeSlinger)
- * Nuevo control de flujo del programa QR Code
+ * Nuevo control de flujo del programa para código QR
* Pantalla de descifrado rediseñada
- * Nuevo uso del icono y colores
- * Repara la importación de clave secretas (privadas) desde Symantec Encryption Desktop
- * Las identificaciones de subclaves sobre Yubikeys ahora están comprobadas correctamente
+ * Nuevo uso y colores del icono
+ * Repara la importación de claves secretas (privadas) desde Symantec Encryption Desktop
+ * Las identificaciones de subclaves en Yubikeys ahora se comprueban correctamente
## 3.0.1
@@ -46,223 +47,223 @@
## 3.0
* ¡Soporte completo para generación de firma y descifrado de Yubikey!
- * Propose installable compatible apps in apps list
- * New design for decryption screens
- * Many fixes for key import, also fixes stripped keys
- * Honor and display key authenticate flags
- * User interface to generate custom keys
- * Fixing user id revocation certificates
- * New cloud search (searches over traditional keyservers and keybase.io)
- * Support for stripping keys inside OpenKeychain
+ * Propone aplicaciones instalables compatibles en la lista de aplicaciones
+ * Nuevo diseño para pantallas de descifrado
+ * Muchas reparaciones para la importación de claves, también repara claves desnudas
+ * Respeta y muestra los distintivos de autentificación de claves
+ * Interfaz de usuario para generar claves personalizadas
+ * Repara certificados de revocación de identificación de usuario
+ * Nueva búsqueda en la nube (busca sobre servidores de claves tradicionales y keybase.io)
+ * Soporte para desvestir claves dentro de OpenKeychain
## 2.9.2
- * Fix keys broken in 2.9.1
- * Yubikey decryption now working via API
+ * Repara claves rotas en la versión 2.9.1
+ * El descifrado de Yubikey ahora funciona vía API
## 2.9.1
- * Split encrypt screen into two
- * Fix key flags handling (now supporting Mailvelope 0.7 keys)
- * Improved passphrase handling
- * Key sharing via SafeSlinger
- * Yubikey: preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
- * Fix usage of stripped keys
- * SHA256 as default for compatibility
- * Intent API has changed, see https://github.com/open-keychain/open-keychain/wiki/Intent-API
- * OpenPGP API now handles revoked/expired keys and returns all user ids
+ * Divide en dos la pantalla de cifrado
+ * Repara el manejo de los indicativos de claves (ahora soporta claves de Mailvelope 0.7)
+ * Manejo de frase-contraseña mejorado
+ * Compartición de claves vía SafeSlinger
+ * Yubikey: Preferencia para permitir otros PINs, actualmente sólo funciona firmando mediante la API de OpenPGP, no dentro de OpenKeychain
+ * Repara el uso de claves desnudas
+ * SHA256 por defecto para compatibilidad
+ * La API de Intent ha cambiado, vea https://github.com/open-keychain/open-keychain/wiki/Intent-API
+ * La API de OpenPGP ahora maneja claves revocadas/caducadas y devuelve todas las identificaciones de usuario
## 2.9
- * Fixing crashes introduced in v2.8
- * Experimental ECC support
- * Experimental Yubikey support (signing-only with imported keys)
+ * Repara caídas introducidas en la versión 2.8
+ * Soporte para ECC (criptografía de curva elíptica) experimental
+ * Soporte experimental para Yubikey (sólo-firmante con claves importadas)
## 2.8
- * So many bugs have been fixed in this release that we focus on the main new features
- * Key edit: awesome new design, key revocation
- * Key import: awesome new design, secure keyserver connections via hkps, keyserver resolving via DNS SRV records
- * New first time screen
- * New key creation screen: autocompletion of name and email based on your personal Android accounts
- * File encryption: awesome new design, support for encrypting multiple files
- * New icons to show status of key (by Brennan Novak)
- * Important bug fix: Importing of large key collections from a file is now possible
- * Notification showing cached passphrases
- * Keys are connected to Android's contacts
+ * Han sido reparados tantos fallos en esta versión que nos centramos en las nuevas características principales
+ * Edición de clave: Un estupendo diseño nuevo, revocación de clave
+ * Importación de clave: Un estupendo diseño nuevo, conexiones seguras a servidor de claves vía hkps (protocolo seguro HTTP de servidor de claves), servidor de claves resolviendo vía registros DNS SRV
+ * Nueva pantalla de primera vez
+ * Nueva pantalla de creación de clave: Autocompletado del nombre y correo electrónico basados en sus cuentas de Android personales
+ * Cifrado de ficheros: Un estupendo diseño nuevo, soporte para cifrar múltiples ficheros
+ * Nuevos iconos para mostrar el estado de la clave (por Brennan Novak)
+ * Reparación de un fallo importante: La importación de colecciones de claves largas desde un fichero ahora es posible
+ * Notificación mostrando frases-contraseña en caché
+ * Las claves están conectadas a los contactos de Android
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+Esta versión no sería posible sin el trabajo de Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
- * Purple! (Dominik, Vincent)
- * New key view design (Dominik, Vincent)
- * New flat Android buttons (Dominik, Vincent)
- * API fixes (Dominik)
- * Keybase.io import (Tim Bray)
+ * ¡Púrpura! (Dominik, Vincent)
+ * Nuevo diseño de vista de clave (Dominik, Vincent)
+ * Nuevos botones planos de Android (Dominik, Vincent)
+ * Reparaciones de la API (Dominik)
+ * Importación desde Keybase.io (Tim Bray)
## 2.6.1
- * Some fixes for regression bugs
+ * Algunas reparaciones para fallos regresivos
## 2.6
- * Key certifications (thanks to Vincent Breitmoser)
- * Support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
- * New design for signature verification
- * Custom key length (thanks to Greg Witczak)
- * Fix share-functionality from other apps
+ * Certificaciones de clave (gracias a Vincent Breitmoser)
+ * Soporte para claves secretas (privadas) parciales de GnuPG (gracias a Vincent Breitmoser)
+ * Nuevo diseño para verificación de firma
+ * Tamaño de clave personalizado (gracias a Greg Witczak)
+ * Repara la funcionalidad-compartida desde otras aplicaciones
## 2.5
- * Fix decryption of symmetric OpenPGP messages/files
- * Refactored key edit screen (thanks to Ash Hughes)
- * New modern design for encrypt/decrypt screens
- * OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
+ * Repara el descifrado de mensajes/ficheros de OpenPGP simétricos
+ * Pantalla de edición de clave refactorizada (gracias a Ash Hughes)
+ * Nuevo diseño moderno para pantallas de cifrado/descifrado
+ * API de OpenPGP versión 3 (múltiples cuentas API, reparaciones internas, búsqueda de claves)
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
-Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
-
- * New unified key list
- * Colorized key fingerprint
- * Support for keyserver ports
- * Deactivate possibility to generate weak keys
- * Much more internal work on the API
- * Certify user ids
- * Keyserver query based on machine-readable output
- * Lock navigation drawer on tablets
- * Suggestions for emails on creation of keys
- * Search in public key lists
- * And much more improvements and fixes…
+¡Gracias a todos los interesados del Google Summer of Code 2014 que hicieron posible esta versión rica en características y libre de fallos!
+Además de varios parches de seguridad pequeños, un número notable de parches fueron elaborados por las siguientes personas (en orden alfabético):
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
+
+ * Nueva lista de claves unificada
+ * Huella de validación de clave (fingerprint) coloreada
+ * Soporte para puertos de servidor de claves
+ * Desactivar la posibilidad de generar claves débiles
+ * Mucho más trabajo interno en la API
+ * Certificar identificaciones de usuario
+ * Petición al servidor de claves basada en salida legible-por-máquina
+ * Bloquea la bandeja deslizante de navegación en tabletas
+ * Sugerencias sobre creación de claves para correos electrónicos
+ * Buscar en listas de claves públicas
+ * Y muchas más mejoras y reparaciones...
## 2.3.1
- * Hotfix for crash when upgrading from old versions
+ * Reparación urgente para caída al actualizar desde versiones antiguas
## 2.3
- * Remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
- * Fix setting expiry dates on keys (thanks to Ash Hughes)
- * More internal fixes when editing keys (thanks to Ash Hughes)
- * Querying keyservers directly from the import screen
- * Fix layout and dialog style on Android 2.2-3.0
- * Fix crash on keys with empty user ids
- * Fix crash and empty lists when coming back from signing screen
- * Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
- * Fix upload of key from signing screen
+ * Elimina la exportación innecesaria de claves públicas al exportar la clave secreta (privada) (gracias a Ash Hughes)
+ * Repara la configuración de fechas de caducidad sobre claves (gracias a Ash Hughes)
+ * Más reparaciones internas al editar claves (gracias a Ash Hughes)
+ * Realiza peticiones directamente a los servidores de claves desde la pantalla de importación
+ * Repara la disposición y estilo del cuadro de diálogo en Android 2.2-3.0
+ * Repara caída en claves con identificaciones de usuario vacías
+ * Repara caída y listas vacías al volver de la pantalla de firmado
+ * Bouncy Castle (librería de criptografía) actualizada desde la versión 1.47 a la 1.50 y compilada desde el código fuente
+ * Repara la subida de clave desde la pantalla de firmado
## 2.2
- * New design with navigation drawer
- * New public key list design
- * New public key view
- * Bug fixes for importing of keys
- * Key cross-certification (thanks to Ash Hughes)
- * Handle UTF-8 passwords properly (thanks to Ash Hughes)
- * First version with new languages (thanks to the contributors on Transifex)
- * Sharing of keys via QR Codes fixed and improved
- * Package signature verification for API
+ * Nuevo diseño con bandeja deslizante de navegación
+ * Nuevo diseño de lista de claves públicas
+ * Nueva vista de clave pública
+ * Reparaciones de fallos para la importación de claves
+ * Certificación-cruzada de claves (gracias a Ash Hughes)
+ * Maneja contraseñas UTF-8 de forma adecuada (gracias a Ash Hughes)
+ * Primera versión con nuevos idiomas (gracias a los contribuidores en Transifex)
+ * Compartición de claves mediante códigos QR reparada y mejorada
+ * Verificación de firmas de paquetes para la API
## 2.1.1
- * API Updates, preparation for K-9 Mail integration
+ * Actualizaciones de la API, preparación para la integración de K-9 Mail
## 2.1
- * Lots of bug fixes
- * New API for developers
- * PRNG bug fix by Google
+ * Muchas reparaciones de fallos
+ * Nueva API para desarrolladores
+ * Reparación de fallo de PRNG (generador de números pseudoaleatorios) por Google
## 2.0
- * Complete redesign
- * Share public keys via QR codes, NFC beam
- * Sign keys
- * Upload keys to server
- * Fixes import issues
- * New AIDL API
+ * Rediseño completo
+ * Comparte claves públicas mediante códigos QR, y NFC
+ * Firma de claves
+ * Subida de claves al servidor
+ * Repara problemas de importación
+ * Nueva API de AIDL (lenguaje de definición de interfaz Android)
## 1.0.8
- * Basic keyserver support
+ * Soporte para servidor de claves básico
* App2sd
- * More choices for passphrase cache: 1, 2, 4, 8, hours
- * Translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
- * Bugfixes
- * Optimizations
+ * Más opciones para la caché de frase-contraseña: 1,2,4,8 horas
+ * Traducciones: Noruego (gracias, Sander Danielsen), Chino (gracias, Zhang Fredrick)
+ * Reparaciones de fallos
+ * Optimizaciones
## 1.0.7
- * Fixed problem with signature verification of texts with trailing newline
- * More options for passphrase cache time to live (20, 40, 60 mins)
+ * Reparado problema con la verificación de firma de textos con un salto de línea al final
+ * Más opciones para el tiempo de vida de la caché de frase-contraseña (20, 40, 60 minutos)
## 1.0.6
- * Account adding crash on Froyo fixed
- * Secure file deletion
- * Option to delete key file after import
- * Stream encryption/decryption (gallery, etc.)
- * New options (language, force v3 signatures)
- * Interface changes
- * Bugfixes
+ * Reparada caída al añadir cuenta en Froyo
+ * Borrado seguro de fichero
+ * Opción para borrar el fichero de clave después de importar
+ * Cifrado/Descifrado de stream (flujo de datos) (galería, etc.)
+ * Nuevas opciones (idioma, forzado de firmas v3)
+ * Cambios en la interfaz
+ * Reparaciones de fallos
## 1.0.5
- * German and Italian translation
- * Much smaller package, due to reduced BC sources
- * New preferences GUI
- * Layout adjustment for localization
- * Signature bugfix
+ * Traducción al alemán y al italiano
+ * Paquete mucho más pequeño, debido al código fuente reducido de Bouncy Castle (BC)
+ * Interfaz gráfica (GUI) de nuevas preferencias
+ * Ajuste de la distribución para localización
+ * Reparación de fallo de firma
## 1.0.4
- * Fixed another crash caused by some SDK bug with query builder
+ * Reparada otra caída causada por algún fallo del SDK con el constructor de peticiones
## 1.0.3
- * Fixed crashes during encryption/signing and possibly key export
+ * Reparadas caídas durante el cifrado/firmado y posible exportación de clave
## 1.0.2
- * Filterable key lists
- * Smarter pre-selection of encryption keys
- * New Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
- * Fixes and additional features (key preselection) for K-9 Mail, new beta build available
+ * Listas de claves filtrables
+ * Pre-selección más inteligente de claves de cifrado
+ * Nuevo manejo de Intent para VIEW y SEND (ver y enviar), permite que los ficheros sean cifrados/descifrados fuera de los administradores de ficheros
+ * Reparaciones y características adicionales (preselección de clave) para K-9 Mail, nueva versión beta disponible
## 1.0.1
- * GMail account listing was broken in 1.0.0, fixed again
+ * El listado de cuenta de GMail se estropeó en la versión 1.0.0, reparado de nuevo
## 1.0.0
- * K-9 Mail integration, APG supporting beta build of K-9 Mail
- * Support of more file managers (including ASTRO)
- * Slovenian translation
- * New database, much faster, less memory usage
- * Defined Intents and content provider for other apps
- * Bugfixes \ No newline at end of file
+ * Integración de K-9 Mail, APG (Android Privacy Guard) soportando la versión beta de K-9 Mail
+ * Soporte para más administradores de ficheros (incluyendo ASTRO)
+ * Traducción al esloveno
+ * Nueva base de datos, mucho más rápida, menos uso de memoria
+ * Definidos Intents y el proveedor de contenido para otras aplicaciones
+ * Reparaciones de fallos \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-es/help_start.md b/OpenKeychain/src/main/res/raw-es/help_start.md
index e8786003c..b304ce39b 100644
--- a/OpenKeychain/src/main/res/raw-es/help_start.md
+++ b/OpenKeychain/src/main/res/raw-es/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTA: ¡Por favor ponga cada frase en su propia línea, Transifex pone cada línea en su propio campo de traducción!)
## ¿Cómo activo OpenKeychain en K-9 Mail?
Para usar OpenKeychain con K-9 Mail, deberá seguir estos pasos:
1. Abra K-9 Mail y realice una pulsación larga sobre la cuenta con la que quiera usar OpenKeychain.
- 2. Seleccione "Configuración de cuenta", desplácese hasta el fondo y pulse "Criptografía".
+ 2. Seleccione "Configuración de cuenta", desplácese hasta el fondo y pulse "Criptografía"
3. Haga clic sobre "Proveedor OpenPGP" y seleccione OpenKeychain de la lista.
## ¡Encontré un fallo en OpenKeychain!
@@ -12,4 +13,4 @@ Por favor informe del fallo usando el [rastreador de fallos de OpenKeychain](htt
Si quiere ayudarnos a desarrollar OpenKeychain contribuyendo con código [siga nuestra pequeña guía en GitHub](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Traducciones
-¡Ayude a traducir OpenKeychain! Todos pueden participar en [OpenKeychain en Transifex] (https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+¡Ayude a traducir OpenKeychain! Todos pueden participar en [OpenKeychain en Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-et/help_about.md b/OpenKeychain/src/main/res/raw-et/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-et/help_about.md
+++ b/OpenKeychain/src/main/res/raw-et/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-et/help_certification.md b/OpenKeychain/src/main/res/raw-et/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-et/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-et/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-et/help_changelog.md b/OpenKeychain/src/main/res/raw-et/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-et/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-et/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-et/help_start.md b/OpenKeychain/src/main/res/raw-et/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-et/help_start.md
+++ b/OpenKeychain/src/main/res/raw-et/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-eu/help_about.md b/OpenKeychain/src/main/res/raw-eu/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-eu/help_about.md
+++ b/OpenKeychain/src/main/res/raw-eu/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-eu/help_certification.md b/OpenKeychain/src/main/res/raw-eu/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-eu/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-eu/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-eu/help_changelog.md b/OpenKeychain/src/main/res/raw-eu/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-eu/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-eu/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-eu/help_start.md b/OpenKeychain/src/main/res/raw-eu/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-eu/help_start.md
+++ b/OpenKeychain/src/main/res/raw-eu/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-fi/help_about.md b/OpenKeychain/src/main/res/raw-fi/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-fi/help_about.md
+++ b/OpenKeychain/src/main/res/raw-fi/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-fi/help_certification.md b/OpenKeychain/src/main/res/raw-fi/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-fi/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-fi/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-fi/help_changelog.md b/OpenKeychain/src/main/res/raw-fi/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-fi/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-fi/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-fi/help_start.md b/OpenKeychain/src/main/res/raw-fi/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-fi/help_start.md
+++ b/OpenKeychain/src/main/res/raw-fi/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-fr/help_about.md b/OpenKeychain/src/main/res/raw-fr/help_about.md
index 1ff60b089..edf3dd78d 100644
--- a/OpenKeychain/src/main/res/raw-fr/help_about.md
+++ b/OpenKeychain/src/main/res/raw-fr/help_about.md
@@ -1,3 +1,4 @@
+[//] : # (NOTE : veuillez mettre chaque phrase dans sa propre ligne. Transifex met chaque ligne dans son propre champ de traduction !)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-fr/help_certification.md b/OpenKeychain/src/main/res/raw-fr/help_certification.md
index 965215a54..643756bcf 100644
--- a/OpenKeychain/src/main/res/raw-fr/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-fr/help_certification.md
@@ -1,3 +1,4 @@
+[//] : # (NOTE : veuillez mettre chaque phrase dans sa propre ligne. Transifex met chaque ligne dans son propre champ de traduction !)
## Confirmation de clef
Sans confirmation, vous ne pouvez pas être certain que la clef appartient à une personne déterminée.
diff --git a/OpenKeychain/src/main/res/raw-fr/help_changelog.md b/OpenKeychain/src/main/res/raw-fr/help_changelog.md
index e9d61d0f3..9682bacae 100644
--- a/OpenKeychain/src/main/res/raw-fr/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-fr/help_changelog.md
@@ -1,268 +1,269 @@
+[//] : # (NOTE : veuillez mettre chaque phrase sur sa propre ligne. Transifex met chaque ligne dans son propre champ de traduction !)
## 3.2beta2
- * Material design
- * Integration of QR Scanner (New permissions required)
- * Improved key creation wizard
- * Fix missing contacts after sync
- * Requires Android 4
- * Redesigned key screen
- * Simplify crypto preferences, better selection of secure ciphers
- * API: Detached signatures, free selection of signing key,...
- * Fix: Some valid keys were shown revoked or expired
- * Don't accept signatures by expired or revoked subkeys
- * Keybase.io support in advanced view
+ * Conception matérielle
+ * Intégration du lecteur QR (nouvelles permissions exigées)
+ * Amélioration de l'assistant de création de clef
+ * Correctif - Contacts manquants après la synchro
+ * Android 4 exigé
+ * Nouvelle conception de l'écran des clefs
+ * Simplification des préférences cryptographiques, meilleure sélection de codes de chiffrement sécurisés
+ * API : signatures détachées, sélection libre de la clef de signature...
+ * Correctif - Certaines clefs valides apparaissaient comme révoquées ou expirées
+ * Ne pas accepter de signatures par des sous-clefs expirées ou révoquées
+ * Prise en charge de keybase.io dans la vue avancée
## 3.1.2
- * Fix key export to files (now for real)
+ * Correctif - Exportation des clefs vers des fichiers (vraiment, maintenant)
## 3.1.1
- * Fix key export to files (they were written partially)
- * Fix crash on Android 2.3
+ * Correctif - Exportation des clefs vers des fichiers (elles n'étaient écrites que partiellement)
+ * Correctif - Plantage sur Android 2.3
## 3.1
- * Fix crash on Android 5
- * New certify screen
- * Secure Exchange directly from key list (SafeSlinger library)
- * New QR Code program flow
- * Redesigned decrypt screen
- * New icon usage and colors
- * Fix import of secret keys from Symantec Encryption Desktop
- * Subkey IDs on Yubikeys are now checked correctly
+ * Correctif - Plantage sur Android 5
+ * Nouvel écran de certification
+ * Échange sécurisé directement de la liste des clefs (bibliothèque SafeSlinger)
+ * Nouveau flux de programme pour les codes QR
+ * Écran de déchiffrement redessiné
+ * Nouveaux agencement et couleurs d'icônes
+ * Importation des clefs secrètes corrigée de Symantec Encryption Desktop
+ * Les ID de sous-clefs des Yubikeys sont maintenant vérifiés correctement
## 3.0.1
- * Better handling of large key imports
- * Improved subkey selection
+ * Meilleure gestion de l'importation de nombreuses clefs
+ * Sélection des sous-clefs améliorée
## 3.0
- * Full support for Yubikey signature generation and decryption!
- * Propose installable compatible apps in apps list
- * New design for decryption screens
- * Many fixes for key import, also fixes stripped keys
- * Honor and display key authenticate flags
- * User interface to generate custom keys
- * Fixing user id revocation certificates
- * New cloud search (searches over traditional keyservers and keybase.io)
- * Support for stripping keys inside OpenKeychain
+ * Prise en charge complète de la génération de signature par Yubikey et de leur déchiffrement !
+ * Des applis compatibles installables sont proposées dans la liste des applis
+ * Nouvelle conception pour les écrans de déchiffrement
+ * Nombreux correctifs d'importation des clefs, corrigent aussi les clefs dépouillées
+ * Accepter et afficher les drapeaux d'authentification des clefs
+ * Interface utilisateur pour générer des clefs personnalisées
+ * Corrigé - Certificats de révocation des ID utilisateurs
+ * Nouvelle recherche nuagique (dans les serveurs traditionnels et dans keybase.io)
+ * Prise en charge du dépouillement des clefs dans OpenKeychain
## 2.9.2
- * Fix keys broken in 2.9.1
- * Yubikey decryption now working via API
+ * Correctif - Clefs brisées dans 2.9.1
+ * Le déchiffrement des Yukukeys par l'API fonctionne maintenant
## 2.9.1
- * Split encrypt screen into two
- * Fix key flags handling (now supporting Mailvelope 0.7 keys)
- * Improved passphrase handling
- * Key sharing via SafeSlinger
- * Yubikey: preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
- * Fix usage of stripped keys
- * SHA256 as default for compatibility
- * Intent API has changed, see https://github.com/open-keychain/open-keychain/wiki/Intent-API
- * OpenPGP API now handles revoked/expired keys and returns all user ids
+ * Partage de l'écran de chiffrement en deux
+ * Correctif - Gestion des drapeaux de clefs (prend maintenant en charge les clefs Mailvelope 0.7)
+ * Gestion des phrases de passe améliorée
+ * Partage de clefs par SafeSlinger
+ * Yubikey : préférence pour permette d'autre NIP, seule la signature par l'API OpenPGP fonctionne présentement, mais pas à l'intérieur d'OpenKeychain
+ * Correctif - Utilisation de clefs dépouillées
+ * SHA256 par défaut pour la compatibilité
+ * L'API des intentions a changé, voir https://github.com/open-keychain/open-keychain/wiki/Intent-API
+ * L'API d'OpenPGP gère maintenant les clefs révoquées/expirées et retourne tous les ID utilisateurs
## 2.9
- * Fixing crashes introduced in v2.8
- * Experimental ECC support
- * Experimental Yubikey support (signing-only with imported keys)
+ * Correction des plantages présents dans v2.8
+ * Prise en charge expérimentale CCE
+ * Prise en charge expérimentale de Yubikey (signature seulement avec les clefs importées)
## 2.8
- * So many bugs have been fixed in this release that we focus on the main new features
- * Key edit: awesome new design, key revocation
- * Key import: awesome new design, secure keyserver connections via hkps, keyserver resolving via DNS SRV records
- * New first time screen
- * New key creation screen: autocompletion of name and email based on your personal Android accounts
- * File encryption: awesome new design, support for encrypting multiple files
- * New icons to show status of key (by Brennan Novak)
- * Important bug fix: Importing of large key collections from a file is now possible
- * Notification showing cached passphrases
- * Keys are connected to Android's contacts
+ * Tellement de bogues ont été réglés dans cette version que nous nous concentrons sur les nouvelles caractéristiques principales.
+ * Modification des clefs : nouvelle et superbe conception, révocations des clefs
+ * Importation des clefs : nouvelle et superbe conception, connexion sécurisé aux serveurs de clefs par hkps, résolution des serveurs de clefs par transactions DNS SRV
+ * Nouvel écran de premier lancement
+ * Nouvel écran de création de clef : auto-remplissage du nom et du courriel d'après vos coordonnées Android
+ * Chiffrement des fichiers : nouvelle et superbe conception, prise en charge du chiffrement de fichiers multiples
+ * Nouvelles icônes d'état des clefs (par Brennan Novak)
+ * Correctif important de bogue : l'importation de grandes collections de clefs à partir d'un fichier est maintenant possible
+ * Notification montrant les phrases de passe en cache
+ * Les clefs sont connectées aux contacts d'Android
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+Cette version ne serait pas possible sans le travail de Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
- * Purple! (Dominik, Vincent)
- * New key view design (Dominik, Vincent)
- * New flat Android buttons (Dominik, Vincent)
- * API fixes (Dominik)
- * Keybase.io import (Tim Bray)
+ * Violet ! (Dominik, Vincent)
+ * Nouvelle présentation de la visualisation des clefs (Dominik, Vincent)
+ * Nouveaux boutons Android plats (Dominik, Vincent)
+ * Correctifs de l'API (Dominik)
+ * Importation de Keybase.io (Tim Bray)
## 2.6.1
- * Some fixes for regression bugs
+ * Quelques correctifs de bogues de régression
## 2.6
- * Key certifications (thanks to Vincent Breitmoser)
- * Support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
- * New design for signature verification
- * Custom key length (thanks to Greg Witczak)
- * Fix share-functionality from other apps
+ * Certifications des clefs (merci à Vincent Breitmoser)
+ * Prise en charge clefs secrètes partielles de GnuPG (merci à Vincent Breitmoser)
+ * Nouvelle conception de la vérification de signatures
+ * Longueur de clef personnalisée (merci à Greg Witczak)
+ * Correctif - Fonctionnalités partagées d'autres applis
## 2.5
- * Fix decryption of symmetric OpenPGP messages/files
- * Refactored key edit screen (thanks to Ash Hughes)
- * New modern design for encrypt/decrypt screens
- * OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
+ * Correctif - Déchiffrement des messages/fichiers symétriques OpenPGP
+ * Écran de modification des clefs remanié (merci à Ash Hughes)
+ * Nouvelle conception moderne pour les écrans de chiffrement/déchiffrement
+ * API OpenPGP version 3 (comptes multiples d'api, correctifs internes, recherche de clefs)
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
-Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
-
- * New unified key list
- * Colorized key fingerprint
- * Support for keyserver ports
- * Deactivate possibility to generate weak keys
- * Much more internal work on the API
- * Certify user ids
- * Keyserver query based on machine-readable output
- * Lock navigation drawer on tablets
- * Suggestions for emails on creation of keys
- * Search in public key lists
- * And much more improvements and fixes…
+Merci à tous les participants de « Google Summer of Code 2014 » qui ont rendu cette version riche en fonctions et sans bogue !
+À part plusieurs petits correctifs, un nombre notable de correctifs ont été apportés par les personnes suivantes (par ordre alphabétique) :
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
+
+ * Nouvelle liste de clefs unifiée
+ * Empreintes de clefs colorées
+ * Prise en charge des ports des serveurs de clefs
+ * Désactiver la possibilité de générer des clefs faibles
+ * Encore plus de travail interne dans l'API
+ * Certifier les ID utilisateurs
+ * Requêtes des serveurs de clefs basées sur des sorties assimilables par la machine
+ * Verrouiller les tiroirs de navigation sur les tablettes
+ * Suggestion de courriels à la création de clefs
+ * Rechercher dans les listes de clefs publiques
+ * Et bien plus d'améliorations et de correctifs
## 2.3.1
- * Hotfix for crash when upgrading from old versions
+ * Correctif d'urgence pour le plantage lors de la mise à niveau à partir d'anciennes versions
## 2.3
- * Remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
- * Fix setting expiry dates on keys (thanks to Ash Hughes)
- * More internal fixes when editing keys (thanks to Ash Hughes)
- * Querying keyservers directly from the import screen
- * Fix layout and dialog style on Android 2.2-3.0
- * Fix crash on keys with empty user ids
- * Fix crash and empty lists when coming back from signing screen
- * Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
- * Fix upload of key from signing screen
+ * Suppressions de l'exportation non nécessaire des clefs publiques lors de l'exportation de clefs secrètes (merci à Ash Hughes)
+ * Correctif - Définition de la date de péremption des clefs (merci à Ash Hughes)
+ * Plus de correctifs internes affectant la modifications des clefs (merci à Ash hughes)
+ * Interrogation des serveurs de clefs directement de l'écran d'importation
+ * Correctif - Mise en page et du style des fenêtres de dialogue sur Android 2.2-3.0
+ * Correctif - Plantage pour les clefs avec des ID utilisateur vides
+ * Correctif - Plantage et listes vides en revenant de l'écran de signature
+ * Bouncy Castle (bibliothèque cryptographique) mise à jour de 1.47 à 1.50 et compilée de la source
+ * Correctif - Téléversement d'une clef de l'écran de signature
## 2.2
- * New design with navigation drawer
- * New public key list design
- * New public key view
- * Bug fixes for importing of keys
- * Key cross-certification (thanks to Ash Hughes)
- * Handle UTF-8 passwords properly (thanks to Ash Hughes)
- * First version with new languages (thanks to the contributors on Transifex)
- * Sharing of keys via QR Codes fixed and improved
- * Package signature verification for API
+ * Nouvelle conception avec tiroir de navigation
+ * Nouvelle conception de la liste des clefs publics
+ * Nouvelle vue des clefs publics
+ * Correctif de bogues d'importation de clefs
+ * Certification croisée des clefs (merci à Ash Hughes)
+ * Bonne gestion des mots de passe UTF-8 (merci à Ash Hughes)
+ * Première version avec de nouvelles langues (merci aux contributeurs sur Transifex)
+ * Correctif et amélioration du partage de clefs par codes QR
+ * Vérification de la signature des paquets pour l'API
## 2.1.1
- * API Updates, preparation for K-9 Mail integration
+ * Mise à jour de l'API, préparation à l'intégration à K-9 Mail
## 2.1
- * Lots of bug fixes
- * New API for developers
- * PRNG bug fix by Google
+ * Beaucoup de bogues corrigés
+ * Nouvelle API pour les développeurs
+ * Correctif du blogue PRNG par Google
## 2.0
- * Complete redesign
- * Share public keys via QR codes, NFC beam
- * Sign keys
- * Upload keys to server
- * Fixes import issues
- * New AIDL API
+ * Conception complètement repensée
+ * Partage de clefs publiques par codes QR, faisceau NFC
+ * Signer les clefs
+ * Téléverser les clefs vers le serveur
+ * Corrige des problèmes d'importation
+ * Nouvelle API AIDL
## 1.0.8
- * Basic keyserver support
+ * Prise en charge de base du serveur de clefs
* App2sd
- * More choices for passphrase cache: 1, 2, 4, 8, hours
- * Translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
- * Bugfixes
- * Optimizations
+ * Plus de choix pour le cache de la phrase de passe : 1, 2, 4, 8 heures
+ * Traductions : norvégien (merci Sander Danielsen), chinois (merci Zhang Fredrick)
+ * Correctifs de bogues
+ * Optimisations
## 1.0.7
- * Fixed problem with signature verification of texts with trailing newline
- * More options for passphrase cache time to live (20, 40, 60 mins)
+ * Problème corrigé avec la vérification de la signature des textes se terminant par un retour à la ligne
+ * Plus de choix pour la durée de vie de la phrase de passe (20, 40, 60 min)
## 1.0.6
- * Account adding crash on Froyo fixed
- * Secure file deletion
- * Option to delete key file after import
- * Stream encryption/decryption (gallery, etc.)
- * New options (language, force v3 signatures)
- * Interface changes
- * Bugfixes
+ * Correctif - Plantage lors de l'ajout de compte sur Froyo
+ * Suppression sécurisée de fichiers
+ * Option de suppression du fichier de clef après l'importation
+ * Chiffrement/déchiffrement de flux (galerie, etc.)
+ * Nouvelles options (langue, forcer les signatures v3)
+ * Changements dans l'interface
+ * Correctifs de bogues
## 1.0.5
- * German and Italian translation
- * Much smaller package, due to reduced BC sources
- * New preferences GUI
- * Layout adjustment for localization
- * Signature bugfix
+ * Traduction allemande et italienne
+ * Paquet beaucoup plus petit grâce à des sources BC réduites
+ * Nouvelle IUG pour les préférences
+ * Ajustement de la mise en page pour les localisations
+ * Correctif de bogue de signature
## 1.0.4
- * Fixed another crash caused by some SDK bug with query builder
+ * Correction d'un autre plantage causé par quelque bogue SDK avec le constructeur de requêtes
## 1.0.3
- * Fixed crashes during encryption/signing and possibly key export
+ * Corrections de plantages durant le chiffrement/la signature et possiblement l'exportation de clefs
## 1.0.2
- * Filterable key lists
- * Smarter pre-selection of encryption keys
- * New Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
- * Fixes and additional features (key preselection) for K-9 Mail, new beta build available
+ * Listes de clefs filtrables
+ * Présélection plus intelligente des clefs de chiffrement
+ * Nouvelle gestion des intentions pour VIEW et SEND, permet le chiffrement/déchiffrement des fichiers du gestionnaires de fichiers
+ * Correctifs et fonctions additionnelles (présélection des clefs) pour K-9-Mail, nouvelle version bêta proposée
## 1.0.1
- * GMail account listing was broken in 1.0.0, fixed again
+ * Le listage des comptes Gmail ne fonctionnait pas dans 1.0.0, maintenant corrigé
## 1.0.0
- * K-9 Mail integration, APG supporting beta build of K-9 Mail
- * Support of more file managers (including ASTRO)
- * Slovenian translation
- * New database, much faster, less memory usage
- * Defined Intents and content provider for other apps
- * Bugfixes \ No newline at end of file
+ * Intégration à K-9 Mail, APG prenant en charge la version bêta de K-9 Mail
+ * Prise en charge de plus de gestionnaires de fichiers (incluant ASTRO)
+ * Traduction slovène
+ * Nouvelle base de données, bien plus rapide, utilisation de la mémoire moindre
+ * Intentions définies et fournisseur de contenu pour d'autres applis
+ * Correctifs de bogues \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-fr/help_start.md b/OpenKeychain/src/main/res/raw-fr/help_start.md
index c7a5cb744..7ac45cc88 100644
--- a/OpenKeychain/src/main/res/raw-fr/help_start.md
+++ b/OpenKeychain/src/main/res/raw-fr/help_start.md
@@ -1,3 +1,4 @@
+[//] : # (NOTE : veuillez mettre chaque phrase dans sa propre ligne. Transifex met chaque ligne dans son propre champ de traduction !)
## Comment puis-je activer OpenKeychain dans K-9 Mail ?
Pour utiliser OpenKeychain avec K-9 Mail, vous devez suivre ces étapes :
@@ -12,4 +13,4 @@ Veuillez signaler le bogue en utilisant le [gestionnaire de bogue d'OpenKeychain
Si vous voulez nous aider à développer OpenKeychain en y contribuant par du code [veuillez suivre notre petit guide sur Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Traductions
-Aidez à traduire OpenKeychain ! Tout le monde peut y participer sur la [page d'OpenKeychain sur Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
+Aidez-nous à traduire le OpenKeychain ! Tout le monde peut y participer sur la <a href="https://www.transifex.com/projects/p/open-keychain/">page d'OpenKeychain sur Transifex</a>. \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-is/help_about.md b/OpenKeychain/src/main/res/raw-is/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-is/help_about.md
+++ b/OpenKeychain/src/main/res/raw-is/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-is/help_certification.md b/OpenKeychain/src/main/res/raw-is/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-is/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-is/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-is/help_changelog.md b/OpenKeychain/src/main/res/raw-is/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-is/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-is/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-is/help_start.md b/OpenKeychain/src/main/res/raw-is/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-is/help_start.md
+++ b/OpenKeychain/src/main/res/raw-is/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-it/help_about.md b/OpenKeychain/src/main/res/raw-it/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-it/help_about.md
+++ b/OpenKeychain/src/main/res/raw-it/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-it/help_certification.md b/OpenKeychain/src/main/res/raw-it/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-it/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-it/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-it/help_changelog.md b/OpenKeychain/src/main/res/raw-it/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-it/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-it/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-it/help_start.md b/OpenKeychain/src/main/res/raw-it/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-it/help_start.md
+++ b/OpenKeychain/src/main/res/raw-it/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-ja/help_about.md b/OpenKeychain/src/main/res/raw-ja/help_about.md
index d6a8eca93..f19a5f877 100644
--- a/OpenKeychain/src/main/res/raw-ja/help_about.md
+++ b/OpenKeychain/src/main/res/raw-ja/help_about.md
@@ -1,12 +1,13 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
-[OpenKeychain](http://www.openkeychain.org) is an OpenPGP implementation for Android.
+[OpenKeychain](http://www.openkeychain.org) は Android における OpenPGP 実装です。
-License: GPLv3+
+ライセンス: GPLv3以降
-## Developers
- * Dominik Schürmann (Maintainer)
+## Developers## 開発者
+ * Dominik Schürmann (メンテナ)
* Art O Cathain
* Ash Hughes
* Brian C. Barnes
@@ -27,7 +28,7 @@ License: GPLv3+
* Tim Bray
* Vincent Breitmoser
-## Libraries
+## ライブラリ
* [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
* [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
@@ -37,7 +38,7 @@ License: GPLv3+
* [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
* [ZXing](https://github.com/zxing/zxing) (Apache License v2)
* [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
- * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design)</a> (Apache License v2)
+ * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
* [MaterialNavigationDrawer](https://github.com/neokree/MaterialNavigationDrawer) (Apache License v2)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
* [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
diff --git a/OpenKeychain/src/main/res/raw-ja/help_certification.md b/OpenKeychain/src/main/res/raw-ja/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-ja/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-ja/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-ja/help_changelog.md b/OpenKeychain/src/main/res/raw-ja/help_changelog.md
index e9d61d0f3..c25d91a19 100644
--- a/OpenKeychain/src/main/res/raw-ja/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-ja/help_changelog.md
@@ -1,51 +1,52 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
- * Material design
- * Integration of QR Scanner (New permissions required)
- * Improved key creation wizard
- * Fix missing contacts after sync
- * Requires Android 4
- * Redesigned key screen
- * Simplify crypto preferences, better selection of secure ciphers
- * API: Detached signatures, free selection of signing key,...
- * Fix: Some valid keys were shown revoked or expired
- * Don't accept signatures by expired or revoked subkeys
- * Keybase.io support in advanced view
+ * マテリアルデザイン
+ * QRスキャナの統合 (新しいパーミッションを必要とします)
+ * 鍵生成ウィザードの改善
+ * 同期後に連絡先を見失う問題の修正
+ * Android 4を必要とします
+ * 鍵画面の再デザイン
+ * 暗号の設定をシンプル化、より良いセキュアな暗号の選択方法
+ * API: 分離署名、署名する鍵の選択がフリーとなる、...
+ * 修正: いくつかの正しい鍵が破棄もしくは期限切れとして表示される
+ * 副鍵が期限切れもしくは破棄されている場合に署名を受け入れない
+ * 拡張ビューでのKeybase.ioのサポート
## 3.1.2
- * Fix key export to files (now for real)
+ * 鍵のファイルへのエクスポートの修正 (現実的になりました)
## 3.1.1
- * Fix key export to files (they were written partially)
- * Fix crash on Android 2.3
+ * 鍵のファイルへのエクスポートの修正 (部分的に修正)
+ * Android 2.3でのクラッシュ修正
## 3.1
- * Fix crash on Android 5
- * New certify screen
- * Secure Exchange directly from key list (SafeSlinger library)
- * New QR Code program flow
- * Redesigned decrypt screen
- * New icon usage and colors
- * Fix import of secret keys from Symantec Encryption Desktop
- * Subkey IDs on Yubikeys are now checked correctly
+ * Android 5でのクラッシュ修正
+ * 新しい検証画面
+ * セキュアな鍵リストの直接交換(SafeSlinger ライブラリ)
+ * 新しいQRコードのプログラムフロー
+ * 復号化画面の再デザイン
+ * 新しいアイコン利用とカラー
+ * Symantec Encryption Desktopから秘密鍵をインポート時の問題修正
+ * Yubikeyでの副鍵IDを正くチェックするようになりました
## 3.0.1
- * Better handling of large key imports
- * Improved subkey selection
+ * 巨大な鍵のインポートのより良い取り扱い
+ * 副鍵選択の改善
## 3.0
- * Full support for Yubikey signature generation and decryption!
+ * Yubikeyでの署名生成と復号化のフルサポート
* Propose installable compatible apps in apps list
* New design for decryption screens
* Many fixes for key import, also fixes stripped keys
@@ -53,67 +54,67 @@
* User interface to generate custom keys
* Fixing user id revocation certificates
* New cloud search (searches over traditional keyservers and keybase.io)
- * Support for stripping keys inside OpenKeychain
+ * OpenKeychain内で鍵をストリップするのをサポートしました
## 2.9.2
- * Fix keys broken in 2.9.1
- * Yubikey decryption now working via API
+ * 2.9.1での鍵破壊問題修正
+ * API経由でYubikeyの復号処理が動くようになった
## 2.9.1
- * Split encrypt screen into two
- * Fix key flags handling (now supporting Mailvelope 0.7 keys)
- * Improved passphrase handling
- * Key sharing via SafeSlinger
- * Yubikey: preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
- * Fix usage of stripped keys
- * SHA256 as default for compatibility
- * Intent API has changed, see https://github.com/open-keychain/open-keychain/wiki/Intent-API
- * OpenPGP API now handles revoked/expired keys and returns all user ids
+ * 暗号化スクリーンを2つに分割
+ * 鍵のフラグ管理を修正 (現在Mailvelope 0.7 鍵をサポート)
+ * パスフレーズの取り回しを改善
+ * SafeSlingerでの鍵の共有
+ * Yubikey: 設定で他のPINを受け付け、現在OpenPGP API経由での署名しか動きません、OpenKeychainの内部ではないため
+ * ストリップした鍵の利用法を修正
+ * 互換性のためデフォルトをSHA256に
+ * インテント API を変更しました、以下参照 https://github.com/open-keychain/open-keychain/wiki/Intent-API
+ * OpenPGP API は現在破棄/期限切れの鍵を扱えるようになり、またすべてのユーザIDを返すようになりました
## 2.9
- * Fixing crashes introduced in v2.8
- * Experimental ECC support
- * Experimental Yubikey support (signing-only with imported keys)
+ * v2.8 から発生したクラッシュ問題をFix
+ * 実験的にECCをサポート
+ * 実験的にYubikeyをサポート(インポート済みの鍵での署名のみ)
## 2.8
- * So many bugs have been fixed in this release that we focus on the main new features
- * Key edit: awesome new design, key revocation
- * Key import: awesome new design, secure keyserver connections via hkps, keyserver resolving via DNS SRV records
- * New first time screen
- * New key creation screen: autocompletion of name and email based on your personal Android accounts
- * File encryption: awesome new design, support for encrypting multiple files
- * New icons to show status of key (by Brennan Novak)
- * Important bug fix: Importing of large key collections from a file is now possible
- * Notification showing cached passphrases
- * Keys are connected to Android's contacts
+ * そして主要な新しい機能を主眼としたこのリリースでたくさんのバグが修正されました
+ * 鍵編集: 新しいすごいデザイン、鍵の破棄
+ * 鍵インポート: 新しいすごいデザイン、hkps経由での鍵サーバとの安全な接続、そしてDNS SRVレコードによる鍵サーバの解決
+ * 新しい初回表示
+ * 新しい鍵生成画面: Androidのあなたの個人アカウントをベースとした名前とメールの自動補完
+ * ファイル暗号化: 新しいすごいデザイン、複数ファイルの暗号化をサポートする
+ * 鍵のステータス表示の新しいアイコン(Brennan Novak提供)
+ * 重要なバグ修正: 巨大な鍵コレクションをファイルからインポートするのが可能になりました
+ * キャッシュしたパスフレーズの通知表示
+ * 鍵のアドレスをAndroidの連絡先と連携するようにした
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfiharの働きなくしてはこのリリースはありませんでした
## 2.7
* Purple! (Dominik, Vincent)
- * New key view design (Dominik, Vincent)
- * New flat Android buttons (Dominik, Vincent)
- * API fixes (Dominik)
- * Keybase.io import (Tim Bray)
+ * 新しい鍵のビューのデザイン (Dominik, Vincent)
+ * 新しいフラットな Android ボタン (Dominik, Vincent)
+ * API のフィックス (Dominik)
+ * Keybase.io からのインポート (Tim Bray)
## 2.6.1
- * Some fixes for regression bugs
+ * いくつかのリグレッションバグ修正
## 2.6
- * Key certifications (thanks to Vincent Breitmoser)
+ * 鍵証明 (ありがとうVincent Breitmoser)
* Support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
* New design for signature verification
* Custom key length (thanks to Greg Witczak)
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-ja/help_start.md b/OpenKeychain/src/main/res/raw-ja/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-ja/help_start.md
+++ b/OpenKeychain/src/main/res/raw-ja/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-nl/help_about.md b/OpenKeychain/src/main/res/raw-nl/help_about.md
index 15d3796e9..9d3693d33 100644
--- a/OpenKeychain/src/main/res/raw-nl/help_about.md
+++ b/OpenKeychain/src/main/res/raw-nl/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-nl/help_certification.md b/OpenKeychain/src/main/res/raw-nl/help_certification.md
index 8da27e8e0..c7b8c6d4c 100644
--- a/OpenKeychain/src/main/res/raw-nl/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-nl/help_certification.md
@@ -1,27 +1,28 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-## Key Confirmation
-Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
-To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
+## Sleutelbevestiging
+Zonder bevestiging kan je niet zeker zijn dat een sleutel echt overeenkomt met een bepaald persoon.
+De meest eenvoudige manier om een sleutel te bevestigen is door de QR-code te scannen of de sleutel uit te wisselen via NFC.
+Om sleutels tussen meer dan twee personen te bevestigen stellen we voor om de sleuteluitwisselingsmethode beschikbaar voor je sleutels te gebruiken.
-## Key Status
+## Sleutelstatus
<img src="status_signature_verified_cutout_24dp"/>
-Confirmed: You have already confirmed this key, e.g., by scanning the QR Code.
+Bevestigd: je hebt deze sleutel al bevestigd, bv. door de QR-code te scannen.
<img src="status_signature_unverified_cutout_24dp"/>
-Unconfirmed: This key has not been confirmed yet. You cannot be sure if the key really corresponds to a specific person.
+Niet bevestigd: deze sleutel is nog niet bevestigd. Je kan niet zeker zijn dat de sleutel echt overeenkomt met een bepaald persoon.
<img src="status_signature_expired_cutout_24dp"/>
-Expired: This key is no longer valid. Only the owner can extend its validity.
+Verlopen: deze sleutel is niet meer geldig. Enkel de eigenaar kan de geldigheid verlengen.
<img src="status_signature_revoked_cutout_24dp"/>
-Revoked: This key is no longer valid. It has been revoked by its owner.
+Ingetrokken: deze sleutel is niet meer geldig. Ze is door de eigenaar ingetrokken.
-## Advanced Information
-A "key confirmation" in OpenKeychain is implemented by creating a certification according to the OpenPGP standard.
-This certification is a ["generic certification (0x10)"](http://tools.ietf.org/html/rfc4880#section-5.2.1) described in the standard by:
-"The issuer of this certification does not make any particular assertion as to how well the certifier has checked that the owner of the key is in fact the person described by the User ID."
+## Geavanceerde informatie
+Een "sleutelbevestiging" in OpenKeychain is geïmplementeerd door een certificatie aan te maken volgens de OpenPGP-standaard.
+Deze certificatie is een ["generische certificatie (0x10)"](http://tools.ietf.org/html/rfc4880#section-5.2.1) omschreven in de standaard als:
+"De uitgever van deze certificatie maakt geen specifieke aanname over hoe goed de certificeerder heeft nagegaan dat de eigenaar van sleutel effectief de persoon is beschreven door het gebruikers-ID."
-Traditionally, certifications (also with higher certification levels, such as "positive certifications" (0x13)) are organized in OpenPGP's Web of Trust.
-Our model of key confirmation is a much simpler concept to avoid common usability problems related to this Web of Trust.
-We assume that keys are verified only to a certain degree that is still usable enough to be executed "on the go".
-We also do not implement (potentially transitive) trust signatures or an ownertrust database like in GnuPG.
-Furthermore, keys which contain at least one user ID certified by a trusted key will be marked as "confirmed" in the key listings. \ No newline at end of file
+Traditioneel worden certificaties (ook met hogere certificatieniveau's, zoals "positieve certificaties" (0x13)) georganiseerd in OpenPGP's Web of Trust.
+Ons model van sleutelbevestiging is een veel eenvoudige concept om veel voorkomende gebruiksproblemen gerelateerd aan dit Web of Trust te vermijden.
+We nemen aan dat sleutels slechts geverifieerd zijn tot een bepaalde graad die nog steeds bruikbaar genoeg is om "onderweg" uitgevoerd te worden.
+We implementeren ook geen (mogelijk transitieve) vertrouwensondertekeningen of een gebruikersvertrouwendatabase zoals in GnuPG.
+Bovendien worden sleutels die minstens een gebruikers-ID gecertificeerd door een vertrouwde sleutel bevatten aangeduid als "bevestigd" in de sleutellijsten. \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-nl/help_changelog.md b/OpenKeychain/src/main/res/raw-nl/help_changelog.md
index 96dcb5241..6fd5d9872 100644
--- a/OpenKeychain/src/main/res/raw-nl/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-nl/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -28,13 +29,13 @@
## 3.1
* Oplossing voor crash op Android 5
- * New certify screen
- * Secure Exchange directly from key list (SafeSlinger library)
- * New QR Code program flow
- * Redesigned decrypt screen
- * New icon usage and colors
- * Fix import of secret keys from Symantec Encryption Desktop
- * Subkey IDs on Yubikeys are now checked correctly
+ * Nieuw certificeerscherm
+ * Veilig uitwisselen vanuit sleutellijst (SafeSlinger bibliotheek)
+ * Nieuwe QR code programma flow
+ * Nieuw design voor ontcijferingsscherm
+ * Nieuw icoon en kleuren
+ * Oplossing voor importeren van geheime sleutels van Symantec Encryption Desktop
+ * Subsleutel-ID's op Yubikeys worden nu currect gecontroleerd
## 3.0.1
@@ -45,15 +46,15 @@
## 3.0
- * Full support for Yubikey signature generation and decryption!
- * Propose installable compatible apps in apps list
- * New design for decryption screens
- * Many fixes for key import, also fixes stripped keys
- * Honor and display key authenticate flags
- * User interface to generate custom keys
- * Fixing user id revocation certificates
- * New cloud search (searches over traditional keyservers and keybase.io)
- * Support for stripping keys inside OpenKeychain
+ * Volledige ondersteuning voor Yubikey ondertekeningsgeneratie en ontcijfering!
+ * Stel installeerbare compatibele apps voor in apps-lijst
+ * Nieuw design voor ontcijferingsschermen
+ * Veel oplossingen voor sleutelimporteren, lost ook gestripte sleutels op
+ * Eer en toon sleutelauthenticatievlaggen
+ * Gebruikersinterface om eigen sleutels aan te maken
+ * Oplossing voor gebruikers-ID-intrekkingscertificaten
+ * Nieuwe cloud search (zoekt op traditionele sleutelservers en keybase.io)
+ * Ondersteuning voor strippen van sleutels in OpenKeychain
## 2.9.2
@@ -64,15 +65,15 @@
## 2.9.1
- * Split encrypt screen into two
- * Fix key flags handling (now supporting Mailvelope 0.7 keys)
- * Improved passphrase handling
- * Key sharing via SafeSlinger
- * Yubikey: preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
- * Fix usage of stripped keys
- * SHA256 as default for compatibility
- * Intent API has changed, see https://github.com/open-keychain/open-keychain/wiki/Intent-API
- * OpenPGP API now handles revoked/expired keys and returns all user ids
+ * Deel versleutelingsscherm in twee
+ * Oplossing voor sleutelvlaggen (ondersteunt nu Mailvelope 0.7 sleutels)
+ * Verbeterde behandeling van wachtwoorden
+ * Sleutels delen via SafeSlinger
+ * Yubikey: optie om andere PINs toe te staan, momenteel werkt enkel ondertekenen via de OpenPGP API, niet in OpenKeychain zelf
+ * Oplossing voor gestripte sleutels
+ * SHA256 als standaard voor compatibiliteit
+ * Intent API is veranderd, zie https://github.com/open-keychain/open-keychain/wiki/Intent-API
+ * OpenPGP API behandelt nu ingetrokken/verlopen sleutels en geeft alle gebruikers-ID's weer
## 2.9
@@ -84,24 +85,24 @@
## 2.8
- * So many bugs have been fixed in this release that we focus on the main new features
- * Key edit: awesome new design, key revocation
- * Key import: awesome new design, secure keyserver connections via hkps, keyserver resolving via DNS SRV records
- * New first time screen
- * New key creation screen: autocompletion of name and email based on your personal Android accounts
- * File encryption: awesome new design, support for encrypting multiple files
- * New icons to show status of key (by Brennan Novak)
- * Important bug fix: Importing of large key collections from a file is now possible
- * Notification showing cached passphrases
- * Keys are connected to Android's contacts
+ * Er zijn zoveel bugs opgelost in deze release dat we kunnen focussen op de belangrijke nieuwe mogelijkheden
+ * Sleutels wijzigen: nieuw design, sleutels intrekken
+ * Sleutels importeren: nieuw design, veilige verbindingen met sleutelservers via hkps, sleutelserver resolving via DNS SRV records
+ * Nieuw eerste gebruiksscherm
+ * Nieuw scherm voor sleutels aanmaken: automatisch aanvullen van naam en e-mailadres gebaseerd op persoonlijke Android-accounts
+ * Bestandsversleuteling: nieuw design, ondersteuning voor versleutelen van meerdere bestanden
+ * Nieuwe iconen om sleutelstatus weer te geven (door Brennan Novak)
+ * Belangrijke bugfix: importeren van grote sleutelbossen uit een bestand is nu mogelijk
+ * Melding om gecachete wachtwoorden weer te geven
+ * Sleutels worden verbonden aan Android's contacten
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+Deze release zou niet mogelijk zijn zonder het werkt van Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
- * Purple! (Dominik, Vincent)
- * New key view design (Dominik, Vincent)
- * New flat Android buttons (Dominik, Vincent)
+ * Paars! (Dominik, Vincent)
+ * Nieuw sleutel scherm design (Dominik, Vincent)
+ * Nieuwe platte Android toetsen (Dominik, Vincent)
* API fixes (Dominik)
* Keybase.io import (Tim Bray)
@@ -113,37 +114,37 @@
## 2.6
- * Key certifications (thanks to Vincent Breitmoser)
- * Support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
- * New design for signature verification
- * Custom key length (thanks to Greg Witczak)
- * Fix share-functionality from other apps
+ * Sleutelcertificaties (dank aan Vincent Breitmoser)
+ * Ondersteuning voor GnuPG gedeeltelijke geheime sleutels (dank aan Vincent Breitmoser)
+ * Nieuw design voor ondertekeningsverificatie
+ * Aangepaste sleutellengte (dank aan Greg Witczak)
+ * Oplossing voor delen vanuit andere apps
## 2.5
- * Fix decryption of symmetric OpenPGP messages/files
- * Refactored key edit screen (thanks to Ash Hughes)
- * New modern design for encrypt/decrypt screens
- * OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
+ * Oplossing voor ontcijfering van symmetrische OpenPGP berichten/bestanden
+ * Nieuw ontwerp voor sleutelbewerkingsscherm (dank aan Ash Hughes)
+ * Nieuw modern design voor versleutelings/ontcijferingsschermen
+ * OpenPGP API versie 3 (meerdere api accounts, interne fixes, sleutel lookup)
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
-Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
-
- * New unified key list
- * Colorized key fingerprint
- * Support for keyserver ports
- * Deactivate possibility to generate weak keys
- * Much more internal work on the API
- * Certify user ids
- * Keyserver query based on machine-readable output
- * Lock navigation drawer on tablets
- * Suggestions for emails on creation of keys
- * Search in public key lists
- * And much more improvements and fixes…
+Bedankt aan alle deelnemers van Google Summer of Code 2014 die deze release vol met nieuwe mogelijkheden en vrij van bugs gemaakt hebben!
+Naast vele kleine patches werden ook een aanzienlijk aantal patches gemaakt door de volgende personen (in alfabetische volgorde):
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
+
+ * Nieuwe geünificeerde sleutellijst
+ * Gekleurde sleutelvingerafdruk
+ * Ondersteuning voor sleutelserver-poorten
+ * Zet mogelijkheid om zwakke sleutels aan te maken uit
+ * Veel meer intern werk aan API
+ * Certificeer gebruikers-ID's
+ * Sleutelserverzoekopdracht gebaseerd op machine-leesbare output
+ * Zet navigatiedrawer op tablets vast
+ * Suggesties voor e-mailadress bij aanmaken van sleutels
+ * Zoeken in publieke sleutellijsten
+ * En veel meer verbeteringen en fixes...
## 2.3.1
@@ -153,28 +154,28 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
## 2.3
- * Remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
- * Fix setting expiry dates on keys (thanks to Ash Hughes)
- * More internal fixes when editing keys (thanks to Ash Hughes)
- * Querying keyservers directly from the import screen
- * Fix layout and dialog style on Android 2.2-3.0
- * Fix crash on keys with empty user ids
- * Fix crash and empty lists when coming back from signing screen
- * Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
- * Fix upload of key from signing screen
+ * Verwijder onnodige export van publieke sleutels bij exporteren van geheime sleutel (dank aan Ash Hughes)
+ * Oplossing voor verloopdata op sleutels (dank aan Ash Hughes)
+ * Meer interne fixes by bewerken van sleutels (dank aan Ash Hughes)
+ * Zoeken op sleutelservers rechtstreeks van importscherm
+ * Oplossing voor layout en dialoogstijl op Android 2.2-3.0
+ * Oplossing voor crash op sleutels met lege gebruikers-ID's
+ * Oplossing voor crash en lege lijsten bij terugkeren van ondertekeningsscherm
+ * Bouncy Castle (cryptografie bibliotheek) bijgewerkt van 1.47 naar 1.50 en versie van bron
+ * Oplossing voor uploaden van sleutel van ondertekeningsscherm
## 2.2
- * New design with navigation drawer
- * New public key list design
- * New public key view
- * Bug fixes for importing of keys
- * Key cross-certification (thanks to Ash Hughes)
- * Handle UTF-8 passwords properly (thanks to Ash Hughes)
- * First version with new languages (thanks to the contributors on Transifex)
- * Sharing of keys via QR Codes fixed and improved
- * Package signature verification for API
+ * Nieuw design met navigatiebalk
+ * Nieuw publieke sleutellijst design
+ * Nieuwe publieke sleutel view
+ * Bugfixes voor importeren van sleutels
+ * Sleutel certificatie (dank aan Ash Hughes)
+ * Behandel UTF-8 wachtwoorden correct (dank aan Ash Hughes)
+ * Eerste versie met nieuwe talen (dank aan de medewerkers op Transifex)
+ * Delen van sleutels via QR codes opgelost en verbeterd
+ * Pakketondertekeningsverificatie voor API
## 2.1.1
@@ -191,22 +192,22 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
## 2.0
- * Complete redesign
- * Share public keys via QR codes, NFC beam
- * Sign keys
- * Upload keys to server
- * Fixes import issues
- * New AIDL API
+ * Volledig nieuw design
+ * Publieke sleutels delen via QR codes, NFC beam
+ * Sleutels ondertekenen
+ * Upload sleutels naar server
+ * Importeerproblemen opgelost
+ * Nieuwe AIDL API
## 1.0.8
- * Basic keyserver support
- * App2sd
- * More choices for passphrase cache: 1, 2, 4, 8, hours
- * Translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
+ * Basisondersteuning voor sleutelservers
+ * App2SD
+ * Meer keuzes voor wachtwoordcache: 1, 2, 4, 8 uur
+ * Vertalingen: Noors (bedankt, Sander Danielsen), Chinees (bedankt, Zhang Fredrick)
* Bugfixes
- * Optimizations
+ * Optimalisaties
## 1.0.7
@@ -217,22 +218,22 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
## 1.0.6
- * Account adding crash on Froyo fixed
- * Secure file deletion
- * Option to delete key file after import
- * Stream encryption/decryption (gallery, etc.)
- * New options (language, force v3 signatures)
- * Interface changes
+ * Crash bij toevoegen van account op Froyo opgelost
+ * Veilige bestandsverwijdering
+ * Optie om sleutelbestand na importeren te verwijderen
+ * Stream versleuteling/ontsleuteling (galerij, enz.)
+ * Nieuwe opties (taal, forceer v3 ondertekeningen)
+ * Wijzigingen in interface
* Bugfixes
## 1.0.5
- * German and Italian translation
- * Much smaller package, due to reduced BC sources
- * New preferences GUI
- * Layout adjustment for localization
- * Signature bugfix
+ * Duitse en Italiaanse vertaling
+ * Veel kleiner pakket, door verminderde BC bronnen
+ * Nieuwe GUI voor voorkeuren
+ * Layout wijzigingen voor localisatie
+ * Bugfix voor ondertekeningen
## 1.0.4
@@ -247,10 +248,10 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
## 1.0.2
- * Filterable key lists
- * Smarter pre-selection of encryption keys
- * New Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
- * Fixes and additional features (key preselection) for K-9 Mail, new beta build available
+ * Filterbare sleutellijsten
+ * Slimmere preselectie van cryptosleutels
+ * Nieuwe Intents voor VIEW en SEND, laat toe bestanden te versleutelen/ontcijferen vanuit bestandsbeheerders
+ * Oplossingen en nieuwe functies (sleutel preselectie) voor K-9 Mail, nieuwe beta build beschikbaar
## 1.0.1
@@ -260,9 +261,9 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
## 1.0.0
- * K-9 Mail integration, APG supporting beta build of K-9 Mail
- * Support of more file managers (including ASTRO)
- * Slovenian translation
- * New database, much faster, less memory usage
- * Defined Intents and content provider for other apps
+ * K-9 Mail integratie, APG ondersteunende beta versie van K-9 Mail
+ * Ondersteuning voor meer bestandsbeheerders (waaronder ASTRO)
+ * Sloveense vertaling
+ * Nieuwe database, veel sneller, minder geheugengebruik
+ * Intents en content provider voor andere apps gedefinieerd
* Bugfixes \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-nl/help_start.md b/OpenKeychain/src/main/res/raw-nl/help_start.md
index 83e27bf97..9eaf23640 100644
--- a/OpenKeychain/src/main/res/raw-nl/help_start.md
+++ b/OpenKeychain/src/main/res/raw-nl/help_start.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Hoe activeer ik OpenKeychain in K-9 Mail?
Volg deze stappen om OpenKeychain te gebruiken met K-9 Mail:
@@ -12,4 +13,4 @@ Rapporteer de bug met de [problementracker van OpenKeychain](https://github.com/
Als je ons wil helpen om OpenKeychain te ontwikkelen door code bij te dragen, [volg dan onze kleine gids op GitHub](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Vertalingen
-Help OpenKeychain te vertalen! Iedereen kan deelnemen op [OpenKeychain op Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help OpenKeychain te vertalen! Iedereen kan deelnemen op [OpenKeychain op Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-pl/help_about.md b/OpenKeychain/src/main/res/raw-pl/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-pl/help_about.md
+++ b/OpenKeychain/src/main/res/raw-pl/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-pl/help_certification.md b/OpenKeychain/src/main/res/raw-pl/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-pl/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-pl/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-pl/help_changelog.md b/OpenKeychain/src/main/res/raw-pl/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-pl/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-pl/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-pl/help_start.md b/OpenKeychain/src/main/res/raw-pl/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-pl/help_start.md
+++ b/OpenKeychain/src/main/res/raw-pl/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-pt/help_about.md b/OpenKeychain/src/main/res/raw-pt/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-pt/help_about.md
+++ b/OpenKeychain/src/main/res/raw-pt/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-pt/help_certification.md b/OpenKeychain/src/main/res/raw-pt/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-pt/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-pt/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-pt/help_changelog.md b/OpenKeychain/src/main/res/raw-pt/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-pt/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-pt/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-pt/help_start.md b/OpenKeychain/src/main/res/raw-pt/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-pt/help_start.md
+++ b/OpenKeychain/src/main/res/raw-pt/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-ro/help_about.md b/OpenKeychain/src/main/res/raw-ro/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-ro/help_about.md
+++ b/OpenKeychain/src/main/res/raw-ro/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-ro/help_certification.md b/OpenKeychain/src/main/res/raw-ro/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-ro/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-ro/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-ro/help_changelog.md b/OpenKeychain/src/main/res/raw-ro/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-ro/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-ro/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-ro/help_start.md b/OpenKeychain/src/main/res/raw-ro/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-ro/help_start.md
+++ b/OpenKeychain/src/main/res/raw-ro/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-ru/help_about.md b/OpenKeychain/src/main/res/raw-ru/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-ru/help_about.md
+++ b/OpenKeychain/src/main/res/raw-ru/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-ru/help_certification.md b/OpenKeychain/src/main/res/raw-ru/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-ru/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-ru/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-ru/help_changelog.md b/OpenKeychain/src/main/res/raw-ru/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-ru/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-ru/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-ru/help_start.md b/OpenKeychain/src/main/res/raw-ru/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-ru/help_start.md
+++ b/OpenKeychain/src/main/res/raw-ru/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-sl/help_about.md b/OpenKeychain/src/main/res/raw-sl/help_about.md
index d6a8eca93..dc333ca2d 100644
--- a/OpenKeychain/src/main/res/raw-sl/help_about.md
+++ b/OpenKeychain/src/main/res/raw-sl/help_about.md
@@ -1,12 +1,13 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
-[OpenKeychain](http://www.openkeychain.org) is an OpenPGP implementation for Android.
+[OpenKeychain](http://www.openkeychain.org) je implementacija OpenPGP za Android.
-License: GPLv3+
+Licenca: GPLv3+
-## Developers
- * Dominik Schürmann (Maintainer)
+## Razvijalci
+ * Dominik Schürmann (Skrbnik)
* Art O Cathain
* Ash Hughes
* Brian C. Barnes
@@ -27,19 +28,19 @@ License: GPLv3+
* Tim Bray
* Vincent Breitmoser
-## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
- * [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
- * [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
- * [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
- * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design)</a> (Apache License v2)
- * [MaterialNavigationDrawer](https://github.com/neokree/MaterialNavigationDrawer) (Apache License v2)
- * [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/dschuermann/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+## Knjižnice
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (Licenca MIT X11)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (Licenca MIT)
+ * [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Licenca Apache v2)
+ * [KeybaseLib](https://github.com/timbray/KeybaseLib) (Licenca Apache v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Licenca Apache v2)
+ * [MiniDNS](https://github.com/rtreffer/minidns) (Licenca Apache v2)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Licenca Apache v2)
+ * [ZXing](https://github.com/zxing/zxing) (Licenca Apache v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Licenca Apache v2)
+ * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design)</a> (Licenca Apache v2)
+ * [MaterialNavigationDrawer](https://github.com/neokree/MaterialNavigationDrawer) (Licenca Apache v2)
+ * [Snackbar](https://github.com/nispok/snackbar) (Licenca MIT)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Licenca Apache v2)
+ * [HtmlTextView](https://github.com/dschuermann/html-textview) (Licenca Apache v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Licenca Apache v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-sl/help_certification.md b/OpenKeychain/src/main/res/raw-sl/help_certification.md
index 8da27e8e0..12a86e726 100644
--- a/OpenKeychain/src/main/res/raw-sl/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-sl/help_certification.md
@@ -1,27 +1,28 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-## Key Confirmation
-Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
-To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
+## Potrjevanje ključev
+Brez overitve ne morete vedeti, če nek ključ zares pripada določeni osebi.
+Najbolj preprost način za overitev ključa je skeniranje kode QR ali izmenjava ključev preko NFC.
+Za overjanje ključev med več kot dvema osebama priporočamo uporabo izmenjave, ki je na voljo za vaše ključe.
-## Key Status
+## Status ključa
<img src="status_signature_verified_cutout_24dp"/>
-Confirmed: You have already confirmed this key, e.g., by scanning the QR Code.
+Ključ je potrjen: ta ključ ste že potrdili, npr. s skeniranjem kode QR.
<img src="status_signature_unverified_cutout_24dp"/>
-Unconfirmed: This key has not been confirmed yet. You cannot be sure if the key really corresponds to a specific person.
+Ključ ni potrjen: Ta ključ še ni bil overjen, zato ne morete vedeti, če res pripada osebi, ki naj bi jo predstavljal.
<img src="status_signature_expired_cutout_24dp"/>
-Expired: This key is no longer valid. Only the owner can extend its validity.
+Ključ je potekel: Ta ključ ni več veljaven. Samo lastnik lahko podaljša veljavnost svojega ključa.
<img src="status_signature_revoked_cutout_24dp"/>
-Revoked: This key is no longer valid. It has been revoked by its owner.
+Ključ preklican: Ta ključ ni več veljaven. Lastnik ga je preklical.
-## Advanced Information
-A "key confirmation" in OpenKeychain is implemented by creating a certification according to the OpenPGP standard.
-This certification is a ["generic certification (0x10)"](http://tools.ietf.org/html/rfc4880#section-5.2.1) described in the standard by:
-"The issuer of this certification does not make any particular assertion as to how well the certifier has checked that the owner of the key is in fact the person described by the User ID."
+## Dodatne informacije
+"Overitev ključa" se v aplikaciji OpenKeychain izvede s stvaritvijo potrdila v skladu s standardom OpenPGP.
+To potrdilo je ["generično potrdilo (0x10)"](http://tools.ietf.org/html/rfc4880#section-5.2.1), kot je zapisano v standardu:
+"Izdajatelj tega potrdila ne jamči za kakovost preverjanja overitelja, če je lastnik ključa dejansko oseba, označena v identifikaciji (ID) ključa."
-Traditionally, certifications (also with higher certification levels, such as "positive certifications" (0x13)) are organized in OpenPGP's Web of Trust.
-Our model of key confirmation is a much simpler concept to avoid common usability problems related to this Web of Trust.
-We assume that keys are verified only to a certain degree that is still usable enough to be executed "on the go".
-We also do not implement (potentially transitive) trust signatures or an ownertrust database like in GnuPG.
-Furthermore, keys which contain at least one user ID certified by a trusted key will be marked as "confirmed" in the key listings. \ No newline at end of file
+Navadno so potrdila (tudi na višji stopnji overjanja, kot so "pozitivna pravila" (0x13)) organizirana v Omrežje zaupanja OpenPGP.
+Naš način overjanja je mnogo bolj preprost, s čimer se želimo izogniti pogostim težavam povezanim z Omrežjem zaupanja.
+Domnevamo, da so ključi preverjeni do mere, ki je še uporabna, glede na mobilno naravo aplikacije.
+Tudi ne ponujamo (potencialno prenosljivih) t.i. podpisov zaupanja kot jih ponuja GnuPG.
+Nadalje; ključi, ki vsebujejo vsaj en ID potrjen s strani zaupanja vrednega ključa, bodo na seznamu označeni kot "overjeni". \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-sl/help_changelog.md b/OpenKeychain/src/main/res/raw-sl/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-sl/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-sl/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-sl/help_start.md b/OpenKeychain/src/main/res/raw-sl/help_start.md
index 1641f913b..78c002de4 100644
--- a/OpenKeychain/src/main/res/raw-sl/help_start.md
+++ b/OpenKeychain/src/main/res/raw-sl/help_start.md
@@ -1,15 +1,16 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-## How do I activate OpenKeychain in K-9 Mail?
-To use OpenKeychain with K-9 Mail, you want to follow these steps:
- 1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
- 3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
+## Kako aktivirati OpenKeychain v aplikaciji K-9 Mail?
+Za uporabo OpenKeychain v aplikaciji K-9 Mail sledite naslednjim korakom:
+ 1. Odprite aplikacijo K-9 Mail in dlje časa zadržite prst na računu s katerim želite uporabljati OpenKeychain.
+ 2. Izberite "Nastavitve računa", se pomaknite na dno in kliknite "Šifriranje".
+ 3. Kliknite na "Ponudnik OpenPGP" in na seznamu izberite OpenKeychain.
-## I found a bug in OpenKeychain!
-Please report the bug using the [issue tracker of OpenKeychain](https://github.com/openpgp-keychain/openpgp-keychain/issues).
+## Našel sem 'hrošča' v aplikaciji OpenKeychain!
+Za prijavo hrošča uporabite [sledilnik težav za OpenKeychain](https://github.com/openpgp-keychain/openpgp-keychain/issues).
-## Contribute
-If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
+## Prispevajte
+Če želite pomagati pri razvoju aplikacije OpenKeychain in prispevati lastno kodo [prosimo sledite navodilom na Github-u](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
-## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+## Prevodi
+Pomagajte nam pri prevajanju aplikacije OpenKeychain! Svoje prevode lahko prispevate tukaj: [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-sr/help_about.md b/OpenKeychain/src/main/res/raw-sr/help_about.md
index 2ffe80e3b..77a4904e5 100644
--- a/OpenKeychain/src/main/res/raw-sr/help_about.md
+++ b/OpenKeychain/src/main/res/raw-sr/help_about.md
@@ -1,3 +1,4 @@
+[//]: #
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-sr/help_certification.md b/OpenKeychain/src/main/res/raw-sr/help_certification.md
index 03af89a61..20b68cf9b 100644
--- a/OpenKeychain/src/main/res/raw-sr/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-sr/help_certification.md
@@ -1,7 +1,8 @@
+[//]: #
## Потврда кључа
Без потврде не можете бити сигурни да ли кључ заиста одговара одређеној особи.
-Најједноставнији начин потврђивања кључа је очитавање бар-кôда или размена преко НФЦ.
+Најједноставнији начин да потврдите кључ је очитавањем бар-кôда или разменом преко НФЦ.
Да бисте потврдили кључеве између две или више особа, предлажемо да користите методу размене кључева која је доступна за ваш кључ.
## Стање кључа
diff --git a/OpenKeychain/src/main/res/raw-sr/help_changelog.md b/OpenKeychain/src/main/res/raw-sr/help_changelog.md
index 3b0dbcc05..e33c6b4e4 100644
--- a/OpenKeychain/src/main/res/raw-sr/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-sr/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: #
## 3.2beta2
@@ -95,7 +96,7 @@
* Обавештење које показује кеширане лозинке
* Кључеви су повезани са Андроидовим контактима
-<p>Ово издање не би било могуће без рада Винсента Брајтмозера (ГСоЦ 2014), „mar-v-in“-а (ГСоЦ 2014), Данијела Алберта (Daniel Albert), Арта Катијана (Art O Cathain), Данијела Хаса, Тима Бреја, „Thialfihar“-а</p>
+Ово издање не би било могуће без рада Винсента Брајтмозера (ГСоЦ 2014), „mar-v-in“-а (ГСоЦ 2014), Данијела Алберта (Daniel Albert), Арта Катијана (Art O Cathain), Данијела Хаса, Тима Бреја, „Thialfihar“-а
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Хвала свим апликантима Гугловог Лета Ко̂да 2014 који су учинили ово издање богатим у могућностима и без грешака!
+Хвала свим апликантима Гугловог Лета Кôда 2014 који су учинили ово издање богатим у могућностима и без грешака!
Осим неколицине малих закрпа, значајан број закрпа направили су следећи људи (по абецедном реду):
-Данијел Хаман (Daniel Hammann), Данијел Хас (Daniel Haß), Грег Вичак (Greg Witczak), Мируђин Бакши (Miroojin Bakshi), Никил Питер Раж (Nikhil Peter Raj), Паул Сарбиновски (Paul Sarbinowski), Срирам Бујапати (Sreeram Boyapati), Винсент Брајтмозер (Vincent Breitmoser).</p>
+Данијел Хаман (Daniel Hammann), Данијел Хас (Daniel Haß), Грег Вичак (Greg Witczak), Мируђин Бакши (Miroojin Bakshi), Никил Питер Раж (Nikhil Peter Raj), Паул Сарбиновски (Paul Sarbinowski), Срирам Бујапати (Sreeram Boyapati), Винсент Брајтмозер (Vincent Breitmoser).
* Нови обједињени списак кључева
* Обојени отисак прста кључа
diff --git a/OpenKeychain/src/main/res/raw-sr/help_start.md b/OpenKeychain/src/main/res/raw-sr/help_start.md
index f531fdc82..1375f91eb 100644
--- a/OpenKeychain/src/main/res/raw-sr/help_start.md
+++ b/OpenKeychain/src/main/res/raw-sr/help_start.md
@@ -1,8 +1,9 @@
+[//]: #
## Како да активирам Отворени кључарник у К-9 Пошти?
Да бисте користили Отворени кључарник са К-9 Поштом, пратите ове кораке:
1. Отворите К-9 Пошту и тапните и задржите на налог са којим желите да користите Отворени кључарник.
- 2. Изаберите „поставке налога“ и клизајте на дно и тапните на „криптографија“.
+ 2. Изаберите „поставке налога“, клизајте на дно и тапните на „криптографија“.
3. Тапните на „ОпенПГП апликација“ и изаберите Отворени кључарник са списка.
## Пронађох грешку у Отвореном кључарнику!
@@ -12,4 +13,4 @@
Ако желите да нам помогнете у развоју Отвореног кључарника доприношењем кôда, [пратите наш мали водич на Гитхабу](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Преводи
-Помозите превођењем Отвореног кључарника! Било ко може да учествује на [пројекту Отвореног кључарника на Трансифексу](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Помозите превођењем Отвореног кључарника! Сви могу да учествују на [пројекту Отвореног кључарника на Трансифексу](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-sv/help_about.md b/OpenKeychain/src/main/res/raw-sv/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-sv/help_about.md
+++ b/OpenKeychain/src/main/res/raw-sv/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-sv/help_certification.md b/OpenKeychain/src/main/res/raw-sv/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-sv/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-sv/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-sv/help_changelog.md b/OpenKeychain/src/main/res/raw-sv/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-sv/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-sv/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-sv/help_start.md b/OpenKeychain/src/main/res/raw-sv/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-sv/help_start.md
+++ b/OpenKeychain/src/main/res/raw-sv/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-tr/help_about.md b/OpenKeychain/src/main/res/raw-tr/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-tr/help_about.md
+++ b/OpenKeychain/src/main/res/raw-tr/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-tr/help_certification.md b/OpenKeychain/src/main/res/raw-tr/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-tr/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-tr/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-tr/help_changelog.md b/OpenKeychain/src/main/res/raw-tr/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-tr/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-tr/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-tr/help_start.md b/OpenKeychain/src/main/res/raw-tr/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-tr/help_start.md
+++ b/OpenKeychain/src/main/res/raw-tr/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-uk/help_about.md b/OpenKeychain/src/main/res/raw-uk/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-uk/help_about.md
+++ b/OpenKeychain/src/main/res/raw-uk/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-uk/help_certification.md b/OpenKeychain/src/main/res/raw-uk/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-uk/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-uk/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-uk/help_changelog.md b/OpenKeychain/src/main/res/raw-uk/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-uk/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-uk/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-uk/help_start.md b/OpenKeychain/src/main/res/raw-uk/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-uk/help_start.md
+++ b/OpenKeychain/src/main/res/raw-uk/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-zh-rTW/help_about.md b/OpenKeychain/src/main/res/raw-zh-rTW/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-zh-rTW/help_about.md
+++ b/OpenKeychain/src/main/res/raw-zh-rTW/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-zh-rTW/help_certification.md b/OpenKeychain/src/main/res/raw-zh-rTW/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-zh-rTW/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-zh-rTW/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-zh-rTW/help_changelog.md b/OpenKeychain/src/main/res/raw-zh-rTW/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-zh-rTW/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-zh-rTW/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-zh-rTW/help_start.md b/OpenKeychain/src/main/res/raw-zh-rTW/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-zh-rTW/help_start.md
+++ b/OpenKeychain/src/main/res/raw-zh-rTW/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-zh/help_about.md b/OpenKeychain/src/main/res/raw-zh/help_about.md
index d6a8eca93..9d635d9df 100644
--- a/OpenKeychain/src/main/res/raw-zh/help_about.md
+++ b/OpenKeychain/src/main/res/raw-zh/help_about.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
[http://www.openkeychain.org](http://www.openkeychain.org)
diff --git a/OpenKeychain/src/main/res/raw-zh/help_certification.md b/OpenKeychain/src/main/res/raw-zh/help_certification.md
index 8da27e8e0..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-zh/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-zh/help_certification.md
@@ -1,7 +1,8 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## Key Confirmation
Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The most simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
+The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
## Key Status
diff --git a/OpenKeychain/src/main/res/raw-zh/help_changelog.md b/OpenKeychain/src/main/res/raw-zh/help_changelog.md
index e9d61d0f3..4a7ddb7f2 100644
--- a/OpenKeychain/src/main/res/raw-zh/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-zh/help_changelog.md
@@ -1,3 +1,4 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## 3.2beta2
@@ -95,7 +96,7 @@
* Notification showing cached passphrases
* Keys are connected to Android's contacts
-<p>This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar</p>
+This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
## 2.7
@@ -129,9 +130,9 @@
## 2.4
-<p>Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.</p>
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
* New unified key list
* Colorized key fingerprint
diff --git a/OpenKeychain/src/main/res/raw-zh/help_start.md b/OpenKeychain/src/main/res/raw-zh/help_start.md
index 1641f913b..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-zh/help_start.md
+++ b/OpenKeychain/src/main/res/raw-zh/help_start.md
@@ -1,8 +1,9 @@
+[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
## How do I activate OpenKeychain in K-9 Mail?
To use OpenKeychain with K-9 Mail, you want to follow these steps:
1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings" and scroll to the very bottom and click "Cryptography".
+ 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
## I found a bug in OpenKeychain!
@@ -12,4 +13,4 @@ Please report the bug using the [issue tracker of OpenKeychain](https://github.c
If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/openpgp-keychain/). \ No newline at end of file
+Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw/help_changelog.md b/OpenKeychain/src/main/res/raw/help_changelog.md
index 18203b1c5..104454f39 100644
--- a/OpenKeychain/src/main/res/raw/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw/help_changelog.md
@@ -35,7 +35,7 @@
* Redesigned decrypt screen
* New icon usage and colors
* Fix import of secret keys from Symantec Encryption Desktop
- * Subkey IDs on Yubikeys are now checked correctly
+ * Subkey IDs on YubiKeys are now checked correctly
## 3.0.1
@@ -46,7 +46,7 @@
## 3.0
- * Full support for Yubikey signature generation and decryption!
+ * Full support for YubiKey signature generation and decryption!
* Propose installable compatible apps in apps list
* New design for decryption screens
* Many fixes for key import, also fixes stripped keys
@@ -60,7 +60,7 @@
## 2.9.2
* Fix keys broken in 2.9.1
- * Yubikey decryption now working via API
+ * YubiKey decryption now working via API
## 2.9.1
@@ -69,7 +69,7 @@
* Fix key flags handling (now supporting Mailvelope 0.7 keys)
* Improved passphrase handling
* Key sharing via SafeSlinger
- * Yubikey: preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
+ * YubiKey: preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
* Fix usage of stripped keys
* SHA256 as default for compatibility
* Intent API has changed, see https://github.com/open-keychain/open-keychain/wiki/Intent-API
@@ -80,7 +80,7 @@
* Fixing crashes introduced in v2.8
* Experimental ECC support
- * Experimental Yubikey support (signing-only with imported keys)
+ * Experimental YubiKey support (signing-only with imported keys)
## 2.8
diff --git a/OpenKeychain/src/main/res/values-cs/strings.xml b/OpenKeychain/src/main/res/values-cs/strings.xml
index 2434c91df..f99b32a2d 100644
--- a/OpenKeychain/src/main/res/values-cs/strings.xml
+++ b/OpenKeychain/src/main/res/values-cs/strings.xml
@@ -4,8 +4,6 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">Vybrat klíče</string>
- <string name="title_select_secret_key">Vybrat svůj klíč</string>
<string name="title_encrypt_text">Zašifrovat</string>
<string name="title_encrypt_files">Zašifrovat</string>
<string name="title_decrypt">Rozšifrovat</string>
@@ -13,7 +11,6 @@
<string name="title_add_subkey">Přidat podklíč</string>
<string name="title_edit_key">Editovat klíč</string>
<string name="title_preferences">Nastavení</string>
- <string name="title_cloud_search_preferences">Nastavení vyhledávání v cloudu</string>
<string name="title_api_registered_apps">Aplikace</string>
<string name="title_change_passphrase">Změnit heslo</string>
<string name="title_share_fingerprint_with">Sdílet otisk s...</string>
@@ -23,7 +20,6 @@
<string name="title_encrypt_to_file">Zašifrovat do souboru</string>
<string name="title_decrypt_to_file">Rozšifrovat do souboru</string>
<string name="title_import_keys">Importovat klíče</string>
- <string name="title_add_keys">Přidat klíče</string>
<string name="title_export_key">Exportovat klíče</string>
<string name="title_export_keys">Exportovat klíče</string>
<string name="title_key_not_found">Klíč nebyl nalezen</string>
@@ -32,36 +28,33 @@
<string name="title_key_details">Detaily klíče</string>
<string name="title_help">Nápověda</string>
<string name="title_log_display">Log</string>
- <string name="title_create_key">Vytvořit klíč</string>
<string name="title_exchange_keys">Vyměnit klíče</string>
<string name="title_advanced_key_info">Další informace ke klíči</string>
- <string name="title_keys">Klíče</string>
<string name="title_delete_secret_key">Smazat Váš klíč \'%s\'?</string>
<string name="title_export_log">Exportovat log</string>
+ <string name="title_manage_my_keys">Spravovat klíče</string>
<!--section-->
<string name="section_user_ids">Identity</string>
+ <string name="section_linked_system_contact">Propojený kontakt v systému</string>
<string name="section_should_you_trust">Důvěřujete tomuto klíči?</string>
+ <string name="section_proof_details">Doložit ověření</string>
+ <string name="section_cloud_evidence">Doložení z cloudu</string>
<string name="section_keys">Podklíče</string>
<string name="section_cloud_search">Vyhledávání v Cloud službě</string>
- <string name="section_general">Obecné</string>
- <string name="section_defaults">Výchozí hodnoty</string>
- <string name="section_advanced">Pokročilé</string>
<string name="section_passphrase_cache">Cache hesel</string>
<string name="section_certify">Potvrdit</string>
<string name="section_actions">Akce</string>
<string name="section_share_key">Klíč</string>
- <string name="section_upload_key">Synchronizovat klíč</string>
<string name="section_key_server">Keyserver</string>
<string name="section_fingerprint">Otisk</string>
- <string name="section_decrypt_files">Soubory</string>
- <string name="section_decrypt_text">Text</string>
- <string name="section_certs">Certifikáty</string>
<string name="section_encrypt">Zašifrovat</string>
<string name="section_decrypt">Rozšifrovat</string>
+ <string name="section_current_expiry">Současná expirace</string>
+ <string name="section_new_expiry">Nová expirace</string>
<!--button-->
<string name="btn_decrypt_verify_file">Dešifrovat, ověřit a uložit soubor</string>
- <string name="btn_encrypt_file">Zaširovat a uložit soubor</string>
<string name="btn_encrypt_share_file">Zašifrovat a sdílet soubor</string>
+ <string name="btn_encrypt_save_file">Zašifrovat a uložit soubor</string>
<string name="btn_save">Uložit</string>
<string name="btn_do_not_save">Zrušit</string>
<string name="btn_delete">Smazat</string>
@@ -70,25 +63,31 @@
<string name="btn_export_to_server">Nahrát na keyserver</string>
<string name="btn_next">Další</string>
<string name="btn_back">Zpět</string>
- <string name="btn_lookup_key">Vyhledat klíč</string>
+ <string name="btn_no">Ne</string>
+ <string name="btn_match">Otisky souhlasí</string>
+ <string name="btn_share_encrypted_signed">Zašifrovat a sdílet text</string>
+ <string name="btn_copy_encrypted_signed">Zašifrovat a zkopírovat text</string>
<string name="btn_view_cert_key">Zobrazit klíč certifikátu</string>
<string name="btn_create_key">Vytvořit klíč</string>
<string name="btn_add_files">Přidat soubor(y)</string>
<string name="btn_add_share_decrypted_text">Sdílet dešifrovaný text</string>
+ <string name="btn_decrypt_clipboard">Dešifrovat text ze schránky</string>
<string name="btn_decrypt_and_verify">a ověřit podpisy</string>
<string name="btn_decrypt_files">Dešifrovat soubory</string>
+ <string name="btn_encrypt_files">Zašifrovat soubory</string>
+ <string name="btn_encrypt_text">Zašifrovat text</string>
+ <string name="btn_add_email">Přidat další emailové adresy</string>
<!--menu-->
<string name="menu_preferences">Nastavení</string>
<string name="menu_help">Nápověda</string>
<string name="menu_export_key">Exportovat do souboru</string>
<string name="menu_delete_key">Smazat klíč</string>
- <string name="menu_import_existing_key">Importovat ze souboru</string>
+ <string name="menu_manage_keys">Spravovat klíče</string>
<string name="menu_search">Hledat</string>
+ <string name="menu_nfc_preferences">NFC nastavení</string>
<string name="menu_beam_preferences">Beam settings</string>
- <string name="menu_key_edit_cancel">Zrušit</string>
<string name="menu_encrypt_to">Zašifrovat do...</string>
<string name="menu_select_all">Vybrat vše</string>
- <string name="menu_add_keys">Přidat klíče</string>
<string name="menu_export_all_keys">Exportovat všechny klíče</string>
<string name="menu_advanced">Zobrazit pokročilé info</string>
<!--label-->
@@ -187,9 +186,6 @@
<string name="encrypt_sign_clipboard_successful">Úspěšně podepsání a/nebo zašifrováno do schránky.</string>
<string name="select_encryption_key">Vyberte alespoň jeden šifrovací klíč.</string>
<string name="select_encryption_or_signature_key">Vyberte alespoň jeden šifrovací nebo podpisový klíč.</string>
- <string name="specify_file_to_encrypt_to">Prosím specifikujte do kterého souboru zašifrovat.\nVAROVÁNÍ: Pokud soubor již existuje, bude přepsán.</string>
- <string name="specify_file_to_decrypt_to">Prosím specifikujte do kterého souboru rozšifrovat.\nVAROVÁNÍ: Pokud soubor již existuje, bude přepsán.</string>
- <string name="specify_file_to_export_to">Prosím specifikujte do kterého souboru exportovat.\nVAROVÁNÍ: Pokud soubor již existuje, bude přepsán.</string>
<string name="also_export_secret_keys">Zárověň exportovat tajný klíč</string>
<string name="reinstall_openkeychain">Narazili jste na známou chybu v Androidu. Přeinstalujte prosím OpenKeychain pokud chcete své propojit kontakty s klíči.</string>
<string name="key_exported">Úspěšně exportován 1 klíč.</string>
diff --git a/OpenKeychain/src/main/res/values-de/strings.xml b/OpenKeychain/src/main/res/values-de/strings.xml
index 0022153a6..4fd310837 100644
--- a/OpenKeychain/src/main/res/values-de/strings.xml
+++ b/OpenKeychain/src/main/res/values-de/strings.xml
@@ -4,8 +4,6 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">Wähle Schlüssel</string>
- <string name="title_select_secret_key">Wähle Deinen Schlüssel</string>
<string name="title_encrypt_text">Verschlüsseln</string>
<string name="title_encrypt_files">Verschlüsseln</string>
<string name="title_decrypt">Entschlüsseln</string>
@@ -13,7 +11,6 @@
<string name="title_add_subkey">Unterschlüssel hinzufügen</string>
<string name="title_edit_key">Schlüssel bearbeiten</string>
<string name="title_preferences">Einstellungen</string>
- <string name="title_cloud_search_preferences">Einstellungen Cloudsuche</string>
<string name="title_api_registered_apps">Apps</string>
<string name="title_key_server_preference">Schlüsselserver</string>
<string name="title_change_passphrase">Passwort ändern</string>
@@ -24,7 +21,6 @@
<string name="title_encrypt_to_file">In eine Datei verschlüsseln</string>
<string name="title_decrypt_to_file">In eine Datei entschlüsseln</string>
<string name="title_import_keys">Schlüssel importieren</string>
- <string name="title_add_keys">Schlüssel hinzufügen</string>
<string name="title_export_key">Schlüssel exportieren</string>
<string name="title_export_keys">Schlüssel exportieren</string>
<string name="title_key_not_found">Schlüssel nicht gefunden</string>
@@ -33,10 +29,8 @@
<string name="title_key_details">Schlüsseldetails</string>
<string name="title_help">Hilfe</string>
<string name="title_log_display">Log</string>
- <string name="title_create_key">Schlüssel erzeugen</string>
<string name="title_exchange_keys">Schlüssel austauschen</string>
<string name="title_advanced_key_info">Erweiterte Schlüsselinformation</string>
- <string name="title_keys">Schlüssel</string>
<string name="title_delete_secret_key">DEINEN Schlüssel \'%s\' löschen?</string>
<string name="title_export_log">Log exportieren</string>
<string name="title_manage_my_keys">Meine Schlüssel verwalten</string>
@@ -48,27 +42,18 @@
<string name="section_cloud_evidence">Nachweise aus der Cloud</string>
<string name="section_keys">Unterschlüssel</string>
<string name="section_cloud_search">Cloudsuche</string>
- <string name="section_general">Allgemein</string>
- <string name="section_defaults">Standardwerte</string>
- <string name="section_advanced">Fortgeschrittene Einstellungen</string>
<string name="section_passphrase_cache">Passwort Zwischenspeicher</string>
<string name="section_certify">Bestätigen</string>
<string name="section_actions">Aktionen</string>
<string name="section_share_key">Schlüssel</string>
- <string name="section_upload_key">Schlüssel synchronisieren</string>
<string name="section_key_server">Schlüsselserver</string>
<string name="section_fingerprint">Fingerabdruck</string>
- <string name="section_decrypt_files">Dateien</string>
- <string name="section_decrypt_text">Text</string>
- <string name="section_certs">Beglaubigungen</string>
<string name="section_encrypt">Verschlüsseln</string>
<string name="section_decrypt">Entschlüsseln</string>
<string name="section_current_expiry">Aktuelles Ablaufdatum</string>
<string name="section_new_expiry">Neues Ablaufdatum</string>
<!--button-->
<string name="btn_decrypt_verify_file">Datei entschlüsseln, verifizieren und speichern</string>
- <string name="btn_decrypt_verify_message">Nachricht entschlüsseln und überprüfen</string>
- <string name="btn_encrypt_file">Datei verschlüsseln und speichern</string>
<string name="btn_encrypt_share_file">Datei verschlüsseln und teilen</string>
<string name="btn_encrypt_save_file">Datei verschlüsseln und speichern</string>
<string name="btn_save">Speichern</string>
@@ -81,7 +66,6 @@
<string name="btn_back">Zurück</string>
<string name="btn_no">Nein</string>
<string name="btn_match">Fingerabdrücke stimmen überein</string>
- <string name="btn_lookup_key">Schlüssel nachschlagen</string>
<string name="btn_share_encrypted_signed">Nachricht verschlüsseln und teilen</string>
<string name="btn_copy_encrypted_signed">Text verschlüsseln und kopieren</string>
<string name="btn_view_cert_key">Beglaubigungsschlüssel anzeigen</string>
@@ -100,16 +84,13 @@
<string name="menu_export_key">In Datei exportieren</string>
<string name="menu_delete_key">Schlüssel löschen</string>
<string name="menu_manage_keys">Meine Schlüssel verwalten</string>
- <string name="menu_import_existing_key">Von Datei importieren</string>
<string name="menu_search">Suchen</string>
<string name="menu_nfc_preferences">NFC-Einstellungen</string>
<string name="menu_beam_preferences">Beam-Einstellungen</string>
- <string name="menu_key_edit_cancel">Abbrechen</string>
<string name="menu_encrypt_to">Verschlüsseln nach…</string>
<string name="menu_select_all">Alles auswählen</string>
- <string name="menu_add_keys">Schlüssel hinzufügen</string>
- <string name="menu_search_cloud">Cloud durchsuchen</string>
<string name="menu_export_all_keys">Alle Schlüssel exportieren</string>
+ <string name="menu_update_all_keys">Alle Schlüssel aktualisieren</string>
<string name="menu_advanced">Erweiterte Infos anzeigen</string>
<string name="menu_certify_fingerprint">Über Fingerabdruckvergleich bestätigen</string>
<string name="menu_export_log">Log exportieren</string>
@@ -161,6 +142,10 @@
<string name="label_enable_compression">Komprimierung aktivieren</string>
<string name="label_encrypt_filenames">Dateinamen verschlüsseln</string>
<string name="label_hidden_recipients">Empfänger verbergen</string>
+ <string name="pref_keyserver">Schlüsselserver durchsuchen</string>
+ <string name="pref_keyserver_summary">HKP-Schlüsselserver durchsuchen</string>
+ <string name="pref_keybase">Keybase.io durchsuchen</string>
+ <string name="pref_keybase_summary">Keybase.io-Index durchsuchen</string>
<string name="user_id_no_name">&lt;kein Name&gt;</string>
<string name="none">&lt;keine&gt;</string>
<plurals name="n_keys">
@@ -218,8 +203,8 @@
<string name="select_encryption_key">Mindestens einen Schlüssel zum Verschlüsseln auswählen.</string>
<string name="select_encryption_or_signature_key">Mindestens einen Schlüssel zum Verschlüsseln oder einen zum Signieren auswählen.</string>
<string name="specify_file_to_encrypt_to">Bitte angeben in welche Datei verschlüsselt werden soll.\nWARNUNG: Datei wird überschrieben, wenn sie bereits existiert.</string>
- <string name="specify_file_to_decrypt_to">Bitte angeben in welche Datei entschlüsselt werden soll.\nWARNUNG: Datei wird überschrieben, wenn sie bereits existiert. </string>
- <string name="specify_file_to_export_to">Bitte angeben in welche Datei exportiert werden soll.\nWARNUNG: Datei wird überschrieben, wenn sie bereits existiert. </string>
+ <string name="specify_file_to_decrypt_to">Bitte angeben in welche Datei entschlüsselt werden soll.\nWARNUNG: Datei wird überschrieben, wenn sie bereits existiert.</string>
+ <string name="specify_file_to_export_to">Bitte angeben in welche Datei exportiert werden soll.\nWARNUNG: Datei wird überschrieben, wenn sie bereits existiert.</string>
<string name="key_deletion_confirmation_multi">Möchtest du wirklich alle ausgewählten Schlüssel löschen?</string>
<string name="secret_key_deletion_confirmation">Nach dem Löschen wird es dir nicht mehr möglich sein mit diesem Schlüssel verschlüsselte Nachrichten zu lesen und zudem wirst du alle damit getätigten Bestätigungen verlieren!</string>
<string name="public_key_deletetion_confirmation">Schlüssel löschen \'%s\'?</string>
@@ -289,6 +274,7 @@
<string name="progress_cancelling">Abbrechen...</string>
<string name="progress_saving">Wird gespeichert…</string>
<string name="progress_importing">Wird importiert…</string>
+ <string name="progress_updating">Aktualisiere Schlüssel...</string>
<string name="progress_exporting">Wird exportiert…</string>
<string name="progress_uploading">Wird hochgeladen...</string>
<string name="progress_building_key">Schlüssel wird erstellt…</string>
@@ -333,7 +319,7 @@
<string name="progress_con_saving">Zusammenführung: Im Cache speichern...</string>
<string name="progress_con_reimport">Zusammenführung: Neuimportierung...</string>
<!--action strings-->
- <string name="hint_cloud_search_hint">Suche via Name, E-Mail...</string>
+ <string name="hint_cloud_search_hint">Via Name, E-Mail durchsuchen...</string>
<!--key bit length selections-->
<string name="key_size_512">512</string>
<string name="key_size_768">768</string>
@@ -451,7 +437,7 @@
<string name="api_settings_hide_advanced">Erweiterte Einstellungen ausblenden</string>
<string name="api_settings_no_key">Kein Schlüssel ausgewählt</string>
<string name="api_settings_select_key">Schlüssel auswählen</string>
- <string name="api_settings_create_key">Erzeuge meinen Schlüssel</string>
+ <string name="api_settings_create_key">Neuen Schlüssel erzeugen</string>
<string name="api_settings_save">Speichern</string>
<string name="api_settings_save_msg">Benutzerkonto wurde gespeichert</string>
<string name="api_settings_cancel">Abbrechen</string>
@@ -589,6 +575,7 @@
<string name="create_key_edit">Schlüsselkonfiguration ändern</string>
<string name="create_key_add_email">E-Mail-Adresse hinzufügen</string>
<string name="create_key_add_email_text">Es sind zusätzliche E-Mail-Adressen mit diesem Schlüssel verknüpft, die zur sicheren Kommunikation verwendet werden können.</string>
+ <string name="create_key_email_already_exists_text">E-Mail wurde bereits hinzugefügt</string>
<!--View key-->
<string name="view_key_revoked">Widerrufen: Schlüssel darf nicht mehr genutzt werden!</string>
<string name="view_key_expired">Abgelaufen: Der Kontakt muss die Gültigkeit des Schlüssels verlängern!</string>
@@ -1097,7 +1084,7 @@
<string name="msg_download_query_too_short">Die Suchanfrage ist zu kurz, bitte die Suchanfrage verfeinern!</string>
<string name="msg_download_too_many_responses">Schlüsselsuchanfrage lieferte zu viele Kandidaten, bitte die Suchanfrage verfeinern!</string>
<string name="msg_download_query_too_short_or_too_many_responses">Entweder keine oder zu viele Schlüssel wurden gefunden, bitte die Suchanfrage prä­zi­sie­ren!</string>
- <string name="msg_download_query_failed">Beim suchen der Schlüssel ist ein Fehler aufgetreten.</string>
+ <string name="msg_download_query_failed">Beim Suchen der Schlüssel ist ein Fehler aufgetreten.</string>
<!--Messages for Export Log operation-->
<string name="msg_export_log_start">Exportiere Protokoll</string>
<string name="msg_export_log_error_fopen">Fehler beim Öffnen der Datei</string>
@@ -1112,7 +1099,7 @@
<string name="passp_cache_notif_pwd">Passwort</string>
<!--First Time-->
<string name="first_time_text1">Hol dir deine Privatsphäre mit OpenKeychain zurück!</string>
- <string name="first_time_create_key">Meinen Schlüssel erzeugen (empfohlen)</string>
+ <string name="first_time_create_key">Meinen Schlüssel erzeugen</string>
<string name="first_time_import_key">Schlüssel aus Datei importieren</string>
<string name="first_time_yubikey">YubiKey NEO verwenden</string>
<string name="first_time_skip">Setup überspringen</string>
diff --git a/OpenKeychain/src/main/res/values-es/strings.xml b/OpenKeychain/src/main/res/values-es/strings.xml
index a042f3809..2d94eb6a2 100644
--- a/OpenKeychain/src/main/res/values-es/strings.xml
+++ b/OpenKeychain/src/main/res/values-es/strings.xml
@@ -4,27 +4,23 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">Seleccionar claves</string>
- <string name="title_select_secret_key">Seleccionar su clave</string>
- <string name="title_encrypt_text">Cifrar</string>
- <string name="title_encrypt_files">Cifrar</string>
+ <string name="title_encrypt_text">Encriptar</string>
+ <string name="title_encrypt_files">Encriptar</string>
<string name="title_decrypt">Descifrar</string>
<string name="title_unlock">Desbloquear clave</string>
<string name="title_add_subkey">Añadir subclave</string>
<string name="title_edit_key"> Editar clave</string>
<string name="title_preferences">Configuración</string>
- <string name="title_cloud_search_preferences">Preferencias de búsqueda en la nube</string>
<string name="title_api_registered_apps">Aplicaciones</string>
<string name="title_key_server_preference">Servidores de claves</string>
<string name="title_change_passphrase">Cambiar frase de contraseña</string>
- <string name="title_share_fingerprint_with">Compartir huella de validación de clave con...</string>
+ <string name="title_share_fingerprint_with">Compartir huella digital con...</string>
<string name="title_share_key">Compartir clave con...</string>
- <string name="title_share_file">Compartir fichero con...</string>
+ <string name="title_share_file">Compartir archivo con...</string>
<string name="title_share_message">Compartir texto con...</string>
<string name="title_encrypt_to_file">Cifrar hacia archivo</string>
<string name="title_decrypt_to_file">Descifrar hacia archivo</string>
<string name="title_import_keys">Importar claves</string>
- <string name="title_add_keys">Añadir claves</string>
<string name="title_export_key">Exportar clave</string>
<string name="title_export_keys">Exportar claves</string>
<string name="title_key_not_found">Clave no encontrada</string>
@@ -33,11 +29,9 @@
<string name="title_key_details">Detalles de la clave</string>
<string name="title_help">Ayuda</string>
<string name="title_log_display">Registro (log)</string>
- <string name="title_create_key">Crear clave</string>
<string name="title_exchange_keys">Intercambiar claves</string>
<string name="title_advanced_key_info">Información avanzada de clave</string>
- <string name="title_keys">Claves</string>
- <string name="title_delete_secret_key">¿Borrar la clave DE USTED \'%s\'?</string>
+ <string name="title_delete_secret_key">¿Borrar clave \'%s\'?</string>
<string name="title_export_log">Exportar registro (log)</string>
<string name="title_manage_my_keys">Administrar mis claves</string>
<!--section-->
@@ -48,51 +42,41 @@
<string name="section_cloud_evidence">Comprobantes desde la nube</string>
<string name="section_keys">Subclaves</string>
<string name="section_cloud_search">Búsqueda en la nube</string>
- <string name="section_general">General</string>
- <string name="section_defaults">Predeterminados</string>
- <string name="section_advanced">Avanzado</string>
<string name="section_passphrase_cache">Caché de frase-contraseña</string>
<string name="section_certify">Confirmar</string>
<string name="section_actions">Acciones</string>
<string name="section_share_key">Clave</string>
- <string name="section_upload_key">Sincronizar clave</string>
<string name="section_key_server">Servidor de claves</string>
- <string name="section_fingerprint">Huella de validación de clave</string>
- <string name="section_decrypt_files">Ficheros</string>
- <string name="section_decrypt_text">Texto</string>
- <string name="section_certs">Certificados</string>
- <string name="section_encrypt">Cifrar</string>
- <string name="section_decrypt">Descifrar</string>
+ <string name="section_fingerprint">Huella digital</string>
+ <string name="section_encrypt">Encriptar</string>
+ <string name="section_decrypt">Desencriptar</string>
<string name="section_current_expiry">Caducidad actual</string>
<string name="section_new_expiry">Nueva caducidad</string>
<!--button-->
- <string name="btn_decrypt_verify_file">Descifrar, verificar, y guardar fichero</string>
- <string name="btn_decrypt_verify_message">Descifrar y verificar texto</string>
- <string name="btn_encrypt_file">Cifrar y guardar fichero</string>
- <string name="btn_encrypt_share_file">Cifrar y compartir fichero</string>
- <string name="btn_encrypt_save_file">Cifrar y guardar fichero</string>
+ <string name="btn_decrypt_verify_file">Desencriptar, verificar, y guardar fichero</string>
+ <string name="btn_encrypt_share_file">Encriptar y compartir fichero</string>
+ <string name="btn_encrypt_save_file">Encriptar y guardar fichero</string>
<string name="btn_save">Guardar</string>
<string name="btn_do_not_save">Cancelar</string>
<string name="btn_delete">Eliminar</string>
- <string name="btn_no_date">Sin fecha de expiración</string>
+ <string name="btn_no_date">No caduca</string>
<string name="btn_okay">De acuerdo</string>
<string name="btn_export_to_server">Cargar al servidor de claves</string>
<string name="btn_next">Siguiente</string>
<string name="btn_back">Volver</string>
<string name="btn_no">No</string>
- <string name="btn_match">Las huellas de validación coinciden</string>
- <string name="btn_lookup_key">Buscar clave</string>
- <string name="btn_share_encrypted_signed">Cifrar y compartir texto</string>
- <string name="btn_copy_encrypted_signed">Cifrar y copiar texto</string>
+ <string name="btn_match">Las huellas digitales coinciden</string>
+ <string name="btn_share_encrypted_signed">Encriptar y compartir texto</string>
+ <string name="btn_copy_encrypted_signed">Encriptar y copiar texto</string>
<string name="btn_view_cert_key">Ver clave de verificación</string>
<string name="btn_create_key">Crear clave</string>
- <string name="btn_add_files">Añadir fichero(s)</string>
- <string name="btn_add_share_decrypted_text">Compartir texto descifrado</string>
+ <string name="btn_add_files">Añadir archivo(s)</string>
+ <string name="btn_add_share_decrypted_text">Compartir texto desencriptado</string>
<string name="btn_decrypt_clipboard">Descifrar texto desde el portapapeles</string>
<string name="btn_decrypt_and_verify">y verificar firmas</string>
- <string name="btn_decrypt_files">Descifrar ficheros</string>
- <string name="btn_encrypt_files">Cifrar ficheros</string>
- <string name="btn_encrypt_text">Cifrar texto</string>
+ <string name="btn_decrypt_files">Desencriptar ficheros</string>
+ <string name="btn_encrypt_files">Encriptar ficheros</string>
+ <string name="btn_encrypt_text">Encriptar texto</string>
<string name="btn_add_email">Añadir dirección de correo electrónico adicional</string>
<!--menu-->
<string name="menu_preferences">Ajustes</string>
@@ -100,24 +84,21 @@
<string name="menu_export_key">Exportar hacia archivo</string>
<string name="menu_delete_key">Borrar clave</string>
<string name="menu_manage_keys">Administrar mis claves</string>
- <string name="menu_import_existing_key">Importar desde fichero</string>
<string name="menu_search">Buscar</string>
<string name="menu_nfc_preferences">Configuraciones NFC</string>
<string name="menu_beam_preferences">Ajustes de Beam</string>
- <string name="menu_key_edit_cancel">Cancelar</string>
<string name="menu_encrypt_to">Cifrar hacia...</string>
<string name="menu_select_all">Seleccionar todo</string>
- <string name="menu_add_keys">Añadir claves</string>
- <string name="menu_search_cloud">Buscar en la nube</string>
<string name="menu_export_all_keys">Exportar todas las claves</string>
+ <string name="menu_update_all_keys">Actualizar todas las claves</string>
<string name="menu_advanced">Mostrar información avanzada</string>
- <string name="menu_certify_fingerprint">Confirmar mediante comparación de la huella de validación (fingerprint)</string>
- <string name="menu_export_log">Exportar registro (log)</string>
+ <string name="menu_certify_fingerprint">Confirmar mediante comparación de la huella digital</string>
+ <string name="menu_export_log">Exportar registro</string>
<!--label-->
<string name="label_message">Texto</string>
<string name="label_file">Archivo</string>
- <string name="label_files">Fichero(s)</string>
- <string name="label_file_colon">Fichero:</string>
+ <string name="label_files">Archivo(s)</string>
+ <string name="label_file_colon">Archivo:</string>
<string name="label_no_passphrase">No hay frase de contraseña</string>
<string name="label_passphrase">Frase de contraseña</string>
<string name="label_unlock">Desbloqueando...</string>
@@ -161,6 +142,10 @@
<string name="label_enable_compression">Habilitar compresión</string>
<string name="label_encrypt_filenames">Cifrar nombres de ficheros</string>
<string name="label_hidden_recipients">Ocultar receptores</string>
+ <string name="pref_keyserver">Buscar en servidor de claves</string>
+ <string name="pref_keyserver_summary">Buscar en servidor de claves HKP</string>
+ <string name="pref_keybase">Buscar en Keybase.io</string>
+ <string name="pref_keybase_summary">Buscar en el índice de Keybase.io</string>
<string name="user_id_no_name">&lt;sin nombre&gt;</string>
<string name="none">&lt;ninguna&gt;</string>
<plurals name="n_keys">
@@ -217,9 +202,9 @@
<string name="encrypt_sign_clipboard_successful">Firmado y/o cifrado del portapapeles con éxito.</string>
<string name="select_encryption_key">Selecciona al menos una clave de cifrado.</string>
<string name="select_encryption_or_signature_key">Selecciona al menos una clave de cifrado o de firma.</string>
- <string name="specify_file_to_encrypt_to">Por favor especifique hacia qué fichero cifrar.\nADVERTENCIA: El fichero se sobreescribirá si existe.</string>
- <string name="specify_file_to_decrypt_to">Por favor especifique hacia que fichero descifrar.\nADVERTENCIA: El fichero se sobreescribirá si existe.</string>
- <string name="specify_file_to_export_to">Por favor especifique hacia qué fichero exportar.\nADVERTENCIA: El fichero se sobreescribirá si existe.</string>
+ <string name="specify_file_to_encrypt_to">Por favor especifique hacia qué fichero cifrar.\nADVERTENCIA: ¡El fichero se sobreescribirá si existe!</string>
+ <string name="specify_file_to_decrypt_to">Por favor especifique hacia qué fichero descifrar.\nADVERTENCIA: ¡El fichero se sobreescribirá si existe!</string>
+ <string name="specify_file_to_export_to">Por favor especifique hacia qué fichero exportar.\nADVERTENCIA: ¡El fichero se sobreescribirá si existe!</string>
<string name="key_deletion_confirmation_multi">¿De verdad quiere borrar todas las claves seleccionadas?</string>
<string name="secret_key_deletion_confirmation">¡Después del borrado no podrá leer mensajes cifrados con esta clave y perderá todas las confirmaciones de clave hechas con ella!</string>
<string name="public_key_deletetion_confirmation">¿Borrar clave \'%s\'?</string>
@@ -289,6 +274,7 @@
<string name="progress_cancelling">cancelando...</string>
<string name="progress_saving">guardando...</string>
<string name="progress_importing">importando...</string>
+ <string name="progress_updating">Actualizando claves...</string>
<string name="progress_exporting">exportando...</string>
<string name="progress_uploading">subiendo...</string>
<string name="progress_building_key">construyendo la clave...</string>
@@ -589,6 +575,7 @@
<string name="create_key_edit">Cambiar configuración de clave</string>
<string name="create_key_add_email">Añadir dirección de correo electrónico</string>
<string name="create_key_add_email_text">Las direcciones adicionales de correo electrónico también están asociadas a esta clave y pueden utilizarse para asegurar la comunicación.</string>
+ <string name="create_key_email_already_exists_text">Ya se ha añadido el correo electrónico</string>
<!--View key-->
<string name="view_key_revoked">Revocada: ¡La clave no debe volver a ser usada!</string>
<string name="view_key_expired">Caducada: ¡El contacto necesita extender la vigencia de la clave!</string>
@@ -1111,7 +1098,7 @@
<string name="passp_cache_notif_pwd">Frase-contraseña</string>
<!--First Time-->
<string name="first_time_text1">¡Recupere su privacidad con OpenKeychain!</string>
- <string name="first_time_create_key">Crear mi clave (recomendado)</string>
+ <string name="first_time_create_key">Crear mi clave</string>
<string name="first_time_import_key">Importar clave desde fichero</string>
<string name="first_time_yubikey">Usar Yubikey NEO</string>
<string name="first_time_skip">Omitir configuración</string>
@@ -1123,7 +1110,7 @@
<string name="empty_certs">No hay certificados para esta clave</string>
<string name="certs_text">Aquí sólo se muestran auto-certificados validados y certificados validados creados con sus claves.</string>
<string name="section_uids_to_certify">Identificaciones para</string>
- <string name="certify_text">Las claves que está importando contienen \"identidades\": nombres y correos electrónicos. Seleccione exactamente aquellos para confirmación que coinciden con lo que esperaba.</string>
+ <string name="certify_text">Las claves que está importando contienen \"identidades\": nombres y direcciones de correo electrónico. Para confirmación seleccione exactamente aquellas que coincidan con lo que esperaba.</string>
<string name="certify_fingerprint_text">Compare la huella de validación mostrada, caracter por caracter, con la que se muestra en el dispositivo de su colega.</string>
<string name="certify_fingerprint_text2">¿Coinciden las huellas de validación mostradas?</string>
<string name="label_revocation">Razón de la revocación</string>
diff --git a/OpenKeychain/src/main/res/values-et/strings.xml b/OpenKeychain/src/main/res/values-et/strings.xml
index 15b0c6c1e..cc9061149 100644
--- a/OpenKeychain/src/main/res/values-et/strings.xml
+++ b/OpenKeychain/src/main/res/values-et/strings.xml
@@ -12,8 +12,6 @@
<string name="title_send_key">Lae võtmeserverisse</string>
<string name="title_help">Abi</string>
<!--section-->
- <string name="section_general">Üldine</string>
- <string name="section_defaults">Vaikeseaded</string>
<!--button-->
<string name="btn_save">Salvesta</string>
<string name="btn_do_not_save">Katkesta</string>
diff --git a/OpenKeychain/src/main/res/values-eu/strings.xml b/OpenKeychain/src/main/res/values-eu/strings.xml
index 77f897b7c..784217b95 100644
--- a/OpenKeychain/src/main/res/values-eu/strings.xml
+++ b/OpenKeychain/src/main/res/values-eu/strings.xml
@@ -4,8 +4,6 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">Hautatu Giltzak</string>
- <string name="title_select_secret_key">Hautatu Zure Giltza</string>
<string name="title_encrypt_text">Enkriptatu</string>
<string name="title_encrypt_files">Enkriptatu</string>
<string name="title_decrypt">Dekriptatu</string>
@@ -13,7 +11,6 @@
<string name="title_add_subkey">Gehitu azpigiltza</string>
<string name="title_edit_key">Editatu Giltza</string>
<string name="title_preferences">Ezarpenak</string>
- <string name="title_cloud_search_preferences">Hodei Bilaketa Hobespenak</string>
<string name="title_api_registered_apps">Aplikazioak</string>
<string name="title_key_server_preference">Giltza-zerbitzariak</string>
<string name="title_change_passphrase">Aldatu Sar-esaldia</string>
@@ -23,7 +20,6 @@
<string name="title_encrypt_to_file">Enkriptatu Agirira</string>
<string name="title_decrypt_to_file">Dekriptatu Agirira</string>
<string name="title_import_keys">Inportatu Giltzak</string>
- <string name="title_add_keys">Gehitu Giltzak</string>
<string name="title_export_key">Esportatu Giltza</string>
<string name="title_export_keys">Esportatu Giltzak</string>
<string name="title_key_not_found">Giltza Ez da Aurkitu</string>
@@ -32,10 +28,8 @@
<string name="title_key_details">Giltzaren Xehetasunak</string>
<string name="title_help">Laguntza</string>
<string name="title_log_display">Oharra</string>
- <string name="title_create_key">Sortu Giltza</string>
<string name="title_exchange_keys">Trukatu Giltzak</string>
<string name="title_advanced_key_info">Giltza Argibide Aurreratuak</string>
- <string name="title_keys">Giltzak</string>
<string name="title_export_log">Esportatu Oharra</string>
<string name="title_manage_my_keys">Kudeatu nire giltzak</string>
<!--section-->
@@ -44,26 +38,17 @@
<string name="section_should_you_trust">Fildatu behar zara giltza honetaz?</string>
<string name="section_keys">Azpigiltzak</string>
<string name="section_cloud_search">Hodei bilaketa</string>
- <string name="section_general">Orokorra</string>
- <string name="section_defaults">Berezkoak</string>
- <string name="section_advanced">Aurreratua</string>
<string name="section_passphrase_cache">Sar-esaldi Katxea</string>
<string name="section_certify">Baieztatu</string>
<string name="section_actions">Ekintzak</string>
<string name="section_share_key">Giltza</string>
- <string name="section_upload_key">Aldiberetu Giltza</string>
<string name="section_key_server">Giltza-zerbitzaria</string>
- <string name="section_decrypt_files">Agiriak</string>
- <string name="section_decrypt_text">Idazkia</string>
- <string name="section_certs">Egiaztagiriak</string>
<string name="section_encrypt">Enkriptatu</string>
<string name="section_decrypt">Dekriptatu</string>
<string name="section_current_expiry">Oraingo epemuga</string>
<string name="section_new_expiry">Epemuga berria</string>
<!--button-->
<string name="btn_decrypt_verify_file">Dekriptatu, egiaztatu eta gorde agiria</string>
- <string name="btn_decrypt_verify_message">Dekriptatu eta egiaztatu idazkia</string>
- <string name="btn_encrypt_file">Enkriptatu eta gorde agiria</string>
<string name="btn_encrypt_share_file">Enkriptatu eta elkarbanatu agiria</string>
<string name="btn_encrypt_save_file">Enkriptatu eta gorde agiria</string>
<string name="btn_save">Gorde</string>
@@ -93,15 +78,11 @@
<string name="menu_export_key">Esportatu agirira</string>
<string name="menu_delete_key">Ezabatu giltza</string>
<string name="menu_manage_keys">Kudeatu nire giltzak</string>
- <string name="menu_import_existing_key">inportatu agiritik</string>
<string name="menu_search">Bilatu</string>
<string name="menu_nfc_preferences">NFC ezarpenak</string>
<string name="menu_beam_preferences">Beam ezarpenak</string>
- <string name="menu_key_edit_cancel">Ezeztatu</string>
<string name="menu_encrypt_to">Enkriptatu hona...</string>
<string name="menu_select_all">Hautatu denak</string>
- <string name="menu_add_keys">Gehitu giltzak</string>
- <string name="menu_search_cloud">Bilatu hodeian</string>
<string name="menu_export_all_keys">Esportatu giltza guztiak</string>
<string name="menu_advanced">Erakutsi argibide aurreratuak</string>
<string name="menu_export_log">Esportatu Oharra</string>
diff --git a/OpenKeychain/src/main/res/values-fi/strings.xml b/OpenKeychain/src/main/res/values-fi/strings.xml
index 3a87d53c1..6cbc2b1fc 100644
--- a/OpenKeychain/src/main/res/values-fi/strings.xml
+++ b/OpenKeychain/src/main/res/values-fi/strings.xml
@@ -3,14 +3,11 @@
<!--GENERAL: Please put all strings inside quotes as described in example 1 on
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<!--title-->
- <string name="title_select_recipients">Valitse Avaimet</string>
- <string name="title_select_secret_key">Valitse Oma Avain</string>
<string name="title_decrypt">Pura Salaus</string>
<string name="title_unlock">Avaa Avain</string>
<string name="title_add_subkey">Lisää aliavain</string>
<string name="title_edit_key">Muokkaa avainta</string>
<string name="title_preferences">Asetukset</string>
- <string name="title_cloud_search_preferences">Pilvihaun Asetukset</string>
<string name="title_api_registered_apps">Sovellukset</string>
<string name="title_change_passphrase">Vaihda Salasana</string>
<string name="title_share_fingerprint_with">Jaa sormenjälki...</string>
@@ -19,7 +16,6 @@
<string name="title_encrypt_to_file">Salaa Tiedostoon</string>
<string name="title_decrypt_to_file">Pura Tiedostoon</string>
<string name="title_import_keys">Tuo Avaimia</string>
- <string name="title_add_keys">Lisää Avaimia</string>
<string name="title_export_key">Vie Avain</string>
<string name="title_export_keys">Vie Avaimia</string>
<string name="title_key_not_found">Avainta Ei Löydy</string>
@@ -27,28 +23,19 @@
<string name="title_key_details">Avaimen Tiedot</string>
<string name="title_help">Apua</string>
<string name="title_log_display">Loki</string>
- <string name="title_create_key">Luo Avain</string>
<string name="title_exchange_keys">Vaihda Avaimia</string>
<string name="title_advanced_key_info">Lisätietoa Avaimesta</string>
<!--section-->
<string name="section_user_ids">Identiteetit</string>
<string name="section_keys">Aliavaimet</string>
<string name="section_cloud_search">Pilvihaku</string>
- <string name="section_general">Yleistä</string>
- <string name="section_defaults">Vakiot</string>
- <string name="section_advanced">Lisäasetukset</string>
<string name="section_passphrase_cache">Salasanavälimuisti</string>
<string name="section_actions">Toiminteet</string>
<string name="section_share_key">Avain</string>
- <string name="section_upload_key">Synkronoi Avain</string>
<string name="section_key_server">Avainpalvelin</string>
<string name="section_fingerprint">Sormenjälki</string>
- <string name="section_decrypt_files">Tiedostot</string>
- <string name="section_decrypt_text">Teksti</string>
- <string name="section_certs">Varmenteet</string>
<!--button-->
<string name="btn_decrypt_verify_file">Pura, todenna ja tallenna tiedosto</string>
- <string name="btn_encrypt_file">Salaa ja tallenna tiedosto</string>
<string name="btn_encrypt_share_file">Salaa ja jaa tiedosto</string>
<string name="btn_save">Tallenna</string>
<string name="btn_do_not_save">Peruuta</string>
@@ -58,7 +45,6 @@
<string name="btn_export_to_server">Lataa Avainpalvelimelle</string>
<string name="btn_next">Seuraava</string>
<string name="btn_back">Takaisin</string>
- <string name="btn_lookup_key">Etsi avain</string>
<string name="btn_view_cert_key">Näytä varmennusavain</string>
<string name="btn_create_key">Luo avain</string>
<string name="btn_add_files">Lisää tiedosto(ja)</string>
@@ -70,14 +56,10 @@
<string name="menu_help">Apua</string>
<string name="menu_export_key">Vie tiedostoon</string>
<string name="menu_delete_key">Poista avain</string>
- <string name="menu_import_existing_key">Tuo tiedostosta</string>
<string name="menu_search">Etsi</string>
<string name="menu_beam_preferences">Beam asetukset</string>
- <string name="menu_key_edit_cancel">Peruuta</string>
<string name="menu_encrypt_to">Salaa...</string>
<string name="menu_select_all">Valitse kaikki</string>
- <string name="menu_add_keys">Lisää avaimia</string>
- <string name="menu_search_cloud">Etsi pilvestä</string>
<string name="menu_export_all_keys">Vie kaikki avaimet</string>
<string name="menu_advanced">Näytä lisäinformaatio</string>
<!--label-->
diff --git a/OpenKeychain/src/main/res/values-fr/strings.xml b/OpenKeychain/src/main/res/values-fr/strings.xml
index f2c249869..f34dd8e46 100644
--- a/OpenKeychain/src/main/res/values-fr/strings.xml
+++ b/OpenKeychain/src/main/res/values-fr/strings.xml
@@ -4,8 +4,6 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">Choisir des clefs</string>
- <string name="title_select_secret_key">Choisir ma clef</string>
<string name="title_encrypt_text">Chiffrer</string>
<string name="title_encrypt_files">Chiffrer</string>
<string name="title_decrypt">Déchiffrer</string>
@@ -13,7 +11,6 @@
<string name="title_add_subkey">Ajouter une sous-clef</string>
<string name="title_edit_key">Modifier une clef</string>
<string name="title_preferences">Paramètres</string>
- <string name="title_cloud_search_preferences">Préférences de recherche nuagique</string>
<string name="title_api_registered_apps">Applis</string>
<string name="title_key_server_preference">Serveurs de clefs</string>
<string name="title_change_passphrase">Modifier la phrase de passe</string>
@@ -24,7 +21,6 @@
<string name="title_encrypt_to_file">Chiffrer vers un fichier</string>
<string name="title_decrypt_to_file">Déchiffrer vers un fichier</string>
<string name="title_import_keys">importer des clefs</string>
- <string name="title_add_keys">Ajouter des clefs</string>
<string name="title_export_key">Exporter la clef</string>
<string name="title_export_keys">Exporter les clefs</string>
<string name="title_key_not_found">Clef introuvable</string>
@@ -33,10 +29,8 @@
<string name="title_key_details">Détails sur la clef</string>
<string name="title_help">Aide</string>
<string name="title_log_display">Journal</string>
- <string name="title_create_key">Créer une clef</string>
<string name="title_exchange_keys">Échanger des clefs</string>
<string name="title_advanced_key_info">Infos avancées sur les clefs</string>
- <string name="title_keys">Clefs</string>
<string name="title_delete_secret_key">Supprimer VOTRE clef « %s » ?</string>
<string name="title_export_log">Exporter le journal</string>
<string name="title_manage_my_keys">Gérer mes clefs</string>
@@ -48,27 +42,18 @@
<string name="section_cloud_evidence">Preuves provenant du nuage</string>
<string name="section_keys">Sous-clefs</string>
<string name="section_cloud_search">Recherche nuagique</string>
- <string name="section_general">Général</string>
- <string name="section_defaults">Valeurs par défaut</string>
- <string name="section_advanced">Avancée</string>
<string name="section_passphrase_cache">Cache de la phrase de passe</string>
<string name="section_certify">Confirmer</string>
<string name="section_actions">Actions</string>
<string name="section_share_key">Clef</string>
- <string name="section_upload_key">Synchroniser la clef</string>
<string name="section_key_server">Serveur de clefs</string>
<string name="section_fingerprint">Empreinte</string>
- <string name="section_decrypt_files">Fichiers</string>
- <string name="section_decrypt_text">Texte</string>
- <string name="section_certs">Certificats</string>
<string name="section_encrypt">Chiffrer</string>
<string name="section_decrypt">Déchiffrer</string>
<string name="section_current_expiry">Expiration actuelle</string>
<string name="section_new_expiry">Nouvelle expiration</string>
<!--button-->
<string name="btn_decrypt_verify_file">Déchiffrer, vérifier et enregistrer le fichier</string>
- <string name="btn_decrypt_verify_message">Déchiffrer et vérifier le texte</string>
- <string name="btn_encrypt_file">Chiffrer et enregistrer le fichier</string>
<string name="btn_encrypt_share_file">Chiffrer et partager le fichier</string>
<string name="btn_encrypt_save_file">Chiffrer et enregistrer un fichier</string>
<string name="btn_save">Enregistrer</string>
@@ -81,7 +66,6 @@
<string name="btn_back">Retour</string>
<string name="btn_no">Non</string>
<string name="btn_match">Les empreintes correspondent</string>
- <string name="btn_lookup_key">Rechercher la clef</string>
<string name="btn_share_encrypted_signed">Chiffrer et partager du texte</string>
<string name="btn_copy_encrypted_signed">Chiffrer et copier du texte</string>
<string name="btn_view_cert_key">Voir la clef de certification</string>
@@ -100,16 +84,13 @@
<string name="menu_export_key">Exporter vers un fichier</string>
<string name="menu_delete_key">Supprimer la clef</string>
<string name="menu_manage_keys">Gérer mes clefs</string>
- <string name="menu_import_existing_key">Importer d\'un fichier</string>
<string name="menu_search">Rechercher</string>
<string name="menu_nfc_preferences">Paramètres NFC</string>
<string name="menu_beam_preferences">Paramètres Beam</string>
- <string name="menu_key_edit_cancel">Annuler</string>
<string name="menu_encrypt_to">Chiffrer vers...</string>
<string name="menu_select_all">Tout sélectionner</string>
- <string name="menu_add_keys">Ajouter des clefs</string>
- <string name="menu_search_cloud">Rechercher dans le nuage</string>
<string name="menu_export_all_keys">Exporter toutes les clefs</string>
+ <string name="menu_update_all_keys">Mettre toutes les clefs à jour</string>
<string name="menu_advanced">Afficher les infos avancées</string>
<string name="menu_certify_fingerprint">Confirmer par une comparaison d\'empreinte</string>
<string name="menu_export_log">Exporter le journal</string>
@@ -161,6 +142,10 @@
<string name="label_enable_compression">Activer la compression</string>
<string name="label_encrypt_filenames">Chiffrer les nom de fichier</string>
<string name="label_hidden_recipients">Cacher les destinataires</string>
+ <string name="pref_keyserver">Rechercher dans le serveur de clef</string>
+ <string name="pref_keyserver_summary">Rechercher dans le serveur de clef HKP</string>
+ <string name="pref_keybase">Rechercher dans Keybase.io</string>
+ <string name="pref_keybase_summary">Rechercher dans l\'index de Keybase.io</string>
<string name="user_id_no_name">&lt;aucun nom&gt;</string>
<string name="none">&lt;aucune&gt;</string>
<plurals name="n_keys">
@@ -217,9 +202,9 @@
<string name="encrypt_sign_clipboard_successful">Signé et/ou chiffré vers le presse-papiers avec succès.</string>
<string name="select_encryption_key">Choisir au moins une clef de chiffrement.</string>
<string name="select_encryption_or_signature_key">Choisir au moins une clef de chiffrement ou de signature.</string>
- <string name="specify_file_to_encrypt_to">Veuillez spécifier vers quel fichier chiffrer.\nAVERTISSEMENT ! Le fichier sera écrasé s\'il existe.</string>
- <string name="specify_file_to_decrypt_to">Veuillez spécifier vers quel fichier déchiffrer.\nAVERTISSEMENT : le fichier sera écrasé s\'il existe.</string>
- <string name="specify_file_to_export_to">Veuillez spécifier vers quel fichier exporter.\nAVERTISSEMENT ! Le fichier sera écrasé s\'il existe.</string>
+ <string name="specify_file_to_encrypt_to">Veuillez spécifier vers quel fichier chiffrer.\nAVERTISSEMENT : le fichier sera écrasé s\'il existe !</string>
+ <string name="specify_file_to_decrypt_to">Veuillez spécifier vers quel fichier déchiffrer.\nAVERTISSEMENT : le fichier sera écrasé s\'il existe !</string>
+ <string name="specify_file_to_export_to">Veuillez spécifier vers quel fichier exporter.\nAVERTISSEMENT : le fichier sera écrasé s\'il existe !</string>
<string name="key_deletion_confirmation_multi">Voulez-vous vraiment supprimer toutes les clefs sélectionnées ?</string>
<string name="secret_key_deletion_confirmation">Après suppression vous ne pourrez plus lire les messages chiffrés avec cette clef et vous perdrez toutes les confirmations de clefs faites avec elle !</string>
<string name="public_key_deletetion_confirmation">Supprimer la clef \'%s\' ?</string>
@@ -289,6 +274,7 @@
<string name="progress_cancelling">annulation...</string>
<string name="progress_saving">sauvegarde...</string>
<string name="progress_importing">importation...</string>
+ <string name="progress_updating">Mise à jour des clefs...</string>
<string name="progress_exporting">exportation...</string>
<string name="progress_uploading">téléversement...</string>
<string name="progress_building_key">assemblage de la clef...</string>
@@ -589,6 +575,7 @@
<string name="create_key_edit">Changer la configuration de la clef</string>
<string name="create_key_add_email">Ajouter une adresse courriel</string>
<string name="create_key_add_email_text">Des adresses courriel supplémentaires sont aussi associées à cette clef et peuvent être utilisées pour des communications sécurisées.</string>
+ <string name="create_key_email_already_exists_text">Le courriel a déjà été ajouté</string>
<!--View key-->
<string name="view_key_revoked">Révoquée : la clef ne doit plus être utilisée !</string>
<string name="view_key_expired">Expirée : le contact doit prolonger la validité de la clef !</string>
@@ -1111,7 +1098,7 @@
<string name="passp_cache_notif_pwd">Phrase de passe</string>
<!--First Time-->
<string name="first_time_text1">Reprenez le contrôle de votre vie privée avec OpenKeychain |</string>
- <string name="first_time_create_key">Créer ma clef (recommandé)</string>
+ <string name="first_time_create_key">Créer ma clef</string>
<string name="first_time_import_key">Importer la clef d\'un fichier</string>
<string name="first_time_yubikey">Utiliser YubiKey NEO</string>
<string name="first_time_skip">Ignorer le paramétrage</string>
diff --git a/OpenKeychain/src/main/res/values-it/strings.xml b/OpenKeychain/src/main/res/values-it/strings.xml
index 4d0e4d6cb..6db044b49 100644
--- a/OpenKeychain/src/main/res/values-it/strings.xml
+++ b/OpenKeychain/src/main/res/values-it/strings.xml
@@ -4,12 +4,9 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">Seleziona chiavi</string>
- <string name="title_select_secret_key">Seleziona la tua chiave</string>
<string name="title_decrypt">Decodifica</string>
<string name="title_add_subkey">Aggiungi Sottochiave</string>
<string name="title_edit_key">Modifica Chiave</string>
- <string name="title_cloud_search_preferences">Preferenze di ricerca</string>
<string name="title_api_registered_apps">Apps</string>
<string name="title_change_passphrase">Cambia Frase Di Accesso</string>
<string name="title_share_fingerprint_with">Condivi impronta con...</string>
@@ -18,7 +15,6 @@
<string name="title_encrypt_to_file">Codifica File</string>
<string name="title_decrypt_to_file">Decodifica File</string>
<string name="title_import_keys">Importa Chiavi</string>
- <string name="title_add_keys">Aggiungi Chiavi</string>
<string name="title_export_key">Esporta Chiave</string>
<string name="title_export_keys">Esporta Chiavi</string>
<string name="title_key_not_found">Chiave Non Trovata</string>
@@ -26,28 +22,19 @@
<string name="title_key_details">Dettagli Chiave</string>
<string name="title_help">Aiuto</string>
<string name="title_log_display">Registro</string>
- <string name="title_create_key">Crea Chiave</string>
<string name="title_exchange_keys">Scambia le chiavi</string>
<string name="title_advanced_key_info">Informazioni avanzate sulla chiave</string>
<!--section-->
<string name="section_user_ids">Identità</string>
<string name="section_keys">Sottochiavi</string>
<string name="section_cloud_search">Ricerca</string>
- <string name="section_general">Generale</string>
- <string name="section_defaults">Predefiniti</string>
- <string name="section_advanced">Avanzato</string>
<string name="section_passphrase_cache">Cache Frase di Accesso</string>
<string name="section_actions">Azioni</string>
<string name="section_share_key">Chiave</string>
- <string name="section_upload_key">Sincronizza Chiave</string>
<string name="section_key_server">Server delle Chiavi</string>
<string name="section_fingerprint">Impronta</string>
- <string name="section_decrypt_files">Files</string>
- <string name="section_decrypt_text">Testo</string>
- <string name="section_certs">Certificati</string>
<!--button-->
<string name="btn_decrypt_verify_file">Decodifica, verifica e salva su file</string>
- <string name="btn_encrypt_file">Codifica e salva file</string>
<string name="btn_encrypt_share_file">Codifica e condividi file</string>
<string name="btn_save">Salva</string>
<string name="btn_do_not_save">Annulla</string>
@@ -57,7 +44,6 @@
<string name="btn_export_to_server">Carica sul Server delle Chiavi</string>
<string name="btn_next">Prossimo</string>
<string name="btn_back">Precedente</string>
- <string name="btn_lookup_key">Chiave di ricerca</string>
<string name="btn_view_cert_key">Mostra chiave di certificazione</string>
<string name="btn_create_key">Crea chiave</string>
<string name="btn_add_files">Aggiungi file(s)</string>
@@ -69,13 +55,10 @@
<string name="menu_help">Aiuto</string>
<string name="menu_export_key">Esporta su un file</string>
<string name="menu_delete_key">Cancella chiave</string>
- <string name="menu_import_existing_key">Importa da file</string>
<string name="menu_search">Cerca</string>
<string name="menu_beam_preferences">Impostazioni Beam</string>
- <string name="menu_key_edit_cancel">Annulla</string>
<string name="menu_encrypt_to">Codifica su...</string>
<string name="menu_select_all">Seleziona tutto</string>
- <string name="menu_add_keys">Aggiungi chiavi</string>
<string name="menu_export_all_keys">Esporta tutte le chiavi</string>
<string name="menu_advanced">Mostra informazioni avanzate</string>
<!--label-->
@@ -167,12 +150,6 @@
<string name="encrypt_sign_clipboard_successful">Firmato e/o codificato con successo negli appunti.</string>
<string name="select_encryption_key">Seleziona almeno una chiave di codifica.</string>
<string name="select_encryption_or_signature_key">Seleziona almeno una chiave di codifica o di firma.</string>
- <string name="specify_file_to_encrypt_to">Perfavore specifica il file da codificare.
-ATTENZIONE: Il file sara\' sovrascritto se esistente.</string>
- <string name="specify_file_to_decrypt_to">Perfavore specifica il file da decodificare.
-ATTENZIONE: Il file sara\' sovrascritto se esistente.</string>
- <string name="specify_file_to_export_to">Perfavore specifica il file da esportare.
-ATTENZIONE: Il file sara\' sovrascritto se esistente.</string>
<string name="also_export_secret_keys">Esporta anche chiave segreta</string>
<string name="reinstall_openkeychain">Hai riscontrato un bug noto con Android. Si prega di reinstallare OpenKeychain se vuoi collegare i tuoi contatti con le chiavi.</string>
<string name="key_exported">1 chiave esportata correttamente.</string>
diff --git a/OpenKeychain/src/main/res/values-ja/strings.xml b/OpenKeychain/src/main/res/values-ja/strings.xml
index d77ae0cf6..13647a1bb 100644
--- a/OpenKeychain/src/main/res/values-ja/strings.xml
+++ b/OpenKeychain/src/main/res/values-ja/strings.xml
@@ -4,8 +4,6 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">鍵を選択</string>
- <string name="title_select_secret_key">あなたの鍵を選択</string>
<string name="title_encrypt_text">暗号化</string>
<string name="title_encrypt_files">暗号化</string>
<string name="title_decrypt">復号化</string>
@@ -13,7 +11,6 @@
<string name="title_add_subkey">副鍵の追加</string>
<string name="title_edit_key">鍵の編集</string>
<string name="title_preferences">設定</string>
- <string name="title_cloud_search_preferences">クラウド検索設定</string>
<string name="title_api_registered_apps">アプリ</string>
<string name="title_key_server_preference">鍵サーバ</string>
<string name="title_change_passphrase">パスフレーズの変更</string>
@@ -24,7 +21,6 @@
<string name="title_encrypt_to_file">暗号化してファイルに</string>
<string name="title_decrypt_to_file">復号化してファイルに</string>
<string name="title_import_keys">鍵のインポート</string>
- <string name="title_add_keys">鍵の追加</string>
<string name="title_export_key">鍵のエクスポート</string>
<string name="title_export_keys">複数鍵のエクスポート</string>
<string name="title_key_not_found">鍵が見当りません</string>
@@ -33,10 +29,8 @@
<string name="title_key_details">鍵の概要</string>
<string name="title_help">ヘルプ</string>
<string name="title_log_display">ログ</string>
- <string name="title_create_key">鍵の生成</string>
<string name="title_exchange_keys">鍵の交換</string>
<string name="title_advanced_key_info">鍵の詳細情報</string>
- <string name="title_keys">鍵</string>
<string name="title_delete_secret_key">あなたの鍵 \'%s\' を削除しますか?</string>
<string name="title_export_log">エクスポートログ</string>
<string name="title_manage_my_keys">自分の鍵の管理</string>
@@ -48,27 +42,18 @@
<string name="section_cloud_evidence">クラウドからの証明</string>
<string name="section_keys">副鍵</string>
<string name="section_cloud_search">クラウド検索</string>
- <string name="section_general">一般</string>
- <string name="section_defaults">デフォルト</string>
- <string name="section_advanced">拡張</string>
<string name="section_passphrase_cache">パスフレーズキャッシュ</string>
<string name="section_certify">確認</string>
<string name="section_actions">アクション</string>
<string name="section_share_key">鍵</string>
- <string name="section_upload_key">鍵の同期</string>
<string name="section_key_server">鍵サーバ</string>
<string name="section_fingerprint">指紋</string>
- <string name="section_decrypt_files">ファイル</string>
- <string name="section_decrypt_text">テキスト</string>
- <string name="section_certs">証明</string>
<string name="section_encrypt">暗号化</string>
<string name="section_decrypt">復号化</string>
<string name="section_current_expiry">現在の期限</string>
<string name="section_new_expiry">新しい期限</string>
<!--button-->
<string name="btn_decrypt_verify_file">復号化と検証、そしてファイルの保存</string>
- <string name="btn_decrypt_verify_message">テキストの復号化と検証</string>
- <string name="btn_encrypt_file">暗号化してファイルを保存</string>
<string name="btn_encrypt_share_file">暗号化してファイルを共有</string>
<string name="btn_encrypt_save_file">暗号化してファイルを保存</string>
<string name="btn_save">保存</string>
@@ -81,7 +66,6 @@
<string name="btn_back">戻る</string>
<string name="btn_no">なし</string>
<string name="btn_match">指紋一致</string>
- <string name="btn_lookup_key">鍵検出</string>
<string name="btn_share_encrypted_signed">暗号化してテキストを共有</string>
<string name="btn_copy_encrypted_signed">暗号化してテキストをコピー</string>
<string name="btn_view_cert_key">検証した鍵を見る</string>
@@ -100,16 +84,13 @@
<string name="menu_export_key">ファイルへのエクスポート</string>
<string name="menu_delete_key">鍵の削除</string>
<string name="menu_manage_keys">自分の鍵の管理</string>
- <string name="menu_import_existing_key">ファイルからインポート</string>
<string name="menu_search">検索</string>
<string name="menu_nfc_preferences">NFC設定</string>
<string name="menu_beam_preferences">Beamの設定</string>
- <string name="menu_key_edit_cancel">キャンセル</string>
<string name="menu_encrypt_to">暗号化...</string>
<string name="menu_select_all">すべて選択</string>
- <string name="menu_add_keys">鍵の追加</string>
- <string name="menu_search_cloud">クラウドを検索</string>
<string name="menu_export_all_keys">すべての鍵のエクスポート</string>
+ <string name="menu_update_all_keys">全部のキーをアップデートする</string>
<string name="menu_advanced">詳細情報を表示</string>
<string name="menu_certify_fingerprint">指紋比較による確認</string>
<string name="menu_export_log">エクスポートログ</string>
@@ -161,6 +142,10 @@
<string name="label_enable_compression">圧縮を有効</string>
<string name="label_encrypt_filenames">暗号化するファイル名</string>
<string name="label_hidden_recipients">受信者を隠す</string>
+ <string name="pref_keyserver">キーサーバーで探す</string>
+ <string name="pref_keyserver_summary">HKPキーサーバーで探す</string>
+ <string name="pref_keybase">Keybase.ioで探す</string>
+ <string name="pref_keybase_summary">Keybase.ioのインデックスで探す</string>
<string name="user_id_no_name">&lt;名前なし&gt;</string>
<string name="none">&lt;無し&gt;</string>
<plurals name="n_keys">
@@ -215,12 +200,9 @@
<string name="encrypt_sign_clipboard_successful">クリップボードの中身の署名/暗号化に成功しました。</string>
<string name="select_encryption_key">少なくとも1つの暗号化鍵を選択して下さい。</string>
<string name="select_encryption_or_signature_key">少なくとも1つの暗号化鍵か署名鍵を選択して下さい。</string>
- <string name="specify_file_to_encrypt_to">どのファイルを暗号化するか決めてください。
-注意: 既存のファイルがあると上書きされます。</string>
- <string name="specify_file_to_decrypt_to">どのファイルを復号化するか決めてください。
-注意: 既存のファイルがあると上書きされます。</string>
- <string name="specify_file_to_export_to">どのファイルをエクスポートするか決めてください。
-注意: 既存のファイルがあると上書きされます。</string>
+ <string name="specify_file_to_encrypt_to">どれのファイルを暗号化するのを入力してください。\n注意:ファイルが存在しているなら上書きされる!</string>
+ <string name="specify_file_to_decrypt_to">どれのファイルを暗号するのを入力してください。\n注意:ファイルが存在しているなら上書きされる!</string>
+ <string name="specify_file_to_export_to">どれのファイルを復号化するのを入力してください。\n注意:ファイルが存在しているなら上書きされる!</string>
<string name="key_deletion_confirmation_multi">選択したすべての鍵を本当に削除してよいですか?</string>
<string name="secret_key_deletion_confirmation">削除後はこの鍵で暗号化されたメッセージが読めなくなります、またその鍵で行われたすべての鍵確認を失います!</string>
<string name="public_key_deletetion_confirmation">鍵 \'%s\' を削除しますか?</string>
@@ -294,6 +276,7 @@
<string name="progress_cancelling">キャンセル中...</string>
<string name="progress_saving">保存...</string>
<string name="progress_importing">インポート...</string>
+ <string name="progress_updating">キーをアップデート中。。。</string>
<string name="progress_exporting">エクスポート...</string>
<string name="progress_uploading">アップロード中...</string>
<string name="progress_building_key">鍵の構築中...</string>
@@ -512,12 +495,16 @@
<string name="key_trust_maybe">この鍵はすでに破棄されたか期限切れです。\n確認済みではなく、しかしあなたは信頼すると選択することもできます。</string>
<string name="key_trust_revoked">このIDは鍵の所有者により破棄されています。信頼することはできません。</string>
<string name="key_trust_expired">この鍵は期限切れです。信頼することができません。</string>
+ <string name="key_trust_old_keys">このキーの有効な日付の時で書いてあるメッセージを復号化 するのは恐らく大丈夫です。</string>
<string name="key_trust_no_cloud_evidence">この鍵の信頼性についてのクラウドでの検証がありません。</string>
<string name="key_trust_start_cloud_search">検索開始</string>
+ <string name="key_trust_results_prefix">Keybase.ioはこのキーのオーナーだと言う証拠を提供している:</string>
+ <string name="key_trust_header_text">注意:Keybase.ioのオーナー証拠は実験的な機会です。キーを確認することに加えて、QRコードや、NFCでキーを交換するのもお勧めする。</string>
<!--keybase proof stuff-->
<string name="keybase_narrative_twitter">Twitterへ以下のIDで投稿</string>
<string name="keybase_narrative_github">Githubでは以下のIDで知られています</string>
<string name="keybase_narrative_dns">制御下にあるドメイン名(たち)</string>
+ <string name="keybase_narrative_web_site">サイトに投稿できる</string>
<string name="keybase_narrative_reddit">Redditへ以下のIDで投稿</string>
<string name="keybase_narrative_coinbase">Coinbaseでは以下で知られています</string>
<string name="keybase_narrative_hackernews">Hacker Newsへ以下のIDで投稿</string>
@@ -580,6 +567,7 @@
<string name="create_key_edit">鍵の設定変更</string>
<string name="create_key_add_email">Eメールアドレスの追加</string>
<string name="create_key_add_email_text">追加のEメールアドレスがこの鍵に紐付きそしてセキュアな通信に使うことができます。</string>
+ <string name="create_key_email_already_exists_text">メールはすでに追加している</string>
<!--View key-->
<string name="view_key_revoked">破棄: 鍵はもう使われません!</string>
<string name="view_key_expired">期限切れ: この連絡先は鍵の妥当性を拡張する必要があります!</string>
@@ -1081,7 +1069,7 @@
<string name="passp_cache_notif_pwd">パスフレーズ</string>
<!--First Time-->
<string name="first_time_text1">OpenKeychainであなたのプライバシーを取り戻しましょう!</string>
- <string name="first_time_create_key">自分の鍵の生成(推奨)</string>
+ <string name="first_time_create_key">自分のキーを作る</string>
<string name="first_time_import_key">ファイルから鍵をインポート</string>
<string name="first_time_yubikey">YubiKey NEOを使用する</string>
<string name="first_time_skip">セットアップをスキップ</string>
diff --git a/OpenKeychain/src/main/res/values-nl/strings.xml b/OpenKeychain/src/main/res/values-nl/strings.xml
index 04c6f10f4..74e2c7117 100644
--- a/OpenKeychain/src/main/res/values-nl/strings.xml
+++ b/OpenKeychain/src/main/res/values-nl/strings.xml
@@ -4,8 +4,6 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">Selecteer sleutels</string>
- <string name="title_select_secret_key">Selecteer je sleutel</string>
<string name="title_encrypt_text">Versleutelen</string>
<string name="title_encrypt_files">Versleutelen</string>
<string name="title_decrypt">Ontsleutelen</string>
@@ -13,7 +11,6 @@
<string name="title_add_subkey">Voeg subsleutel toe</string>
<string name="title_edit_key">Sleutel bewerken</string>
<string name="title_preferences">Instellingen</string>
- <string name="title_cloud_search_preferences">Cloud-zoekvoorkeuren</string>
<string name="title_api_registered_apps">Apps</string>
<string name="title_key_server_preference">Sleutelservers</string>
<string name="title_change_passphrase">Wachtwoord wijzigen</string>
@@ -24,7 +21,6 @@
<string name="title_encrypt_to_file">Versleutelen naar bestand</string>
<string name="title_decrypt_to_file">Ontsleutelen naar bestand</string>
<string name="title_import_keys">Sleutels importeren</string>
- <string name="title_add_keys">Voeg sleutels toe</string>
<string name="title_export_key">Sleutels exporteren</string>
<string name="title_export_keys">Sleutels exporteren</string>
<string name="title_key_not_found">Sleutel niet gevonden</string>
@@ -33,10 +29,8 @@
<string name="title_key_details">Sleutel Details</string>
<string name="title_help">Help</string>
<string name="title_log_display">Log</string>
- <string name="title_create_key">Sleutel aanmaken</string>
<string name="title_exchange_keys">Sleutels uitwisselen</string>
<string name="title_advanced_key_info">Geavanceerde sleutelinfo</string>
- <string name="title_keys">Sleutels</string>
<string name="title_delete_secret_key">JOUW sleutel \'%s\' verwijderen?</string>
<string name="title_export_log">Log exporteren</string>
<string name="title_manage_my_keys">Beheer mijn sleutels</string>
@@ -48,27 +42,18 @@
<string name="section_cloud_evidence">Bewijzen van de cloud</string>
<string name="section_keys">Subsleutels</string>
<string name="section_cloud_search">Cloud zoeken</string>
- <string name="section_general">Algemeen</string>
- <string name="section_defaults">Standaard</string>
- <string name="section_advanced">Geavanceerd</string>
<string name="section_passphrase_cache">Wachtwoordcache</string>
<string name="section_certify">Bevestigen</string>
<string name="section_actions">Acties</string>
<string name="section_share_key">Sleutel</string>
- <string name="section_upload_key">Synchroniseer sleutel</string>
<string name="section_key_server">Sleutelserver</string>
<string name="section_fingerprint">Vingerafdruk</string>
- <string name="section_decrypt_files">Bestanden</string>
- <string name="section_decrypt_text">Tekst</string>
- <string name="section_certs">Certificaten</string>
<string name="section_encrypt">Versleutelen</string>
<string name="section_decrypt">Ontsleutelen</string>
<string name="section_current_expiry">Huidige verloopdatum</string>
<string name="section_new_expiry">Nieuwe verloopdatum</string>
<!--button-->
<string name="btn_decrypt_verify_file">Decodeer, verifiëer en sla bestand op</string>
- <string name="btn_decrypt_verify_message">Tekst ontsleutelen en verifiëren</string>
- <string name="btn_encrypt_file">Codeer en sla bestanden op</string>
<string name="btn_encrypt_share_file">Bestand versleutelen en delen</string>
<string name="btn_encrypt_save_file">Bestand versleutelen en opslaan</string>
<string name="btn_save">Opslaan</string>
@@ -81,7 +66,6 @@
<string name="btn_back">Terug</string>
<string name="btn_no">Nee</string>
<string name="btn_match">Vingerafdrukken komen overeen</string>
- <string name="btn_lookup_key">Opzoeksleutel</string>
<string name="btn_share_encrypted_signed">Tekst versleutelen en opslaan</string>
<string name="btn_copy_encrypted_signed">Tekst versleutelen en kopiëren</string>
<string name="btn_view_cert_key">Toon certificatiesleutel</string>
@@ -100,16 +84,13 @@
<string name="menu_export_key">Exporteren naar bestand</string>
<string name="menu_delete_key">Sleutel verwijderen</string>
<string name="menu_manage_keys">Beheer mijn sleutels</string>
- <string name="menu_import_existing_key">Importeren van bestand</string>
<string name="menu_search">Zoeken</string>
<string name="menu_nfc_preferences">NFC-instellingen</string>
<string name="menu_beam_preferences">Beam-instellingen</string>
- <string name="menu_key_edit_cancel">Annuleren</string>
<string name="menu_encrypt_to">Versleutelen naar…</string>
<string name="menu_select_all">Alles selecteren</string>
- <string name="menu_add_keys">Sleutels toevoegen</string>
- <string name="menu_search_cloud">Zoeken</string>
<string name="menu_export_all_keys">Alle sleutels exporteren</string>
+ <string name="menu_update_all_keys">Alle sleutels bijwerken</string>
<string name="menu_advanced">Geavanceerde info tonen</string>
<string name="menu_certify_fingerprint">Bevestigen door vingerafdrukken te vergelijken</string>
<string name="menu_export_log">Log exporteren</string>
@@ -161,6 +142,10 @@
<string name="label_enable_compression">Compressie aanzetten</string>
<string name="label_encrypt_filenames">Versleutel bestandsnamen</string>
<string name="label_hidden_recipients">Verberg ontvangers</string>
+ <string name="pref_keyserver">Zoeken op sleutelserver</string>
+ <string name="pref_keyserver_summary">Zoeken op HKP sleutelserver</string>
+ <string name="pref_keybase">Zoeken op Keybase.io</string>
+ <string name="pref_keybase_summary">Zoeken in Keybase.io-index</string>
<string name="user_id_no_name">&lt;no naam&gt;</string>
<string name="none">&lt;geen&gt;</string>
<plurals name="n_keys">
@@ -217,9 +202,9 @@
<string name="encrypt_sign_clipboard_successful">Succesvol gesigneerd en/of gecodeerd naar klembord.</string>
<string name="select_encryption_key">Selecteer ten minste één versleutelingssleutel.</string>
<string name="select_encryption_or_signature_key">Selecter ten minste één versleutelings-/ondertekeningssleutel.</string>
- <string name="specify_file_to_encrypt_to">Gelieve aan te geven naar welk bestand versleuteld moet worden.\nWAARSCHUWING: Als het bestand al bestaat, zal het overschreven worden.</string>
- <string name="specify_file_to_decrypt_to">Gelieve aan te geven naar welk bestand ontcijferd moet worden.\nWAARSCHUWING: Als het bestand al bestaat, zal het overschreven worden.</string>
- <string name="specify_file_to_export_to">Gelieve aan te geven naar welk bestand geëxporteerd moet worden.\nWAARSCHUWING: Als het bestand al bestaat, zal het overschreven worden.</string>
+ <string name="specify_file_to_encrypt_to">Gelieve aan te geven naar welk bestand versleuteld moet worden.\nWAARSCHUWING: Als het bestand al bestaat, zal het overschreven worden!</string>
+ <string name="specify_file_to_decrypt_to">Gelieve aan te geven naar welk bestand ontcijferd moet worden.\nWAARSCHUWING: Als het bestand al bestaat, zal het overschreven worden!</string>
+ <string name="specify_file_to_export_to">Gelieve aan te geven naar welk bestand geëxporteerd moet worden.\nWAARSCHUWING: Als het bestand al bestaat, zal het overschreven worden!</string>
<string name="key_deletion_confirmation_multi">Ben je zeker dat je alle geselecteerde sleutels wil verwijderen?</string>
<string name="secret_key_deletion_confirmation">Na verwijderen zal je niet langer berichten versleuteld met deze sleutel kunnen lezen, en alle sleutelbevestigingen die ermee gedaan zijn verliezen!</string>
<string name="public_key_deletetion_confirmation">Sleutel \'%s\' verwijderen?</string>
@@ -289,6 +274,7 @@
<string name="progress_cancelling">bezig met annuleren…</string>
<string name="progress_saving">opslaan…</string>
<string name="progress_importing">importeren…</string>
+ <string name="progress_updating">Bezig met bijwerken van sleutels…</string>
<string name="progress_exporting">exporteren…</string>
<string name="progress_uploading">bezig met uploaden…</string>
<string name="progress_building_key">sleutel maken…</string>
@@ -589,6 +575,7 @@
<string name="create_key_edit">Sleutelconfiguratie wijzigen</string>
<string name="create_key_add_email">E-mailadres toevoegen</string>
<string name="create_key_add_email_text">Bijkomstige e-mailadressen zijn ook verbonden met deze sleutel en kunnen gebruikt worden voor veilige communicatie.</string>
+ <string name="create_key_email_already_exists_text">E-mail is al toegevoegd</string>
<!--View key-->
<string name="view_key_revoked">Ingetrokken: sleutel mag niet meer gebruikt worden!</string>
<string name="view_key_expired">Verlopen: het contact moet de geldigheid van de sleutel verlengen!</string>
@@ -1111,7 +1098,7 @@
<string name="passp_cache_notif_pwd">Wachtwoord</string>
<!--First Time-->
<string name="first_time_text1">Neem je privacy terug met OpenKeychain!</string>
- <string name="first_time_create_key">Maak mijn sleutel aan (aanbevolen)</string>
+ <string name="first_time_create_key">Mijn sleutel aanmaken</string>
<string name="first_time_import_key">Sleutel importeren uit bestand</string>
<string name="first_time_yubikey">Gebruik YubiKey NEO</string>
<string name="first_time_skip">Setup overslaan</string>
diff --git a/OpenKeychain/src/main/res/values-pl/strings.xml b/OpenKeychain/src/main/res/values-pl/strings.xml
index cbaca4aa1..b0cf1abaa 100644
--- a/OpenKeychain/src/main/res/values-pl/strings.xml
+++ b/OpenKeychain/src/main/res/values-pl/strings.xml
@@ -4,14 +4,11 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">Wybierz klucze</string>
- <string name="title_select_secret_key">Wybierz swój klucz</string>
<string name="title_decrypt">Odszyfruj</string>
<string name="title_unlock">Odblokuj klucz</string>
<string name="title_add_subkey">Dodaj pod-klucz</string>
<string name="title_edit_key">Edytuj klucz</string>
<string name="title_preferences">Ustawienia</string>
- <string name="title_cloud_search_preferences">Właściwości Szukania w Chmurze</string>
<string name="title_api_registered_apps">Aplikacje</string>
<string name="title_key_server_preference">Serwery kluczy</string>
<string name="title_change_passphrase">Zmień hasło</string>
@@ -21,7 +18,6 @@
<string name="title_encrypt_to_file">Zaszyfruj do pliku</string>
<string name="title_decrypt_to_file">Odszyfruj do pliku</string>
<string name="title_import_keys">Importuj klucze</string>
- <string name="title_add_keys">Dodaj klucze</string>
<string name="title_export_key">Eksportuj klucz</string>
<string name="title_export_keys">Eksportuj klucze</string>
<string name="title_key_not_found">Nie znaleziono klucza</string>
@@ -29,31 +25,21 @@
<string name="title_key_details">Szczegóły klucza</string>
<string name="title_help">Pomoc</string>
<string name="title_log_display">Logi</string>
- <string name="title_create_key">Utwórz klucz</string>
<string name="title_exchange_keys">Wymień się kluczami</string>
<string name="title_advanced_key_info">Zaawansowane informacje o kluczu</string>
- <string name="title_keys">Klucze</string>
<!--section-->
<string name="section_user_ids">Tożsamości</string>
<string name="section_keys">Pod-klucze</string>
<string name="section_cloud_search">Szukanie w Chmurze</string>
- <string name="section_general">Ogólne</string>
- <string name="section_defaults">Domyślne</string>
- <string name="section_advanced">Zaawansowane</string>
<string name="section_passphrase_cache">Pamięć cache hasła</string>
<string name="section_actions">Działania</string>
<string name="section_share_key">Klucz</string>
- <string name="section_upload_key">Synchronizuj Klucz</string>
<string name="section_key_server">Serwer kluczy</string>
<string name="section_fingerprint">Odcisk klucza</string>
- <string name="section_decrypt_files">Pliki</string>
- <string name="section_decrypt_text">Tekst</string>
- <string name="section_certs">Certyfikaty</string>
<string name="section_encrypt">Zaszyfruj</string>
<string name="section_decrypt">Odszyfruj</string>
<!--button-->
<string name="btn_decrypt_verify_file">Odszyfruj, weryfikuj i zapisz plik</string>
- <string name="btn_encrypt_file">Szyfruj i zapisz plik</string>
<string name="btn_encrypt_share_file">Szyfruj i podziel się plikiem</string>
<string name="btn_save">Zapisz</string>
<string name="btn_do_not_save">Anuluj</string>
@@ -63,7 +49,6 @@
<string name="btn_export_to_server">Wyślij do serwera kluczy</string>
<string name="btn_next">Dalej</string>
<string name="btn_back">Wstecz</string>
- <string name="btn_lookup_key">Sprawdź klucz</string>
<string name="btn_view_cert_key">Wyświetl klucz certyfikacji</string>
<string name="btn_create_key">Utwórz klucz</string>
<string name="btn_add_files">Dodaj plik(i)</string>
@@ -78,13 +63,10 @@
<string name="menu_help">Pomoc</string>
<string name="menu_export_key">Eksportuj do pliku</string>
<string name="menu_delete_key">Usuń klucz</string>
- <string name="menu_import_existing_key">Importuj z pliku</string>
<string name="menu_search">Szukaj</string>
<string name="menu_beam_preferences">Ustawienia Beam</string>
- <string name="menu_key_edit_cancel">Anuluj</string>
<string name="menu_encrypt_to">Zaszyfruj do...</string>
<string name="menu_select_all">Wybierz wszystko</string>
- <string name="menu_add_keys">Dodaj klucze</string>
<string name="menu_export_all_keys">Eksportuj wszystkie klucze</string>
<string name="menu_advanced">Pokaż zaawansowane informacje</string>
<!--label-->
@@ -182,9 +164,6 @@
<string name="encrypt_sign_clipboard_successful">Pomyslnie podpisano i/lub zaszyfrowano do schowka.</string>
<string name="select_encryption_key">Wybierz co najmniej jeden klucz szyfrujący.</string>
<string name="select_encryption_or_signature_key">Wybierz co najmniej jeden klucz szyfrujący lub klucz podpisujący.</string>
- <string name="specify_file_to_encrypt_to">Wskaż, do którego pliku zapisać zaszyfrowane dane.\nOSTRZEŻENIE: Plik zostanie nadpisany, jeżeli istnieje.</string>
- <string name="specify_file_to_decrypt_to">Wskaż, do którego pliku zapisać odszyfrowane dane.\nOSTRZEŻENIE: Plik zostanie nadpisany, jeżeli istnieje.</string>
- <string name="specify_file_to_export_to">Wskaż, do którego pliku wyeksportować dane.\nOSTRZEŻENIE: Plik zostanie nadpisany, jeżeli istnieje.</string>
<string name="also_export_secret_keys">Także eksportuj tajne klucze</string>
<string name="reinstall_openkeychain">Napotkałeś się na znany błąd w Androidzie. Proszę ponownie zainstalować OpenKeychain jeśli chcesz połączyć kontakty z kluczami.</string>
<string name="key_exported">Pomyślnie wyeksportowano 1 klucz.</string>
diff --git a/OpenKeychain/src/main/res/values-ru/strings.xml b/OpenKeychain/src/main/res/values-ru/strings.xml
index 0724ced26..2dd1821ee 100644
--- a/OpenKeychain/src/main/res/values-ru/strings.xml
+++ b/OpenKeychain/src/main/res/values-ru/strings.xml
@@ -4,16 +4,13 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">Выберите ключи</string>
- <string name="title_select_secret_key">Выберите Ваш ключ</string>
<string name="title_encrypt_text">Зашифровать текст</string>
<string name="title_encrypt_files">Зашифровать файлы</string>
<string name="title_decrypt">Расшифровать</string>
<string name="title_unlock">Разблокировать ключ</string>
- <string name="title_add_subkey">Добавить доп. ключ</string>
+ <string name="title_add_subkey">Добавить подключ</string>
<string name="title_edit_key">Изменить ключ</string>
<string name="title_preferences">Настройки</string>
- <string name="title_cloud_search_preferences">Настройки облачного поиска</string>
<string name="title_api_registered_apps">Приложения</string>
<string name="title_key_server_preference">Серверы ключей</string>
<string name="title_change_passphrase">Изменить пароль</string>
@@ -24,7 +21,6 @@
<string name="title_encrypt_to_file">Зашифровать в файл</string>
<string name="title_decrypt_to_file">Расшифровать в файл</string>
<string name="title_import_keys">Импорт ключей</string>
- <string name="title_add_keys">Добавить ключи</string>
<string name="title_export_key">Экспортировать ключ</string>
<string name="title_export_keys">Экспорт ключей</string>
<string name="title_key_not_found">Ключ не найден</string>
@@ -33,10 +29,8 @@
<string name="title_key_details">Сведения о ключе</string>
<string name="title_help">Помощь</string>
<string name="title_log_display">Журнал</string>
- <string name="title_create_key">Создать ключ</string>
<string name="title_exchange_keys">Обмен ключами</string>
<string name="title_advanced_key_info">Детальная информация о ключе</string>
- <string name="title_keys">Ключи</string>
<string name="title_delete_secret_key">Удалить ВАШ ключ \'%s\'?</string>
<!--section-->
<string name="section_user_ids">Идентификаторы</string>
@@ -46,26 +40,17 @@
<string name="section_cloud_evidence">Подтвердить из облака</string>
<string name="section_keys">Доп. ключи</string>
<string name="section_cloud_search">Облачный поиск</string>
- <string name="section_general">Приложение</string>
- <string name="section_defaults">Алгоритмы</string>
- <string name="section_advanced">Дополнительно</string>
<string name="section_passphrase_cache">Кэш пароля</string>
<string name="section_actions">Действия</string>
<string name="section_share_key">Ключ</string>
- <string name="section_upload_key">Синхронизировать ключ</string>
<string name="section_key_server">Сервер ключей</string>
<string name="section_fingerprint">Отпечаток ключа</string>
- <string name="section_decrypt_files">Файлы</string>
- <string name="section_decrypt_text">Текст</string>
- <string name="section_certs">Сертификаты</string>
<string name="section_encrypt">Зашифровать</string>
<string name="section_decrypt">Расшифровать</string>
<string name="section_current_expiry">Текущий срок годности</string>
<string name="section_new_expiry">Новый срок годности</string>
<!--button-->
<string name="btn_decrypt_verify_file">Расшифровать, проверить и сохранить файл</string>
- <string name="btn_decrypt_verify_message">Расшифровать и проверить текст</string>
- <string name="btn_encrypt_file">Зашифровать и сохранить файл</string>
<string name="btn_encrypt_share_file">Зашифровать и отправить файл</string>
<string name="btn_save">Сохранить</string>
<string name="btn_do_not_save">Отмена</string>
@@ -77,7 +62,6 @@
<string name="btn_back">Назад</string>
<string name="btn_no">Нет</string>
<string name="btn_match">Отпечатки совпадают</string>
- <string name="btn_lookup_key">Найти ключ</string>
<string name="btn_view_cert_key">Просмотр ключа</string>
<string name="btn_create_key">Создать ключ</string>
<string name="btn_add_files">Добавить файл(ы)</string>
@@ -92,15 +76,11 @@
<string name="menu_help">Помощь</string>
<string name="menu_export_key">Экспорт в файл</string>
<string name="menu_delete_key">Удалить ключ</string>
- <string name="menu_import_existing_key">Импорт из файла</string>
<string name="menu_search">Поиск</string>
<string name="menu_nfc_preferences">Настройки NFC</string>
<string name="menu_beam_preferences">Настройки Beam</string>
- <string name="menu_key_edit_cancel">Отмена</string>
<string name="menu_encrypt_to">Зашифровать....</string>
<string name="menu_select_all">Выбрать все</string>
- <string name="menu_add_keys">Добавить ключи</string>
- <string name="menu_search_cloud">Поиск в облаке</string>
<string name="menu_export_all_keys">Экспорт всех ключей</string>
<string name="menu_advanced">Подробные данные</string>
<!--label-->
@@ -127,6 +107,7 @@
<string name="label_symmetric">Зашифровать паролем</string>
<string name="label_passphrase_cache_ttl">Время хранения в кэше</string>
<string name="label_passphrase_cache_subs">Кэшировать пароли по доп. ключу</string>
+ <string name="label_message_compression">Сжатие текста</string>
<string name="label_file_compression">Сжатие файла</string>
<string name="label_keyservers">Серверы ключей</string>
<string name="label_key_id">ID ключа</string>
@@ -202,9 +183,6 @@
<string name="encrypt_sign_clipboard_successful">Успешно подписано и/или зашифровано в буфер обмена.</string>
<string name="select_encryption_key">Укажите хотя бы один ключ.</string>
<string name="select_encryption_or_signature_key">Выберите хотя бы один ключ для шифрования или подписи.</string>
- <string name="specify_file_to_encrypt_to">Пожалуйста, выберите файл для шифрования.\nВНИМАНИЕ! Файл будет перезаписан если он уже существует.</string>
- <string name="specify_file_to_decrypt_to">Пожалуйста, выберите файл для расшифровки.\nВНИМАНИЕ! Файл будет перезаписан если он уже существует.</string>
- <string name="specify_file_to_export_to">Пожалуйста, выберите файл для экспорта.\nВНИМАНИЕ! Файл будет перезаписан если он уже существует.</string>
<string name="also_export_secret_keys">Экспортировать секретные ключи</string>
<string name="reinstall_openkeychain">Вы столкнулись с багом Андроид. Пожалуйста, переустановите OpenKeychain чтобы связать ваши контакты и ключи. </string>
<string name="key_exported">Успешный экспорт 1 ключа.</string>
@@ -723,16 +701,37 @@
<!--Consolidate-->
<string name="msg_con">Консолидация базы данных</string>
<string name="msg_con_error_bad_state">Консолидация началась но база не кэширована! Это программная ошибка, пожалуйста, сообщите об этом.</string>
+ <string name="msg_con_db_clear">Очистка базы данных</string>
<string name="msg_con_error_db">Ошибка открытия базы данных!</string>
+ <string name="msg_con_error_io_public">Ошибка записи публичных ключей в кэш!</string>
+ <string name="msg_con_error_io_secret">Ошибка записи приватных ключей в кэш!</string>
+ <string name="msg_con_error_public">Ошибка переимпортирования публичных ключей!</string>
+ <string name="msg_con_error_secret">Ошибка переимпортирования приватных ключей!</string>
<!--Edit Key (higher level than modify)-->
<string name="msg_ed_error_key_not_found">Ключ не найден!</string>
+ <string name="msg_ed_success">Операция с ключом успешна!</string>
<!--Promote key-->
+ <string name="msg_pr_error_already_secret">Этот ключ уже приватный!</string>
<string name="msg_pr_error_key_not_found">Ключ не найден!</string>
<!--Other messages used in OperationLogs-->
<string name="msg_ek_error_divert">Редактирование NFC ключей (еще) не поддерживается!</string>
<string name="msg_ek_error_not_found">Ключ не найден!</string>
<!--Messages for DecryptVerify operation-->
+ <string name="msg_dc_clear_decompress">Распаковка сжатых данных</string>
+ <string name="msg_dc_clear_meta_size_unknown">Неизвестный размер файла</string>
+ <string name="msg_dc_clear_signature_bad">Проверка подписи НЕ ПРОЙДЕНА!</string>
+ <string name="msg_dc_error_unsupported_hash_algo">Неподдерживаемый, и потенциально небезопасный алгоритм хэширования!</string>
+ <string name="msg_dc_clear_signature_check">Проверка подписи данных</string>
+ <string name="msg_dc_clear_signature_ok">Проверка подписи ПРОЙДЕНА</string>
+ <string name="msg_dc_clear_signature">Сохранение данных подписи</string>
+ <string name="msg_dc_error_bad_passphrase">Ошибка разблокирования ключа, неверная фраза-пароль!</string>
+ <string name="msg_dc_error_extract_key">Неизвестная ошибка разблокировения ключа!</string>
+ <string name="msg_dc_error_no_data">Зашифрованные данные не найдены!</string>
+ <string name="msg_dc_error_no_key">Зашифрованные данные с известным приватным ключом не найдены!</string>
+ <string name="msg_dc_ok">Расшифрование/проверка закончена</string>
+ <string name="msg_dc_pass_cached">Использование фразы-пароля из кэша</string>
<string name="msg_dc_unlocking">Разблокировка секретного ключа</string>
+ <string name="msg_dc_old_symmetric_encryption_algo">Был использован потенциально небезопасный алгоритм шифрования!</string>
<!--Messages for VerifySignedLiteralData operation-->
<string name="msg_vl_clear_signature_check">Проверка подписи данных</string>
<string name="msg_vl_ok">ОК</string>
@@ -758,16 +757,30 @@
<string name="msg_pse_error_nfc">Ошибка данных NFC!</string>
<string name="msg_pse_error_no_passphrase">Парольных фраз не найдено!</string>
<string name="msg_pse_error_pgp">Внутренняя ошибка OpenPGP!</string>
+ <string name="msg_crt_certifying">Генерация сертификатов</string>
+ <string name="msg_crt_error_master_not_found">Основной ключ не найден!</string>
+ <string name="msg_crt_error_nothing">Нет сертифицированных ключей!</string>
+ <string name="msg_crt_error_unlock">Ошибка разблокирования основного ключа!</string>
<string name="msg_crt_saving">Сохранение связки</string>
<string name="msg_crt_unlock">Разблокировка основного ключа</string>
<string name="msg_crt_warn_not_found">Ключ не найден!</string>
<string name="msg_crt_warn_cert_failed">Создание сертификата не удалось!</string>
+ <string name="msg_crt_warn_save_failed">Ошибка операции сохранения!</string>
<string name="msg_crt_upload_success">Ключ успешно загружен на сервер</string>
<string name="msg_import_fingerprint_ok">Проверка отпечатка успешна</string>
+ <string name="msg_import_error">Ошибка операции импорта!</string>
+ <string name="msg_import_error_io">Операция импорта прервана из-за ошибки ввода/вывода!</string>
+ <string name="msg_import_success">Операция импорта успешна!</string>
+ <string name="msg_export_all">Экспорт всех ключей</string>
+ <string name="msg_export_error_no_file">Не выбрано имя файла!</string>
<string name="msg_export_error_fopen">Ошибка открытия файла!</string>
+ <string name="msg_export_error_no_uri">Не выбран URL!</string>
+ <string name="msg_export_error_storage">Диск не готов для записи!</string>
<string name="msg_export_error_db">Ошибка базы данных!</string>
<string name="msg_export_error_io">Ошибка ввода/вывода!</string>
+ <string name="msg_export_success">Операция экспорта успешна</string>
<string name="msg_del_error_empty">Нет данных для удаления!</string>
+ <string name="msg_del_error_multi_secret">Секретные ключи можно удалять только по одному!</string>
<string name="msg_acc_saved">Аккаунт сохранен</string>
<plurals name="error_import_non_pgp_part">
<item quantity="one">часть загруженного файла содержит данные OpenPGP, но это не ключ</item>
@@ -775,12 +788,19 @@
<item quantity="other">части загруженного файла содержат данные OpenPGP, но это не ключ</item>
</plurals>
<!--Messages for Export Log operation-->
+ <string name="msg_export_log_error_fopen">Ошибка открытия файла</string>
+ <string name="msg_export_log_error_no_file">Не выбрано имя файла!</string>
+ <string name="msg_export_log_error_writing">Ошибка записи в файл!</string>
+ <string name="msg_export_log_success">Лог успешно экспортирован!</string>
<!--PassphraseCache-->
<string name="passp_cache_notif_keys">Кэшированные пароли:</string>
<string name="passp_cache_notif_clear">Очистить кэш</string>
<string name="passp_cache_notif_pwd">Пароль</string>
<!--First Time-->
<string name="first_time_text1">Верните вашу приватность с помощью OpenKeychain!</string>
+ <string name="first_time_create_key">Создать свой ключ</string>
+ <string name="first_time_import_key">Импорт ключа из файла</string>
+ <string name="first_time_yubikey">Использовать YubiKey NEO</string>
<string name="first_time_skip">Пропустить настройку</string>
<!--unsorted-->
<string name="section_certifier_id">Кем подписан</string>
@@ -792,6 +812,7 @@
<string name="label_cert_type">Тип</string>
<string name="error_key_not_found">Ключ не найден!</string>
<string name="error_key_processing">Ошибка обработки ключа!</string>
+ <string name="key_no_passphrase">Без фразы-пароля</string>
<string name="key_unavailable">недоступно</string>
<string name="title_view_cert">Просмотреть детали сертификации</string>
<string name="unknown_algorithm">неизв.</string>
diff --git a/OpenKeychain/src/main/res/values-sl/strings.xml b/OpenKeychain/src/main/res/values-sl/strings.xml
index 051f960ed..4fee0250d 100644
--- a/OpenKeychain/src/main/res/values-sl/strings.xml
+++ b/OpenKeychain/src/main/res/values-sl/strings.xml
@@ -4,24 +4,23 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">Izberi ključe</string>
- <string name="title_select_secret_key">Izberi zasebni ključ</string>
+ <string name="title_encrypt_text">Šifriraj</string>
+ <string name="title_encrypt_files">Šifriraj</string>
<string name="title_decrypt">Dešifriraj</string>
<string name="title_unlock">Odkleni ključ</string>
<string name="title_add_subkey">Dodaj podključ</string>
<string name="title_edit_key">Uredi ključ</string>
<string name="title_preferences">Nastavitve</string>
- <string name="title_cloud_search_preferences">Nastavitve iskanja v oblaku</string>
<string name="title_api_registered_apps">Aplikacije</string>
<string name="title_key_server_preference">Strežniki javnih ključev</string>
<string name="title_change_passphrase">Spremeni geslo</string>
<string name="title_share_fingerprint_with">Deli prstni odtis z...</string>
<string name="title_share_key">Deli ključ z...</string>
<string name="title_share_file">Deli datoteko z...</string>
+ <string name="title_share_message">Deli besedilo z...</string>
<string name="title_encrypt_to_file">Šifriraj v datoteko</string>
<string name="title_decrypt_to_file">Dešifriraj v datoteko</string>
<string name="title_import_keys">Uvozi ključe</string>
- <string name="title_add_keys">Dodaj ključe</string>
<string name="title_export_key">Izvozi kluč</string>
<string name="title_export_keys">Izvozi ključe</string>
<string name="title_key_not_found">Ključ ni bil najden</string>
@@ -30,32 +29,33 @@
<string name="title_key_details">Podrobnosti o ključu</string>
<string name="title_help">Pomoč</string>
<string name="title_log_display">Dnevnik</string>
- <string name="title_create_key">Ustvari kluč</string>
<string name="title_exchange_keys">Izmenjava ključev</string>
<string name="title_advanced_key_info">Napredne informacije o ključu</string>
- <string name="title_keys">Ključi</string>
+ <string name="title_delete_secret_key">Izbrišem VAŠ ključ \'%s\'?</string>
+ <string name="title_export_log">Izvozi sistemsko zabeležbo</string>
+ <string name="title_manage_my_keys">Upravljanje mojih ključev</string>
<!--section-->
<string name="section_user_ids">Identitete</string>
+ <string name="section_linked_system_contact">Povezan stik</string>
<string name="section_should_you_trust">Ali zaupate temu ključu?</string>
+ <string name="section_proof_details">Overba dokazila</string>
+ <string name="section_cloud_evidence">Dokazila iz oblaka</string>
<string name="section_keys">Podključi</string>
<string name="section_cloud_search">Iskanje v oblaku</string>
- <string name="section_general">Splošno</string>
- <string name="section_defaults">Privzeto</string>
- <string name="section_advanced">Napredno</string>
+ <string name="section_passphrase_cache">Hranjenje gesla v spominu</string>
<string name="section_certify">Potrdi</string>
<string name="section_actions">Ravnanja</string>
<string name="section_share_key">Ključ</string>
<string name="section_key_server">Strežnik</string>
<string name="section_fingerprint">Prstni odtis</string>
- <string name="section_decrypt_files">Datoteke</string>
- <string name="section_decrypt_text">Besedilo</string>
- <string name="section_certs">Certifikati</string>
<string name="section_encrypt">Šifriraj</string>
<string name="section_decrypt">Dešifriraj</string>
+ <string name="section_current_expiry">Trenuten datum poteka</string>
+ <string name="section_new_expiry">Nov datum poteka</string>
<!--button-->
<string name="btn_decrypt_verify_file">Dešifriraj, preveri in shrani</string>
- <string name="btn_encrypt_file">Šifriraj in shrani datoteko</string>
<string name="btn_encrypt_share_file">Šifriraj in deli datoteko</string>
+ <string name="btn_encrypt_save_file">Šifriraj in shrani datoteko</string>
<string name="btn_save">Shrani</string>
<string name="btn_do_not_save">Prekliči</string>
<string name="btn_delete">Izbriši</string>
@@ -64,26 +64,38 @@
<string name="btn_export_to_server">Naloži na strežnik</string>
<string name="btn_next">Naprej</string>
<string name="btn_back">Nazaj</string>
- <string name="btn_lookup_key">Išči ključ</string>
+ <string name="btn_no">Ne</string>
+ <string name="btn_match">Prstna odtisa se ujemata</string>
+ <string name="btn_share_encrypted_signed">Šifriraj in deli besedilo</string>
+ <string name="btn_copy_encrypted_signed">Šifriraj besedilo in kopiraj v odložišče</string>
<string name="btn_view_cert_key">Poglej ključ za overjanje</string>
<string name="btn_create_key">Ustvari ključ</string>
<string name="btn_add_files">Dodaj datoteko</string>
+ <string name="btn_add_share_decrypted_text">Deli dešifrirano besedilo</string>
+ <string name="btn_decrypt_clipboard">Dešifriraj besedilo iz odložišča</string>
+ <string name="btn_decrypt_and_verify">in preveri podpise</string>
<string name="btn_decrypt_files">Dešifriraj datoteke</string>
+ <string name="btn_encrypt_files">Šifriraj datoteke</string>
+ <string name="btn_encrypt_text">Šifriraj besedilo</string>
+ <string name="btn_add_email">Dodaj elektronske naslove</string>
<!--menu-->
<string name="menu_preferences">Nastavitve</string>
<string name="menu_help">Pomoč</string>
<string name="menu_export_key">Izvozi v datoteko</string>
<string name="menu_delete_key">Izbriši ključ</string>
- <string name="menu_import_existing_key">Uvozi iz datoteke</string>
+ <string name="menu_manage_keys">Upravljanje mojih ključev</string>
<string name="menu_search">Išči</string>
+ <string name="menu_nfc_preferences">Nastavitve NFC</string>
<string name="menu_beam_preferences">Nastavitve Beam</string>
- <string name="menu_key_edit_cancel">Prekliči</string>
<string name="menu_encrypt_to">Šifriraj v...</string>
<string name="menu_select_all">Izberi vse</string>
- <string name="menu_add_keys">Dodaj ključe</string>
<string name="menu_export_all_keys">Izvozi vse ključe</string>
+ <string name="menu_update_all_keys">Posodobi vse ključe</string>
<string name="menu_advanced">Prikaži dodatne informacije</string>
+ <string name="menu_certify_fingerprint">Potrdi s primerjavo prstnih odtisov</string>
+ <string name="menu_export_log">Izvozi sistemsko zabeležbo</string>
<!--label-->
+ <string name="label_message">Besedilo</string>
<string name="label_file">Datoteka</string>
<string name="label_files">Datoteke</string>
<string name="label_file_colon">Datoteka:</string>
@@ -91,17 +103,25 @@
<string name="label_passphrase">Geslo</string>
<string name="label_unlock">Odklepanje...</string>
<string name="label_passphrase_again">Ponovi geslo</string>
+ <string name="label_show_passphrase">Prikaži geslo</string>
<string name="label_algorithm">Algoritem</string>
<string name="label_ascii_armor">ASCII oklep datotek</string>
<string name="label_file_ascii_armor">Omogoči ASCII ovoj</string>
<string name="label_write_version_header">Daj drugim vedeti, da uporabljate OpenKeychain</string>
<string name="label_write_version_header_summary">Zapiše \'OpenKeychain v2.7\' v OpenPGP podpis, šifrirano besedilo in izvožene ključe</string>
+ <string name="label_use_default_yubikey_pin">Uporabi privzeto YubiKey PIN kodo</string>
+ <string name="label_use_num_keypad_for_yubikey_pin">Uporabi numerično tipkovnico za YubiKey PIN kodo</string>
+ <string name="label_label_use_default_yubikey_pin_summary">Uporablja privzeto PIN kodo (123456) za dostop do ključev YubiKey preko NFC</string>
<string name="label_asymmetric_from">Podpisal:</string>
<string name="label_to">Šifriraj za:</string>
+ <string name="label_delete_after_encryption">Po dešifriranju izbriši datoteke</string>
<string name="label_delete_after_decryption">Izbriši po dešifriranju</string>
<string name="label_encryption_algorithm">Šifrirni algoritem</string>
<string name="label_hash_algorithm">Zgostitveni algoritem</string>
<string name="label_symmetric">Šifriranje z geslom</string>
+ <string name="label_passphrase_cache_ttl">Čas pomnjenja</string>
+ <string name="label_passphrase_cache_subs">Pomni gesla glede na podključ</string>
+ <string name="label_message_compression">Kompresija besedila</string>
<string name="label_file_compression">Stiskanje datotek</string>
<string name="label_keyservers">Strežniki</string>
<string name="label_key_id">ID ključa</string>
@@ -114,8 +134,18 @@
<string name="label_name">Ime</string>
<string name="label_comment">Komentar</string>
<string name="label_email">E-pošta</string>
+ <string name="label_send_key">Sinhroniziraj z oblakom</string>
<string name="label_fingerprint">Prstni odtis</string>
<string name="expiry_date_dialog_title">Določi datum poteka veljavnosti</string>
+ <string name="label_first_keyserver_is_used">(Prednost ima prvi strežnik na seznamu)</string>
+ <string name="label_preferred">prednostni</string>
+ <string name="label_enable_compression">Omogoči kompresijo</string>
+ <string name="label_encrypt_filenames">Šifriraj imena datotek</string>
+ <string name="label_hidden_recipients">Skrij prejemnike</string>
+ <string name="pref_keyserver">Preišči strežnik s ključi</string>
+ <string name="pref_keyserver_summary">Preišči strežnik HKP</string>
+ <string name="pref_keybase">Preišči strežnik Keybase.io</string>
+ <string name="pref_keybase_summary">Preišči seznam Keybase.io</string>
<string name="user_id_no_name">&lt;brez imena&gt;</string>
<string name="none">&lt;nič&gt;</string>
<plurals name="n_keys">
@@ -165,28 +195,49 @@
<string name="passphrase_must_not_be_empty">Vnesite geslo.</string>
<string name="passphrase_for_symmetric_encryption">Simetrično šifriranje.</string>
<string name="passphrase_for">Vnesite geslo za \'%s\'</string>
+ <string name="pin_for">Vnesite PIN kodo za \'%s\'</string>
+ <string name="yubikey_pin_for">Vnesite PIN kodo za dostop YubiKey za \'%s\'</string>
+ <string name="nfc_text">Prislonite YubiKey k hrbtišču mobilne naprave.</string>
+ <string name="file_delete_confirmation_title">Izbrišem izvirne datoteke?</string>
+ <string name="file_delete_confirmation">Izbrisane bodo naslednje datoteke:%s</string>
+ <string name="file_delete_successful">Izbrisanih je bilo %1$d od %2$d datotek.%3$s</string>
<string name="no_file_selected">Najprej izberite datoteko.</string>
<string name="encrypt_sign_successful">Uspešno podpisano in/ali šifrirano.</string>
<string name="encrypt_sign_clipboard_successful">Uspešno podpisano in/ali šifrirano ter poslano v odložišče.</string>
<string name="select_encryption_key">Izberite vsaj en šifrirni ključ.</string>
<string name="select_encryption_or_signature_key">Vnesite vsaj en šifrirni ključ ali ključ za podpisovanje.</string>
<string name="specify_file_to_encrypt_to">Določite datoteko, v katero želite šifrirati vsebino.\nPOZOR: če datoteka že obstaja, bo prepisana.</string>
+ <string name="specify_file_to_decrypt_to">Določite datoteko, v katero želite dešifrirati vsebino.\nPOZOR: če datoteka že obstaja, bo prepisana.</string>
<string name="specify_file_to_export_to">Določite datoteko, v katero želite izvoziti vsebino.\nPOZOR: če datoteka že obstaja, bo prepisana.</string>
+ <string name="key_deletion_confirmation_multi">Ali zares želite izbrisati vse izbrane ključe?</string>
+ <string name="secret_key_deletion_confirmation">Po izbrisu ne bo več mogoče prebirati sporočil šifriranih s tem ključem! Izgubljene bodo tudi vse z njim narejene potrditve.</string>
+ <string name="public_key_deletetion_confirmation">Izbrišem ključ \'%s\'?</string>
<string name="also_export_secret_keys">Izvozi tudi zasebne ključe</string>
+ <string name="reinstall_openkeychain">Naleteli ste na poznanega \'hrošča\' v sistemu Android. Za povezavo vaših stikov s ključi ponovno naložite aplikacijo OpenKeycahain.</string>
<string name="key_exported">Uspešno izvožen 1 ključ.</string>
<string name="keys_exported">Uspešno izvoženih ključev: %d</string>
<string name="no_keys_exported">Noben ključ ni bil izvožen.</string>
<string name="key_creation_el_gamal_info">Pozor: ELGamal podpirajo samo podključi.</string>
<string name="key_not_found">Ne najdem ključa %08X.</string>
+ <string name="specify_file_to_export_log_to">Določite datoteko, v katero želite izvoziti vsebino.\nPOZOR: če datoteka že obstaja, bo prepisana.</string>
+ <plurals name="bad_keys_encountered">
+ <item quantity="one">Neupoštevan %d slab zasebni ključ. Morda je bil izvožen na način\n --export-secret-subkeys\nPoskrbite, da bo izvožen z\n --export-secret-keys</item>
+ <item quantity="two">Neupoštevana %d slaba zasebna ključa. Morda sta bila izvožena na način\n --export-secret-subkeys\nPoskrbite, da bosta izvožena z\n --export-secret-keys</item>
+ <item quantity="few">Neupoštevani %d slabi zasebni ključi. Morda so bili izvoženi na način\n --export-secret-subkeys\nPoskrbite, da bodo izvoženi z\n --export-secret-keys</item>
+ <item quantity="other">Neupoštevanih %d slabih zasebnih ključev. Morda so bili izvoženi na način\n --export-secret-subkeys\nPoskrbite, da bodo izvoženi z\n --export-secret-keys</item>
+ </plurals>
<string name="list_empty">Lista je prazna!</string>
<string name="nfc_successful">Ključ uspešno poslan preko NFC Beam!</string>
<string name="key_copied_to_clipboard">Ključ je bil prekopiran v odložišče!</string>
<string name="fingerprint_copied_to_clipboard">Prstni odtis je bil prekopiran v odložišče!</string>
+ <string name="select_key_to_certify">Izberite ključ, ki ga boste uporabljali za potrjevanje!</string>
<string name="key_too_big_for_sharing">Ključ je prevelik za delitev na ta način!</string>
<string name="text_copied_to_clipboard">Besedilo je bilo prekopirano v odložišče!</string>
<!--errors
no punctuation, all lowercase,
they will be put after "error_message", e.g. "Error: file not found"-->
+ <string name="error_file_delete_failed">niso bili izbisani. Izbrišite jih ročno!</string>
+ <string name="error_file_added_already">%s je bil že dodan.</string>
<string name="error_file_not_found">ne najdem datoteke</string>
<string name="error_no_secret_key_found">ne najdem ustreznega zasebnega ključa</string>
<string name="error_external_storage_not_ready">zunanja shramba ni na voljo</string>
@@ -196,12 +247,16 @@
<string name="error_key_needs_a_user_id">potrebujete vsaj eno identiteto</string>
<string name="error_no_signature_passphrase">dano ni bilo nobeno geslo</string>
<string name="error_no_signature_key">dan ni bil noben podpisni ključ</string>
+ <string name="error_invalid_data">Ne najdem nobene vsebine šifrirane ali podpisane z OpenPGP!</string>
<string name="error_integrity_check_failed">Preverba neokrnjenosti ni bila uspešna! Podatki so bili spremenjeni!</string>
<string name="error_wrong_passphrase">napačno geslo</string>
<string name="error_could_not_extract_private_key">ne morem izvleči zasebnega ključa</string>
<!--errors without preceeding Error:-->
<string name="error_jelly_bean_needed">Za uporabo storitve NFC Beam potrebujete najmanj Android 4.1!</string>
+ <string name="error_nfc_needed">Vključen mora biti NFC!</string>
+ <string name="error_beam_needed">Vključen mora biti Beam!</string>
<string name="error_nothing_import">Najden ni bil noben ključ!</string>
+ <string name="error_contacts_key_id_missing">Pridobivanje ID-jev ključev iz vaših stikov ni bilo uspešno!</string>
<string name="error_generic_report_bug">Pripetila se je splošna napaka, prosimo ustvarite poročilo o \'hrošču\'.</string>
<!--results shown after decryption/verification-->
<string name="decrypt_result_no_signature">Ni podpisano</string>
@@ -215,6 +270,8 @@
<string name="decrypt_result_not_encrypted">Nešifrirano</string>
<string name="decrypt_result_action_show">Prikaži</string>
<string name="decrypt_result_action_Lookup">Poišči</string>
+ <string name="decrypt_invalid_text">Nekaj ni v redu: ali je neveljaven podpis ali pa je ključ potekel oz. bil preklican. Zato se ne da reči, kdo je v resnici napisal besedilo. Naj ga vseeno prikažem?</string>
+ <string name="decrypt_invalid_button">Seznanjen sem s tveganji, prikaži!</string>
<!--Add keys-->
<string name="add_keys_my_key">Moj ključ:</string>
<!--progress dialogs, usually ending in '…'-->
@@ -223,6 +280,7 @@
<string name="progress_cancelling">preklic...</string>
<string name="progress_saving">shranjujem...</string>
<string name="progress_importing">uvažam...</string>
+ <string name="progress_updating">Posodabljam ključe...</string>
<string name="progress_exporting">izvažam...</string>
<string name="progress_uploading">pošiljanje...</string>
<string name="progress_building_key">ustvarjam ključ...</string>
@@ -232,9 +290,15 @@
<string name="progress_generating_elgamal">ustvarjanje novega ElGamal ključa...</string>
<string name="progress_generating_ecdsa">ustvarjanje novega ECDSA ključa...</string>
<string name="progress_generating_ecdh">ustvarjanje novega ECDH ključa...</string>
- <string name="progress_modify_primaryuid">menjavam glavno identiteto uporabnika...</string>
+ <string name="progress_modify">spreminjam zbirko ključev...</string>
+ <string name="progress_modify_unlock">odklepam zbirko ključev...</string>
+ <string name="progress_modify_adduid">dodajam ID-je uporabnikov...</string>
+ <string name="progress_modify_adduat">dodajam lastnosti uporabnikov...</string>
+ <string name="progress_modify_revokeuid">razveljavljam ID-je uporabnikov...</string>
+ <string name="progress_modify_primaryuid">menjavam glavni ID...</string>
<string name="progress_modify_subkeychange">spreminjanje podključev...</string>
<string name="progress_modify_subkeyrevoke">preklicevanje podključev...</string>
+ <string name="progress_modify_subkeystrip">razstavljam podključe...</string>
<string name="progress_modify_subkeyadd">dodajanje podključev...</string>
<string name="progress_modify_passphrase">menjava gesla...</string>
<plurals name="progress_exporting_key">
@@ -260,7 +324,10 @@
<string name="progress_verifying_integrity">preverjam neokrnjenost...</string>
<string name="progress_deleting_securely">varno brišem \'%s\'…</string>
<string name="progress_deleting">brisanje ključev...</string>
+ <string name="progress_con_saving">združevanje: spravljanje v spomin...</string>
+ <string name="progress_con_reimport">združevanje: ponoven uvoz...</string>
<!--action strings-->
+ <string name="hint_cloud_search_hint">Iskanje po Imenu, E-pošti...</string>
<!--key bit length selections-->
<string name="key_size_512">512</string>
<string name="key_size_768">768</string>
@@ -288,6 +355,7 @@
<!--Help-->
<string name="help_tab_start">Start</string>
<string name="help_tab_faq">Pogosta vprašanja</string>
+ <string name="help_tab_wot">Potrjevanje ključev</string>
<string name="help_tab_nfc_beam">NFC Beam</string>
<string name="help_tab_changelog">Dnevnik sprememb</string>
<string name="help_tab_about">O aplikaciji</string>
@@ -296,15 +364,101 @@
<string name="import_tab_keyserver">Strežnik</string>
<string name="import_tab_cloud">Iskanje v oblaku</string>
<string name="import_tab_direct">Datoteka/odložišče</string>
+ <string name="import_tab_qr_code">Koda QR/NFC</string>
<string name="import_import">Uvozi izbrane ključe</string>
<string name="import_qr_code_wrong">Koda QR je deformirana! Poskusite znova!</string>
<string name="import_qr_code_too_short_fingerprint">Prstni odtis je prekratek (&lt; 16 znakov)</string>
+ <string name="import_qr_code_button">Skeniraj kodo QR</string>
+ <string name="import_qr_code_text">Zajamite kodo QR s kamero!</string>
<!--Generic result toast-->
+ <string name="view_log">Podrobnosti</string>
+ <string name="with_warnings">, z opozorili</string>
+ <string name="with_cancelled">, do preklica</string>
<!--Import result toast-->
+ <plurals name="import_keys_added_and_updated_1">
+ <item quantity="one">Uspešno uvožen ključ</item>
+ <item quantity="two">Uspešno uvožena %1$d ključa</item>
+ <item quantity="few">Uspešno uvoženi %1$d ključi</item>
+ <item quantity="other">Uspešno uvoženih %1$d ključev</item>
+ </plurals>
+ <plurals name="import_keys_added_and_updated_2">
+ <item quantity="one">in posodobljen ključ%2$s.</item>
+ <item quantity="two">in posodobljena %1$d ključa%2$s.</item>
+ <item quantity="few">in posodobljeni %1$d ključi%2$s.</item>
+ <item quantity="other">in posodobljenih %1$d ključev%2$s.</item>
+ </plurals>
+ <plurals name="import_keys_added">
+ <item quantity="one">Uspešno uvožen ključ%2$s.</item>
+ <item quantity="two">Uspešno uvožena %1$d ključa%2$s.</item>
+ <item quantity="few">Uspešno uvoženi %1$d ključi%2$s.</item>
+ <item quantity="other">Uspešno uvoženih %1$d ključev%2$s.</item>
+ </plurals>
+ <plurals name="import_keys_updated">
+ <item quantity="one">Uspešno posodobljen ključ%2$s.</item>
+ <item quantity="two">Uspešno posodobljena %1$d ključa%2$s.</item>
+ <item quantity="few">Uspešno posodobljeni %1$d ključi%2$s.</item>
+ <item quantity="other">Uspešno posodobljenih %1$d ključev%2$s.</item>
+ </plurals>
+ <plurals name="import_keys_with_errors">
+ <item quantity="one">Neuspešen uvoz enega ključa!</item>
+ <item quantity="two">Neuspešen uvoz %d ključev!</item>
+ <item quantity="few">Neuspešen uvoz %d ključev!</item>
+ <item quantity="other">Neuspešen uvoz %d ključev!</item>
+ </plurals>
+ <plurals name="import_error">
+ <item quantity="one">Uvoz neuspešen!</item>
+ <item quantity="two">Uvoz %d ključev neuspešen!!</item>
+ <item quantity="few">Uvoz %d ključev neuspešen!!</item>
+ <item quantity="other">Uvoz %d ključev neuspešen!!</item>
+ </plurals>
<string name="import_error_nothing">Nič za uvoziti.</string>
<string name="import_error_nothing_cancelled">Uvoz preklican.</string>
<!--Delete result toast-->
+ <plurals name="delete_ok_but_fail_1">
+ <item quantity="one">Uspešno izbrisan en ključ</item>
+ <item quantity="two">Uspešno izbrisana %1$d ključa</item>
+ <item quantity="few">Uspešno izbrisani %1$d ključi</item>
+ <item quantity="other">Uspešno izbrisanih %1$d ključev</item>
+ </plurals>
+ <plurals name="delete_ok_but_fail_2">
+ <item quantity="one">, en ključ%2$s ni bil izbrisan.</item>
+ <item quantity="two">, %1$d ključa%2$s nista bila izbrisana.</item>
+ <item quantity="few">, %1$d ključi%2$s niso bili izbrisani.</item>
+ <item quantity="other">, %1$d ključev%2$s ni bilo izbrisanih.</item>
+ </plurals>
+ <plurals name="delete_ok">
+ <item quantity="one">Uspešno izbrisanih ključ%2$s.</item>
+ <item quantity="two">Uspešno izbrisana %1$d ključa%2$s.</item>
+ <item quantity="few">Uspešno izbrisani %1$d ključi%2$s.</item>
+ <item quantity="other">Uspešno izbrisanih %1$d ključev%2$s.</item>
+ </plurals>
+ <plurals name="delete_fail">
+ <item quantity="one">Napaka pri brisanju enega ključa%2$s.</item>
+ <item quantity="two">Napaka pri brisanju %1$d ključev.</item>
+ <item quantity="few">Napaka pri brisanju %1$d ključev.</item>
+ <item quantity="other">Napaka pri brisanju %1$d ključev.</item>
+ </plurals>
+ <string name="delete_nothing">Ničesar ni za izbrisati.</string>
+ <string name="delete_cancelled">Operacija brisanja prekinjena.</string>
<!--Certify result toast-->
+ <plurals name="certify_keys_ok">
+ <item quantity="one">Uspešno potrjen ključ%2$s.</item>
+ <item quantity="two">Uspešno potrjena %1$d ključa%2$s.</item>
+ <item quantity="few">Uspešno potrjeni %1$d ključi%2$s.</item>
+ <item quantity="other">Uspešno potrjenih %1$d ključev%2$s.</item>
+ </plurals>
+ <plurals name="certify_keys_with_errors">
+ <item quantity="one">Ključ ni bil potrjen!</item>
+ <item quantity="two">%d ključa nista bila potrjena!</item>
+ <item quantity="few">%d ključi niso bili potrjeni!</item>
+ <item quantity="other">%d ključev ni bilo potrjenih!</item>
+ </plurals>
+ <plurals name="certify_error">
+ <item quantity="one">Potrditev neuspešna!</item>
+ <item quantity="two">Potrditev %d ključev neuspešna!</item>
+ <item quantity="few">Potrditev %d ključev neuspešna!</item>
+ <item quantity="other">Potrditev %d ključev neuspešna!</item>
+ </plurals>
<!--Intent labels-->
<string name="intent_decrypt_file">Dešifriraj datoteko z OpenKeychain</string>
<string name="intent_import_key">Uvozi ključ z OpenKeychain</string>
@@ -317,21 +471,33 @@
<string name="api_settings_hide_advanced">Skrij napredne nastavitve</string>
<string name="api_settings_no_key">Izbran ni bil noben ključ</string>
<string name="api_settings_select_key">Izberite ključ</string>
+ <string name="api_settings_create_key">Ustvari nov ključ</string>
<string name="api_settings_save">Shrani</string>
+ <string name="api_settings_save_msg">Račun je bil shranjen</string>
<string name="api_settings_cancel">Prekliči</string>
<string name="api_settings_revoke">Prekliči dostop</string>
<string name="api_settings_start">Zaženi aplikacijo</string>
<string name="api_settings_delete_account">Izbriši račun</string>
<string name="api_settings_package_name">Ime paketa</string>
<string name="api_settings_package_signature">SHA-256 podpisa paketa</string>
+ <string name="api_settings_accounts">Računi (opuščen API)</string>
+ <string name="api_settings_advanced">Dodatne informacije</string>
+ <string name="api_settings_allowed_keys">Dovoljeni ključi</string>
<string name="api_settings_settings">Nastavitve</string>
+ <string name="api_settings_key">Ključ računa:</string>
<string name="api_settings_accounts_empty">S to aplikacijo ni povezan noben račun</string>
+ <string name="api_create_account_text">Za ta račun ni nastavljen noben ključ. Izberite enega izmed svojih obstoječih ključev, oziroma ustvarite novega.\nAplikacije lahko dešifrirajo/podpisujejo le s tu izbranimi ključi!</string>
+ <string name="api_update_account_text">Ključ nastavljen za ta račun je bil izbrisan. Prosimo izberite drugega.\nAplikacije lahko dešifrirajo/podpisujejo le s tu izbranimi ključi!</string>
+ <string name="api_register_text">Prikazane aplikacije želijo šifrirati/dešifrirati sporočila ter jih podpisovati v vašem imenu.\nDovolim dostop?\n\nPOZOR: Če ne veste zakaj se je pojavilo to obvestilo, ne dovolite dostopa! Dostop lahko prekličete tudi kasneje, v oknu \'Aplikacije\'.</string>
<string name="api_register_allow">Dovoli dostop</string>
<string name="api_register_disallow">Zavrni dostop</string>
<string name="api_register_error_select_key">Izberite ključ!</string>
+ <string name="api_select_pub_keys_missing_text">Za te identitete ni bil najden noben ključ:</string>
+ <string name="api_select_pub_keys_dublicates_text">Za te identitete obstaja več ključev:</string>
<string name="api_select_pub_keys_text">Preverite seznam prejemnikov!</string>
<string name="api_select_pub_keys_text_no_user_ids">Prosim, izberite prejemnike!</string>
<string name="api_error_wrong_signature">Preverjanje podpisa ni uspelo! Ste namestili to aplikacijo iz drugega vira? Če ste prepričani, da to ni napad, prekličite registracijo te aplikacije v OpenKeychain in jo izvedite znova.</string>
+ <string name="api_select_sign_key_text">Prosimo izberite enega od svojih obstoječih ključev, oziroma ustvarite novega.</string>
<!--Share-->
<string name="share_qr_code_dialog_title">Deli s kodo QR</string>
<string name="share_nfc_dialog">Deli preko NFC</string>
@@ -342,10 +508,14 @@
<item quantity="few">Izbrani %d ključi.</item>
<item quantity="other">Izbranih %d ključev.</item>
</plurals>
+ <string name="key_list_empty_text1">Najden ni bil noben ključ!</string>
+ <string name="key_list_filter_show_all">Prikaži vse ključe</string>
+ <string name="key_list_filter_show_certified">Prikaži samo overjene ključe</string>
<!--Key view-->
<string name="key_view_action_edit">Uredi ključ</string>
<string name="key_view_action_encrypt">Šifriraj besedilo</string>
<string name="key_view_action_encrypt_files">datoteke</string>
+ <string name="key_view_action_certify">Potrdi ključ</string>
<string name="key_view_action_update">Posodobi s strežnika</string>
<string name="key_view_action_share_with">Deli z...</string>
<string name="key_view_action_share_nfc">Deli preko NFC</string>
@@ -353,27 +523,102 @@
<string name="key_view_tab_main">Glavne informacije</string>
<string name="key_view_tab_share">Deli</string>
<string name="key_view_tab_keys">Podključi</string>
- <string name="key_view_tab_certs">Certifikati</string>
+ <string name="key_view_tab_certs">Potrdila</string>
+ <string name="key_view_tab_keybase">Keybase.io</string>
<string name="user_id_info_revoked_title">Preklican</string>
<string name="user_id_info_revoked_text">Lastnik ključa je preklical to identiteto. Ta ni več veljavna.</string>
+ <string name="user_id_info_certified_title">Overjeno</string>
+ <string name="user_id_info_certified_text">Ta identiteta je bila overjena z vaše strani.</string>
+ <string name="user_id_info_uncertified_title">Neoverjeno</string>
+ <string name="user_id_info_uncertified_text">Ta identiteta še ni bila overjena, zato ni mogoče vedeti, če ustreza osebi za katero se predstavlja.</string>
<string name="user_id_info_invalid_title">Neveljaven</string>
+ <string name="user_id_info_invalid_text">Nekaj je narobe s to identiteto!</string>
<!--Key trust-->
+ <string name="key_trust_already_verified">Ta ključ ste že potrdili!</string>
+ <string name="key_trust_it_is_yours">To je en izmed vaših ključev!</string>
+ <string name="key_trust_maybe">Ta ključ ni niti preklican, niti potečen.\nNiste ga potrdili, a mogoče mu zaupate.</string>
+ <string name="key_trust_revoked">Ta ključ je bil preklican s strani lastnika, zato mu ne gre zaupati.</string>
+ <string name="key_trust_expired">Ta ključ je potekel, zato mu ne gre zaupati.</string>
+ <string name="key_trust_old_keys">Uporaba tega ključa za dešifriranje starejših sporočil iz časa, ko ključ še ni potekel, oz. bil preklican, ni kritična.</string>
+ <string name="key_trust_no_cloud_evidence">Ni podatkov z oblaka o pristnosti tega ključa.</string>
+ <string name="key_trust_start_cloud_search">Začni iskanje</string>
+ <string name="key_trust_results_prefix">Keybase.io ponuja \"dokazilo\", da je lastnik tega kluča:</string>
+ <string name="key_trust_header_text">Pozor: Dokazila Keybase.io v aplikaciji OpenKeychain so eksperimantalne narave. Za večjo zanesljivost priporočamo, da dodatno skenirate kode QR ali izmenjate ključe preko NFC.</string>
<!--keybase proof stuff-->
+ <string name="keybase_narrative_twitter">Objavlja na Twitterju kot</string>
+ <string name="keybase_narrative_github">Prisoten na GitHub-u kot</string>
+ <string name="keybase_narrative_dns">Upravlja domeno(e)</string>
+ <string name="keybase_narrative_web_site">Objavlja na spletni strani(eh)</string>
+ <string name="keybase_narrative_reddit">Objavlja na Reddit-u kot</string>
+ <string name="keybase_narrative_coinbase">Prisoten na Coinbase-u kot</string>
+ <string name="keybase_narrative_hackernews">Objavlja na Hacker News kot</string>
+ <string name="keybase_narrative_unknown">Neznano dokazilo</string>
+ <string name="keybase_proof_failure">Dokazila se žal ne da preveriti.</string>
+ <string name="keybase_unknown_proof_failure">Neznan problem pri pregledovalniku dokazil</string>
+ <string name="keybase_problem_fetching_evidence">Problem z dokazilom</string>
+ <string name="keybase_key_mismatch">Prstni odtis ključa ne ustreza tistemu v dokazilu</string>
+ <string name="keybase_message_payload_mismatch">Dešifrirano dokazilo ne ustreza pričakovani vrednosti</string>
+ <string name="keybase_message_fetching_data">Pridobivam dokazilo</string>
+ <string name="keybase_proof_succeeded">To dokazilo je bilo overjeno!</string>
+ <string name="keybase_a_post">Objava</string>
+ <string name="keybase_fetched_from">pridobljeno od</string>
+ <string name="keybase_for_the_domain">za domeno</string>
+ <string name="keybase_contained_signature">vsebuje sporočilo, ki ga je lahko ustvaril samo lastnik tega ključa.</string>
+ <string name="keybase_twitter_proof">Čivk</string>
+ <string name="keybase_web_site_proof">Datoteka z besedilom</string>
+ <string name="keybase_github_proof">Gist</string>
+ <string name="keybase_reddit_proof">Datoteka JSON</string>
+ <string name="keybase_verify">Overi</string>
<!--Edit key-->
<string name="edit_key_action_change_passphrase">Zamenjaj geslo</string>
<string name="edit_key_action_add_identity">Dodaj identiteto</string>
<string name="edit_key_action_add_subkey">Dodaj podključ</string>
<string name="edit_key_edit_user_id_title">Izberite dejanje!</string>
+ <string-array name="edit_key_edit_user_id">
+ <item>Zamenjaj za primarno identiteto</item>
+ <item>Prekliči identitetoy</item>
+ </string-array>
<string-array name="edit_key_edit_user_id_revert_revocation">
<item>Revert revocation</item>
</string-array>
+ <string name="edit_key_edit_user_id_revoked">Identiteta je bila preklicana. Ta poteza ne more biti razveljavljena.</string>
<string name="edit_key_edit_subkey_title">Izberite dejanje!</string>
+ <string-array name="edit_key_edit_subkey">
+ <item>Spremeni datum poteka</item>
+ <item>Prekliči podključ</item>
+ <item>Razstavi podključ</item>
+ </string-array>
+ <string name="edit_key_new_subkey">nov podključ</string>
+ <string name="edit_key_select_flag">Izberite vsaj eno oznako!</string>
+ <string name="edit_key_error_add_identity">Dodajte vsaj eno identiteto!</string>
+ <string name="edit_key_error_add_subkey">Dodajte vsaj en podključ!</string>
<!--Create key-->
+ <string name="create_key_upload">Sinhroniziraj z oblakom</string>
<string name="create_key_empty">To polje je obvezno</string>
<string name="create_key_passphrases_not_equal">Gesli se ne ujemata</string>
+ <string name="create_key_final_text">Vnesli ste identiteto:</string>
+ <string name="create_key_final_robot_text">Ustvarjanje ključa zna potrajati. Privoščite si kavo...</string>
+ <string name="create_key_rsa">(3 podključi, RSA, 4096 bit)</string>
+ <string name="create_key_custom">(konfiguracija po meri)</string>
+ <string name="create_key_name_text">Izberite ime povezano s tem ključem. Lahko je polno ime, npr. \'Marjan Novak\', ali nadimek, npr. \'Mare\'.</string>
+ <string name="create_key_email_text">Vnesite svoj glavni e-poštni naslov za varno komunikacijo.</string>
+ <string name="create_key_passphrase_text">Izberite močno geslo. To bo varovalo vaš ključ v primeru odtujitve naprave.</string>
+ <string name="create_key_hint_full_name">Polno ime ali nadimek</string>
+ <string name="create_key_edit">Spremeni konfiguracijo ključa.</string>
+ <string name="create_key_add_email">Dodaj naslov e-pošte</string>
+ <string name="create_key_add_email_text">Dodatni e-poštni naslovi so prav tako povezani s tem ključem in so na voljo za varno komunikacijo.</string>
+ <string name="create_key_email_already_exists_text">E-poštni naslov je že bil dodan</string>
<!--View key-->
+ <string name="view_key_revoked">Ključ je preklican: ne smete ga več uporabljati!</string>
+ <string name="view_key_expired">Ključ je potekel: stvaritelj mora podaljšati njegovo veljavo!</string>
+ <string name="view_key_expired_secret">Ključ je potekel: njegovo veljavnost lahko podaljšate, če ga popravite!</string>
+ <string name="view_key_my_key">Moj ključ</string>
+ <string name="view_key_verified">Potrjen ključ</string>
+ <string name="view_key_unverified">Ključ ni potrjen: za potrditev skenirajte kodo QR!</string>
+ <string name="view_key_fragment_no_system_contact">&lt;brez&gt;</string>
<!--Navigation Drawer-->
<string name="nav_keys">Ključi</string>
+ <string name="nav_encrypt_decrypt">Šifriraj/Dešifriraj</string>
<string name="nav_apps">Aplikacije</string>
<string name="drawer_open">Odprite navigacijski poteznik</string>
<string name="drawer_close">Zaprite navigacijski poteznik</string>
@@ -391,6 +636,7 @@
<string name="cert_verify_error">napaka!</string>
<string name="cert_verify_unavailable">ključ ni na voljo</string>
<!--LogType log messages. Errors should have _ERROR_ in their name and end with a !-->
+ <string name="msg_internal_error">Interna napaka!</string>
<string name="msg_cancelled">Dejanje preklicano.</string>
<!--Import Public log entries-->
<string name="msg_ip_apply_batch">Uveljavljam serijsko dodajanje.</string>
@@ -398,35 +644,208 @@
<string name="msg_ip_delete_old_fail">Noben star ključ ni bil izbrisan (ustvarim novega?)</string>
<string name="msg_ip_delete_old_ok">Star ključ je bil izbrisan iz baze</string>
<string name="msg_ip_encode_fail">Operacija ni uspela zaradi napake</string>
+ <string name="msg_ip_error_io_exc">Postopek ni uspel zaradi napake i/o</string>
+ <string name="msg_ip_error_op_exc">Postopek ni uspel zaradi napake v bazi podatkov</string>
+ <string name="msg_ip_error_remote_ex">Postopek ni uspel zaradi interne napake</string>
<string name="msg_ip">Uvažam javno zbirko ključev %s</string>
<string name="msg_ip_insert_keyring">Šifriram podatke zbirke klučev</string>
+ <string name="msg_ip_insert_keys">Razčlenjujem ključe</string>
<string name="msg_ip_prepare">Pripravljam </string>
<string name="msg_ip_master">Obdelujem glavni ključ %s</string>
+ <string name="msg_ip_master_expired">Zbirka ključev je potekla %s</string>
+ <string name="msg_ip_master_expires">Zbirka ključev poteče %s</string>
+ <string name="msg_ip_master_flags_unspecified">Glavne oznake: nedoločeno (najverjetneje vse)</string>
+ <string name="msg_ip_master_flags_cesa">Glavne oznake: potrdi, šifriraj, podpiši, overi</string>
+ <string name="msg_ip_master_flags_cesx">Glavne oznake: potrdi. šifriraj, podpiši</string>
+ <string name="msg_ip_master_flags_cexa">Glavne oznake: potrdi, šifriraj, overi</string>
+ <string name="msg_ip_master_flags_cexx">Glavne oznake: potrdi, šifriraj</string>
+ <string name="msg_ip_master_flags_cxsa">Glavne oznake: potrdi, podpiši, overi</string>
+ <string name="msg_ip_master_flags_cxsx">Glavne oznake: potrdi, podpiši</string>
+ <string name="msg_ip_master_flags_cxxa">Glavne oznake: potrdi, overi</string>
+ <string name="msg_ip_master_flags_cxxx">Glavne oznake: potrdi</string>
+ <string name="msg_ip_master_flags_xesa">Glavne oznake: šifriraj, podpiši, overi</string>
+ <string name="msg_ip_master_flags_xesx">Glavne oznake: šifriraj, podpiši</string>
+ <string name="msg_ip_master_flags_xexa">Glavne oznake: šifriraj, overi</string>
+ <string name="msg_ip_master_flags_xexx">Glavne oznake: šifriraj</string>
+ <string name="msg_ip_master_flags_xxsa">Glavne oznake: podpiši, overi</string>
+ <string name="msg_ip_master_flags_xxsx">Glavne oznake: podpiši</string>
+ <string name="msg_ip_master_flags_xxxa">Glavne oznake: overi</string>
+ <string name="msg_ip_master_flags_xxxx">Glavne oznake: brez</string>
+ <string name="msg_ip_merge_public">Združujem uvožene podatke z obstoječo zbirko javnih ključev</string>
+ <string name="msg_ip_merge_secret">Združujem uvožene podatke z obstoječo zbirko javnih ključev</string>
<string name="msg_ip_subkey">Obdelujem podključ %s</string>
<string name="msg_ip_subkey_expired">Podključ je potekel %s</string>
<string name="msg_ip_subkey_expires">Podključ poteče %s</string>
+ <string name="msg_ip_subkey_flags_unspecified">Oznake podključev: nedoločeno (najverjetneje vse)</string>
+ <string name="msg_ip_subkey_flags_cesa">Oznake podključev: potrdi, šifriraj, podpiši, overi</string>
+ <string name="msg_ip_subkey_flags_cesx">Oznake podključev: potrdi, šifriraj, podpiši</string>
+ <string name="msg_ip_subkey_flags_cexa">Oznake podključev: potrdi, šifriraj, overi</string>
+ <string name="msg_ip_subkey_flags_cexx">Oznake podključev: potrdi, šifriraj</string>
+ <string name="msg_ip_subkey_flags_cxsa">Oznake podključev: potrdi, podpiši, overi</string>
+ <string name="msg_ip_subkey_flags_cxsx">Oznake podključev: potrdi, podpiši</string>
+ <string name="msg_ip_subkey_flags_cxxa">Oznake podključev: potrdi, overi</string>
+ <string name="msg_ip_subkey_flags_cxxx">Oznake podključev: potrdi</string>
+ <string name="msg_ip_subkey_flags_xesa">Oznake podključev: šifriraj, podpiši, overi</string>
+ <string name="msg_ip_subkey_flags_xesx">Oznake podključev: šifriraj, podpiši</string>
+ <string name="msg_ip_subkey_flags_xexa">Oznake podključev: šifriraj, overi</string>
+ <string name="msg_ip_subkey_flags_xexx">Oznake podključev: šifriraj</string>
+ <string name="msg_ip_subkey_flags_xxsa">Oznake podključev: podpiši, overi</string>
+ <string name="msg_ip_subkey_flags_xxsx">Oznake podključev: podpiši</string>
+ <string name="msg_ip_subkey_flags_xxxa">Oznake podključev: overi</string>
+ <string name="msg_ip_subkey_flags_xxxx">Oznake podključev: brez</string>
<string name="msg_ip_success">Uspešno uvožena javna zbirka klučev </string>
+ <string name="msg_ip_success_identical">Zbirka ključev ne vsebuje novih podatkov. Nič za storiti.</string>
<string name="msg_ip_reinsert_secret">Ponovno vnašam zasebni ključ</string>
- <string name="msg_ip_uid_cert_bad">Naleteli ste na slab certifikat!</string>
- <string name="msg_ip_uid_cert_error">Napaka pri obdelavi certifikata!</string>
+ <string name="msg_ip_uid_cert_bad">Naleteli ste na slabo potrdilo!</string>
+ <string name="msg_ip_uid_cert_error">Napaka pri obdelavi potrdila!</string>
+ <string name="msg_ip_uid_cert_nonrevoke">Že posedujete ne-preklicna potrdila. Izpuščam.</string>
+ <string name="msg_ip_uid_cert_old">Potrdilo je starejše od trenutnega. Izpuščam.</string>
+ <string name="msg_ip_uid_cert_new">Potrdilo je novejše. Menjam trenutnega.</string>
+ <string name="msg_ip_uid_cert_good">Najdeno uporabno potrdilo od %1$s</string>
+ <string name="msg_ip_uid_cert_good_revoke">Najdeno preklicano potrdilo od %1$s</string>
+ <plurals name="msg_ip_uid_certs_unknown">
+ <item quantity="one">Izpuščam potrdilo, potrjeno s strani neznanih javnih ključev.</item>
+ <item quantity="two">Izpuščam %s potrdili, potrjeni s strani neznanih javnih ključev.</item>
+ <item quantity="few">Izpuščam %s potrdila, potrjena s strani neznanih javnih ključev.</item>
+ <item quantity="other">Izpuščam %s potrdil, potrjenih s strani neznanih javnih ključev.</item>
+ </plurals>
+ <string name="msg_ip_uid_classifying_zero">Razvrščam ID-je (na voljo ni noben ključ vreden zaupanja)</string>
+ <plurals name="msg_ip_uid_classifying">
+ <item quantity="one">Razvrščam ID-je (uporabljam en ključ vreden zaupanja)</item>
+ <item quantity="two">Razvrščam ID-je (uporabljam %s ključa vredna zaupanja)</item>
+ <item quantity="few">Razvrščam ID-je (uporabljam %s ključe vredne zaupanja)</item>
+ <item quantity="other">Razvrščam ID-je (uporabljam %s ključev vrednih zaupanja)</item>
+ </plurals>
+ <string name="msg_ip_uid_reorder">Prerazvrščam ID-je</string>
+ <string name="msg_ip_uid_processing">Procesiram ID %s</string>
+ <string name="msg_ip_uid_revoked">ID je preklican</string>
+ <string name="msg_ip_uat_cert_bad">Najdeno slabo potrdilo!</string>
+ <string name="msg_ip_uat_cert_error">Napaka pri obdelavi potrdil!</string>
+ <string name="msg_ip_uat_cert_nonrevoke">Že posedujete ne-preklicno potrdilo. Izpuščam.</string>
+ <string name="msg_ip_uat_cert_old">Potrdilo je starejše od trenutnega. Izpuščam.</string>
+ <string name="msg_ip_uat_cert_new">Potrdilo je novejše. Menjam trenutnega.</string>
+ <string name="msg_ip_uat_cert_good">Najdeno uporabno potrdilo od %1$s</string>
+ <string name="msg_ip_uat_cert_good_revoke">Najden preklic potrdila od %1$s</string>
+ <plurals name="msg_ip_uat_certs_unknown">
+ <item quantity="one">Izpuščam potrdilo, potrjenio s strani neznanih javnih ključev</item>
+ <item quantity="two">Izpuščam %s potrdii, potrjeni s strani neznanih javnih ključev</item>
+ <item quantity="few">Izpuščam %s potrdila, potrjena s strani neznanih javnih ključev</item>
+ <item quantity="other">Izpuščam %s potrdil, potrjenih s strani neznanih javnih ključev</item>
+ </plurals>
<string name="msg_is_bad_type_public">Poskus uvoza javne zbirke ključev kot zasebne. Prosimo prijavite dogodek kot \'hrošč\' (napako).</string>
<!--Import Secret log entries-->
<string name="msg_is">Uvažam zasebni ključ %s</string>
+ <string name="msg_is_db_exception">Napaka v bazi podatkov!</string>
<string name="msg_is_importing_subkeys">Procesiram zasebne podključe</string>
+ <string name="msg_is_error_io_exc">Napaka pri kodiranju zbirke ključev</string>
+ <string name="msg_is_merge_public">Združujem uvožene podatke v obstoječo zbirko ključev</string>
+ <string name="msg_is_merge_secret">Združujem uvožene podatke v obstoječo javno zbirko ključev</string>
+ <string name="msg_is_merge_special">Združujem podatke o samo-potrdilih iz javne zbirke ključev</string>
+ <string name="msg_is_pubring_generate">Generiram javno zbirko ključev iz zasebne</string>
+ <string name="msg_is_subkey_nonexistent">Podključ %s ni na voljo v zasebnem ključu</string>
+ <string name="msg_is_subkey_ok">Zasebni podključ %s označen kot razpoložljiv</string>
+ <string name="msg_is_subkey_empty">Zasebni podključ %s označen kot razpoložljiv, s praznim geslom</string>
+ <string name="msg_is_subkey_pin">Zasebni podključ %s označen kot razpoložljiv, s PIN kodo</string>
+ <string name="msg_is_subkey_stripped">Zasebni podključ %s označen kot razstavljen</string>
+ <string name="msg_is_subkey_divert">Zasebni podključ %s označen kot \'preusmerjen na pamtno kartico/NFC\'</string>
+ <string name="msg_is_success_identical">Zbirka ključev ne vsebuje nobenih novih podatkov. Nič za storiti.</string>
<string name="msg_is_success">Zasebna zbirka ključev uspešno uvožena</string>
<!--Keyring Canonicalization log entries-->
+ <string name="msg_kc_public">Kanoniziram javno zbirko ključev %s</string>
+ <string name="msg_kc_secret">Kanoniziram zasebno zbirko ključev %s</string>
+ <string name="msg_kc_error_v3">Toje ključ verzije OpenPGP 3, ki je zastarela in ni več podprta!</string>
+ <string name="msg_kc_error_no_uid">Zbirka ključev nima nobenega veljavnega ID-ja!</string>
+ <string name="msg_kc_error_master_algo">Glavni ključ uporablja neznan (%s) algoritem!</string>
<string name="msg_kc_master">Obdelujem glavni ključ...</string>
- <string name="msg_kc_revoke_dup">Umikam odvečen certifikat za preklic zbirk ključev</string>
+ <string name="msg_kc_master_bad_type">Odstranjujem potrdilo glavnega ključa neznanega tipa (%s)</string>
+ <string name="msg_kc_master_bad_local">Odstranjujem potrdilo glavnega ključa z oznako \'lokalno\'</string>
+ <string name="msg_kc_master_bad_err">Odstranjujem slabo potrdilo glavnega ključa</string>
+ <string name="msg_kc_master_bad_time">Odstranjujem preklicno potrdilo zbirke ključev s časovno znamko v prihodnosti</string>
+ <string name="msg_kc_master_bad_type_uid">Odstranjujem potrdilo ID-ja na slabi poziciji</string>
+ <string name="msg_kc_master_bad">Odstranjujem slabo potrdilo glavnega ključa</string>
+ <string name="msg_kc_master_local">Odstranjujem potrdilo glavnega ključa z oznako \"lokalno\"</string>
+ <string name="msg_kc_revoke_dup">Odstranjujem odvečno preklicno potrdilo zbirke ključev</string>
+ <string name="msg_kc_notation_dup">Odstranjujem odvečno potrdilo notacije</string>
+ <string name="msg_kc_notation_empty">Odstranjujem prazno potrdilo notacije</string>
<string name="msg_kc_sub">Obdelujem podključ %s</string>
- <string name="msg_kc_sub_bad">Umikam neveljaven certifikat za povezovanje podključev</string>
- <string name="msg_kc_sub_bad_err">Umikam slab certifikat za povezovanje podključev</string>
- <string name="msg_kc_sub_bad_time">Umikam certifikat za povezovanje podključev z časovno znamko v prihodnosti</string>
+ <string name="msg_kc_sub_bad">Umikam neveljavno potrdilo za povezovanje podključev</string>
+ <string name="msg_kc_sub_bad_err">Umikam slabo potrdilo za povezovanje podključev</string>
+ <string name="msg_kc_sub_bad_local">Odstranjujem povezano potrdilo podključa z oznako \'lokalno\'</string>
+ <string name="msg_kc_sub_bad_time">Umikam potrdilo za povezovanje podključev z časovno znamko v prihodnosti</string>
+ <string name="msg_kc_sub_bad_type">Neznano potrdilo podključa tipa %s</string>
+ <string name="msg_kc_sub_dup">Odstranjujem odvečno povezano potrdilo podključa</string>
+ <string name="msg_kc_sub_primary_bad">Zaradi neveljavnega primarnega povezanega potrdila odstranjujem povezano potrdilo podključa</string>
+ <string name="msg_kc_sub_primary_bad_err">Zaradi slabega glavnega povezanega potrdila odstranjujem povezano potrdilo podključa</string>
+ <string name="msg_kc_sub_primary_none">Zaradi manjkajočega primarnega povezanega potrdila odstranjujem povezano potrdilo podključa</string>
+ <string name="msg_kc_sub_no_cert">Najti ni nobenega veljavnega potrdila za %s. Odstranjujem iz zbirke.</string>
+ <string name="msg_kc_sub_revoke_bad_err">Odstranjujem slabo preklicno potrdilo podključa</string>
+ <string name="msg_kc_sub_revoke_bad">Odstranjujem slabo preklicno potrdilo podključa</string>
+ <string name="msg_kc_sub_revoke_dup">Odstranjujem odvečno preklicno potrdilo podključa</string>
+ <string name="msg_kc_sub_algo_bad_encrpyt">Podključ je označen za šifriranje, toda algoritem tega ne podpira.</string>
+ <string name="msg_kc_sub_algo_bad_sign">Podključ je označen za podpisovanje, toda algoritem tega ne podpira.</string>
+ <plurals name="msg_kc_success_bad">
+ <item quantity="one">Kanonizacija zbirke ključev uspešna. Odstranjeno je bilo eno napačno potrdilo.</item>
+ <item quantity="two">Kanonizacija zbirke ključev uspešna. Odstranjeni sta bili %d napačni potrdili.</item>
+ <item quantity="few">Kanonizacija zbirke ključev uspešna. Odstranjena so bila %d napačna potrdila.</item>
+ <item quantity="other">Kanonizacija zbirke ključev uspešna. Odstranjenih je bilo %d napačnih potrdil.</item>
+ </plurals>
+ <string name="msg_kc_success_bad_and_red">Kanonizacija zbirke ključev uspešna. Odstranjenih je bilo %1$s napačnih in %2$s odvečnih potrdil.</string>
+ <plurals name="msg_kc_success_redundant">
+ <item quantity="one">Kanonizacija zbirke ključev uspešna. Odstranjeno je bilo eno odvečno potrdilo.</item>
+ <item quantity="two">Kanonizacija zbirke ključev uspešna. Odstranjeni sta bili %d odvečni potrdili.</item>
+ <item quantity="few">Kanonizacija zbirke ključev uspešna. Odstranjena so bila %d odvečna potrdia.</item>
+ <item quantity="other">Kanonizacija zbirke ključev uspešna. Odstranjenih je bilo %d odvečnih potrdil.</item>
+ </plurals>
+ <string name="msg_kc_uid_bad_err">Odstranjujem slabo samo-potrdilo ID-ja \'%s\'</string>
+ <string name="msg_kc_uid_bad_local">Odstranjujem potrdilo ID-ja z oznako \'lokalno\'</string>
+ <string name="msg_kc_uid_bad_time">Odstranjujem ID z časovno oznako v prihodnosti</string>
+ <string name="msg_kc_uid_bad_type">Odstranjujem potrdilo ID-ja neznanega tipa (%s)</string>
+ <string name="msg_kc_uid_bad">Odstranujem slabo samo-potrdilo ID-ja \'%s\'</string>
+ <string name="msg_kc_uid_cert_dup">Odstranujem zastarelo samo-potrdilo ID-ja \'%s\'</string>
+ <string name="msg_kc_uid_foreign">Odstranjuejm potrdilo tujega ID-ja od \'%s\'</string>
+ <string name="msg_kc_uid_revoke_dup">Odstranjujem odvečno preklicno potrdilo ID-ja \'%s\'</string>
+ <string name="msg_kc_uid_revoke_old">Odstranjujem zastarelo preklicno potrdilo za ID %s\'</string>
+ <string name="msg_kc_uid_no_cert">Ne najdem veljavnega samo-potrdila za ID %s\'. Odstranjujem iz zbirke.</string>
+ <string name="msg_kc_uid_remove">Odstranjujem neveljaven ID \'%s\'</string>
+ <string name="msg_kc_uid_dup">Odstranjujem podvojeo identiteto %s\'. Ključ je vseboval dve. To lahko privede do manjkajočih potrdil!</string>
+ <string name="msg_kc_uid_warn_encoding">ID ni potrjen kot UTF-8!</string>
+ <string name="msg_kc_uat_bad_err">Odstranjujem slabo samo-potrdilo za povezanega uporabnika</string>
+ <string name="msg_kc_uat_bad_local">Odstranjujem potrdilo s strani uporabnika z oznako \'lokalno\'</string>
+ <string name="msg_kc_uat_bad_type">Odstranjujem potrdilo povezanega uporabnika neznanega tipa (%s)</string>
+ <string name="msg_kc_uat_bad">Odstranjujem slabo samo-potrdilo za povezanega uporabnika</string>
+ <string name="msg_kc_uat_cert_dup">Odstranjujem zastarelo samo-potrdilo za povezanega uporabnika</string>
+ <string name="msg_kc_uat_dup">Odstranjujem podvojenega povezanega uporabnika. Ključ je vseboval dva. To lahko privede do manjkajočih potrdil!</string>
+ <string name="msg_kc_uat_foreign">Odstranjujem potrdilo tujega povezanega uporabnika od</string>
+ <string name="msg_kc_uat_revoke_dup">Odstranjujem odvečno preklicno potrdilo za povezanega uporabnika</string>
+ <string name="msg_kc_uat_revoke_old">Odstranjujem zastarelo preklicno potrdilo za povezanega uporabnika</string>
+ <string name="msg_kc_uat_no_cert">Najdeno ni bilo nobeno veljavno samo-potrdilo povezanega uporabnika. Odstranjujem iz zbirke.</string>
+ <string name="msg_kc_uat_remove">Odstranjujem neveljavnega povezanega uporabnika</string>
+ <string name="msg_kc_uat_warn_encoding">ID ni potrjen kot UTF-8!</string>
<!--Keyring merging log entries-->
+ <string name="msg_mg_found_new">Najdenih %s novih potrdil v zbirki ključev</string>
<!--createSecretKeyRing-->
+ <string name="msg_cr_error_no_user_id">Zbirke ključev morajo biti ustvarjene z najmanj enim ID-jem!</string>
+ <string name="msg_cr_error_no_certify">Glavni ključ mora biti označen za potrjevanje!</string>
+ <string name="msg_cr_error_flags_dsa">Ključ vsebuje napačne oznake, DSA ne more biti uporabljen za šifriranje!</string>
+ <string name="msg_cr_error_flags_elgamal">Ključ vsebuje napačne oznake, ElGamal ne more biti uporabljen za podpisovanje!</string>
+ <string name="msg_cr_error_flags_ecdsa">Ključ vsebuje napačne oznake, ECDSA ne more biti uporabljen za šifriranje!</string>
+ <string name="msg_cr_error_flags_ecdh">Ključ vsebuje napačne oznake, ECDH ne more biti uporabljen za podpisovanje!</string>
<!--modifySecretKeyRing-->
+ <string name="msg_mf_error_keyid">NI ID-ja ključa. To je interna napaka, prosimo prijavite hrošča!</string>
+ <string name="msg_mf_error_master_none">Najdeno ni bilo nobeno uporabno glavno potrdilo (so vsa odstranjena?)</string>
+ <string name="msg_mf_error_noexist_primary">Naveden je slab primarni ID!</string>
+ <string name="msg_mf_error_noexist_revoke">Naveden je slab ID za preklic!</string>
+ <string name="msg_mf_error_revoked_primary">Preklican ID ne more biti primaren!</string>
+ <string name="msg_mf_primary_replace_old">Menjavam potrdilo prejšnjega ID-ja</string>
+ <string name="msg_mf_primary_new">Ustvarjam novo potrdilo za nov primaren ID</string>
<string name="msg_mf_subkey_new_id">Nov podključ z ID-jem: %s</string>
<string name="msg_mf_subkey_revoke">Preklic podključa %s</string>
+ <string name="msg_mf_uid_add">Dodajam ID %s</string>
+ <string name="msg_mf_uid_primary">Menjam primarni ID za %s</string>
+ <string name="msg_mf_uid_revoke">Preklicujem ID %s</string>
+ <string name="msg_mf_uid_error_empty">ID ne more biti prazen!</string>
<!--Consolidate-->
+ <string name="msg_con">Konsolidiram bazo podatkov</string>
<string name="msg_con_db_clear">Čiščenje podatkovne baze</string>
<!--Edit Key (higher level than modify)-->
<!--Promote key-->
@@ -436,7 +855,15 @@
<!--Messages for VerifySignedLiteralData operation-->
<!--Messages for SignEncrypt operation-->
<!--Messages for PgpSignEncrypt operation-->
+ <plurals name="msg_crt_certify_uids">
+ <item quantity="one">Potrjujem en ID za ključ %2$s</item>
+ <item quantity="two">Potrjujem %1$d ID-ja za ključ %2$s</item>
+ <item quantity="few">Potrjujem %1$d ID-je za ključ %2$s</item>
+ <item quantity="other">Potrjujem %1$d ID-jev za ključ %2$s</item>
+ </plurals>
+ <string name="msg_crt_error_self">Tak način izdajanja samo-potrdil ni mogoč!</string>
<string name="msg_crt_warn_not_found">Ključ ni bil najden!</string>
+ <string name="msg_crt_warn_cert_failed">Generacija potrdila ni uspela!</string>
<plurals name="error_import_non_pgp_part">
<item quantity="one">Del naložene datoteke je veljavnen objekt OpenPGP a ni ključ.</item>
<item quantity="two">Deli naložene datoteke so veljavni objekti OpenPGP a niso ključi.</item>
@@ -458,6 +885,7 @@
<string name="label_user_id">Identiteta</string>
<string name="unknown_uid">&lt;neznan&gt;</string>
<string name="empty_certs">Ni potrdil za ta ključ</string>
+ <string name="certs_text">Tu so prikazana samo preverjena samo-potrdila in preverjena potrdila ustvarjena z vašimi ključi</string>
<string name="label_revocation">Razlog za preklic</string>
<string name="label_cert_type">Vrsta</string>
<string name="error_key_not_found">Ključ ni bil najden!</string>
@@ -466,7 +894,7 @@
<string name="key_divert">preusmeri na pametno kartico/NFC</string>
<string name="key_no_passphrase">brez gesla</string>
<string name="key_unavailable">ni na voljo</string>
- <string name="title_view_cert">Preglej podrobosti certifikata</string>
+ <string name="title_view_cert">Preglej podrobosti potrdila</string>
<string name="unknown_algorithm">neznan</string>
<string name="can_sign_not">ne more podpisati</string>
<string name="error_no_encrypt_subkey">Ni nobenega podključa za šifriranje!</string>
diff --git a/OpenKeychain/src/main/res/values-sv/strings.xml b/OpenKeychain/src/main/res/values-sv/strings.xml
index e17fcdddc..f73be4861 100644
--- a/OpenKeychain/src/main/res/values-sv/strings.xml
+++ b/OpenKeychain/src/main/res/values-sv/strings.xml
@@ -4,8 +4,6 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">Välj nycklar</string>
- <string name="title_select_secret_key">Välj din nyckel</string>
<string name="title_encrypt_text">Kryptera</string>
<string name="title_encrypt_files">Kryptera</string>
<string name="title_decrypt">Dekryptera</string>
@@ -13,7 +11,6 @@
<string name="title_add_subkey">Lägg till undernyckel</string>
<string name="title_edit_key">Redigera nyckel</string>
<string name="title_preferences">Inställningar</string>
- <string name="title_cloud_search_preferences">Inställningar för molnsökning</string>
<string name="title_api_registered_apps">Appar</string>
<string name="title_key_server_preference">Nyckelservrar</string>
<string name="title_change_passphrase">Ändra lösenordsfras</string>
@@ -24,7 +21,6 @@
<string name="title_encrypt_to_file">Kryptera till fil</string>
<string name="title_decrypt_to_file">Dekryptera till fil</string>
<string name="title_import_keys">Importera nycklar</string>
- <string name="title_add_keys">Lägg till nycklar</string>
<string name="title_export_key">Exportera nyckel</string>
<string name="title_export_keys">Exportera nycklar</string>
<string name="title_key_not_found">Nyckel hittades inte</string>
@@ -33,10 +29,8 @@
<string name="title_key_details">Nyckelinformation</string>
<string name="title_help">Hjälp</string>
<string name="title_log_display">Logg</string>
- <string name="title_create_key">Skapa nyckel</string>
<string name="title_exchange_keys">Utbyt nycklar</string>
<string name="title_advanced_key_info">Avancerad nyckelinfo</string>
- <string name="title_keys">Nycklar</string>
<string name="title_delete_secret_key">Radera DIN nyckel \'%s\'?</string>
<string name="title_export_log">Exportera logg</string>
<!--section-->
@@ -46,27 +40,18 @@
<string name="section_cloud_evidence">Bevis från molnet</string>
<string name="section_keys">Undernycklar</string>
<string name="section_cloud_search">Molnsökning</string>
- <string name="section_general">Allmänt</string>
- <string name="section_defaults">Förval</string>
- <string name="section_advanced">Avancerat</string>
<string name="section_passphrase_cache">Cache för lösenordsfras</string>
<string name="section_certify">Bekräfta</string>
<string name="section_actions">Åtgärder</string>
<string name="section_share_key">Nyckel</string>
- <string name="section_upload_key">Synkronisera nyckel</string>
<string name="section_key_server">Nyckelserver</string>
<string name="section_fingerprint">Fingeravtryck</string>
- <string name="section_decrypt_files">Filer</string>
- <string name="section_decrypt_text">Text</string>
- <string name="section_certs">Certifikat</string>
<string name="section_encrypt">Kryptera</string>
<string name="section_decrypt">Dekryptera</string>
<string name="section_current_expiry">Aktuellt utgångsdatum</string>
<string name="section_new_expiry">Nytt utgångsdaum</string>
<!--button-->
<string name="btn_decrypt_verify_file">Dekryptera, verifiera och spara fil</string>
- <string name="btn_decrypt_verify_message">Avkryptera och verifiera text</string>
- <string name="btn_encrypt_file">Kryptera och spara fil</string>
<string name="btn_encrypt_share_file">Kryptera och dela fil</string>
<string name="btn_encrypt_save_file">Kryptera och spara fil</string>
<string name="btn_save">Spara</string>
@@ -79,7 +64,6 @@
<string name="btn_back">Föregående</string>
<string name="btn_no">Nej</string>
<string name="btn_match">Fingeravtrycken matchar</string>
- <string name="btn_lookup_key">Sök efter nyckel</string>
<string name="btn_share_encrypted_signed">Kryptera och dela text</string>
<string name="btn_copy_encrypted_signed">Kryptera och kopiera text</string>
<string name="btn_view_cert_key">Visa nyckel för certifiering</string>
@@ -97,15 +81,11 @@
<string name="menu_help">Hjälp</string>
<string name="menu_export_key">Exportera till fil</string>
<string name="menu_delete_key">Radera nyckel</string>
- <string name="menu_import_existing_key">Importera från fil</string>
<string name="menu_search">Sök</string>
<string name="menu_nfc_preferences">NFC-inställningar</string>
<string name="menu_beam_preferences">Beam-inställningar</string>
- <string name="menu_key_edit_cancel">Avbryt</string>
<string name="menu_encrypt_to">Kryptera till…</string>
<string name="menu_select_all">Markera alla</string>
- <string name="menu_add_keys">Lägg till nycklar</string>
- <string name="menu_search_cloud">Sök i molnet</string>
<string name="menu_export_all_keys">Exportera alla nycklar</string>
<string name="menu_advanced">Visa avancerad information</string>
<string name="menu_certify_fingerprint">Bekräfta via fingeravtrycksjämförelse</string>
@@ -213,9 +193,6 @@
<string name="encrypt_sign_clipboard_successful">Signerades och/eller krypterades till urklipp.</string>
<string name="select_encryption_key">Välj åtminstone en krypteringsnyckel.</string>
<string name="select_encryption_or_signature_key">Välj åtminstone en krypterings- eller signeringsnyckel.</string>
- <string name="specify_file_to_encrypt_to">Ange vilken fil som du vill kryptera till.\nVARNING: Om filen redan finns kommer den att skrivas över.</string>
- <string name="specify_file_to_decrypt_to">Ange vilken fil som du vill dekryptera till.\nVARNING: Om filen redan finns kommer den att skrivas över.</string>
- <string name="specify_file_to_export_to">Ange vilken fil som du vill exportera till.\nVARNING: Om filen redan finns kommer den att skrivas över.</string>
<string name="key_deletion_confirmation_multi">Vill du verkligen radera alla markerade nycklar?</string>
<string name="secret_key_deletion_confirmation">Efter radering kommer du inte kunna läsa meddelande krypterade med den här nyckeln samt förlora alla nyckelbekräftningar som gjorts med den!</string>
<string name="public_key_deletetion_confirmation">Radera nyckel \'%s\'?</string>
diff --git a/OpenKeychain/src/main/res/values-tr/strings.xml b/OpenKeychain/src/main/res/values-tr/strings.xml
index 2e55eb620..12115e93b 100644
--- a/OpenKeychain/src/main/res/values-tr/strings.xml
+++ b/OpenKeychain/src/main/res/values-tr/strings.xml
@@ -4,12 +4,9 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">Anahtarları Seç</string>
- <string name="title_select_secret_key">Anahtarını Seç</string>
<string name="title_decrypt">Şifre çöz</string>
<string name="title_add_subkey">Alt anahtar ekle</string>
<string name="title_edit_key">Anahtarı düzenle</string>
- <string name="title_cloud_search_preferences">Bulut Arama Seçenekleri</string>
<string name="title_api_registered_apps">Uygulamalar</string>
<string name="title_change_passphrase">Parolayı Değiştir</string>
<string name="title_share_fingerprint_with">Parmak izini paylaş...</string>
@@ -18,7 +15,6 @@
<string name="title_encrypt_to_file">Dosyaya Şifrele</string>
<string name="title_decrypt_to_file">Dosyaya Çözümle</string>
<string name="title_import_keys">Anahtarları Al</string>
- <string name="title_add_keys">Anahtarlar Ekle</string>
<string name="title_export_key">Anahtarı Ver</string>
<string name="title_export_keys">Anahtarları Ver</string>
<string name="title_key_not_found">Anahtar Bulunamadı</string>
@@ -26,28 +22,19 @@
<string name="title_key_details">Anahtar Detayları</string>
<string name="title_help">Yardım</string>
<string name="title_log_display">Günlük</string>
- <string name="title_create_key">Anahtar Oluştur</string>
<string name="title_exchange_keys">Anahtarları Değiş Tokuş Et</string>
<string name="title_advanced_key_info">Gelişmiş Anahtar Bilgisi</string>
<!--section-->
<string name="section_user_ids">Kimlikler</string>
<string name="section_keys">Alt anahtarlar</string>
<string name="section_cloud_search">Bulut araması</string>
- <string name="section_general">Genel</string>
- <string name="section_defaults">Varsayılanlar</string>
- <string name="section_advanced">Gelişmiş</string>
<string name="section_passphrase_cache">Parola Önbelleği</string>
<string name="section_actions">Eylemler</string>
<string name="section_share_key">Anahtar</string>
- <string name="section_upload_key">Anahtarı Eşitle</string>
<string name="section_key_server">Anahtar Sunucusu</string>
<string name="section_fingerprint">Parmak izi</string>
- <string name="section_decrypt_files">Dosyalar</string>
- <string name="section_decrypt_text">Metin</string>
- <string name="section_certs">Sertifikalar</string>
<!--button-->
<string name="btn_decrypt_verify_file">Şifreyi çöz, doğrula ve dosyayı kaydet</string>
- <string name="btn_encrypt_file">Şifrele ve dosyayı kaydet</string>
<string name="btn_encrypt_share_file">Şifrele ve dosyayı paylaş</string>
<string name="btn_save">Kaydet</string>
<string name="btn_do_not_save">İptal</string>
@@ -57,7 +44,6 @@
<string name="btn_export_to_server">Anahtar Sunucusuna Yükle</string>
<string name="btn_next">İleri</string>
<string name="btn_back">Geri</string>
- <string name="btn_lookup_key">Anahtarı ara</string>
<string name="btn_view_cert_key">Tasdikleme anahtarını görüntüle</string>
<string name="btn_create_key">Anahtar oluştur</string>
<string name="btn_add_files">Dosya(lar) ekle</string>
@@ -69,13 +55,10 @@
<string name="menu_help">Yardım</string>
<string name="menu_export_key">Dosyaya ver</string>
<string name="menu_delete_key">Anahtar sil</string>
- <string name="menu_import_existing_key">Dosyadan al</string>
<string name="menu_search">Ara</string>
<string name="menu_beam_preferences">NFC ayarları</string>
- <string name="menu_key_edit_cancel">İptal</string>
<string name="menu_encrypt_to">Şuna şifrele...</string>
<string name="menu_select_all">Hepsini seç</string>
- <string name="menu_add_keys">Anahtar ekle</string>
<string name="menu_export_all_keys">Tüm anahtarları ver</string>
<string name="menu_advanced">Gelişmiş bilgiyi göster</string>
<!--label-->
@@ -170,9 +153,6 @@
<string name="encrypt_sign_clipboard_successful">Kopyalama önbelleğine başarıyla imzalandı ve/veya şifrelendi.</string>
<string name="select_encryption_key">En az bir şifreleme anahtarı seçiniz.</string>
<string name="select_encryption_or_signature_key">En az bir şifreleme anahtarı veya imza anahtarı seçiniz.</string>
- <string name="specify_file_to_encrypt_to">Lütfen şifreleme sonucu hangi dosyanın oluşturulması gerektiğini belirtin.\nUYARI: Eğer dosya mevcutsa üzerine yazılacaktır.</string>
- <string name="specify_file_to_decrypt_to">Lütfen şifre çözme sonucu hangi dosyanın oluşturulması gerektiğini belirtin.\nUYARI: Eğer dosya mevcutsa üzerine yazılacaktır.</string>
- <string name="specify_file_to_export_to">Lütfen dışa aktarım için hangi dosyanın kullanılması gerektiğini belirtin.\nUYARI: Eğer dosya mevcutsa üzerine yazılacaktır.</string>
<string name="also_export_secret_keys">Özel anahtarları da dışa aktar</string>
<string name="reinstall_openkeychain">Android için bilinen bir hataya denk geldiniz. Eğer kişilerinizi anahtarlarla eşlemek istiyorsanız, lütfen OpenKeychain uygulamasını yeniden yükleyin.</string>
<string name="key_exported">1 anahtar başarıyla dışa aktarıldı.</string>
diff --git a/OpenKeychain/src/main/res/values-uk/strings.xml b/OpenKeychain/src/main/res/values-uk/strings.xml
index ecd5592be..58272c597 100644
--- a/OpenKeychain/src/main/res/values-uk/strings.xml
+++ b/OpenKeychain/src/main/res/values-uk/strings.xml
@@ -4,12 +4,9 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">Вибрати ключі</string>
- <string name="title_select_secret_key">Виберіть ваш ключ</string>
<string name="title_decrypt">Розшифрувати</string>
<string name="title_add_subkey">Додати підключ</string>
<string name="title_edit_key">Редагувати ключ</string>
- <string name="title_cloud_search_preferences">Налаштування хмарного пошуку</string>
<string name="title_api_registered_apps">Програми</string>
<string name="title_change_passphrase">Змінити парольну фразу</string>
<string name="title_share_fingerprint_with">Поділитися відбитком із…</string>
@@ -18,7 +15,6 @@
<string name="title_encrypt_to_file">Зашифрувати до файлу</string>
<string name="title_decrypt_to_file">Розшифрувати до файлу</string>
<string name="title_import_keys">Імпортувати ключі</string>
- <string name="title_add_keys">Додати ключі</string>
<string name="title_export_key">Експортувати ключ</string>
<string name="title_export_keys">Експортувати ключі</string>
<string name="title_key_not_found">Ключ не знайдено</string>
@@ -26,28 +22,19 @@
<string name="title_key_details">Подробиці про ключ</string>
<string name="title_help">Довідка</string>
<string name="title_log_display">Журнал</string>
- <string name="title_create_key">Створити ключ</string>
<string name="title_exchange_keys">Обміняти ключі</string>
<string name="title_advanced_key_info">Додаткова інформація про ключ</string>
<!--section-->
<string name="section_user_ids">Сутності</string>
<string name="section_keys">Підключі</string>
<string name="section_cloud_search">Хмарний пошук</string>
- <string name="section_general">Загальне</string>
- <string name="section_defaults">Типове</string>
- <string name="section_advanced">Додаткове</string>
<string name="section_passphrase_cache">Кеш парольної фрази</string>
<string name="section_actions">Дії</string>
<string name="section_share_key">Ключ</string>
- <string name="section_upload_key">Синхронізувати ключ</string>
<string name="section_key_server">Сервер ключів</string>
<string name="section_fingerprint">Відбиток</string>
- <string name="section_decrypt_files">Файли</string>
- <string name="section_decrypt_text">Текст</string>
- <string name="section_certs">Сертифікати</string>
<!--button-->
<string name="btn_decrypt_verify_file">Розшифрувати, перевірити та зберегти файл</string>
- <string name="btn_encrypt_file">Шифрувати і зберегти файл</string>
<string name="btn_encrypt_share_file">Зашифрувати та поширити файл</string>
<string name="btn_save">Зберегти</string>
<string name="btn_do_not_save">Скасувати</string>
@@ -57,7 +44,6 @@
<string name="btn_export_to_server">Завантажити на сервер ключів</string>
<string name="btn_next">Далі</string>
<string name="btn_back">Назад</string>
- <string name="btn_lookup_key">Шукати ключ</string>
<string name="btn_view_cert_key">Переглянути ключ сертифікації</string>
<string name="btn_create_key">Створити ключ</string>
<string name="btn_add_files">Додати файл(и)</string>
@@ -69,13 +55,10 @@
<string name="menu_help">Довідка</string>
<string name="menu_export_key">Експорт до файлу</string>
<string name="menu_delete_key">Вилучити ключ</string>
- <string name="menu_import_existing_key">Імпорт з файлу</string>
<string name="menu_search">Пошук</string>
<string name="menu_beam_preferences">Налаштування променя</string>
- <string name="menu_key_edit_cancel">Скасувати</string>
<string name="menu_encrypt_to">Зашифрувати…</string>
<string name="menu_select_all">Вибрати усе</string>
- <string name="menu_add_keys">Додати ключі</string>
<string name="menu_export_all_keys">Експортувати усі ключі</string>
<string name="menu_advanced">Показати додаткову інформацію</string>
<!--label-->
@@ -171,9 +154,6 @@
<string name="encrypt_sign_clipboard_successful">Успішно підписано та/або зашифровано до буфера обміну.</string>
<string name="select_encryption_key">Виберіть принаймні один ключ шифрування.</string>
<string name="select_encryption_or_signature_key">Виберіть принаймні один ключ шифрування або ключ підпису.</string>
- <string name="specify_file_to_encrypt_to">Будь ласка, виберіть файл для шифрування.\nУВАГА! Якщо файл існує, то він буде переписаний.</string>
- <string name="specify_file_to_decrypt_to">Будь ласка, виберіть файл для розшифрування.\nУВАГА! Якщо файл існує, то він буде переписаний.</string>
- <string name="specify_file_to_export_to">Будь ласка, виберіть файл для експорту.\nУВАГА! Якщо файл існує, то він буде переписаний.</string>
<string name="also_export_secret_keys">Також експортувати секретні ключі</string>
<string name="key_exported">Успішно експортовано 1 ключ.</string>
<string name="keys_exported">Успішно експортовано %d ключів.</string>
diff --git a/OpenKeychain/src/main/res/values-zh-rTW/strings.xml b/OpenKeychain/src/main/res/values-zh-rTW/strings.xml
index a6fd905e1..ffe2d0aae 100644
--- a/OpenKeychain/src/main/res/values-zh-rTW/strings.xml
+++ b/OpenKeychain/src/main/res/values-zh-rTW/strings.xml
@@ -4,47 +4,53 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">選擇金鑰</string>
- <string name="title_select_secret_key">選擇私鑰</string>
+ <string name="title_encrypt_text">加密</string>
+ <string name="title_encrypt_files">加密</string>
<string name="title_decrypt">解密</string>
+ <string name="title_unlock">解鎖金鑰</string>
<string name="title_add_subkey">新增子金鑰</string>
<string name="title_edit_key">編輯金鑰</string>
- <string name="title_cloud_search_preferences">雲端查詢設定</string>
+ <string name="title_preferences">設定</string>
<string name="title_api_registered_apps">應用程式</string>
+ <string name="title_key_server_preference">金鑰伺服器</string>
<string name="title_change_passphrase">變更口令</string>
<string name="title_share_fingerprint_with">分享指紋…</string>
<string name="title_share_key">分享金鑰…</string>
<string name="title_share_file">分享檔案…</string>
+ <string name="title_share_message">分享文字...</string>
<string name="title_encrypt_to_file">加密到檔案</string>
<string name="title_decrypt_to_file">解密到檔案</string>
<string name="title_import_keys">匯入金鑰</string>
- <string name="title_add_keys">新增金鑰</string>
<string name="title_export_key">匯出金鑰</string>
<string name="title_export_keys">匯出所有金鑰</string>
<string name="title_key_not_found">找不到金鑰</string>
<string name="title_send_key">上傳到金鑰伺服器</string>
+ <string name="title_certify_key">確認金鑰</string>
<string name="title_key_details">金鑰內容</string>
<string name="title_help">說明</string>
<string name="title_log_display">紀錄</string>
- <string name="title_create_key">建立金鑰</string>
<string name="title_exchange_keys">交換金鑰</string>
<string name="title_advanced_key_info">進階資訊</string>
+ <string name="title_delete_secret_key">刪除您的金鑰 \'%s\'?</string>
+ <string name="title_export_log">匯出記錄</string>
+ <string name="title_manage_my_keys">管理我的金鑰</string>
<!--section-->
<string name="section_user_ids">身份</string>
+ <string name="section_should_you_trust">您信任這把金鑰嗎?</string>
<string name="section_keys">子金鑰</string>
<string name="section_cloud_search">雲端查詢</string>
- <string name="section_general">一般</string>
- <string name="section_defaults">預設</string>
- <string name="section_advanced">進階</string>
<string name="section_passphrase_cache">口令快取</string>
+ <string name="section_certify">確認</string>
+ <string name="section_actions">操作</string>
+ <string name="section_share_key">金鑰</string>
<string name="section_key_server">金鑰伺服器</string>
<string name="section_fingerprint">指紋</string>
- <string name="section_decrypt_files">檔案</string>
- <string name="section_decrypt_text">文字</string>
+ <string name="section_encrypt">加密</string>
+ <string name="section_decrypt">解密</string>
<!--button-->
<string name="btn_decrypt_verify_file">解密並驗證檔案</string>
- <string name="btn_encrypt_file">加密檔案</string>
<string name="btn_encrypt_share_file">加密並分享檔案</string>
+ <string name="btn_encrypt_save_file">加密並儲存檔案</string>
<string name="btn_save">儲存</string>
<string name="btn_do_not_save">取消</string>
<string name="btn_delete">刪除</string>
@@ -53,42 +59,61 @@
<string name="btn_export_to_server">上傳到金鑰伺服器</string>
<string name="btn_next">下一步</string>
<string name="btn_back">返回</string>
- <string name="btn_lookup_key">尋找金鑰</string>
+ <string name="btn_no">不</string>
+ <string name="btn_match">指紋符合</string>
+ <string name="btn_share_encrypted_signed">加密並分享文字</string>
+ <string name="btn_copy_encrypted_signed">加密並複製文字</string>
<string name="btn_view_cert_key">檢視簽署的金鑰</string>
<string name="btn_create_key">建立金鑰</string>
<string name="btn_add_files">加入檔案</string>
<string name="btn_add_share_decrypted_text">解密並分享訊息</string>
+ <string name="btn_decrypt_clipboard">解密剪貼簿裏的文字</string>
<string name="btn_decrypt_and_verify">並且驗證簽名</string>
<string name="btn_decrypt_files">解密檔案</string>
+ <string name="btn_encrypt_files">加密檔案</string>
+ <string name="btn_encrypt_text">加密文字</string>
+ <string name="btn_add_email">增加額外的電子郵件信箱</string>
<!--menu-->
<string name="menu_preferences">設定</string>
<string name="menu_help">說明</string>
<string name="menu_export_key">匯出到檔案</string>
<string name="menu_delete_key">刪除金鑰</string>
- <string name="menu_import_existing_key">從檔案匯入</string>
+ <string name="menu_manage_keys">管理我的金鑰</string>
<string name="menu_search">搜尋</string>
+ <string name="menu_nfc_preferences">NFC 設定</string>
<string name="menu_beam_preferences">Beam 設定</string>
- <string name="menu_key_edit_cancel">取消</string>
+ <string name="menu_encrypt_to">加密到...</string>
<string name="menu_select_all">全選</string>
- <string name="menu_add_keys">加入金鑰</string>
<string name="menu_export_all_keys">匯出所有金鑰</string>
+ <string name="menu_update_all_keys">上傳所有金鑰</string>
<string name="menu_advanced">顯示進階資訊</string>
+ <string name="menu_certify_fingerprint">藉由指紋比對來認證</string>
+ <string name="menu_export_log">匯出記錄</string>
<!--label-->
+ <string name="label_message">文字</string>
<string name="label_file">檔案</string>
<string name="label_files">檔案</string>
+ <string name="label_file_colon">檔案:</string>
<string name="label_no_passphrase">沒有口令</string>
<string name="label_passphrase">口令</string>
+ <string name="label_unlock">解鎖中...</string>
<string name="label_passphrase_again">再次輸入口令</string>
+ <string name="label_show_passphrase">顯示口令</string>
<string name="label_algorithm">演算法</string>
<string name="label_write_version_header">讓別人知道我在使用OpenKeychain</string>
<string name="label_write_version_header_summary">在簽名、密文與匯出的金鑰裡寫入\'OpenKeychain v2.7\'</string>
+ <string name="label_use_default_yubikey_pin">使用預設的 Yubikey PIN</string>
+ <string name="label_use_num_keypad_for_yubikey_pin">輸入 YubiKey PIN 時使用數字鍵盤</string>
+ <string name="label_label_use_default_yubikey_pin_summary">使用預設的 PIN (123456) 來使用 NFC 存取 Yubikeys</string>
<string name="label_asymmetric_from">簽名自:</string>
<string name="label_to">加密給:</string>
+ <string name="label_delete_after_encryption">加密後刪除檔案</string>
<string name="label_delete_after_decryption">解密後刪除檔案</string>
<string name="label_encryption_algorithm">加密演算法</string>
<string name="label_hash_algorithm">雜湊演算法</string>
<string name="label_symmetric">使用口令加密</string>
<string name="label_passphrase_cache_ttl">快取時間</string>
+ <string name="label_message_compression">文字壓縮</string>
<string name="label_file_compression">檔案壓縮</string>
<string name="label_keyservers">金鑰伺服器</string>
<string name="label_key_id">金鑰ID</string>
@@ -100,12 +125,30 @@
<string name="label_main_user_id">主身份</string>
<string name="label_name">名字</string>
<string name="label_comment">註記</string>
- <string name="label_email">Email</string>
+ <string name="label_email">電子郵件</string>
<string name="label_send_key">與雲端同步</string>
<string name="label_fingerprint">指紋</string>
<string name="expiry_date_dialog_title">設定效期</string>
+ <string name="label_first_keyserver_is_used">(先列出的金鑰伺服器爲優先)</string>
+ <string name="label_preferred">優先</string>
+ <string name="label_enable_compression">啓用壓縮</string>
+ <string name="label_encrypt_filenames">加密檔名</string>
+ <string name="label_hidden_recipients">隱藏收件人</string>
+ <string name="pref_keyserver">搜尋金鑰伺服器</string>
+ <string name="pref_keyserver_summary">搜尋 HKP 金鑰伺服器</string>
+ <string name="pref_keybase">搜尋 Keybase.io</string>
+ <string name="pref_keybase_summary">搜尋 Keybase.io 索引</string>
+ <string name="user_id_no_name">&lt;無名&gt;</string>
+ <string name="none">&lt;無&gt;</string>
+ <plurals name="n_keys">
+ <item quantity="other">%d 金鑰</item>
+ </plurals>
+ <plurals name="n_keyservers">
+ <item quantity="other">%d 金鑰伺服器</item>
+ </plurals>
<string name="secret_key">密鑰:</string>
<!--choice-->
+ <string name="choice_none">無</string>
<string name="choice_15secs">15秒</string>
<string name="choice_1min">1分鐘</string>
<string name="choice_3mins">3分鐘</string>
@@ -137,58 +180,93 @@
<string name="passphrases_do_not_match">口令不相符。</string>
<string name="passphrase_must_not_be_empty">請輸入口令。</string>
<string name="passphrase_for_symmetric_encryption">對稱加密。</string>
+ <string name="passphrase_for">輸入 \'%s\' 的口令</string>
+ <string name="pin_for">輸入 \'%s\' 的 PIN</string>
+ <string name="yubikey_pin_for">輸入 PIN 來存取 \'%s\' 的 YubiKey</string>
+ <string name="file_delete_confirmation_title">刪除原始檔案?</string>
+ <string name="file_delete_confirmation">下列的檔案將會被刪除:%s</string>
+ <string name="file_delete_successful">%1$d 之 %2$d 的檔案已經被刪除。%3$s</string>
<string name="no_file_selected">請先選擇檔案。</string>
<string name="encrypt_sign_successful">成功簽名並/或加密。</string>
<string name="encrypt_sign_clipboard_successful">成功簽名並/或加密到剪貼簿。</string>
<string name="select_encryption_key">選擇至少一把加密金鑰。</string>
<string name="select_encryption_or_signature_key">選擇至少一把加密或簽名金鑰。</string>
- <string name="specify_file_to_encrypt_to">請選擇要將檔案加密到哪。\n警告:已經存在的檔案將被覆蓋。</string>
- <string name="specify_file_to_decrypt_to">請選擇要將檔案解密到哪。\n警告:已經存在的檔案將被覆蓋。</string>
- <string name="specify_file_to_export_to">請選擇要將檔案匯出到哪。\n警告:已經存在的檔案將被覆蓋。</string>
+ <string name="specify_file_to_encrypt_to">請指定欲加密的檔案。\n警告:已經存在的檔案將被覆蓋。</string>
+ <string name="specify_file_to_decrypt_to">請指定欲解密的檔案。\n警告:已經存在的檔案將被覆蓋。</string>
+ <string name="specify_file_to_export_to">請指定欲輸出的檔案。\n警告:已經存在的檔案將被覆蓋。</string>
+ <string name="key_deletion_confirmation_multi">您真的想要刪除所有已選金鑰嗎?</string>
+ <string name="secret_key_deletion_confirmation">刪除之後您將無法閱讀以這把金鑰加密的訊息,而且所有用這把金鑰做的認證都會失效!</string>
+ <string name="public_key_deletetion_confirmation">刪除金鑰 \'%s\' ?</string>
<string name="also_export_secret_keys">一併匯出私鑰</string>
+ <string name="reinstall_openkeychain">您遇到了一個已知的 Android 錯誤。如果您想要鏈接聯絡人和金鑰,請重新安裝 OpenKeychain。</string>
<string name="key_exported">成功匯出 1 把金鑰。</string>
<string name="keys_exported">成功匯出 %d 把金鑰。</string>
+ <string name="no_keys_exported">沒有金鑰被匯出。</string>
+ <string name="key_creation_el_gamal_info">注意:只有子金鑰支援 ElGamal。</string>
+ <string name="key_not_found">無法找到金鑰 %08X。</string>
+ <string name="specify_file_to_export_log_to">請指定欲匯出的檔案。\n警告:已經存在的檔案將被覆蓋。</string>
+ <plurals name="bad_keys_encountered">
+ <item quantity="other">%d 忽略不良的密鑰。或許您在輸出時使用\n --export-secret-subkeys 選項\n 請確認您使用\n --export-secret-keys\n 作爲選項。\"</item>
+ </plurals>
+ <string name="list_empty">這個清單是空的 !</string>
<string name="nfc_successful">NFC Beam發送金鑰成功!</string>
<string name="key_copied_to_clipboard">金鑰已複製到剪貼簿!</string>
<string name="fingerprint_copied_to_clipboard">指紋已複製到剪貼簿!</string>
+ <string name="select_key_to_certify">請選擇一把金鑰來做認證 !</string>
<string name="key_too_big_for_sharing">金鑰太大無法使用此方式分享!</string>
<string name="text_copied_to_clipboard">文字已複製到剪貼簿!</string>
<!--errors
no punctuation, all lowercase,
they will be put after "error_message", e.g. "Error: file not found"-->
+ <string name="error_file_delete_failed">尚未被刪除。請手動刪除他們 !</string>
+ <string name="error_file_added_already">%s 已經加入。</string>
<string name="error_file_not_found">找不到檔案</string>
<string name="error_no_secret_key_found">沒有適合的私鑰</string>
<string name="error_external_storage_not_ready">外部儲存空間尚未就緒</string>
<string name="error_key_size_minimum512bit">金鑰長度必須大於512位元</string>
+ <string name="error_unknown_algorithm_choice">不明的演算法選擇</string>
<string name="error_user_id_no_email">沒有找到電子郵件</string>
<string name="error_key_needs_a_user_id">需要至少一個身分識別</string>
<string name="error_no_signature_passphrase">沒有提供口令</string>
<string name="error_no_signature_key">找不到簽名金鑰</string>
+ <string name="error_invalid_data">沒有有效的 OpenPGP 加密或簽署內容 !</string>
<string name="error_integrity_check_failed">完整性檢查失敗!資料已被修改!</string>
<string name="error_wrong_passphrase">口令錯誤</string>
<string name="error_could_not_extract_private_key">無法抽取私鑰</string>
<!--errors without preceeding Error:-->
<string name="error_jelly_bean_needed">需要Android 4.1以上才能使用NFC Beam功能!</string>
+ <string name="error_nfc_needed">NFC 必須開啓 !</string>
+ <string name="error_beam_needed">Bean 必須開啓 !</string>
<string name="error_nothing_import">找不到金鑰!</string>
+ <string name="error_contacts_key_id_missing">從聯絡人取回金鑰 ID 失敗 !</string>
+ <string name="error_generic_report_bug">發生錯誤,請建立一個新的錯誤回報給 OpenKeychain。</string>
<!--results shown after decryption/verification-->
<string name="decrypt_result_no_signature">尚未簽名</string>
<string name="decrypt_result_invalid_signature">無效的簽章!</string>
+ <string name="decrypt_result_signature_uncertified">簽署自 (未認證 !)</string>
+ <string name="decrypt_result_signature_certified">簽署自</string>
<string name="decrypt_result_signature_expired_key">金鑰已過期!</string>
<string name="decrypt_result_signature_revoked_key">金鑰已被撤銷!</string>
<string name="decrypt_result_signature_missing_key">未知的公鑰</string>
<string name="decrypt_result_encrypted">已加密</string>
<string name="decrypt_result_not_encrypted">未加密</string>
+ <string name="decrypt_result_action_show">顯示</string>
+ <string name="decrypt_result_action_Lookup">查詢</string>
<string name="decrypt_invalid_text">簽名無效或是金鑰已經過期/被撤銷,無法確認訊息內容的作者。是否繼續顯示?</string>
<string name="decrypt_invalid_button">我明白這樣做的風險,顯示它!</string>
<!--Add keys-->
+ <string name="add_keys_my_key">我的金鑰:</string>
<!--progress dialogs, usually ending in '…'-->
<string name="progress_done">完成。</string>
<string name="progress_cancel">取消</string>
<string name="progress_cancelling">正在取消…</string>
<string name="progress_saving">正在儲存…</string>
<string name="progress_importing">匯入中…</string>
+ <string name="progress_updating">正在更新金鑰...</string>
<string name="progress_exporting">匯出中…</string>
<string name="progress_uploading">正在上傳…</string>
+ <string name="progress_building_key">正在建立金鑰...</string>
+ <string name="progress_building_master_key">正在建立主環...</string>
<string name="progress_generating_rsa">正在產生新的RSA金鑰…</string>
<string name="progress_generating_dsa">正在產生新的DSA金鑰…</string>
<string name="progress_generating_elgamal">正在產生新的ElGamal金鑰…</string>
@@ -197,10 +275,12 @@
<string name="progress_modify">正在變更鑰匙圈…</string>
<string name="progress_modify_unlock">正在解鎖鑰匙圈…</string>
<string name="progress_modify_adduid">正在新增使用者身份…</string>
+ <string name="progress_modify_adduat">正在增加使用者屬性...</string>
<string name="progress_modify_revokeuid">正在撤銷使用者身份…</string>
<string name="progress_modify_primaryuid">正在變更主要使用者身份…</string>
<string name="progress_modify_subkeychange">正在變更子金鑰…</string>
<string name="progress_modify_subkeyrevoke">正在撤銷子金鑰…</string>
+ <string name="progress_modify_subkeystrip">正在卸下子金鑰...</string>
<string name="progress_modify_subkeyadd">正在新增子金鑰…</string>
<string name="progress_modify_passphrase">正在變更口令…</string>
<plurals name="progress_exporting_key">
@@ -221,8 +301,10 @@
<string name="progress_finding_key">正在尋找金鑰…</string>
<string name="progress_decompressing_data">正在解壓縮…</string>
<string name="progress_verifying_integrity">正在驗證完整性…</string>
+ <string name="progress_deleting_securely">正在安全地刪除 \'%s\'...</string>
<string name="progress_deleting">正在刪除金鑰…</string>
<!--action strings-->
+ <string name="hint_cloud_search_hint">使用姓名,電子郵件尋找...</string>
<!--key bit length selections-->
<string name="key_size_512">512</string>
<string name="key_size_768">768</string>
@@ -233,6 +315,9 @@
<string name="key_size_4096">4096</string>
<string name="key_size_8192">8192</string>
<string name="key_size_custom">自訂金鑰長度</string>
+ <string name="key_size_custom_info">輸入自定金鑰長度 (位元數):</string>
+ <string name="key_size_custom_info_rsa">RSA 金鑰長度必須要大於 1024 最多 16384。且必須爲 8 的倍數。</string>
+ <string name="key_size_custom_info_dsa">DSA 金鑰長度必須要大於 512 最多 1024。且必須爲 64 的倍數。</string>
<!--elliptic curve names-->
<string name="key_curve_nist_p256">NIST P-256</string>
<string name="key_curve_nist_p384">NIST P-384</string>
@@ -247,6 +332,7 @@
<!--Help-->
<string name="help_tab_start">快速上手</string>
<string name="help_tab_faq">常見問題</string>
+ <string name="help_tab_wot">金鑰認證</string>
<string name="help_tab_nfc_beam">NFC Beam</string>
<string name="help_tab_changelog">更新紀錄</string>
<string name="help_tab_about">關於</string>
@@ -257,8 +343,14 @@
<string name="import_tab_direct">檔案/剪貼簿</string>
<string name="import_tab_qr_code">二維條碼/NFC</string>
<string name="import_import">匯入選擇的金鑰</string>
+ <string name="import_qr_code_wrong">QR Code 異常 ! 請再試一次 !</string>
+ <string name="import_qr_code_too_short_fingerprint">指紋過短 (&lt; 16 個字元)</string>
<string name="import_qr_code_button">掃描二維條碼</string>
+ <string name="import_qr_code_text">將您的相機對準 QR Code !</string>
<!--Generic result toast-->
+ <string name="view_log">詳細</string>
+ <string name="with_warnings">,包含警告</string>
+ <string name="with_cancelled">,直到被取消</string>
<!--Import result toast-->
<plurals name="import_keys_added_and_updated_1">
<item quantity="other">成功匯入%1$d金鑰</item>
@@ -272,12 +364,39 @@
<plurals name="import_keys_updated">
<item quantity="other">成功更新%1$d金鑰%2$s。</item>
</plurals>
+ <plurals name="import_keys_with_errors">
+ <item quantity="other">匯入 %d 金鑰失敗 !</item>
+ </plurals>
+ <plurals name="import_error">
+ <item quantity="other">匯入 %d 金鑰失敗 !</item>
+ </plurals>
<string name="import_error_nothing">沒有東西可以匯入。</string>
<string name="import_error_nothing_cancelled">匯入已取消。</string>
<!--Delete result toast-->
+ <plurals name="delete_ok_but_fail_1">
+ <item quantity="other">成功刪除 %1$d 金鑰</item>
+ </plurals>
+ <plurals name="delete_ok_but_fail_2">
+ <item quantity="other">,但刪除 %1$d 金鑰%2$s 失敗。</item>
+ </plurals>
+ <plurals name="delete_ok">
+ <item quantity="other">成功刪除 %1$d 金鑰%2$s。</item>
+ </plurals>
+ <plurals name="delete_fail">
+ <item quantity="other">錯誤刪除 %1$d 金鑰。</item>
+ </plurals>
<string name="delete_nothing">沒有東西可以刪除。</string>
<string name="delete_cancelled">刪除已取消。</string>
<!--Certify result toast-->
+ <plurals name="certify_keys_ok">
+ <item quantity="other">成功認證 %1$d 金鑰%2$s。</item>
+ </plurals>
+ <plurals name="certify_keys_with_errors">
+ <item quantity="other">認證 %d 金鑰失敗 !</item>
+ </plurals>
+ <plurals name="certify_error">
+ <item quantity="other">認證 %d 金鑰失敗 !</item>
+ </plurals>
<!--Intent labels-->
<string name="intent_decrypt_file">使用OpenKeychain解密檔案</string>
<string name="intent_import_key">匯入金鑰至OpenKeychain</string>
@@ -290,12 +409,15 @@
<string name="api_settings_hide_advanced">隱藏進階設定</string>
<string name="api_settings_no_key">沒有選擇金鑰</string>
<string name="api_settings_select_key">選擇金鑰</string>
+ <string name="api_settings_create_key">建立新金鑰</string>
<string name="api_settings_save">儲存</string>
<string name="api_settings_save_msg">帳戶已儲存</string>
<string name="api_settings_cancel">取消</string>
<string name="api_settings_revoke">撤銷存取</string>
<string name="api_settings_start">開啟應用程式</string>
<string name="api_settings_delete_account">移除帳戶</string>
+ <string name="api_settings_package_name">打包名稱</string>
+ <string name="api_settings_package_signature">SHA-256 所打包的簽章</string>
<string name="api_settings_settings">設定</string>
<string name="api_settings_key">帳戶金鑰:</string>
<string name="api_settings_accounts_empty">沒有帳戶被指派給這個應用程式。</string>
@@ -421,5 +543,15 @@
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<!--<string name="enter_passphrase_twice">Enter passphrase twice</string>-->
+ <string name="passphrase_again">再一次</string>
+ <string name="unlock_method">解鎖方法</string>
+ <string name="set_passphrase">設定口令</string>
+ <string name="nfc_title">NFC</string>
<!--<string name="nfc_text">Please place a NFC tag near your device</string>-->
+ <string name="nfc_wrong_tag">錯誤的標籤。請再試一次。</string>
+ <string name="enable_nfc">請在您的設定中啓用 NFC</string>
+ <string name="no_nfc_support">該裝置不支援 NFC</string>
+ <string name="nfc_write_succesful">成功寫入 NFC 標籤</string>
+ <string name="unlocked">解鎖</string>
+ <string name="nfc_settings">設定</string>
</resources>
diff --git a/OpenKeychain/src/main/res/values-zh/strings.xml b/OpenKeychain/src/main/res/values-zh/strings.xml
index 86059840a..f43cb3ebd 100644
--- a/OpenKeychain/src/main/res/values-zh/strings.xml
+++ b/OpenKeychain/src/main/res/values-zh/strings.xml
@@ -4,13 +4,10 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">OpenKeychain</string>
<!--title-->
- <string name="title_select_recipients">选择密钥</string>
- <string name="title_select_secret_key">选择私钥</string>
<string name="title_decrypt">解密</string>
<string name="title_add_subkey">添加子密钥</string>
<string name="title_edit_key">编辑密钥</string>
<string name="title_preferences">设置</string>
- <string name="title_cloud_search_preferences">云搜索设置</string>
<string name="title_api_registered_apps">已注册应用</string>
<string name="title_key_server_preference">密钥服务器</string>
<string name="title_change_passphrase">变更密码</string>
@@ -21,7 +18,6 @@
<string name="title_encrypt_to_file">加密至文件</string>
<string name="title_decrypt_to_file">解密至文件</string>
<string name="title_import_keys">导入密钥</string>
- <string name="title_add_keys">添加密钥</string>
<string name="title_export_key">导出密钥</string>
<string name="title_export_keys">导出密钥</string>
<string name="title_key_not_found">无法找到密钥</string>
@@ -30,27 +26,19 @@
<string name="title_key_details">密钥详情</string>
<string name="title_help">帮助</string>
<string name="title_log_display">日志</string>
- <string name="title_create_key">创建密钥</string>
<string name="title_advanced_key_info">更多密钥详情</string>
- <string name="title_keys">密钥</string>
<string name="title_export_log">导出日志</string>
<!--section-->
<string name="section_user_ids">用户名</string>
<string name="section_should_you_trust">应该相信此密钥?</string>
<string name="section_keys">子密钥</string>
<string name="section_cloud_search">在线搜索</string>
- <string name="section_general">常规</string>
- <string name="section_defaults">缺省</string>
- <string name="section_advanced">高级</string>
<string name="section_passphrase_cache">密语缓存</string>
<string name="section_certify">确认</string>
<string name="section_key_server">密钥服务器</string>
<string name="section_fingerprint">签名</string>
- <string name="section_decrypt_files">解密文件</string>
- <string name="section_decrypt_text">解密文本</string>
<!--button-->
<string name="btn_decrypt_verify_file">解密并验证文件</string>
- <string name="btn_encrypt_file">加密文件</string>
<string name="btn_encrypt_share_file">加密并分享文件</string>
<string name="btn_save">保存</string>
<string name="btn_do_not_save">取消</string>
@@ -73,10 +61,8 @@
<string name="menu_delete_key">删除密钥</string>
<string name="menu_search">搜索</string>
<string name="menu_beam_preferences">参数</string>
- <string name="menu_key_edit_cancel">取消</string>
<string name="menu_encrypt_to">加密到...</string>
<string name="menu_select_all">选择全部</string>
- <string name="menu_add_keys">添加密钥</string>
<string name="menu_export_all_keys">导出全部密钥</string>
<string name="menu_advanced">高级</string>
<!--label-->
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index 6a13a0b4f..4d5181a51 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -12,14 +12,13 @@
<string name="title_encrypt_text">"Encrypt"</string>
<string name="title_encrypt_files">"Encrypt"</string>
<string name="title_decrypt">"Decrypt"</string>
- <string name="title_unlock">"Unlock Key"</string>
<string name="title_add_subkey">"Add subkey"</string>
<string name="title_edit_key">"Edit Key"</string>
<string name="title_linked_create">"Create a Linked Identity"</string>
<string name="title_preferences">"Settings"</string>
<string name="title_api_registered_apps">"Apps"</string>
<string name="title_key_server_preference">"Keyservers"</string>
- <string name="title_change_passphrase">"Change Passphrase"</string>
+ <string name="title_change_passphrase">"Change Password"</string>
<string name="title_share_fingerprint_with">"Share fingerprint with…"</string>
<string name="title_share_key">"Share key with…"</string>
<string name="title_share_file">"Share file with…"</string>
@@ -36,20 +35,21 @@
<string name="title_help">"Help"</string>
<string name="title_log_display">"Log"</string>
<string name="title_exchange_keys">"Exchange Keys"</string>
- <string name="title_advanced_key_info">"Advanced Key Info"</string>
+ <string name="title_advanced_key_info">"Extended Information"</string>
<string name="title_delete_secret_key">"Delete YOUR key '%s'?"</string>
<string name="title_export_log">"Export Log"</string>
<string name="title_manage_my_keys">"Manage my keys"</string>
<!-- section -->
<string name="section_user_ids">"Identities"</string>
+ <string name="section_yubikey">"Yubikey"</string>
<string name="section_linked_system_contact">"Linked System Contact"</string>
<string name="section_should_you_trust">"Should you trust this key?"</string>
<string name="section_proof_details">Proof verification</string>
<string name="section_cloud_evidence">"Proofs from the cloud"</string>
<string name="section_keys">"Subkeys"</string>
<string name="section_cloud_search">"Cloud search"</string>
- <string name="section_passphrase_cache">"Passphrase Cache"</string>
+ <string name="section_passphrase_cache">"Password Cache"</string>
<string name="section_certify">"Confirm"</string>
<string name="section_actions">"Actions"</string>
<string name="section_share_key">"Key"</string>
@@ -86,6 +86,7 @@
<string name="btn_encrypt_files">"Encrypt files"</string>
<string name="btn_encrypt_text">"Encrypt text"</string>
<string name="btn_add_email">"Add additional email address"</string>
+ <string name="btn_unlock">"Unlock"</string>
<!-- menu -->
<string name="menu_preferences">"Settings"</string>
@@ -100,7 +101,7 @@
<string name="menu_select_all">"Select all"</string>
<string name="menu_export_all_keys">"Export all keys"</string>
<string name="menu_update_all_keys">"Update all keys"</string>
- <string name="menu_advanced">"Show advanced info"</string>
+ <string name="menu_advanced">"Extended information"</string>
<string name="menu_certify_fingerprint">"Confirm via fingerprint comparison"</string>
<string name="menu_export_log">"Export Log"</string>
@@ -109,11 +110,11 @@
<string name="label_file">"File"</string>
<string name="label_files">"File(s)"</string>
<string name="label_file_colon">"File:"</string>
- <string name="label_no_passphrase">"No Passphrase"</string>
- <string name="label_passphrase">"Passphrase"</string>
+ <string name="label_no_passphrase">"No Password"</string>
+ <string name="label_passphrase">"Password"</string>
<string name="label_unlock">"Unlocking…"</string>
- <string name="label_passphrase_again">"Repeat Passphrase"</string>
- <string name="label_show_passphrase">"Show Passphrase"</string>
+ <string name="label_passphrase_again">"Repeat Password"</string>
+ <string name="label_show_passphrase">"Show Password"</string>
<string name="label_algorithm">"Algorithm"</string>
<string name="label_ascii_armor">"File ASCII Armor"</string>
<string name="label_file_ascii_armor">"Enable ASCII Armor"</string>
@@ -128,9 +129,9 @@
<string name="label_delete_after_decryption">"Delete after decryption"</string>
<string name="label_encryption_algorithm">"Encryption algorithm"</string>
<string name="label_hash_algorithm">"Hash algorithm"</string>
- <string name="label_symmetric">"Encrypt with passphrase"</string>
+ <string name="label_symmetric">"Encrypt with password"</string>
<string name="label_passphrase_cache_ttl">"Cache time"</string>
- <string name="label_passphrase_cache_subs">"Cache passphrases by subkey"</string>
+ <string name="label_passphrase_cache_subs">"Cache passwords by subkey"</string>
<string name="label_message_compression">"Text compression"</string>
<string name="label_file_compression">"File compression"</string>
<string name="label_keyservers">"Keyservers"</string>
@@ -204,12 +205,12 @@
<string name="flag_authenticate">"Authenticate"</string>
<!-- sentences -->
- <string name="wrong_passphrase">"Wrong passphrase."</string>
+ <string name="wrong_passphrase">"Wrong password."</string>
<string name="no_filemanager_installed">"No compatible file manager installed."</string>
- <string name="passphrases_do_not_match">"The passphrases didn't match."</string>
- <string name="passphrase_must_not_be_empty">"Please enter a passphrase."</string>
+ <string name="passphrases_do_not_match">"The passwords didn't match."</string>
+ <string name="passphrase_must_not_be_empty">"Please enter a password."</string>
<string name="passphrase_for_symmetric_encryption">"Symmetric encryption."</string>
- <string name="passphrase_for">"Enter passphrase for '%s'"</string>
+ <string name="passphrase_for">"Enter password for '%s'"</string>
<string name="pin_for">"Enter PIN for '%s'"</string>
<string name="yubikey_pin_for">"Enter PIN to access YubiKey for '%s'"</string>
<string name="nfc_text">"Hold YubiKey against the back of your device."</string>
@@ -263,13 +264,13 @@
<string name="error_external_storage_not_ready">"external storage not ready"</string>
<string name="error_key_size_minimum512bit">"key size must be at least 512bit"</string>
<string name="error_unknown_algorithm_choice">"unknown algorithm choice"</string>
- <string name="error_user_id_no_email">"no email found"</string>
+ <string name="error_user_id_no_email">"no email address found"</string>
<string name="error_key_needs_a_user_id">"need at least one identity"</string>
- <string name="error_no_signature_passphrase">"no passphrase given"</string>
+ <string name="error_no_signature_passphrase">"no password given"</string>
<string name="error_no_signature_key">"no signature key given"</string>
<string name="error_invalid_data">"No valid encrypted or signed OpenPGP content!"</string>
<string name="error_integrity_check_failed">"integrity check failed! Data has been modified!"</string>
- <string name="error_wrong_passphrase">"wrong passphrase"</string>
+ <string name="error_wrong_passphrase">"wrong password"</string>
<string name="error_could_not_extract_private_key">"could not extract private key"</string>
<!-- errors without preceeding Error: -->
@@ -326,7 +327,7 @@
<string name="progress_modify_subkeyrevoke">"revoking subkeys…"</string>
<string name="progress_modify_subkeystrip">"stripping subkeys…"</string>
<string name="progress_modify_subkeyadd">"adding subkeys…"</string>
- <string name="progress_modify_passphrase">"changing passphrase…"</string>
+ <string name="progress_modify_passphrase">"changing passwords…"</string>
<plurals name="progress_exporting_key">
<item quantity="one">"exporting key…"</item>
@@ -479,10 +480,10 @@
<string name="intent_send_decrypt">"Decrypt with OpenKeychain"</string>
<!-- Remote API -->
- <string name="api_settings_show_info">"Show advanced information"</string>
- <string name="api_settings_hide_info">"Hide advanced information"</string>
- <string name="api_settings_show_advanced">"Show advanced settings"</string>
- <string name="api_settings_hide_advanced">"Hide advanced settings"</string>
+ <string name="api_settings_show_info">"Show extended information"</string>
+ <string name="api_settings_hide_info">"Hide extended information"</string>
+ <string name="api_settings_show_advanced">"Show extended settings"</string>
+ <string name="api_settings_hide_advanced">"Hide extended settings"</string>
<string name="api_settings_no_key">"No key selected"</string>
<string name="api_settings_select_key">"Select key"</string>
<string name="api_settings_create_key">"Create new key"</string>
@@ -495,7 +496,7 @@
<string name="api_settings_package_name">"Package Name"</string>
<string name="api_settings_package_signature">"SHA-256 of Package Signature"</string>
<string name="api_settings_accounts">"Accounts (deprecated API)"</string>
- <string name="api_settings_advanced">"Advanced Information"</string>
+ <string name="api_settings_advanced">"Extended Information"</string>
<string name="api_settings_allowed_keys">"Allowed Keys"</string>
<string name="api_settings_settings">"Settings"</string>
<string name="api_settings_key">"Account key:"</string>
@@ -593,7 +594,7 @@
<string name="keybase_verify">"Verify"</string>
<!-- Edit key -->
- <string name="edit_key_action_change_passphrase">"Change Passphrase"</string>
+ <string name="edit_key_action_change_passphrase">"Change Password"</string>
<string name="edit_key_action_add_identity">"Add Identity"</string>
<string name="edit_key_action_add_subkey">"Add Subkey"</string>
<string name="edit_key_edit_user_id_title">"Select an action!"</string>
@@ -619,19 +620,19 @@
<!-- Create key -->
<string name="create_key_upload">"Synchronize with the cloud"</string>
<string name="create_key_empty">"This field is required"</string>
- <string name="create_key_passphrases_not_equal">"Passphrases do not match"</string>
+ <string name="create_key_passphrases_not_equal">"Passwords do not match"</string>
<string name="create_key_final_text">"You entered the following identity:"</string>
<string name="create_key_final_robot_text">"Creating a key may take a while, have a cup of coffee in the meantime…"</string>
<string name="create_key_rsa">"(3 subkeys, RSA, 4096 bit)"</string>
<string name="create_key_custom">"(custom key configuration)"</string>
<string name="create_key_name_text">"Choose a name associated with this key. This can be a full name, e.g., 'John Doe', or a nickname, e.g., 'Johnny'."</string>
<string name="create_key_email_text">"Enter your main email address used for secure communication."</string>
- <string name="create_key_passphrase_text">"Choose a strong passphrase. It protects your key when your device gets stolen."</string>
+ <string name="create_key_passphrase_text">"Choose a strong password. It protects your key when your device gets stolen."</string>
<string name="create_key_hint_full_name">"Full Name or Nickname"</string>
<string name="create_key_edit">"Change key configuration"</string>
<string name="create_key_add_email">"Add email address"</string>
<string name="create_key_add_email_text">"Additional email addresses are also associated to this key and can be used for secure communication."</string>
- <string name="create_key_email_already_exists_text">"Email has already been added"</string>
+ <string name="create_key_email_already_exists_text">"Email address has already been added"</string>
<!-- View key -->
<string name="view_key_revoked">"Revoked: Key must not be used anymore!"</string>
@@ -778,7 +779,7 @@
<string name="msg_is_pubring_generate">"Generating public keyring from secret keyring"</string>
<string name="msg_is_subkey_nonexistent">"Subkey %s unavailable in secret key"</string>
<string name="msg_is_subkey_ok">"Marked secret subkey %s as available"</string>
- <string name="msg_is_subkey_empty">"Marked secret subkey %s as available, with empty passphrase"</string>
+ <string name="msg_is_subkey_empty">"Marked secret subkey %s as available, with empty password"</string>
<string name="msg_is_subkey_pin">"Marked secret subkey %s as available, with PIN"</string>
<string name="msg_is_subkey_stripped">"Marked secret subkey %s as stripped"</string>
<string name="msg_is_subkey_divert">"Marked secret subkey %s as 'divert to smartcard/NFC'"</string>
@@ -888,6 +889,7 @@
<!-- modifySecretKeyRing -->
<string name="msg_mr">"Modifying keyring %s"</string>
+ <string name="msg_mf_divert">"Will divert to card/nfc for crypto operations"</string>
<string name="msg_mf_error_divert_serial">"The serial number of a divert-to-card key must be 16 bytes! This is a programming error, please file a bug report!"</string>
<string name="msg_mf_error_encode">"Encoding exception!"</string>
<string name="msg_mf_error_fingerprint">"Actual key fingerprint does not match the expected one!"</string>
@@ -896,23 +898,27 @@
<string name="msg_mf_error_master_none">"No master certificate found to operate on! (All revoked?)"</string>
<string name="msg_mf_error_noexist_primary">"Bad primary user ID specified!"</string>
<string name="msg_mf_error_noexist_revoke">"Bad user ID for revocation specified!"</string>
- <string name="msg_mf_error_restricted">"Tried to execute restricted operation without passphrase! This is a programming error, please file a bug report!"</string>
+ <string name="msg_mf_error_restricted">"Tried to execute restricted operation without password! This is a programming error, please file a bug report!"</string>
<string name="msg_mf_error_revoked_primary">"Revoked user IDs cannot be primary!"</string>
<string name="msg_mf_error_null_expiry">"Expiry time cannot be "same as before" on subkey creation. This is a programming error, please file a bug report!"</string>
+ <string name="msg_mf_error_noop">"Nothing to do!"</string>
<string name="msg_mf_error_passphrase_master">"Fatal error decrypting master key! This is likely a programming error, please file a bug report!"</string>
<string name="msg_mf_error_pgp">"Internal OpenPGP error!"</string>
<string name="msg_mf_error_sig">"Signature exception!"</string>
+ <string name="msg_mf_error_subkey_missing">"Tried to operate on missing subkey %s!"</string>
<string name="msg_mf_master">"Modifying master certifications"</string>
<string name="msg_mf_notation_empty">"Adding empty notation packet"</string>
<string name="msg_mf_notation_pin">"Adding PIN notation packet"</string>
- <string name="msg_mf_passphrase">"Changing passphrase for keyring"</string>
- <string name="msg_mf_passphrase_key">"Re-encrypting subkey %s with new passphrase"</string>
- <string name="msg_mf_passphrase_empty_retry">"Setting new passphrase failed, trying again with empty old passphrase"</string>
- <string name="msg_mf_passphrase_fail">"Passphrase for subkey could not be changed! (Does it have a different one from the other keys?)"</string>
+ <string name="msg_mf_passphrase">"Changing password for keyring"</string>
+ <string name="msg_mf_passphrase_key">"Re-encrypting subkey %s with new password"</string>
+ <string name="msg_mf_passphrase_empty_retry">"Setting new password failed, trying again with empty old password"</string>
+ <string name="msg_mf_passphrase_fail">"Password for subkey could not be changed! (Does it have a different one from the other keys?)"</string>
<string name="msg_mf_primary_replace_old">"Replacing certificate of previous primary user ID"</string>
<string name="msg_mf_primary_new">"Generating new certificate for new primary user ID"</string>
+ <string name="msg_mf_restricted_mode">"Changing to restricted operation mode"</string>
<string name="msg_mf_subkey_change">"Modifying subkey %s"</string>
- <string name="msg_mf_error_subkey_missing">"Tried to operate on missing subkey %s!"</string>
+ <string name="msg_mf_require_divert">"Diverting to card/nfc for crypto operations"</string>
+ <string name="msg_mf_require_passphrase">"Password required for operations"</string>
<string name="msg_mf_subkey_new">"Adding new subkey of type %s"</string>
<string name="msg_mf_subkey_new_id">"New subkey ID: %s"</string>
<string name="msg_mf_error_past_expiry">"Expiry date cannot be in the past!"</string>
@@ -964,7 +970,7 @@
<!-- Edit Key (higher level than modify) -->
<string name="msg_ed">"Performing key operation"</string>
- <string name="msg_ed_caching_new">"Caching new passphrase"</string>
+ <string name="msg_ed_caching_new">"Caching new password"</string>
<string name="msg_ed_error_no_parcel">"Missing SaveKeyringParcel! (this is a bug, please report)"</string>
<string name="msg_ed_error_key_not_found">"Key not found!"</string>
<string name="msg_ed_fetching">"Fetching key to modify (%s)"</string>
@@ -972,13 +978,11 @@
<!-- Promote key -->
<string name="msg_pr">"Promoting public key to secret key"</string>
- <string name="msg_pr_error_already_secret">"Key is already a secret key!"</string>
<string name="msg_pr_error_key_not_found">"Key not found!"</string>
<string name="msg_pr_fetching">"Fetching key to modify (%s)"</string>
<string name="msg_pr_success">"Key successfully promoted"</string>
<!-- Other messages used in OperationLogs -->
- <string name="msg_ek_error_divert">"Editing of NFC keys is not (yet) supported!"</string>
<string name="msg_ek_error_dummy">"Cannot edit keyring with stripped master key!"</string>
<string name="msg_ek_error_not_found">"Key not found!"</string>
@@ -1000,7 +1004,7 @@
<string name="msg_dc_clear_signature_ok">"Signature check OK"</string>
<string name="msg_dc_clear_signature">"Saving signature data for later"</string>
<string name="msg_dc_clear">"Processing cleartext data"</string>
- <string name="msg_dc_error_bad_passphrase">"Error unlocking key, bad passphrase!"</string>
+ <string name="msg_dc_error_bad_passphrase">"Error unlocking key, bad password!"</string>
<string name="msg_dc_error_extract_key">"Unknown error unlocking key!"</string>
<string name="msg_dc_error_integrity_check">"Integrity check error!"</string>
<string name="msg_dc_error_integrity_missing">"Missing integrity check! This can happen because the encrypting application is out of date, or from a downgrade attack."</string>
@@ -1012,9 +1016,9 @@
<string name="msg_dc_integrity_check_ok">"Integrity check OK!"</string>
<string name="msg_dc_ok_meta_only">"Only metadata was requested, skipping decryption"</string>
<string name="msg_dc_ok">"Decryption/Verification finished"</string>
- <string name="msg_dc_pass_cached">"Using passphrase from cache"</string>
+ <string name="msg_dc_pass_cached">"Using password from cache"</string>
<string name="msg_dc_pending_nfc">"NFC token required, requesting user input…"</string>
- <string name="msg_dc_pending_passphrase">"Passphrase required, requesting user input…"</string>
+ <string name="msg_dc_pending_passphrase">"Password required, requesting user input…"</string>
<string name="msg_dc_prep_streams">"Preparing streams for decryption"</string>
<string name="msg_dc">"Starting decrypt operation…"</string>
<string name="msg_dc_sym_skip">"Symmetric data not allowed, skipping…"</string>
@@ -1046,7 +1050,6 @@
<string name="msg_se_error_input_uri_not_found">"Error opening URI for reading!"</string>
<string name="msg_se_error_output_uri_not_found">"Error opening URI for writing!"</string>
<string name="msg_se_error_too_many_inputs">"More inputs than outputs specified! This is probably a programming error, please report!"</string>
- <string name="msg_se_warn_output_left">"Got outputs left but no inputs. This is probably a programming error, please report!"</string>
<string name="msg_se_success">"Sign/encrypt operation successful"</string>
<!-- Messages for PgpSignEncrypt operation -->
@@ -1054,13 +1057,13 @@
<string name="msg_pse_clearsign_only">"Signing of cleartext input not supported!"</string>
<string name="msg_pse_compressing">"Preparing compression"</string>
<string name="msg_pse_encrypting">"Encrypting data"</string>
- <string name="msg_pse_error_bad_passphrase">"Bad passphrase!"</string>
+ <string name="msg_pse_error_bad_passphrase">"Bad password!"</string>
<string name="msg_pse_error_hash_algo">"Requested hashing algorithm is not supported by this key!"</string>
<string name="msg_pse_error_io">"Encountered IO Exception during operation!"</string>
<string name="msg_pse_error_key_sign">"Selected signing key cannot sign data!"</string>
<string name="msg_pse_error_sign_key">"Error fetching signing key!"</string>
<string name="msg_pse_error_nfc">"NFC data error!"</string>
- <string name="msg_pse_error_no_passphrase">"No passphrase provided!"</string>
+ <string name="msg_pse_error_no_passphrase">"No password provided!"</string>
<string name="msg_pse_error_pgp">"Internal OpenPGP error!"</string>
<string name="msg_pse_error_sig">"Encountered OpenPGP signature exception!"</string>
<string name="msg_pse_error_unlock">"Unknown error unlocking key!"</string>
@@ -1069,7 +1072,7 @@
<string name="msg_pse_key_warn">"Bad key for encryption: %s"</string>
<string name="msg_pse_ok">"Sign/Encrypt operation successful!"</string>
<string name="msg_pse_pending_nfc">"NFC token required, requesting user input…"</string>
- <string name="msg_pse_pending_passphrase">"Passphrase required, requesting user input…"</string>
+ <string name="msg_pse_pending_passphrase">"Password required, requesting user input…"</string>
<string name="msg_pse_signing">"Signing data (without encryption)"</string>
<string name="msg_pse_signing_cleartext">"Creating cleartext signature"</string>
<string name="msg_pse_signing_detached">"Creating detached signature"</string>
@@ -1090,9 +1093,9 @@
<string name="msg_crt_error_master_not_found">"Master key not found!"</string>
<string name="msg_crt_error_nothing">"No keys certified!"</string>
<string name="msg_crt_error_unlock">"Error unlocking master key!"</string>
- <string name="msg_crt_error_divert">"Certification with NFC is not (yet) supported!"</string>
<string name="msg_crt">"Certifying keyrings"</string>
<string name="msg_crt_master_fetch">"Fetching certifying master key"</string>
+ <string name="msg_crt_nfc_return">"Returning for NFC input"</string>
<string name="msg_crt_save">"Saving certified key %s"</string>
<string name="msg_crt_saving">"Saving keyrings"</string>
<string name="msg_crt_unlock">"Unlocking master key"</string>
@@ -1110,7 +1113,7 @@
<string name="msg_import_fetch_error_decode">"Error decoding retrieved keyring!"</string>
<string name="msg_import_fetch_error">"Key could not be retrieved! (Network problems?)"</string>
<string name="msg_import_fetch_keybase">"Retrieving from keybase.io: %s"</string>
- <string name="msg_import_fetch_keyserver_error">"Could not retrieve key from keybase!"</string>
+ <string name="msg_import_fetch_keyserver_error">"Could not retrieve key from keyservers: %s"</string>
<string name="msg_import_fetch_keyserver">"Retrieving from keyserver: %s"</string>
<string name="msg_import_fetch_keyserver_ok">"Key retrieval successful"</string>
<string name="msg_import_keyserver">"Using keyserver %s"</string>
@@ -1202,11 +1205,11 @@
<string name="msg_export_log_success">"Log exported successfully!"</string>
<!-- PassphraseCache -->
- <string name="passp_cache_notif_click_to_clear">"Click to clear cached passphrases"</string>
- <string name="passp_cache_notif_n_keys">"OpenKeychain has cached %d passphrases"</string>
- <string name="passp_cache_notif_keys">"Cached Passphrases:"</string>
+ <string name="passp_cache_notif_click_to_clear">"Click to clear cached passwords"</string>
+ <string name="passp_cache_notif_n_keys">"OpenKeychain has cached %d passwords"</string>
+ <string name="passp_cache_notif_keys">"Cached Passwords:"</string>
<string name="passp_cache_notif_clear">"Clear Cache"</string>
- <string name="passp_cache_notif_pwd">"Passphrase"</string>
+ <string name="passp_cache_notif_pwd">"Password"</string>
<!-- First Time -->
<string name="first_time_text1">"Take back your privacy with OpenKeychain!"</string>
@@ -1232,7 +1235,7 @@
<string name="error_key_processing">"Error processing key!"</string>
<string name="key_stripped">"stripped"</string>
<string name="key_divert">"divert to smartcard/NFC"</string>
- <string name="key_no_passphrase">"no passphrase"</string>
+ <string name="key_no_passphrase">"no password"</string>
<string name="key_unavailable">"unavailable"</string>
<string name="secret_cannot_multiple">"Your own keys can only be deleted individually!"</string>
<string name="title_view_cert">"View Certificate Details"</string>
@@ -1252,20 +1255,20 @@
<!-- Passphrase wizard -->
<!-- TODO: rename all the things! -->
<string name="title_unlock_method">Choose an unlock method</string>
- <!--<string name="enter_passphrase_twice">Enter passphrase twice</string>-->
- <string name="enter_passphrase">Enter passphrase</string>
- <string name="passphrase">Passphrase</string>
- <string name="noPassphrase">No passphrase</string>
- <string name="no_passphrase_set">No passphrase set</string>
- <string name="passphrases_match">Passphrases do match</string>
- <string name="passphrase_saved">Passphrase saved</string>
- <string name="passphrase_invalid">Passphrase invalid</string>
- <string name="missing_passphrase">Missing passphrase</string>
+ <!--<string name="enter_passphrase_twice">Enter password twice</string>-->
+ <string name="enter_passphrase">Enter password</string>
+ <string name="passphrase">Password</string>
+ <string name="noPassphrase">No password</string>
+ <string name="no_passphrase_set">No password set</string>
+ <string name="passphrases_match">Passwords do match</string>
+ <string name="passphrase_saved">Password saved</string>
+ <string name="passphrase_invalid">Password invalid</string>
+ <string name="missing_passphrase">Missing password</string>
<string name="passphrase_again">Again</string>
<string name="lockpattern">Lockpattern</string>
<string name="lockpatternNFC">NFC + Lockpattern</string>
<string name="unlock_method">Unlock method</string>
- <string name="set_passphrase">Set passphrase</string>
+ <string name="set_passphrase">Set password</string>
<string name="draw_lockpattern">Draw lockpattern</string>
<string name="nfc_title">NFC</string>
<!--<string name="nfc_text">Please place a NFC tag near your device</string>-->
@@ -1275,6 +1278,19 @@
<string name="nfc_write_succesful">Successfully written on NFC tag</string>
<string name="unlocked">Unlocked</string>
<string name="nfc_settings">Settings</string>
+ <string name="snack_yubikey_view">"View"</string>
+ <string name="snack_yubikey_import">"Import"</string>
+ <string name="button_bind_key">"Bind Key"</string>
+ <string name="yubikey_serno">"Serial No: %s"</string>
+ <string name="yubikey_key_holder">"Key holder: "</string>
+ <string name="yubikey_key_holder_unset">"Key holder: &lt;unset&gt;"</string>
+ <string name="yubikey_status_bound">"Yubikey matches and is bound to key"</string>
+ <string name="yubikey_status_unbound">"Yubikey matches, can be bound to key"</string>
+ <string name="yubikey_status_partly">"Yubikey matches, partly bound to key"</string>
+ <string name="btn_import">"Import"</string>
+ <string name="snack_yubi_other">Different key stored on Yubikey!</string>
+ <string name="error_nfc">"NFC Error: %s"</string>
+ <string name="error_pin_nodefault">Default PIN was rejected!</string>
<string name="linked_create_https_1_1">"By creating a Linked Identity of this type, you can link your key to a website you control."</string>
<string name="linked_create_https_1_2">"To do this, you publish a text file on this website, then create a Linked Identity which links to it."</string>