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

SOP: Inject API instance

This commit is contained in:
Paul Schaub 2025-03-20 15:03:24 +01:00
parent 57540d8028
commit 2200cb7372
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
18 changed files with 72 additions and 62 deletions

View file

@ -9,6 +9,7 @@ import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import kotlin.jvm.Throws import kotlin.jvm.Throws
import org.bouncycastle.util.io.Streams import org.bouncycastle.util.io.Streams
import org.pgpainless.PGPainless
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
@ -16,7 +17,7 @@ import sop.exception.SOPGPException
import sop.operation.Armor import sop.operation.Armor
/** Implementation of the `armor` operation using PGPainless. */ /** Implementation of the `armor` operation using PGPainless. */
class ArmorImpl : Armor { class ArmorImpl(private val api: PGPainless) : Armor {
@Throws(SOPGPException.BadData::class) @Throws(SOPGPException.BadData::class)
override fun data(data: InputStream): Ready { override fun data(data: InputStream): Ready {

View file

@ -9,6 +9,7 @@ import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import org.bouncycastle.openpgp.PGPException import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection import org.bouncycastle.openpgp.PGPSecretKeyRingCollection
import org.pgpainless.PGPainless
import org.pgpainless.bouncycastle.extensions.openPgpFingerprint import org.pgpainless.bouncycastle.extensions.openPgpFingerprint
import org.pgpainless.exception.MissingPassphraseException import org.pgpainless.exception.MissingPassphraseException
import org.pgpainless.key.protection.SecretKeyRingProtector import org.pgpainless.key.protection.SecretKeyRingProtector
@ -20,7 +21,7 @@ import sop.exception.SOPGPException
import sop.operation.ChangeKeyPassword import sop.operation.ChangeKeyPassword
/** Implementation of the `change-key-password` operation using PGPainless. */ /** Implementation of the `change-key-password` operation using PGPainless. */
class ChangeKeyPasswordImpl : ChangeKeyPassword { class ChangeKeyPasswordImpl(private val api: PGPainless) : ChangeKeyPassword {
private val oldProtector = MatchMakingSecretKeyRingProtector() private val oldProtector = MatchMakingSecretKeyRingProtector()
private var newPassphrase = Passphrase.emptyPassphrase() private var newPassphrase = Passphrase.emptyPassphrase()

View file

@ -10,12 +10,13 @@ import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import org.bouncycastle.openpgp.PGPUtil import org.bouncycastle.openpgp.PGPUtil
import org.bouncycastle.util.io.Streams import org.bouncycastle.util.io.Streams
import org.pgpainless.PGPainless
import sop.Ready import sop.Ready
import sop.exception.SOPGPException import sop.exception.SOPGPException
import sop.operation.Dearmor import sop.operation.Dearmor
/** Implementation of the `dearmor` operation using PGPainless. */ /** Implementation of the `dearmor` operation using PGPainless. */
class DearmorImpl : Dearmor { class DearmorImpl(private val api: PGPainless) : Dearmor {
override fun data(data: InputStream): Ready { override fun data(data: InputStream): Ready {
val decoder = val decoder =

View file

@ -25,9 +25,9 @@ import sop.operation.Decrypt
import sop.util.UTF8Util import sop.util.UTF8Util
/** Implementation of the `decrypt` operation using PGPainless. */ /** Implementation of the `decrypt` operation using PGPainless. */
class DecryptImpl : Decrypt { class DecryptImpl(private val api: PGPainless) : Decrypt {
private val consumerOptions = ConsumerOptions.get() private val consumerOptions = ConsumerOptions.get(api)
private val protector = MatchMakingSecretKeyRingProtector() private val protector = MatchMakingSecretKeyRingProtector()
override fun ciphertext(ciphertext: InputStream): ReadyWithResult<DecryptionResult> { override fun ciphertext(ciphertext: InputStream): ReadyWithResult<DecryptionResult> {

View file

@ -30,9 +30,9 @@ import sop.operation.DetachedSign
import sop.util.UTF8Util import sop.util.UTF8Util
/** Implementation of the `sign` operation using PGPainless. */ /** Implementation of the `sign` operation using PGPainless. */
class DetachedSignImpl : DetachedSign { class DetachedSignImpl(private val api: PGPainless) : DetachedSign {
private val signingOptions = SigningOptions.get() private val signingOptions = SigningOptions.get(api)
private val protector = MatchMakingSecretKeyRingProtector() private val protector = MatchMakingSecretKeyRingProtector()
private val signingKeys = mutableListOf<PGPSecretKeyRing>() private val signingKeys = mutableListOf<PGPSecretKeyRing>()
@ -56,10 +56,10 @@ class DetachedSignImpl : DetachedSign {
try { try {
val signingStream = val signingStream =
PGPainless.encryptAndOrSign() api.generateMessage()
.discardOutput() .discardOutput()
.withOptions( .withOptions(
ProducerOptions.sign(signingOptions) ProducerOptions.sign(signingOptions, api)
.setAsciiArmor(armor) .setAsciiArmor(armor)
.overrideCompressionAlgorithm(CompressionAlgorithm.UNCOMPRESSED)) .overrideCompressionAlgorithm(CompressionAlgorithm.UNCOMPRESSED))
@ -94,7 +94,7 @@ class DetachedSignImpl : DetachedSign {
override fun key(key: InputStream): DetachedSign = apply { override fun key(key: InputStream): DetachedSign = apply {
KeyReader.readSecretKeys(key, true).forEach { KeyReader.readSecretKeys(key, true).forEach {
val info = PGPainless.inspectKeyRing(it) val info = api.inspect(api.toKey(it))
if (!info.isUsableForSigning) { if (!info.isUsableForSigning) {
throw SOPGPException.KeyCannotSign( throw SOPGPException.KeyCannotSign(
"Key ${info.fingerprint} does not have valid, signing capable subkeys.") "Key ${info.fingerprint} does not have valid, signing capable subkeys.")

View file

@ -18,9 +18,9 @@ import sop.operation.DetachedVerify
import sop.operation.VerifySignatures import sop.operation.VerifySignatures
/** Implementation of the `verify` operation using PGPainless. */ /** Implementation of the `verify` operation using PGPainless. */
class DetachedVerifyImpl : DetachedVerify { class DetachedVerifyImpl(private val api: PGPainless) : DetachedVerify {
private val options = ConsumerOptions.get().forceNonOpenPgpData() private val options = ConsumerOptions.get(api).forceNonOpenPgpData()
override fun cert(cert: InputStream): DetachedVerify = apply { override fun cert(cert: InputStream): DetachedVerify = apply {
options.addVerificationCerts(KeyReader.readPublicKeys(cert, true)) options.addVerificationCerts(KeyReader.readPublicKeys(cert, true))

View file

@ -30,7 +30,7 @@ import sop.operation.Encrypt
import sop.util.UTF8Util import sop.util.UTF8Util
/** Implementation of the `encrypt` operation using PGPainless. */ /** Implementation of the `encrypt` operation using PGPainless. */
class EncryptImpl : Encrypt { class EncryptImpl(private val api: PGPainless) : Encrypt {
companion object { companion object {
@JvmField val RFC4880_PROFILE = Profile("rfc4880", "Follow the packet format of rfc4880") @JvmField val RFC4880_PROFILE = Profile("rfc4880", "Follow the packet format of rfc4880")
@ -38,7 +38,7 @@ class EncryptImpl : Encrypt {
@JvmField val SUPPORTED_PROFILES = listOf(RFC4880_PROFILE) @JvmField val SUPPORTED_PROFILES = listOf(RFC4880_PROFILE)
} }
private val encryptionOptions = EncryptionOptions.get() private val encryptionOptions = EncryptionOptions.get(api)
private var signingOptions: SigningOptions? = null private var signingOptions: SigningOptions? = null
private val signingKeys = mutableListOf<PGPSecretKeyRing>() private val signingKeys = mutableListOf<PGPSecretKeyRing>()
private val protector = MatchMakingSecretKeyRingProtector() private val protector = MatchMakingSecretKeyRingProtector()
@ -58,9 +58,9 @@ class EncryptImpl : Encrypt {
val options = val options =
if (signingOptions != null) { if (signingOptions != null) {
ProducerOptions.signAndEncrypt(encryptionOptions, signingOptions!!) ProducerOptions.signAndEncrypt(encryptionOptions, signingOptions!!, api)
} else { } else {
ProducerOptions.encrypt(encryptionOptions) ProducerOptions.encrypt(encryptionOptions, api)
} }
.setAsciiArmor(armor) .setAsciiArmor(armor)
.setEncoding(modeToStreamEncoding(mode)) .setEncoding(modeToStreamEncoding(mode))
@ -81,9 +81,7 @@ class EncryptImpl : Encrypt {
return object : ReadyWithResult<EncryptionResult>() { return object : ReadyWithResult<EncryptionResult>() {
override fun writeTo(outputStream: OutputStream): EncryptionResult { override fun writeTo(outputStream: OutputStream): EncryptionResult {
val encryptionStream = val encryptionStream =
PGPainless.encryptAndOrSign() api.generateMessage().onOutputStream(outputStream).withOptions(options)
.onOutputStream(outputStream)
.withOptions(options)
Streams.pipeAll(plaintext, encryptionStream) Streams.pipeAll(plaintext, encryptionStream)
encryptionStream.close() encryptionStream.close()
// TODO: Extract and emit session key once BC supports that // TODO: Extract and emit session key once BC supports that
@ -103,7 +101,7 @@ class EncryptImpl : Encrypt {
override fun signWith(key: InputStream): Encrypt = apply { override fun signWith(key: InputStream): Encrypt = apply {
if (signingOptions == null) { if (signingOptions == null) {
signingOptions = SigningOptions.get() signingOptions = SigningOptions.get(api)
} }
val signingKey = val signingKey =
@ -112,7 +110,7 @@ class EncryptImpl : Encrypt {
AssertionError( AssertionError(
"Exactly one secret key at a time expected. Got zero or multiple instead.")) "Exactly one secret key at a time expected. Got zero or multiple instead."))
val info = PGPainless.inspectKeyRing(signingKey) val info = api.inspect(api.toKey(signingKey))
if (info.signingSubkeys.isEmpty()) { if (info.signingSubkeys.isEmpty()) {
throw SOPGPException.KeyCannotSign("Key ${info.fingerprint} cannot sign.") throw SOPGPException.KeyCannotSign("Key ${info.fingerprint} cannot sign.")
} }

View file

@ -13,7 +13,7 @@ import sop.Ready
import sop.operation.ExtractCert import sop.operation.ExtractCert
/** Implementation of the `extract-cert` operation using PGPainless. */ /** Implementation of the `extract-cert` operation using PGPainless. */
class ExtractCertImpl : ExtractCert { class ExtractCertImpl(private val api: PGPainless) : ExtractCert {
private var armor = true private var armor = true

View file

@ -26,7 +26,7 @@ import sop.exception.SOPGPException
import sop.operation.GenerateKey import sop.operation.GenerateKey
/** Implementation of the `generate-key` operation using PGPainless. */ /** Implementation of the `generate-key` operation using PGPainless. */
class GenerateKeyImpl : GenerateKey { class GenerateKeyImpl(private val api: PGPainless) : GenerateKey {
companion object { companion object {
@JvmField @JvmField

View file

@ -13,8 +13,8 @@ import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPLiteralData import org.bouncycastle.openpgp.PGPLiteralData
import org.bouncycastle.openpgp.PGPOnePassSignatureList import org.bouncycastle.openpgp.PGPOnePassSignatureList
import org.bouncycastle.openpgp.PGPSignatureList import org.bouncycastle.openpgp.PGPSignatureList
import org.bouncycastle.openpgp.api.OpenPGPImplementation
import org.bouncycastle.util.io.Streams import org.bouncycastle.util.io.Streams
import org.pgpainless.PGPainless
import org.pgpainless.decryption_verification.OpenPgpInputStream import org.pgpainless.decryption_verification.OpenPgpInputStream
import org.pgpainless.decryption_verification.cleartext_signatures.ClearsignedMessageUtil import org.pgpainless.decryption_verification.cleartext_signatures.ClearsignedMessageUtil
import org.pgpainless.exception.WrongConsumingMethodException import org.pgpainless.exception.WrongConsumingMethodException
@ -25,7 +25,7 @@ import sop.exception.SOPGPException
import sop.operation.InlineDetach import sop.operation.InlineDetach
/** Implementation of the `inline-detach` operation using PGPainless. */ /** Implementation of the `inline-detach` operation using PGPainless. */
class InlineDetachImpl : InlineDetach { class InlineDetachImpl(private val api: PGPainless) : InlineDetach {
private var armor = true private var armor = true
@ -72,7 +72,7 @@ class InlineDetachImpl : InlineDetach {
} }
// handle binary OpenPGP data // handle binary OpenPGP data
var objectFactory = OpenPGPImplementation.getInstance().pgpObjectFactory(pgpIn) var objectFactory = api.implementation.pgpObjectFactory(pgpIn)
var next: Any? var next: Any?
while (objectFactory.nextObject().also { next = it } != null) { while (objectFactory.nextObject().also { next = it } != null) {
@ -94,8 +94,8 @@ class InlineDetachImpl : InlineDetach {
// Decompress compressed data // Decompress compressed data
try { try {
objectFactory = objectFactory =
OpenPGPImplementation.getInstance() api.implementation.pgpObjectFactory(
.pgpObjectFactory((next as PGPCompressedData).dataStream) (next as PGPCompressedData).dataStream)
} catch (e: PGPException) { } catch (e: PGPException) {
throw SOPGPException.BadData( throw SOPGPException.BadData(
"Cannot decompress PGPCompressedData", e) "Cannot decompress PGPCompressedData", e)

View file

@ -27,9 +27,9 @@ import sop.operation.InlineSign
import sop.util.UTF8Util import sop.util.UTF8Util
/** Implementation of the `inline-sign` operation using PGPainless. */ /** Implementation of the `inline-sign` operation using PGPainless. */
class InlineSignImpl : InlineSign { class InlineSignImpl(private val api: PGPainless) : InlineSign {
private val signingOptions = SigningOptions.get() private val signingOptions = SigningOptions.get(api)
private val protector = MatchMakingSecretKeyRingProtector() private val protector = MatchMakingSecretKeyRingProtector()
private val signingKeys = mutableListOf<PGPSecretKeyRing>() private val signingKeys = mutableListOf<PGPSecretKeyRing>()
@ -57,7 +57,7 @@ class InlineSignImpl : InlineSign {
} }
val producerOptions = val producerOptions =
ProducerOptions.sign(signingOptions).apply { ProducerOptions.sign(signingOptions, api).apply {
when (mode) { when (mode) {
InlineSignAs.clearsigned -> { InlineSignAs.clearsigned -> {
setCleartextSigned() setCleartextSigned()
@ -80,7 +80,7 @@ class InlineSignImpl : InlineSign {
override fun writeTo(outputStream: OutputStream) { override fun writeTo(outputStream: OutputStream) {
try { try {
val signingStream = val signingStream =
PGPainless.encryptAndOrSign() api.generateMessage()
.onOutputStream(outputStream) .onOutputStream(outputStream)
.withOptions(producerOptions) .withOptions(producerOptions)
@ -98,7 +98,7 @@ class InlineSignImpl : InlineSign {
override fun key(key: InputStream): InlineSign = apply { override fun key(key: InputStream): InlineSign = apply {
KeyReader.readSecretKeys(key, true).forEach { KeyReader.readSecretKeys(key, true).forEach {
val info = PGPainless.inspectKeyRing(it) val info = api.inspect(api.toKey(it))
if (!info.isUsableForSigning) { if (!info.isUsableForSigning) {
throw SOPGPException.KeyCannotSign( throw SOPGPException.KeyCannotSign(
"Key ${info.fingerprint} does not have valid, signing capable subkeys.") "Key ${info.fingerprint} does not have valid, signing capable subkeys.")

View file

@ -19,9 +19,9 @@ import sop.exception.SOPGPException
import sop.operation.InlineVerify import sop.operation.InlineVerify
/** Implementation of the `inline-verify` operation using PGPainless. */ /** Implementation of the `inline-verify` operation using PGPainless. */
class InlineVerifyImpl : InlineVerify { class InlineVerifyImpl(private val api: PGPainless) : InlineVerify {
private val options = ConsumerOptions.get() private val options = ConsumerOptions.get(api)
override fun cert(cert: InputStream): InlineVerify = apply { override fun cert(cert: InputStream): InlineVerify = apply {
options.addVerificationCerts(KeyReader.readPublicKeys(cert, true)) options.addVerificationCerts(KeyReader.readPublicKeys(cert, true))

View file

@ -4,12 +4,13 @@
package org.pgpainless.sop package org.pgpainless.sop
import org.pgpainless.PGPainless
import sop.Profile import sop.Profile
import sop.exception.SOPGPException import sop.exception.SOPGPException
import sop.operation.ListProfiles import sop.operation.ListProfiles
/** Implementation of the `list-profiles` operation using PGPainless. */ /** Implementation of the `list-profiles` operation using PGPainless. */
class ListProfilesImpl : ListProfiles { class ListProfilesImpl(private val api: PGPainless) : ListProfiles {
override fun subcommand(command: String): List<Profile> = override fun subcommand(command: String): List<Profile> =
when (command) { when (command) {

View file

@ -86,8 +86,8 @@ class MatchMakingSecretKeyRingProtector : SecretKeyRingProtector {
override fun getEncryptor(key: PGPPublicKey): PBESecretKeyEncryptor? = override fun getEncryptor(key: PGPPublicKey): PBESecretKeyEncryptor? =
protector.getEncryptor(key) protector.getEncryptor(key)
override fun getKeyPassword(p0: OpenPGPKey.OpenPGPSecretKey): CharArray? = override fun getKeyPassword(key: OpenPGPKey.OpenPGPSecretKey): CharArray? =
protector.getKeyPassword(p0) protector.getKeyPassword(key)
/** Clear all known passphrases from the protector. */ /** Clear all known passphrases from the protector. */
fun clear() { fun clear() {

View file

@ -24,7 +24,7 @@ import sop.exception.SOPGPException
import sop.operation.RevokeKey import sop.operation.RevokeKey
import sop.util.UTF8Util import sop.util.UTF8Util
class RevokeKeyImpl : RevokeKey { class RevokeKeyImpl(private val api: PGPainless) : RevokeKey {
private val protector = MatchMakingSecretKeyRingProtector() private val protector = MatchMakingSecretKeyRingProtector()
private var armor = true private var armor = true
@ -41,21 +41,23 @@ class RevokeKeyImpl : RevokeKey {
val revocationCertificates = mutableListOf<OpenPGPCertificate>() val revocationCertificates = mutableListOf<OpenPGPCertificate>()
secretKeyRings.forEach { secretKeys -> secretKeyRings.forEach { secretKeys ->
val editor = PGPainless.modifyKeyRing(secretKeys) val openPGPKey = api.toKey(secretKeys)
val editor = api.modify(openPGPKey)
try { try {
val attributes = val attributes =
RevocationAttributes.createKeyRevocation() RevocationAttributes.createKeyRevocation()
.withReason(RevocationAttributes.Reason.NO_REASON) .withReason(RevocationAttributes.Reason.NO_REASON)
.withoutDescription() .withoutDescription()
if (secretKeys.publicKey.version == 6) { if (openPGPKey.primaryKey.version == 6) {
revocationCertificates.add( revocationCertificates.add(
editor.createMinimalRevocationCertificate(protector, attributes)) editor.createMinimalRevocationCertificate(protector, attributes))
} else { } else {
val certificate = PGPainless.extractCertificate(secretKeys) val certificate = openPGPKey.toCertificate()
val revocation = editor.createRevocation(protector, attributes) val revocation = editor.createRevocation(protector, attributes)
revocationCertificates.add( revocationCertificates.add(
KeyRingUtils.injectCertification(certificate, revocation.signature) KeyRingUtils.injectCertification(
.toOpenPGPCertificate()) certificate.pgpKeyRing, revocation.signature)
.toOpenPGPCertificate(api.implementation))
} }
} catch (e: WrongPassphraseException) { } catch (e: WrongPassphraseException) {
throw SOPGPException.KeyIsProtected( throw SOPGPException.KeyIsProtected(

View file

@ -4,6 +4,7 @@
package org.pgpainless.sop package org.pgpainless.sop
import org.pgpainless.PGPainless
import sop.SOP import sop.SOP
import sop.SOPV import sop.SOPV
import sop.operation.Armor import sop.operation.Armor
@ -22,35 +23,38 @@ import sop.operation.ListProfiles
import sop.operation.RevokeKey import sop.operation.RevokeKey
import sop.operation.Version import sop.operation.Version
class SOPImpl(private val sopv: SOPV = SOPVImpl()) : SOP { class SOPImpl(
private val api: PGPainless = PGPainless.getInstance(),
private val sopv: SOPV = SOPVImpl(api)
) : SOP {
override fun armor(): Armor = ArmorImpl() override fun armor(): Armor = ArmorImpl(api)
override fun changeKeyPassword(): ChangeKeyPassword = ChangeKeyPasswordImpl() override fun changeKeyPassword(): ChangeKeyPassword = ChangeKeyPasswordImpl(api)
override fun dearmor(): Dearmor = DearmorImpl() override fun dearmor(): Dearmor = DearmorImpl(api)
override fun decrypt(): Decrypt = DecryptImpl() override fun decrypt(): Decrypt = DecryptImpl(api)
override fun detachedSign(): DetachedSign = DetachedSignImpl() override fun detachedSign(): DetachedSign = DetachedSignImpl(api)
override fun detachedVerify(): DetachedVerify = sopv.detachedVerify() override fun detachedVerify(): DetachedVerify = sopv.detachedVerify()
override fun encrypt(): Encrypt = EncryptImpl() override fun encrypt(): Encrypt = EncryptImpl(api)
override fun extractCert(): ExtractCert = ExtractCertImpl() override fun extractCert(): ExtractCert = ExtractCertImpl(api)
override fun generateKey(): GenerateKey = GenerateKeyImpl() override fun generateKey(): GenerateKey = GenerateKeyImpl(api)
override fun inlineDetach(): InlineDetach = InlineDetachImpl() override fun inlineDetach(): InlineDetach = InlineDetachImpl(api)
override fun inlineSign(): InlineSign = InlineSignImpl() override fun inlineSign(): InlineSign = InlineSignImpl(api)
override fun inlineVerify(): InlineVerify = sopv.inlineVerify() override fun inlineVerify(): InlineVerify = sopv.inlineVerify()
override fun listProfiles(): ListProfiles = ListProfilesImpl() override fun listProfiles(): ListProfiles = ListProfilesImpl(api)
override fun revokeKey(): RevokeKey = RevokeKeyImpl() override fun revokeKey(): RevokeKey = RevokeKeyImpl(api)
override fun version(): Version = sopv.version() override fun version(): Version = sopv.version()
} }

View file

@ -4,21 +4,22 @@
package org.pgpainless.sop package org.pgpainless.sop
import org.pgpainless.PGPainless
import org.pgpainless.util.ArmoredOutputStreamFactory import org.pgpainless.util.ArmoredOutputStreamFactory
import sop.SOPV import sop.SOPV
import sop.operation.DetachedVerify import sop.operation.DetachedVerify
import sop.operation.InlineVerify import sop.operation.InlineVerify
import sop.operation.Version import sop.operation.Version
class SOPVImpl : SOPV { class SOPVImpl(private val api: PGPainless) : SOPV {
init { init {
ArmoredOutputStreamFactory.setVersionInfo(null) ArmoredOutputStreamFactory.setVersionInfo(null)
} }
override fun detachedVerify(): DetachedVerify = DetachedVerifyImpl() override fun detachedVerify(): DetachedVerify = DetachedVerifyImpl(api)
override fun inlineVerify(): InlineVerify = InlineVerifyImpl() override fun inlineVerify(): InlineVerify = InlineVerifyImpl(api)
override fun version(): Version = VersionImpl() override fun version(): Version = VersionImpl(api)
} }

View file

@ -8,11 +8,12 @@ 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 org.pgpainless.PGPainless
import sop.SOP 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. */
class VersionImpl : Version { class VersionImpl(private val api: PGPainless) : Version {
companion object { companion object {
const val SOP_VERSION = 10 const val SOP_VERSION = 10