From 7dc4329c52cfd8d4fa6bf9eb3a2b501f2ea4e16d Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 20 Mar 2025 18:05:37 +0100 Subject: [PATCH 01/27] PGPainless 1.7.5-SNAPSHOT --- version.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.gradle b/version.gradle index 709d1863..05fff865 100644 --- a/version.gradle +++ b/version.gradle @@ -4,8 +4,8 @@ allprojects { ext { - shortVersion = '1.7.4' - isSnapshot = false + shortVersion = '1.7.5' + isSnapshot = true pgpainlessMinAndroidSdk = 10 javaSourceCompatibility = 1.8 bouncyCastleVersion = '1.80' From eebd02e309116139af06fec41683feb5f880f152 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 20 Mar 2025 18:18:40 +0100 Subject: [PATCH 02/27] Perform coveralls task after jacocoRootReport --- .github/workflows/gradle_push.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle_push.yml b/.github/workflows/gradle_push.yml index e4624726..8c03a399 100644 --- a/.github/workflows/gradle_push.yml +++ b/.github/workflows/gradle_push.yml @@ -28,9 +28,13 @@ jobs: with: java-version: '11' distribution: 'temurin' - - name: Build, Check and Coverage + - name: Build and Check + uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 + with: + arguments: check jacocoRootReport + - name: Coveralls uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} with: - arguments: check jacocoRootReport coveralls \ No newline at end of file + arguments: coveralls From a0254f47fb89d4d0cf827619417adfd84828c138 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 25 Mar 2025 11:03:22 +0100 Subject: [PATCH 03/27] Simplify mavenCentralChecksums task --- build.gradle | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/build.gradle b/build.gradle index b084a89c..f8cfbc9d 100644 --- a/build.gradle +++ b/build.gradle @@ -296,34 +296,13 @@ task mavenCentralChecksums() { description 'Fetch and display checksums for artifacts published to Maven Central' String ver = project.hasProperty('release') ? release : shortVersion doLast { - Process p = "curl -f https://repo1.maven.org/maven2/org/pgpainless/pgpainless-core/${ver}/pgpainless-core-${ver}.jar.sha256".execute() - if (p.waitFor() == 0) { - print p.text.trim() - println " pgpainless-core/build/libs/pgpainless-core-${ver}.jar" - } - - p = "curl -f https://repo1.maven.org/maven2/org/pgpainless/pgpainless-sop/${ver}/pgpainless-sop-${ver}.jar.sha256".execute() - if (p.waitFor() == 0) { - print p.text.trim() - println " pgpainless-sop/build/libs/pgpainless-sop-${ver}.jar" - } - - p = "curl -f https://repo1.maven.org/maven2/org/pgpainless/pgpainless-cli/${ver}/pgpainless-cli-${ver}-all.jar.sha256".execute() - if (p.waitFor() == 0) { - print p.text.trim() - println " pgpainless-cli/build/libs/pgpainless-cli-${ver}-all.jar" - } - - p = "curl -f https://repo1.maven.org/maven2/org/pgpainless/pgpainless-cli/${ver}/pgpainless-cli-${ver}.jar.sha256".execute() - if (p.waitFor() == 0) { - print p.text.trim() - println " pgpainless-cli/build/libs/pgpainless-cli-${ver}.jar" - } - - p = "curl -f https://repo1.maven.org/maven2/org/pgpainless/hsregex/${ver}/hsregex-${ver}.jar.sha256".execute() - if (p.waitFor() == 0) { - print p.text.trim() - println " hsregex/build/libs/hsregex-${ver}.jar" + for (Project p : rootProject.subprojects) { + String url = "https://repo1.maven.org/maven2/org/pgpainless/${p.name}/${ver}/${p.name}-${ver}.jar.sha256" + Process fetch = "curl -f $url".execute() + if (fetch.waitFor() == 0) { + print fetch.text.trim() + println " ${p.name}/build/libs/${p.name}-${ver}.jar" + } } } } From 65113a6d82cc0671f5065eb4b0d96bbb41d1132f Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 25 Mar 2025 11:22:16 +0100 Subject: [PATCH 04/27] Rework gradle, making use of toolchain feature --- build.gradle | 44 ++++++++----------------------------- pgpainless-cli/build.gradle | 19 ---------------- version.gradle | 3 +-- 3 files changed, 10 insertions(+), 56 deletions(-) diff --git a/build.gradle b/build.gradle index f8cfbc9d..d05845b4 100644 --- a/build.gradle +++ b/build.gradle @@ -33,18 +33,6 @@ allprojects { apply plugin: 'kotlin' apply plugin: 'com.diffplug.spotless' - java { - targetCompatibility = JavaVersion.VERSION_1_8 - } - - compileJava { - options.release = 8 - } - - tasks.withType(JavaCompile).configureEach { - options.release = 8 - } - // Only generate jar for submodules // without this we would generate an empty pgpainless.jar for the project root // https://stackoverflow.com/a/25445035 @@ -68,8 +56,6 @@ allprojects { description = "Simple to use OpenPGP API for Java based on Bouncycastle" version = shortVersion - sourceCompatibility = javaSourceCompatibility - repositories { mavenCentral() mavenLocal() @@ -84,6 +70,10 @@ allprojects { fileMode = 0644 } + kotlin { + jvmToolchain(javaSourceCompatibility) + } + // Compatibility of default implementations in kotlin interfaces with Java implementations. tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { kotlinOptions { @@ -124,7 +114,7 @@ allprojects { sourceDirectories.setFrom(project.files(sourceSets.main.allSource.srcDirs)) classDirectories.setFrom(project.files(sourceSets.main.output)) reports { - xml.enabled true + xml.required = true } } @@ -142,15 +132,15 @@ subprojects { apply plugin: 'signing' task sourcesJar(type: Jar, dependsOn: classes) { - classifier = 'sources' + archiveClassifier = 'sources' from sourceSets.main.allSource } task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' + archiveClassifier = 'javadoc' from javadoc.destinationDir } task testsJar(type: Jar, dependsOn: testClasses) { - classifier = 'tests' + archiveClassifier = 'tests' from sourceSets.test.output } @@ -247,7 +237,7 @@ task jacocoRootReport(type: JacocoReport) { classDirectories.setFrom(files(subprojects.sourceSets.main.output)) executionData.setFrom(files(subprojects.jacocoTestReport.executionData)) reports { - xml.enabled true + xml.required = true xml.destination file("${buildDir}/reports/jacoco/test/jacocoTestReport.xml") } // We could remove the following setOnlyIf line, but then @@ -258,10 +248,6 @@ task jacocoRootReport(type: JacocoReport) { } task javadocAll(type: Javadoc) { - def currentJavaVersion = JavaVersion.current() - if (currentJavaVersion.compareTo(JavaVersion.VERSION_1_9) >= 0) { - options.addStringOption("-release", "8"); - } source subprojects.collect {project -> project.sourceSets.main.allJava } destinationDir = new File(buildDir, 'javadoc') @@ -275,18 +261,6 @@ task javadocAll(type: Javadoc) { ] as String[] } -if (JavaVersion.current().isJava8Compatible()) { - tasks.withType(Javadoc) { - // The '-quiet' as second argument is actually a hack, - // since the one paramater addStringOption doesn't seem to - // work, we extra add '-quiet', which is added anyway by - // gradle. See https://github.com/gradle/gradle/issues/2354 - // See JDK-8200363 (https://bugs.openjdk.java.net/browse/JDK-8200363) - // for information about the -Xwerror option. - // options.addStringOption('Xwerror', '-quiet') - } -} - /** * Fetch sha256 checksums of artifacts published to maven central. * diff --git a/pgpainless-cli/build.gradle b/pgpainless-cli/build.gradle index d6550139..b3bc192c 100644 --- a/pgpainless-cli/build.gradle +++ b/pgpainless-cli/build.gradle @@ -4,7 +4,6 @@ plugins { id 'application' - id "com.github.johnrengelman.shadow" version "6.1.0" } dependencies { @@ -31,22 +30,6 @@ mainClassName = 'org.pgpainless.cli.PGPainlessCLI' application { mainClass = mainClassName } -/** -jar { - duplicatesStrategy(DuplicatesStrategy.EXCLUDE) - manifest { - attributes 'Main-Class': "$mainClassName" - } - - from { - configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } - } { - exclude "META-INF/*.SF" - exclude "META-INF/*.DSA" - exclude "META-INF/*.RSA" - } -} - */ run { // https://stackoverflow.com/questions/59445306/pipe-into-gradle-run @@ -56,5 +39,3 @@ run { args Eval.me(appArgs) } } - -// tasks."jar".dependsOn(":pgpainless-core:assemble", ":pgpainless-sop:assemble") diff --git a/version.gradle b/version.gradle index 05fff865..72b388a6 100644 --- a/version.gradle +++ b/version.gradle @@ -6,8 +6,7 @@ allprojects { ext { shortVersion = '1.7.5' isSnapshot = true - pgpainlessMinAndroidSdk = 10 - javaSourceCompatibility = 1.8 + javaSourceCompatibility = 11 bouncyCastleVersion = '1.80' bouncyPgVersion = bouncyCastleVersion junitVersion = '5.8.2' From f054c30460cae0887c4c73b5124f1c7484515aeb Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 25 Mar 2025 11:58:55 +0100 Subject: [PATCH 05/27] Upgrade gradle-wrapper to 8.8 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8049c684..0d184210 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 2b9c5ea2724baac3a03b0866f776b95eac15e849 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 25 Mar 2025 12:01:29 +0100 Subject: [PATCH 06/27] Update CHANGELOG --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9f79e45..a593249b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ SPDX-License-Identifier: CC0-1.0 # PGPainless Changelog +## 1.7.5-SNAPSHOT +- Actually attempt to fix Kotlin desugaring. +- Bump javaSourceCompatibility and javaTargetCompatibility to 11 +- Bump gradle-wrapper to 8.8 + ## 1.7.4 - Fix proper Kotlin desugaring for Java 8 From de5ef4de004eceaaecccab997e37b48618791238 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 25 Mar 2025 12:05:33 +0100 Subject: [PATCH 07/27] PGPainless 1.7.5 --- CHANGELOG.md | 2 +- README.md | 2 +- pgpainless-sop/README.md | 4 ++-- version.gradle | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a593249b..8edff65d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ SPDX-License-Identifier: CC0-1.0 # PGPainless Changelog -## 1.7.5-SNAPSHOT +## 1.7.5 - Actually attempt to fix Kotlin desugaring. - Bump javaSourceCompatibility and javaTargetCompatibility to 11 - Bump gradle-wrapper to 8.8 diff --git a/README.md b/README.md index f2810265..44eb180d 100644 --- a/README.md +++ b/README.md @@ -191,7 +191,7 @@ repositories { } dependencies { - implementation 'org.pgpainless:pgpainless-core:1.7.4' + implementation 'org.pgpainless:pgpainless-core:1.7.5' } ``` diff --git a/pgpainless-sop/README.md b/pgpainless-sop/README.md index 50551fec..e21c821f 100644 --- a/pgpainless-sop/README.md +++ b/pgpainless-sop/README.md @@ -23,7 +23,7 @@ To start using pgpainless-sop in your code, include the following lines in your ... dependencies { ... - implementation "org.pgpainless:pgpainless-sop:1.7.4" + implementation "org.pgpainless:pgpainless-sop:1.7.5" ... } @@ -34,7 +34,7 @@ dependencies { org.pgpainless pgpainless-sop - 1.7.4 + 1.7.5 ... diff --git a/version.gradle b/version.gradle index 72b388a6..54933725 100644 --- a/version.gradle +++ b/version.gradle @@ -5,7 +5,7 @@ allprojects { ext { shortVersion = '1.7.5' - isSnapshot = true + isSnapshot = false javaSourceCompatibility = 11 bouncyCastleVersion = '1.80' bouncyPgVersion = bouncyCastleVersion From a6f8058fb43b97d25e0acb25ebede521f5e8dbe6 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 25 Mar 2025 12:09:43 +0100 Subject: [PATCH 08/27] PGPainless 1.7.6-SNAPSHOT --- version.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.gradle b/version.gradle index 54933725..73c8c686 100644 --- a/version.gradle +++ b/version.gradle @@ -4,8 +4,8 @@ allprojects { ext { - shortVersion = '1.7.5' - isSnapshot = false + shortVersion = '1.7.6' + isSnapshot = true javaSourceCompatibility = 11 bouncyCastleVersion = '1.80' bouncyPgVersion = bouncyCastleVersion From 811f72ffef7a00edcca041e51e50697a66eeddf7 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Wed, 26 Mar 2025 15:00:59 +0100 Subject: [PATCH 09/27] Fix RevocationSignatureBuilder properly calculating 3rd-party delegation revocations --- .../pgpainless/signature/builder/RevocationSignatureBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/RevocationSignatureBuilder.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/RevocationSignatureBuilder.kt index d8c594fe..36589613 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/RevocationSignatureBuilder.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/RevocationSignatureBuilder.kt @@ -52,7 +52,7 @@ class RevocationSignatureBuilder : AbstractSignatureBuilder Date: Wed, 26 Mar 2025 15:04:22 +0100 Subject: [PATCH 10/27] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8edff65d..75b18280 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ SPDX-License-Identifier: CC0-1.0 # PGPainless Changelog +## 1.7.5-SNAPSHOT +- Fix `RevocationSignatureBuilder` properly calculating third-party signatures of type `KeyRevocation` (delegation revocations) + ## 1.7.5 - Actually attempt to fix Kotlin desugaring. - Bump javaSourceCompatibility and javaTargetCompatibility to 11 From 143c9777d644fe3ccaff8d6f93ade2c9aaa5699c Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 3 Apr 2025 14:59:08 +0200 Subject: [PATCH 11/27] Implement graal nativeimage compilation Requires sop-java 10.1.1-SNAPSHOT for now, as that version includes picocli configurations files --- pgpainless-cli/build.gradle | 8 +++++++- version.gradle | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pgpainless-cli/build.gradle b/pgpainless-cli/build.gradle index b3bc192c..6c1d283a 100644 --- a/pgpainless-cli/build.gradle +++ b/pgpainless-cli/build.gradle @@ -4,6 +4,11 @@ plugins { id 'application' + id 'org.graalvm.buildtools.native' version '0.10.6' +} + +graalvmNative { + toolchainDetection = true } dependencies { @@ -16,7 +21,8 @@ dependencies { // implementation "ch.qos.logback:logback-core:1.2.6" // We want logback logging in tests and in the app testImplementation "ch.qos.logback:logback-classic:$logbackVersion" - implementation "ch.qos.logback:logback-classic:$logbackVersion" + // implementation "ch.qos.logback:logback-classic:$logbackVersion" + implementation "org.slf4j:slf4j-nop:$slf4jVersion" implementation(project(":pgpainless-sop")) implementation "org.pgpainless:sop-java-picocli:$sopJavaVersion" diff --git a/version.gradle b/version.gradle index 73c8c686..a4ace4c2 100644 --- a/version.gradle +++ b/version.gradle @@ -13,6 +13,6 @@ allprojects { logbackVersion = '1.5.13' mockitoVersion = '4.5.1' slf4jVersion = '1.7.36' - sopJavaVersion = '10.1.0' + sopJavaVersion = '10.1.1-SNAPSHOT' } } From 2d0608cf0f6f2da15ad6e2fcc5babaa962dbd882 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sun, 13 Apr 2025 19:45:12 +0200 Subject: [PATCH 12/27] Re-add shadow plugin --- pgpainless-cli/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/pgpainless-cli/build.gradle b/pgpainless-cli/build.gradle index 6c1d283a..e86ddedf 100644 --- a/pgpainless-cli/build.gradle +++ b/pgpainless-cli/build.gradle @@ -5,6 +5,7 @@ plugins { id 'application' id 'org.graalvm.buildtools.native' version '0.10.6' + id 'com.github.johnrengelman.shadow' version '8.1.1' } graalvmNative { From d20a3b75569d529d05ff11716a165268dcc812f8 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Mon, 14 Apr 2025 15:30:58 +0200 Subject: [PATCH 13/27] Add config files for nativeimage Those were generated by running the following commands in order: gradle -Pagent test gradle metadataCopy --task test --dir src/main/resources/META-INF/native-image gradle nativeCompile The resulting nativeimage can resolve method calls that use reflection. Yay --- .../META-INF/native-image/jni-config.json | 2 + .../predefined-classes-config.json | 7 + .../META-INF/native-image/proxy-config.json | 2 + .../META-INF/native-image/reflect-config.json | 991 ++++++++++++++++++ .../native-image/resource-config.json | 95 ++ .../native-image/serialization-config.json | 41 + 6 files changed, 1138 insertions(+) create mode 100644 pgpainless-cli/src/main/resources/META-INF/native-image/jni-config.json create mode 100644 pgpainless-cli/src/main/resources/META-INF/native-image/predefined-classes-config.json create mode 100644 pgpainless-cli/src/main/resources/META-INF/native-image/proxy-config.json create mode 100644 pgpainless-cli/src/main/resources/META-INF/native-image/reflect-config.json create mode 100644 pgpainless-cli/src/main/resources/META-INF/native-image/resource-config.json create mode 100644 pgpainless-cli/src/main/resources/META-INF/native-image/serialization-config.json diff --git a/pgpainless-cli/src/main/resources/META-INF/native-image/jni-config.json b/pgpainless-cli/src/main/resources/META-INF/native-image/jni-config.json new file mode 100644 index 00000000..32960f8c --- /dev/null +++ b/pgpainless-cli/src/main/resources/META-INF/native-image/jni-config.json @@ -0,0 +1,2 @@ +[ +] \ No newline at end of file diff --git a/pgpainless-cli/src/main/resources/META-INF/native-image/predefined-classes-config.json b/pgpainless-cli/src/main/resources/META-INF/native-image/predefined-classes-config.json new file mode 100644 index 00000000..84789507 --- /dev/null +++ b/pgpainless-cli/src/main/resources/META-INF/native-image/predefined-classes-config.json @@ -0,0 +1,7 @@ +[ + { + "type":"agent-extracted", + "classes":[ + ] + } +] diff --git a/pgpainless-cli/src/main/resources/META-INF/native-image/proxy-config.json b/pgpainless-cli/src/main/resources/META-INF/native-image/proxy-config.json new file mode 100644 index 00000000..32960f8c --- /dev/null +++ b/pgpainless-cli/src/main/resources/META-INF/native-image/proxy-config.json @@ -0,0 +1,2 @@ +[ +] \ No newline at end of file diff --git a/pgpainless-cli/src/main/resources/META-INF/native-image/reflect-config.json b/pgpainless-cli/src/main/resources/META-INF/native-image/reflect-config.json new file mode 100644 index 00000000..25ad3faf --- /dev/null +++ b/pgpainless-cli/src/main/resources/META-INF/native-image/reflect-config.json @@ -0,0 +1,991 @@ +[ +{ + "name":"[B" +}, +{ + "name":"[Ljava.lang.Object;" +}, +{ + "name":"[Ljava.lang.String;" +}, +{ + "name":"[Lsun.security.pkcs.SignerInfo;" +}, +{ + "name":"ch.qos.logback.classic.encoder.PatternLayoutEncoder", + "queryAllPublicMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.joran.SerializedModelConfigurator", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.util.DefaultJoranConfigurator", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.core.ConsoleAppender", + "queryAllPublicMethods":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setTarget","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"ch.qos.logback.core.OutputStreamAppender", + "methods":[{"name":"setEncoder","parameterTypes":["ch.qos.logback.core.encoder.Encoder"] }] +}, +{ + "name":"ch.qos.logback.core.encoder.Encoder", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"ch.qos.logback.core.encoder.LayoutWrappingEncoder", + "methods":[{"name":"setParent","parameterTypes":["ch.qos.logback.core.spi.ContextAware"] }] +}, +{ + "name":"ch.qos.logback.core.pattern.PatternLayoutEncoderBase", + "methods":[{"name":"setPattern","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"ch.qos.logback.core.spi.ContextAware", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"groovy.lang.Closure" +}, +{ + "name":"java.io.FilePermission" +}, +{ + "name":"java.lang.Enum" +}, +{ + "name":"java.lang.Object", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.RuntimePermission" +}, +{ + "name":"java.lang.String" +}, +{ + "name":"java.lang.System", + "methods":[{"name":"console","parameterTypes":[] }] +}, +{ + "name":"java.lang.invoke.MethodHandle" +}, +{ + "name":"java.net.NetPermission" +}, +{ + "name":"java.net.SocketPermission" +}, +{ + "name":"java.net.URLPermission", + "methods":[{"name":"","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"java.nio.channels.SelectionKey", + "fields":[{"name":"attachment"}] +}, +{ + "name":"java.nio.file.Path" +}, +{ + "name":"java.nio.file.Paths", + "methods":[{"name":"get","parameterTypes":["java.lang.String","java.lang.String[]"] }] +}, +{ + "name":"java.security.AlgorithmParametersSpi" +}, +{ + "name":"java.security.AllPermission" +}, +{ + "name":"java.security.MessageDigestSpi" +}, +{ + "name":"java.security.SecureRandomParameters" +}, +{ + "name":"java.security.SecurityPermission" +}, +{ + "name":"java.security.cert.PKIXRevocationChecker" +}, +{ + "name":"java.security.interfaces.DSAPrivateKey" +}, +{ + "name":"java.security.interfaces.DSAPublicKey" +}, +{ + "name":"java.security.interfaces.RSAPrivateKey" +}, +{ + "name":"java.security.interfaces.RSAPublicKey" +}, +{ + "name":"java.security.spec.DSAParameterSpec" +}, +{ + "name":"java.sql.Connection" +}, +{ + "name":"java.sql.Driver" +}, +{ + "name":"java.sql.DriverManager", + "methods":[{"name":"getConnection","parameterTypes":["java.lang.String"] }, {"name":"getDriver","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.sql.Time", + "methods":[{"name":"","parameterTypes":["long"] }] +}, +{ + "name":"java.sql.Timestamp", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.time.Duration", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.Instant", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.LocalDate", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.LocalDateTime", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.LocalTime", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.MonthDay", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.OffsetDateTime", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.OffsetTime", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.Period", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.Year", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.YearMonth", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.time.ZoneId", + "methods":[{"name":"of","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.time.ZoneOffset", + "methods":[{"name":"of","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.time.ZonedDateTime", + "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] +}, +{ + "name":"java.util.Date" +}, +{ + "name":"java.util.HashSet" +}, +{ + "name":"java.util.LinkedHashSet" +}, +{ + "name":"java.util.PropertyPermission" +}, +{ + "name":"java.util.concurrent.ArrayBlockingQueue" +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.locks.AbstractOwnableSynchronizer" +}, +{ + "name":"java.util.concurrent.locks.AbstractQueuedSynchronizer" +}, +{ + "name":"java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject" +}, +{ + "name":"java.util.concurrent.locks.ReentrantLock" +}, +{ + "name":"java.util.concurrent.locks.ReentrantLock$NonfairSync" +}, +{ + "name":"java.util.concurrent.locks.ReentrantLock$Sync" +}, +{ + "name":"javax.security.auth.x500.X500Principal", + "fields":[{"name":"thisX500Name"}], + "methods":[{"name":"","parameterTypes":["sun.security.x509.X500Name"] }] +}, +{ + "name":"javax.smartcardio.CardPermission" +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.COMPOSITE$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.CONTEXT$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.CompositeSignatures$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.DH$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.DSA$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.DSTU4145$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.Dilithium$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.EC$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.ECGOST$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.EXTERNAL$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.EdEC$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.ElGamal$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.Falcon$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.GM$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.GOST$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.IES$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.LMS$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.MLDSA$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.MLKEM$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.NTRU$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.RSA$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.SLHDSA$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.SPHINCSPlus$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.X509$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.edec.KeyPairGeneratorSpi$EdDSA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.edec.KeyPairGeneratorSpi$XDH", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyPairGeneratorSpi", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.Blake2b$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.Blake2s$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.Blake3$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.DSTU7564$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.GOST3411$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.Haraka$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.Keccak$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.MD2$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.MD4$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.MD5$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.RIPEMD128$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.RIPEMD160$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.RIPEMD256$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.RIPEMD320$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.SHA1$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.SHA224$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.SHA256$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.SHA3$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.SHA384$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.SHA512$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.SM3$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.Skein$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.Tiger$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.digest.Whirlpool$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.drbg.DRBG$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.keystore.BC$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.keystore.BCFKS$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.keystore.PKCS12$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.AES$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.ARC4$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.ARIA$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Blowfish$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.CAST5$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.CAST6$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Camellia$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.ChaCha$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.DES$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.DESede$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.DSTU7624$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.GOST28147$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.GOST3412_2015$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Grain128$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Grainv1$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.HC128$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.HC256$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.IDEA$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Noekeon$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.OpenSSLPBKDF$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF1$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF2$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.PBEPKCS12$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Poly1305$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.RC2$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.RC5$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.RC6$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Rijndael$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.SCRYPT$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.SEED$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.SM4$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Salsa20$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Serpent$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Shacal2$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.SipHash$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.SipHash128$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Skipjack$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.TEA$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.TLSKDF$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Threefish$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Twofish$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.VMPC$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.VMPCKSA3$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.XSalsa20$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.XTEA$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.symmetric.Zuc$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.ExitCodeTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"successfulExecutionDoesNotTerminateJVM","parameterTypes":[] }, {"name":"testCommandWithUnknownOption_37","parameterTypes":[] }, {"name":"testUnknownCommand_69","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.TestUtils", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"org.pgpainless.cli.commands.ArmorCmdTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"armorAlreadyArmoredDataIsIdempotent","parameterTypes":[] }, {"name":"armorMessage","parameterTypes":[] }, {"name":"armorPublicKey","parameterTypes":[] }, {"name":"armorSecretKey","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.commands.CLITest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"cleanup","parameterTypes":[] }, {"name":"setup","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.commands.DearmorCmdTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"dearmorBrokenArmoredKeyFails","parameterTypes":[] }, {"name":"dearmorCertificate","parameterTypes":[] }, {"name":"dearmorGarbageEmitsEmpty","parameterTypes":[] }, {"name":"dearmorMessage","parameterTypes":[] }, {"name":"dearmorSecretKey","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.commands.ExtractCertCmdTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"extractCertFromGarbageFails","parameterTypes":[] }, {"name":"testExtractCert","parameterTypes":[] }, {"name":"testExtractCertFromCertFails","parameterTypes":[] }, {"name":"testExtractCertUnarmored","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.commands.GenerateKeyCmdTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"testGenerateBinaryKey","parameterTypes":[] }, {"name":"testGenerateKey","parameterTypes":[] }, {"name":"testGenerateKeyWithMultipleUserIds","parameterTypes":[] }, {"name":"testGeneratePasswordProtectedKey_missingPasswordFile","parameterTypes":[] }, {"name":"testPasswordProtectedKey","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.commands.InlineDetachCmdTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"detachInbandSignatureAndMessage","parameterTypes":[] }, {"name":"detachInbandSignatureAndMessageNoArmor","parameterTypes":[] }, {"name":"detachMissingSignaturesFromCleartextSignedMessageFails","parameterTypes":[] }, {"name":"detachNonOpenPgpDataFails","parameterTypes":[] }, {"name":"existingSignatureOutCausesException","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.commands.ListProfilesCmdTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"listProfileOfGenerateKey","parameterTypes":[] }, {"name":"listProfilesOfEncrypt","parameterTypes":[] }, {"name":"listProfilesWithoutCommand","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.commands.RoundTripEncryptDecryptCmdTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"decryptGarbageFails","parameterTypes":[] }, {"name":"decryptMalformedMessageYieldsBadData","parameterTypes":[] }, {"name":"decryptMessageWithSessionKey","parameterTypes":[] }, {"name":"decryptMessageWithWrongKeyFails","parameterTypes":[] }, {"name":"decryptWithPasswordWithPendingWhitespaceWorks","parameterTypes":[] }, {"name":"decryptWithWhitespacePasswordWorks","parameterTypes":[] }, {"name":"decrypt_verifyWithGarbageCertFails","parameterTypes":[] }, {"name":"decrypt_withGarbageKeyFails","parameterTypes":[] }, {"name":"encryptAndDecryptAMessage","parameterTypes":[] }, {"name":"encryptAndDecryptMessageWithPassphrase","parameterTypes":[] }, {"name":"encryptWithGarbageCertFails","parameterTypes":[] }, {"name":"encryptWithPasswordADecryptWithPasswordBFails","parameterTypes":[] }, {"name":"encryptWithProtectedKey_wrongPassphraseFails","parameterTypes":[] }, {"name":"encryptWithTrailingWhitespaceDecryptWithoutWorks","parameterTypes":[] }, {"name":"encrypt_signWithGarbageKeyFails","parameterTypes":[] }, {"name":"testDecryptVerifyOut_withoutVerifyWithFails","parameterTypes":[] }, {"name":"testDecryptWithSessionKeyVerifyWithYieldsExpectedVerifications","parameterTypes":[] }, {"name":"testDecryptWithoutDecryptionOptionFails","parameterTypes":[] }, {"name":"testEncryptDecryptRoundTripWithPasswordProtectedKey","parameterTypes":[] }, {"name":"testEncryptDecryptWithFreshRSAKey","parameterTypes":[] }, {"name":"testEncryptWithIncapableCert","parameterTypes":[] }, {"name":"testEncrypt_SignWithCertFails","parameterTypes":[] }, {"name":"testMissingArgumentsIfNoArgsSupplied","parameterTypes":[] }, {"name":"testSessionKeyOutWritesSessionKeyOut","parameterTypes":[] }, {"name":"testSignWithIncapableKey","parameterTypes":[] }, {"name":"testVerificationsOutAlreadyExistFails","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.commands.RoundTripInlineSignInlineVerifyCmdTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"cannotVerifyEncryptedMessage","parameterTypes":[] }, {"name":"cannotVerifyMalformedMessage","parameterTypes":[] }, {"name":"createAndVerifyCleartextSignedMessage","parameterTypes":[] }, {"name":"createAndVerifyMultiKeyBinarySignedMessage","parameterTypes":[] }, {"name":"createAndVerifyTextSignedMessage","parameterTypes":[] }, {"name":"createCleartextSignedMessage","parameterTypes":[] }, {"name":"createMalformedMessage","parameterTypes":[] }, {"name":"createSignedMessageWithKeyAAndVerifyWithKeyBFails","parameterTypes":[] }, {"name":"createTextSignedMessageInlineDetachAndDetachedVerify","parameterTypes":[] }, {"name":"signWithProtectedKeyWithWrongPassphraseFails","parameterTypes":[] }, {"name":"testInlineSignWithMissingSecretKeysFails","parameterTypes":[] }, {"name":"testUnlockKeyWithOneOfMultiplePasswords","parameterTypes":[] }, {"name":"verifyPrependedSignedMessage","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.commands.RoundTripInlineSignVerifyCmdTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"encryptAndDecryptAMessage","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.commands.RoundTripSignVerifyCmdTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"createArmoredSignature","parameterTypes":[] }, {"name":"createUnarmoredSignature","parameterTypes":[] }, {"name":"signWithProtectedKey","parameterTypes":[] }, {"name":"signWithProtectedKey_missingPassphraseFails","parameterTypes":[] }, {"name":"signWithProtectedKey_wrongPassphraseFails","parameterTypes":[] }, {"name":"testNotAfter","parameterTypes":[] }, {"name":"testNotBefore","parameterTypes":[] }, {"name":"testSignWithIncapableKey","parameterTypes":[] }, {"name":"testSignatureCreationAndVerification","parameterTypes":[] }, {"name":"unarmorArmoredSigAndVerify","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.commands.VersionCmdTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"testExtendedVersion","parameterTypes":[] }, {"name":"testGetBackendVersion","parameterTypes":[] }, {"name":"testSopSpecVersion","parameterTypes":[] }, {"name":"testVersion","parameterTypes":[] }] +}, +{ + "name":"org.pgpainless.cli.misc.SignUsingPublicKeyBehaviorTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"testSignatureCreationAndVerification","parameterTypes":[] }] +}, +{ + "name":"picocli.AutoComplete$GenerateCompletion", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"picocli.CommandLine$AutoHelpMixin", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"picocli.CommandLine$HelpCommand", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"sop.cli.picocli.SopCLI", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.SopCLI$InitLocale", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"sop.cli.picocli.commands.AbstractSopCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"sop.cli.picocli.commands.ArmorCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.commands.ChangeKeyPasswordCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"sop.cli.picocli.commands.DearmorCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.commands.DecryptCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.commands.EncryptCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.commands.ExtractCertCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.commands.GenerateKeyCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.commands.InlineDetachCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.commands.InlineSignCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.commands.InlineVerifyCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.commands.ListProfilesCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.commands.RevokeKeyCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"sop.cli.picocli.commands.SignCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.commands.VerifyCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.commands.VersionCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sop.cli.picocli.commands.VersionCmd$Exclusive", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.DSA$SHA256withDSA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.DSAKeyFactory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.DSAParameters", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.NativePRNG", + "methods":[{"name":"","parameterTypes":[] }, {"name":"","parameterTypes":["java.security.SecureRandomParameters"] }] +}, +{ + "name":"sun.security.provider.SHA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.SHA2$SHA256", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.X509Factory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSAKeyFactory$Legacy", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSASignature$SHA256withRSA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.util.ObjectIdentifier" +}, +{ + "name":"sun.security.x509.AuthorityInfoAccessExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.AuthorityKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.BasicConstraintsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CRLDistributionPointsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CertificateExtensions" +}, +{ + "name":"sun.security.x509.CertificatePoliciesExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.ExtendedKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.KeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +} +] \ No newline at end of file diff --git a/pgpainless-cli/src/main/resources/META-INF/native-image/resource-config.json b/pgpainless-cli/src/main/resources/META-INF/native-image/resource-config.json new file mode 100644 index 00000000..af650dc9 --- /dev/null +++ b/pgpainless-cli/src/main/resources/META-INF/native-image/resource-config.json @@ -0,0 +1,95 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/ch.qos.logback.classic.spi.Configurator\\E" + }, { + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.nio.channels.spi.SelectorProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.util.spi.ResourceBundleControlProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/javax.xml.parsers.SAXParserFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.engine.TestEngine\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherDiscoveryListener\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherSessionListener\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.PostDiscoveryFilter\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.TestExecutionListener\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qjunit-platform.properties\\E" + }, { + "pattern":"\\Qlogback-test.scmo\\E" + }, { + "pattern":"\\Qlogback-test.xml\\E" + }, { + "pattern":"\\Qlogback.scmo\\E" + }, { + "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" + }, { + "pattern":"\\Qpgpainless-sop.properties\\E" + }, { + "pattern":"\\Qsop-java-version.properties\\E" + }, { + "pattern":"java.base:\\Qsun/text/resources/LineBreakIteratorData\\E" + }, { + "pattern":"java.base:\\Qsun/text/resources/nfkc.icu\\E" + }]}, + "bundles":[{ + "name":"msg_armor", + "locales":["de", "und"] + }, { + "name":"msg_change-key-password", + "locales":["de", "und"] + }, { + "name":"msg_dearmor", + "locales":["de", "und"] + }, { + "name":"msg_decrypt", + "locales":["de", "und"] + }, { + "name":"msg_detached-sign", + "locales":["de", "und"] + }, { + "name":"msg_detached-verify", + "locales":["de", "und"] + }, { + "name":"msg_encrypt", + "locales":["de", "und"] + }, { + "name":"msg_extract-cert", + "locales":["de", "und"] + }, { + "name":"msg_generate-key", + "locales":["de", "und"] + }, { + "name":"msg_inline-detach", + "locales":["de", "und"] + }, { + "name":"msg_inline-sign", + "locales":["de", "und"] + }, { + "name":"msg_inline-verify", + "locales":["de", "und"] + }, { + "name":"msg_list-profiles", + "locales":["de", "und"] + }, { + "name":"msg_revoke-key", + "locales":["de", "und"] + }, { + "name":"msg_sop", + "locales":["de", "und"] + }, { + "name":"msg_version", + "locales":["de", "und"] + }] +} \ No newline at end of file diff --git a/pgpainless-cli/src/main/resources/META-INF/native-image/serialization-config.json b/pgpainless-cli/src/main/resources/META-INF/native-image/serialization-config.json new file mode 100644 index 00000000..3f06d9a8 --- /dev/null +++ b/pgpainless-cli/src/main/resources/META-INF/native-image/serialization-config.json @@ -0,0 +1,41 @@ +{ + "types":[ + { + "name":"java.lang.Enum" + }, + { + "name":"java.lang.Object[]" + }, + { + "name":"java.util.HashSet" + }, + { + "name":"java.util.LinkedHashSet" + }, + { + "name":"java.util.concurrent.ArrayBlockingQueue" + }, + { + "name":"java.util.concurrent.locks.AbstractOwnableSynchronizer" + }, + { + "name":"java.util.concurrent.locks.AbstractQueuedSynchronizer" + }, + { + "name":"java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject" + }, + { + "name":"java.util.concurrent.locks.ReentrantLock" + }, + { + "name":"java.util.concurrent.locks.ReentrantLock$NonfairSync" + }, + { + "name":"java.util.concurrent.locks.ReentrantLock$Sync" + } + ], + "lambdaCapturingTypes":[ + ], + "proxies":[ + ] +} \ No newline at end of file From 05c84835e69d5de69c64d1f007b5b5838da77b8a Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Mon, 14 Apr 2025 15:31:27 +0200 Subject: [PATCH 14/27] Bump SOP-Java to 10.1.1 --- version.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.gradle b/version.gradle index a4ace4c2..f3c4f100 100644 --- a/version.gradle +++ b/version.gradle @@ -13,6 +13,6 @@ allprojects { logbackVersion = '1.5.13' mockitoVersion = '4.5.1' slf4jVersion = '1.7.36' - sopJavaVersion = '10.1.1-SNAPSHOT' + sopJavaVersion = '10.1.1' } } From 83613250efecc50daf6171c8f46a944597b496a9 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Mon, 14 Apr 2025 15:55:29 +0200 Subject: [PATCH 15/27] PGPainless 1.7.6 --- CHANGELOG.md | 4 +++- README.md | 2 +- pgpainless-sop/README.md | 4 ++-- version.gradle | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75b18280..b1f63d6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,10 @@ SPDX-License-Identifier: CC0-1.0 # PGPainless Changelog -## 1.7.5-SNAPSHOT +## 1.7.6 - Fix `RevocationSignatureBuilder` properly calculating third-party signatures of type `KeyRevocation` (delegation revocations) +- Enable support for native images +- Re-enable shadow plugin and build fat-jar ## 1.7.5 - Actually attempt to fix Kotlin desugaring. diff --git a/README.md b/README.md index 44eb180d..e305e43a 100644 --- a/README.md +++ b/README.md @@ -191,7 +191,7 @@ repositories { } dependencies { - implementation 'org.pgpainless:pgpainless-core:1.7.5' + implementation 'org.pgpainless:pgpainless-core:1.7.6' } ``` diff --git a/pgpainless-sop/README.md b/pgpainless-sop/README.md index e21c821f..da112604 100644 --- a/pgpainless-sop/README.md +++ b/pgpainless-sop/README.md @@ -23,7 +23,7 @@ To start using pgpainless-sop in your code, include the following lines in your ... dependencies { ... - implementation "org.pgpainless:pgpainless-sop:1.7.5" + implementation "org.pgpainless:pgpainless-sop:1.7.6" ... } @@ -34,7 +34,7 @@ dependencies { org.pgpainless pgpainless-sop - 1.7.5 + 1.7.6 ... diff --git a/version.gradle b/version.gradle index f3c4f100..7ed1f065 100644 --- a/version.gradle +++ b/version.gradle @@ -5,7 +5,7 @@ allprojects { ext { shortVersion = '1.7.6' - isSnapshot = true + isSnapshot = false javaSourceCompatibility = 11 bouncyCastleVersion = '1.80' bouncyPgVersion = bouncyCastleVersion From 3b92ccc59d8c6f8c9ef4ccc5f5e8317659fee729 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Mon, 14 Apr 2025 16:05:05 +0200 Subject: [PATCH 16/27] PGPainless 1.7.7-SNAPSHOT --- version.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.gradle b/version.gradle index 7ed1f065..003de912 100644 --- a/version.gradle +++ b/version.gradle @@ -4,8 +4,8 @@ allprojects { ext { - shortVersion = '1.7.6' - isSnapshot = false + shortVersion = '1.7.7' + isSnapshot = true javaSourceCompatibility = 11 bouncyCastleVersion = '1.80' bouncyPgVersion = bouncyCastleVersion From 5a413f53a42a26169901ce634b6dfa7cc002f22b Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Mon, 21 Apr 2025 19:11:52 +0200 Subject: [PATCH 17/27] Specify license information for native-image metadata --- REUSE.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/REUSE.toml b/REUSE.toml index d250e0be..66b5e867 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -93,6 +93,12 @@ precedence = "aggregate" SPDX-FileCopyrightText = "2022 Paul Schaub , 2017 Steve Smith" SPDX-License-Identifier = "CC-BY-SA-3.0" +[[annotations]] +path = "pgpainless-cli/src/main/resources/META-INF/native-image/**" +precedence = "aggregate" +SPDX-FileCopyrightText = "2025 Paul Schaub " +SPDX-License-Identifier = "Apache-2.0" + [[annotations]] path = "pgpainless-cli/rewriteManPages.sh" precedence = "aggregate" From 0649c041cdead499b391f874830a0bdc2c17e246 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Mon, 21 Apr 2025 19:12:10 +0200 Subject: [PATCH 18/27] gradle: migrate to new shadow plugin namespace --- pgpainless-cli/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pgpainless-cli/build.gradle b/pgpainless-cli/build.gradle index e86ddedf..e4c3f060 100644 --- a/pgpainless-cli/build.gradle +++ b/pgpainless-cli/build.gradle @@ -5,7 +5,7 @@ plugins { id 'application' id 'org.graalvm.buildtools.native' version '0.10.6' - id 'com.github.johnrengelman.shadow' version '8.1.1' + id 'com.gradleup.shadow' version '8.3.6' } graalvmNative { From 7953ade13673568487eb0a3b7b141f96a08af585 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 3 Jun 2025 12:37:04 +0200 Subject: [PATCH 19/27] Bump checkstyle to 10.25.0 Fixes https://github.com/pgpainless/pgpainless/security/dependabot/24 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d05845b4..93100f4d 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,7 @@ allprojects { // checkstyle checkstyle { - toolVersion = '10.12.1' + toolVersion = '10.25.0' } spotless { From 5f30df6d166962f780fbfcb870f9934d84e6e771 Mon Sep 17 00:00:00 2001 From: Felix Hagemans Date: Wed, 4 Jun 2025 16:02:23 +0200 Subject: [PATCH 20/27] Fixed typo in sop readme --- pgpainless-sop/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pgpainless-sop/README.md b/pgpainless-sop/README.md index da112604..7f7267cd 100644 --- a/pgpainless-sop/README.md +++ b/pgpainless-sop/README.md @@ -67,7 +67,7 @@ byte[] encrypted = sop.encrypt() // Decrypt a message ByteArrayAndResult messageAndVerifications = sop.decrypt() - .verifyWith(cert) + .verifyWithCert(cert) .withKey(key) .ciphertext(encrypted) .toByteArrayAndResult(); From 0f54cc615c5409b5fa12d61182f63d022e78f828 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 17 Jun 2025 10:30:42 +0200 Subject: [PATCH 21/27] Bump BC to 1.81, update native-image reflect-config, resource-config --- .../META-INF/native-image/reflect-config.json | 108 +----------------- .../native-image/resource-config.json | 2 - version.gradle | 2 +- 3 files changed, 5 insertions(+), 107 deletions(-) diff --git a/pgpainless-cli/src/main/resources/META-INF/native-image/reflect-config.json b/pgpainless-cli/src/main/resources/META-INF/native-image/reflect-config.json index 25ad3faf..63bdf5f3 100644 --- a/pgpainless-cli/src/main/resources/META-INF/native-image/reflect-config.json +++ b/pgpainless-cli/src/main/resources/META-INF/native-image/reflect-config.json @@ -1,16 +1,7 @@ [ -{ - "name":"[B" -}, { "name":"[Ljava.lang.Object;" }, -{ - "name":"[Ljava.lang.String;" -}, -{ - "name":"[Lsun.security.pkcs.SignerInfo;" -}, { "name":"ch.qos.logback.classic.encoder.PatternLayoutEncoder", "queryAllPublicMethods":true, @@ -70,9 +61,6 @@ { "name":"java.lang.RuntimePermission" }, -{ - "name":"java.lang.String" -}, { "name":"java.lang.System", "methods":[{"name":"console","parameterTypes":[] }] @@ -101,9 +89,6 @@ "name":"java.nio.file.Paths", "methods":[{"name":"get","parameterTypes":["java.lang.String","java.lang.String[]"] }] }, -{ - "name":"java.security.AlgorithmParametersSpi" -}, { "name":"java.security.AllPermission" }, @@ -119,21 +104,6 @@ { "name":"java.security.cert.PKIXRevocationChecker" }, -{ - "name":"java.security.interfaces.DSAPrivateKey" -}, -{ - "name":"java.security.interfaces.DSAPublicKey" -}, -{ - "name":"java.security.interfaces.RSAPrivateKey" -}, -{ - "name":"java.security.interfaces.RSAPublicKey" -}, -{ - "name":"java.security.spec.DSAParameterSpec" -}, { "name":"java.sql.Connection" }, @@ -208,9 +178,6 @@ "name":"java.time.ZonedDateTime", "methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }] }, -{ - "name":"java.util.Date" -}, { "name":"java.util.HashSet" }, @@ -245,11 +212,6 @@ { "name":"java.util.concurrent.locks.ReentrantLock$Sync" }, -{ - "name":"javax.security.auth.x500.X500Principal", - "fields":[{"name":"thisX500Name"}], - "methods":[{"name":"","parameterTypes":["sun.security.x509.X500Name"] }] -}, { "name":"javax.smartcardio.CardPermission" }, @@ -333,6 +295,10 @@ "name":"org.bouncycastle.jcajce.provider.asymmetric.NTRU$Mappings", "methods":[{"name":"","parameterTypes":[] }] }, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.NoSig$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, { "name":"org.bouncycastle.jcajce.provider.asymmetric.RSA$Mappings", "methods":[{"name":"","parameterTypes":[] }] @@ -914,18 +880,6 @@ "queryAllDeclaredMethods":true, "methods":[{"name":"","parameterTypes":[] }] }, -{ - "name":"sun.security.provider.DSA$SHA256withDSA", - "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"sun.security.provider.DSAKeyFactory", - "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"sun.security.provider.DSAParameters", - "methods":[{"name":"","parameterTypes":[] }] -}, { "name":"sun.security.provider.NativePRNG", "methods":[{"name":"","parameterTypes":[] }, {"name":"","parameterTypes":["java.security.SecureRandomParameters"] }] @@ -933,59 +887,5 @@ { "name":"sun.security.provider.SHA", "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"sun.security.provider.SHA2$SHA256", - "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"sun.security.provider.X509Factory", - "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"sun.security.rsa.RSAKeyFactory$Legacy", - "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"sun.security.rsa.RSASignature$SHA256withRSA", - "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"sun.security.util.ObjectIdentifier" -}, -{ - "name":"sun.security.x509.AuthorityInfoAccessExtension", - "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] -}, -{ - "name":"sun.security.x509.AuthorityKeyIdentifierExtension", - "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] -}, -{ - "name":"sun.security.x509.BasicConstraintsExtension", - "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] -}, -{ - "name":"sun.security.x509.CRLDistributionPointsExtension", - "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] -}, -{ - "name":"sun.security.x509.CertificateExtensions" -}, -{ - "name":"sun.security.x509.CertificatePoliciesExtension", - "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] -}, -{ - "name":"sun.security.x509.ExtendedKeyUsageExtension", - "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] -}, -{ - "name":"sun.security.x509.KeyUsageExtension", - "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] -}, -{ - "name":"sun.security.x509.SubjectKeyIdentifierExtension", - "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] } ] \ No newline at end of file diff --git a/pgpainless-cli/src/main/resources/META-INF/native-image/resource-config.json b/pgpainless-cli/src/main/resources/META-INF/native-image/resource-config.json index af650dc9..3c66a520 100644 --- a/pgpainless-cli/src/main/resources/META-INF/native-image/resource-config.json +++ b/pgpainless-cli/src/main/resources/META-INF/native-image/resource-config.json @@ -40,8 +40,6 @@ "pattern":"\\Qsop-java-version.properties\\E" }, { "pattern":"java.base:\\Qsun/text/resources/LineBreakIteratorData\\E" - }, { - "pattern":"java.base:\\Qsun/text/resources/nfkc.icu\\E" }]}, "bundles":[{ "name":"msg_armor", diff --git a/version.gradle b/version.gradle index 003de912..bc2515a4 100644 --- a/version.gradle +++ b/version.gradle @@ -7,7 +7,7 @@ allprojects { shortVersion = '1.7.7' isSnapshot = true javaSourceCompatibility = 11 - bouncyCastleVersion = '1.80' + bouncyCastleVersion = '1.81' bouncyPgVersion = bouncyCastleVersion junitVersion = '5.8.2' logbackVersion = '1.5.13' From 4cf6c6b16a2f8d352fe54d3b0276eff936caeb03 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 17 Jun 2025 10:42:50 +0200 Subject: [PATCH 22/27] Update CHANGELOG --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1f63d6e..13c93c07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ SPDX-License-Identifier: CC0-1.0 # PGPainless Changelog +## 1.7.7-SNAPSHOT +- Bump `bcpg-jdk8on` to `1.81` +- Bump `bcprov-jdk18on` to `1.81` + ## 1.7.6 - Fix `RevocationSignatureBuilder` properly calculating third-party signatures of type `KeyRevocation` (delegation revocations) - Enable support for native images From f2cbde43bee0da523717b65f10f95defc4ad6f60 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 1 Jul 2025 10:54:06 +0200 Subject: [PATCH 23/27] Update codeql action to v3 --- .github/workflows/codeql-analysis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 031ba56d..d45b16a3 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' ] + language: [ 'java-kotlin' ] # 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@v2 + uses: github/codeql-action/init@v3 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@v2 + uses: github/codeql-action/autobuild@v3 # â„šī¸ 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@v2 + uses: github/codeql-action/analyze@v3 From 0ee31b232ac7b4beda0940bcbd52fc078209dfc4 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Wed, 23 Jul 2025 11:23:34 +0200 Subject: [PATCH 24/27] Allow UserIDs with trailing/leading whitespace and escape newlines in ASCII armor --- .../org/pgpainless/key/generation/KeyRingBuilder.kt | 2 +- .../modification/secretkeyring/SecretKeyRingEditor.kt | 7 ++++--- .../src/main/kotlin/org/pgpainless/util/ArmorUtils.kt | 3 ++- .../test/java/org/pgpainless/sop/GenerateKeyTest.java | 10 ++++++++++ 4 files changed, 17 insertions(+), 5 deletions(-) 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 05adf7d9..aacfcceb 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 @@ -45,7 +45,7 @@ class KeyRingBuilder : KeyRingBuilderInterface { } override fun addUserId(userId: CharSequence): KeyRingBuilder = apply { - userIds[userId.toString().trim()] = null + userIds[userId.toString()] = null } override fun addUserId(userId: ByteArray): KeyRingBuilder = 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 ec93c6d6..56fb7695 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 @@ -569,9 +569,10 @@ class SecretKeyRingEditor( } private fun sanitizeUserId(userId: CharSequence): CharSequence = - // TODO: Further research how to sanitize user IDs. - // e.g. what about newlines? - userId.toString().trim() + // 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() 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 b5d5b839..b6e802b2 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/util/ArmorUtils.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/util/ArmorUtils.kt @@ -247,7 +247,8 @@ class ArmorUtils { .add(OpenPgpFingerprint.of(publicKey).prettyPrint()) // Primary / First User ID (primary ?: first)?.let { - headerMap.getOrPut(HEADER_COMMENT) { mutableSetOf() }.add(it) + headerMap.getOrPut(HEADER_COMMENT) { mutableSetOf() } + .add(it.replace("\n", "\\n").replace("\r", "\\r")) } // X-1 further identities when (userIds.size) { 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 ca6df790..521cdfe0 100644 --- a/pgpainless-sop/src/test/java/org/pgpainless/sop/GenerateKeyTest.java +++ b/pgpainless-sop/src/test/java/org/pgpainless/sop/GenerateKeyTest.java @@ -100,4 +100,14 @@ 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")); + } } From 9b0a3cd4c7ffe8866ab9622fde866b79cd34a62b Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Wed, 23 Jul 2025 11:24:10 +0200 Subject: [PATCH 25/27] Do not trim passphrases automatically --- .../main/kotlin/org/pgpainless/util/Passphrase.kt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) 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 4d1e49d2..bd25f2b9 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/util/Passphrase.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/util/Passphrase.kt @@ -11,14 +11,9 @@ import org.bouncycastle.util.Arrays * * @param chars may be null for empty passwords. */ -class Passphrase(chars: CharArray?) { +class Passphrase(private val 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 @@ -67,6 +62,13 @@ class Passphrase(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 { /** From 0d807cb6b8317f2e878509b5cb5f4a9a91e5287d Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Wed, 23 Jul 2025 11:25:31 +0200 Subject: [PATCH 26/27] Fix typo in error message --- .../key/modification/secretkeyring/SecretKeyRingEditor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 56fb7695..5480442d 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 @@ -478,7 +478,7 @@ class SecretKeyRingEditor( val prevBinding = inspectKeyRing(secretKeyRing).getCurrentSubkeyBindingSignature(keyId) ?: throw NoSuchElementException( - "Previous subkey binding signaure for ${keyId.openPgpKeyId()} MUST NOT be null.") + "Previous subkey binding signature for ${keyId.openPgpKeyId()} MUST NOT be null.") val bindingSig = reissueSubkeyBindingSignature(subkey, expiration, protector, prevBinding) secretKeyRing = injectCertification(secretKeyRing, subkey, bindingSig) } From 0fe3a7abf660ee7814e87255c13b5775030e73f9 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sat, 30 Aug 2025 10:36:40 +0200 Subject: [PATCH 27/27] Fix ArmorUtils spotless complaint --- .../src/main/kotlin/org/pgpainless/util/ArmorUtils.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 b6e802b2..db1cb54d 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/util/ArmorUtils.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/util/ArmorUtils.kt @@ -247,7 +247,8 @@ class ArmorUtils { .add(OpenPgpFingerprint.of(publicKey).prettyPrint()) // Primary / First User ID (primary ?: first)?.let { - headerMap.getOrPut(HEADER_COMMENT) { mutableSetOf() } + headerMap + .getOrPut(HEADER_COMMENT) { mutableSetOf() } .add(it.replace("\n", "\\n").replace("\r", "\\r")) } // X-1 further identities