diff --git a/ledger/ledger-api-common/src/main/scala/com/digitalasset/ledger/api/tls/DecryptionParameters.scala b/ledger/ledger-api-common/src/main/scala/com/digitalasset/ledger/api/tls/DecryptionParameters.scala index 098b69a88050..c4b0f4ee49af 100644 --- a/ledger/ledger-api-common/src/main/scala/com/digitalasset/ledger/api/tls/DecryptionParameters.scala +++ b/ledger/ledger-api-common/src/main/scala/com/digitalasset/ledger/api/tls/DecryptionParameters.scala @@ -8,12 +8,12 @@ import java.nio.charset.StandardCharsets import java.nio.file.Files import javax.crypto.Cipher import javax.crypto.spec.{IvParameterSpec, SecretKeySpec} - import org.apache.commons.codec.binary.Hex import org.apache.commons.io.IOUtils import spray.json.{DefaultJsonProtocol, RootJsonFormat} -import scala.util.Using +import java.util.Base64 +import scala.util.{Try, Using} final class PrivateKeyDecryptionException(cause: Throwable) extends Exception(cause) @@ -39,6 +39,15 @@ case class DecryptionParameters( transformation.split("/")(0) } + private def decodeBase64OrGetVerbatim(encrypted: Array[Byte]): Array[Byte] = { + val potentialBase64Char = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/+=\n\r".getBytes() + encrypted.find(!potentialBase64Char.contains(_)) match { + case None => Try(Base64.getMimeDecoder.decode(encrypted)).getOrElse(encrypted) + case _ => encrypted + } + } + private[tls] def decrypt(encrypted: Array[Byte]): Array[Byte] = { val key: Array[Byte] = Hex.decodeHex(keyInHex) val secretKey = new SecretKeySpec(key, algorithm) @@ -46,7 +55,8 @@ case class DecryptionParameters( val cipher = Cipher.getInstance(transformation) val ivParameterSpec = new IvParameterSpec(iv) cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec) - cipher.doFinal(encrypted) + val binary = decodeBase64OrGetVerbatim(encrypted) + cipher.doFinal(binary) } } diff --git a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/tls/DecryptionParametersTest.scala b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/tls/DecryptionParametersTest.scala index b64446432fe0..fc5b5aa1c6b1 100644 --- a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/tls/DecryptionParametersTest.scala +++ b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/tls/DecryptionParametersTest.scala @@ -6,18 +6,19 @@ package com.daml.ledger.api.tls import java.io.ByteArrayInputStream import java.nio.file.Files import javax.crypto.{Cipher, KeyGenerator, SecretKey} - import org.apache.commons.codec.binary.Hex import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec +import java.util.Base64 + class DecryptionParametersTest extends AnyWordSpec with Matchers { "decryption parameters" should { // given val key: SecretKey = KeyGenerator.getInstance("AES").generateKey() - val clearText = "clearText123" + val clearText = "clearText123 " * 10 val clearTextBytes = clearText.getBytes val transformation = "AES/CBC/PKCS5Padding" val cipher = Cipher.getInstance(transformation) @@ -41,11 +42,20 @@ class DecryptionParametersTest extends AnyWordSpec with Matchers { new String(actual) shouldBe clearText } - "decrypt a file" in { + "decrypt a file" in + testFileDecoding("-verbatim", cipherText) + + "decrypt a file in base64" in + testFileDecoding("-base64", Base64.getEncoder.encode(cipherText)) + + "decrypt a file in MIME base64" in + testFileDecoding("-mime-base64", Base64.getMimeEncoder.encode(cipherText)) + + def testFileDecoding(fileSuffix: String, content: Array[Byte]) = { // given - val tmpFilePath = Files.createTempFile("cipher-text", ".enc") - Files.write(tmpFilePath, cipherText) - assume(Files.readAllBytes(tmpFilePath) sameElements cipherText) + val tmpFilePath = Files.createTempFile(s"cipher-text$fileSuffix", ".enc") + Files.write(tmpFilePath, content) + assume(Files.readAllBytes(tmpFilePath) sameElements content) // when val actual: Array[Byte] = tested.decrypt(tmpFilePath.toFile) diff --git a/ledger/test-common/test-certificates/BUILD.bazel b/ledger/test-common/test-certificates/BUILD.bazel index 0d87db30fe04..05ea9dee7aee 100644 --- a/ledger/test-common/test-certificates/BUILD.bazel +++ b/ledger/test-common/test-certificates/BUILD.bazel @@ -80,7 +80,7 @@ chmod 444 $(location server.crt) # Encrypt server's key and dump encryption parameters to a JSON file. # NOTE: Encryption details used to encrypt the private must be kept in sync with `ledger/test-common/files/server-pem-decryption-parameters.json` -$(location @openssl_dev_env//:openssl) enc -aes-128-cbc \ +$(location @openssl_dev_env//:openssl) enc -aes-128-cbc -base64 \ -in $(location server.pem) \ -out $(location server.pem.enc) \ -K 0034567890abcdef1234567890abcdef \