mirror of
https://codeberg.org/PGPainless/sop-java.git
synced 2024-11-26 17:12:08 +01:00
Add implementation of update-key command
This commit is contained in:
parent
a07446e29a
commit
a2315f9847
6 changed files with 163 additions and 12 deletions
|
@ -27,6 +27,7 @@ import sop.exception.SOPGPException
|
||||||
ChangeKeyPasswordCmd::class,
|
ChangeKeyPasswordCmd::class,
|
||||||
RevokeKeyCmd::class,
|
RevokeKeyCmd::class,
|
||||||
ExtractCertCmd::class,
|
ExtractCertCmd::class,
|
||||||
|
UpdateKeyCmd::class,
|
||||||
// Messaging subcommands
|
// Messaging subcommands
|
||||||
SignCmd::class,
|
SignCmd::class,
|
||||||
VerifyCmd::class,
|
VerifyCmd::class,
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package sop.cli.picocli.commands
|
||||||
|
|
||||||
|
import picocli.CommandLine.Command
|
||||||
|
import picocli.CommandLine.Option
|
||||||
|
import sop.cli.picocli.SopCLI
|
||||||
|
import sop.exception.SOPGPException.*
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
@Command(
|
||||||
|
name = "update-key",
|
||||||
|
resourceBundle = "msg_update-key",
|
||||||
|
exitCodeOnInvalidInput = UnsupportedOption.EXIT_CODE)
|
||||||
|
class UpdateKeyCmd : AbstractSopCmd() {
|
||||||
|
|
||||||
|
@Option(names = ["--no-armor"], negatable = true) var armor = true
|
||||||
|
|
||||||
|
@Option(names = ["--signing-only"]) var signingOnly = false
|
||||||
|
|
||||||
|
@Option(names = ["--no-new-mechanisms"]) var noNewMechanisms = false
|
||||||
|
|
||||||
|
@Option(names = ["--with-key-password"], paramLabel = "PASSWORD")
|
||||||
|
var withKeyPassword: List<String> = listOf()
|
||||||
|
|
||||||
|
@Option(names = ["--merge-certs"], paramLabel = "CERTS")
|
||||||
|
var mergeCerts: List<String> = listOf()
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
val updateKey = throwIfUnsupportedSubcommand(SopCLI.getSop().updateKey(), "update-key")
|
||||||
|
|
||||||
|
if (!armor) {
|
||||||
|
updateKey.noArmor()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signingOnly) {
|
||||||
|
updateKey.signingOnly()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noNewMechanisms) {
|
||||||
|
updateKey.noNewMechanisms()
|
||||||
|
}
|
||||||
|
|
||||||
|
for (passwordFileName in withKeyPassword) {
|
||||||
|
try {
|
||||||
|
val password = stringFromInputStream(getInput(passwordFileName))
|
||||||
|
updateKey.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 (certInput in mergeCerts) {
|
||||||
|
try {
|
||||||
|
getInput(certInput).use { certIn -> updateKey.mergeCerts(certIn) }
|
||||||
|
} catch (e: IOException) {
|
||||||
|
throw RuntimeException(e)
|
||||||
|
} catch (badData: BadData) {
|
||||||
|
val errorMsg = getMsg("sop.error.input.not_a_certificate", certInput)
|
||||||
|
throw BadData(errorMsg, badData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
val ready = updateKey.key(System.`in`)
|
||||||
|
ready.writeTo(System.out)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
throw RuntimeException(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
# SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
usage.header=Keep a secret key up-to-date
|
||||||
|
no-armor=ASCII armor the output
|
||||||
|
signing-only=TODO: Document
|
||||||
|
no-new-mechanisms=Do not add feature support for new mechanisms, which the key did not previously support
|
||||||
|
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...).
|
||||||
|
merge-certs.0=Merge additional elements found in the corresponding CERTS objects into the updated secret keys
|
||||||
|
merge-certs.1=This can be used, for example, to absorb a third-party certification into the Transferable Secret Key
|
||||||
|
|
||||||
|
stacktrace=Print stacktrace
|
||||||
|
# Generic TODO: Remove when bumping picocli to 4.7.0
|
||||||
|
usage.parameterListHeading=%nParameters:%n
|
||||||
|
usage.synopsisHeading=Usage:\u0020
|
||||||
|
usage.commandListHeading = %nCommands:%n
|
||||||
|
usage.optionListHeading = %nOptions:%n
|
||||||
|
usage.footerHeading=Powered by picocli%n
|
|
@ -0,0 +1,18 @@
|
||||||
|
# SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
usage.header=Halte einen Schlüssel auf dem neusten Stand
|
||||||
|
no-armor=Schütze Ausgabe mit ASCII Armor
|
||||||
|
signing-only=TODO: Dokumentieren
|
||||||
|
no-new-mechanisms=Füge keine neuen Funktionen hinzu, die der Schlüssel nicht bereits zuvor unterstützt hat
|
||||||
|
with-key-password.0=Passwort zum Entsperren der privaten Schlüssel
|
||||||
|
with-key-password.1=Ist INDIREKTER Datentyp (z.B.. Datei, Umgebungsvariable, Dateideskriptor...).
|
||||||
|
merge-certs.0=Führe zusätzliche Elemente aus entsprechenden CERTS Objekten mit dem privaten Schlüssel zusammen
|
||||||
|
merge-certs.1=Dies kann zum Beispiel dazu genutzt werden, Zertifizierungen dritter in den privaten Schlüssel zu übernehmen
|
||||||
|
|
||||||
|
# Generic TODO: Remove when bumping picocli to 4.7.0
|
||||||
|
usage.parameterListHeading=%nParameter:%n
|
||||||
|
usage.synopsisHeading=Aufruf:\u0020
|
||||||
|
usage.commandListHeading=%nBefehle:%n
|
||||||
|
usage.optionListHeading = %nOptionen:%n
|
||||||
|
usage.footerHeading=Powered by Picocli%n
|
|
@ -4,18 +4,7 @@
|
||||||
|
|
||||||
package sop
|
package sop
|
||||||
|
|
||||||
import sop.operation.Armor
|
import sop.operation.*
|
||||||
import sop.operation.ChangeKeyPassword
|
|
||||||
import sop.operation.Dearmor
|
|
||||||
import sop.operation.Decrypt
|
|
||||||
import sop.operation.DetachedSign
|
|
||||||
import sop.operation.Encrypt
|
|
||||||
import sop.operation.ExtractCert
|
|
||||||
import sop.operation.GenerateKey
|
|
||||||
import sop.operation.InlineDetach
|
|
||||||
import sop.operation.InlineSign
|
|
||||||
import sop.operation.ListProfiles
|
|
||||||
import sop.operation.RevokeKey
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stateless OpenPGP Interface. This class provides a stateless interface to various OpenPGP related
|
* Stateless OpenPGP Interface. This class provides a stateless interface to various OpenPGP related
|
||||||
|
@ -70,4 +59,9 @@ interface SOP : SOPV {
|
||||||
|
|
||||||
/** Update a key's password. */
|
/** Update a key's password. */
|
||||||
fun changeKeyPassword(): ChangeKeyPassword
|
fun changeKeyPassword(): ChangeKeyPassword
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep a secret key up-to-date.
|
||||||
|
*/
|
||||||
|
fun updateKey(): UpdateKey
|
||||||
}
|
}
|
||||||
|
|
43
sop-java/src/main/kotlin/sop/operation/UpdateKey.kt
Normal file
43
sop-java/src/main/kotlin/sop/operation/UpdateKey.kt
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// 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 UpdateKey {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable ASCII armor encoding of the output.
|
||||||
|
*
|
||||||
|
* @return builder instance
|
||||||
|
*/
|
||||||
|
fun noArmor(): UpdateKey
|
||||||
|
|
||||||
|
@Throws(SOPGPException.UnsupportedOption::class) fun signingOnly(): UpdateKey
|
||||||
|
|
||||||
|
@Throws(SOPGPException.UnsupportedOption::class) fun noNewMechanisms(): UpdateKey
|
||||||
|
|
||||||
|
@Throws(SOPGPException.PasswordNotHumanReadable::class, SOPGPException.UnsupportedOption::class)
|
||||||
|
fun withKeyPassword(password: String): UpdateKey = withKeyPassword(password.toByteArray(UTF8Util.UTF8))
|
||||||
|
|
||||||
|
@Throws(SOPGPException.PasswordNotHumanReadable::class, SOPGPException.UnsupportedOption::class)
|
||||||
|
fun withKeyPassword(password: ByteArray): UpdateKey
|
||||||
|
|
||||||
|
@Throws(SOPGPException.UnsupportedOption::class, SOPGPException.BadData::class, IOException::class)
|
||||||
|
fun mergeCerts(certs: InputStream): UpdateKey
|
||||||
|
|
||||||
|
@Throws(SOPGPException.UnsupportedOption::class, SOPGPException.BadData::class, IOException::class)
|
||||||
|
fun mergeCerts(certs: ByteArray): UpdateKey = mergeCerts(certs.inputStream())
|
||||||
|
|
||||||
|
@Throws(SOPGPException.BadData::class, IOException::class, SOPGPException.KeyIsProtected::class, SOPGPException.PrimaryKeyBad::class)
|
||||||
|
fun key(key: InputStream): Ready
|
||||||
|
|
||||||
|
@Throws(SOPGPException.BadData::class, IOException::class, SOPGPException.KeyIsProtected::class, SOPGPException.PrimaryKeyBad::class)
|
||||||
|
fun key(key: ByteArray): Ready = key(key.inputStream())
|
||||||
|
}
|
Loading…
Reference in a new issue