package expo.modules.crypto import android.util.Base64 import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition import expo.modules.kotlin.typedarray.TypedArray import java.security.MessageDigest import java.security.SecureRandom import java.util.UUID import kotlin.math.min class CryptoModule : Module() { private val secureRandom by lazy { SecureRandom() } override fun definition() = ModuleDefinition { Name("ExpoCrypto") Function("digestString", this@CryptoModule::digestString) AsyncFunction("digestStringAsync", this@CryptoModule::digestString) Function("getRandomValues", this@CryptoModule::getRandomValues) Function("digest", this@CryptoModule::digest) Function("randomUUID") { UUID.randomUUID().toString() } } private fun digestString(algorithm: DigestAlgorithm, data: String, options: DigestOptions): String { val messageDigest = MessageDigest.getInstance(algorithm.value).apply { update(data.toByteArray()) } val digest: ByteArray = messageDigest.digest() return when (options.encoding) { DigestOptions.Encoding.BASE64 -> { Base64.encodeToString(digest, Base64.NO_WRAP) } DigestOptions.Encoding.HEX -> { digest.joinToString(separator = "") { byte -> ((byte.toInt() and 0xff) + 0x100) .toString(radix = 16) .substring(startIndex = 1) } } } } private fun digest(algorithm: DigestAlgorithm, output: TypedArray, data: TypedArray) { val messageDigest = MessageDigest.getInstance(algorithm.value).apply { update(data.toDirectBuffer()) } val digest: ByteArray = messageDigest.digest() val outputLength = min(digest.size, output.byteLength) output.write(digest, 0, outputLength) } private fun getRandomValues(typedArray: TypedArray) { val array = ByteArray(typedArray.byteLength) secureRandom.nextBytes(array) typedArray.write(array, 0, typedArray.byteLength) } }