mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 01:07:18 +03:00
Improve MessageDigest and Mac instance creation to solve lock contention [DPP-956] (#13221)
* Improve MessageDigest and Mac instance creation to solve lock contention problem [DPP-956] changelog_begin Scalability bottleneck in regard to hashing has been fixed in multiple places. changelog_end
This commit is contained in:
parent
1a66bb998b
commit
9a27edd656
@ -29,8 +29,8 @@ load("@rules_pkg//:pkg.bzl", "pkg_tar")
|
||||
name = "daml_lf_%s_archive_proto_srcs" % version,
|
||||
srcs = glob([
|
||||
"src/{directory}/protobuf/com/daml/daml_lf_{version}/*.proto".format(
|
||||
version = mangled_version,
|
||||
directory = directory,
|
||||
version = mangled_version,
|
||||
),
|
||||
]),
|
||||
),
|
||||
@ -105,6 +105,7 @@ da_scala_library(
|
||||
":daml_lf_1.dev_archive_proto_java",
|
||||
"//daml-lf/data",
|
||||
"//daml-lf/language",
|
||||
"//libs-scala/crypto",
|
||||
"//libs-scala/nameof",
|
||||
"//libs-scala/scala-utils",
|
||||
"@maven//:com_google_protobuf_protobuf_java",
|
||||
|
@ -3,12 +3,11 @@
|
||||
|
||||
package com.daml.lf.archive
|
||||
|
||||
import com.daml.crypto.MessageDigestPrototype
|
||||
import com.daml.daml_lf_dev.DamlLf
|
||||
import com.daml.lf.data.Ref.PackageId
|
||||
import com.daml.lf.language.{LanguageMajorVersion, LanguageVersion}
|
||||
|
||||
import java.security.MessageDigest
|
||||
|
||||
case class ArchivePayload(
|
||||
pkgId: PackageId,
|
||||
proto: DamlLf.ArchivePayload,
|
||||
@ -27,8 +26,7 @@ object Reader {
|
||||
.fromString(lf.getHash)
|
||||
.left
|
||||
.map(err => Error.Parsing("Invalid hash: " + err))
|
||||
ourHash = MessageDigest
|
||||
.getInstance("SHA-256")
|
||||
ourHash = MessageDigestPrototype.SHA_256.newDigest
|
||||
.digest(lf.getPayload.toByteArray)
|
||||
.map("%02x" format _)
|
||||
.mkString
|
||||
|
@ -26,6 +26,7 @@ da_scala_library(
|
||||
"//visibility:public",
|
||||
],
|
||||
deps = [
|
||||
"//libs-scala/crypto",
|
||||
"//libs-scala/logging-entries",
|
||||
"//libs-scala/scala-utils",
|
||||
"@maven//:com_google_guava_guava",
|
||||
|
@ -4,10 +4,8 @@
|
||||
package com.daml.lf
|
||||
package data
|
||||
|
||||
import java.security.MessageDigest
|
||||
|
||||
import com.daml.crypto.MessageDigestPrototype
|
||||
import com.daml.scalautil.Statement.discard
|
||||
|
||||
import com.google.common.io.BaseEncoding
|
||||
import com.google.protobuf.ByteString
|
||||
import scalaz.Order
|
||||
@ -40,7 +38,7 @@ object Utf8 {
|
||||
Bytes.fromByteString(ByteString.copyFromUtf8(s))
|
||||
|
||||
def sha256(s: String): String = {
|
||||
val digest = MessageDigest.getInstance("SHA-256")
|
||||
val digest = MessageDigestPrototype.SHA_256.newDigest
|
||||
digest.update(getBytes(s).toByteBuffer)
|
||||
BaseEncoding.base16().lowerCase().encode(digest.digest())
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ da_scala_library(
|
||||
"//daml-lf/archive:daml_lf_archive_reader",
|
||||
"//daml-lf/data",
|
||||
"//daml-lf/language",
|
||||
"//libs-scala/crypto",
|
||||
"//libs-scala/safe-proto",
|
||||
"@maven//:com_google_protobuf_protobuf_java",
|
||||
],
|
||||
|
@ -5,12 +5,11 @@ package com.daml.lf
|
||||
package archive.testing
|
||||
|
||||
import com.daml.SafeProto
|
||||
|
||||
import java.security.MessageDigest
|
||||
import com.daml.crypto.MessageDigestPrototype
|
||||
import com.daml.daml_lf_dev.{DamlLf => PLF}
|
||||
import com.daml.lf.data.Ref.PackageId
|
||||
import com.daml.lf.language.Ast.Package
|
||||
import com.daml.lf.language.{LanguageMajorVersion, LanguageVersion}
|
||||
import com.daml.daml_lf_dev.{DamlLf => PLF}
|
||||
|
||||
// Important: do not use this in production code. It is designed for testing only.
|
||||
object Encode {
|
||||
@ -39,7 +38,10 @@ object Encode {
|
||||
|
||||
val payload = data.assertRight(SafeProto.toByteString(encodePayloadOfVersion(pkg, version)))
|
||||
val hash = PackageId.assertFromString(
|
||||
MessageDigest.getInstance("SHA-256").digest(payload.toByteArray).map("%02x" format _).mkString
|
||||
MessageDigestPrototype.SHA_256.newDigest
|
||||
.digest(payload.toByteArray)
|
||||
.map("%02x" format _)
|
||||
.mkString
|
||||
)
|
||||
|
||||
PLF.Archive
|
||||
|
@ -57,6 +57,7 @@ da_scala_library(
|
||||
":value_proto_java",
|
||||
"//daml-lf/data",
|
||||
"//daml-lf/language",
|
||||
"//libs-scala/crypto",
|
||||
"//libs-scala/nameof",
|
||||
"//libs-scala/safe-proto",
|
||||
"//libs-scala/scala-utils",
|
||||
|
@ -4,17 +4,17 @@
|
||||
package com.daml.lf
|
||||
package crypto
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
import java.security.MessageDigest
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
import com.daml.crypto.{MacPrototype, MessageDigestPrototype}
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
import com.daml.lf.data.{Bytes, ImmArray, Ref, Time, Utf8}
|
||||
import com.daml.lf.value.Value
|
||||
import com.daml.scalautil.Statement.discard
|
||||
import scalaz.Order
|
||||
|
||||
import javax.crypto.Mac
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
import scala.util.control.NoStackTrace
|
||||
|
||||
final class Hash private (val bytes: Bytes) {
|
||||
@ -239,7 +239,7 @@ object Hash {
|
||||
cid2Bytes: Value.ContractId => Bytes,
|
||||
): Builder = new Builder(cid2Bytes) {
|
||||
|
||||
private val md = MessageDigest.getInstance("SHA-256")
|
||||
private val md = MessageDigestPrototype.SHA_256.newDigest
|
||||
|
||||
override protected def update(a: ByteBuffer): Unit =
|
||||
md.update(a)
|
||||
@ -255,13 +255,12 @@ object Hash {
|
||||
|
||||
}
|
||||
|
||||
private val hMacAlgorithm = "HmacSHA256"
|
||||
|
||||
private[crypto] def hMacBuilder(key: Hash): Builder = new Builder(noCid2String) {
|
||||
|
||||
private val mac: Mac = Mac.getInstance(hMacAlgorithm)
|
||||
private val macPrototype: MacPrototype = MacPrototype.HmacSHA_256
|
||||
private val mac: Mac = macPrototype.newMac
|
||||
|
||||
mac.init(new SecretKeySpec(key.bytes.toByteArray, hMacAlgorithm))
|
||||
mac.init(new SecretKeySpec(key.bytes.toByteArray, macPrototype.algorithm))
|
||||
|
||||
override protected def update(a: ByteBuffer): Unit =
|
||||
mac.update(a)
|
||||
|
@ -313,6 +313,7 @@ alias(
|
||||
"//ledger/ledger-api-common",
|
||||
"//ledger/test-common:dar-files-default-lib",
|
||||
"//libs-scala/contextualized-logging",
|
||||
"//libs-scala/crypto",
|
||||
"//libs-scala/db-utils",
|
||||
"//libs-scala/doobie-slf4j",
|
||||
"//libs-scala/ports",
|
||||
|
@ -13,6 +13,7 @@ import akka.stream.scaladsl.{Source, StreamConverters}
|
||||
import akka.util.ByteString
|
||||
import com.daml.api.util.TimestampConversion
|
||||
import com.daml.bazeltools.BazelRunfiles.requiredResource
|
||||
import com.daml.crypto.MessageDigestPrototype
|
||||
import com.daml.lf.data.Ref
|
||||
import com.daml.http.dbbackend.JdbcConfig
|
||||
import com.daml.http.domain.ContractId
|
||||
@ -71,9 +72,7 @@ object AbstractHttpServiceIntegrationTestFuns {
|
||||
def sha256(source: Source[ByteString, Any])(implicit mat: Materializer): Try[String] = Try {
|
||||
import com.google.common.io.BaseEncoding
|
||||
|
||||
import java.security.MessageDigest
|
||||
|
||||
val md = MessageDigest.getInstance("SHA-256")
|
||||
val md = MessageDigestPrototype.SHA_256.newDigest
|
||||
val is = source.runWith(StreamConverters.asInputStream())
|
||||
val dis = new DigestInputStream(is, md)
|
||||
|
||||
|
@ -42,6 +42,7 @@ da_scala_library(
|
||||
"//ledger/ledger-resources",
|
||||
"//ledger/metrics",
|
||||
"//libs-scala/contextualized-logging",
|
||||
"//libs-scala/crypto",
|
||||
"//libs-scala/logging-entries",
|
||||
"//libs-scala/resources",
|
||||
"//libs-scala/resources-akka",
|
||||
|
@ -3,9 +3,10 @@
|
||||
|
||||
package com.daml.platform.store.serialization
|
||||
|
||||
import com.daml.crypto.MessageDigestPrototype
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
import java.security.MessageDigest
|
||||
|
||||
import com.daml.lf.data.{Numeric, Utf8}
|
||||
import com.daml.lf.transaction.GlobalKey
|
||||
import com.daml.lf.value.Value
|
||||
@ -154,7 +155,7 @@ object KeyHasher extends KeyHasher {
|
||||
/** @deprecated in favor of [[GlobalKey.hash]]
|
||||
*/
|
||||
override def hashKey(key: GlobalKey): Array[Byte] = {
|
||||
val digest = MessageDigest.getInstance("SHA-256")
|
||||
val digest = MessageDigestPrototype.SHA_256.newDigest
|
||||
|
||||
// First, write the template ID
|
||||
putString(digest, key.templateId.packageId)
|
||||
|
@ -287,6 +287,7 @@ da_scala_test_suite(
|
||||
"//ledger/test-common:dar-files-default-lib",
|
||||
"//libs-scala/concurrent",
|
||||
"//libs-scala/contextualized-logging",
|
||||
"//libs-scala/crypto",
|
||||
"//libs-scala/grpc-utils",
|
||||
"//libs-scala/logging-entries",
|
||||
"//libs-scala/ports",
|
||||
|
@ -3,10 +3,7 @@
|
||||
|
||||
package com.daml.platform.store
|
||||
|
||||
import java.math.BigInteger
|
||||
import java.nio.charset.Charset
|
||||
import java.security.MessageDigest
|
||||
|
||||
import com.daml.crypto.MessageDigestPrototype
|
||||
import com.daml.platform.store.FlywayMigrationsSpec._
|
||||
import org.apache.commons.io.IOUtils
|
||||
import org.flywaydb.core.Flyway
|
||||
@ -17,6 +14,8 @@ import org.flywaydb.core.internal.scanner.{LocationScannerCache, ResourceNameCac
|
||||
import org.scalatest.matchers.should.Matchers._
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
import java.math.BigInteger
|
||||
import java.nio.charset.Charset
|
||||
import scala.jdk.CollectionConverters._
|
||||
|
||||
// SQL MIGRATION AND THEIR DIGEST FILES SHOULD BE CREATED ONLY ONCE AND NEVER CHANGED AGAIN,
|
||||
@ -44,7 +43,7 @@ class FlywayMigrationsSpec extends AnyWordSpec {
|
||||
|
||||
object FlywayMigrationsSpec {
|
||||
|
||||
private val digester = MessageDigest.getInstance("SHA-256")
|
||||
private val digester = MessageDigestPrototype.SHA_256.newDigest
|
||||
|
||||
private def assertFlywayMigrationFileHashes(
|
||||
dbType: DbType,
|
||||
|
@ -58,6 +58,7 @@ da_scala_library(
|
||||
"//ledger/participant-state-index",
|
||||
"//libs-scala/concurrent",
|
||||
"//libs-scala/contextualized-logging",
|
||||
"//libs-scala/crypto",
|
||||
"//libs-scala/grpc-utils",
|
||||
"//libs-scala/logging-entries",
|
||||
"//libs-scala/resources",
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
package com.daml.ledger.validator
|
||||
|
||||
import java.security.MessageDigest
|
||||
import com.daml.crypto.MessageDigestPrototype
|
||||
|
||||
import com.daml.ledger.participant.state.kvutils.Raw
|
||||
import com.daml.ledger.participant.state.kvutils.store.DamlLogEntryId
|
||||
@ -30,8 +30,7 @@ object HashingLogEntryIdComputationStrategy extends LogEntryIdComputationStrateg
|
||||
.build
|
||||
|
||||
private def hash(rawEnvelope: Raw.Envelope): ByteString = {
|
||||
val messageDigest = MessageDigest
|
||||
.getInstance("SHA-256")
|
||||
val messageDigest = MessageDigestPrototype.SHA_256.newDigest
|
||||
messageDigest.update(rawEnvelope.bytes.asReadOnlyByteBuffer())
|
||||
val hash = messageDigest
|
||||
.digest()
|
||||
|
35
libs-scala/crypto/BUILD.bazel
Normal file
35
libs-scala/crypto/BUILD.bazel
Normal file
@ -0,0 +1,35 @@
|
||||
# Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
load("//bazel_tools:scala.bzl", "da_scala_benchmark_jmh", "da_scala_library", "da_scala_test")
|
||||
load("@scala_version//:index.bzl", "scala_major_version")
|
||||
|
||||
da_scala_library(
|
||||
name = "crypto",
|
||||
srcs = glob(["src/main/scala/**/*.scala"]),
|
||||
tags = ["maven_coordinates=com.daml:crypto:__VERSION__"],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
deps = [
|
||||
"//libs-scala/scala-utils",
|
||||
],
|
||||
)
|
||||
|
||||
da_scala_test(
|
||||
name = "crypto-tests",
|
||||
size = "small",
|
||||
srcs = glob(["src/test/scala/**/*.scala"]),
|
||||
deps = [
|
||||
":crypto",
|
||||
],
|
||||
)
|
||||
|
||||
da_scala_benchmark_jmh(
|
||||
name = "crypto-perf",
|
||||
srcs = glob(["src/jmh/scala/**/*.scala"]),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":crypto",
|
||||
],
|
||||
)
|
@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.crypto
|
||||
import org.openjdk.jmh.annotations._
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
import scala.util.Random
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
@Warmup(iterations = 5, time = 1)
|
||||
@Measurement(iterations = 5, time = 5)
|
||||
class MacPrototypeBenchmark {
|
||||
|
||||
var key = ""
|
||||
var value = ""
|
||||
val charset = StandardCharsets.UTF_8
|
||||
|
||||
@Setup
|
||||
def setup(): Unit = {
|
||||
key = Random.nextString(32)
|
||||
value = Random.nextString(32)
|
||||
}
|
||||
|
||||
private def encode(): Array[Byte] = {
|
||||
val prototype = MacPrototype.HmacSHA_256
|
||||
val mac = prototype.newMac
|
||||
mac.init(new SecretKeySpec(key.getBytes(charset), prototype.algorithm))
|
||||
mac.doFinal(value.getBytes(charset))
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Threads(1)
|
||||
def encodeHmacSHA_256_1(): Array[Byte] = {
|
||||
encode()
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Threads(4)
|
||||
def encodeHmacSHA_256_4(): Array[Byte] = {
|
||||
encode()
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Threads(16)
|
||||
def encodeHmacSHA_256_16(): Array[Byte] = {
|
||||
encode()
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.crypto
|
||||
|
||||
import org.openjdk.jmh.annotations._
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
import scala.util.Random
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
@Warmup(iterations = 5, time = 1)
|
||||
@Measurement(iterations = 5, time = 5)
|
||||
class MessageDigestPrototypeBenchmark {
|
||||
|
||||
var value = ""
|
||||
val charset = StandardCharsets.UTF_8
|
||||
|
||||
@Setup
|
||||
def setup(): Unit = {
|
||||
value = Random.nextString(32)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Threads(1)
|
||||
def newDigest(): Array[Byte] = {
|
||||
MessageDigestPrototype.SHA_256.newDigest.digest(value.getBytes(charset))
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Threads(4)
|
||||
def newDigest4(): Array[Byte] = {
|
||||
MessageDigestPrototype.SHA_256.newDigest.digest(value.getBytes(charset))
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Threads(16)
|
||||
def newDigest16(): Array[Byte] = {
|
||||
MessageDigestPrototype.SHA_256.newDigest.digest(value.getBytes(charset))
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Threads(32)
|
||||
def newDigest32(): Array[Byte] = {
|
||||
MessageDigestPrototype.SHA_256.newDigest.digest(value.getBytes(charset))
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.crypto
|
||||
|
||||
import com.daml.scalautil.Statement.discard
|
||||
|
||||
import javax.crypto.Mac
|
||||
|
||||
/*
|
||||
* Use Mac prototypes as a workaround for
|
||||
* https://bugs.openjdk.java.net/browse/JDK-7092821, similar to Guava's
|
||||
* workaround https://github.com/google/guava/issues/1197
|
||||
*/
|
||||
final class MacPrototype(val algorithm: String) {
|
||||
private val prototype = createMac
|
||||
|
||||
private val supportsClone: Boolean =
|
||||
try {
|
||||
discard(prototype.clone())
|
||||
true
|
||||
} catch {
|
||||
case _: CloneNotSupportedException =>
|
||||
false
|
||||
}
|
||||
|
||||
private def createMac: Mac = Mac.getInstance(algorithm)
|
||||
|
||||
def newMac: Mac = {
|
||||
if (supportsClone)
|
||||
prototype.clone().asInstanceOf[Mac]
|
||||
else
|
||||
createMac
|
||||
}
|
||||
}
|
||||
|
||||
object MacPrototype {
|
||||
val HmacSHA_256 = new MacPrototype("HmacSHA256")
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.crypto
|
||||
|
||||
import com.daml.scalautil.Statement.discard
|
||||
|
||||
import java.security.MessageDigest
|
||||
|
||||
/*
|
||||
* Use MessageDigest prototypes as a workaround for
|
||||
* https://bugs.openjdk.java.net/browse/JDK-7092821, similar to Guava's
|
||||
* workaround https://github.com/google/guava/issues/1197
|
||||
*/
|
||||
final class MessageDigestPrototype(val algorithm: String) {
|
||||
private def createDigest: MessageDigest = MessageDigest.getInstance(algorithm)
|
||||
|
||||
private val prototype = createDigest
|
||||
|
||||
private val supportsClone: Boolean =
|
||||
try {
|
||||
discard(prototype.clone())
|
||||
true
|
||||
} catch {
|
||||
case _: CloneNotSupportedException =>
|
||||
false
|
||||
}
|
||||
|
||||
def newDigest: MessageDigest = {
|
||||
if (supportsClone)
|
||||
prototype.clone().asInstanceOf[MessageDigest]
|
||||
else
|
||||
createDigest
|
||||
}
|
||||
}
|
||||
|
||||
object MessageDigestPrototype {
|
||||
final val SHA_256 = new MessageDigestPrototype("SHA-256")
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.crypto
|
||||
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.util.Base64
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
class MacPrototypeSpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
behavior of MacPrototype.getClass.getSimpleName
|
||||
|
||||
it should "provide new instance of digest for HmacSHA256" in {
|
||||
val mac = MacPrototype.HmacSHA_256.newMac
|
||||
val mac2 = MacPrototype.HmacSHA_256.newMac
|
||||
mac should not be theSameInstanceAs(mac2)
|
||||
}
|
||||
|
||||
it should "expose algorithm" in {
|
||||
MacPrototype.HmacSHA_256.algorithm shouldBe "HmacSHA256"
|
||||
}
|
||||
|
||||
it should "perform encoding for the `HmacSHA256` algorithm" in {
|
||||
val key = "Hello"
|
||||
val prototype = MacPrototype.HmacSHA_256
|
||||
val mac = prototype.newMac
|
||||
mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), prototype.algorithm))
|
||||
val sha = mac.doFinal("Hello World".getBytes(StandardCharsets.UTF_8))
|
||||
new String(
|
||||
Base64.getEncoder.encode(sha),
|
||||
StandardCharsets.UTF_8,
|
||||
) shouldBe "Y0PTLXgtpY9zSmzT6w2U48JcDGx7G7pRyHTRCIE/Pm0="
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.crypto
|
||||
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.util.Base64
|
||||
|
||||
class MessageDigestPrototypeSpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
behavior of MessageDigestPrototype.getClass.getSimpleName
|
||||
|
||||
it should "provide new instance of digest for SHA-256" in {
|
||||
val digest = MessageDigestPrototype.SHA_256.newDigest
|
||||
val digest2 = MessageDigestPrototype.SHA_256.newDigest
|
||||
digest should not be theSameInstanceAs(digest2)
|
||||
}
|
||||
|
||||
it should "expose algorithm" in {
|
||||
MessageDigestPrototype.SHA_256.algorithm shouldBe "SHA-256"
|
||||
}
|
||||
|
||||
it should "perform a digest for the SHA-256 algorithm" in {
|
||||
val digest = MessageDigestPrototype.SHA_256.newDigest
|
||||
val sha = digest.digest("Hello World".getBytes(StandardCharsets.UTF_8))
|
||||
new String(
|
||||
Base64.getEncoder.encode(sha),
|
||||
StandardCharsets.UTF_8,
|
||||
) shouldBe "pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4="
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ da_scala_library(
|
||||
tags = ["maven_coordinates=com.daml:flyway-testing:__VERSION__"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//libs-scala/crypto",
|
||||
"@maven//:org_flywaydb_flyway_core",
|
||||
"@maven//:org_scalatest_scalatest_compatible",
|
||||
],
|
||||
|
@ -3,12 +3,7 @@
|
||||
|
||||
package com.daml.flyway
|
||||
|
||||
import java.io.{BufferedReader, FileNotFoundException}
|
||||
import java.math.BigInteger
|
||||
import java.nio.charset.Charset
|
||||
import java.security.MessageDigest
|
||||
import java.util
|
||||
|
||||
import com.daml.crypto.MessageDigestPrototype
|
||||
import org.flywaydb.core.Flyway
|
||||
import org.flywaydb.core.api.configuration.FluentConfiguration
|
||||
import org.flywaydb.core.api.resource.LoadableResource
|
||||
@ -16,6 +11,10 @@ import org.flywaydb.core.internal.scanner.{LocationScannerCache, ResourceNameCac
|
||||
import org.scalatest.matchers.should.Matchers._
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
import java.io.{BufferedReader, FileNotFoundException}
|
||||
import java.math.BigInteger
|
||||
import java.nio.charset.Charset
|
||||
import java.util
|
||||
import scala.jdk.CollectionConverters._
|
||||
|
||||
abstract class AbstractImmutableMigrationsSpec extends AnyWordSpec {
|
||||
@ -50,7 +49,7 @@ abstract class AbstractImmutableMigrationsSpec extends AnyWordSpec {
|
||||
}
|
||||
|
||||
private def computeCurrentDigest(resource: LoadableResource, encoding: Charset): String = {
|
||||
val sha256 = MessageDigest.getInstance("SHA-256")
|
||||
val sha256 = MessageDigestPrototype.SHA_256.newDigest
|
||||
new BufferedReader(resource.read())
|
||||
.lines()
|
||||
.forEach(line => sha256.update((line + "\n").getBytes(encoding)))
|
||||
|
@ -217,6 +217,8 @@
|
||||
type: jar-scala
|
||||
- target: //libs-scala/contextualized-logging:contextualized-logging
|
||||
type: jar-scala
|
||||
- target: //libs-scala/crypto:crypto
|
||||
type: jar-scala
|
||||
- target: //libs-scala/doobie-slf4j:doobie-slf4j
|
||||
type: jar-scala
|
||||
- target: //libs-scala/grpc-utils:grpc-utils
|
||||
|
Loading…
Reference in New Issue
Block a user