From 299748ecfd2a837e9c57cf6fa939588e3afdee17 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Fri, 19 Aug 2022 06:00:51 +0000 Subject: [PATCH 01/12] Hash on Native --- build.sbt | 28 ++++++---- .../org/http4s/crypto/SecurityException.scala | 0 .../org/http4s/crypto/SecureEqPlatform.scala | 0 .../org/http4s/crypto/CryptoPlatform.scala | 28 ++++++++++ .../org/http4s/crypto/HashPlatform.scala | 54 ++++++++++++++++++ .../http4s/crypto/HmacKeyGenPlatform.scala | 33 +++++++++++ .../org/http4s/crypto/HmacPlatform.scala | 55 +++++++++++++++++++ .../scala/org/http4s/crypto/KeyPlatform.scala | 23 ++++++++ .../scala/org/http4s/crypto/openssl/evp.scala | 40 ++++++++++++++ .../scala/org/http4s/crypto/HashSuite.scala | 6 +- project/plugins.sbt | 2 + 11 files changed, 256 insertions(+), 13 deletions(-) rename crypto/{js => js-native}/src/main/scala/org/http4s/crypto/SecurityException.scala (100%) rename crypto/{jvm => jvm-native}/src/main/scala/org/http4s/crypto/SecureEqPlatform.scala (100%) create mode 100644 crypto/native/src/main/scala/org/http4s/crypto/CryptoPlatform.scala create mode 100644 crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala create mode 100644 crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala create mode 100644 crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala create mode 100644 crypto/native/src/main/scala/org/http4s/crypto/KeyPlatform.scala create mode 100644 crypto/native/src/main/scala/org/http4s/crypto/openssl/evp.scala diff --git a/build.sbt b/build.sbt index 228b65f..2566fbb 100644 --- a/build.sbt +++ b/build.sbt @@ -54,7 +54,8 @@ ThisBuild / githubWorkflowBuildMatrixExclusions ++= { ThisBuild / githubWorkflowBuildMatrixExclusions ++= { for { jsenv <- jsenvs.tail - } yield MatrixExclude(Map("project" -> "rootJVM", "jsenv" -> jsenv)) + project <- List("rootJVM", "rootNative") + } yield MatrixExclude(Map("project" -> project, "jsenv" -> jsenv)) } lazy val useJSEnv = @@ -78,32 +79,34 @@ ThisBuild / Test / jsEnv := { } val catsVersion = "2.8.0" -val catsEffectVersion = "3.3.14" +val catsEffectVersion = "3.4-f28b163-SNAPSHOT" val scodecBitsVersion = "1.1.34" -val munitVersion = "0.7.29" -val munitCEVersion = "1.0.7" -val disciplineMUnitVersion = "1.0.9" +val munitVersion = "1.0.0-M6" +val munitCEVersion = "2.0-4e051ab-SNAPSHOT" +val disciplineMUnitVersion = "2.0.0-M3" + +ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots") lazy val root = tlCrossRootProject.aggregate(crypto, testRuntime) -lazy val crypto = crossProject(JSPlatform, JVMPlatform) +lazy val crypto = crossProject(JSPlatform, JVMPlatform, NativePlatform) .in(file("crypto")) .settings( name := "http4s-crypto", libraryDependencies ++= Seq( "org.typelevel" %%% "cats-core" % catsVersion, - "org.typelevel" %%% "cats-effect-kernel" % catsEffectVersion, + "com.armanbilge" %%% "cats-effect-kernel" % catsEffectVersion, "org.scodec" %%% "scodec-bits" % scodecBitsVersion, "org.scalameta" %%% "munit" % munitVersion % Test, "org.typelevel" %%% "cats-laws" % catsVersion % Test, - "org.typelevel" %%% "cats-effect" % catsEffectVersion % Test, + "com.armanbilge" %%% "cats-effect" % catsEffectVersion % Test, "org.typelevel" %%% "discipline-munit" % disciplineMUnitVersion % Test, - "org.typelevel" %%% "munit-cats-effect-3" % munitCEVersion % Test + "com.armanbilge" %%% "munit-cats-effect" % munitCEVersion % Test ) ) .dependsOn(testRuntime % Test) -lazy val testRuntime = crossProject(JSPlatform, JVMPlatform) +lazy val testRuntime = crossProject(JSPlatform, JVMPlatform, NativePlatform) .crossType(CrossType.Pure) .in(file("test-runtime")) .enablePlugins(BuildInfoPlugin, NoPublishPlugin) @@ -120,3 +123,8 @@ lazy val testRuntime = crossProject(JSPlatform, JVMPlatform) BuildInfoKey("runtime" -> useJSEnv.value.toString) ) ) + .nativeSettings( + buildInfoKeys := Seq( + BuildInfoKey("runtime" -> "Native") + ) + ) \ No newline at end of file diff --git a/crypto/js/src/main/scala/org/http4s/crypto/SecurityException.scala b/crypto/js-native/src/main/scala/org/http4s/crypto/SecurityException.scala similarity index 100% rename from crypto/js/src/main/scala/org/http4s/crypto/SecurityException.scala rename to crypto/js-native/src/main/scala/org/http4s/crypto/SecurityException.scala diff --git a/crypto/jvm/src/main/scala/org/http4s/crypto/SecureEqPlatform.scala b/crypto/jvm-native/src/main/scala/org/http4s/crypto/SecureEqPlatform.scala similarity index 100% rename from crypto/jvm/src/main/scala/org/http4s/crypto/SecureEqPlatform.scala rename to crypto/jvm-native/src/main/scala/org/http4s/crypto/SecureEqPlatform.scala diff --git a/crypto/native/src/main/scala/org/http4s/crypto/CryptoPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/CryptoPlatform.scala new file mode 100644 index 0000000..297a2be --- /dev/null +++ b/crypto/native/src/main/scala/org/http4s/crypto/CryptoPlatform.scala @@ -0,0 +1,28 @@ +/* + * Copyright 2021 http4s.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.http4s.crypto + +import cats.effect.kernel.Sync + +private[crypto] trait CryptoCompanionPlatform { + implicit def forSync[F[_]: Sync]: Crypto[F] = + new UnsealedCrypto[F] { + override def hash: Hash[F] = Hash[F] + override def hmac: Hmac[F] = Hmac[F] + override def hmacKeyGen: HmacKeyGen[F] = HmacKeyGen[F] + } +} diff --git a/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala new file mode 100644 index 0000000..94d2210 --- /dev/null +++ b/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala @@ -0,0 +1,54 @@ +/* + * Copyright 2021 http4s.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.http4s.crypto + +import cats.ApplicativeThrow +import scodec.bits.ByteVector + +import scala.scalanative.unsafe._ +import scala.scalanative.unsigned._ + +private[crypto] trait HashCompanionPlatform { + implicit def forApplicativeThrow[F[_]](implicit F: ApplicativeThrow[F]): Hash[F] = + new UnsealedHash[F] { + def digest(algorithm: HashAlgorithm, data: ByteVector): F[ByteVector] = + Zone { implicit z => + + import HashAlgorithm._ + + val name = algorithm match { + case MD5 => c"MD5" + case SHA1 => c"SHA1" + case SHA256 => c"SHA256" + case SHA512 => c"SHA512" + } + + val `type` = openssl.evp.EVP_get_digestbyname(name) + if (`type` == null) + F.raiseError(new RuntimeException("EVP_get_digestbyname")) + + val md = stackalloc[CUnsignedChar](openssl.evp.EVP_MAX_MD_SIZE) + val size = stackalloc[CUnsignedInt]() + + if (openssl.evp.EVP_Digest(data.toPtr, data.size.toULong, md, size, `type`, null) == 1) + F.pure(ByteVector.fromPtr(md.asInstanceOf[Ptr[Byte]], (!size).toLong)) + else + F.raiseError(new RuntimeException("EVP_DIGEST")) + } + + } +} diff --git a/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala new file mode 100644 index 0000000..105ff9e --- /dev/null +++ b/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala @@ -0,0 +1,33 @@ +/* + * Copyright 2021 http4s.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.http4s.crypto + +import cats.effect.kernel.Sync +import scodec.bits.ByteVector + +import javax.crypto + +private[crypto] trait HmacKeyGenCompanionPlatform { + implicit def forSync[F[_]](implicit F: Sync[F]): HmacKeyGen[F] = + new UnsealedHmacKeyGen[F] { + override def generateKey[A <: HmacAlgorithm](algorithm: A): F[SecretKey[A]] = + F.delay { + val key = crypto.KeyGenerator.getInstance(algorithm.toStringJava).generateKey() + SecretKeySpec(ByteVector.view(key.getEncoded()), algorithm) + } + } +} diff --git a/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala new file mode 100644 index 0000000..11780fd --- /dev/null +++ b/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala @@ -0,0 +1,55 @@ +/* + * Copyright 2021 http4s.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.http4s.crypto + +import cats.ApplicativeThrow +import scodec.bits.ByteVector + +import javax.crypto + +private[crypto] trait HmacPlatform[F[_]] { + def importJavaKey(key: crypto.SecretKey): F[SecretKey[HmacAlgorithm]] +} + +private[crypto] trait HmacCompanionPlatform { + implicit def forApplicativeThrow[F[_]](implicit F: ApplicativeThrow[F]): Hmac[F] = + new UnsealedHmac[F] { + + override def digest(key: SecretKey[HmacAlgorithm], data: ByteVector): F[ByteVector] = + F.catchNonFatal { + val mac = crypto.Mac.getInstance(key.algorithm.toStringJava) + // val sk = key.toJava + // mac.init(sk) + mac.update(data.toByteBuffer) + ByteVector.view(mac.doFinal()) + } + + override def importKey[A <: HmacAlgorithm]( + key: ByteVector, + algorithm: A): F[SecretKey[A]] = + F.pure(SecretKeySpec(key, algorithm)) + + override def importJavaKey(key: crypto.SecretKey): F[SecretKey[HmacAlgorithm]] = + F.fromOption( + for { + algorithm <- HmacAlgorithm.fromStringJava(key.getAlgorithm()) + key <- Option(key.getEncoded()) + } yield SecretKeySpec(ByteVector.view(key), algorithm), + new InvalidKeyException + ) + } +} diff --git a/crypto/native/src/main/scala/org/http4s/crypto/KeyPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/KeyPlatform.scala new file mode 100644 index 0000000..177f965 --- /dev/null +++ b/crypto/native/src/main/scala/org/http4s/crypto/KeyPlatform.scala @@ -0,0 +1,23 @@ +/* + * Copyright 2021 http4s.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.http4s.crypto + +private[crypto] trait KeyPlatform +private[crypto] trait PublicKeyPlatform +private[crypto] trait PrivateKeyPlatform +private[crypto] trait SecretKeyPlatform +private[crypto] trait SecretKeySpecPlatform[+A <: Algorithm] diff --git a/crypto/native/src/main/scala/org/http4s/crypto/openssl/evp.scala b/crypto/native/src/main/scala/org/http4s/crypto/openssl/evp.scala new file mode 100644 index 0000000..396e7e5 --- /dev/null +++ b/crypto/native/src/main/scala/org/http4s/crypto/openssl/evp.scala @@ -0,0 +1,40 @@ +/* + * Copyright 2021 http4s.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.http4s.crypto.openssl + +import scala.annotation.nowarn +import scala.scalanative.unsafe._ + +@link("crypto") +@extern +@nowarn +private[crypto] object evp { + + final val EVP_MAX_MD_SIZE = 64 + + def EVP_Digest( + data: Ptr[Byte], + count: CSize, + md: Ptr[CUnsignedChar], + size: Ptr[CUnsignedInt], + `type`: Ptr[Byte], + impl: Ptr[Byte] + ): CInt = extern + + def EVP_get_digestbyname(name: Ptr[CChar]): Ptr[Byte] = extern + +} diff --git a/crypto/shared/src/test/scala/org/http4s/crypto/HashSuite.scala b/crypto/shared/src/test/scala/org/http4s/crypto/HashSuite.scala index a0d741f..49f4c4b 100644 --- a/crypto/shared/src/test/scala/org/http4s/crypto/HashSuite.scala +++ b/crypto/shared/src/test/scala/org/http4s/crypto/HashSuite.scala @@ -44,7 +44,7 @@ final class HashSuite extends CatsEffectSuite { } def tests[F[_]: Hash: Functor](implicit ct: ClassTag[F[Nothing]]): Unit = { - if (Set("JVM", "NodeJS").contains(BuildInfo.runtime)) + if (Set("JVM", "NodeJS", "Native").contains(BuildInfo.runtime)) testHash[F](MD5, "9e107d9d372bb6826bd81d3542a419d6") testHash[F](SHA1, "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12") testHash[F](SHA256, "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592") @@ -53,10 +53,10 @@ final class HashSuite extends CatsEffectSuite { "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6") } - if (Set("JVM", "NodeJS").contains(BuildInfo.runtime)) + if (Set("JVM", "NodeJS", "Native").contains(BuildInfo.runtime)) tests[SyncIO] - if (BuildInfo.runtime != "JVM") + if (!Set("JVM", "Native").contains(BuildInfo.runtime)) tests[IO] } diff --git a/project/plugins.sbt b/project/plugins.sbt index 1e65d8c..cbc2396 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -3,3 +3,5 @@ libraryDependencies += "org.scala-js" %% "scalajs-env-selenium" % "1.1.1" addSbtPlugin("org.http4s" % "sbt-http4s-org" % "0.14.4") addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.10.1") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0") +addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.5") +addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.2.0") From 8c82670a428229206202f5aef9a40b4ca094dc32 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Fri, 19 Aug 2022 06:47:42 +0000 Subject: [PATCH 02/12] HMAC native --- .../org/http4s/crypto/HashPlatform.scala | 5 +- .../http4s/crypto/HmacKeyGenPlatform.scala | 7 +-- .../org/http4s/crypto/HmacPlatform.scala | 59 +++++++++++-------- .../org/http4s/crypto/openssl/hmac.scala | 37 ++++++++++++ .../scala/org/http4s/crypto/HmacSuite.scala | 8 +-- 5 files changed, 82 insertions(+), 34 deletions(-) create mode 100644 crypto/native/src/main/scala/org/http4s/crypto/openssl/hmac.scala diff --git a/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala index 94d2210..8b67d4d 100644 --- a/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala +++ b/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala @@ -27,7 +27,6 @@ private[crypto] trait HashCompanionPlatform { new UnsealedHash[F] { def digest(algorithm: HashAlgorithm, data: ByteVector): F[ByteVector] = Zone { implicit z => - import HashAlgorithm._ val name = algorithm match { @@ -44,7 +43,9 @@ private[crypto] trait HashCompanionPlatform { val md = stackalloc[CUnsignedChar](openssl.evp.EVP_MAX_MD_SIZE) val size = stackalloc[CUnsignedInt]() - if (openssl.evp.EVP_Digest(data.toPtr, data.size.toULong, md, size, `type`, null) == 1) + if (openssl + .evp + .EVP_Digest(data.toPtr, data.size.toULong, md, size, `type`, null) == 1) F.pure(ByteVector.fromPtr(md.asInstanceOf[Ptr[Byte]], (!size).toLong)) else F.raiseError(new RuntimeException("EVP_DIGEST")) diff --git a/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala index 105ff9e..a5a4cd9 100644 --- a/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala +++ b/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala @@ -19,15 +19,12 @@ package org.http4s.crypto import cats.effect.kernel.Sync import scodec.bits.ByteVector -import javax.crypto - private[crypto] trait HmacKeyGenCompanionPlatform { implicit def forSync[F[_]](implicit F: Sync[F]): HmacKeyGen[F] = new UnsealedHmacKeyGen[F] { - override def generateKey[A <: HmacAlgorithm](algorithm: A): F[SecretKey[A]] = + def generateKey[A <: HmacAlgorithm](algorithm: A): F[SecretKey[A]] = F.delay { - val key = crypto.KeyGenerator.getInstance(algorithm.toStringJava).generateKey() - SecretKeySpec(ByteVector.view(key.getEncoded()), algorithm) + ??? } } } diff --git a/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala index 11780fd..733abf1 100644 --- a/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala +++ b/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala @@ -19,37 +19,50 @@ package org.http4s.crypto import cats.ApplicativeThrow import scodec.bits.ByteVector -import javax.crypto +import scala.scalanative.unsafe._ +import scala.scalanative.unsigned._ -private[crypto] trait HmacPlatform[F[_]] { - def importJavaKey(key: crypto.SecretKey): F[SecretKey[HmacAlgorithm]] -} +private[crypto] trait HmacPlatform[F[_]] private[crypto] trait HmacCompanionPlatform { implicit def forApplicativeThrow[F[_]](implicit F: ApplicativeThrow[F]): Hmac[F] = new UnsealedHmac[F] { - override def digest(key: SecretKey[HmacAlgorithm], data: ByteVector): F[ByteVector] = - F.catchNonFatal { - val mac = crypto.Mac.getInstance(key.algorithm.toStringJava) - // val sk = key.toJava - // mac.init(sk) - mac.update(data.toByteBuffer) - ByteVector.view(mac.doFinal()) + def digest(key: SecretKey[HmacAlgorithm], data: ByteVector): F[ByteVector] = + Zone { implicit z => + import HmacAlgorithm._ + + val SecretKeySpec(keyBytes, algorithm) = key + + val name = algorithm match { + case SHA1 => c"SHA1" + case SHA256 => c"SHA256" + case SHA512 => c"SHA512" + } + + val evpMd = openssl.evp.EVP_get_digestbyname(name) + if (evpMd == null) + F.raiseError(new RuntimeException("EVP_get_digestbyname")) + + val md = stackalloc[CUnsignedChar](openssl.evp.EVP_MAX_MD_SIZE) + val mdLen = stackalloc[CUnsignedInt]() + + if (openssl + .hmac + .HMAC( + evpMd, + keyBytes.toPtr, + keyBytes.size.toInt, + data.toPtr.asInstanceOf[Ptr[CUnsignedChar]], + data.size.toULong, + md, + mdLen) != null) + F.pure(ByteVector.fromPtr(md.asInstanceOf[Ptr[Byte]], (!mdLen).toLong)) + else + F.raiseError(new RuntimeException("HMAC")) } - override def importKey[A <: HmacAlgorithm]( - key: ByteVector, - algorithm: A): F[SecretKey[A]] = + def importKey[A <: HmacAlgorithm](key: ByteVector, algorithm: A): F[SecretKey[A]] = F.pure(SecretKeySpec(key, algorithm)) - - override def importJavaKey(key: crypto.SecretKey): F[SecretKey[HmacAlgorithm]] = - F.fromOption( - for { - algorithm <- HmacAlgorithm.fromStringJava(key.getAlgorithm()) - key <- Option(key.getEncoded()) - } yield SecretKeySpec(ByteVector.view(key), algorithm), - new InvalidKeyException - ) } } diff --git a/crypto/native/src/main/scala/org/http4s/crypto/openssl/hmac.scala b/crypto/native/src/main/scala/org/http4s/crypto/openssl/hmac.scala new file mode 100644 index 0000000..003ca80 --- /dev/null +++ b/crypto/native/src/main/scala/org/http4s/crypto/openssl/hmac.scala @@ -0,0 +1,37 @@ +/* + * Copyright 2021 http4s.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.http4s.crypto.openssl + +import scala.annotation.nowarn +import scala.scalanative.unsafe._ + +@link("crypto") +@extern +@nowarn +private[crypto] object hmac { + + def HMAC( + evp_md: Ptr[Byte], + key: Ptr[Byte], + key_len: Int, + d: Ptr[CUnsignedChar], + n: CSize, + md: Ptr[CUnsignedChar], + md_len: Ptr[CUnsignedInt] + ): Ptr[CUnsignedChar] = extern + +} diff --git a/crypto/shared/src/test/scala/org/http4s/crypto/HmacSuite.scala b/crypto/shared/src/test/scala/org/http4s/crypto/HmacSuite.scala index 15009c5..a70f89a 100644 --- a/crypto/shared/src/test/scala/org/http4s/crypto/HmacSuite.scala +++ b/crypto/shared/src/test/scala/org/http4s/crypto/HmacSuite.scala @@ -62,16 +62,16 @@ final class HmacSuite extends CatsEffectSuite { } } - if (Set("JVM", "NodeJS").contains(BuildInfo.runtime)) + if (Set("JVM", "NodeJS", "Native").contains(BuildInfo.runtime)) tests[SyncIO] - if (BuildInfo.runtime != "JVM") + if (!Set("JVM", "Native").contains(BuildInfo.runtime)) tests[IO] - if (BuildInfo.runtime == "JVM") + if (Set("JVM").contains(BuildInfo.runtime)) List(SHA1, SHA256, SHA512).foreach(testGenerateKey[SyncIO]) - if (!Set("JVM", "NodeJS").contains( + if (!Set("JVM", "Native", "NodeJS").contains( BuildInfo.runtime )) // Disabled until testing against Node 16 List(SHA1, SHA256, SHA512).foreach(testGenerateKey[IO]) From c1ca55eb36da1a86e3eea95ccd5a182ed8ba9585 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Fri, 19 Aug 2022 08:12:24 +0000 Subject: [PATCH 03/12] HmacKeyGen native --- build.sbt | 7 ++++++- .../main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala | 8 ++++++-- .../src/test/scala/org/http4s/crypto/HmacSuite.scala | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/build.sbt b/build.sbt index 2566fbb..cc929ba 100644 --- a/build.sbt +++ b/build.sbt @@ -104,6 +104,11 @@ lazy val crypto = crossProject(JSPlatform, JVMPlatform, NativePlatform) "com.armanbilge" %%% "munit-cats-effect" % munitCEVersion % Test ) ) + .nativeSettings( + libraryDependencies ++= Seq( + "com.armanbilge" %%% "cats-effect" % catsEffectVersion + ) + ) .dependsOn(testRuntime % Test) lazy val testRuntime = crossProject(JSPlatform, JVMPlatform, NativePlatform) @@ -127,4 +132,4 @@ lazy val testRuntime = crossProject(JSPlatform, JVMPlatform, NativePlatform) buildInfoKeys := Seq( BuildInfoKey("runtime" -> "Native") ) - ) \ No newline at end of file + ) diff --git a/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala index a5a4cd9..79187b6 100644 --- a/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala +++ b/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala @@ -17,14 +17,18 @@ package org.http4s.crypto import cats.effect.kernel.Sync +import cats.effect.std.SecureRandom +import cats.effect.SyncIO +import cats.syntax.all._ import scodec.bits.ByteVector private[crypto] trait HmacKeyGenCompanionPlatform { implicit def forSync[F[_]](implicit F: Sync[F]): HmacKeyGen[F] = new UnsealedHmacKeyGen[F] { + private val random = SecureRandom.javaSecuritySecureRandom[SyncIO].unsafeRunSync() def generateKey[A <: HmacAlgorithm](algorithm: A): F[SecretKey[A]] = - F.delay { - ??? + random.nextBytes(algorithm.minimumKeyLength).to[F].map { bytes => + SecretKeySpec(ByteVector.view(bytes), algorithm) } } } diff --git a/crypto/shared/src/test/scala/org/http4s/crypto/HmacSuite.scala b/crypto/shared/src/test/scala/org/http4s/crypto/HmacSuite.scala index a70f89a..f4deccb 100644 --- a/crypto/shared/src/test/scala/org/http4s/crypto/HmacSuite.scala +++ b/crypto/shared/src/test/scala/org/http4s/crypto/HmacSuite.scala @@ -68,7 +68,7 @@ final class HmacSuite extends CatsEffectSuite { if (!Set("JVM", "Native").contains(BuildInfo.runtime)) tests[IO] - if (Set("JVM").contains(BuildInfo.runtime)) + if (Set("JVM", "Native").contains(BuildInfo.runtime)) List(SHA1, SHA256, SHA512).foreach(testGenerateKey[SyncIO]) if (!Set("JVM", "Native", "NodeJS").contains( From ec1fd65006580bb4c1f3ef0f6d7a8b2369d6d2bd Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Fri, 9 Sep 2022 14:20:29 +0000 Subject: [PATCH 04/12] I've been writing too much imperative code lately --- .../org/http4s/crypto/HashPlatform.scala | 21 ++++++------ .../org/http4s/crypto/HmacPlatform.scala | 33 ++++++++++--------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala index 8b67d4d..09d48bf 100644 --- a/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala +++ b/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala @@ -39,16 +39,17 @@ private[crypto] trait HashCompanionPlatform { val `type` = openssl.evp.EVP_get_digestbyname(name) if (`type` == null) F.raiseError(new RuntimeException("EVP_get_digestbyname")) - - val md = stackalloc[CUnsignedChar](openssl.evp.EVP_MAX_MD_SIZE) - val size = stackalloc[CUnsignedInt]() - - if (openssl - .evp - .EVP_Digest(data.toPtr, data.size.toULong, md, size, `type`, null) == 1) - F.pure(ByteVector.fromPtr(md.asInstanceOf[Ptr[Byte]], (!size).toLong)) - else - F.raiseError(new RuntimeException("EVP_DIGEST")) + else { + val md = stackalloc[CUnsignedChar](openssl.evp.EVP_MAX_MD_SIZE) + val size = stackalloc[CUnsignedInt]() + + if (openssl + .evp + .EVP_Digest(data.toPtr, data.size.toULong, md, size, `type`, null) == 1) + F.pure(ByteVector.fromPtr(md.asInstanceOf[Ptr[Byte]], (!size).toLong)) + else + F.raiseError(new RuntimeException("EVP_DIGEST")) + } } } diff --git a/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala index 733abf1..1653d07 100644 --- a/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala +++ b/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala @@ -43,23 +43,24 @@ private[crypto] trait HmacCompanionPlatform { val evpMd = openssl.evp.EVP_get_digestbyname(name) if (evpMd == null) F.raiseError(new RuntimeException("EVP_get_digestbyname")) + else { + val md = stackalloc[CUnsignedChar](openssl.evp.EVP_MAX_MD_SIZE) + val mdLen = stackalloc[CUnsignedInt]() - val md = stackalloc[CUnsignedChar](openssl.evp.EVP_MAX_MD_SIZE) - val mdLen = stackalloc[CUnsignedInt]() - - if (openssl - .hmac - .HMAC( - evpMd, - keyBytes.toPtr, - keyBytes.size.toInt, - data.toPtr.asInstanceOf[Ptr[CUnsignedChar]], - data.size.toULong, - md, - mdLen) != null) - F.pure(ByteVector.fromPtr(md.asInstanceOf[Ptr[Byte]], (!mdLen).toLong)) - else - F.raiseError(new RuntimeException("HMAC")) + if (openssl + .hmac + .HMAC( + evpMd, + keyBytes.toPtr, + keyBytes.size.toInt, + data.toPtr.asInstanceOf[Ptr[CUnsignedChar]], + data.size.toULong, + md, + mdLen) != null) + F.pure(ByteVector.fromPtr(md.asInstanceOf[Ptr[Byte]], (!mdLen).toLong)) + else + F.raiseError(new RuntimeException("HMAC")) + } } def importKey[A <: HmacAlgorithm](key: ByteVector, algorithm: A): F[SecretKey[A]] = From 5fcf578c7aff66c346e343ebf508560b0a4feda7 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Fri, 9 Sep 2022 23:04:33 +0000 Subject: [PATCH 05/12] Bump versions --- build.sbt | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/build.sbt b/build.sbt index cc929ba..b42de26 100644 --- a/build.sbt +++ b/build.sbt @@ -79,14 +79,12 @@ ThisBuild / Test / jsEnv := { } val catsVersion = "2.8.0" -val catsEffectVersion = "3.4-f28b163-SNAPSHOT" +val catsEffectVersion = "3.3.14-1-5d11fe9" val scodecBitsVersion = "1.1.34" val munitVersion = "1.0.0-M6" -val munitCEVersion = "2.0-4e051ab-SNAPSHOT" +val munitCEVersion = "2.0-5e03bfc" val disciplineMUnitVersion = "2.0.0-M3" -ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots") - lazy val root = tlCrossRootProject.aggregate(crypto, testRuntime) lazy val crypto = crossProject(JSPlatform, JVMPlatform, NativePlatform) @@ -95,13 +93,13 @@ lazy val crypto = crossProject(JSPlatform, JVMPlatform, NativePlatform) name := "http4s-crypto", libraryDependencies ++= Seq( "org.typelevel" %%% "cats-core" % catsVersion, - "com.armanbilge" %%% "cats-effect-kernel" % catsEffectVersion, + "org.typelevel" %%% "cats-effect-kernel" % catsEffectVersion, "org.scodec" %%% "scodec-bits" % scodecBitsVersion, "org.scalameta" %%% "munit" % munitVersion % Test, "org.typelevel" %%% "cats-laws" % catsVersion % Test, - "com.armanbilge" %%% "cats-effect" % catsEffectVersion % Test, + "org.typelevel" %%% "cats-effect" % catsEffectVersion % Test, "org.typelevel" %%% "discipline-munit" % disciplineMUnitVersion % Test, - "com.armanbilge" %%% "munit-cats-effect" % munitCEVersion % Test + "org.typelevel" %%% "munit-cats-effect" % munitCEVersion % Test ) ) .nativeSettings( From bb48bf18164879f4f2fa49de116c2a7bdf106685 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Sat, 10 Sep 2022 00:08:54 +0000 Subject: [PATCH 06/12] Use `RAND_bytes` --- build.sbt | 4 +-- .../http4s/crypto/HmacKeyGenPlatform.scala | 14 ++++---- .../org/http4s/crypto/openssl/rand.scala | 32 +++++++++++++++++++ 3 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 crypto/native/src/main/scala/org/http4s/crypto/openssl/rand.scala diff --git a/build.sbt b/build.sbt index b6db1e1..07b18d1 100644 --- a/build.sbt +++ b/build.sbt @@ -103,9 +103,7 @@ lazy val crypto = crossProject(JSPlatform, JVMPlatform, NativePlatform) ) ) .nativeSettings( - libraryDependencies ++= Seq( - "com.armanbilge" %%% "cats-effect" % catsEffectVersion - ) + tlVersionIntroduced := List("2.12", "2.13", "3").map(_ -> "0.2.4").toMap ) .dependsOn(testRuntime % Test) diff --git a/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala index 79187b6..4c0ce37 100644 --- a/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala +++ b/crypto/native/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala @@ -17,18 +17,20 @@ package org.http4s.crypto import cats.effect.kernel.Sync -import cats.effect.std.SecureRandom -import cats.effect.SyncIO -import cats.syntax.all._ import scodec.bits.ByteVector +import scala.scalanative.unsafe._ + private[crypto] trait HmacKeyGenCompanionPlatform { implicit def forSync[F[_]](implicit F: Sync[F]): HmacKeyGen[F] = new UnsealedHmacKeyGen[F] { - private val random = SecureRandom.javaSecuritySecureRandom[SyncIO].unsafeRunSync() def generateKey[A <: HmacAlgorithm](algorithm: A): F[SecretKey[A]] = - random.nextBytes(algorithm.minimumKeyLength).to[F].map { bytes => - SecretKeySpec(ByteVector.view(bytes), algorithm) + F.delay { + val len = algorithm.minimumKeyLength + val buf = stackalloc[Byte](len.toLong) + if (openssl.rand.RAND_bytes(buf, len) != 1) + throw new GeneralSecurityException("RAND_bytes") + SecretKeySpec(ByteVector.fromPtr(buf, len.toLong), algorithm) } } } diff --git a/crypto/native/src/main/scala/org/http4s/crypto/openssl/rand.scala b/crypto/native/src/main/scala/org/http4s/crypto/openssl/rand.scala new file mode 100644 index 0000000..b8ca7a3 --- /dev/null +++ b/crypto/native/src/main/scala/org/http4s/crypto/openssl/rand.scala @@ -0,0 +1,32 @@ +/* + * Copyright 2021 http4s.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.http4s.crypto.openssl + +import scala.annotation.nowarn +import scala.scalanative.unsafe._ + +@link("crypto") +@extern +@nowarn +private[crypto] object rand { + + def RAND_bytes( + buf: Ptr[CChar], + num: CInt + ): CInt = extern + +} From ca26911a41160966040f611884fa2c2426f73498 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Sat, 10 Sep 2022 00:09:23 +0000 Subject: [PATCH 07/12] Bump Scala Native --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index cbc2396..7c7f742 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -3,5 +3,5 @@ libraryDependencies += "org.scala-js" %% "scalajs-env-selenium" % "1.1.1" addSbtPlugin("org.http4s" % "sbt-http4s-org" % "0.14.4") addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.10.1") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0") -addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.5") +addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.7") addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.2.0") From 10073325ce9640330fac595b530a4c0af373a660 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Sat, 10 Sep 2022 00:12:32 +0000 Subject: [PATCH 08/12] Use `GeneralSecurityException` for openssl errors --- .../src/main/scala/org/http4s/crypto/HashPlatform.scala | 4 ++-- .../src/main/scala/org/http4s/crypto/HmacPlatform.scala | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala index 09d48bf..5cb5b59 100644 --- a/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala +++ b/crypto/native/src/main/scala/org/http4s/crypto/HashPlatform.scala @@ -38,7 +38,7 @@ private[crypto] trait HashCompanionPlatform { val `type` = openssl.evp.EVP_get_digestbyname(name) if (`type` == null) - F.raiseError(new RuntimeException("EVP_get_digestbyname")) + F.raiseError(new GeneralSecurityException("EVP_get_digestbyname")) else { val md = stackalloc[CUnsignedChar](openssl.evp.EVP_MAX_MD_SIZE) val size = stackalloc[CUnsignedInt]() @@ -48,7 +48,7 @@ private[crypto] trait HashCompanionPlatform { .EVP_Digest(data.toPtr, data.size.toULong, md, size, `type`, null) == 1) F.pure(ByteVector.fromPtr(md.asInstanceOf[Ptr[Byte]], (!size).toLong)) else - F.raiseError(new RuntimeException("EVP_DIGEST")) + F.raiseError(new GeneralSecurityException("EVP_DIGEST")) } } diff --git a/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala b/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala index 1653d07..c8df420 100644 --- a/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala +++ b/crypto/native/src/main/scala/org/http4s/crypto/HmacPlatform.scala @@ -42,7 +42,7 @@ private[crypto] trait HmacCompanionPlatform { val evpMd = openssl.evp.EVP_get_digestbyname(name) if (evpMd == null) - F.raiseError(new RuntimeException("EVP_get_digestbyname")) + F.raiseError(new GeneralSecurityException("EVP_get_digestbyname")) else { val md = stackalloc[CUnsignedChar](openssl.evp.EVP_MAX_MD_SIZE) val mdLen = stackalloc[CUnsignedInt]() @@ -59,7 +59,7 @@ private[crypto] trait HmacCompanionPlatform { mdLen) != null) F.pure(ByteVector.fromPtr(md.asInstanceOf[Ptr[Byte]], (!mdLen).toLong)) else - F.raiseError(new RuntimeException("HMAC")) + F.raiseError(new GeneralSecurityException("HMAC")) } } From 6f5833025cfcc5ad2b9b16db2b8ec9ebfcc817f5 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Sat, 10 Sep 2022 00:13:20 +0000 Subject: [PATCH 09/12] Regenerate workflow --- .github/workflows/ci.yml | 48 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3390054..5702c1b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: os: [ubuntu-latest] scala: [3.1.3, 2.12.16, 2.13.8] java: [temurin@8, temurin@11, temurin@17] - project: [rootJS, rootJVM] + project: [rootJS, rootJVM, rootNative] jsenv: [NodeJS, Chrome, Firefox] exclude: - scala: 3.1.3 @@ -46,6 +46,10 @@ jobs: java: temurin@11 - project: rootJS java: temurin@17 + - project: rootNative + java: temurin@11 + - project: rootNative + java: temurin@17 - scala: 3.1.3 jsenv: Chrome - scala: 3.1.3 @@ -56,8 +60,12 @@ jobs: jsenv: Firefox - project: rootJVM jsenv: Chrome + - project: rootNative + jsenv: Chrome - project: rootJVM jsenv: Firefox + - project: rootNative + jsenv: Firefox runs-on: ${{ matrix.os }} steps: - name: Checkout current branch (full) @@ -142,6 +150,10 @@ jobs: if: matrix.project == 'rootJS' run: 'sbt ''project ${{ matrix.project }}'' ''++${{ matrix.scala }}'' ''set Global / useJSEnv := JSEnv.${{ matrix.jsenv }}'' Test/scalaJSLinkerResult' + - name: nativeLink + if: matrix.project == 'rootNative' + run: 'sbt ''project ${{ matrix.project }}'' ''++${{ matrix.scala }}'' ''set Global / useJSEnv := JSEnv.${{ matrix.jsenv }}'' Test/nativeLink' + - name: Test run: 'sbt ''project ${{ matrix.project }}'' ''++${{ matrix.scala }}'' ''set Global / useJSEnv := JSEnv.${{ matrix.jsenv }}'' test' @@ -163,11 +175,11 @@ jobs: - name: Make target directories if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') - run: mkdir -p crypto/jvm/target target .js/target .jvm/target .native/target test-runtime/.jvm/target crypto/js/target test-runtime/.js/target project/target + run: mkdir -p crypto/jvm/target target .js/target crypto/native/target .jvm/target .native/target test-runtime/.jvm/target crypto/js/target test-runtime/.js/target test-runtime/.native/target project/target - name: Compress target directories if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') - run: tar cf targets.tar crypto/jvm/target target .js/target .jvm/target .native/target test-runtime/.jvm/target crypto/js/target test-runtime/.js/target project/target + run: tar cf targets.tar crypto/jvm/target target .js/target crypto/native/target .jvm/target .native/target test-runtime/.jvm/target crypto/js/target test-runtime/.js/target test-runtime/.native/target project/target - name: Upload target directories if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') @@ -272,6 +284,16 @@ jobs: tar xf targets.tar rm targets.tar + - name: Download target directories (3.1.3, NodeJS, rootNative) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-3.1.3-NodeJS-rootNative + + - name: Inflate target directories (3.1.3, NodeJS, rootNative) + run: | + tar xf targets.tar + rm targets.tar + - name: Download target directories (2.12.16, NodeJS, rootJS) uses: actions/download-artifact@v2 with: @@ -292,6 +314,16 @@ jobs: tar xf targets.tar rm targets.tar + - name: Download target directories (2.12.16, NodeJS, rootNative) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.16-NodeJS-rootNative + + - name: Inflate target directories (2.12.16, NodeJS, rootNative) + run: | + tar xf targets.tar + rm targets.tar + - name: Download target directories (2.13.8, NodeJS, rootJS) uses: actions/download-artifact@v2 with: @@ -312,6 +344,16 @@ jobs: tar xf targets.tar rm targets.tar + - name: Download target directories (2.13.8, NodeJS, rootNative) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.8-NodeJS-rootNative + + - name: Inflate target directories (2.13.8, NodeJS, rootNative) + run: | + tar xf targets.tar + rm targets.tar + - name: Import signing key if: env.PGP_SECRET != '' && env.PGP_PASSPHRASE == '' run: echo $PGP_SECRET | base64 -di | gpg --import From 910ba57bf6103605424cd2814629b80fdbfa55bc Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Sat, 10 Sep 2022 00:20:06 +0000 Subject: [PATCH 10/12] annoying unusedCompileDependenciesTest --- build.sbt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 07b18d1..1e8644a 100644 --- a/build.sbt +++ b/build.sbt @@ -103,7 +103,8 @@ lazy val crypto = crossProject(JSPlatform, JVMPlatform, NativePlatform) ) ) .nativeSettings( - tlVersionIntroduced := List("2.12", "2.13", "3").map(_ -> "0.2.4").toMap + tlVersionIntroduced := List("2.12", "2.13", "3").map(_ -> "0.2.4").toMap, + unusedCompileDependenciesTest := {} ) .dependsOn(testRuntime % Test) From 69df0619b6b3eb0fe4813594151e8a9dbe870fbd Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Sat, 10 Sep 2022 00:24:52 +0000 Subject: [PATCH 11/12] And another... --- build.sbt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 1e8644a..6b5f675 100644 --- a/build.sbt +++ b/build.sbt @@ -128,5 +128,6 @@ lazy val testRuntime = crossProject(JSPlatform, JVMPlatform, NativePlatform) .nativeSettings( buildInfoKeys := Seq( BuildInfoKey("runtime" -> "Native") - ) + ), + unusedCompileDependenciesTest := {} ) From ed971783376a8898cddf73efa7695b0c89bb226c Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Thu, 15 Sep 2022 22:59:32 +0000 Subject: [PATCH 12/12] Bumps --- build.sbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index 6b5f675..23d27bf 100644 --- a/build.sbt +++ b/build.sbt @@ -79,10 +79,10 @@ ThisBuild / Test / jsEnv := { } val catsVersion = "2.8.0" -val catsEffectVersion = "3.3.14-1-5d11fe9" +val catsEffectVersion = "3.3.14" val scodecBitsVersion = "1.1.34" val munitVersion = "1.0.0-M6" -val munitCEVersion = "2.0-5e03bfc" +val munitCEVersion = "2.0.0-M3" val disciplineMUnitVersion = "2.0.0-M3" lazy val root = tlCrossRootProject.aggregate(crypto, testRuntime)