mirror of
https://codeberg.org/PGPainless/sop-java.git
synced 2025-09-09 02:09:42 +02:00
Kotlin conversion: DecryptExternal
This commit is contained in:
parent
da2b299f4d
commit
03da9bbfb7
2 changed files with 133 additions and 185 deletions
133
external-sop/src/main/kotlin/sop/external/operation/DecryptExternal.kt
vendored
Normal file
133
external-sop/src/main/kotlin/sop/external/operation/DecryptExternal.kt
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.external.operation
|
||||
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
import sop.DecryptionResult
|
||||
import sop.ReadyWithResult
|
||||
import sop.SessionKey
|
||||
import sop.Verification
|
||||
import sop.external.ExternalSOP
|
||||
import sop.external.ExternalSOP.Companion.finish
|
||||
import sop.external.ExternalSOP.Companion.readString
|
||||
import sop.operation.Decrypt
|
||||
import sop.util.UTCUtil
|
||||
|
||||
/** Implementation of the [Decrypt] operation using an external SOP binary. */
|
||||
class DecryptExternal(
|
||||
binary: String,
|
||||
environment: Properties,
|
||||
private val tempDirProvider: ExternalSOP.TempDirProvider
|
||||
) : Decrypt {
|
||||
|
||||
private val commandList = mutableListOf(binary, "decrypt")
|
||||
private val envList = ExternalSOP.propertiesToEnv(environment).toMutableList()
|
||||
|
||||
private var argCounter = 0
|
||||
private var requireVerification = false
|
||||
|
||||
override fun verifyNotBefore(timestamp: Date): Decrypt = apply {
|
||||
commandList.add("--verify-not-before=${UTCUtil.formatUTCDate(timestamp)}")
|
||||
}
|
||||
|
||||
override fun verifyNotAfter(timestamp: Date): Decrypt = apply {
|
||||
commandList.add("--verify-not-after=${UTCUtil.formatUTCDate(timestamp)}")
|
||||
}
|
||||
|
||||
override fun verifyWithCert(cert: InputStream): Decrypt = apply {
|
||||
commandList.add("--verify-with=@ENV:VERIFY_WITH_$argCounter")
|
||||
envList.add("VERIFY_WITH_$argCounter=${readString(cert)}")
|
||||
argCounter += 1
|
||||
requireVerification = true
|
||||
}
|
||||
|
||||
override fun withSessionKey(sessionKey: SessionKey): Decrypt = apply {
|
||||
commandList.add("--with-session-key=@ENV:SESSION_KEY_$argCounter")
|
||||
envList.add("SESSION_KEY_$argCounter=$sessionKey")
|
||||
argCounter += 1
|
||||
}
|
||||
|
||||
override fun withPassword(password: String): Decrypt = apply {
|
||||
commandList.add("--with-password=@ENV:PASSWORD_$argCounter")
|
||||
envList.add("PASSWORD_$argCounter=$password")
|
||||
argCounter += 1
|
||||
}
|
||||
|
||||
override fun withKey(key: InputStream): Decrypt = apply {
|
||||
commandList.add("@ENV:KEY_$argCounter")
|
||||
envList.add("KEY_$argCounter=${readString(key)}")
|
||||
argCounter += 1
|
||||
}
|
||||
|
||||
override fun withKeyPassword(password: ByteArray): Decrypt = apply {
|
||||
commandList.add("--with-key-password=@ENV:KEY_PASSWORD_$argCounter")
|
||||
envList.add("KEY_PASSWORD_$argCounter=${String(password)}")
|
||||
argCounter += 1
|
||||
}
|
||||
|
||||
override fun ciphertext(ciphertext: InputStream): ReadyWithResult<DecryptionResult> {
|
||||
val tempDir = tempDirProvider.provideTempDirectory()
|
||||
|
||||
val sessionKeyOut = File(tempDir, "session-key-out")
|
||||
sessionKeyOut.delete()
|
||||
commandList.add("--session-key-out=${sessionKeyOut.absolutePath}")
|
||||
|
||||
val verifyOut = File(tempDir, "verifications-out")
|
||||
verifyOut.delete()
|
||||
if (requireVerification) {
|
||||
commandList.add("--verify-out=${verifyOut.absolutePath}")
|
||||
}
|
||||
|
||||
try {
|
||||
val process =
|
||||
Runtime.getRuntime().exec(commandList.toTypedArray(), envList.toTypedArray())
|
||||
val processOut = process.outputStream
|
||||
val processIn = process.inputStream
|
||||
|
||||
return object : ReadyWithResult<DecryptionResult>() {
|
||||
override fun writeTo(outputStream: OutputStream): DecryptionResult {
|
||||
val buf = ByteArray(4096)
|
||||
var r: Int
|
||||
while (ciphertext.read(buf).also { r = it } > 0) {
|
||||
processOut.write(buf, 0, r)
|
||||
}
|
||||
|
||||
ciphertext.close()
|
||||
processOut.close()
|
||||
|
||||
while (processIn.read(buf).also { r = it } > 0) {
|
||||
outputStream.write(buf, 0, r)
|
||||
}
|
||||
|
||||
processIn.close()
|
||||
outputStream.close()
|
||||
|
||||
finish(process)
|
||||
|
||||
val sessionKeyOutIn = FileInputStream(sessionKeyOut)
|
||||
var line = readString(sessionKeyOutIn)
|
||||
val sessionKey = SessionKey.fromString(line.trim { it <= ' ' })
|
||||
sessionKeyOutIn.close()
|
||||
sessionKeyOut.delete()
|
||||
|
||||
val verifications: MutableList<Verification> = ArrayList()
|
||||
if (requireVerification) {
|
||||
val verifyOutIn = FileInputStream(verifyOut)
|
||||
val reader = BufferedReader(InputStreamReader(verifyOutIn))
|
||||
while (reader.readLine().also { line = it } != null) {
|
||||
verifications.add(Verification.fromString(line.trim()))
|
||||
}
|
||||
reader.close()
|
||||
}
|
||||
|
||||
return DecryptionResult(sessionKey, verifications)
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue