diff options
author | Harsh Shandilya <me@msfjarvis.dev> | 2023-08-10 03:21:47 +0530 |
---|---|---|
committer | Harsh Shandilya <me@msfjarvis.dev> | 2023-08-10 03:31:08 +0530 |
commit | 959a56d7ffbc20db60721d7a09f399c8bdefe07e (patch) | |
tree | 0d9b14e0bb770fd6da2e04295f2c22c087142439 /crypto-pgpainless | |
parent | efef72b6327c8e683c8844146e23d12104f12dd1 (diff) |
refactor: un-flatten module structure
Diffstat (limited to 'crypto-pgpainless')
23 files changed, 0 insertions, 1450 deletions
diff --git a/crypto-pgpainless/build.gradle.kts b/crypto-pgpainless/build.gradle.kts deleted file mode 100644 index 22363f23..00000000 --- a/crypto-pgpainless/build.gradle.kts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -plugins { id("com.github.android-password-store.kotlin-jvm-library") } - -dependencies { - api(projects.cryptoCommon) - implementation(projects.coroutineUtils) - implementation(libs.androidx.annotation) - implementation(libs.dagger.hilt.core) - implementation(libs.kotlinx.coroutines.core) - implementation(libs.thirdparty.kotlinResult) - implementation(libs.thirdparty.pgpainless) - testImplementation(libs.bundles.testDependencies) - testImplementation(libs.kotlinx.coroutines.test) - testImplementation(libs.testing.testparameterinjector) -} diff --git a/crypto-pgpainless/lint-baseline.xml b/crypto-pgpainless/lint-baseline.xml deleted file mode 100644 index 2ed8a3bb..00000000 --- a/crypto-pgpainless/lint-baseline.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<issues format="6" by="lint 8.2.0-alpha14" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha14)" variant="all" version="8.2.0-alpha14"> - -</issues> diff --git a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/KeyUtils.kt b/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/KeyUtils.kt deleted file mode 100644 index 5b23dc18..00000000 --- a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/KeyUtils.kt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright © 2014-2022 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -package app.passwordstore.crypto - -import app.passwordstore.crypto.PGPIdentifier.KeyId -import app.passwordstore.crypto.PGPIdentifier.UserId -import com.github.michaelbull.result.get -import com.github.michaelbull.result.runCatching -import org.bouncycastle.openpgp.PGPKeyRing -import org.pgpainless.PGPainless -import org.pgpainless.key.parsing.KeyRingReader - -/** Utility methods to deal with [PGPKey]s. */ -public object KeyUtils { - /** - * Attempts to parse a [PGPKeyRing] from a given [key]. The key is first tried as a secret key and - * then as a public one before the method gives up and returns null. - */ - public fun tryParseKeyring(key: PGPKey): PGPKeyRing? { - return runCatching { KeyRingReader.readKeyRing(key.contents.inputStream()) }.get() - } - - /** Parses a [PGPKeyRing] from the given [key] and calculates its long key ID */ - public fun tryGetId(key: PGPKey): KeyId? { - val keyRing = tryParseKeyring(key) ?: return null - return KeyId(keyRing.publicKey.keyID) - } - - /** - * Attempts to parse the given [PGPKey] into a [PGPKeyRing] and obtains the [UserId] of the - * corresponding public key. - */ - public fun tryGetEmail(key: PGPKey): UserId? { - val keyRing = tryParseKeyring(key) ?: return null - return UserId(keyRing.publicKey.userIDs.next()) - } - - /** - * Tests if the given [key] can be used for encryption, which is a bare minimum necessity for the - * app. - */ - public fun isKeyUsable(key: PGPKey): Boolean { - return runCatching { - val keyRing = tryParseKeyring(key) ?: return false - PGPainless.inspectKeyRing(keyRing).isUsableForEncryption - } - .get() != null - } -} diff --git a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPDecryptOptions.kt b/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPDecryptOptions.kt deleted file mode 100644 index 15ce92f0..00000000 --- a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPDecryptOptions.kt +++ /dev/null @@ -1,21 +0,0 @@ -package app.passwordstore.crypto - -/** [CryptoOptions] implementation for PGPainless decrypt operations. */ -public class PGPDecryptOptions -private constructor( - private val values: Map<String, Boolean>, -) : CryptoOptions { - - override fun isOptionEnabled(option: String): Boolean { - return values.getOrDefault(option, false) - } - - /** Implementation of a builder pattern for [PGPDecryptOptions]. */ - public class Builder { - - /** Build the final [PGPDecryptOptions] object. */ - public fun build(): PGPDecryptOptions { - return PGPDecryptOptions(emptyMap()) - } - } -} diff --git a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPEncryptOptions.kt b/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPEncryptOptions.kt deleted file mode 100644 index 90de6b51..00000000 --- a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPEncryptOptions.kt +++ /dev/null @@ -1,35 +0,0 @@ -package app.passwordstore.crypto - -/** [CryptoOptions] implementation for PGPainless encrypt operations. */ -public class PGPEncryptOptions -private constructor( - private val values: Map<String, Boolean>, -) : CryptoOptions { - - internal companion object { - const val ASCII_ARMOR = "ASCII_ARMOR" - } - - override fun isOptionEnabled(option: String): Boolean { - return values.getOrDefault(option, false) - } - - /** Implementation of a builder pattern for [PGPEncryptOptions]. */ - public class Builder { - private val optionsMap = mutableMapOf<String, Boolean>() - - /** - * Toggle whether the encryption operation output will be ASCII armored or in OpenPGP's binary - * format. - */ - public fun withAsciiArmor(enabled: Boolean): Builder { - optionsMap[ASCII_ARMOR] = enabled - return this - } - - /** Build the final [PGPEncryptOptions] object. */ - public fun build(): PGPEncryptOptions { - return PGPEncryptOptions(optionsMap) - } - } -} diff --git a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPIdentifier.kt b/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPIdentifier.kt deleted file mode 100644 index 98a1de2e..00000000 --- a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPIdentifier.kt +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright © 2014-2022 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -package app.passwordstore.crypto - -import java.util.Locale -import java.util.regex.Pattern - -/** Supertype for valid identifiers of PGP keys. */ -public sealed class PGPIdentifier { - - /** A [PGPIdentifier] that represents either a long key ID or a fingerprint. */ - public data class KeyId(val id: Long) : PGPIdentifier() { - override fun toString(): String { - return convertKeyIdToHex(id) - } - - /** Convert a [Long] key ID to a formatted string. */ - private fun convertKeyIdToHex(keyId: Long): String { - return convertKeyIdToHex32bit(keyId shr HEX_32_BIT_COUNT) + convertKeyIdToHex32bit(keyId) - } - - /** - * Converts [keyId] to an unsigned [Long] then uses [java.lang.Long.toHexString] to convert it - * to a lowercase hex ID. - */ - private fun convertKeyIdToHex32bit(keyId: Long): String { - var hexString = java.lang.Long.toHexString(keyId and HEX_32_BITMASK).lowercase(Locale.ENGLISH) - while (hexString.length < HEX_32_STRING_LENGTH) { - hexString = "0$hexString" - } - return hexString - } - } - - /** - * A [PGPIdentifier] that represents the textual name/email combination corresponding to a key. - * Despite the [email] property in this class, the value is not guaranteed to be a valid email. - */ - public data class UserId(val email: String) : PGPIdentifier() { - override fun toString(): String { - return email - } - } - - public companion object { - private const val HEX_RADIX = 16 - private const val HEX_32_BIT_COUNT = 32 - private const val HEX_32_BITMASK = 0xffffffffL - private const val HEX_32_STRING_LENGTH = 8 - private const val TRUNCATED_FINGERPRINT_LENGTH = 16 - - /** - * Attempts to parse an untyped String identifier into a concrete subtype of [PGPIdentifier]. - */ - @Suppress("ReturnCount") - public fun fromString(identifier: String): PGPIdentifier? { - if (identifier.isEmpty()) return null - // Match long key IDs: - // FF22334455667788 or 0xFF22334455667788 - val maybeLongKeyId = - identifier.removePrefix("0x").takeIf { it.matches("[a-fA-F\\d]{16}".toRegex()) } - if (maybeLongKeyId != null) { - val keyId = maybeLongKeyId.toULong(HEX_RADIX) - return KeyId(keyId.toLong()) - } - - // Match fingerprints: - // FF223344556677889900112233445566778899 or 0xFF223344556677889900112233445566778899 - val maybeFingerprint = - identifier.removePrefix("0x").takeIf { it.matches("[a-fA-F\\d]{40}".toRegex()) } - if (maybeFingerprint != null) { - // Truncating to the long key ID is not a security issue since OpenKeychain only - // accepts - // non-ambiguous key IDs. - val keyId = maybeFingerprint.takeLast(TRUNCATED_FINGERPRINT_LENGTH).toULong(HEX_RADIX) - return KeyId(keyId.toLong()) - } - - return splitUserId(identifier)?.let { UserId(it) } - } - - private object UserIdRegex { - val PATTERN: Pattern = Pattern.compile("^(.*?)(?: \\((.*)\\))?(?: <(.*)>)?$") - const val NAME = 1 - const val EMAIL = 3 - } - - private object EmailRegex { - val PATTERN: Pattern = Pattern.compile("^<?\"?([^<>\"]*@[^<>\"]*[.]?[^<>\"]*)\"?>?$") - const val EMAIL = 1 - } - - /** - * Takes a 'Name (Comment) <Email>' user ID in any of its permutations and attempts to extract - * an email from it. - */ - @Suppress("NestedBlockDepth") - private fun splitUserId(userId: String): String? { - if (userId.isNotEmpty()) { - val matcher = UserIdRegex.PATTERN.matcher(userId) - if (matcher.matches()) { - var name = - if (matcher.group(UserIdRegex.NAME)?.isEmpty() == true) null - else matcher.group(UserIdRegex.NAME) - var email = matcher.group(UserIdRegex.EMAIL) - if (email != null && name != null) { - val emailMatcher = EmailRegex.PATTERN.matcher(name) - if (emailMatcher.matches() && email == emailMatcher.group(EmailRegex.EMAIL)) { - email = emailMatcher.group(EmailRegex.EMAIL) - name = null - } - } - if (email == null && name != null) { - val emailMatcher = EmailRegex.PATTERN.matcher(name) - if (emailMatcher.matches()) { - email = emailMatcher.group(EmailRegex.EMAIL) - } - } - return email - } - } - return null - } - } -} diff --git a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKey.kt b/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKey.kt deleted file mode 100644 index a33655d4..00000000 --- a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKey.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -package app.passwordstore.crypto - -/** - * A simple value class wrapping over a [ByteArray] that can represent a PGP key. The implementation - * details of public/ private parts as well as identities are deferred to [PGPKeyManager]. - */ -@JvmInline public value class PGPKey(public val contents: ByteArray) diff --git a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKeyManager.kt b/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKeyManager.kt deleted file mode 100644 index aed1acf2..00000000 --- a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKeyManager.kt +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -@file:Suppress("BlockingMethodInNonBlockingContext") - -package app.passwordstore.crypto - -import androidx.annotation.VisibleForTesting -import app.passwordstore.crypto.KeyUtils.isKeyUsable -import app.passwordstore.crypto.KeyUtils.tryGetId -import app.passwordstore.crypto.KeyUtils.tryParseKeyring -import app.passwordstore.crypto.errors.InvalidKeyException -import app.passwordstore.crypto.errors.KeyAlreadyExistsException -import app.passwordstore.crypto.errors.KeyDeletionFailedException -import app.passwordstore.crypto.errors.KeyDirectoryUnavailableException -import app.passwordstore.crypto.errors.KeyNotFoundException -import app.passwordstore.crypto.errors.NoKeysAvailableException -import app.passwordstore.crypto.errors.UnusableKeyException -import app.passwordstore.util.coroutines.runSuspendCatching -import com.github.michaelbull.result.Result -import com.github.michaelbull.result.unwrap -import java.io.File -import javax.inject.Inject -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.withContext -import org.bouncycastle.openpgp.PGPPublicKeyRing -import org.bouncycastle.openpgp.PGPSecretKeyRing -import org.pgpainless.PGPainless -import org.pgpainless.util.selection.userid.SelectUserId - -public class PGPKeyManager -@Inject -constructor( - filesDir: String, - private val dispatcher: CoroutineDispatcher, -) : KeyManager<PGPKey, PGPIdentifier> { - - private val keyDir = File(filesDir, KEY_DIR_NAME) - - /** @see KeyManager.addKey */ - override suspend fun addKey(key: PGPKey, replace: Boolean): Result<PGPKey, Throwable> = - withContext(dispatcher) { - runSuspendCatching { - if (!keyDirExists()) throw KeyDirectoryUnavailableException - val incomingKeyRing = tryParseKeyring(key) ?: throw InvalidKeyException - if (!isKeyUsable(key)) throw UnusableKeyException - val keyFile = File(keyDir, "${tryGetId(key)}.$KEY_EXTENSION") - if (keyFile.exists()) { - val existingKeyBytes = keyFile.readBytes() - val existingKeyRing = - tryParseKeyring(PGPKey(existingKeyBytes)) ?: throw InvalidKeyException - when { - existingKeyRing is PGPPublicKeyRing && incomingKeyRing is PGPSecretKeyRing -> { - keyFile.writeBytes(key.contents) - return@runSuspendCatching key - } - existingKeyRing is PGPPublicKeyRing && incomingKeyRing is PGPPublicKeyRing -> { - val updatedPublicKey = PGPainless.mergeCertificate(existingKeyRing, incomingKeyRing) - val keyBytes = PGPainless.asciiArmor(updatedPublicKey).encodeToByteArray() - keyFile.writeBytes(keyBytes) - return@runSuspendCatching key - } - } - // Check for replace flag first and if it is false, throw an error - if (!replace) - throw KeyAlreadyExistsException( - tryGetId(key)?.toString() ?: "Failed to retrieve key ID" - ) - if (!keyFile.delete()) throw KeyDeletionFailedException - } - - keyFile.writeBytes(key.contents) - - key - } - } - - /** @see KeyManager.removeKey */ - override suspend fun removeKey(identifier: PGPIdentifier): Result<Unit, Throwable> = - withContext(dispatcher) { - runSuspendCatching { - if (!keyDirExists()) throw KeyDirectoryUnavailableException - val key = getKeyById(identifier).unwrap() - val keyFile = File(keyDir, "${tryGetId(key)}.$KEY_EXTENSION") - if (keyFile.exists()) { - if (!keyFile.delete()) throw KeyDeletionFailedException - } - } - } - - /** @see KeyManager.getKeyById */ - override suspend fun getKeyById(id: PGPIdentifier): Result<PGPKey, Throwable> = - withContext(dispatcher) { - runSuspendCatching { - if (!keyDirExists()) throw KeyDirectoryUnavailableException - val keyFiles = keyDir.listFiles() - if (keyFiles.isNullOrEmpty()) throw NoKeysAvailableException - val keys = keyFiles.map { file -> PGPKey(file.readBytes()) } - - val matchResult = - when (id) { - is PGPIdentifier.KeyId -> { - val keyIdMatch = - keys - .map { key -> key to tryGetId(key) } - .firstOrNull { (_, keyId) -> keyId?.id == id.id } - keyIdMatch?.first - } - is PGPIdentifier.UserId -> { - val selector = SelectUserId.byEmail(id.email) - val userIdMatch = - keys - .map { key -> key to tryParseKeyring(key) } - .firstOrNull { (_, keyRing) -> selector.firstMatch(keyRing) != null } - userIdMatch?.first - } - } - - if (matchResult != null) { - return@runSuspendCatching matchResult - } - - throw KeyNotFoundException("$id") - } - } - - /** @see KeyManager.getAllKeys */ - override suspend fun getAllKeys(): Result<List<PGPKey>, Throwable> = - withContext(dispatcher) { - runSuspendCatching { - if (!keyDirExists()) throw KeyDirectoryUnavailableException - val keyFiles = keyDir.listFiles() - if (keyFiles.isNullOrEmpty()) return@runSuspendCatching emptyList() - keyFiles.map { keyFile -> PGPKey(keyFile.readBytes()) }.toList() - } - } - - /** @see KeyManager.getKeyById */ - override suspend fun getKeyId(key: PGPKey): PGPIdentifier? = tryGetId(key) - - /** Checks if [keyDir] exists and attempts to create it if not. */ - private fun keyDirExists(): Boolean { - return keyDir.exists() || keyDir.mkdirs() - } - - public companion object { - - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - internal const val KEY_DIR_NAME: String = "keys" - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - internal const val KEY_EXTENSION: String = "key" - } -} diff --git a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandler.kt b/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandler.kt deleted file mode 100644 index a7087acf..00000000 --- a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandler.kt +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -package app.passwordstore.crypto - -import app.passwordstore.crypto.errors.CryptoHandlerException -import app.passwordstore.crypto.errors.IncorrectPassphraseException -import app.passwordstore.crypto.errors.NoKeysProvidedException -import app.passwordstore.crypto.errors.UnknownError -import com.github.michaelbull.result.Result -import com.github.michaelbull.result.mapError -import com.github.michaelbull.result.runCatching -import java.io.InputStream -import java.io.OutputStream -import javax.inject.Inject -import org.bouncycastle.openpgp.PGPPublicKeyRing -import org.bouncycastle.openpgp.PGPPublicKeyRingCollection -import org.bouncycastle.openpgp.PGPSecretKeyRing -import org.bouncycastle.openpgp.PGPSecretKeyRingCollection -import org.bouncycastle.util.io.Streams -import org.pgpainless.PGPainless -import org.pgpainless.decryption_verification.ConsumerOptions -import org.pgpainless.encryption_signing.EncryptionOptions -import org.pgpainless.encryption_signing.ProducerOptions -import org.pgpainless.exception.WrongPassphraseException -import org.pgpainless.key.protection.SecretKeyRingProtector -import org.pgpainless.util.Passphrase - -public class PGPainlessCryptoHandler @Inject constructor() : - CryptoHandler<PGPKey, PGPEncryptOptions, PGPDecryptOptions> { - - /** - * Decrypts the given [ciphertextStream] using [PGPainless] and writes the decrypted output to - * [outputStream]. The provided [passphrase] is wrapped in a [SecretKeyRingProtector] and the - * [keys] argument is defensively checked to ensure it has at least one key present. - * - * @see CryptoHandler.decrypt - */ - public override fun decrypt( - keys: List<PGPKey>, - passphrase: String, - ciphertextStream: InputStream, - outputStream: OutputStream, - options: PGPDecryptOptions, - ): Result<Unit, CryptoHandlerException> = - runCatching { - if (keys.isEmpty()) { - throw NoKeysProvidedException - } - val keyringCollection = - keys - .map { key -> PGPainless.readKeyRing().secretKeyRing(key.contents) } - .run(::PGPSecretKeyRingCollection) - val protector = SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword(passphrase)) - val decryptionStream = - PGPainless.decryptAndOrVerify() - .onInputStream(ciphertextStream) - .withOptions( - ConsumerOptions() - .addDecryptionKeys(keyringCollection, protector) - .addDecryptionPassphrase(Passphrase.fromPassword(passphrase)) - ) - Streams.pipeAll(decryptionStream, outputStream) - decryptionStream.close() - keyringCollection.forEach { keyRing -> - check(decryptionStream.metadata.isEncryptedFor(keyRing)) { - "Stream should be encrypted for ${keyRing.secretKey.keyID} but wasn't" - } - } - return@runCatching - } - .mapError { error -> - when (error) { - is WrongPassphraseException -> IncorrectPassphraseException(error) - is CryptoHandlerException -> error - else -> UnknownError(error) - } - } - - /** - * Encrypts the provided [plaintextStream] and writes the encrypted output to [outputStream]. The - * [keys] argument is defensively checked to contain at least one key. - * - * @see CryptoHandler.encrypt - */ - public override fun encrypt( - keys: List<PGPKey>, - plaintextStream: InputStream, - outputStream: OutputStream, - options: PGPEncryptOptions, - ): Result<Unit, CryptoHandlerException> = - runCatching { - if (keys.isEmpty()) { - throw NoKeysProvidedException - } - val publicKeyRings = - keys.mapNotNull(KeyUtils::tryParseKeyring).mapNotNull { keyRing -> - when (keyRing) { - is PGPPublicKeyRing -> keyRing - is PGPSecretKeyRing -> PGPainless.extractCertificate(keyRing) - else -> null - } - } - require(keys.size == publicKeyRings.size) { - "Failed to parse all keys: ${keys.size} keys were provided but only ${publicKeyRings.size} were valid" - } - if (publicKeyRings.isEmpty()) { - throw NoKeysProvidedException - } - val publicKeyRingCollection = PGPPublicKeyRingCollection(publicKeyRings) - val encryptionOptions = EncryptionOptions().addRecipients(publicKeyRingCollection) - val producerOptions = - ProducerOptions.encrypt(encryptionOptions) - .setAsciiArmor(options.isOptionEnabled(PGPEncryptOptions.ASCII_ARMOR)) - val encryptionStream = - PGPainless.encryptAndOrSign().onOutputStream(outputStream).withOptions(producerOptions) - Streams.pipeAll(plaintextStream, encryptionStream) - encryptionStream.close() - val result = encryptionStream.result - publicKeyRingCollection.forEach { keyRing -> - require(result.isEncryptedFor(keyRing)) { - "Stream should be encrypted for ${keyRing.publicKey.keyID} but wasn't" - } - } - } - .mapError { error -> - when (error) { - is CryptoHandlerException -> error - else -> UnknownError(error) - } - } - - /** Runs a naive check on the extension for the given [fileName] to check if it is a PGP file. */ - public override fun canHandle(fileName: String): Boolean { - return fileName.substringAfterLast('.', "") == "gpg" - } -} diff --git a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/CryptoConstants.kt b/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/CryptoConstants.kt deleted file mode 100644 index d827e169..00000000 --- a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/CryptoConstants.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -package app.passwordstore.crypto - -object CryptoConstants { - const val KEY_PASSPHRASE = "hunter2" - const val PLAIN_TEXT = "encryption worthy content" - const val KEY_NAME = "John Doe" - const val KEY_EMAIL = "john.doe@example.com" - const val KEY_ID = 0x08edf7567183ce27 -} diff --git a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/KeyUtilsTest.kt b/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/KeyUtilsTest.kt deleted file mode 100644 index a0f84402..00000000 --- a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/KeyUtilsTest.kt +++ /dev/null @@ -1,35 +0,0 @@ -package app.passwordstore.crypto - -import app.passwordstore.crypto.KeyUtils.isKeyUsable -import app.passwordstore.crypto.KeyUtils.tryGetId -import app.passwordstore.crypto.KeyUtils.tryParseKeyring -import app.passwordstore.crypto.TestUtils.AllKeys -import app.passwordstore.crypto.TestUtils.getArmoredSecretKeyWithMultipleIdentities -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertIs -import kotlin.test.assertNotNull -import org.bouncycastle.openpgp.PGPSecretKeyRing - -class KeyUtilsTest { - @Test - fun parseKeyWithMultipleIdentities() { - val key = PGPKey(getArmoredSecretKeyWithMultipleIdentities()) - val keyring = tryParseKeyring(key) - assertNotNull(keyring) - assertIs<PGPSecretKeyRing>(keyring) - val keyId = tryGetId(key) - assertNotNull(keyId) - assertIs<PGPIdentifier.KeyId>(keyId) - assertEquals("b950ae2813841585", keyId.toString()) - } - - @Test - fun isKeyUsable() { - val params = AllKeys.entries.map { it to (it != AllKeys.AEAD_PUB && it != AllKeys.AEAD_SEC) } - params.forEach { (allKeys, isUsable) -> - val key = PGPKey(allKeys.keyMaterial) - assertEquals(isUsable, isKeyUsable(key), "${allKeys.name} failed expectation:") - } - } -} diff --git a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPIdentifierTest.kt b/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPIdentifierTest.kt deleted file mode 100644 index efc6e0ba..00000000 --- a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPIdentifierTest.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright © 2014-2022 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -package app.passwordstore.crypto - -import kotlin.test.Test -import kotlin.test.assertNotNull -import kotlin.test.assertTrue - -class PGPIdentifierTest { - - @Test - fun parseHexKeyIdWithout0xPrefix() { - val identifier = PGPIdentifier.fromString("79E8208280490C77") - assertNotNull(identifier) - assertTrue { identifier is PGPIdentifier.KeyId } - } - - @Test - fun parseHexKeyId() { - val identifier = PGPIdentifier.fromString("0x79E8208280490C77") - assertNotNull(identifier) - assertTrue { identifier is PGPIdentifier.KeyId } - } - - @Test - fun parseValidEmail() { - val identifier = PGPIdentifier.fromString("john.doe@example.org") - assertNotNull(identifier) - assertTrue { identifier is PGPIdentifier.UserId } - } - - @Test - fun parseEmailWithoutTLD() { - val identifier = PGPIdentifier.fromString("john.doe@example") - assertNotNull(identifier) - assertTrue { identifier is PGPIdentifier.UserId } - } -} diff --git a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPKeyManagerTest.kt b/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPKeyManagerTest.kt deleted file mode 100644 index 85cf8e1b..00000000 --- a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPKeyManagerTest.kt +++ /dev/null @@ -1,236 +0,0 @@ -package app.passwordstore.crypto - -import app.passwordstore.crypto.KeyUtils.tryGetId -import app.passwordstore.crypto.PGPIdentifier.KeyId -import app.passwordstore.crypto.PGPIdentifier.UserId -import app.passwordstore.crypto.errors.KeyAlreadyExistsException -import app.passwordstore.crypto.errors.KeyNotFoundException -import app.passwordstore.crypto.errors.NoKeysAvailableException -import app.passwordstore.crypto.errors.UnusableKeyException -import com.github.michaelbull.result.Err -import com.github.michaelbull.result.Ok -import com.github.michaelbull.result.unwrap -import com.github.michaelbull.result.unwrapError -import java.io.File -import kotlin.test.Test -import kotlin.test.assertContentEquals -import kotlin.test.assertEquals -import kotlin.test.assertIs -import kotlin.test.assertNotEquals -import kotlin.test.assertNotNull -import kotlinx.coroutines.test.StandardTestDispatcher -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runTest -import org.junit.Rule -import org.junit.rules.TemporaryFolder - -class PGPKeyManagerTest { - - @get:Rule val temporaryFolder: TemporaryFolder = TemporaryFolder() - private val dispatcher = StandardTestDispatcher() - private val scope = TestScope(dispatcher) - private val filesDir by unsafeLazy { temporaryFolder.root } - private val keysDir by unsafeLazy { File(filesDir, PGPKeyManager.KEY_DIR_NAME) } - private val keyManager by unsafeLazy { PGPKeyManager(filesDir.absolutePath, dispatcher) } - private val secretKey = PGPKey(TestUtils.getArmoredSecretKey()) - private val publicKey = PGPKey(TestUtils.getArmoredPublicKey()) - - private fun <T> unsafeLazy(initializer: () -> T) = - lazy(LazyThreadSafetyMode.NONE) { initializer.invoke() } - - @Test - fun addKey() = - runTest(dispatcher) { - // Check if the key id returned is correct - val keyId = keyManager.getKeyId(keyManager.addKey(secretKey).unwrap()) - assertEquals(KeyId(CryptoConstants.KEY_ID), keyId) - // Check if the keys directory have one file - assertEquals(1, filesDir.list()?.size) - // Check if the file name is correct - val keyFile = keysDir.listFiles()?.first() - assertEquals(keyFile?.name, "$keyId.${PGPKeyManager.KEY_EXTENSION}") - } - - @Test - fun addKeyWithoutReplaceFlag() = - runTest(dispatcher) { - // Check adding the keys twice - keyManager.addKey(secretKey, false).unwrap() - val error = keyManager.addKey(secretKey, false).unwrapError() - - assertIs<KeyAlreadyExistsException>(error) - } - - @Test - fun addKeyWithReplaceFlag() = - runTest(dispatcher) { - // Check adding the keys twice - keyManager.addKey(secretKey, true).unwrap() - val keyId = keyManager.getKeyId(keyManager.addKey(secretKey, true).unwrap()) - - assertEquals(KeyId(CryptoConstants.KEY_ID), keyId) - } - - @Test - fun addKeyWithUnusableKey() = - runTest(dispatcher) { - val error = keyManager.addKey(PGPKey(TestUtils.getAEADSecretKey())).unwrapError() - assertEquals(UnusableKeyException, error) - } - - @Test - fun removeKey() = - runTest(dispatcher) { - // Add key using KeyManager - keyManager.addKey(secretKey).unwrap() - // Remove key - keyManager.removeKey(tryGetId(secretKey)!!).unwrap() - // Check that no keys remain - val keys = keyManager.getAllKeys().unwrap() - assertEquals(0, keys.size) - } - - @Test - fun getKeyById() = - runTest(dispatcher) { - // Add key using KeyManager - keyManager.addKey(secretKey).unwrap() - val keyId = keyManager.getKeyId(secretKey) - assertNotNull(keyId) - assertEquals(KeyId(CryptoConstants.KEY_ID), keyManager.getKeyId(secretKey)) - // Check returned key id matches the expected id and the created key id - val returnedKey = keyManager.getKeyById(keyId).unwrap() - assertEquals(keyManager.getKeyId(secretKey), keyManager.getKeyId(returnedKey)) - } - - @Test - fun getKeyByFullUserId() = - runTest(dispatcher) { - keyManager.addKey(secretKey).unwrap() - val keyId = "${CryptoConstants.KEY_NAME} <${CryptoConstants.KEY_EMAIL}>" - val returnedKey = keyManager.getKeyById(UserId(keyId)).unwrap() - assertEquals(keyManager.getKeyId(secretKey), keyManager.getKeyId(returnedKey)) - } - - @Test - fun getKeyByEmailUserId() = - runTest(dispatcher) { - keyManager.addKey(secretKey).unwrap() - val keyId = CryptoConstants.KEY_EMAIL - val returnedKey = keyManager.getKeyById(UserId(keyId)).unwrap() - assertEquals(keyManager.getKeyId(secretKey), keyManager.getKeyId(returnedKey)) - } - - @Test - fun getNonExistentKey() = - runTest(dispatcher) { - // Add key using KeyManager - keyManager.addKey(secretKey).unwrap() - val keyId = KeyId(0x08edf7567183ce44) - // Check returned key - val error = keyManager.getKeyById(keyId).unwrapError() - assertIs<KeyNotFoundException>(error) - assertEquals("No key found with id: $keyId", error.message) - } - - @Test - fun findNonExistentKey() = - runTest(dispatcher) { - // Check returned key - val error = keyManager.getKeyById(KeyId(0x08edf7567183ce44)).unwrapError() - assertIs<NoKeysAvailableException>(error) - assertEquals("No keys were found", error.message) - } - - @Test - fun getAllKeys() = - runTest(dispatcher) { - // Check if KeyManager returns no key - val noKeyList = keyManager.getAllKeys().unwrap() - assertEquals(0, noKeyList.size) - // Add key using KeyManager - keyManager.addKey(secretKey).unwrap() - keyManager.addKey(PGPKey(TestUtils.getArmoredSecretKeyWithMultipleIdentities())).unwrap() - // Check if KeyManager returns one key - val singleKeyList = keyManager.getAllKeys().unwrap() - assertEquals(2, singleKeyList.size) - } - - @Test - fun getMultipleIdentityKeyWithAllIdentities() = - runTest(dispatcher) { - val key = PGPKey(TestUtils.getArmoredSecretKeyWithMultipleIdentities()) - keyManager.addKey(key).unwrap() - val johnKey = keyManager.getKeyById(UserId("john@doe.org")).unwrap() - val janeKey = keyManager.getKeyById(UserId("jane@doe.org")).unwrap() - - assertContentEquals(johnKey.contents, janeKey.contents) - } - - @Test - fun replaceSecretKeyWithPublicKey() = - runTest(dispatcher) { - assertIs<Ok<PGPKey>>(keyManager.addKey(secretKey)) - assertIs<Err<KeyAlreadyExistsException>>(keyManager.addKey(publicKey)) - } - - @Test - fun replacePublicKeyWithSecretKey() = - runTest(dispatcher) { - assertIs<Ok<PGPKey>>(keyManager.addKey(publicKey)) - assertIs<Ok<PGPKey>>(keyManager.addKey(secretKey)) - } - - @Test - fun replacePublicKeyWithPublicKey() = - runTest(dispatcher) { - assertIs<Ok<PGPKey>>(keyManager.addKey(publicKey)) - assertIs<Ok<PGPKey>>(keyManager.addKey(publicKey)) - val allKeys = keyManager.getAllKeys() - assertIs<Ok<List<PGPKey>>>(allKeys) - assertEquals(1, allKeys.value.size) - val key = allKeys.value[0] - assertContentEquals(publicKey.contents, key.contents) - } - - @Test - fun replaceSecretKeyWithSecretKey() = - runTest(dispatcher) { - assertIs<Ok<PGPKey>>(keyManager.addKey(secretKey)) - assertIs<Err<KeyAlreadyExistsException>>(keyManager.addKey(secretKey)) - } - - @Test - fun addMultipleKeysWithSameEmail() = - runTest(dispatcher) { - val alice = - PGPKey(this::class.java.classLoader.getResource("alice_owner@example_com")!!.readBytes()) - val bobby = - PGPKey(this::class.java.classLoader.getResource("bobby_owner@example_com")!!.readBytes()) - assertIs<Ok<PGPKey>>(keyManager.addKey(alice)) - assertIs<Ok<PGPKey>>(keyManager.addKey(bobby)) - - keyManager.getAllKeys().apply { - assertIs<Ok<List<PGPKey>>>(this) - assertEquals(2, this.value.size) - } - val longKeyIds = - arrayOf( - KeyId(-7087927403306410599), // Alice - KeyId(-961222705095032109), // Bobby - ) - val userIds = - arrayOf( - UserId("Alice <owner@example.com>"), - UserId("Bobby <owner@example.com>"), - ) - - for (idCollection in arrayOf(longKeyIds, userIds)) { - val alice1 = keyManager.getKeyById(idCollection[0]) - val bobby1 = keyManager.getKeyById(idCollection[1]) - assertIs<Ok<PGPKey>>(alice1) - assertIs<Ok<PGPKey>>(bobby1) - assertNotEquals(alice1.value.contents, bobby1.value.contents) - } - } -} diff --git a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandlerTest.kt b/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandlerTest.kt deleted file mode 100644 index 8bf6ba1e..00000000 --- a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandlerTest.kt +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -@file:Suppress("JUnitMalformedDeclaration") // The test runner takes care of it - -package app.passwordstore.crypto - -import app.passwordstore.crypto.CryptoConstants.KEY_PASSPHRASE -import app.passwordstore.crypto.CryptoConstants.PLAIN_TEXT -import app.passwordstore.crypto.errors.IncorrectPassphraseException -import com.github.michaelbull.result.Err -import com.github.michaelbull.result.Ok -import com.github.michaelbull.result.getError -import com.google.testing.junit.testparameterinjector.TestParameter -import com.google.testing.junit.testparameterinjector.TestParameterInjector -import java.io.ByteArrayOutputStream -import kotlin.test.Test -import kotlin.test.assertContains -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertIs -import kotlin.test.assertTrue -import org.junit.runner.RunWith -import org.pgpainless.PGPainless -import org.pgpainless.decryption_verification.MessageInspector - -@Suppress("Unused") // Test runner handles it internally -enum class EncryptionKey(val keySet: List<PGPKey>) { - PUBLIC(listOf(PGPKey(TestUtils.getArmoredPublicKey()))), - SECRET(listOf(PGPKey(TestUtils.getArmoredSecretKey()))), - ALL(listOf(PGPKey(TestUtils.getArmoredPublicKey()), PGPKey(TestUtils.getArmoredSecretKey()))), -} - -@RunWith(TestParameterInjector::class) -class PGPainlessCryptoHandlerTest { - - private val cryptoHandler = PGPainlessCryptoHandler() - private val secretKey = PGPKey(TestUtils.getArmoredSecretKey()) - - @Test - fun encryptAndDecrypt(@TestParameter encryptionKey: EncryptionKey) { - val ciphertextStream = ByteArrayOutputStream() - val encryptRes = - cryptoHandler.encrypt( - encryptionKey.keySet, - PLAIN_TEXT.byteInputStream(Charsets.UTF_8), - ciphertextStream, - PGPEncryptOptions.Builder().build(), - ) - assertIs<Ok<Unit>>(encryptRes) - val plaintextStream = ByteArrayOutputStream() - val decryptRes = - cryptoHandler.decrypt( - listOf(secretKey), - KEY_PASSPHRASE, - ciphertextStream.toByteArray().inputStream(), - plaintextStream, - PGPDecryptOptions.Builder().build(), - ) - assertIs<Ok<Unit>>(decryptRes) - assertEquals(PLAIN_TEXT, plaintextStream.toString(Charsets.UTF_8)) - } - - @Test - fun decryptWithWrongPassphrase(@TestParameter encryptionKey: EncryptionKey) { - val ciphertextStream = ByteArrayOutputStream() - val encryptRes = - cryptoHandler.encrypt( - encryptionKey.keySet, - PLAIN_TEXT.byteInputStream(Charsets.UTF_8), - ciphertextStream, - PGPEncryptOptions.Builder().build(), - ) - assertIs<Ok<Unit>>(encryptRes) - val plaintextStream = ByteArrayOutputStream() - val result = - cryptoHandler.decrypt( - listOf(secretKey), - "very incorrect passphrase", - ciphertextStream.toByteArray().inputStream(), - plaintextStream, - PGPDecryptOptions.Builder().build(), - ) - assertIs<Err<Throwable>>(result) - assertIs<IncorrectPassphraseException>(result.getError()) - } - - @Test - fun encryptAsciiArmored(@TestParameter encryptionKey: EncryptionKey) { - val ciphertextStream = ByteArrayOutputStream() - val encryptRes = - cryptoHandler.encrypt( - encryptionKey.keySet, - PLAIN_TEXT.byteInputStream(Charsets.UTF_8), - ciphertextStream, - PGPEncryptOptions.Builder().withAsciiArmor(true).build(), - ) - assertIs<Ok<Unit>>(encryptRes) - val ciphertext = ciphertextStream.toString(Charsets.UTF_8) - assertContains(ciphertext, "Version: PGPainless") - assertContains(ciphertext, "-----BEGIN PGP MESSAGE-----") - assertContains(ciphertext, "-----END PGP MESSAGE-----") - } - - @Test - fun encryptMultiple() { - val alice = - PGPainless.generateKeyRing().modernKeyRing("Alice <owner@example.com>", KEY_PASSPHRASE) - val bob = PGPainless.generateKeyRing().modernKeyRing("Bob <owner@example.com>", KEY_PASSPHRASE) - val aliceKey = PGPKey(PGPainless.asciiArmor(alice).encodeToByteArray()) - val bobKey = PGPKey(PGPainless.asciiArmor(bob).encodeToByteArray()) - val ciphertextStream = ByteArrayOutputStream() - val encryptRes = - cryptoHandler.encrypt( - listOf(aliceKey, bobKey), - PLAIN_TEXT.byteInputStream(Charsets.UTF_8), - ciphertextStream, - PGPEncryptOptions.Builder().withAsciiArmor(true).build(), - ) - assertIs<Ok<Unit>>(encryptRes) - val message = ciphertextStream.toByteArray().decodeToString() - val info = MessageInspector.determineEncryptionInfoForMessage(message) - assertTrue(info.isEncrypted) - assertEquals(2, info.keyIds.size) - assertFalse(info.isSignedOnly) - for (key in listOf(aliceKey, bobKey)) { - val ciphertextStreamCopy = message.byteInputStream() - val plaintextStream = ByteArrayOutputStream() - val res = - cryptoHandler.decrypt( - listOf(key), - KEY_PASSPHRASE, - ciphertextStreamCopy, - plaintextStream, - PGPDecryptOptions.Builder().build(), - ) - assertIs<Ok<Unit>>(res) - } - } - - @Test - fun canHandleFiltersFormats() { - assertFalse { cryptoHandler.canHandle("example.com") } - assertTrue { cryptoHandler.canHandle("example.com.gpg") } - assertFalse { cryptoHandler.canHandle("example.com.asc") } - } -} diff --git a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/TestUtils.kt b/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/TestUtils.kt deleted file mode 100644 index 90b98ac9..00000000 --- a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/TestUtils.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -@file:Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") - -package app.passwordstore.crypto - -object TestUtils { - fun getArmoredSecretKey() = this::class.java.classLoader.getResource("secret_key").readBytes() - - fun getArmoredPublicKey() = this::class.java.classLoader.getResource("public_key").readBytes() - - fun getArmoredSecretKeyWithMultipleIdentities() = - this::class.java.classLoader.getResource("secret_key_multiple_identities").readBytes() - - fun getArmoredPublicKeyWithMultipleIdentities() = - this::class.java.classLoader.getResource("public_key_multiple_identities").readBytes() - - fun getAEADPublicKey() = this::class.java.classLoader.getResource("aead_pub").readBytes() - - fun getAEADSecretKey() = this::class.java.classLoader.getResource("aead_sec").readBytes() - - enum class AllKeys(val keyMaterial: ByteArray) { - ARMORED_SEC(getArmoredSecretKey()), - ARMORED_PUB(getArmoredPublicKey()), - MULTIPLE_IDENTITIES_SEC(getArmoredSecretKeyWithMultipleIdentities()), - MULTIPLE_IDENTITIES_PUB(getArmoredPublicKeyWithMultipleIdentities()), - AEAD_SEC(getAEADSecretKey()), - AEAD_PUB(getAEADPublicKey()), - } -} diff --git a/crypto-pgpainless/src/test/resources/aead_pub b/crypto-pgpainless/src/test/resources/aead_pub deleted file mode 100644 index f6ae1e82..00000000 --- a/crypto-pgpainless/src/test/resources/aead_pub +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -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 -=lwhh ------END PGP PUBLIC KEY BLOCK----- diff --git a/crypto-pgpainless/src/test/resources/aead_sec b/crypto-pgpainless/src/test/resources/aead_sec deleted file mode 100644 index 8e13ac0e..00000000 --- a/crypto-pgpainless/src/test/resources/aead_sec +++ /dev/null @@ -1,107 +0,0 @@ ------BEGIN PGP PRIVATE KEY BLOCK----- - -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 -iHcmZE4pREmRPz9CinzsQXCm5yqJkucSfXtqn4c= -=m5E4 ------END PGP PRIVATE KEY BLOCK----- diff --git a/crypto-pgpainless/src/test/resources/alice_owner@example_com b/crypto-pgpainless/src/test/resources/alice_owner@example_com deleted file mode 100644 index d2612b0d..00000000 --- a/crypto-pgpainless/src/test/resources/alice_owner@example_com +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP PRIVATE KEY BLOCK----- - -lIYEY2to0BYJKwYBBAHaRw8BAQdAuI+Z2XyvQv6qBnA06ZAoKArgfMXFN783oYWl -Vh1DqpT+BwMCSqjdffS3e+X/Kfnv30tVSSrb8j2nX2C+P0ODVvS7xWs8MG8TN33d -NJXWUkfct513yADC520EL2KpXPU6GThIxsYmxBXPdyBb3CAiQQDJWLQZQWxpY2Ug -PG93bmVyQGV4YW1wbGUuY29tPoiQBBMWCAA4FiEEMqSK1ESF5td0+gNunaKflIQq -HZkFAmNraNACGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQnaKflIQqHZk6 -sAD/Xx8MQbtXcKPJi/0UGXkyRHEYbcC+zzhECFalHsQsNh0A/3Naih9zRixXt3v0 -JVCv7fbKaXpfKdGi8tj9muSa+5QBnIsEY2to0BIKKwYBBAGXVQEFAQEHQJqcQkrg -shQO4tyyshE9Ng74LAdu4zRD/yb9aQet+61BAwEIB/4HAwIEJ6OJJ8OAFf/0IyRK -Frmj2UHklu1UT1P2JPF5RPzgPlAxZB1eGHFcCQoJX/ro2AsbQ5KZUwraSs1QgX5b -GKAdcyJqFwtbz+pkTpBvOWS6iHgEGBYIACAWIQQypIrURIXm13T6A26dop+UhCod -mQUCY2to0AIbDAAKCRCdop+UhCodmYTSAP0U5Q6clPUsFcjIcwKA+x5G1Q+wzODx -7/pUS2Vg+cKOMAEAuY5wW5k0eCuWMC/uzXy8l2a3BwsMN3nlApuGk0zOcwM= -=ApnA ------END PGP PRIVATE KEY BLOCK----- diff --git a/crypto-pgpainless/src/test/resources/bobby_owner@example_com b/crypto-pgpainless/src/test/resources/bobby_owner@example_com deleted file mode 100644 index 6bd548e7..00000000 --- a/crypto-pgpainless/src/test/resources/bobby_owner@example_com +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP PRIVATE KEY BLOCK----- - -lIYEY2tpShYJKwYBBAHaRw8BAQdA0syygn/sjv82T226XDe7ZmsJ897HQ88pruR6 -uMSdtYP+BwMCAaOsMuRJoq3/eHOl9Df1jlr3zfIBdw0hQrmcJ2qVOS4xQGDegjLW -Bbqnmjw7cCRUN1knjHdMWYwrnm8G9YmhOhhwHwdmhxw/LJOA00SyVLQZQm9iYnkg -PG93bmVyQGV4YW1wbGUuY29tPoiQBBMWCAA4FiEEPnwcCqistth5tnEB8qkNCuDF -QtMFAmNraUoCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ8qkNCuDFQtOx -NAD+MzrKYoQQxgLWkqf08Jhc58sa+2xeZBI3Sq0o+huMql0A/39hfDlJnzD61gEZ -vwOeZuTNb+LH23ha2uG8UpoMx4oLnIsEY2tpShIKKwYBBAGXVQEFAQEHQIVF4gjr -Wpw7KN/IYZQdml9Rn7zlBMsXNIxXhcMVjxlZAwEIB/4HAwJenw1L/ZS8WP+e3uzg -khxkk1dQ3fZbTaR90z0wzLDGngVJO1J2XmfIPnTeU8conEeak8Yyt8+85QdM9MK0 -ch0MyhEa/8hRgtCL8Fo3XkLKiHgEGBYIACAWIQQ+fBwKqKy22Hm2cQHyqQ0K4MVC -0wUCY2tpSgIbDAAKCRDyqQ0K4MVC04+aAQDEW/aasrpOYw35DIddH/Wp4tSrWi65 -kv18HvDPl/c6KwEAw6ZxYsfWmxMtzY6efTIzVnvb4T3OZEVWG6XetZoDTAI= -=OFsg ------END PGP PRIVATE KEY BLOCK----- diff --git a/crypto-pgpainless/src/test/resources/public_key b/crypto-pgpainless/src/test/resources/public_key deleted file mode 100644 index 987bac6f..00000000 --- a/crypto-pgpainless/src/test/resources/public_key +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: PGPainless -Comment: BC98 82EF 93DC 22F8 D7D4 47AD 08ED F756 7183 CE27 -Comment: John Doe <john.doe@example.com> - -mDMEYT33+BYJKwYBBAHaRw8BAQdAoofwCvOfKJ4pGxEO4s64wFD+QnePpNY5zXgW -TTOFb2+0H0pvaG4gRG9lIDxqb2huLmRvZUBleGFtcGxlLmNvbT6IeAQTFgoAIAUC -YT33+AIbAQUWAgMBAAQLCQgHBRUKCQgLAh4BAhkBAAoJEAjt91Zxg84n5dYA/AiA -BqBdt2ItWgDPLCNEqt9wIMgRpkDrAMtXXyyLSkWsAQCoowpenGsq5fxhuRcS3w6Q -s+/Qw1GqnoidxhioR9J+ALg4BGE99/gSCisGAQQBl1UBBQEBB0C7eFVsFUif4q9S -taBI6JAwsI+hQSAo3I6V4jU3rix8XwMBCAeIdQQYFgoAHQUCYT33+AIbDAUWAgMB -AAQLCQgHBRUKCQgLAh4BAAoJEAjt91Zxg84nmn4BALmD8WYxTdrJqUZUE1TcFvzG -5r0//rPM8Vut5X+KwUXjAQDWVP22KaA8VXpevSxkS3n/ti0KjQVKEFzGbmwB2dTT -CbgzBGE99/gWCSsGAQQB2kcPAQEHQJXfqDjCO9L4qBu62/UPpQ5q0638kG8+AGf/ -hJH2q2BTiNUEGBYKAH0FAmE99/gCGwIFFgIDAQAECwkIBwUVCgkICwIeAV8gBBkW -CgAGBQJhPff4AAoJEGSLoii3QC8mrhcBALzpJQTHF8cJJRA9+DQ3qZ85Eu217MJi -x1aYA1i0zyP5AQD/jN/aBsSTqAHF+zU8/ezzHeoilyBYgxLS9Q2qelDeDAAKCRAI -7fdWcYPOJ7aHAP9EBq0rzV3c6GtVl8bPnk+llpV/1aodxTSnijQtVSMuMAD+JMUD -Jd2bimlhuVwpu0DFiF7IF64SAxmVifTwsTWYiQs= -=jGlC ------END PGP PUBLIC KEY BLOCK----- diff --git a/crypto-pgpainless/src/test/resources/public_key_multiple_identities b/crypto-pgpainless/src/test/resources/public_key_multiple_identities deleted file mode 100644 index 2cc896c2..00000000 --- a/crypto-pgpainless/src/test/resources/public_key_multiple_identities +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -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 -GorvBkqXcIR7 -=dL2N ------END PGP PUBLIC KEY BLOCK----- diff --git a/crypto-pgpainless/src/test/resources/secret_key b/crypto-pgpainless/src/test/resources/secret_key deleted file mode 100644 index 61334b01..00000000 --- a/crypto-pgpainless/src/test/resources/secret_key +++ /dev/null @@ -1,26 +0,0 @@ ------BEGIN PGP PRIVATE KEY BLOCK----- -Version: PGPainless -Comment: BC98 82EF 93DC 22F8 D7D4 47AD 08ED F756 7183 CE27 -Comment: John Doe <john.doe@example.com> - -lIYEYT33+BYJKwYBBAHaRw8BAQdAoofwCvOfKJ4pGxEO4s64wFD+QnePpNY5zXgW -TTOFb2/+CQMCh3Bp60ThtX9g8u+uxtuLdeeU5UC14Ox4zVD/x2L7sUzN94XVocOn -WVJTIgeZ1CBhrsSOMg5grj0Zwf1YODlBpZ85V8stPebpjZ2mCZUz1rQfSm9obiBE -b2UgPGpvaG4uZG9lQGV4YW1wbGUuY29tPoh4BBMWCgAgBQJhPff4AhsBBRYCAwEA -BAsJCAcFFQoJCAsCHgECGQEACgkQCO33VnGDzifl1gD8CIAGoF23Yi1aAM8sI0Sq -33AgyBGmQOsAy1dfLItKRawBAKijCl6cayrl/GG5FxLfDpCz79DDUaqeiJ3GGKhH -0n4AnIsEYT33+BIKKwYBBAGXVQEFAQEHQLt4VWwVSJ/ir1K1oEjokDCwj6FBICjc -jpXiNTeuLHxfAwEIB/4JAwKHcGnrROG1f2AcnEUWhC2rDrztJB3JK7pe+PVJbMaK -O2eYKLiBZOT6Dy1rexMi0vS19IMYLf1V2qgsO9phoglOD+m95tr8Ha9FhfbpJjua -iHUEGBYKAB0FAmE99/gCGwwFFgIDAQAECwkIBwUVCgkICwIeAQAKCRAI7fdWcYPO -J5p+AQC5g/FmMU3ayalGVBNU3Bb8xua9P/6zzPFbreV/isFF4wEA1lT9timgPFV6 -Xr0sZEt5/7YtCo0FShBcxm5sAdnU0wmchgRhPff4FgkrBgEEAdpHDwEBB0CV36g4 -wjvS+Kgbutv1D6UOatOt/JBvPgBn/4SR9qtgU/4JAwKHcGnrROG1f2A1hnm2UXZL -Go/tPJo3pJCJDLClIKi7I5RoHruafuQ2ODvznLbCnbuft9B2cA5MZUMFCk6nBvoU -k6hwGWxOSNJIOmrCx+PMiNUEGBYKAH0FAmE99/gCGwIFFgIDAQAECwkIBwUVCgkI -CwIeAV8gBBkWCgAGBQJhPff4AAoJEGSLoii3QC8mrhcBALzpJQTHF8cJJRA9+DQ3 -qZ85Eu217MJix1aYA1i0zyP5AQD/jN/aBsSTqAHF+zU8/ezzHeoilyBYgxLS9Q2q -elDeDAAKCRAI7fdWcYPOJ7aHAP9EBq0rzV3c6GtVl8bPnk+llpV/1aodxTSnijQt -VSMuMAD+JMUDJd2bimlhuVwpu0DFiF7IF64SAxmVifTwsTWYiQs= -=/dDf ------END PGP PRIVATE KEY BLOCK----- diff --git a/crypto-pgpainless/src/test/resources/secret_key_multiple_identities b/crypto-pgpainless/src/test/resources/secret_key_multiple_identities deleted file mode 100644 index 5da8ac81..00000000 --- a/crypto-pgpainless/src/test/resources/secret_key_multiple_identities +++ /dev/null @@ -1,93 +0,0 @@ ------BEGIN PGP PRIVATE KEY BLOCK----- - -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 -hmaBvZKKiR6/QRMyZMQ34dx9GorvBkqXcIR7 -=8IuC ------END PGP PRIVATE KEY BLOCK----- |