Current section
Files
Jump to
Current section
Files
src/gose@jwa.erl
-module(gose@jwa).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gose/jwa.gleam").
-export([jws_alg_to_string/1, jws_alg_from_string/1, jwe_alg_to_string/1, jwe_alg_from_string/1, enc_to_string/1, enc_from_string/1, aes_key_size_in_bytes/1, hmac_alg_octet_key_size/1, enc_octet_key_size/1, chacha20_kw_nonce_size/1]).
-export_type([aes_key_size/0, aes_kw_mode/0, cha_cha20_kw/0, hmac_alg/0, rsa_pkcs1_alg/0, rsa_pss_alg/0, ecdsa_alg/0, jws_alg/0, rsa_jwe_alg/0, ecdh_es_alg/0, pbes2_alg/0, jwe_alg/0, enc/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" JSON Web Algorithms (JWA) - [RFC 7518](https://www.rfc-editor.org/rfc/rfc7518.html)\n"
"\n"
" This module defines the cryptographic algorithms used for signing (JWS)\n"
" and encryption (JWE) operations.\n"
).
-type aes_key_size() :: aes128 | aes192 | aes256.
-type aes_kw_mode() :: aes_kw | aes_gcm_kw.
-type cha_cha20_kw() :: c20_p_kw | x_c20_p_kw.
-type hmac_alg() :: hmac_sha256 | hmac_sha384 | hmac_sha512.
-type rsa_pkcs1_alg() :: rsa_pkcs1_sha256 | rsa_pkcs1_sha384 | rsa_pkcs1_sha512.
-type rsa_pss_alg() :: rsa_pss_sha256 | rsa_pss_sha384 | rsa_pss_sha512.
-type ecdsa_alg() :: ecdsa_p256 | ecdsa_p384 | ecdsa_p521 | ecdsa_secp256k1.
-type jws_alg() :: {jws_hmac, hmac_alg()} |
{jws_rsa_pkcs1, rsa_pkcs1_alg()} |
{jws_rsa_pss, rsa_pss_alg()} |
{jws_ecdsa, ecdsa_alg()} |
jws_eddsa.
-type rsa_jwe_alg() :: rsa_pkcs1v15 | rsa_oaep_sha1 | rsa_oaep_sha256.
-type ecdh_es_alg() :: ecdh_es_direct |
{ecdh_es_aes_kw, aes_key_size()} |
{ecdh_es_cha_cha20_kw, cha_cha20_kw()}.
-type pbes2_alg() :: pbes2_sha256_aes128_kw |
pbes2_sha384_aes192_kw |
pbes2_sha512_aes256_kw.
-type jwe_alg() :: jwe_direct |
{jwe_aes_key_wrap, aes_kw_mode(), aes_key_size()} |
{jwe_cha_cha20_key_wrap, cha_cha20_kw()} |
{jwe_rsa, rsa_jwe_alg()} |
{jwe_ecdh_es, ecdh_es_alg()} |
{jwe_pbes2, pbes2_alg()}.
-type enc() :: {aes_gcm, aes_key_size()} |
{aes_cbc_hmac, aes_key_size()} |
cha_cha20_poly1305 |
x_cha_cha20_poly1305.
-file("src/gose/jwa.gleam", 163).
?DOC(
" Convert a JWS algorithm to its RFC string representation.\n"
"\n"
" ## Parameters\n"
"\n"
" - `alg` - The JWS algorithm variant to convert.\n"
"\n"
" ## Returns\n"
"\n"
" The RFC 7518 string identifier (e.g. `\"HS256\"`, `\"EdDSA\"`).\n"
).
-spec jws_alg_to_string(jws_alg()) -> binary().
jws_alg_to_string(Alg) ->
case Alg of
{jws_hmac, hmac_sha256} ->
<<"HS256"/utf8>>;
{jws_hmac, hmac_sha384} ->
<<"HS384"/utf8>>;
{jws_hmac, hmac_sha512} ->
<<"HS512"/utf8>>;
{jws_rsa_pkcs1, rsa_pkcs1_sha256} ->
<<"RS256"/utf8>>;
{jws_rsa_pkcs1, rsa_pkcs1_sha384} ->
<<"RS384"/utf8>>;
{jws_rsa_pkcs1, rsa_pkcs1_sha512} ->
<<"RS512"/utf8>>;
{jws_rsa_pss, rsa_pss_sha256} ->
<<"PS256"/utf8>>;
{jws_rsa_pss, rsa_pss_sha384} ->
<<"PS384"/utf8>>;
{jws_rsa_pss, rsa_pss_sha512} ->
<<"PS512"/utf8>>;
{jws_ecdsa, ecdsa_p256} ->
<<"ES256"/utf8>>;
{jws_ecdsa, ecdsa_p384} ->
<<"ES384"/utf8>>;
{jws_ecdsa, ecdsa_p521} ->
<<"ES512"/utf8>>;
{jws_ecdsa, ecdsa_secp256k1} ->
<<"ES256K"/utf8>>;
jws_eddsa ->
<<"EdDSA"/utf8>>
end.
-file("src/gose/jwa.gleam", 192).
?DOC(
" Parse a JWS algorithm from its RFC string representation.\n"
"\n"
" ## Parameters\n"
"\n"
" - `alg` - The RFC 7518 string identifier (e.g. `\"HS256\"`, `\"EdDSA\"`).\n"
"\n"
" ## Returns\n"
"\n"
" `Ok(JwsAlg)` with the parsed algorithm variant, or `Error(ParseError)`\n"
" if the string is not a recognized JWS algorithm.\n"
).
-spec jws_alg_from_string(binary()) -> {ok, jws_alg()} |
{error, gose:gose_error()}.
jws_alg_from_string(Alg) ->
case Alg of
<<"HS256"/utf8>> ->
{ok, {jws_hmac, hmac_sha256}};
<<"HS384"/utf8>> ->
{ok, {jws_hmac, hmac_sha384}};
<<"HS512"/utf8>> ->
{ok, {jws_hmac, hmac_sha512}};
<<"RS256"/utf8>> ->
{ok, {jws_rsa_pkcs1, rsa_pkcs1_sha256}};
<<"RS384"/utf8>> ->
{ok, {jws_rsa_pkcs1, rsa_pkcs1_sha384}};
<<"RS512"/utf8>> ->
{ok, {jws_rsa_pkcs1, rsa_pkcs1_sha512}};
<<"PS256"/utf8>> ->
{ok, {jws_rsa_pss, rsa_pss_sha256}};
<<"PS384"/utf8>> ->
{ok, {jws_rsa_pss, rsa_pss_sha384}};
<<"PS512"/utf8>> ->
{ok, {jws_rsa_pss, rsa_pss_sha512}};
<<"ES256"/utf8>> ->
{ok, {jws_ecdsa, ecdsa_p256}};
<<"ES384"/utf8>> ->
{ok, {jws_ecdsa, ecdsa_p384}};
<<"ES512"/utf8>> ->
{ok, {jws_ecdsa, ecdsa_p521}};
<<"ES256K"/utf8>> ->
{ok, {jws_ecdsa, ecdsa_secp256k1}};
<<"EdDSA"/utf8>> ->
{ok, jws_eddsa};
_ ->
{error,
{parse_error, <<"unknown JWS algorithm: "/utf8, Alg/binary>>}}
end.
-file("src/gose/jwa.gleam", 221).
?DOC(
" Convert a JWE key encryption algorithm to its RFC string representation.\n"
"\n"
" ## Parameters\n"
"\n"
" - `alg` - The JWE key encryption algorithm variant to convert.\n"
"\n"
" ## Returns\n"
"\n"
" The RFC 7518 string identifier (e.g. `\"dir\"`, `\"RSA-OAEP-256\"`).\n"
).
-spec jwe_alg_to_string(jwe_alg()) -> binary().
jwe_alg_to_string(Alg) ->
case Alg of
jwe_direct ->
<<"dir"/utf8>>;
{jwe_aes_key_wrap, aes_kw, aes128} ->
<<"A128KW"/utf8>>;
{jwe_aes_key_wrap, aes_kw, aes192} ->
<<"A192KW"/utf8>>;
{jwe_aes_key_wrap, aes_kw, aes256} ->
<<"A256KW"/utf8>>;
{jwe_aes_key_wrap, aes_gcm_kw, aes128} ->
<<"A128GCMKW"/utf8>>;
{jwe_aes_key_wrap, aes_gcm_kw, aes192} ->
<<"A192GCMKW"/utf8>>;
{jwe_aes_key_wrap, aes_gcm_kw, aes256} ->
<<"A256GCMKW"/utf8>>;
{jwe_rsa, rsa_pkcs1v15} ->
<<"RSA1_5"/utf8>>;
{jwe_rsa, rsa_oaep_sha1} ->
<<"RSA-OAEP"/utf8>>;
{jwe_rsa, rsa_oaep_sha256} ->
<<"RSA-OAEP-256"/utf8>>;
{jwe_ecdh_es, ecdh_es_direct} ->
<<"ECDH-ES"/utf8>>;
{jwe_ecdh_es, {ecdh_es_aes_kw, aes128}} ->
<<"ECDH-ES+A128KW"/utf8>>;
{jwe_ecdh_es, {ecdh_es_aes_kw, aes192}} ->
<<"ECDH-ES+A192KW"/utf8>>;
{jwe_ecdh_es, {ecdh_es_aes_kw, aes256}} ->
<<"ECDH-ES+A256KW"/utf8>>;
{jwe_ecdh_es, {ecdh_es_cha_cha20_kw, c20_p_kw}} ->
<<"ECDH-ES+C20PKW"/utf8>>;
{jwe_ecdh_es, {ecdh_es_cha_cha20_kw, x_c20_p_kw}} ->
<<"ECDH-ES+XC20PKW"/utf8>>;
{jwe_cha_cha20_key_wrap, c20_p_kw} ->
<<"C20PKW"/utf8>>;
{jwe_cha_cha20_key_wrap, x_c20_p_kw} ->
<<"XC20PKW"/utf8>>;
{jwe_pbes2, pbes2_sha256_aes128_kw} ->
<<"PBES2-HS256+A128KW"/utf8>>;
{jwe_pbes2, pbes2_sha384_aes192_kw} ->
<<"PBES2-HS384+A192KW"/utf8>>;
{jwe_pbes2, pbes2_sha512_aes256_kw} ->
<<"PBES2-HS512+A256KW"/utf8>>
end.
-file("src/gose/jwa.gleam", 257).
?DOC(
" Parse a JWE key encryption algorithm from its RFC string representation.\n"
"\n"
" ## Parameters\n"
"\n"
" - `alg` - The RFC 7518 string identifier (e.g. `\"dir\"`, `\"RSA-OAEP\"`).\n"
"\n"
" ## Returns\n"
"\n"
" `Ok(JweAlg)` with the parsed algorithm variant, or `Error(ParseError)`\n"
" if the string is not a recognized JWE algorithm.\n"
).
-spec jwe_alg_from_string(binary()) -> {ok, jwe_alg()} |
{error, gose:gose_error()}.
jwe_alg_from_string(Alg) ->
case Alg of
<<"dir"/utf8>> ->
{ok, jwe_direct};
<<"A128KW"/utf8>> ->
{ok, {jwe_aes_key_wrap, aes_kw, aes128}};
<<"A192KW"/utf8>> ->
{ok, {jwe_aes_key_wrap, aes_kw, aes192}};
<<"A256KW"/utf8>> ->
{ok, {jwe_aes_key_wrap, aes_kw, aes256}};
<<"A128GCMKW"/utf8>> ->
{ok, {jwe_aes_key_wrap, aes_gcm_kw, aes128}};
<<"A192GCMKW"/utf8>> ->
{ok, {jwe_aes_key_wrap, aes_gcm_kw, aes192}};
<<"A256GCMKW"/utf8>> ->
{ok, {jwe_aes_key_wrap, aes_gcm_kw, aes256}};
<<"RSA1_5"/utf8>> ->
{ok, {jwe_rsa, rsa_pkcs1v15}};
<<"RSA-OAEP"/utf8>> ->
{ok, {jwe_rsa, rsa_oaep_sha1}};
<<"RSA-OAEP-256"/utf8>> ->
{ok, {jwe_rsa, rsa_oaep_sha256}};
<<"ECDH-ES"/utf8>> ->
{ok, {jwe_ecdh_es, ecdh_es_direct}};
<<"ECDH-ES+A128KW"/utf8>> ->
{ok, {jwe_ecdh_es, {ecdh_es_aes_kw, aes128}}};
<<"ECDH-ES+A192KW"/utf8>> ->
{ok, {jwe_ecdh_es, {ecdh_es_aes_kw, aes192}}};
<<"ECDH-ES+A256KW"/utf8>> ->
{ok, {jwe_ecdh_es, {ecdh_es_aes_kw, aes256}}};
<<"ECDH-ES+C20PKW"/utf8>> ->
{ok, {jwe_ecdh_es, {ecdh_es_cha_cha20_kw, c20_p_kw}}};
<<"ECDH-ES+XC20PKW"/utf8>> ->
{ok, {jwe_ecdh_es, {ecdh_es_cha_cha20_kw, x_c20_p_kw}}};
<<"C20PKW"/utf8>> ->
{ok, {jwe_cha_cha20_key_wrap, c20_p_kw}};
<<"XC20PKW"/utf8>> ->
{ok, {jwe_cha_cha20_key_wrap, x_c20_p_kw}};
<<"PBES2-HS256+A128KW"/utf8>> ->
{ok, {jwe_pbes2, pbes2_sha256_aes128_kw}};
<<"PBES2-HS384+A192KW"/utf8>> ->
{ok, {jwe_pbes2, pbes2_sha384_aes192_kw}};
<<"PBES2-HS512+A256KW"/utf8>> ->
{ok, {jwe_pbes2, pbes2_sha512_aes256_kw}};
_ ->
{error,
{parse_error, <<"unknown JWE algorithm: "/utf8, Alg/binary>>}}
end.
-file("src/gose/jwa.gleam", 293).
?DOC(
" Convert a content encryption algorithm to its RFC string representation.\n"
"\n"
" ## Parameters\n"
"\n"
" - `alg` - The content encryption algorithm variant to convert.\n"
"\n"
" ## Returns\n"
"\n"
" The RFC 7518 string identifier (e.g. `\"A256GCM\"`, `\"C20P\"`).\n"
).
-spec enc_to_string(enc()) -> binary().
enc_to_string(Alg) ->
case Alg of
{aes_gcm, aes128} ->
<<"A128GCM"/utf8>>;
{aes_gcm, aes192} ->
<<"A192GCM"/utf8>>;
{aes_gcm, aes256} ->
<<"A256GCM"/utf8>>;
{aes_cbc_hmac, aes128} ->
<<"A128CBC-HS256"/utf8>>;
{aes_cbc_hmac, aes192} ->
<<"A192CBC-HS384"/utf8>>;
{aes_cbc_hmac, aes256} ->
<<"A256CBC-HS512"/utf8>>;
cha_cha20_poly1305 ->
<<"C20P"/utf8>>;
x_cha_cha20_poly1305 ->
<<"XC20P"/utf8>>
end.
-file("src/gose/jwa.gleam", 316).
?DOC(
" Parse a content encryption algorithm from its RFC string representation.\n"
"\n"
" ## Parameters\n"
"\n"
" - `alg` - The RFC 7518 string identifier (e.g. `\"A256GCM\"`, `\"C20P\"`).\n"
"\n"
" ## Returns\n"
"\n"
" `Ok(Enc)` with the parsed encryption algorithm variant, or\n"
" `Error(ParseError)` if the string is not a recognized encryption algorithm.\n"
).
-spec enc_from_string(binary()) -> {ok, enc()} | {error, gose:gose_error()}.
enc_from_string(Alg) ->
case Alg of
<<"A128GCM"/utf8>> ->
{ok, {aes_gcm, aes128}};
<<"A192GCM"/utf8>> ->
{ok, {aes_gcm, aes192}};
<<"A256GCM"/utf8>> ->
{ok, {aes_gcm, aes256}};
<<"A128CBC-HS256"/utf8>> ->
{ok, {aes_cbc_hmac, aes128}};
<<"A192CBC-HS384"/utf8>> ->
{ok, {aes_cbc_hmac, aes192}};
<<"A256CBC-HS512"/utf8>> ->
{ok, {aes_cbc_hmac, aes256}};
<<"C20P"/utf8>> ->
{ok, cha_cha20_poly1305};
<<"XC20P"/utf8>> ->
{ok, x_cha_cha20_poly1305};
_ ->
{error,
{parse_error,
<<"unknown content encryption algorithm: "/utf8,
Alg/binary>>}}
end.
-file("src/gose/jwa.gleam", 339).
?DOC(
" Returns the key size in bytes for an AES key size variant.\n"
"\n"
" ## Parameters\n"
"\n"
" - `size` - The AES key size variant to query.\n"
"\n"
" ## Returns\n"
"\n"
" The key size in bytes (16, 24, or 32).\n"
).
-spec aes_key_size_in_bytes(aes_key_size()) -> integer().
aes_key_size_in_bytes(Size) ->
case Size of
aes128 ->
16;
aes192 ->
24;
aes256 ->
32
end.
-file("src/gose/jwa.gleam", 356).
?DOC(
" Returns the recommended symmetric key size in bytes for an HMAC algorithm.\n"
"\n"
" ## Parameters\n"
"\n"
" - `alg` - The HMAC algorithm variant to query.\n"
"\n"
" ## Returns\n"
"\n"
" The key size in bytes (32, 48, or 64).\n"
).
-spec hmac_alg_octet_key_size(hmac_alg()) -> integer().
hmac_alg_octet_key_size(Alg) ->
case Alg of
hmac_sha256 ->
32;
hmac_sha384 ->
48;
hmac_sha512 ->
64
end.
-file("src/gose/jwa.gleam", 376).
?DOC(
" Returns the content encryption key (CEK) size in bytes for a content\n"
" encryption algorithm.\n"
"\n"
" ## Parameters\n"
"\n"
" - `enc` - The content encryption algorithm to query.\n"
"\n"
" ## Returns\n"
"\n"
" The key size in bytes. Every `Enc` variant has a defined key size.\n"
" For `AesCbcHmac`, the CEK is double the AES key size because\n"
" it is split into separate HMAC and AES-CBC keys.\n"
).
-spec enc_octet_key_size(enc()) -> integer().
enc_octet_key_size(Enc) ->
case Enc of
{aes_gcm, Size} ->
aes_key_size_in_bytes(Size);
{aes_cbc_hmac, Size@1} ->
aes_key_size_in_bytes(Size@1) * 2;
cha_cha20_poly1305 ->
32;
x_cha_cha20_poly1305 ->
32
end.
-file("src/gose/jwa.gleam", 394).
?DOC(
" Returns the nonce size in bytes for a ChaCha20 key wrapping variant.\n"
"\n"
" ## Parameters\n"
"\n"
" - `variant` - The ChaCha20 key wrapping variant (`C20PKw` or `XC20PKw`).\n"
"\n"
" ## Returns\n"
"\n"
" The nonce size in bytes (12 for C20PKW, 24 for XC20PKW).\n"
).
-spec chacha20_kw_nonce_size(cha_cha20_kw()) -> integer().
chacha20_kw_nonce_size(Variant) ->
case Variant of
c20_p_kw ->
12;
x_c20_p_kw ->
24
end.