mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-09-10 10:49:39 +02:00
Compare commits
No commits in common. "main" and "1.7.1" have entirely different histories.
56 changed files with 570 additions and 1655 deletions
8
.github/workflows/codeql-analysis.yml
vendored
8
.github/workflows/codeql-analysis.yml
vendored
|
@ -36,7 +36,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
language: [ 'java-kotlin' ]
|
language: [ 'java' ]
|
||||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ jobs:
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v2
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# 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).
|
# 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)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v3
|
uses: github/codeql-action/autobuild@v2
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
|
@ -71,4 +71,4 @@ jobs:
|
||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v3
|
uses: github/codeql-action/analyze@v2
|
||||||
|
|
8
.github/workflows/gradle_push.yml
vendored
8
.github/workflows/gradle_push.yml
vendored
|
@ -28,13 +28,9 @@ jobs:
|
||||||
with:
|
with:
|
||||||
java-version: '11'
|
java-version: '11'
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
- name: Build and Check
|
- name: Build, Check and Coverage
|
||||||
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
|
|
||||||
with:
|
|
||||||
arguments: check jacocoRootReport
|
|
||||||
- name: Coveralls
|
|
||||||
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
|
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
|
||||||
env:
|
env:
|
||||||
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
|
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
|
||||||
with:
|
with:
|
||||||
arguments: coveralls
|
arguments: check jacocoRootReport coveralls
|
86
.reuse/dep5
Normal file
86
.reuse/dep5
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: PGPainless
|
||||||
|
Upstream-Contact: Paul Schaub <info@pgpainless.org>
|
||||||
|
Source: https://pgpainless.org
|
||||||
|
|
||||||
|
# Sample paragraph, commented out:
|
||||||
|
#
|
||||||
|
# Files: src/*
|
||||||
|
# Copyright: $YEAR $NAME <$CONTACT>
|
||||||
|
# License: ...
|
||||||
|
|
||||||
|
# GitBlameIgnore
|
||||||
|
Files: .git-blame-ignore-revs
|
||||||
|
Copyright: 2023 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: CC0-1.0
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
Files: docs/*
|
||||||
|
Copyright: 2022 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: CC-BY-3.0
|
||||||
|
|
||||||
|
Files: .readthedocs.yaml
|
||||||
|
Copyright: 2022 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: CC0-1.0
|
||||||
|
|
||||||
|
# Gradle build tool
|
||||||
|
Files: gradle*
|
||||||
|
Copyright: 2015 the original author or authors.
|
||||||
|
License: Apache-2.0
|
||||||
|
|
||||||
|
# Editorconfig
|
||||||
|
Files: .editorconfig
|
||||||
|
Copyright: Facebook
|
||||||
|
License: Apache-2.0
|
||||||
|
|
||||||
|
# PGPainless Logo
|
||||||
|
Files: assets/repository-open-graph.png
|
||||||
|
Copyright: 2021 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: CC-BY-3.0
|
||||||
|
|
||||||
|
Files: assets/pgpainless.svg
|
||||||
|
Copyright: 2021 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: CC-BY-3.0
|
||||||
|
|
||||||
|
Files: assets/logo.png
|
||||||
|
Copyright: 2022 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: CC-BY-3.0
|
||||||
|
|
||||||
|
Files: assets/test_vectors/*
|
||||||
|
Copyright: 2018 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: CC0-1.0
|
||||||
|
|
||||||
|
Files: pgpainless-core/src/test/resources/*
|
||||||
|
Copyright: 2020 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: CC0-1.0
|
||||||
|
|
||||||
|
Files: audit/*
|
||||||
|
Copyright: 2021 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: CC0-1.0
|
||||||
|
|
||||||
|
# GH Pages
|
||||||
|
Files: CNAME
|
||||||
|
Copyright: 2022 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: CC0-1.0
|
||||||
|
|
||||||
|
Files: _config.yml
|
||||||
|
Copyright: 2022 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: CC0-1.0
|
||||||
|
|
||||||
|
Files: _layouts/*
|
||||||
|
Copyright: 2022 Paul Schaub <info@pgpainless.org>, 2017 Steve Smith
|
||||||
|
License: CC-BY-SA-3.0
|
||||||
|
|
||||||
|
# Man Pages
|
||||||
|
Files: pgpainless-cli/rewriteManPages.sh
|
||||||
|
Copyright: 2022 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: Apache-2.0
|
||||||
|
|
||||||
|
Files: pgpainless-cli/packaging/man/*
|
||||||
|
Copyright: 2022 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: Apache-2.0
|
||||||
|
|
||||||
|
# Github Issue Templates
|
||||||
|
Files: .github/ISSUE_TEMPLATE/*
|
||||||
|
Copyright: 2024 Paul Schaub <info@pgpainless.org>
|
||||||
|
License: CC0-1.0
|
41
CHANGELOG.md
41
CHANGELOG.md
|
@ -5,42 +5,6 @@ SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
# PGPainless Changelog
|
# 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
|
|
||||||
- Re-enable shadow plugin and build fat-jar
|
|
||||||
|
|
||||||
## 1.7.5
|
|
||||||
- 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
|
|
||||||
|
|
||||||
## 1.7.3
|
|
||||||
- Bump `bcpg-jdk8on` to `1.80`
|
|
||||||
- Bump `bcprov-jdk18on` to `1.80`
|
|
||||||
- Add dependency on `bcutil-jdk18on` as a workaround
|
|
||||||
- Ignore unknown type signatures on certificates
|
|
||||||
- Fix typo on signature creation bounds check (thanks @elduffy)
|
|
||||||
- Fix superfluous newline added in CRLF encoding (thanks @bjansen)
|
|
||||||
- Bump `sop-java` to `1.10.0`
|
|
||||||
- SOP inline-sign: Do not apply compression
|
|
||||||
|
|
||||||
## 1.7.2
|
|
||||||
- Fix bug in `KeyRingInfo.lastModified` (thanks to @Jerbell, @sosnovsky for reporting)
|
|
||||||
- Bump `sop-java` to `10.0.3`
|
|
||||||
- allow multiple arguments `--with-key-password` in `revoke-key` command
|
|
||||||
- Properly pass `--old-key-password` and `--new-key-password` options as indirect arguments in `change-key-password` command
|
|
||||||
|
|
||||||
## 1.7.1
|
|
||||||
- Bump `sop-java` to `10.0.2`
|
|
||||||
- Downgrade `logback-core` and `logback-classic` to `1.2.13` (fix CLI spam)
|
|
||||||
|
|
||||||
## 1.7.0
|
## 1.7.0
|
||||||
- Bump `bcpg-jdk8on` to `1.78.1`
|
- Bump `bcpg-jdk8on` to `1.78.1`
|
||||||
|
@ -71,11 +35,6 @@ SPDX-License-Identifier: CC0-1.0
|
||||||
- Throw `BadData` error when passing KEYS where CERTS are expected.
|
- Throw `BadData` error when passing KEYS where CERTS are expected.
|
||||||
- `armor`: Remove `--label` option
|
- `armor`: Remove `--label` option
|
||||||
|
|
||||||
## 1.6.8
|
|
||||||
- Bump `sop-java` to `7.0.2`
|
|
||||||
- SOP `change-key-password`: Fix reading password from indirect parameter instead of erroneously passing filename (fixes #453)
|
|
||||||
- SOP `revoke-key`: Allow for multiple `--with-key-password` options
|
|
||||||
|
|
||||||
## 1.6.7
|
## 1.6.7
|
||||||
- SOP: Fix OOM error when detached-signing large amounts of data (fix #432)
|
- SOP: Fix OOM error when detached-signing large amounts of data (fix #432)
|
||||||
- Move `CachingBcPublicKeyDataDecryptorFactory` from `org.bouncycastle` packet to `org.pgpainless.decryption_verification` to avoid package split (partially addresses #428)
|
- Move `CachingBcPublicKeyDataDecryptorFactory` from `org.bouncycastle` packet to `org.pgpainless.decryption_verification` to avoid package split (partially addresses #428)
|
||||||
|
|
|
@ -164,7 +164,7 @@ This behaviour can be modified though using the `Policy` class.
|
||||||
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
|
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
|
||||||
.onInputStream(encryptedInputStream)
|
.onInputStream(encryptedInputStream)
|
||||||
.withOptions(new ConsumerOptions()
|
.withOptions(new ConsumerOptions()
|
||||||
.addDecryptionKey(bobSecKeys, secretKeyProtector)
|
.addMessagePassphrase(bobSecKeys, secretKeyProtector)
|
||||||
.addVerificationCert(alicePubKeys)
|
.addVerificationCert(alicePubKeys)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.pgpainless:pgpainless-core:1.7.6'
|
implementation 'org.pgpainless:pgpainless-core:1.7.1'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -222,6 +222,9 @@ Parts of PGPainless development ([project page](https://nlnet.nl/project/PGPainl
|
||||||
NGI Assure is made possible with financial support from the [European Commission](https://ec.europa.eu/)'s [Next Generation Internet](https://ngi.eu/) programme, under the aegis of [DG Communications Networks, Content and Technology](https://ec.europa.eu/info/departments/communications-networks-content-and-technology_en).
|
NGI Assure is made possible with financial support from the [European Commission](https://ec.europa.eu/)'s [Next Generation Internet](https://ngi.eu/) programme, under the aegis of [DG Communications Networks, Content and Technology](https://ec.europa.eu/info/departments/communications-networks-content-and-technology_en).
|
||||||
[](https://nlnet.nl/assure/)
|
[](https://nlnet.nl/assure/)
|
||||||
|
|
||||||
|
Thanks to [YourKit](https://www.yourkit.com/) for providing a free license of the [YourKit Java Profiler](https://www.yourkit.com/java/profiler/) to support PGPainless Development!
|
||||||
|
[](https://www.yourkit.com/)
|
||||||
|
|
||||||
Big thank you also to those who decided to support the work by donating!
|
Big thank you also to those who decided to support the work by donating!
|
||||||
Notably @msfjarvis
|
Notably @msfjarvis
|
||||||
|
|
||||||
|
|
118
REUSE.toml
118
REUSE.toml
|
@ -1,118 +0,0 @@
|
||||||
version = 1
|
|
||||||
SPDX-PackageName = "PGPainless"
|
|
||||||
SPDX-PackageSupplier = "Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-PackageDownloadLocation = "https://pgpainless.org"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "REUSE.toml"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2025 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "CC0-1.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = ".git-blame-ignore-revs"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2023 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "CC0-1.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "docs/**"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2022 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "CC-BY-3.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = ".readthedocs.yaml"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2022 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "CC0-1.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "gradle**"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2015 the original author or authors."
|
|
||||||
SPDX-License-Identifier = "Apache-2.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = ".editorconfig"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "Facebook"
|
|
||||||
SPDX-License-Identifier = "Apache-2.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "assets/repository-open-graph.png"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2021 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "CC-BY-3.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "assets/pgpainless.svg"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2021 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "CC-BY-3.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "assets/logo.png"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2022 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "CC-BY-3.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "assets/test_vectors/**"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2018 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "CC0-1.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "pgpainless-core/src/test/resources/**"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2020 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "CC0-1.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "audit/**"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2021 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "CC0-1.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "CNAME"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2022 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "CC0-1.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "_config.yml"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2022 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "CC0-1.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "_layouts/**"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2022 Paul Schaub <info@pgpainless.org>, 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 <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "Apache-2.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "pgpainless-cli/rewriteManPages.sh"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2022 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "Apache-2.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "pgpainless-cli/packaging/man/**"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2022 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "Apache-2.0"
|
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = ".github/ISSUE_TEMPLATE/**"
|
|
||||||
precedence = "aggregate"
|
|
||||||
SPDX-FileCopyrightText = "2024 Paul Schaub <info@pgpainless.org>"
|
|
||||||
SPDX-License-Identifier = "CC0-1.0"
|
|
78
build.gradle
78
build.gradle
|
@ -33,17 +33,24 @@ allprojects {
|
||||||
apply plugin: 'kotlin'
|
apply plugin: 'kotlin'
|
||||||
apply plugin: 'com.diffplug.spotless'
|
apply plugin: 'com.diffplug.spotless'
|
||||||
|
|
||||||
|
java {
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
compileJava {
|
||||||
|
options.release = 8
|
||||||
|
}
|
||||||
|
|
||||||
// Only generate jar for submodules
|
// Only generate jar for submodules
|
||||||
// without this we would generate an empty pgpainless.jar for the project root
|
// without this we would generate an empty pgpainless.jar for the project root
|
||||||
// https://stackoverflow.com/a/25445035
|
// https://stackoverflow.com/a/25445035
|
||||||
jar {
|
jar {
|
||||||
reproducibleFileOrder = true
|
|
||||||
onlyIf { !sourceSets.main.allSource.files.isEmpty() }
|
onlyIf { !sourceSets.main.allSource.files.isEmpty() }
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkstyle
|
// checkstyle
|
||||||
checkstyle {
|
checkstyle {
|
||||||
toolVersion = '10.25.0'
|
toolVersion = '10.12.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
spotless {
|
spotless {
|
||||||
|
@ -56,6 +63,8 @@ allprojects {
|
||||||
description = "Simple to use OpenPGP API for Java based on Bouncycastle"
|
description = "Simple to use OpenPGP API for Java based on Bouncycastle"
|
||||||
version = shortVersion
|
version = shortVersion
|
||||||
|
|
||||||
|
sourceCompatibility = javaSourceCompatibility
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
|
@ -70,10 +79,6 @@ allprojects {
|
||||||
fileMode = 0644
|
fileMode = 0644
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
|
||||||
jvmToolchain(javaSourceCompatibility)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compatibility of default implementations in kotlin interfaces with Java implementations.
|
// Compatibility of default implementations in kotlin interfaces with Java implementations.
|
||||||
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
|
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
|
@ -114,7 +119,7 @@ allprojects {
|
||||||
sourceDirectories.setFrom(project.files(sourceSets.main.allSource.srcDirs))
|
sourceDirectories.setFrom(project.files(sourceSets.main.allSource.srcDirs))
|
||||||
classDirectories.setFrom(project.files(sourceSets.main.output))
|
classDirectories.setFrom(project.files(sourceSets.main.output))
|
||||||
reports {
|
reports {
|
||||||
xml.required = true
|
xml.enabled true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,15 +137,15 @@ subprojects {
|
||||||
apply plugin: 'signing'
|
apply plugin: 'signing'
|
||||||
|
|
||||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||||
archiveClassifier = 'sources'
|
classifier = 'sources'
|
||||||
from sourceSets.main.allSource
|
from sourceSets.main.allSource
|
||||||
}
|
}
|
||||||
task javadocJar(type: Jar, dependsOn: javadoc) {
|
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||||
archiveClassifier = 'javadoc'
|
classifier = 'javadoc'
|
||||||
from javadoc.destinationDir
|
from javadoc.destinationDir
|
||||||
}
|
}
|
||||||
task testsJar(type: Jar, dependsOn: testClasses) {
|
task testsJar(type: Jar, dependsOn: testClasses) {
|
||||||
archiveClassifier = 'tests'
|
classifier = 'tests'
|
||||||
from sourceSets.test.output
|
from sourceSets.test.output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +242,7 @@ task jacocoRootReport(type: JacocoReport) {
|
||||||
classDirectories.setFrom(files(subprojects.sourceSets.main.output))
|
classDirectories.setFrom(files(subprojects.sourceSets.main.output))
|
||||||
executionData.setFrom(files(subprojects.jacocoTestReport.executionData))
|
executionData.setFrom(files(subprojects.jacocoTestReport.executionData))
|
||||||
reports {
|
reports {
|
||||||
xml.required = true
|
xml.enabled true
|
||||||
xml.destination file("${buildDir}/reports/jacoco/test/jacocoTestReport.xml")
|
xml.destination file("${buildDir}/reports/jacoco/test/jacocoTestReport.xml")
|
||||||
}
|
}
|
||||||
// We could remove the following setOnlyIf line, but then
|
// We could remove the following setOnlyIf line, but then
|
||||||
|
@ -248,6 +253,10 @@ task jacocoRootReport(type: JacocoReport) {
|
||||||
}
|
}
|
||||||
|
|
||||||
task javadocAll(type: Javadoc) {
|
task javadocAll(type: Javadoc) {
|
||||||
|
def currentJavaVersion = JavaVersion.current()
|
||||||
|
if (currentJavaVersion.compareTo(JavaVersion.VERSION_1_9) >= 0) {
|
||||||
|
options.addStringOption("-release", "8");
|
||||||
|
}
|
||||||
source subprojects.collect {project ->
|
source subprojects.collect {project ->
|
||||||
project.sourceSets.main.allJava }
|
project.sourceSets.main.allJava }
|
||||||
destinationDir = new File(buildDir, 'javadoc')
|
destinationDir = new File(buildDir, 'javadoc')
|
||||||
|
@ -261,6 +270,18 @@ task javadocAll(type: Javadoc) {
|
||||||
] as String[]
|
] 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.
|
* Fetch sha256 checksums of artifacts published to maven central.
|
||||||
*
|
*
|
||||||
|
@ -270,13 +291,34 @@ task mavenCentralChecksums() {
|
||||||
description 'Fetch and display checksums for artifacts published to Maven Central'
|
description 'Fetch and display checksums for artifacts published to Maven Central'
|
||||||
String ver = project.hasProperty('release') ? release : shortVersion
|
String ver = project.hasProperty('release') ? release : shortVersion
|
||||||
doLast {
|
doLast {
|
||||||
for (Project p : rootProject.subprojects) {
|
Process p = "curl -f https://repo1.maven.org/maven2/org/pgpainless/pgpainless-core/${ver}/pgpainless-core-${ver}.jar.sha256".execute()
|
||||||
String url = "https://repo1.maven.org/maven2/org/pgpainless/${p.name}/${ver}/${p.name}-${ver}.jar.sha256"
|
if (p.waitFor() == 0) {
|
||||||
Process fetch = "curl -f $url".execute()
|
print p.text.trim()
|
||||||
if (fetch.waitFor() == 0) {
|
println " pgpainless-core/build/libs/pgpainless-core-${ver}.jar"
|
||||||
print fetch.text.trim()
|
}
|
||||||
println " ${p.name}/build/libs/${p.name}-${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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,5 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
@ -4,13 +4,27 @@
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'application'
|
id 'application'
|
||||||
id 'org.graalvm.buildtools.native' version '0.10.6'
|
id "com.github.johnrengelman.shadow" version "6.1.0"
|
||||||
id 'com.gradleup.shadow' version '8.3.6'
|
}
|
||||||
|
def generatedVersionDir = "${buildDir}/generated-version"
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
output.dir(generatedVersionDir, builtBy: 'generateVersionProperties')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
graalvmNative {
|
task generateVersionProperties {
|
||||||
toolchainDetection = true
|
doLast {
|
||||||
|
def propertiesFile = file "$generatedVersionDir/version.properties"
|
||||||
|
propertiesFile.parentFile.mkdirs()
|
||||||
|
propertiesFile.createNewFile()
|
||||||
|
// Instead of using a Properties object here, we directly write to the file
|
||||||
|
// since Properties adds a timestamp, ruining reproducibility
|
||||||
|
propertiesFile.write("version="+rootProject.version.toString())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
processResources.dependsOn generateVersionProperties
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
|
@ -18,12 +32,13 @@ dependencies {
|
||||||
|
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
|
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
|
||||||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
|
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
|
||||||
|
// https://todd.ginsberg.com/post/testing-system-exit/
|
||||||
|
testImplementation 'com.ginsberg:junit5-system-exit:1.1.2'
|
||||||
|
|
||||||
// implementation "ch.qos.logback:logback-core:1.2.6"
|
// implementation "ch.qos.logback:logback-core:1.2.6"
|
||||||
// We want logback logging in tests and in the app
|
// We want logback logging in tests and in the app
|
||||||
testImplementation "ch.qos.logback:logback-classic:$logbackVersion"
|
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(project(":pgpainless-sop"))
|
||||||
implementation "org.pgpainless:sop-java-picocli:$sopJavaVersion"
|
implementation "org.pgpainless:sop-java-picocli:$sopJavaVersion"
|
||||||
|
@ -37,6 +52,22 @@ mainClassName = 'org.pgpainless.cli.PGPainlessCLI'
|
||||||
application {
|
application {
|
||||||
mainClass = mainClassName
|
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 {
|
run {
|
||||||
// https://stackoverflow.com/questions/59445306/pipe-into-gradle-run
|
// https://stackoverflow.com/questions/59445306/pipe-into-gradle-run
|
||||||
|
@ -46,3 +77,5 @@ run {
|
||||||
args Eval.me(appArgs)
|
args Eval.me(appArgs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tasks."jar".dependsOn(":pgpainless-core:assemble", ":pgpainless-sop:assemble")
|
||||||
|
|
|
@ -14,10 +14,6 @@ import sop.cli.picocli.SopCLI;
|
||||||
public class PGPainlessCLI {
|
public class PGPainlessCLI {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// Prevent slf4j initialization logging
|
|
||||||
// https://github.com/qos-ch/slf4j/issues/422#issuecomment-2277280185
|
|
||||||
System.setProperty("slf4j.internal.verbosity", "WARN");
|
|
||||||
|
|
||||||
SopCLI.EXECUTABLE_NAME = "pgpainless-cli";
|
SopCLI.EXECUTABLE_NAME = "pgpainless-cli";
|
||||||
SopCLI.setSopInstance(new SOPImpl());
|
SopCLI.setSopInstance(new SOPImpl());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
[
|
|
||||||
]
|
|
|
@ -1,7 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"type":"agent-extracted",
|
|
||||||
"classes":[
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,2 +0,0 @@
|
||||||
[
|
|
||||||
]
|
|
|
@ -1,891 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"name":"[Ljava.lang.Object;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"ch.qos.logback.classic.encoder.PatternLayoutEncoder",
|
|
||||||
"queryAllPublicMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"ch.qos.logback.classic.joran.SerializedModelConfigurator",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"ch.qos.logback.classic.util.DefaultJoranConfigurator",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"ch.qos.logback.core.ConsoleAppender",
|
|
||||||
"queryAllPublicMethods":true,
|
|
||||||
"methods":[{"name":"<init>","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":"<init>","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.System",
|
|
||||||
"methods":[{"name":"console","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.lang.invoke.MethodHandle"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.net.NetPermission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.net.SocketPermission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.net.URLPermission",
|
|
||||||
"methods":[{"name":"<init>","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.AllPermission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.security.MessageDigestSpi"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.security.SecureRandomParameters"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.security.SecurityPermission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.security.cert.PKIXRevocationChecker"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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":"<init>","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.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.smartcardio.CardPermission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.COMPOSITE$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.CONTEXT$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.CompositeSignatures$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.DH$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.DSA$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.DSTU4145$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.Dilithium$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.EC$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.ECGOST$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.EXTERNAL$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.EdEC$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.ElGamal$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.Falcon$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.GM$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.GOST$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.IES$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.LMS$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.MLDSA$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.MLKEM$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.NTRU$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.NoSig$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.RSA$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.SLHDSA$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.SPHINCSPlus$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.X509$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.edec.KeyPairGeneratorSpi$EdDSA",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.edec.KeyPairGeneratorSpi$XDH",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyPairGeneratorSpi",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.Blake2b$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.Blake2s$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.Blake3$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.DSTU7564$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.GOST3411$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.Haraka$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.Keccak$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.MD2$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.MD4$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.MD5$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.RIPEMD128$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.RIPEMD160$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.RIPEMD256$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.RIPEMD320$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.SHA1$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.SHA224$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.SHA256$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.SHA3$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.SHA384$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.SHA512$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.SM3$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.Skein$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.Tiger$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.digest.Whirlpool$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.drbg.DRBG$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.keystore.BC$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.keystore.BCFKS$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.keystore.PKCS12$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.AES$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.ARC4$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.ARIA$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Blowfish$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.CAST5$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.CAST6$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Camellia$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.ChaCha$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.DES$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.DESede$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.DSTU7624$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.GOST28147$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.GOST3412_2015$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Grain128$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Grainv1$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.HC128$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.HC256$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.IDEA$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Noekeon$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.OpenSSLPBKDF$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF1$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF2$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.PBEPKCS12$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Poly1305$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.RC2$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.RC5$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.RC6$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Rijndael$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.SCRYPT$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.SEED$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.SM4$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Salsa20$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Serpent$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Shacal2$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.SipHash$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.SipHash128$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Skipjack$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.TEA$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.TLSKDF$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Threefish$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Twofish$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.VMPC$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.VMPCKSA3$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.XSalsa20$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.XTEA$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.bouncycastle.jcajce.provider.symmetric.Zuc$Mappings",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.pgpainless.cli.ExitCodeTest",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"allDeclaredClasses":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"queryAllPublicMethods":true,
|
|
||||||
"queryAllDeclaredConstructors":true,
|
|
||||||
"methods":[{"name":"<init>","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":"<init>","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":"<init>","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":"<init>","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":"<init>","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":"<init>","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":"<init>","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":"<init>","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":"<init>","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":"<init>","parameterTypes":[] }, {"name":"encryptAndDecryptAMessage","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.pgpainless.cli.commands.RoundTripSignVerifyCmdTest",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"allDeclaredClasses":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"queryAllPublicMethods":true,
|
|
||||||
"queryAllDeclaredConstructors":true,
|
|
||||||
"methods":[{"name":"<init>","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":"<init>","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":"<init>","parameterTypes":[] }, {"name":"testSignatureCreationAndVerification","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"picocli.AutoComplete$GenerateCompletion",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","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":"<init>","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":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.ChangeKeyPasswordCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.DearmorCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.DecryptCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.EncryptCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.ExtractCertCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.GenerateKeyCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.InlineDetachCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.InlineSignCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.InlineVerifyCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.ListProfilesCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.RevokeKeyCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.SignCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.VerifyCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.VersionCmd",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sop.cli.picocli.commands.VersionCmd$Exclusive",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.provider.NativePRNG",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }, {"name":"<init>","parameterTypes":["java.security.SecureRandomParameters"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.provider.SHA",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,93 +0,0 @@
|
||||||
{
|
|
||||||
"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"
|
|
||||||
}]},
|
|
||||||
"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"]
|
|
||||||
}]
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
{
|
|
||||||
"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":[
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -5,5 +5,22 @@ SPDX-License-Identifier: Apache-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<configuration debug="false">
|
<configuration debug="false">
|
||||||
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
|
<appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<target>System.err</target>
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<target>System.out</target>
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="error">
|
||||||
|
<appender-ref ref="STDERR" />
|
||||||
|
</root>
|
||||||
|
|
||||||
</configuration>
|
</configuration>
|
|
@ -4,35 +4,28 @@
|
||||||
|
|
||||||
package org.pgpainless.cli;
|
package org.pgpainless.cli;
|
||||||
|
|
||||||
|
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
|
||||||
|
import com.ginsberg.junit.exit.FailOnSystemExit;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.cli.commands.CLITest;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import sop.exception.SOPGPException;
|
import sop.exception.SOPGPException;
|
||||||
|
|
||||||
import java.io.IOException;
|
public class ExitCodeTest {
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
@Test
|
||||||
|
@ExpectSystemExitWithStatus(SOPGPException.UnsupportedSubcommand.EXIT_CODE)
|
||||||
public class ExitCodeTest extends CLITest {
|
public void testUnknownCommand_69() {
|
||||||
|
PGPainlessCLI.main(new String[] {"generate-kex"});
|
||||||
public ExitCodeTest() {
|
|
||||||
super(LoggerFactory.getLogger(ExitCodeTest.class));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnknownCommand_69() throws IOException {
|
@ExpectSystemExitWithStatus(SOPGPException.UnsupportedOption.EXIT_CODE)
|
||||||
assertEquals(SOPGPException.UnsupportedSubcommand.EXIT_CODE,
|
public void testCommandWithUnknownOption_37() {
|
||||||
executeCommand("unsupported-subcommand"));
|
PGPainlessCLI.main(new String[] {"generate-key", "-k", "\"k is unknown\""});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCommandWithUnknownOption_37() throws IOException {
|
@FailOnSystemExit
|
||||||
assertEquals(SOPGPException.UnsupportedOption.EXIT_CODE,
|
public void successfulExecutionDoesNotTerminateJVM() {
|
||||||
executeCommand("generate-key", "-k", "\"k is unknown\""));
|
PGPainlessCLI.main(new String[] {"version"});
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void successfulExecutionDoesNotTerminateJVM() throws IOException {
|
|
||||||
assertSuccess(executeCommand("version"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import java.io.IOException;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
import com.ginsberg.junit.exit.FailOnSystemExit;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
@ -82,6 +83,7 @@ public class RoundTripEncryptDecryptCmdTest extends CLITest {
|
||||||
"-----END PGP PUBLIC KEY BLOCK-----";
|
"-----END PGP PUBLIC KEY BLOCK-----";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@FailOnSystemExit
|
||||||
public void encryptAndDecryptAMessage() throws IOException {
|
public void encryptAndDecryptAMessage() throws IOException {
|
||||||
// Juliets key and cert
|
// Juliets key and cert
|
||||||
File julietKeyFile = pipeStdoutToFile("juliet.key");
|
File julietKeyFile = pipeStdoutToFile("juliet.key");
|
||||||
|
|
|
@ -138,10 +138,6 @@ public class RoundTripInlineSignInlineVerifyCmdTest extends CLITest {
|
||||||
"\n" +
|
"\n" +
|
||||||
"There is only one Lord of the Keys, only one who can bend them to his will. And he does not share power.";
|
"There is only one Lord of the Keys, only one who can bend them to his will. And he does not share power.";
|
||||||
|
|
||||||
private static final String MESSAGE_CRLF = "One does not simply use OpenPGP!\r\n" +
|
|
||||||
"\r\n" +
|
|
||||||
"There is only one Lord of the Keys, only one who can bend them to his will. And he does not share power.";
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createCleartextSignedMessage() throws IOException {
|
public void createCleartextSignedMessage() throws IOException {
|
||||||
File key = writeFile("key.asc", KEY_1);
|
File key = writeFile("key.asc", KEY_1);
|
||||||
|
@ -157,7 +153,7 @@ public class RoundTripInlineSignInlineVerifyCmdTest extends CLITest {
|
||||||
String cleartextSigned = ciphertextOut.toString();
|
String cleartextSigned = ciphertextOut.toString();
|
||||||
assertTrue(cleartextSigned.startsWith("-----BEGIN PGP SIGNED MESSAGE-----\n" +
|
assertTrue(cleartextSigned.startsWith("-----BEGIN PGP SIGNED MESSAGE-----\n" +
|
||||||
"Hash: "));
|
"Hash: "));
|
||||||
assertTrue(cleartextSigned.contains(MESSAGE_CRLF));
|
assertTrue(cleartextSigned.contains(MESSAGE));
|
||||||
assertTrue(cleartextSigned.contains("\n-----BEGIN PGP SIGNATURE-----\n"));
|
assertTrue(cleartextSigned.contains("\n-----BEGIN PGP SIGNATURE-----\n"));
|
||||||
assertTrue(cleartextSigned.endsWith("-----END PGP SIGNATURE-----\n"));
|
assertTrue(cleartextSigned.endsWith("-----END PGP SIGNATURE-----\n"));
|
||||||
}
|
}
|
||||||
|
@ -207,7 +203,7 @@ public class RoundTripInlineSignInlineVerifyCmdTest extends CLITest {
|
||||||
"--verifications-out", verifications.getAbsolutePath(),
|
"--verifications-out", verifications.getAbsolutePath(),
|
||||||
cert.getAbsolutePath()));
|
cert.getAbsolutePath()));
|
||||||
|
|
||||||
assertEquals(MESSAGE_CRLF, plaintextOut.toString());
|
assertEquals(MESSAGE, plaintextOut.toString());
|
||||||
String verificationString = readStringFromFile(verifications);
|
String verificationString = readStringFromFile(verifications);
|
||||||
assertTrue(verificationString.contains(CERT_1_SIGNING_KEY));
|
assertTrue(verificationString.contains(CERT_1_SIGNING_KEY));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,49 +4,104 @@
|
||||||
|
|
||||||
package org.pgpainless.cli.commands;
|
package org.pgpainless.cli.commands;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import com.ginsberg.junit.exit.FailOnSystemExit;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.pgpainless.cli.PGPainlessCLI;
|
||||||
|
import org.pgpainless.cli.TestUtils;
|
||||||
|
|
||||||
public class RoundTripInlineSignVerifyCmdTest extends CLITest {
|
public class RoundTripInlineSignVerifyCmdTest {
|
||||||
|
private static File tempDir;
|
||||||
|
private static PrintStream originalSout;
|
||||||
|
|
||||||
public RoundTripInlineSignVerifyCmdTest() {
|
@BeforeAll
|
||||||
super(LoggerFactory.getLogger(RoundTripInlineSignVerifyCmdTest.class));
|
public static void prepare() throws IOException {
|
||||||
|
tempDir = TestUtils.createTempDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@FailOnSystemExit
|
||||||
public void encryptAndDecryptAMessage() throws IOException {
|
public void encryptAndDecryptAMessage() throws IOException {
|
||||||
|
originalSout = System.out;
|
||||||
|
File sigmundKeyFile = new File(tempDir, "sigmund.key");
|
||||||
|
assertTrue(sigmundKeyFile.createNewFile());
|
||||||
|
|
||||||
|
File sigmundCertFile = new File(tempDir, "sigmund.cert");
|
||||||
|
assertTrue(sigmundCertFile.createNewFile());
|
||||||
|
|
||||||
|
File msgFile = new File(tempDir, "signed.asc");
|
||||||
|
assertTrue(msgFile.createNewFile());
|
||||||
|
|
||||||
|
File passwordFile = new File(tempDir, "password");
|
||||||
|
assertTrue(passwordFile.createNewFile());
|
||||||
|
|
||||||
// write password file
|
// write password file
|
||||||
File password = writeFile("password", "sw0rdf1sh");
|
FileOutputStream passwordOut = new FileOutputStream(passwordFile);
|
||||||
|
passwordOut.write("sw0rdf1sh".getBytes(StandardCharsets.UTF_8));
|
||||||
|
passwordOut.close();
|
||||||
|
|
||||||
// generate key
|
// generate key
|
||||||
File sigmundKey = pipeStdoutToFile("sigmund.key");
|
OutputStream sigmundKeyOut = new FileOutputStream(sigmundKeyFile);
|
||||||
assertSuccess(executeCommand("generate-key", "--with-key-password=" + password.getAbsolutePath(),
|
System.setOut(new PrintStream(sigmundKeyOut));
|
||||||
"Sigmund Freud <sigmund@pgpainless.org>"));
|
PGPainlessCLI.execute("generate-key",
|
||||||
|
"--with-key-password=" + passwordFile.getAbsolutePath(),
|
||||||
|
"Sigmund Freud <sigmund@pgpainless.org>");
|
||||||
|
sigmundKeyOut.close();
|
||||||
|
|
||||||
// extract cert
|
// extract cert
|
||||||
File sigmundCert = pipeStdoutToFile("sigmund.cert");
|
FileInputStream sigmundKeyIn = new FileInputStream(sigmundKeyFile);
|
||||||
pipeFileToStdin(sigmundKey);
|
System.setIn(sigmundKeyIn);
|
||||||
assertSuccess(executeCommand("extract-cert"));
|
OutputStream sigmundCertOut = new FileOutputStream(sigmundCertFile);
|
||||||
|
System.setOut(new PrintStream(sigmundCertOut));
|
||||||
|
PGPainlessCLI.execute("extract-cert");
|
||||||
|
sigmundKeyIn.close();
|
||||||
|
sigmundCertOut.close();
|
||||||
|
|
||||||
// sign message
|
// sign message
|
||||||
pipeBytesToStdin("Hello, World!\n".getBytes(StandardCharsets.UTF_8));
|
String msg = "Hello World!\n";
|
||||||
File signedMsg = pipeStdoutToFile("signed.asc");
|
ByteArrayInputStream msgIn = new ByteArrayInputStream(msg.getBytes(StandardCharsets.UTF_8));
|
||||||
assertSuccess(executeCommand("inline-sign", "--with-key-password=" + password.getAbsolutePath(),
|
System.setIn(msgIn);
|
||||||
sigmundKey.getAbsolutePath()));
|
OutputStream msgAscOut = new FileOutputStream(msgFile);
|
||||||
|
System.setOut(new PrintStream(msgAscOut));
|
||||||
|
PGPainlessCLI.execute("inline-sign",
|
||||||
|
"--with-key-password=" + passwordFile.getAbsolutePath(),
|
||||||
|
sigmundKeyFile.getAbsolutePath());
|
||||||
|
msgAscOut.close();
|
||||||
|
|
||||||
// verify message
|
File verifyFile = new File(tempDir, "verify.txt");
|
||||||
File verifyFile = nonExistentFile("verify.txt");
|
|
||||||
pipeFileToStdin(signedMsg);
|
|
||||||
assertSuccess(executeCommand("inline-verify", "--verifications-out", verifyFile.getAbsolutePath(),
|
|
||||||
sigmundCert.getAbsolutePath()));
|
|
||||||
|
|
||||||
String verifications = readStringFromFile(verifyFile);
|
FileInputStream msgAscIn = new FileInputStream(msgFile);
|
||||||
assertFalse(verifications.trim().isEmpty());
|
System.setIn(msgAscIn);
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
PrintStream pOut = new PrintStream(out);
|
||||||
|
System.setOut(pOut);
|
||||||
|
PGPainlessCLI.execute("inline-verify",
|
||||||
|
"--verifications-out", verifyFile.getAbsolutePath(),
|
||||||
|
sigmundCertFile.getAbsolutePath());
|
||||||
|
msgAscIn.close();
|
||||||
|
|
||||||
|
assertEquals(msg, out.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void after() {
|
||||||
|
System.setOut(originalSout);
|
||||||
|
// CHECKSTYLE:OFF
|
||||||
|
System.out.println(tempDir.getAbsolutePath());
|
||||||
|
// CHECKSTYLE:ON
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,18 +4,28 @@
|
||||||
|
|
||||||
package org.pgpainless.cli.misc;
|
package org.pgpainless.cli.misc;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
|
||||||
|
import org.bouncycastle.util.io.Streams;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.cli.commands.CLITest;
|
import org.pgpainless.cli.PGPainlessCLI;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.pgpainless.cli.TestUtils;
|
||||||
import sop.exception.SOPGPException;
|
import sop.exception.SOPGPException;
|
||||||
|
|
||||||
public class SignUsingPublicKeyBehaviorTest extends CLITest {
|
public class SignUsingPublicKeyBehaviorTest {
|
||||||
|
|
||||||
public static final String KEY_THAT_IS_A_CERT = "" +
|
public static final String KEY_THAT_IS_A_CERT = "" +
|
||||||
"-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
|
"-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
|
||||||
|
@ -79,24 +89,61 @@ public class SignUsingPublicKeyBehaviorTest extends CLITest {
|
||||||
"=oJQ2\n" +
|
"=oJQ2\n" +
|
||||||
"-----END PGP PUBLIC KEY BLOCK-----";
|
"-----END PGP PUBLIC KEY BLOCK-----";
|
||||||
|
|
||||||
public SignUsingPublicKeyBehaviorTest() {
|
|
||||||
super(LoggerFactory.getLogger(SignUsingPublicKeyBehaviorTest.class));
|
private static File tempDir;
|
||||||
|
private static PrintStream originalSout;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void prepare() throws IOException {
|
||||||
|
tempDir = TestUtils.createTempDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ExpectSystemExitWithStatus(SOPGPException.KeyCannotSign.EXIT_CODE)
|
||||||
public void testSignatureCreationAndVerification() throws IOException {
|
public void testSignatureCreationAndVerification() throws IOException {
|
||||||
|
originalSout = System.out;
|
||||||
|
InputStream originalIn = System.in;
|
||||||
|
|
||||||
// Write alice key to disc
|
// Write alice key to disc
|
||||||
File aliceKeyFile = writeFile("alice.key", KEY_THAT_IS_A_CERT);
|
File aliceKeyFile = new File(tempDir, "alice.key");
|
||||||
|
assertTrue(aliceKeyFile.createNewFile());
|
||||||
|
OutputStream aliceKeyOut = new FileOutputStream(aliceKeyFile);
|
||||||
|
Streams.pipeAll(new ByteArrayInputStream(KEY_THAT_IS_A_CERT.getBytes(StandardCharsets.UTF_8)), aliceKeyOut);
|
||||||
|
aliceKeyOut.close();
|
||||||
|
|
||||||
|
// Write alice pub key to disc
|
||||||
|
File aliceCertFile = new File(tempDir, "alice.pub");
|
||||||
|
assertTrue(aliceCertFile.createNewFile());
|
||||||
|
OutputStream aliceCertOut = new FileOutputStream(aliceCertFile);
|
||||||
|
Streams.pipeAll(new ByteArrayInputStream(KEY_THAT_IS_A_CERT.getBytes(StandardCharsets.UTF_8)), aliceCertOut);
|
||||||
|
aliceCertOut.close();
|
||||||
|
|
||||||
// Write test data to disc
|
// Write test data to disc
|
||||||
File dataFile = writeFile("data", "If privacy is outlawed, only outlaws will have privacy.\n");
|
String data = "If privacy is outlawed, only outlaws will have privacy.\n";
|
||||||
|
|
||||||
|
File dataFile = new File(tempDir, "data");
|
||||||
|
assertTrue(dataFile.createNewFile());
|
||||||
|
FileOutputStream dataOut = new FileOutputStream(dataFile);
|
||||||
|
Streams.pipeAll(new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8)), dataOut);
|
||||||
|
dataOut.close();
|
||||||
|
|
||||||
// Sign test data
|
// Sign test data
|
||||||
File sigFile = pipeStdoutToFile("sig.asc");
|
FileInputStream dataIn = new FileInputStream(dataFile);
|
||||||
pipeFileToStdin(dataFile);
|
System.setIn(dataIn);
|
||||||
assertEquals(SOPGPException.KeyCannotSign.EXIT_CODE,
|
File sigFile = new File(tempDir, "sig.asc");
|
||||||
executeCommand("sign", "--armor", aliceKeyFile.getAbsolutePath()));
|
assertTrue(sigFile.createNewFile());
|
||||||
|
FileOutputStream sigOut = new FileOutputStream(sigFile);
|
||||||
|
System.setOut(new PrintStream(sigOut));
|
||||||
|
PGPainlessCLI.main(new String[] {"sign", "--armor", aliceKeyFile.getAbsolutePath()});
|
||||||
|
|
||||||
assertTrue(readStringFromFile(sigFile).trim().isEmpty());
|
System.setIn(originalIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void after() {
|
||||||
|
System.setOut(originalSout);
|
||||||
|
// CHECKSTYLE:OFF
|
||||||
|
System.out.println(tempDir.getAbsolutePath());
|
||||||
|
// CHECKSTYLE:ON
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ dependencies {
|
||||||
// Bouncy Castle
|
// Bouncy Castle
|
||||||
api "org.bouncycastle:bcprov-jdk18on:$bouncyCastleVersion"
|
api "org.bouncycastle:bcprov-jdk18on:$bouncyCastleVersion"
|
||||||
api "org.bouncycastle:bcpg-jdk18on:$bouncyPgVersion"
|
api "org.bouncycastle:bcpg-jdk18on:$bouncyPgVersion"
|
||||||
api "org.bouncycastle:bcutil-jdk18on:$bouncyCastleVersion"
|
|
||||||
// api(files("../libs/bcpg-jdk18on-1.70.jar"))
|
// api(files("../libs/bcpg-jdk18on-1.70.jar"))
|
||||||
|
|
||||||
// @Nullable, @Nonnull annotations
|
// @Nullable, @Nonnull annotations
|
||||||
|
|
|
@ -32,7 +32,6 @@ import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.BCPGInputStream;
|
import org.bouncycastle.bcpg.BCPGInputStream;
|
||||||
import org.bouncycastle.openpgp.PGPCompressedData;
|
import org.bouncycastle.openpgp.PGPCompressedData;
|
||||||
|
@ -209,8 +208,8 @@ public class OpenPgpInputStream extends BufferedInputStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SignatureType.requireFromCode(sigType);
|
SignatureType.valueOf(sigType);
|
||||||
} catch (NoSuchElementException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,8 +236,8 @@ public class OpenPgpInputStream extends BufferedInputStream {
|
||||||
if (opsVersion == 3) {
|
if (opsVersion == 3) {
|
||||||
int opsSigType = bcpgIn.read();
|
int opsSigType = bcpgIn.read();
|
||||||
try {
|
try {
|
||||||
SignatureType.requireFromCode(opsSigType);
|
SignatureType.valueOf(opsSigType);
|
||||||
} catch (NoSuchElementException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int opsHashAlg = bcpgIn.read();
|
int opsHashAlg = bcpgIn.read();
|
||||||
|
|
|
@ -28,14 +28,7 @@ public class SignatureValidationException extends PGPException {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(rejections.size()).append(" rejected signatures:\n");
|
sb.append(rejections.size()).append(" rejected signatures:\n");
|
||||||
for (PGPSignature signature : rejections.keySet()) {
|
for (PGPSignature signature : rejections.keySet()) {
|
||||||
String typeString;
|
sb.append(SignatureType.valueOf(signature.getSignatureType())).append(' ')
|
||||||
SignatureType type = SignatureType.fromCode(signature.getSignatureType());
|
|
||||||
if (type == null) {
|
|
||||||
typeString = "0x" + Long.toHexString(signature.getSignatureType());
|
|
||||||
} else {
|
|
||||||
typeString = type.toString();
|
|
||||||
}
|
|
||||||
sb.append(typeString).append(' ')
|
|
||||||
.append(signature.getCreationTime()).append(": ")
|
.append(signature.getCreationTime()).append(": ")
|
||||||
.append(rejections.get(signature).getMessage()).append('\n');
|
.append(rejections.get(signature).getMessage()).append('\n');
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,11 +34,7 @@ public final class OpenPgpKeyAttributeUtil {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SignatureType signatureType = SignatureType.fromCode(signature.getSignatureType());
|
SignatureType signatureType = SignatureType.valueOf(signature.getSignatureType());
|
||||||
if (signatureType == null) {
|
|
||||||
// unknown signature type
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (signatureType == SignatureType.POSITIVE_CERTIFICATION
|
if (signatureType == SignatureType.POSITIVE_CERTIFICATION
|
||||||
|| signatureType == SignatureType.GENERIC_CERTIFICATION) {
|
|| signatureType == SignatureType.GENERIC_CERTIFICATION) {
|
||||||
int[] hashAlgos = signature.getHashedSubPackets().getPreferredHashAlgorithms();
|
int[] hashAlgos = signature.getHashedSubPackets().getPreferredHashAlgorithms();
|
||||||
|
@ -75,8 +71,8 @@ public final class OpenPgpKeyAttributeUtil {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SignatureType signatureType = SignatureType.fromCode(signature.getSignatureType());
|
SignatureType signatureType = SignatureType.valueOf(signature.getSignatureType());
|
||||||
if (signatureType == null || signatureType != SignatureType.POSITIVE_CERTIFICATION
|
if (signatureType != SignatureType.POSITIVE_CERTIFICATION
|
||||||
&& signatureType != SignatureType.GENERIC_CERTIFICATION) {
|
&& signatureType != SignatureType.GENERIC_CERTIFICATION) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,8 +170,7 @@ enum class SignatureType(val code: Int) {
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun isRevocationSignature(signatureType: Int): Boolean {
|
fun isRevocationSignature(signatureType: Int): Boolean {
|
||||||
val sigType = fromCode(signatureType)
|
return isRevocationSignature(valueOf(signatureType))
|
||||||
return sigType?.let { isRevocationSignature(it) } ?: false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
|
|
@ -77,8 +77,7 @@ fun PGPSignature.wasIssuedBy(key: PGPPublicKey): Boolean = wasIssuedBy(OpenPgpFi
|
||||||
/** Return true, if this signature is a hard revocation. */
|
/** Return true, if this signature is a hard revocation. */
|
||||||
val PGPSignature.isHardRevocation
|
val PGPSignature.isHardRevocation
|
||||||
get() =
|
get() =
|
||||||
when (SignatureType.fromCode(signatureType)) {
|
when (SignatureType.requireFromCode(signatureType)) {
|
||||||
null -> false
|
|
||||||
SignatureType.KEY_REVOCATION,
|
SignatureType.KEY_REVOCATION,
|
||||||
SignatureType.SUBKEY_REVOCATION,
|
SignatureType.SUBKEY_REVOCATION,
|
||||||
SignatureType.CERTIFICATION_REVOCATION -> {
|
SignatureType.CERTIFICATION_REVOCATION -> {
|
||||||
|
@ -105,4 +104,4 @@ val PGPSignature.signatureHashAlgorithm: HashAlgorithm
|
||||||
get() = HashAlgorithm.requireFromId(hashAlgorithm)
|
get() = HashAlgorithm.requireFromId(hashAlgorithm)
|
||||||
|
|
||||||
fun PGPSignature.isOfType(type: SignatureType): Boolean =
|
fun PGPSignature.isOfType(type: SignatureType): Boolean =
|
||||||
SignatureType.fromCode(signatureType) == type
|
SignatureType.requireFromCode(signatureType) == type
|
||||||
|
|
|
@ -4,11 +4,7 @@
|
||||||
|
|
||||||
package org.pgpainless.decryption_verification
|
package org.pgpainless.decryption_verification
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.AEADEncDataPacket
|
|
||||||
import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket
|
|
||||||
import org.bouncycastle.openpgp.PGPPrivateKey
|
import org.bouncycastle.openpgp.PGPPrivateKey
|
||||||
import org.bouncycastle.openpgp.PGPSessionKey
|
|
||||||
import org.bouncycastle.openpgp.operator.PGPDataDecryptor
|
|
||||||
import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory
|
import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory
|
||||||
import org.bouncycastle.util.encoders.Base64
|
import org.bouncycastle.util.encoders.Base64
|
||||||
import org.pgpainless.key.SubkeyIdentifier
|
import org.pgpainless.key.SubkeyIdentifier
|
||||||
|
@ -25,34 +21,16 @@ import org.pgpainless.key.SubkeyIdentifier
|
||||||
class CachingBcPublicKeyDataDecryptorFactory(
|
class CachingBcPublicKeyDataDecryptorFactory(
|
||||||
privateKey: PGPPrivateKey,
|
privateKey: PGPPrivateKey,
|
||||||
override val subkeyIdentifier: SubkeyIdentifier
|
override val subkeyIdentifier: SubkeyIdentifier
|
||||||
) : CustomPublicKeyDataDecryptorFactory() {
|
) : BcPublicKeyDataDecryptorFactory(privateKey), CustomPublicKeyDataDecryptorFactory {
|
||||||
|
|
||||||
private val decryptorFactory: BcPublicKeyDataDecryptorFactory =
|
|
||||||
BcPublicKeyDataDecryptorFactory(privateKey)
|
|
||||||
private val cachedSessions: MutableMap<String, ByteArray> = mutableMapOf()
|
private val cachedSessions: MutableMap<String, ByteArray> = mutableMapOf()
|
||||||
|
|
||||||
override fun createDataDecryptor(p0: Boolean, p1: Int, p2: ByteArray?): PGPDataDecryptor {
|
|
||||||
return decryptorFactory.createDataDecryptor(p0, p1, p2)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createDataDecryptor(p0: AEADEncDataPacket?, p1: PGPSessionKey?): PGPDataDecryptor {
|
|
||||||
return decryptorFactory.createDataDecryptor(p0, p1)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createDataDecryptor(
|
|
||||||
p0: SymmetricEncIntegrityPacket?,
|
|
||||||
p1: PGPSessionKey?
|
|
||||||
): PGPDataDecryptor {
|
|
||||||
return decryptorFactory.createDataDecryptor(p0, p1)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun recoverSessionData(
|
override fun recoverSessionData(
|
||||||
keyAlgorithm: Int,
|
keyAlgorithm: Int,
|
||||||
secKeyData: Array<out ByteArray>,
|
secKeyData: Array<out ByteArray>
|
||||||
pkeskVersion: Int
|
|
||||||
): ByteArray =
|
): ByteArray =
|
||||||
lookupSessionKeyData(secKeyData)
|
lookupSessionKeyData(secKeyData)
|
||||||
?: costlyRecoverSessionData(keyAlgorithm, secKeyData, pkeskVersion).also {
|
?: costlyRecoverSessionData(keyAlgorithm, secKeyData).also {
|
||||||
cacheSessionKeyData(secKeyData, it)
|
cacheSessionKeyData(secKeyData, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,9 +39,8 @@ class CachingBcPublicKeyDataDecryptorFactory(
|
||||||
|
|
||||||
private fun costlyRecoverSessionData(
|
private fun costlyRecoverSessionData(
|
||||||
keyAlgorithm: Int,
|
keyAlgorithm: Int,
|
||||||
secKeyData: Array<out ByteArray>,
|
secKeyData: Array<out ByteArray>
|
||||||
pkeskVersion: Int
|
): ByteArray = super.recoverSessionData(keyAlgorithm, secKeyData)
|
||||||
): ByteArray = decryptorFactory.recoverSessionData(keyAlgorithm, secKeyData, pkeskVersion)
|
|
||||||
|
|
||||||
private fun cacheSessionKeyData(secKeyData: Array<out ByteArray>, sessionKey: ByteArray) {
|
private fun cacheSessionKeyData(secKeyData: Array<out ByteArray>, sessionKey: ByteArray) {
|
||||||
cachedSessions[toKey(secKeyData)] = sessionKey.clone()
|
cachedSessions[toKey(secKeyData)] = sessionKey.clone()
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
package org.pgpainless.decryption_verification
|
package org.pgpainless.decryption_verification
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.operator.AbstractPublicKeyDataDecryptorFactory
|
|
||||||
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory
|
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory
|
||||||
import org.pgpainless.key.SubkeyIdentifier
|
import org.pgpainless.key.SubkeyIdentifier
|
||||||
|
|
||||||
|
@ -15,7 +14,7 @@ import org.pgpainless.key.SubkeyIdentifier
|
||||||
*
|
*
|
||||||
* @see [ConsumerOptions.addCustomDecryptorFactory]
|
* @see [ConsumerOptions.addCustomDecryptorFactory]
|
||||||
*/
|
*/
|
||||||
abstract class CustomPublicKeyDataDecryptorFactory : AbstractPublicKeyDataDecryptorFactory() {
|
interface CustomPublicKeyDataDecryptorFactory : PublicKeyDataDecryptorFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identifier for the subkey for which this particular [CustomPublicKeyDataDecryptorFactory] is
|
* Identifier for the subkey for which this particular [CustomPublicKeyDataDecryptorFactory] is
|
||||||
|
@ -23,5 +22,5 @@ abstract class CustomPublicKeyDataDecryptorFactory : AbstractPublicKeyDataDecryp
|
||||||
*
|
*
|
||||||
* @return subkey identifier
|
* @return subkey identifier
|
||||||
*/
|
*/
|
||||||
abstract val subkeyIdentifier: SubkeyIdentifier
|
val subkeyIdentifier: SubkeyIdentifier
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,17 +29,11 @@ class HardwareSecurity {
|
||||||
* @param keyId id of the key
|
* @param keyId id of the key
|
||||||
* @param keyAlgorithm algorithm
|
* @param keyAlgorithm algorithm
|
||||||
* @param sessionKeyData encrypted session key
|
* @param sessionKeyData encrypted session key
|
||||||
* @param pkeskVersion version of the Public-Key-Encrypted-Session-Key packet (3 or 6)
|
|
||||||
* @return decrypted session key
|
* @return decrypted session key
|
||||||
* @throws HardwareSecurityException exception
|
* @throws HardwareSecurityException exception
|
||||||
*/
|
*/
|
||||||
@Throws(HardwareSecurityException::class)
|
@Throws(HardwareSecurityException::class)
|
||||||
fun decryptSessionKey(
|
fun decryptSessionKey(keyId: Long, keyAlgorithm: Int, sessionKeyData: ByteArray): ByteArray
|
||||||
keyId: Long,
|
|
||||||
keyAlgorithm: Int,
|
|
||||||
sessionKeyData: ByteArray,
|
|
||||||
pkeskVersion: Int
|
|
||||||
): ByteArray
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,7 +44,7 @@ class HardwareSecurity {
|
||||||
class HardwareDataDecryptorFactory(
|
class HardwareDataDecryptorFactory(
|
||||||
override val subkeyIdentifier: SubkeyIdentifier,
|
override val subkeyIdentifier: SubkeyIdentifier,
|
||||||
private val callback: DecryptionCallback,
|
private val callback: DecryptionCallback,
|
||||||
) : CustomPublicKeyDataDecryptorFactory() {
|
) : CustomPublicKeyDataDecryptorFactory {
|
||||||
|
|
||||||
// luckily we can instantiate the BcPublicKeyDataDecryptorFactory with null as argument.
|
// luckily we can instantiate the BcPublicKeyDataDecryptorFactory with null as argument.
|
||||||
private val factory: PublicKeyDataDecryptorFactory = BcPublicKeyDataDecryptorFactory(null)
|
private val factory: PublicKeyDataDecryptorFactory = BcPublicKeyDataDecryptorFactory(null)
|
||||||
|
@ -79,12 +73,10 @@ class HardwareSecurity {
|
||||||
|
|
||||||
override fun recoverSessionData(
|
override fun recoverSessionData(
|
||||||
keyAlgorithm: Int,
|
keyAlgorithm: Int,
|
||||||
secKeyData: Array<out ByteArray>,
|
secKeyData: Array<out ByteArray>
|
||||||
pkeskVersion: Int
|
|
||||||
): ByteArray {
|
): ByteArray {
|
||||||
return try {
|
return try {
|
||||||
callback.decryptSessionKey(
|
callback.decryptSessionKey(subkeyIdentifier.subkeyId, keyAlgorithm, secKeyData[0])
|
||||||
subkeyIdentifier.subkeyId, keyAlgorithm, secKeyData[0], pkeskVersion)
|
|
||||||
} catch (e: HardwareSecurityException) {
|
} catch (e: HardwareSecurityException) {
|
||||||
throw PGPException("Hardware-backed decryption failed.", e)
|
throw PGPException("Hardware-backed decryption failed.", e)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ class CRLFGeneratorStream(private val crlfOut: OutputStream, encoding: StreamEnc
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
if (!isBinary && lastB == '\r'.code) {
|
if (!isBinary && lastB == 'r'.code) {
|
||||||
crlfOut.write('\n'.code)
|
crlfOut.write('\n'.code)
|
||||||
}
|
}
|
||||||
crlfOut.close()
|
crlfOut.close()
|
||||||
|
|
|
@ -45,7 +45,7 @@ class KeyRingBuilder : KeyRingBuilderInterface<KeyRingBuilder> {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addUserId(userId: CharSequence): KeyRingBuilder = apply {
|
override fun addUserId(userId: CharSequence): KeyRingBuilder = apply {
|
||||||
userIds[userId.toString()] = null
|
userIds[userId.toString().trim()] = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addUserId(userId: ByteArray): KeyRingBuilder =
|
override fun addUserId(userId: ByteArray): KeyRingBuilder =
|
||||||
|
|
|
@ -67,9 +67,11 @@ abstract class KeyAccessor(protected val info: KeyRingInfo, protected val key: S
|
||||||
info.getLatestUserIdCertification(userId).let { if (it != null) return it }
|
info.getLatestUserIdCertification(userId).let { if (it != null) return it }
|
||||||
}
|
}
|
||||||
|
|
||||||
return info.getCurrentSubkeyBindingSignature(key.subkeyId)
|
if (info.latestDirectKeySelfSignature != null) {
|
||||||
?: throw NoSuchElementException(
|
return info.latestDirectKeySelfSignature
|
||||||
"Key does not carry acceptable self-signature signature.")
|
}
|
||||||
|
|
||||||
|
return info.getCurrentSubkeyBindingSignature(key.subkeyId)!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,8 +172,11 @@ class KeyRingInfo(
|
||||||
primaryUserIdCertification?.let { getKeyExpirationTimeAsDate(it, publicKey) }
|
primaryUserIdCertification?.let { getKeyExpirationTimeAsDate(it, publicKey) }
|
||||||
|
|
||||||
if (latestDirectKeySelfSignature == null && primaryUserIdCertification == null) {
|
if (latestDirectKeySelfSignature == null && primaryUserIdCertification == null) {
|
||||||
|
/*
|
||||||
throw NoSuchElementException(
|
throw NoSuchElementException(
|
||||||
"No direct-key signature and no user-id signature found.")
|
"No direct-key signature and no user-id signature found.")
|
||||||
|
*/
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
if (directKeyExpirationDate != null && userIdExpirationDate == null) {
|
if (directKeyExpirationDate != null && userIdExpirationDate == null) {
|
||||||
return directKeyExpirationDate
|
return directKeyExpirationDate
|
||||||
|
@ -402,7 +405,7 @@ class KeyRingInfo(
|
||||||
.plus(signatures.userIdRevocations.values)
|
.plus(signatures.userIdRevocations.values)
|
||||||
.plus(signatures.subkeyBindings.values)
|
.plus(signatures.subkeyBindings.values)
|
||||||
.plus(signatures.subkeyRevocations.values)
|
.plus(signatures.subkeyRevocations.values)
|
||||||
.maxByOrNull { it.creationTime }
|
.maxByOrNull { creationDate }
|
||||||
/**
|
/**
|
||||||
* Return the creation time of the latest added subkey.
|
* Return the creation time of the latest added subkey.
|
||||||
*
|
*
|
||||||
|
|
|
@ -478,7 +478,7 @@ class SecretKeyRingEditor(
|
||||||
val prevBinding =
|
val prevBinding =
|
||||||
inspectKeyRing(secretKeyRing).getCurrentSubkeyBindingSignature(keyId)
|
inspectKeyRing(secretKeyRing).getCurrentSubkeyBindingSignature(keyId)
|
||||||
?: throw NoSuchElementException(
|
?: throw NoSuchElementException(
|
||||||
"Previous subkey binding signature for ${keyId.openPgpKeyId()} MUST NOT be null.")
|
"Previous subkey binding signaure for ${keyId.openPgpKeyId()} MUST NOT be null.")
|
||||||
val bindingSig = reissueSubkeyBindingSignature(subkey, expiration, protector, prevBinding)
|
val bindingSig = reissueSubkeyBindingSignature(subkey, expiration, protector, prevBinding)
|
||||||
secretKeyRing = injectCertification(secretKeyRing, subkey, bindingSig)
|
secretKeyRing = injectCertification(secretKeyRing, subkey, bindingSig)
|
||||||
}
|
}
|
||||||
|
@ -569,10 +569,9 @@ class SecretKeyRingEditor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sanitizeUserId(userId: CharSequence): CharSequence =
|
private fun sanitizeUserId(userId: CharSequence): CharSequence =
|
||||||
// I'm not sure, what kind of sanitization is needed.
|
// TODO: Further research how to sanitize user IDs.
|
||||||
// Newlines are allowed, they just need to be escaped when emitted in an ASCII armor header
|
// e.g. what about newlines?
|
||||||
// Trailing/Leading whitespace is also fine.
|
userId.toString().trim()
|
||||||
userId.toString()
|
|
||||||
|
|
||||||
private fun callbackFromRevocationAttributes(attributes: RevocationAttributes?) =
|
private fun callbackFromRevocationAttributes(attributes: RevocationAttributes?) =
|
||||||
object : RevocationSignatureSubpackets.Callback {
|
object : RevocationSignatureSubpackets.Callback {
|
||||||
|
|
|
@ -52,7 +52,7 @@ class RevocationSignatureBuilder : AbstractSignatureBuilder<RevocationSignatureB
|
||||||
require(revokeeKey.isMasterKey) {
|
require(revokeeKey.isMasterKey) {
|
||||||
"Signature type is KEY_REVOCATION, but provided revokee does not appear to be a primary key."
|
"Signature type is KEY_REVOCATION, but provided revokee does not appear to be a primary key."
|
||||||
}
|
}
|
||||||
it.generateCertification(revokeeKey)
|
it.generateCertification(publicSigningKey)
|
||||||
} else {
|
} else {
|
||||||
it.generateCertification(publicSigningKey, revokeeKey)
|
it.generateCertification(publicSigningKey, revokeeKey)
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,8 +235,7 @@ abstract class SignatureValidator {
|
||||||
signature: PGPSignature,
|
signature: PGPSignature,
|
||||||
policy: Policy
|
policy: Policy
|
||||||
): Policy.HashAlgorithmPolicy {
|
): Policy.HashAlgorithmPolicy {
|
||||||
return when (SignatureType.fromCode(signature.signatureType)) {
|
return when (SignatureType.requireFromCode(signature.signatureType)) {
|
||||||
null -> policy.certificationSignatureHashAlgorithmPolicy
|
|
||||||
SignatureType.CERTIFICATION_REVOCATION,
|
SignatureType.CERTIFICATION_REVOCATION,
|
||||||
SignatureType.KEY_REVOCATION,
|
SignatureType.KEY_REVOCATION,
|
||||||
SignatureType.SUBKEY_REVOCATION -> policy.revocationSignatureHashAlgorithmPolicy
|
SignatureType.SUBKEY_REVOCATION -> policy.revocationSignatureHashAlgorithmPolicy
|
||||||
|
@ -599,8 +598,7 @@ abstract class SignatureValidator {
|
||||||
if (signatureType.none { signature.isOfType(it) }) {
|
if (signatureType.none { signature.isOfType(it) }) {
|
||||||
throw SignatureValidationException(
|
throw SignatureValidationException(
|
||||||
"Signature is of type" +
|
"Signature is of type" +
|
||||||
" ${SignatureType.fromCode(signature.signatureType) ?:
|
" ${SignatureType.requireFromCode(signature.signatureType)}, " +
|
||||||
("0x" + signature.signatureType.toString(16))}, " +
|
|
||||||
"while only ${signatureType.contentToString()} are allowed here.")
|
"while only ${signatureType.contentToString()} are allowed here.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -690,7 +688,7 @@ abstract class SignatureValidator {
|
||||||
}
|
}
|
||||||
if (notAfter != null && timestamp > notAfter) {
|
if (notAfter != null && timestamp > notAfter) {
|
||||||
throw SignatureValidationException(
|
throw SignatureValidationException(
|
||||||
"Signature was made after the latest allowed signature creation time." +
|
"Signature was made before the latest allowed signature creation time." +
|
||||||
" Created: ${timestamp.formatUTC()}," +
|
" Created: ${timestamp.formatUTC()}," +
|
||||||
" latest allowed: ${notAfter.formatUTC()}")
|
" latest allowed: ${notAfter.formatUTC()}")
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,13 +59,12 @@ class SignatureVerifier {
|
||||||
policy: Policy,
|
policy: Policy,
|
||||||
referenceTime: Date
|
referenceTime: Date
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val type = SignatureType.fromCode(signature.signatureType)
|
val type = SignatureType.requireFromCode(signature.signatureType)
|
||||||
return when (type) {
|
return when (type) {
|
||||||
SignatureType.GENERIC_CERTIFICATION,
|
SignatureType.GENERIC_CERTIFICATION,
|
||||||
SignatureType.NO_CERTIFICATION,
|
SignatureType.NO_CERTIFICATION,
|
||||||
SignatureType.CASUAL_CERTIFICATION,
|
SignatureType.CASUAL_CERTIFICATION,
|
||||||
SignatureType.POSITIVE_CERTIFICATION,
|
SignatureType.POSITIVE_CERTIFICATION ->
|
||||||
null ->
|
|
||||||
verifyUserIdCertification(
|
verifyUserIdCertification(
|
||||||
userId, signature, signingKey, keyWithUserId, policy, referenceTime)
|
userId, signature, signingKey, keyWithUserId, policy, referenceTime)
|
||||||
SignatureType.CERTIFICATION_REVOCATION ->
|
SignatureType.CERTIFICATION_REVOCATION ->
|
||||||
|
|
|
@ -247,9 +247,7 @@ class ArmorUtils {
|
||||||
.add(OpenPgpFingerprint.of(publicKey).prettyPrint())
|
.add(OpenPgpFingerprint.of(publicKey).prettyPrint())
|
||||||
// Primary / First User ID
|
// Primary / First User ID
|
||||||
(primary ?: first)?.let {
|
(primary ?: first)?.let {
|
||||||
headerMap
|
headerMap.getOrPut(HEADER_COMMENT) { mutableSetOf() }.add(it)
|
||||||
.getOrPut(HEADER_COMMENT) { mutableSetOf() }
|
|
||||||
.add(it.replace("\n", "\\n").replace("\r", "\\r"))
|
|
||||||
}
|
}
|
||||||
// X-1 further identities
|
// X-1 further identities
|
||||||
when (userIds.size) {
|
when (userIds.size) {
|
||||||
|
|
|
@ -11,9 +11,14 @@ import org.bouncycastle.util.Arrays
|
||||||
*
|
*
|
||||||
* @param chars may be null for empty passwords.
|
* @param chars may be null for empty passwords.
|
||||||
*/
|
*/
|
||||||
class Passphrase(private val chars: CharArray?) {
|
class Passphrase(chars: CharArray?) {
|
||||||
private val lock = Any()
|
private val lock = Any()
|
||||||
private var valid = true
|
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
|
* 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()
|
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 {
|
companion object {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package org.pgpainless.algorithm;
|
package org.pgpainless.algorithm;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -30,6 +31,6 @@ public class SignatureTypeTest {
|
||||||
assertFalse(SignatureType.isRevocationSignature(SignatureType.STANDALONE.getCode()));
|
assertFalse(SignatureType.isRevocationSignature(SignatureType.STANDALONE.getCode()));
|
||||||
assertFalse(SignatureType.isRevocationSignature(SignatureType.TIMESTAMP.getCode()));
|
assertFalse(SignatureType.isRevocationSignature(SignatureType.TIMESTAMP.getCode()));
|
||||||
|
|
||||||
assertFalse(SignatureType.isRevocationSignature(-3));
|
assertThrows(IllegalArgumentException.class, () -> SignatureType.isRevocationSignature(-3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
||||||
import org.bouncycastle.bcpg.CompressionAlgorithmTags;
|
import org.bouncycastle.bcpg.CompressionAlgorithmTags;
|
||||||
|
@ -31,9 +30,6 @@ import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder;
|
||||||
import org.bouncycastle.util.io.Streams;
|
import org.bouncycastle.util.io.Streams;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.algorithm.DocumentSignatureType;
|
import org.pgpainless.algorithm.DocumentSignatureType;
|
||||||
import org.pgpainless.algorithm.HashAlgorithm;
|
import org.pgpainless.algorithm.HashAlgorithm;
|
||||||
|
@ -292,9 +288,11 @@ public class CanonicalizedDataEncryptionTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@MethodSource("resultOfDecryptionIsCRLFEncodedArguments")
|
public void resultOfDecryptionIsCRLFEncoded() throws PGPException, IOException {
|
||||||
public void resultOfDecryptionIsCRLFEncoded(String before, String after) throws PGPException, IOException {
|
String before = "Foo\nBar!\n";
|
||||||
|
String after = "Foo\r\nBar!\r\n";
|
||||||
|
|
||||||
String encrypted = encryptAndSign(before, DocumentSignatureType.BINARY_DOCUMENT, StreamEncoding.TEXT, true);
|
String encrypted = encryptAndSign(before, DocumentSignatureType.BINARY_DOCUMENT, StreamEncoding.TEXT, true);
|
||||||
|
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(encrypted.getBytes(StandardCharsets.UTF_8));
|
ByteArrayInputStream in = new ByteArrayInputStream(encrypted.getBytes(StandardCharsets.UTF_8));
|
||||||
|
@ -311,16 +309,6 @@ public class CanonicalizedDataEncryptionTest {
|
||||||
assertArrayEquals(after.getBytes(StandardCharsets.UTF_8), decrypted.toByteArray());
|
assertArrayEquals(after.getBytes(StandardCharsets.UTF_8), decrypted.toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Stream<Arguments> resultOfDecryptionIsCRLFEncodedArguments() {
|
|
||||||
return Stream.of(
|
|
||||||
Arguments.of("foo", "foo"),
|
|
||||||
Arguments.of("rrr", "rrr"),
|
|
||||||
Arguments.of("Foo\nBar!\n", "Foo\r\nBar!\r\n"),
|
|
||||||
Arguments.of("Foo\rBar!\r", "Foo\r\nBar!\r\n"),
|
|
||||||
Arguments.of("Foo\r\nBar!\r\n", "Foo\r\nBar!\r\n")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resultOfDecryptionIsNotCRLFEncoded() throws PGPException, IOException {
|
public void resultOfDecryptionIsNotCRLFEncoded() throws PGPException, IOException {
|
||||||
String beforeAndAfter = "Foo\nBar!\n";
|
String beforeAndAfter = "Foo\nBar!\n";
|
||||||
|
|
|
@ -55,14 +55,14 @@ public class CustomPublicKeyDataDecryptorFactoryTest {
|
||||||
|
|
||||||
HardwareSecurity.DecryptionCallback hardwareDecryptionCallback = new HardwareSecurity.DecryptionCallback() {
|
HardwareSecurity.DecryptionCallback hardwareDecryptionCallback = new HardwareSecurity.DecryptionCallback() {
|
||||||
@Override
|
@Override
|
||||||
public byte[] decryptSessionKey(long keyId, int keyAlgorithm, byte[] sessionKeyData, int pkeskVersion)
|
public byte[] decryptSessionKey(long keyId, int keyAlgorithm, byte[] sessionKeyData)
|
||||||
throws HardwareSecurity.HardwareSecurityException {
|
throws HardwareSecurity.HardwareSecurityException {
|
||||||
// Emulate hardware decryption.
|
// Emulate hardware decryption.
|
||||||
try {
|
try {
|
||||||
PGPSecretKey decryptionKey = secretKey.getSecretKey(encryptionKey.getKeyID());
|
PGPSecretKey decryptionKey = secretKey.getSecretKey(encryptionKey.getKeyID());
|
||||||
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(decryptionKey, Passphrase.emptyPassphrase());
|
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(decryptionKey, Passphrase.emptyPassphrase());
|
||||||
PublicKeyDataDecryptorFactory internal = new BcPublicKeyDataDecryptorFactory(privateKey);
|
PublicKeyDataDecryptorFactory internal = new BcPublicKeyDataDecryptorFactory(privateKey);
|
||||||
return internal.recoverSessionData(keyAlgorithm, new byte[][] {sessionKeyData}, pkeskVersion);
|
return internal.recoverSessionData(keyAlgorithm, new byte[][] {sessionKeyData});
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
throw new HardwareSecurity.HardwareSecurityException();
|
throw new HardwareSecurity.HardwareSecurityException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class MessageMetadataTest {
|
||||||
@Test
|
@Test
|
||||||
public void processTestMessage_COMP_ENC_ENC_LIT() {
|
public void processTestMessage_COMP_ENC_ENC_LIT() {
|
||||||
// Note: COMP of ENC does not make sense, since ENC is indistinguishable from randomness
|
// Note: COMP of ENC does not make sense, since ENC is indistinguishable from randomness
|
||||||
// and randomness cannot be compressed.
|
// and randomness cannot be encrypted.
|
||||||
// For the sake of testing though, this is okay.
|
// For the sake of testing though, this is okay.
|
||||||
MessageMetadata.Message message = new MessageMetadata.Message();
|
MessageMetadata.Message message = new MessageMetadata.Message();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.key
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
import org.bouncycastle.openpgp.PGPPublicKey
|
||||||
|
import org.bouncycastle.openpgp.PGPPublicKeyRing
|
||||||
|
import org.bouncycastle.openpgp.PGPSecretKeyRing
|
||||||
|
import org.bouncycastle.util.io.Streams
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.pgpainless.PGPainless
|
||||||
|
import org.pgpainless.algorithm.KeyFlag
|
||||||
|
import org.pgpainless.decryption_verification.ConsumerOptions
|
||||||
|
import org.pgpainless.encryption_signing.EncryptionOptions
|
||||||
|
import org.pgpainless.encryption_signing.ProducerOptions
|
||||||
|
import org.pgpainless.encryption_signing.SigningOptions
|
||||||
|
import org.pgpainless.key.generation.KeySpec
|
||||||
|
import org.pgpainless.key.generation.type.KeyType
|
||||||
|
import org.pgpainless.key.generation.type.eddsa_legacy.EdDSALegacyCurve
|
||||||
|
import org.pgpainless.key.generation.type.xdh_legacy.XDHLegacySpec
|
||||||
|
import org.pgpainless.key.protection.SecretKeyRingProtector
|
||||||
|
|
||||||
|
class KeyWithoutSelfSigsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun signAndVerify() {
|
||||||
|
val key = PGPainless.readKeyRing().secretKeyRing(KEY)
|
||||||
|
val cert = PGPainless.extractCertificate(key!!)
|
||||||
|
|
||||||
|
val ciphertextOut = ByteArrayOutputStream()
|
||||||
|
val encryptionStream =
|
||||||
|
PGPainless.encryptAndOrSign()
|
||||||
|
.onOutputStream(ciphertextOut)
|
||||||
|
.withOptions(
|
||||||
|
ProducerOptions.signAndEncrypt(
|
||||||
|
EncryptionOptions.encryptCommunications().addRecipient(cert),
|
||||||
|
SigningOptions.get()
|
||||||
|
.addSignature(SecretKeyRingProtector.unprotectedKeys(), key)))
|
||||||
|
encryptionStream.write("Hello, World!\n".toByteArray())
|
||||||
|
encryptionStream.close()
|
||||||
|
|
||||||
|
val plaintextOut = ByteArrayOutputStream()
|
||||||
|
val decryptionStream =
|
||||||
|
PGPainless.decryptAndOrVerify()
|
||||||
|
.onInputStream(ciphertextOut.toByteArray().inputStream())
|
||||||
|
.withOptions(
|
||||||
|
ConsumerOptions.get()
|
||||||
|
.addVerificationCert(cert)
|
||||||
|
.addDecryptionKey(key, SecretKeyRingProtector.unprotectedKeys()))
|
||||||
|
Streams.pipeAll(decryptionStream, plaintextOut)
|
||||||
|
decryptionStream.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateKey() {
|
||||||
|
val key =
|
||||||
|
PGPainless.buildKeyRing()
|
||||||
|
.setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519)))
|
||||||
|
.addSubkey(
|
||||||
|
KeySpec.getBuilder(
|
||||||
|
KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.SIGN_DATA))
|
||||||
|
.addSubkey(
|
||||||
|
KeySpec.getBuilder(
|
||||||
|
KeyType.XDH_LEGACY(XDHLegacySpec._X25519),
|
||||||
|
KeyFlag.ENCRYPT_STORAGE,
|
||||||
|
KeyFlag.ENCRYPT_COMMS))
|
||||||
|
.build()
|
||||||
|
.let {
|
||||||
|
var cert = PGPainless.extractCertificate(it)
|
||||||
|
cert =
|
||||||
|
PGPPublicKeyRing(
|
||||||
|
buildList {
|
||||||
|
val iterator = cert.publicKeys
|
||||||
|
val primaryKey = iterator.next()
|
||||||
|
add(
|
||||||
|
PGPPublicKey.removeCertification(
|
||||||
|
primaryKey, primaryKey.signatures.next()))
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
add(iterator.next())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
PGPSecretKeyRing.replacePublicKeys(it, cert)
|
||||||
|
}
|
||||||
|
println(PGPainless.asciiArmor(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
const val KEY =
|
||||||
|
"-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
||||||
|
"Version: PGPainless\n" +
|
||||||
|
"Comment: DA3E CC77 1CD6 46F0 C6C4 4FDA 86A3 7B22 7802 2FC7\n" +
|
||||||
|
"\n" +
|
||||||
|
"lFgEZUuWuhYJKwYBBAHaRw8BAQdAuXfarON/+UG1qwhVy4/VCYuEb9iLFLb8KGQt\n" +
|
||||||
|
"KfX4Se0AAQDgqGHsb2M43F+6wK5Hla+oZzFkTUsBx8HMpRx2yeQT6hFAnFgEZUuW\n" +
|
||||||
|
"uhYJKwYBBAHaRw8BAQdAx0OHISLtekltdUVGGrG/Gs3asc/jG/nqCkBEZ5uyELwA\n" +
|
||||||
|
"AP0faf8bprP3fj248/NacfynKEVnjzc1gocfhGiWrnVgAxC1iNUEGBYKAH0FAmVL\n" +
|
||||||
|
"lroCngECmwIFFgIDAQAECwkIBwUVCgkIC18gBBkWCgAGBQJlS5a6AAoJED9gFx9r\n" +
|
||||||
|
"B25syqoA/0JR3Zcs6fHQ0jW7+u6330SD5h8WvG78IKsE6AfChBLXAP4hlXGidztq\n" +
|
||||||
|
"5sOHEQvXD2KPCHEJ6MuQ+rbNSSf0fQhgDwAKCRCGo3sieAIvxzmIAP9+9vRoevUM\n" +
|
||||||
|
"luQhZzQ7DgYqTCyNkeq2cpVgOfa0lyVDgwEApwrd5DlU3GorGHAQHFS6jhw1IOoG\n" +
|
||||||
|
"FGQ3zpWaOXd7XwKcXQRlS5a6EgorBgEEAZdVAQUBAQdAZIY7ISyNzp0oMoK0dgb8\n" +
|
||||||
|
"dX6t/i4Uh+l0jnxM0Z1dEB8DAQgHAAD/fhL5dzdJQ7hFhr78AmDEZKFE4txZFPvd\n" +
|
||||||
|
"ZVFvIWTthFgQ5Ih1BBgWCgAdBQJlS5a6Ap4BApsMBRYCAwEABAsJCAcFFQoJCAsA\n" +
|
||||||
|
"CgkQhqN7IngCL8cIGgEAzydjTfKvdrTvzXXu97j8TAoOxk89QnLqsM6BU0VsVmkA\n" +
|
||||||
|
"/1IzH+PXgPPW9ff+elxTi2NWmK+P033P6i5b5Jdf41YD\n" +
|
||||||
|
"=GBVS\n" +
|
||||||
|
"-----END PGP PRIVATE KEY BLOCK-----"
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,7 @@ To start using pgpainless-sop in your code, include the following lines in your
|
||||||
...
|
...
|
||||||
dependencies {
|
dependencies {
|
||||||
...
|
...
|
||||||
implementation "org.pgpainless:pgpainless-sop:1.7.6"
|
implementation "org.pgpainless:pgpainless-sop:1.7.1"
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ dependencies {
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.pgpainless</groupId>
|
<groupId>org.pgpainless</groupId>
|
||||||
<artifactId>pgpainless-sop</artifactId>
|
<artifactId>pgpainless-sop</artifactId>
|
||||||
<version>1.7.6</version>
|
<version>1.7.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
...
|
...
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -67,7 +67,7 @@ byte[] encrypted = sop.encrypt()
|
||||||
|
|
||||||
// Decrypt a message
|
// Decrypt a message
|
||||||
ByteArrayAndResult<DecryptionResult> messageAndVerifications = sop.decrypt()
|
ByteArrayAndResult<DecryptionResult> messageAndVerifications = sop.decrypt()
|
||||||
.verifyWithCert(cert)
|
.verifyWith(cert)
|
||||||
.withKey(key)
|
.withKey(key)
|
||||||
.ciphertext(encrypted)
|
.ciphertext(encrypted)
|
||||||
.toByteArrayAndResult();
|
.toByteArrayAndResult();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
import org.apache.tools.ant.filters.*
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'java-library'
|
id 'java-library'
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ dependencies {
|
||||||
testImplementation "ch.qos.logback:logback-classic:$logbackVersion"
|
testImplementation "ch.qos.logback:logback-classic:$logbackVersion"
|
||||||
|
|
||||||
// Depend on "shared" sop-java test suite (fixtures are turned into tests by inheritance inside test sources)
|
// Depend on "shared" sop-java test suite (fixtures are turned into tests by inheritance inside test sources)
|
||||||
testImplementation "org.pgpainless:sop-java-testfixtures:$sopJavaVersion"
|
testImplementation(testFixtures("org.pgpainless:sop-java:$sopJavaVersion"))
|
||||||
|
|
||||||
implementation(project(":pgpainless-core"))
|
implementation(project(":pgpainless-core"))
|
||||||
api "org.pgpainless:sop-java:$sopJavaVersion"
|
api "org.pgpainless:sop-java:$sopJavaVersion"
|
||||||
|
@ -30,12 +30,6 @@ dependencies {
|
||||||
implementation "com.google.code.findbugs:jsr305:3.0.2"
|
implementation "com.google.code.findbugs:jsr305:3.0.2"
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
|
||||||
filter ReplaceTokens, tokens: [
|
|
||||||
"project.version": project.version.toString()
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
test {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
environment("test.implementation", "sop.testsuite.pgpainless.PGPainlessSopInstanceFactory")
|
environment("test.implementation", "sop.testsuite.pgpainless.PGPainlessSopInstanceFactory")
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.bouncycastle.util.io.Streams
|
||||||
import org.pgpainless.decryption_verification.OpenPgpInputStream
|
import org.pgpainless.decryption_verification.OpenPgpInputStream
|
||||||
import org.pgpainless.util.ArmoredOutputStreamFactory
|
import org.pgpainless.util.ArmoredOutputStreamFactory
|
||||||
import sop.Ready
|
import sop.Ready
|
||||||
|
import sop.enums.ArmorLabel
|
||||||
import sop.exception.SOPGPException
|
import sop.exception.SOPGPException
|
||||||
import sop.operation.Armor
|
import sop.operation.Armor
|
||||||
|
|
||||||
|
@ -45,4 +46,9 @@ class ArmorImpl : Armor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Setting custom labels is not supported.")
|
||||||
|
override fun label(label: ArmorLabel): Armor {
|
||||||
|
throw SOPGPException.UnsupportedOption("Setting custom Armor labels not supported.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import org.bouncycastle.openpgp.PGPSecretKeyRing
|
||||||
import org.bouncycastle.openpgp.PGPSignature
|
import org.bouncycastle.openpgp.PGPSignature
|
||||||
import org.bouncycastle.util.io.Streams
|
import org.bouncycastle.util.io.Streams
|
||||||
import org.pgpainless.PGPainless
|
import org.pgpainless.PGPainless
|
||||||
import org.pgpainless.algorithm.CompressionAlgorithm
|
|
||||||
import org.pgpainless.algorithm.DocumentSignatureType
|
import org.pgpainless.algorithm.DocumentSignatureType
|
||||||
import org.pgpainless.algorithm.HashAlgorithm
|
import org.pgpainless.algorithm.HashAlgorithm
|
||||||
import org.pgpainless.bouncycastle.extensions.openPgpFingerprint
|
import org.pgpainless.bouncycastle.extensions.openPgpFingerprint
|
||||||
|
@ -58,10 +57,7 @@ class DetachedSignImpl : DetachedSign {
|
||||||
val signingStream =
|
val signingStream =
|
||||||
PGPainless.encryptAndOrSign()
|
PGPainless.encryptAndOrSign()
|
||||||
.discardOutput()
|
.discardOutput()
|
||||||
.withOptions(
|
.withOptions(ProducerOptions.sign(signingOptions).setAsciiArmor(armor))
|
||||||
ProducerOptions.sign(signingOptions)
|
|
||||||
.setAsciiArmor(armor)
|
|
||||||
.overrideCompressionAlgorithm(CompressionAlgorithm.UNCOMPRESSED))
|
|
||||||
|
|
||||||
return object : ReadyWithResult<SigningResult>() {
|
return object : ReadyWithResult<SigningResult>() {
|
||||||
override fun writeTo(outputStream: OutputStream): SigningResult {
|
override fun writeTo(outputStream: OutputStream): SigningResult {
|
||||||
|
|
|
@ -11,9 +11,7 @@ import org.bouncycastle.openpgp.PGPException
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing
|
import org.bouncycastle.openpgp.PGPSecretKeyRing
|
||||||
import org.bouncycastle.util.io.Streams
|
import org.bouncycastle.util.io.Streams
|
||||||
import org.pgpainless.PGPainless
|
import org.pgpainless.PGPainless
|
||||||
import org.pgpainless.algorithm.CompressionAlgorithm
|
|
||||||
import org.pgpainless.algorithm.DocumentSignatureType
|
import org.pgpainless.algorithm.DocumentSignatureType
|
||||||
import org.pgpainless.algorithm.StreamEncoding
|
|
||||||
import org.pgpainless.bouncycastle.extensions.openPgpFingerprint
|
import org.pgpainless.bouncycastle.extensions.openPgpFingerprint
|
||||||
import org.pgpainless.encryption_signing.ProducerOptions
|
import org.pgpainless.encryption_signing.ProducerOptions
|
||||||
import org.pgpainless.encryption_signing.SigningOptions
|
import org.pgpainless.encryption_signing.SigningOptions
|
||||||
|
@ -58,23 +56,13 @@ class InlineSignImpl : InlineSign {
|
||||||
|
|
||||||
val producerOptions =
|
val producerOptions =
|
||||||
ProducerOptions.sign(signingOptions).apply {
|
ProducerOptions.sign(signingOptions).apply {
|
||||||
when (mode) {
|
if (mode == InlineSignAs.clearsigned) {
|
||||||
InlineSignAs.clearsigned -> {
|
|
||||||
setCleartextSigned()
|
setCleartextSigned()
|
||||||
setAsciiArmor(true) // CSF is always armored
|
setAsciiArmor(true) // CSF is always armored
|
||||||
setEncoding(StreamEncoding.TEXT)
|
} else {
|
||||||
applyCRLFEncoding()
|
|
||||||
}
|
|
||||||
InlineSignAs.text -> {
|
|
||||||
setEncoding(StreamEncoding.TEXT)
|
|
||||||
applyCRLFEncoding()
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
setAsciiArmor(armor)
|
setAsciiArmor(armor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
overrideCompressionAlgorithm(CompressionAlgorithm.UNCOMPRESSED)
|
|
||||||
}
|
|
||||||
|
|
||||||
return object : Ready() {
|
return object : Ready() {
|
||||||
override fun writeTo(outputStream: OutputStream) {
|
override fun writeTo(outputStream: OutputStream) {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||||
import sop.SOP
|
|
||||||
import sop.operation.Version
|
import sop.operation.Version
|
||||||
|
|
||||||
/** Implementation of the `version` operation using PGPainless. */
|
/** Implementation of the `version` operation using PGPainless. */
|
||||||
|
@ -26,14 +25,14 @@ class VersionImpl : Version {
|
||||||
String.format(Locale.US, "Bouncy Castle %.2f", BouncyCastleProvider().version)
|
String.format(Locale.US, "Bouncy Castle %.2f", BouncyCastleProvider().version)
|
||||||
val specVersion = String.format("%02d", SOP_VERSION)
|
val specVersion = String.format("%02d", SOP_VERSION)
|
||||||
return """${getName()} ${getVersion()}
|
return """${getName()} ${getVersion()}
|
||||||
https://codeberg.org/PGPainless/pgpainless/src/branch/main/pgpainless-sop
|
https://codeberg.org/PGPainless/pgpainless/src/branch/master/pgpainless-sop
|
||||||
|
|
||||||
Implementation of the Stateless OpenPGP Protocol Version $specVersion
|
Implementation of the Stateless OpenPGP Protocol Version $specVersion
|
||||||
https://datatracker.ietf.org/doc/html/draft-dkg-openpgp-stateless-cli-$specVersion
|
https://datatracker.ietf.org/doc/html/draft-dkg-openpgp-stateless-cli-$specVersion
|
||||||
|
|
||||||
Based on pgpainless-core ${getVersion()}
|
Based on pgpainless-core ${getVersion()}
|
||||||
https://pgpainless.org
|
https://pgpainless.org
|
||||||
${formatSopJavaVersion()}
|
|
||||||
Using $bcVersion
|
Using $bcVersion
|
||||||
https://www.bouncycastle.org/java.html"""
|
https://www.bouncycastle.org/java.html"""
|
||||||
}
|
}
|
||||||
|
@ -50,27 +49,15 @@ https://www.bouncycastle.org/java.html"""
|
||||||
// See https://stackoverflow.com/a/50119235
|
// See https://stackoverflow.com/a/50119235
|
||||||
return try {
|
return try {
|
||||||
val resourceIn: InputStream =
|
val resourceIn: InputStream =
|
||||||
SOP::class.java.getResourceAsStream("/pgpainless-sop.properties")
|
javaClass.getResourceAsStream("/version.properties")
|
||||||
?: throw IOException("File pgpainless-sop.properties not found.")
|
?: throw IOException("File version.properties not found.")
|
||||||
|
|
||||||
val properties = Properties().apply { load(resourceIn) }
|
val properties = Properties().apply { load(resourceIn) }
|
||||||
properties.getProperty("pgpainless-sop-version")
|
properties.getProperty("version")
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
"DEVELOPMENT"
|
"DEVELOPMENT"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun formatSopJavaVersion(): String {
|
|
||||||
return getSopJavaVersion()?.let {
|
|
||||||
"""
|
|
||||||
|
|
||||||
sop-java $it
|
|
||||||
|
|
||||||
"""
|
|
||||||
.trimIndent()
|
|
||||||
}
|
|
||||||
?: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isSopSpecImplementationIncomplete(): Boolean = false
|
override fun isSopSpecImplementationIncomplete(): Boolean = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
# SPDX-FileCopyrightText: 2025 Paul Schaub <info@pgpainless.org>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
pgpainless-sop-version=@project.version@
|
|
|
@ -100,14 +100,4 @@ public class GenerateKeyTest {
|
||||||
assertThrows(SOPGPException.UnsupportedProfile.class, () ->
|
assertThrows(SOPGPException.UnsupportedProfile.class, () ->
|
||||||
sop.generateKey().profile("invalid"));
|
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"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,164 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package org.pgpainless.sop;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.pgpainless.PGPainless;
|
|
||||||
import org.pgpainless.policy.Policy;
|
|
||||||
import sop.ByteArrayAndResult;
|
|
||||||
import sop.Verification;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
||||||
|
|
||||||
public class VerifyLegacySignatureTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void verifyLegacySignature() throws IOException {
|
|
||||||
// Key generated in 2012 using SHA1 for self sigs
|
|
||||||
String KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
|
||||||
"Version: PGPainless\n" +
|
|
||||||
"Comment: 21FA 6E60 D6C9 B7D1 0EAC 56A2 984B 91CF D303 214C\n" +
|
|
||||||
"Comment: Legacy <legacy@example.com>\n" +
|
|
||||||
"\n" +
|
|
||||||
"lQVYBFDUVsABDADg6AuFsM0JckT7spS/1KNdobaZ1vrOFhGdyXbJ1jUkbMwi+f5o\n" +
|
|
||||||
"UtQsfeFQRBHeQFfmtt4mo6lE6cAsQFJPFat/ReNxCwCqHi5QbennpbueHJ5N2KVj\n" +
|
|
||||||
"YrIz6eeTsVKs16gS17zLOMkeBt0TK8+Vu7HHfqLqQ1jNNGujwPydUbO8M431XKeW\n" +
|
|
||||||
"WhM9ziV9m/20nHYJGIM+aN9AicxtR+khFsNjpRlCMg+8kKUelP2FDWv/5QZwnSXc\n" +
|
|
||||||
"nMFaCJiH1hx56027AB8PZrUW+ShRhqb0P3EhOt+Gs3IW39rGjc9iQVEWl7745BTZ\n" +
|
|
||||||
"xEZ4FO84DQQtdKBp510VN8LfiZkO7K9JKOo+vqL4IvSBCJNRVvxDxInShHfVyht7\n" +
|
|
||||||
"jJJvEC0mxv1Oi8rZ/g9iNd6/Ijthi3svNd3DwNFyMzhrbggynEyWr8nu17Zz0c6C\n" +
|
|
||||||
"KT7XtFZWOUmio8G14KH6dFRCt7TGRw7mz059ViICMN56Ka5LJaQgGRbT+omY2CQJ\n" +
|
|
||||||
"q5eSkZMXLndmjtUAEQEAAQAL+QFsyzhLl/oLPs0+63JrTaXPY9s5EpNEkHYTgN29\n" +
|
|
||||||
"HTUELKdWFBaa7M9sBbCJmiODdEB0mfT+yGW9R6wPCXiaEj8ysMt0QvVzG03Qr6pX\n" +
|
|
||||||
"kWCmHSuW5ZQHytJjDJMA0T+3K0fQWWFPC/bmX12+1Flw4qI9g6oigub1aF4eJFdV\n" +
|
|
||||||
"XVq7vhadY9aSIiGtJnX+PqiRIIwPeRDfMjsvwA6H/1dwftltRnbLVr0vnUutRnPv\n" +
|
|
||||||
"ZGbiOim35bWubLW55Ehycb4T4KyW70Xq0Lljr04/33d7S/SUNHXM/ci2kFDEkJb8\n" +
|
|
||||||
"N+rssxaVjgPsn9+5wQFDEcrewdMLgaRHSrEf46GvcYMbM8lfnzrDyhYc5+vc24b5\n" +
|
|
||||||
"85WCVYaYKFrJGEa1vHAMmDwXqDNETtDtaYXZpNsUqvjlG+lU4/p0zeqGfyIDLnzK\n" +
|
|
||||||
"R5zAmWQkd4aSrgN4F6/7xQ1npnvBq/eZiHJx4sBsPMS10TFPPi3A9jEAiu0eljTq\n" +
|
|
||||||
"E7eXqDObHD8xSjQ3gm9fBclTUQYA4vVChPT9SgJo2aY5ug+2nLWfv4hgK2LTRNkt\n" +
|
|
||||||
"exEelaU3vrl83a/HEljg3DZ63P6odRIv0HGRl4YSOEC5CANDcDqjz34p7T6suRU5\n" +
|
|
||||||
"GzrZHey33joLj9oAGF+2HefmHpvWc8ZzFaS14XiO4m9TMMLZwSokNyhccHl7FSYZ\n" +
|
|
||||||
"XqxzXD2JnaM+m3XMGRVnASQ2gtmsv8dpXuto+gF/9W1b8kyPp1sjtgup2O4PjiQg\n" +
|
|
||||||
"1uQMpx6H3OSC8tCH3f9/MvlVTpgtBgD9r5PnN5h6fQd6MQl7UEdTU3jIOcXrr1xh\n" +
|
|
||||||
"0rQkTQx1WJ29f/tr/sGPb3HgPcpk+x6xctRVpW6yf6OLBP02CnJllBYE73tqIxxa\n" +
|
|
||||||
"qK+3kDAqIa9n/Ds8SZTH/45JXDFLay5g7kFMpv6dxUUMtdJ8INmcChVPxKeUB5DZ\n" +
|
|
||||||
"iGMzmCTsR0RxvEIc3ofht7mrMhH361xUZGbIMP6ykZZNlE4FmOW4zBATa8o4V3gl\n" +
|
|
||||||
"mdbIYopEGPwAuj1gIy0G7fLL0cayEkkF/RI7uep4d2QY87mC+fswbiPWM3mp6/7i\n" +
|
|
||||||
"e2JLmA2bdDju7SL6X4DMgV8RQakOlQf17JEGA4HrKi3odugiBjdXWv6ZmfcIIPgq\n" +
|
|
||||||
"ns2Us6wCcr4uqCxEvYj2fUd/q03ui5aglLTqSSuNtnB9yww0EYrj9qjHFIi/ByrF\n" +
|
|
||||||
"L6DVBrMDJ0BwHY5LkY1OWot4GyjLE43Uqu0ObZhFSMttGQkRxdae0R9+4NPR7Dlw\n" +
|
|
||||||
"B8+zwytxGRs1NgTy7O+KRl9e3K05bgUXVNsJtBtMZWdhY3kgPGxlZ2FjeUBleGFt\n" +
|
|
||||||
"cGxlLmNvbT6JAdAEEwECAEQJEJhLkc/TAyFMFiEEIfpuYNbJt9EOrFaimEuRz9MD\n" +
|
|
||||||
"IUwFglDUVsACngECmwMFFgIDAQAECwkIBwIVAgWJH6AIMQKZAQAAWU0L/jUvlxt0\n" +
|
|
||||||
"TLLFTcT1tQWvy1MBLJcdiXuoN0/w1Rcz54iSCgWeuNZ5BD6qwCMORmVG1fMuvtCt\n" +
|
|
||||||
"Lq4NZizE63QfeFE8q22vrNDoZ5pAnjC7KlMMjq1ykQHN7cqH1FgxrS3PrBo1k8/s\n" +
|
|
||||||
"0P6863Vlso02YYbWluJt4HbnX0vEap4/z05RLBCQyZyiaon5zad5rNd0z1nXfMC8\n" +
|
|
||||||
"EPRK9MsjBX5/5zhx6RPwCrAlrk5dKZ3Nks6bquTCme8sayBgBHX0Tjeum+3sfwiE\n" +
|
|
||||||
"Jn2xTYJU6cB7fWYREi9E9z7YrmpVCjDkh8U7p0MLC3dmIYUT3EDL5F0jxTReoX+B\n" +
|
|
||||||
"7f8HrKUIOyvLlAJs4oxYG/g9QHzVFSAbekwf3Jnwm4Czd6qPx62gI6na11ku64Ua\n" +
|
|
||||||
"RezZ3NkTInSXi1+Bi7mT4qVcV6Z6vl5YXe8T/Zihcv5/Wp4bNEJ2dHJlhwVAn8Ax\n" +
|
|
||||||
"Ykl8S2ZVfQ5hN8gWLRW40wnCrbuNUdWI/el9D1arc8AQclXfF8/4kULTq50FWARQ\n" +
|
|
||||||
"1FbAAQwAv/eK+LYwdkUoGfATB6wcmqaJFrjFIaKYbM1VEWckb4FYc0T1yc9MEq65\n" +
|
|
||||||
"gz1/PUPt+XwQCa/gP5iCcVuze91ksJVkoeOjy/CQgMD1D1s0IVikVMvOKqdnVa4k\n" +
|
|
||||||
"SxkLkOvVdzZ5QebDbE5QqfTupyr/SgWarm7TYb4HVFNG5xXVh8+uFMpLe897E+/K\n" +
|
|
||||||
"mSQMZZ8vdKVvnEm+EOlm0ZzRml4kM8k1LyVxJdoLUJ0t5Ac7B1k/Xq0Fz1Pl3Yjr\n" +
|
|
||||||
"xahxvz68gTph+uL0IlnxKIt+lI2YKTaZ/QZ6POzif0UHLH4akEoTLjzlzkgNYdiI\n" +
|
|
||||||
"O3ZekqHViYtlX0brc7TYo3iip1LIvv3NMI7QskA2v9V1NWcf/cPBt0uwJ2wMDDDy\n" +
|
|
||||||
"bckrrwwsfNn6qFxY3xFo1aexzgpG2C9ZVpIDLMd3F6SUoqrrmAHJLoP0dSYBVujO\n" +
|
|
||||||
"EAJdPqvLC45KJFgXu6IrBqFrx+WTACJCvgoF8XLLhEba99CwmS8Rc2luS+G3iB8l\n" +
|
|
||||||
"YQlj5QWXABEBAAEAC/wMe00lhe/f7ZGbIVYun4ahZfnWTyxyI9JPvYh62ZjJSNqD\n" +
|
|
||||||
"B2IIo/PitLDXObGcpPgQl3wR3sYKT7sOuwZ2ihsFgd38yk8lVktVZwM7SZQGi9VT\n" +
|
|
||||||
"gu59+eVPV6oaDLmimJ+7YQCNXZj2ewXmDXwe+Aq7ucjCIrtklY7m14Tt4MH1H9z5\n" +
|
|
||||||
"X3xJw2A4GAiCRvfClV3oJbTJSRPH1Ouch9r3c7uPqm6zPBBmHg4Yr1k2hGNwKa6X\n" +
|
|
||||||
"IOtJyb8ebzKogJ7n7zo4Cpst01PkdLPnXK3fTEBYjuBQa5F2sSvT89uK3seN3J7W\n" +
|
|
||||||
"OP05lCcg1k9e4bnD9uGlba0fhsgUhqTEg3za6MNcVezPqRXGXlkWH5gjxbVQHu8B\n" +
|
|
||||||
"Y8Ix9YvWhCwIA25bSE51bTq2vQuCTaRG5fXVWD8qZ043APcB99c9zW9OvmiJzH47\n" +
|
|
||||||
"zYk+rB+lByK8/KiaXUqcKjyUniXc9LKda71xb4MwoBuBF9RdCsQvHwFRibdpMd0t\n" +
|
|
||||||
"a9O7RoTFKPxhUewySoEGANTBWhstEUlsytFMSeNmCmpNR2/mKbuE+n78+zaPCmLF\n" +
|
|
||||||
"TsLWxil+y3FrJCvffn9k5shtxLADtEvKJKWl/vjXxh9DXzFvMgRPsrETzAkg0zwr\n" +
|
|
||||||
"+5P8d26x4xcnQaE59RQIhyiJPsT4fXqld+kaKDng0vYkVRGHSIC//NPMPA2KaTdC\n" +
|
|
||||||
"4EQvEx702dF3/+tIDwXO/kjk6taEEOv0W5nj0aHm+JtEw+X0ja1VvUcDx50Ttwpc\n" +
|
|
||||||
"LzojtWjFpBNFHLGZyWac4QYA5vx6WsovX9j3YXkYDHbN+r8rCfL/16+z+qEJ/pbw\n" +
|
|
||||||
"2eevICtB4KLcqXlep4rSLhDJlYphxZfHhsVahwX1ga+fGDB/AuDozJhtfQp7evwN\n" +
|
|
||||||
"NH5IIAT3o56iBUIO2CywWcdkY+HMo787MbITfvVOdOrGE8hRcCFdkZepaSwfbTRz\n" +
|
|
||||||
"LZH+jKAU6xOgInuoPVLOOIIlLaTVb6TTRV9BXyRUdele0DqbZIMCwE8P53kFuGuM\n" +
|
|
||||||
"sRZQ1RNha8H7WU2T2m7QxDl3Bf4+KYQ5AfFPkGZKMQcIJy4CR7hSP9gk3/4B06RM\n" +
|
|
||||||
"DH3c4rmd50CPpQ5TTA0cGCthOnYVewUgJaxQjKAToX8xCQYFRO59YOc8PMVZ/xgf\n" +
|
|
||||||
"kGrEkX4tlwECbjoWx2kWT4uZvYmnUzfDdXXr8E+9h2ziEKobF0/b9HQB5BKKLycr\n" +
|
|
||||||
"KzoTKbV4En1602VltRInAfnjpmQ7VSYV/JyoHJ824d/7O+fLLZkmyibLiSMWPwYu\n" +
|
|
||||||
"z9rt26lC3cT/HSMrG3L0jjdWH7bYaIkBsAQYAQIAGgWCUNRWwAKeAQKbDAUWAgMB\n" +
|
|
||||||
"AAQLCQgHAhUCAAoJEJhLkc/TAyFMEn4MAKI6RC+VUJr+p2bMf5Pbfml/iy5QsRBG\n" +
|
|
||||||
"J1iTyPzu8yJUzHs60y6YckGrIKSFE5x6a6utz/CdtpIlb9e/FJvl82zjxJkFjhre\n" +
|
|
||||||
"fhHjcu6iIvLCCer6v1XtL4frx6Qoi6TGmlKXWvaLTuRINQFomLwScoHRW1QSQHTE\n" +
|
|
||||||
"BNUmIo89nRU5PQ8LJBGZWzdkVqVmdbK8ek5ycuolwLUQizbeGIhJo/9IIC2i2RCJ\n" +
|
|
||||||
"hMVsmbjHB1zdVbwPZuwtCH7ROr4xTLp9Gwq1XcIRYY5am/SyBLgkwKSyrXQs6Zsr\n" +
|
|
||||||
"2qRd2+ccBF0UYFxvH9JOKmBS6QGwtnAYRqbeeCj8Lx3mgAIv15kGeKd72ezFi0ZT\n" +
|
|
||||||
"smO3dpb6pSD44BSsdvjZdHENCxYIbBsroDZrZGShygluOCrFjG//PSSbrNE+Bz70\n" +
|
|
||||||
"imnM2QH/XaS6rpbNPGfrn0Vw5M/ZFT/9PWrEg4ZdCI32ei5uyjYwL7aPAPS3MqkB\n" +
|
|
||||||
"SV9g8CiU0cX7hiBYYpktcDVU3uRCR4Fkvw==\n" +
|
|
||||||
"=n8qw\n" +
|
|
||||||
"-----END PGP PRIVATE KEY BLOCK-----";
|
|
||||||
// Sig generated in 2012 using SHA1
|
|
||||||
String oldSig = "-----BEGIN PGP MESSAGE-----\n" +
|
|
||||||
"Version: PGPainless\n" +
|
|
||||||
"\n" +
|
|
||||||
"owEB2gEl/pANAwACAZhLkc/TAyFMAcsTYgAAAAAASGVsbG8sIFdvcmxkIYkBswQA\n" +
|
|
||||||
"AQIAJwkQmEuRz9MDIUwWIQQh+m5g1sm30Q6sVqKYS5HP0wMhTAWCUNRWwAAALxEL\n" +
|
|
||||||
"/2uhYsTLM8nUnYm2GJB6pkapX1kbQrqfAhK46IjxcPpRdl6CW4cFrG6iFegx4YLE\n" +
|
|
||||||
"fu44VKG+XGy/RTZXIEJubi9zVyOGGJM9Bwwdcp/eekO16/kJ7BsbkaO+5AG/fNeg\n" +
|
|
||||||
"bL5C8D2m6jV1seAt/+tRyM9jLkRi9odq8BsGA6ZcthAxh3MUoo1yw3QwwEcFFHg/\n" +
|
|
||||||
"gBw4ZtL8KIQN1PKDz3sSV4GXPQAiz+/uADZ2lL6mbDEK/gXAK1KevIO3U8ZU9B6l\n" +
|
|
||||||
"cOF9fJww31SCqFGDq50Lzwz7eySJB1TZ0IoehGDXoQ8JF88uTVfACkBATE0Zx7zg\n" +
|
|
||||||
"TAYIgPSjWY4TEDZ9YjdxJ0hKTMncxVfZPB+J/mYCpVADYSEhLbUJ1ntjc0s35xJD\n" +
|
|
||||||
"udLSwUWuboedVdEcaqnfgHoaaV+nKk+6F9y8NO56RK3Bfx5FmKmNZHbhfXO/qRt9\n" +
|
|
||||||
"H43UktMUD6xWxxJv7mutThOp2aizBeboa5YSJ1mxtkPW0/lyK1jr438ETHUnCeu6\n" +
|
|
||||||
"Vw==\n" +
|
|
||||||
"=TtKx\n" +
|
|
||||||
"-----END PGP MESSAGE-----";
|
|
||||||
|
|
||||||
SOPImpl sop = new SOPImpl();
|
|
||||||
byte[] cert = sop.extractCert().key(KEY.getBytes(StandardCharsets.UTF_8))
|
|
||||||
.getBytes();
|
|
||||||
ByteArrayAndResult<List<Verification>> result = sop.inlineVerify()
|
|
||||||
.cert(cert)
|
|
||||||
.data(oldSig.getBytes(StandardCharsets.UTF_8))
|
|
||||||
.toByteArrayAndResult();
|
|
||||||
|
|
||||||
assertFalse(result.getResult().isEmpty());
|
|
||||||
|
|
||||||
// Adjust data signature hash policy to accept new SHA-1 sigs
|
|
||||||
PGPainless.getPolicy().setDataSignatureHashAlgorithmPolicy(
|
|
||||||
Policy.HashAlgorithmPolicy.static2022RevocationSignatureHashAlgorithmPolicy());
|
|
||||||
|
|
||||||
// Sig generated in 2024 using SHA1
|
|
||||||
String newSig = "-----BEGIN PGP MESSAGE-----\n" +
|
|
||||||
"Version: PGPainless\n" +
|
|
||||||
"\n" +
|
|
||||||
"owEB2gEl/pANAwACAZhLkc/TAyFMAcsTYgAAAAAASGVsbG8sIFdvcmxkIYkBswQA\n" +
|
|
||||||
"AQIAJwWCZw5i2AkQmEuRz9MDIUwWIQQh+m5g1sm30Q6sVqKYS5HP0wMhTAAAhVML\n" +
|
|
||||||
"+QGH+O2fEJoAY8ZxKz/mosg4it9IeSzMhBvDgZJE8Jc+VGk7EuXL0M8pfHL+Jgmv\n" +
|
|
||||||
"FMzF3chzzLS7QA4K6hbxO31/M8TNSU12geuzQiBV7Kb1hjpvIObBgEqYsX50ZV8r\n" +
|
|
||||||
"5DHcr7huABUOH6tCKmCA2OxOvr1QV8X39h856bz3WqqP9HW8kZ6H1Z6d7XWlRMtW\n" +
|
|
||||||
"mAnSevvOJbb0Z3D97obYqytSLzi2Jyv+w2R9kYzMQff2Rl6Cv4F7zsRrF9JRC0m6\n" +
|
|
||||||
"X/s+VSNuT2yG0/4F5y8vrxvNkfd8YfM8DM6irJV4yJyVuwIoZnM913XCA4F7Uo4t\n" +
|
|
||||||
"Z8ER17SY4WOYvdja/7qPcOUjX5n1dDU0W7q2muqnZXREw2JXTULiDl0MET3K4kFu\n" +
|
|
||||||
"a6FyyMGGQwFpAnZ4gDZKzw06abd95AgHx4QlkD89J7MnUBBV+AGHNAQlCPPEVPQq\n" +
|
|
||||||
"dWTInYndt4GKCUxVkJeHD6ZPLdxEEvICmEap4FQzhqM8U7weoEsSinoVoc4JmSY9\n" +
|
|
||||||
"dQ==\n" +
|
|
||||||
"=XrzP\n" +
|
|
||||||
"-----END PGP MESSAGE-----";
|
|
||||||
result = sop.inlineVerify()
|
|
||||||
.cert(cert)
|
|
||||||
.data(newSig.getBytes(StandardCharsets.UTF_8))
|
|
||||||
.toByteArrayAndResult();
|
|
||||||
|
|
||||||
assertFalse(result.getResult().isEmpty());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,15 +4,16 @@
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
ext {
|
ext {
|
||||||
shortVersion = '1.7.7'
|
shortVersion = '1.7.1'
|
||||||
isSnapshot = true
|
isSnapshot = false
|
||||||
javaSourceCompatibility = 11
|
pgpainlessMinAndroidSdk = 10
|
||||||
bouncyCastleVersion = '1.81'
|
javaSourceCompatibility = 1.8
|
||||||
|
bouncyCastleVersion = '1.78.1'
|
||||||
bouncyPgVersion = bouncyCastleVersion
|
bouncyPgVersion = bouncyCastleVersion
|
||||||
junitVersion = '5.8.2'
|
junitVersion = '5.8.2'
|
||||||
logbackVersion = '1.5.13'
|
logbackVersion = '1.2.13' // 1.4+ cause CLI spam :/
|
||||||
mockitoVersion = '4.5.1'
|
mockitoVersion = '4.5.1'
|
||||||
slf4jVersion = '1.7.36'
|
slf4jVersion = '1.7.36'
|
||||||
sopJavaVersion = '10.1.1'
|
sopJavaVersion = '10.0.2'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue