From 8129495608c1029cdb09071a80a73971d20f25d7 Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Wed, 24 Aug 2022 22:44:02 +0530 Subject: Implement support for `.gpg-id` (#2080) --- .../crypto/PGPainlessCryptoHandler.kt | 33 +++++++++++----------- .../crypto/PGPainlessCryptoHandlerTest.kt | 4 +-- 2 files changed, 18 insertions(+), 19 deletions(-) (limited to 'crypto-pgpainless') diff --git a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandler.kt b/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandler.kt index 64ad426f..74f880a2 100644 --- a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandler.kt +++ b/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandler.kt @@ -12,12 +12,12 @@ 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.ByteArrayInputStream 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.pgpainless.PGPainless import org.pgpainless.decryption_verification.ConsumerOptions @@ -25,23 +25,25 @@ import org.pgpainless.encryption_signing.EncryptionOptions import org.pgpainless.encryption_signing.ProducerOptions import org.pgpainless.exception.WrongPassphraseException import org.pgpainless.key.protection.PasswordBasedSecretKeyRingProtector -import org.pgpainless.key.util.KeyRingUtils import org.pgpainless.util.Passphrase public class PGPainlessCryptoHandler @Inject constructor() : CryptoHandler { public override fun decrypt( - secretKey: PGPKey, + keys: List, passphrase: String, ciphertextStream: InputStream, outputStream: OutputStream, ): Result = runCatching { - val pgpSecretKeyRing = PGPainless.readKeyRing().secretKeyRing(secretKey.contents) - val keyringCollection = PGPSecretKeyRingCollection(listOf(pgpSecretKeyRing)) + if (keys.isEmpty()) throw NoKeysProvided("No keys provided for encryption") + val keyringCollection = + keys + .map { key -> PGPainless.readKeyRing().secretKeyRing(key.contents) } + .run(::PGPSecretKeyRingCollection) val protector = PasswordBasedSecretKeyRingProtector.forKey( - pgpSecretKeyRing, + keyringCollection.first(), Passphrase.fromPassword(passphrase) ) PGPainless.decryptAndOrVerify() @@ -68,17 +70,14 @@ public class PGPainlessCryptoHandler @Inject constructor() : CryptoHandler = runCatching { if (keys.isEmpty()) throw NoKeysProvided("No keys provided for encryption") - val publicKeyRings = arrayListOf() - val armoredKeys = - keys.joinToString("\n") { key -> key.contents.decodeToString() }.toByteArray() - val secKeysStream = ByteArrayInputStream(armoredKeys) - publicKeyRings.addAll( - KeyRingUtils.publicKeyRingCollectionFrom( - PGPainless.readKeyRing().secretKeyRingCollection(secKeysStream) - ) - ) - val pubKeysStream = ByteArrayInputStream(armoredKeys) - publicKeyRings.addAll(PGPainless.readKeyRing().publicKeyRingCollection(pubKeysStream)) + 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=${keys.size},parsed=${publicKeyRings.size}" } diff --git a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandlerTest.kt b/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandlerTest.kt index 6a20fe25..80c8dc7c 100644 --- a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandlerTest.kt +++ b/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandlerTest.kt @@ -46,7 +46,7 @@ class PGPainlessCryptoHandlerTest { val plaintextStream = ByteArrayOutputStream() val decryptRes = cryptoHandler.decrypt( - secretKey, + listOf(secretKey), CryptoConstants.KEY_PASSPHRASE, ciphertextStream.toByteArray().inputStream(), plaintextStream, @@ -68,7 +68,7 @@ class PGPainlessCryptoHandlerTest { val plaintextStream = ByteArrayOutputStream() val result = cryptoHandler.decrypt( - secretKey, + listOf(secretKey), "very incorrect passphrase", ciphertextStream.toByteArray().inputStream(), plaintextStream, -- cgit v1.2.3