|
import scala.scalanative.unsafe |
|
import scala.scalanative.unsafe._ |
|
|
|
object CryptoPlatformCompat { |
|
type Binary = Array[Byte] |
|
|
|
def binaryFromString(str: String): Binary = |
|
str.getBytes("UTF-8") |
|
|
|
def toHexString(binary: Binary): String = |
|
binary.map("%02x".format(_)).mkString |
|
|
|
def sha256HexDigest(message: String): String = |
|
unsafe.Zone { implicit z => |
|
val outLength: Ptr[CUnsignedInt] = unsafe.alloc[CUnsignedInt] |
|
val digest: Ptr[CUnsignedChar] = |
|
unsafe.alloc[CUnsignedChar](CryptoPlatformCompat.EVP_MAX_MD_SIZE) |
|
val dataLen = message.length.toLong |
|
val cInput: CString = toCString(message) |
|
|
|
val ctx = crypto.EVP_MD_CTX_new() |
|
crypto.EVP_DigestInit(ctx, crypto.EVP_sha256()) |
|
crypto.EVP_DigestUpdate(ctx, cInput, dataLen) |
|
crypto.EVP_DigestFinal(ctx, digest, outLength) |
|
|
|
val out = Array.fill[Byte]((!outLength).toInt)(0) |
|
for (i <- 0 until (!outLength).toInt) out(i) = digest(i.toLong).toByte |
|
out.map("%02x".format(_)).mkString |
|
} |
|
|
|
def hmacSha256(data: String, key: Binary): Binary = |
|
unsafe.Zone { implicit z => |
|
val outLength: Ptr[CUnsignedInt] = unsafe.alloc[CUnsignedInt] |
|
val digest: Ptr[CUnsignedChar] = |
|
unsafe.alloc[CUnsignedChar](CryptoPlatformCompat.EVP_MAX_MD_SIZE) |
|
|
|
val cKey = arrayToCString(key) |
|
val keylen = key.length.toLong |
|
|
|
val cData: CString = toCString(data) |
|
val datalen = data.length.toLong |
|
|
|
crypto.HMAC(crypto.EVP_sha256(), |
|
cKey, |
|
keylen, |
|
cData, |
|
datalen, |
|
digest, |
|
outLength) |
|
|
|
val out = Array.fill[Byte]((!outLength).toInt)(0) |
|
for (i <- 0 until (!outLength).toInt) out(i) = digest(i.toLong).toByte |
|
out |
|
} |
|
|
|
private def arrayToCString(bytes: Array[Byte])(implicit z: Zone): CString = { |
|
val cstr = z.alloc(bytes.length.toLong + 1) |
|
var c = 0 |
|
while (c < bytes.length) { |
|
!(cstr + c.toLong) = bytes(c) |
|
c += 1 |
|
} |
|
!(cstr + c.toLong) = 0.toByte |
|
cstr |
|
} |
|
|
|
val EVP_MAX_MD_SIZE = 64L |
|
} |