diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d45b16a3..031ba56d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -36,7 +36,7 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'java-kotlin' ] + language: [ 'java' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://git.io/codeql-language-support @@ -46,7 +46,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -57,7 +57,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v3 + uses: github/codeql-action/autobuild@v2 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -71,4 +71,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v2 diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/exception/KeyException.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/exception/KeyException.kt index 584de2ad..56d685c9 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/exception/KeyException.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/exception/KeyException.kt @@ -38,11 +38,6 @@ abstract class KeyException : RuntimeException { ) { constructor(cert: OpenPGPCertificate, expirationDate: Date) : this(of(cert), expirationDate) - - constructor( - componentKey: OpenPGPComponentKey, - expirationDate: Date - ) : this(of(componentKey), expirationDate) } class RevokedKeyException : KeyException { diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/generation/KeyRingBuilder.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/generation/KeyRingBuilder.kt index b7038307..cd703ace 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/generation/KeyRingBuilder.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/generation/KeyRingBuilder.kt @@ -52,7 +52,7 @@ class KeyRingBuilder(private val version: OpenPGPKeyVersion, private val api: PG } override fun addUserId(userId: CharSequence): KeyRingBuilder = apply { - userIds[userId.toString()] = null + userIds[userId.toString().trim()] = null } override fun addUserId(userId: ByteArray): KeyRingBuilder = diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/info/KeyRingInfo.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/info/KeyRingInfo.kt index d324b953..3197dc51 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/info/KeyRingInfo.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/info/KeyRingInfo.kt @@ -35,8 +35,7 @@ class KeyRingInfo( api: PGPainless = PGPainless.getInstance(), referenceDate: Date = Date() ) : this( - if (keys is PGPSecretKeyRing) OpenPGPKey(keys, api.implementation) - else OpenPGPCertificate(keys, api.implementation), + if (keys is PGPSecretKeyRing) OpenPGPKey(keys) else OpenPGPCertificate(keys), api, referenceDate) diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.kt index c98fd4bd..ce03501c 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.kt @@ -532,7 +532,7 @@ class SecretKeyRingEditor( val prevBinding = api.inspect(key).getCurrentSubkeyBindingSignature(keyId) ?: throw NoSuchElementException( - "Previous subkey binding signature for $keyId MUST NOT be null.") + "Previous subkey binding signaure for $keyId MUST NOT be null.") val bindingSig = reissueSubkeyBindingSignature(subkey, expiration, protector, prevBinding) secretKeyRing = injectCertification(secretKeyRing, subkey.pgpPublicKey, bindingSig.signature) @@ -624,10 +624,9 @@ class SecretKeyRingEditor( } private fun sanitizeUserId(userId: CharSequence): CharSequence = - // I'm not sure, what kind of sanitization is needed. - // Newlines are allowed, they just need to be escaped when emitted in an ASCII armor header - // Trailing/Leading whitespace is also fine. - userId.toString() + // TODO: Further research how to sanitize user IDs. + // e.g. what about newlines? + userId.toString().trim() private fun callbackFromRevocationAttributes(attributes: RevocationAttributes?) = object : RevocationSignatureSubpackets.Callback { diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/util/ArmorUtils.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/util/ArmorUtils.kt index 92da93c5..1e37c8f0 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/util/ArmorUtils.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/util/ArmorUtils.kt @@ -247,8 +247,7 @@ class ArmorUtils { .add(OpenPgpFingerprint.of(publicKey).prettyPrint()) // Primary / First User ID (primary ?: first)?.let { - headerMap.getOrPut(HEADER_COMMENT) { mutableSetOf() } - .add(it.replace("\n", "\\n").replace("\r", "\\r")) + headerMap.getOrPut(HEADER_COMMENT) { mutableSetOf() }.add(it) } // X-1 further identities when (userIds.size) { diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/util/Passphrase.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/util/Passphrase.kt index bd25f2b9..4d1e49d2 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/util/Passphrase.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/util/Passphrase.kt @@ -11,9 +11,14 @@ import org.bouncycastle.util.Arrays * * @param chars may be null for empty passwords. */ -class Passphrase(private val chars: CharArray?) { +class Passphrase(chars: CharArray?) { private val lock = Any() private var valid = true + private val chars: CharArray? + + init { + this.chars = trimWhitespace(chars) + } /** * Return a copy of the underlying char array. A return value of null represents an empty @@ -62,13 +67,6 @@ class Passphrase(private val chars: CharArray?) { override fun hashCode(): Int = getChars()?.let { String(it) }.hashCode() - /** - * Return a copy of this [Passphrase], but with whitespace characters trimmed off. - * - * @return copy with trimmed whitespace - */ - fun withTrimmedWhitespace(): Passphrase = Passphrase(trimWhitespace(chars)) - companion object { /** diff --git a/pgpainless-sop/src/test/java/org/pgpainless/sop/GenerateKeyTest.java b/pgpainless-sop/src/test/java/org/pgpainless/sop/GenerateKeyTest.java index 521cdfe0..ca6df790 100644 --- a/pgpainless-sop/src/test/java/org/pgpainless/sop/GenerateKeyTest.java +++ b/pgpainless-sop/src/test/java/org/pgpainless/sop/GenerateKeyTest.java @@ -100,14 +100,4 @@ public class GenerateKeyTest { assertThrows(SOPGPException.UnsupportedProfile.class, () -> sop.generateKey().profile("invalid")); } - - @Test - public void generateKeyWithNewlinesInUserId() throws IOException { - byte[] keyBytes = sop.generateKey() - .userId("Foo\n\nBar") - .generate() - .getBytes(); - - assertTrue(new String(keyBytes).contains("Foo\\n\\nBar")); - } }