1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-09-09 18:29:39 +02:00

Implement crude update-key command (only merges certs for now)

This commit is contained in:
Paul Schaub 2025-04-10 15:28:06 +02:00
parent b7dedbd619
commit 1dd666d32b
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
2 changed files with 85 additions and 1 deletions

View file

@ -66,7 +66,7 @@ class SOPImpl(
override fun revokeKey(): RevokeKey = RevokeKeyImpl(api)
override fun updateKey(): UpdateKey? = null
override fun updateKey(): UpdateKey = UpdateKeyImpl(api)
override fun validateUserId(): ValidateUserId = ValidateUserIdImpl(api)

View file

@ -0,0 +1,84 @@
// SPDX-FileCopyrightText: 2025 Paul Schaub <info@pgpainless.org>
//
// SPDX-License-Identifier: CC0-1.0
package org.pgpainless.sop
import java.io.InputStream
import java.io.OutputStream
import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.bcpg.PacketFormat
import org.bouncycastle.openpgp.PGPSecretKeyRing
import org.bouncycastle.openpgp.api.OpenPGPCertificate
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.pgpainless.PGPainless
import org.pgpainless.util.ArmoredOutputStreamFactory
import org.pgpainless.util.Passphrase
import sop.Ready
import sop.operation.UpdateKey
class UpdateKeyImpl(private val api: PGPainless) : UpdateKey {
private var armor = true
private var addCapabilities = true
private var signingOnly = false
private val protector: MatchMakingSecretKeyRingProtector = MatchMakingSecretKeyRingProtector()
private val mergeCerts: MutableMap<KeyIdentifier, OpenPGPCertificate> = mutableMapOf()
override fun key(key: InputStream): Ready {
return object : Ready() {
override fun writeTo(outputStream: OutputStream) {
val out =
if (armor) {
ArmoredOutputStreamFactory.get(outputStream)
} else {
outputStream
}
val keyList = api.readKey().parseKeys(key)
for (k in keyList) {
val updatedKey: OpenPGPKey =
if (mergeCerts[k.keyIdentifier] == null) {
k
} else {
val updatedCert: OpenPGPCertificate =
api.mergeCertificate(
k.toCertificate(), mergeCerts[k.keyIdentifier]!!)
api.toKey(
PGPSecretKeyRing.replacePublicKeys(
k.pgpSecretKeyRing, updatedCert.pgpPublicKeyRing))
}
out.write(updatedKey.getEncoded(PacketFormat.CURRENT))
}
if (armor) {
out.close()
}
outputStream.close()
}
}
}
override fun mergeCerts(certs: InputStream): UpdateKey = apply {
val certList = api.readKey().parseCertificates(certs)
for (cert in certList) {
if (mergeCerts[cert.keyIdentifier] == null) {
mergeCerts[cert.keyIdentifier] = cert
} else {
val existing = mergeCerts[cert.keyIdentifier]!!
mergeCerts[cert.keyIdentifier] = api.mergeCertificate(existing, cert)
}
}
}
override fun noAddedCapabilities(): UpdateKey = apply { addCapabilities = false }
override fun noArmor(): UpdateKey = apply { armor = false }
override fun signingOnly(): UpdateKey = apply { signingOnly = true }
override fun withKeyPassword(password: ByteArray): UpdateKey = apply {
protector.addPassphrase(Passphrase.fromPassword(String(password)))
}
}