aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/pgpainless/src/main
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-11-02 10:09:49 +0100
committerDanilo M. <danix@danix.xyz>2026-11-02 10:09:49 +0100
commit1c4d04c2089f719e8344f6c4f5cd8488c2320e9f (patch)
treeb4d3f432f7ebf558af01186601745e0402e135e4 /crypto/pgpainless/src/main
parent9b8a56cb859f45845a620d7de344079e6a91d7c9 (diff)
downloadHardenedPass-1c4d04c2089f719e8344f6c4f5cd8488c2320e9f.tar.gz
HardenedPass-1c4d04c2089f719e8344f6c4f5cd8488c2320e9f.zip
build(deps): update Bouncy Castle to 1.86 and PGPainless to 1.7.8
Bouncy Castle 1.78.1 is affected by GHSA-574f-3g2m-x479, GHSA-9pwp-9qqc-pr26, GHSA-c3fc-8qff-9hwx and GHSA-qp49-qgx5-5m26, all fixed by 1.85. PGPainless 1.7.8 is the newest 1.x release. A root resolution rule keeps every Bouncy Castle module on the catalog version; before, bcpg 1.77 shipped next to bcprov 1.78.1. The new stack decrypts the OCB (LibrePGP) packets GnuPG 2.3+ emits by default, which the old one rejected as "non-standard AEAD". Drop the NonStandardAEAD error, its bottom sheet and strings, and replace the mislabelled aead_* fixtures (SHA-1 self-signed keys plus a message encrypted to an unrelated key) with a real GnuPG 2.5 key and OCB message that the tests now decrypt. The new fixture is a throwaway test key, so it is allowlisted in .gitleaksignore by fingerprint. Fix KeyUtils.isKeyUsable, which compared a Boolean to null and so accepted every key that parsed, including keys with no encryption subkey. A signing-only key fixture now covers the rejection path. Also: migrate the removed SelectUserId.firstMatch and deprecated addDecryptionPassphrase APIs, keep one copy of the Bouncy Castle META-INF/LICENSE.md in the APK, and move the existing InvalidPackage lint baseline entries to the bcpkix 1.86 jar. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'crypto/pgpainless/src/main')
-rw-r--r--crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/KeyUtils.kt2
-rw-r--r--crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKeyManager.kt4
-rw-r--r--crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandler.kt11
3 files changed, 5 insertions, 12 deletions
diff --git a/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/KeyUtils.kt b/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/KeyUtils.kt
index 939fed43..f85fe92c 100644
--- a/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/KeyUtils.kt
+++ b/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/KeyUtils.kt
@@ -47,6 +47,6 @@ public object KeyUtils {
val keyRing = tryParseKeyring(key) ?: return false
PGPainless.inspectKeyRing(keyRing).isUsableForEncryption
}
- .get() != null
+ .get() == true
}
}
diff --git a/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKeyManager.kt b/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKeyManager.kt
index ca411fa3..6f852af4 100644
--- a/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKeyManager.kt
+++ b/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKeyManager.kt
@@ -110,7 +110,9 @@ constructor(filesDir: String, private val dispatcher: CoroutineDispatcher) :
val userIdMatch =
keys
.map { key -> key to tryParseKeyring(key) }
- .firstOrNull { (_, keyRing) -> selector.firstMatch(keyRing) != null }
+ .firstOrNull { (_, keyRing) ->
+ keyRing?.publicKey?.userIDs?.asSequence()?.any(selector) == true
+ }
userIdMatch?.first
}
}
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 4a800129..a284ee0d 100644
--- a/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandler.kt
+++ b/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandler.kt
@@ -8,7 +8,6 @@ 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.NonStandardAEAD
import app.passwordstore.crypto.errors.UnknownError
import com.github.michaelbull.result.Result
import com.github.michaelbull.result.mapBoth
@@ -26,7 +25,6 @@ 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.MessageNotIntegrityProtectedException
import org.pgpainless.exception.WrongPassphraseException
import org.pgpainless.key.protection.SecretKeyRingProtector
import org.pgpainless.util.Passphrase
@@ -63,7 +61,7 @@ public class PGPainlessCryptoHandler @Inject constructor() :
.withOptions(
ConsumerOptions()
.addDecryptionKeys(keyringCollection, protector)
- .addDecryptionPassphrase(Passphrase.fromPassword(passphrase))
+ .addMessagePassphrase(Passphrase.fromPassword(passphrase))
)
decryptionStream.use { Streams.pipeAll(it, outputStream) }
return@runCatching
@@ -72,13 +70,6 @@ public class PGPainlessCryptoHandler @Inject constructor() :
when (error) {
is WrongPassphraseException -> IncorrectPassphraseException(error)
is CryptoHandlerException -> error
- is MessageNotIntegrityProtectedException -> {
- if (error.message?.contains("Symmetrically Encrypted Data") == true) {
- NonStandardAEAD(error)
- } else {
- UnknownError(error)
- }
- }
else -> UnknownError(error)
}
}