mirror of
https://codeberg.org/PGPainless/sop-java.git
synced 2024-11-26 00:52:07 +01:00
Implement certify-userid command
This commit is contained in:
parent
a607013cfb
commit
3104085fe7
6 changed files with 177 additions and 0 deletions
|
@ -29,6 +29,7 @@ import sop.exception.SOPGPException
|
||||||
ExtractCertCmd::class,
|
ExtractCertCmd::class,
|
||||||
UpdateKeyCmd::class,
|
UpdateKeyCmd::class,
|
||||||
MergeCertsCmd::class,
|
MergeCertsCmd::class,
|
||||||
|
CertifyUserIdCmd::class,
|
||||||
// Messaging subcommands
|
// Messaging subcommands
|
||||||
SignCmd::class,
|
SignCmd::class,
|
||||||
VerifyCmd::class,
|
VerifyCmd::class,
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package sop.cli.picocli.commands
|
||||||
|
|
||||||
|
import java.io.IOException
|
||||||
|
import picocli.CommandLine.Command
|
||||||
|
import picocli.CommandLine.Model.CommandSpec
|
||||||
|
import picocli.CommandLine.Option
|
||||||
|
import picocli.CommandLine.Parameters
|
||||||
|
import picocli.CommandLine.Spec
|
||||||
|
import sop.cli.picocli.SopCLI
|
||||||
|
import sop.exception.SOPGPException.BadData
|
||||||
|
import sop.exception.SOPGPException.UnsupportedOption
|
||||||
|
|
||||||
|
@Command(
|
||||||
|
name = "certify-userid",
|
||||||
|
resourceBundle = "msg_certify-userid",
|
||||||
|
exitCodeOnInvalidInput = UnsupportedOption.EXIT_CODE)
|
||||||
|
class CertifyUserIdCmd : AbstractSopCmd() {
|
||||||
|
|
||||||
|
@Spec var spec: CommandSpec? = null
|
||||||
|
|
||||||
|
@Option(names = ["--no-armor"], negatable = true) var armor = true
|
||||||
|
|
||||||
|
@Option(names = ["--userid"], required = true, arity = "1..*", paramLabel = "USERID")
|
||||||
|
var userIds: List<String> = listOf()
|
||||||
|
|
||||||
|
@Option(names = ["--with-key-password"], paramLabel = "PASSWORD")
|
||||||
|
var withKeyPassword: List<String> = listOf()
|
||||||
|
|
||||||
|
@Option(names = ["--no-require-self-sig"]) var noRequireSelfSig = false
|
||||||
|
|
||||||
|
@Parameters(paramLabel = "KEYS", arity = "1..*") var keys: List<String> = listOf()
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
val certifyUserId =
|
||||||
|
throwIfUnsupportedSubcommand(SopCLI.getSop().certifyUserId(), "certify-userid")
|
||||||
|
|
||||||
|
if (!armor) {
|
||||||
|
certifyUserId.noArmor()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noRequireSelfSig) {
|
||||||
|
certifyUserId.noRequireSelfSig()
|
||||||
|
}
|
||||||
|
|
||||||
|
for (userId in userIds) {
|
||||||
|
certifyUserId.userId(userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (passwordFileName in withKeyPassword) {
|
||||||
|
try {
|
||||||
|
val password = stringFromInputStream(getInput(passwordFileName))
|
||||||
|
certifyUserId.withKeyPassword(password)
|
||||||
|
} catch (unsupportedOption: UnsupportedOption) {
|
||||||
|
val errorMsg =
|
||||||
|
getMsg("sop.error.feature_support.option_not_supported", "--with-key-password")
|
||||||
|
throw UnsupportedOption(errorMsg, unsupportedOption)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
throw RuntimeException(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (keyInput in keys) {
|
||||||
|
try {
|
||||||
|
getInput(keyInput).use { certifyUserId.keys(it) }
|
||||||
|
} catch (e: IOException) {
|
||||||
|
throw RuntimeException(e)
|
||||||
|
} catch (badData: BadData) {
|
||||||
|
val errorMsg = getMsg("sop.error.input.not_a_private_key", keyInput)
|
||||||
|
throw BadData(errorMsg, badData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
val ready = certifyUserId.certs(System.`in`)
|
||||||
|
ready.writeTo(System.out)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
throw RuntimeException(e)
|
||||||
|
} catch (badData: BadData) {
|
||||||
|
val errorMsg = getMsg("sop.error.input.not_a_private_key", "STDIN")
|
||||||
|
throw BadData(errorMsg, badData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
# SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
usage.header=Certify OpenPGP Certificate User IDs
|
||||||
|
no-armor=ASCII armor the output
|
||||||
|
userid=Identities that shall be certified
|
||||||
|
with-key-password.0=Passphrase to unlock the secret key(s).
|
||||||
|
with-key-password.1=Is an INDIRECT data type (e.g. file, environment variable, file descriptor...).
|
||||||
|
no-require-self-sig=Certify the UserID regardless of whether self-certifications are present
|
||||||
|
KEYS[0..*]=Private keys
|
||||||
|
|
||||||
|
standardInput=CERTS
|
||||||
|
standardInputDescription=Certificates that shall be certified
|
||||||
|
standardOutput=CERTS
|
||||||
|
standardOutputDescription=Certified certificates
|
||||||
|
|
||||||
|
stacktrace=Print stacktrace
|
||||||
|
# Generic TODO: Remove when bumping picocli to 4.7.0
|
||||||
|
usage.parameterListHeading=Parameters:%n
|
||||||
|
usage.synopsisHeading=Usage:\u0020
|
||||||
|
usage.commandListHeading = Commands:%n
|
||||||
|
usage.optionListHeading = Options:%n
|
||||||
|
usage.footerHeading=Powered by picocli%n
|
|
@ -0,0 +1,20 @@
|
||||||
|
# SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
usage.header=Zertifiziere OpenPGP Zertifikat Identitäten
|
||||||
|
no-armor=Schütze Ausgabe mit ASCII Armor
|
||||||
|
userid=Identität, die zertifiziert werden soll
|
||||||
|
with-key-password.0=Passwort zum Entsperren der privaten Schlüssel
|
||||||
|
with-key-password.1=Ist INDIREKTER Datentyp (z.B.. Datei, Umgebungsvariable, Dateideskriptor...).
|
||||||
|
no-require-self-sig=Zertifiziere die Identität, unabhängig davon, ob eine Selbstzertifizierung vorhanden ist
|
||||||
|
KEYS[0..*]=Private Schlüssel
|
||||||
|
|
||||||
|
standardInputDescription=Zertifikate, auf denen Identitäten zertifiziert werden sollen
|
||||||
|
standardOutputDescription=Zertifizierte Zertifikate
|
||||||
|
|
||||||
|
# Generic TODO: Remove when bumping picocli to 4.7.0
|
||||||
|
usage.parameterListHeading=Parameter:%n
|
||||||
|
usage.synopsisHeading=Aufruf:\u0020
|
||||||
|
usage.commandListHeading=Befehle:%n
|
||||||
|
usage.optionListHeading = Optionen:%n
|
||||||
|
usage.footerHeading=Powered by Picocli%n
|
|
@ -69,4 +69,9 @@ interface SOP : SOPV {
|
||||||
* Merge OpenPGP certificates.
|
* Merge OpenPGP certificates.
|
||||||
*/
|
*/
|
||||||
fun mergeCerts(): MergeCerts
|
fun mergeCerts(): MergeCerts
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Certify OpenPGP Certificate User-IDs.
|
||||||
|
*/
|
||||||
|
fun certifyUserId(): CertifyUserId
|
||||||
}
|
}
|
||||||
|
|
41
sop-java/src/main/kotlin/sop/operation/CertifyUserId.kt
Normal file
41
sop-java/src/main/kotlin/sop/operation/CertifyUserId.kt
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package sop.operation
|
||||||
|
|
||||||
|
import sop.Ready
|
||||||
|
import sop.exception.SOPGPException
|
||||||
|
import sop.util.UTF8Util
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
interface CertifyUserId {
|
||||||
|
|
||||||
|
@Throws(SOPGPException.UnsupportedOption::class)
|
||||||
|
fun noArmor(): CertifyUserId
|
||||||
|
|
||||||
|
@Throws(SOPGPException.UnsupportedOption::class)
|
||||||
|
fun userId(userId: String): CertifyUserId
|
||||||
|
|
||||||
|
@Throws(SOPGPException.PasswordNotHumanReadable::class, SOPGPException.UnsupportedOption::class)
|
||||||
|
fun withKeyPassword(password: String): CertifyUserId = withKeyPassword(password.toByteArray(UTF8Util.UTF8))
|
||||||
|
|
||||||
|
@Throws(SOPGPException.PasswordNotHumanReadable::class, SOPGPException.UnsupportedOption::class)
|
||||||
|
fun withKeyPassword(password: ByteArray): CertifyUserId
|
||||||
|
|
||||||
|
@Throws(SOPGPException.UnsupportedOption::class)
|
||||||
|
fun noRequireSelfSig(): CertifyUserId
|
||||||
|
|
||||||
|
@Throws(SOPGPException.BadData::class, IOException::class, SOPGPException.KeyIsProtected::class)
|
||||||
|
fun keys(keys: InputStream): CertifyUserId
|
||||||
|
|
||||||
|
@Throws(SOPGPException.BadData::class, IOException::class, SOPGPException.KeyIsProtected::class)
|
||||||
|
fun keys(keys: ByteArray): CertifyUserId = keys(keys.inputStream())
|
||||||
|
|
||||||
|
@Throws(SOPGPException.BadData::class, IOException::class, SOPGPException.CertUserIdNoMatch::class)
|
||||||
|
fun certs(certs: InputStream): Ready
|
||||||
|
|
||||||
|
@Throws(SOPGPException.BadData::class, IOException::class, SOPGPException.CertUserIdNoMatch::class)
|
||||||
|
fun certs(certs: ByteArray): Ready = certs(certs.inputStream())
|
||||||
|
}
|
Loading…
Reference in a new issue