Packages
plinth
0.7.1
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.0
0.2.0
0.1.13
0.1.12
0.1.11
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Bindings to Node.js and browser platform APIs
Current section
Files
Jump to
Current section
Files
src/plinth/browser/crypto/subtle.gleam
import gleam/javascript/array.{type Array}
import gleam/javascript/promise.{type Promise}
import gleam/json.{type Json}
import gleam/list
pub type DigestAlgorithm {
SHA1
SHA256
SHA384
SHA512
}
pub fn digest_algorithm_to_string(algorithm) {
case algorithm {
SHA1 -> "SHA-1"
SHA256 -> "SHA-256"
SHA384 -> "SHA-384"
SHA512 -> "SHA-512"
}
}
@external(javascript, "../../../plinth_browser_crypto_subtle_ffi.mjs", "digest")
fn do_digest(
algorithm: String,
data: BitArray,
) -> Promise(Result(BitArray, String))
pub fn digest(algorithm, data) {
do_digest(digest_algorithm_to_string(algorithm), data)
}
pub type CryptoKey
/// export Jwk is separate because it returns JSON, other formats return array buffer
@external(javascript, "../../../plinth_browser_crypto_subtle_ffi.mjs", "exportJwk")
pub fn export_jwk(key: CryptoKey) -> Promise(Result(Json, String))
@external(javascript, "../../../plinth_browser_crypto_subtle_ffi.mjs", "generateKey")
fn do_generate_key(
algorithm: Json,
extractable: Bool,
key_usages: Array(String),
) -> Promise(Result(#(CryptoKey, CryptoKey), String))
pub fn generate_key(algorithm, extractable, key_usages) {
let algorithm = public_key_algorithm_to_json(algorithm)
let key_usages =
key_usages
|> list.map(key_usage_to_string)
|> array.from_list
do_generate_key(algorithm, extractable, key_usages)
}
pub type PublicKeyAlgorithm {
EcKeyGenParams(name: String, named_curve: String)
}
fn public_key_algorithm_to_json(key_algorithm) {
case key_algorithm {
EcKeyGenParams(name:, named_curve:) ->
json.object([
#("name", json.string(name)),
#("namedCurve", json.string(named_curve)),
])
}
}
pub type KeyUsage {
Encrypt
Decrypt
Sign
Verify
DeriveKey
DeriveBits
WrapKey
UnwrapKey
}
fn key_usage_to_string(key_usage) {
case key_usage {
Encrypt -> "encrypt"
Decrypt -> "decrypt"
Sign -> "sign"
Verify -> "verify"
DeriveKey -> "deriveKey"
DeriveBits -> "deriveBits"
WrapKey -> "wrapKey"
UnwrapKey -> "unwrapKey"
}
}
@external(javascript, "../../../plinth_browser_crypto_subtle_ffi.mjs", "importKey")
fn do_import_key(
format: String,
key_data: BitArray,
algorithm: Json,
extractable: Bool,
key_usages: Array(String),
) -> Promise(Result(CryptoKey, String))
pub fn import_key(format, key_data, algorithm, extractable, key_usages) {
let algorithm = import_algorithm_to_json(algorithm)
let key_usages =
key_usages
|> list.map(key_usage_to_string)
|> array.from_list
do_import_key(format, key_data, algorithm, extractable, key_usages)
}
@external(javascript, "../../../plinth_browser_crypto_subtle_ffi.mjs", "importJwk")
fn do_import_jwk(
key_data: Json,
algorithm: Json,
extractable: Bool,
key_usages: Array(String),
) -> Promise(Result(CryptoKey, String))
pub fn import_jwk(key_data, algorithm, extractable, key_usages) {
let algorithm = import_algorithm_to_json(algorithm)
let key_usages =
key_usages
|> list.map(key_usage_to_string)
|> array.from_list
do_import_jwk(key_data, algorithm, extractable, key_usages)
}
pub type ImportAlgorithm {
RsaHashedImportParams(name: String, hash: DigestAlgorithm)
EcKeyImportParams(name: String, named_curve: NamedCurve)
HmacImportParams(hash: DigestAlgorithm)
OtherImportParams(name: String)
}
fn import_algorithm_to_json(algorithm_parameters) {
case algorithm_parameters {
RsaHashedImportParams(name, hash) ->
json.object([
#("name", json.string(name)),
#("hash", json.string(digest_algorithm_to_string(hash))),
])
EcKeyImportParams(name, named_curve) ->
json.object([
#("name", json.string(name)),
#("namedCurve", json.string(named_curve_to_string(named_curve))),
])
HmacImportParams(hash) ->
json.object([
#("name", json.string("HMAC")),
#("hash", json.string(digest_algorithm_to_string(hash))),
])
OtherImportParams(name) -> json.object([#("name", json.string(name))])
}
}
pub type NamedCurve {
P256
P384
P521
}
fn named_curve_to_string(named_curve) {
case named_curve {
P256 -> "P-256"
P384 -> "P-384"
P521 -> "P-521"
}
}
@external(javascript, "../../../plinth_browser_crypto_subtle_ffi.mjs", "sign")
fn do_sign(
algorithm: Json,
key: CryptoKey,
data: BitArray,
) -> Promise(Result(BitArray, String))
pub fn sign(algorithm, key, data) {
let algorithm = sign_algorithm_to_json(algorithm)
do_sign(algorithm, key, data)
}
pub type SignAlgorithm {
RsaSsaPkcs1v15
RsaPssParams(salt_length: Int)
EcdsaParams(hash: DigestAlgorithm)
Hmac
Ed25519
}
fn sign_algorithm_to_json(key_algorithm) {
case key_algorithm {
RsaSsaPkcs1v15 -> json.object([#("name", json.string("RSASSA-PKCS1-v1_5"))])
RsaPssParams(salt_length) ->
json.object([
#("name", json.string("RSA-PSS")),
#("saltLength", json.int(salt_length)),
])
EcdsaParams(hash) ->
json.object([
#("name", json.string("ECDSA")),
#("hash", json.string(digest_algorithm_to_string(hash))),
])
Hmac -> json.object([#("name", json.string("HMAC"))])
Ed25519 -> json.object([#("name", json.string("Ed25519"))])
}
}
@external(javascript, "../../../plinth_browser_crypto_subtle_ffi.mjs", "verify")
fn do_verify(
algorithm: Json,
key: CryptoKey,
signature: BitArray,
data: BitArray,
) -> Promise(Result(Bool, String))
pub fn verify(algorithm, key, signature, data) {
let algorithm = sign_algorithm_to_json(algorithm)
do_verify(algorithm, key, signature, data)
}