mirror of
https://codeberg.org/PGPainless/sop-java.git
synced 2025-09-09 18:29:48 +02:00
Compare commits
70 commits
69dd846667
...
7ee856f9b9
Author | SHA1 | Date | |
---|---|---|---|
7ee856f9b9 | |||
b42b966866 | |||
0b68d9f04e | |||
db315e9ed2 | |||
966ea3c3a6 | |||
f6d7af2dab | |||
3367450f94 | |||
54782d2a22 | |||
83eafd8817 | |||
6c7fcfccce | |||
04f7a5d30d | |||
88d3301daa | |||
6fc849bb6a | |||
5bebdb779a | |||
3e6e47ed50 | |||
023b4ea45b | |||
dd07d10350 | |||
859bb5bdde | |||
edb405d79e | |||
57e2f8391b | |||
51ba24ddbe | |||
d1893c5ea0 | |||
c145f8bb37 | |||
924cfaa140 | |||
f2602bb413 | |||
97e91f50ab | |||
690ba6dc16 | |||
9ec3cc911b | |||
f92a73a5ad | |||
2b6015f59a | |||
84e381fe8e | |||
b1e1a2283f | |||
b3b8da4e35 | |||
ca65cbe668 | |||
4eb6d1fdcb | |||
594b9029b2 | |||
471947ef9c | |||
1fd3161851 | |||
a8a753536a | |||
eadea08d3c | |||
547acdb740 | |||
bb026bcbeb | |||
e7778cb0d2 | |||
ac00b68694 | |||
e6c9d6f43d | |||
c136d40fa7 | |||
f35fd6c1ae | |||
375dd65789 | |||
42a16a4f6d | |||
b3f446fe8d | |||
1958614fac | |||
a09f10fe85 | |||
a90f9be0e4 | |||
63d8045224 | |||
7014dbcfb7 | |||
354ef8841a | |||
261ac212b8 | |||
f7530e3263 | |||
8d7e89098f | |||
a523270395 | |||
d25a424adc | |||
2d4bc24c64 | |||
65945e0094 | |||
4388f00dc0 | |||
1df5747549 | |||
ae2389cabf | |||
34a05e96a1 | |||
7b04275625 | |||
a0e7356757 | |||
173bc55eb9 |
44 changed files with 177 additions and 38 deletions
|
@ -16,4 +16,6 @@ steps:
|
||||||
- gradle check javadocAll
|
- gradle check javadocAll
|
||||||
# Code has coverage
|
# Code has coverage
|
||||||
- gradle jacocoRootReport coveralls
|
- gradle jacocoRootReport coveralls
|
||||||
secrets: [coveralls_repo_token]
|
environment:
|
||||||
|
coveralls_repo_token:
|
||||||
|
from_secret: coveralls_repo_token
|
||||||
|
|
40
CHANGELOG.md
40
CHANGELOG.md
|
@ -6,10 +6,37 @@ SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 10.0.1-SNAPSHOT
|
## 10.1.1-SNAPSHOT
|
||||||
|
- Prepare jar files for use in native images, e.g. using GraalVM by generating and including
|
||||||
|
configuration files for reflection, resources and dynamic proxies.
|
||||||
|
|
||||||
|
## 10.1.0
|
||||||
|
- `sop-java`:
|
||||||
|
- Remove `label()` option from `armor()` subcommand
|
||||||
|
- Move test-fixtures artifact built with the `testFixtures` plugin into
|
||||||
|
its own module `sop-java-testfixtures`, which can be consumed by maven builds.
|
||||||
|
- `sop-java-picocli`:
|
||||||
|
- Properly map `MissingParameterException` to `MissingArg` exit code
|
||||||
|
- As a workaround for native builds using graalvm:
|
||||||
|
- Do not re-set message bundles dynamically (fails in native builds)
|
||||||
|
- Prevent an unmatched argument error
|
||||||
|
|
||||||
|
## 10.0.3
|
||||||
|
- CLI `change-key-password`: Fix indirect parameter passing for new and old passwords (thanks to @dkg for the report)
|
||||||
|
- Backport: `revoke-key`: Allow for multiple password options
|
||||||
|
|
||||||
|
## 10.0.2
|
||||||
|
- Downgrade `logback-core` to `1.2.13`
|
||||||
|
|
||||||
|
## 10.0.1
|
||||||
- Remove `label()` option from `Armor` operation
|
- Remove `label()` option from `Armor` operation
|
||||||
- Fix exit code for 'Missing required option/parameter' error
|
- Fix exit code for 'Missing required option/parameter' error
|
||||||
- Fix `revoke-key`: Allow for multiple invocations of `--with-key-password` option
|
- Fix `revoke-key`: Allow for multiple invocations of `--with-key-password` option
|
||||||
|
- Fix `EncryptExternal` use of `--sign-with` parameter
|
||||||
|
- Fix `NullPointerException` in `DecryptExternal` when reading lines
|
||||||
|
- Fix `DecryptExternal` use of `verifications-out`
|
||||||
|
- Test suite: Ignore tests if `UnsupportedOption` is thrown
|
||||||
|
- Bump `logback-core` to `1.4.14`
|
||||||
|
|
||||||
## 10.0.0
|
## 10.0.0
|
||||||
- Update implementation to [SOP Specification revision 10](https://www.ietf.org/archive/id/draft-dkg-openpgp-stateless-cli-10.html).
|
- Update implementation to [SOP Specification revision 10](https://www.ietf.org/archive/id/draft-dkg-openpgp-stateless-cli-10.html).
|
||||||
|
@ -17,6 +44,10 @@ SPDX-License-Identifier: Apache-2.0
|
||||||
- Introduce `sopv` interface subset with revision `1.0`
|
- Introduce `sopv` interface subset with revision `1.0`
|
||||||
- Add `sop version --sopv`
|
- Add `sop version --sopv`
|
||||||
|
|
||||||
|
## 8.0.2
|
||||||
|
- CLI `change-key-password`: Fix indirect parameter passing for new and old passwords (thanks to @dkg for the report)
|
||||||
|
- Backport: `revoke-key`: Allow for multiple password options
|
||||||
|
|
||||||
## 8.0.1
|
## 8.0.1
|
||||||
- `decrypt`: Do not throw `NoSignature` exception (exit code 3) if `--verify-with` is provided, but `VERIFICATIONS` is empty.
|
- `decrypt`: Do not throw `NoSignature` exception (exit code 3) if `--verify-with` is provided, but `VERIFICATIONS` is empty.
|
||||||
|
|
||||||
|
@ -35,6 +66,13 @@ SPDX-License-Identifier: Apache-2.0
|
||||||
- Change `EncryptAs` values into lowercase
|
- Change `EncryptAs` values into lowercase
|
||||||
- Change `SignAs` values into lowercase
|
- Change `SignAs` values into lowercase
|
||||||
|
|
||||||
|
## 7.0.2
|
||||||
|
- CLI `change-key-password`: Fix indirect parameter passing for new and old passwords (thanks to @dkg for the report)
|
||||||
|
- Backport: revoke-key command: Allow for multiple '--with-key-password' options
|
||||||
|
|
||||||
|
## 7.0.1
|
||||||
|
- `decrypt`: Do not throw `NoSignature` exception (exit code 3) if `--verify-with` is provided, but `VERIFICATIONS` is empty.
|
||||||
|
|
||||||
## 7.0.0
|
## 7.0.0
|
||||||
- Update implementation to [SOP Specification revision 07](https://www.ietf.org/archive/id/draft-dkg-openpgp-stateless-cli-07.html).
|
- Update implementation to [SOP Specification revision 07](https://www.ietf.org/archive/id/draft-dkg-openpgp-stateless-cli-07.html).
|
||||||
- Add support for new `revoke-key` subcommand
|
- Add support for new `revoke-key` subcommand
|
||||||
|
|
|
@ -27,6 +27,8 @@ The repository contains the following modules:
|
||||||
compatible with the SOP-CLI specification.
|
compatible with the SOP-CLI specification.
|
||||||
* [external-sop](/external-sop) contains an API implementation that can be used to forward API calls to a SOP executable,
|
* [external-sop](/external-sop) contains an API implementation that can be used to forward API calls to a SOP executable,
|
||||||
allowing to delegate the implementation logic to an arbitrary SOP CLI implementation.
|
allowing to delegate the implementation logic to an arbitrary SOP CLI implementation.
|
||||||
|
* [sop-java-testfixtures](/sop-java-testfixtures) contains a test suite that can be shared by downstream implementations
|
||||||
|
of `sop-java`.
|
||||||
|
|
||||||
## Known Implementations
|
## Known Implementations
|
||||||
(Please expand!)
|
(Please expand!)
|
||||||
|
@ -35,9 +37,11 @@ allowing to delegate the implementation logic to an arbitrary SOP CLI implementa
|
||||||
|-------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------|
|
|-------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------|
|
||||||
| [pgpainless-sop](https://github.com/pgpainless/pgpainless/tree/main/pgpainless-sop) | Implementation of `sop-java` using PGPainless |
|
| [pgpainless-sop](https://github.com/pgpainless/pgpainless/tree/main/pgpainless-sop) | Implementation of `sop-java` using PGPainless |
|
||||||
| [external-sop](https://github.com/pgpainless/sop-java/tree/main/external-sop) | Implementation of `sop-java` that allows binding to external SOP binaries such as `sqop` |
|
| [external-sop](https://github.com/pgpainless/sop-java/tree/main/external-sop) | Implementation of `sop-java` that allows binding to external SOP binaries such as `sqop` |
|
||||||
|
| [bcsop](https://codeberg.org/PGPainless/bc-sop) | Implementation of `sop-java` using vanilla Bouncy Castle |
|
||||||
|
|
||||||
### Implementations in other languages
|
### Implementations in other languages
|
||||||
| Project | Language |
|
| Project | Language |
|
||||||
|-------------------------------------------------|----------|
|
|---------------------------------------------------|----------|
|
||||||
| [sop-rs](https://sequoia-pgp.gitlab.io/sop-rs/) | Rust |
|
| [sop-rs](https://sequoia-pgp.gitlab.io/sop-rs/) | Rust |
|
||||||
| [SOP for python](https://pypi.org/project/sop/) | Python |
|
| [SOP for python](https://pypi.org/project/sop/) | Python |
|
||||||
|
| [rpgpie-sop](https://crates.io/crates/rpgpie-sop) | Rust |
|
||||||
|
|
|
@ -19,7 +19,7 @@ buildscript {
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'ru.vyarus.animalsniffer' version '1.5.3'
|
id 'ru.vyarus.animalsniffer' version '1.5.3'
|
||||||
id 'org.jetbrains.kotlin.jvm' version "1.8.10"
|
id 'org.jetbrains.kotlin.jvm' version "1.9.21"
|
||||||
id 'com.diffplug.spotless' version '6.22.0' apply false
|
id 'com.diffplug.spotless' version '6.22.0' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ allprojects {
|
||||||
apply plugin: 'jacoco'
|
apply plugin: 'jacoco'
|
||||||
apply plugin: 'checkstyle'
|
apply plugin: 'checkstyle'
|
||||||
apply plugin: 'kotlin'
|
apply plugin: 'kotlin'
|
||||||
|
apply plugin: 'kotlin-kapt'
|
||||||
apply plugin: 'com.diffplug.spotless'
|
apply plugin: 'com.diffplug.spotless'
|
||||||
|
|
||||||
// For non-cli modules enable android api compatibility check
|
// For non-cli modules enable android api compatibility check
|
||||||
|
|
|
@ -27,7 +27,7 @@ dependencies {
|
||||||
// The ExternalTestSubjectFactory reads json config file to find configured SOP binaries...
|
// The ExternalTestSubjectFactory reads json config file to find configured SOP binaries...
|
||||||
testImplementation "com.google.code.gson:gson:$gsonVersion"
|
testImplementation "com.google.code.gson:gson:$gsonVersion"
|
||||||
// ...and extends TestSubjectFactory
|
// ...and extends TestSubjectFactory
|
||||||
testImplementation(testFixtures(project(":sop-java")))
|
testImplementation(project(":sop-java-testfixtures"))
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|
|
@ -78,7 +78,7 @@ class DecryptExternal(
|
||||||
val verifyOut = File(tempDir, "verifications-out")
|
val verifyOut = File(tempDir, "verifications-out")
|
||||||
verifyOut.delete()
|
verifyOut.delete()
|
||||||
if (requireVerification) {
|
if (requireVerification) {
|
||||||
commandList.add("--verify-out=${verifyOut.absolutePath}")
|
commandList.add("--verifications-out=${verifyOut.absolutePath}")
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -37,7 +37,7 @@ class EncryptExternal(
|
||||||
|
|
||||||
override fun signWith(key: InputStream): Encrypt = apply {
|
override fun signWith(key: InputStream): Encrypt = apply {
|
||||||
commandList.add("--sign-with=@ENV:SIGN_WITH_$argCounter")
|
commandList.add("--sign-with=@ENV:SIGN_WITH_$argCounter")
|
||||||
envList.add("SIGN_WITH_$argCounter=${ExternalSOP.readString(key)}")
|
envList.add("SIGN_WITH_$argCounter=${readString(key)}")
|
||||||
argCounter += 1
|
argCounter += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,5 +6,6 @@ rootProject.name = 'SOP-Java'
|
||||||
|
|
||||||
include 'sop-java',
|
include 'sop-java',
|
||||||
'sop-java-picocli',
|
'sop-java-picocli',
|
||||||
|
'sop-java-testfixtures',
|
||||||
'external-sop'
|
'external-sop'
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,11 @@ dependencies {
|
||||||
|
|
||||||
// SOP
|
// SOP
|
||||||
implementation(project(":sop-java"))
|
implementation(project(":sop-java"))
|
||||||
testImplementation(testFixtures(project(":sop-java")))
|
testImplementation(project(":sop-java-testfixtures"))
|
||||||
|
|
||||||
// CLI
|
// CLI
|
||||||
implementation "info.picocli:picocli:$picocliVersion"
|
implementation "info.picocli:picocli:$picocliVersion"
|
||||||
annotationProcessor "info.picocli:picocli-codegen:$picocliVersion"
|
kapt "info.picocli:picocli-codegen:$picocliVersion"
|
||||||
|
|
||||||
// @Nonnull, @Nullable...
|
// @Nonnull, @Nullable...
|
||||||
implementation "com.google.code.findbugs:jsr305:$jsrVersion"
|
implementation "com.google.code.findbugs:jsr305:$jsrVersion"
|
||||||
|
@ -33,6 +33,10 @@ application {
|
||||||
mainClass = mainClassName
|
mainClass = mainClassName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compileJava {
|
||||||
|
options.compilerArgs += ["-Aproject=${project.group}/${project.name}"]
|
||||||
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
dependsOn(":sop-java:jar")
|
dependsOn(":sop-java:jar")
|
||||||
duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
|
duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
|
||||||
|
|
|
@ -64,7 +64,7 @@ class SopCLI {
|
||||||
@JvmField var EXECUTABLE_NAME = "sop"
|
@JvmField var EXECUTABLE_NAME = "sop"
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
@Option(names = ["--stacktrace"], scope = CommandLine.ScopeType.INHERIT)
|
@Option(names = ["--stacktrace"], scope = ScopeType.INHERIT)
|
||||||
var stacktrace = false
|
var stacktrace = false
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@ -78,33 +78,25 @@ class SopCLI {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun execute(vararg args: String): Int {
|
fun execute(vararg args: String): Int {
|
||||||
// Set locale
|
// Set locale
|
||||||
CommandLine(InitLocale()).parseArgs(*args)
|
CommandLine(InitLocale()).setUnmatchedArgumentsAllowed(true).parseArgs(*args)
|
||||||
|
|
||||||
// Re-set bundle with updated locale
|
// Re-set bundle with updated locale
|
||||||
cliMsg = ResourceBundle.getBundle("msg_sop")
|
cliMsg = ResourceBundle.getBundle("msg_sop")
|
||||||
|
|
||||||
val cmd =
|
return CommandLine(SopCLI::class.java)
|
||||||
CommandLine(SopCLI::class.java).apply {
|
.apply {
|
||||||
// explicitly set help command resource bundle
|
|
||||||
subcommands["help"]?.setResourceBundle(ResourceBundle.getBundle("msg_help"))
|
|
||||||
// Hide generate-completion command
|
// Hide generate-completion command
|
||||||
subcommands["generate-completion"]?.commandSpec?.usageMessage()?.hidden(true)
|
subcommands["generate-completion"]?.commandSpec?.usageMessage()?.hidden(true)
|
||||||
|
// render Input/Output sections in help command
|
||||||
|
subcommands.values.filter { (it.getCommand() as Any) is AbstractSopCmd } // Only for AbstractSopCmd objects
|
||||||
|
.forEach { (it.getCommand() as AbstractSopCmd).installIORenderer(it) }
|
||||||
// overwrite executable name
|
// overwrite executable name
|
||||||
commandName = EXECUTABLE_NAME
|
commandName = EXECUTABLE_NAME
|
||||||
// setup exception handling
|
// setup exception handling
|
||||||
executionExceptionHandler = SOPExecutionExceptionHandler()
|
executionExceptionHandler = SOPExecutionExceptionHandler()
|
||||||
exitCodeExceptionMapper = SOPExceptionExitCodeMapper()
|
exitCodeExceptionMapper = SOPExceptionExitCodeMapper()
|
||||||
isCaseInsensitiveEnumValuesAllowed = true
|
isCaseInsensitiveEnumValuesAllowed = true
|
||||||
}
|
}.execute(*args)
|
||||||
|
|
||||||
// render Input/Output sections in help command
|
|
||||||
cmd.subcommands.values
|
|
||||||
.filter {
|
|
||||||
(it.getCommand() as Any) is AbstractSopCmd
|
|
||||||
} // Only for AbstractSopCmd objects
|
|
||||||
.forEach { (it.getCommand() as AbstractSopCmd).installIORenderer(it) }
|
|
||||||
|
|
||||||
return cmd.execute(*args)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,9 +33,15 @@ class ChangeKeyPasswordCmd : AbstractSopCmd() {
|
||||||
changeKeyPassword.noArmor()
|
changeKeyPassword.noArmor()
|
||||||
}
|
}
|
||||||
|
|
||||||
oldKeyPasswords.forEach { changeKeyPassword.oldKeyPassphrase(it) }
|
oldKeyPasswords.forEach {
|
||||||
|
val password = stringFromInputStream(getInput(it))
|
||||||
|
changeKeyPassword.oldKeyPassphrase(password)
|
||||||
|
}
|
||||||
|
|
||||||
newKeyPassword?.let { changeKeyPassword.newKeyPassphrase(it) }
|
newKeyPassword?.let {
|
||||||
|
val password = stringFromInputStream(getInput(it))
|
||||||
|
changeKeyPassword.newKeyPassphrase(password)
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
changeKeyPassword.keys(System.`in`).writeTo(System.out)
|
changeKeyPassword.keys(System.`in`).writeTo(System.out)
|
||||||
|
|
|
@ -29,7 +29,7 @@ class DecryptCmd : AbstractSopCmd() {
|
||||||
@Option(names = [OPT_WITH_PASSWORD], paramLabel = "PASSWORD")
|
@Option(names = [OPT_WITH_PASSWORD], paramLabel = "PASSWORD")
|
||||||
var withPassword: List<String> = listOf()
|
var withPassword: List<String> = listOf()
|
||||||
|
|
||||||
@Option(names = [OPT_VERIFICATIONS_OUT], paramLabel = "VERIFICATIONS")
|
@Option(names = [OPT_VERIFICATIONS_OUT, "--verify-out"], paramLabel = "VERIFICATIONS")
|
||||||
var verifyOut: String? = null
|
var verifyOut: String? = null
|
||||||
|
|
||||||
@Option(names = [OPT_VERIFY_WITH], paramLabel = "CERT") var certs: List<String> = listOf()
|
@Option(names = [OPT_VERIFY_WITH], paramLabel = "CERT") var certs: List<String> = listOf()
|
||||||
|
|
24
sop-java-testfixtures/build.gradle
Normal file
24
sop-java-testfixtures/build.gradle
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id 'java-library'
|
||||||
|
}
|
||||||
|
|
||||||
|
group 'org.pgpainless'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":sop-java"))
|
||||||
|
implementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
|
||||||
|
implementation "org.junit.jupiter:junit-jupiter-params:$junitVersion"
|
||||||
|
runtimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
|
||||||
|
|
||||||
|
// @Nullable, @Nonnull annotations
|
||||||
|
implementation "com.google.code.findbugs:jsr305:3.0.2"
|
||||||
|
|
||||||
|
}
|
|
@ -5,8 +5,11 @@
|
||||||
package sop.testsuite.operation;
|
package sop.testsuite.operation;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Named;
|
import org.junit.jupiter.api.Named;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import sop.SOP;
|
import sop.SOP;
|
||||||
|
import sop.testsuite.AbortOnUnsupportedOption;
|
||||||
|
import sop.testsuite.AbortOnUnsupportedOptionExtension;
|
||||||
import sop.testsuite.SOPInstanceFactory;
|
import sop.testsuite.SOPInstanceFactory;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
@ -15,6 +18,8 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@ExtendWith(AbortOnUnsupportedOptionExtension.class)
|
||||||
|
@AbortOnUnsupportedOption
|
||||||
public abstract class AbstractSOPTest {
|
public abstract class AbstractSOPTest {
|
||||||
|
|
||||||
private static final List<Arguments> backends = new ArrayList<>();
|
private static final List<Arguments> backends = new ArrayList<>();
|
|
@ -0,0 +1,12 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package sop.testsuite
|
||||||
|
|
||||||
|
import java.lang.annotation.Inherited
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@Inherited
|
||||||
|
annotation class AbortOnUnsupportedOption
|
|
@ -0,0 +1,21 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package sop.testsuite
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assumptions
|
||||||
|
import org.junit.jupiter.api.extension.ExtensionContext
|
||||||
|
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler
|
||||||
|
import sop.exception.SOPGPException
|
||||||
|
|
||||||
|
class AbortOnUnsupportedOptionExtension : TestExecutionExceptionHandler {
|
||||||
|
override fun handleTestExecutionException(context: ExtensionContext, throwable: Throwable) {
|
||||||
|
val testClass = context.requiredTestClass
|
||||||
|
val annotation = testClass.getAnnotation(AbortOnUnsupportedOption::class.java)
|
||||||
|
if (annotation != null && SOPGPException.UnsupportedOption::class.isInstance(throwable)) {
|
||||||
|
Assumptions.assumeTrue(false, "Test aborted due to: " + throwable.message)
|
||||||
|
}
|
||||||
|
throw throwable
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,12 @@
|
||||||
|
import org.apache.tools.ant.filters.ReplaceTokens
|
||||||
|
|
||||||
// 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'
|
||||||
id 'java-test-fixtures'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
group 'org.pgpainless'
|
group 'org.pgpainless'
|
||||||
|
@ -17,14 +19,19 @@ dependencies {
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
|
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion"
|
testImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion"
|
||||||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
|
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
|
||||||
testFixturesImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
|
testImplementation(project(":sop-java-testfixtures"))
|
||||||
testFixturesImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion"
|
|
||||||
|
|
||||||
// @Nullable, @Nonnull annotations
|
// @Nullable, @Nonnull annotations
|
||||||
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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,9 @@ package sop
|
||||||
*
|
*
|
||||||
* @param micAlg string identifying the digest mechanism used to create the signed message. This is
|
* @param micAlg string identifying the digest mechanism used to create the signed message. This is
|
||||||
* useful for setting the `micalg=` parameter for the multipart/signed content-type of a PGP/MIME
|
* useful for setting the `micalg=` parameter for the multipart/signed content-type of a PGP/MIME
|
||||||
* object as described in section 5 of [RFC3156]. If more than one signature was generated and
|
* object as described in section 5 of [RFC3156](https://www.rfc-editor.org/rfc/rfc3156#section-5).
|
||||||
* different digest mechanisms were used, the value of the micalg object is an empty string.
|
* If more than one signature was generated and different digest mechanisms were used, the value
|
||||||
|
* of the micalg object is an empty string.
|
||||||
*/
|
*/
|
||||||
data class SigningResult(val micAlg: MicAlg) {
|
data class SigningResult(val micAlg: MicAlg) {
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ interface GenerateKey {
|
||||||
fun signingOnly(): GenerateKey
|
fun signingOnly(): GenerateKey
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the OpenPGP key and return it encoded as an [InputStream].
|
* Generate the OpenPGP key and return it encoded as an [java.io.InputStream].
|
||||||
*
|
*
|
||||||
* @return key
|
* @return key
|
||||||
* @throws MissingArg if no user-id was provided
|
* @throws MissingArg if no user-id was provided
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
|
|
||||||
package sop.operation
|
package sop.operation
|
||||||
|
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.util.*
|
||||||
import kotlin.jvm.Throws
|
import kotlin.jvm.Throws
|
||||||
import sop.exception.SOPGPException
|
import sop.exception.SOPGPException
|
||||||
|
|
||||||
|
@ -107,4 +110,17 @@ interface Version {
|
||||||
* this method throws an [SOPGPException.UnsupportedOption] instead.
|
* this method throws an [SOPGPException.UnsupportedOption] instead.
|
||||||
*/
|
*/
|
||||||
@Throws(SOPGPException.UnsupportedOption::class) fun getSopVVersion(): String
|
@Throws(SOPGPException.UnsupportedOption::class) fun getSopVVersion(): String
|
||||||
|
|
||||||
|
/** Return the current version of the SOP-Java library. */
|
||||||
|
fun getSopJavaVersion(): String? {
|
||||||
|
return try {
|
||||||
|
val resourceIn: InputStream =
|
||||||
|
javaClass.getResourceAsStream("/sop-java-version.properties")
|
||||||
|
?: throw IOException("File sop-java-version.properties not found.")
|
||||||
|
val properties = Properties().apply { load(resourceIn) }
|
||||||
|
properties.getProperty("sop-java-version")
|
||||||
|
} catch (e: IOException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import java.io.OutputStream
|
||||||
* target output stream is not yet known.
|
* target output stream is not yet known.
|
||||||
*/
|
*/
|
||||||
@Deprecated("Marked for removal.")
|
@Deprecated("Marked for removal.")
|
||||||
|
// TODO: Remove in 11.X
|
||||||
class ProxyOutputStream : OutputStream() {
|
class ProxyOutputStream : OutputStream() {
|
||||||
private val buffer = ByteArrayOutputStream()
|
private val buffer = ByteArrayOutputStream()
|
||||||
private var swapped: OutputStream? = null
|
private var swapped: OutputStream? = null
|
||||||
|
|
4
sop-java/src/main/resources/sop-java-version.properties
Normal file
4
sop-java/src/main/resources/sop-java-version.properties
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# SPDX-FileCopyrightText: 2025 Paul Schaub <info@pgpainless.org>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
sop-java-version=@project.version@
|
|
@ -12,7 +12,7 @@ allprojects {
|
||||||
jsrVersion = '3.0.2'
|
jsrVersion = '3.0.2'
|
||||||
junitVersion = '5.8.2'
|
junitVersion = '5.8.2'
|
||||||
junitSysExitVersion = '1.1.2'
|
junitSysExitVersion = '1.1.2'
|
||||||
logbackVersion = '1.2.13'
|
logbackVersion = '1.2.13' // 1.4+ cause CLI spam
|
||||||
mockitoVersion = '4.5.1'
|
mockitoVersion = '4.5.1'
|
||||||
picocliVersion = '4.6.3'
|
picocliVersion = '4.6.3'
|
||||||
slf4jVersion = '1.7.36'
|
slf4jVersion = '1.7.36'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue