-module(kryptos@ec). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/kryptos/ec.gleam"). -export([coordinate_size/1, generate_key_pair/1, from_pem/1, from_der/1, to_pem/1, to_der/1, public_key_from_pem/1, public_key_from_der/1, public_key_from_raw_point/2, public_key_to_raw_point/1, public_key_to_pem/1, public_key_to_der/1, public_key_from_private_key/1]). -export_type([private_key/0, public_key/0, curve/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( " Elliptic Curve Cryptography key generation and management.\n" "\n" " This module provides key pair generation for elliptic curve cryptography,\n" " supporting standard NIST curves and secp256k1. EC keys can be used for\n" " both ECDSA signatures and ECDH key agreement.\n" "\n" " ## Key Generation\n" "\n" " ```gleam\n" " import kryptos/ec\n" "\n" " let #(private_key, public_key) = ec.generate_key_pair(ec.P256)\n" " ```\n" "\n" " ## Import/Export\n" "\n" " ```gleam\n" " import kryptos/ec\n" "\n" " let #(private_key, _public_key) = ec.generate_key_pair(ec.P256)\n" " let assert Ok(pem) = ec.to_pem(private_key)\n" " let assert Ok(#(imported_private, _)) = ec.from_pem(pem)\n" " ```\n" ). -type private_key() :: any(). -type public_key() :: any(). -type curve() :: p256 | p384 | p521 | secp256k1. -file("src/kryptos/ec.gleam", 49). ?DOC( " Returns the coordinate size in bytes for the given curve.\n" "\n" " This is the size of each coordinate (x or y) in an EC point.\n" ). -spec coordinate_size(curve()) -> integer(). coordinate_size(Curve) -> case Curve of p256 -> 32; secp256k1 -> 32; p384 -> 48; p521 -> 66 end. -file("src/kryptos/ec.gleam", 69). ?DOC( " Generates a new elliptic curve key pair.\n" "\n" " The private key should be kept secret and used for signing or ECDH key agreement.\n" " The public key can be shared and is used for signature verification or ECDH key agreement.\n" "\n" " ## Parameters\n" " - `curve`: The elliptic curve to use for key generation\n" "\n" " ## Returns\n" " A tuple of `#(private_key, public_key)`.\n" ). -spec generate_key_pair(curve()) -> {private_key(), public_key()}. generate_key_pair(Curve) -> kryptos_ffi:ec_generate_key_pair(Curve). -file("src/kryptos/ec.gleam", 82). ?DOC( " Imports an EC private key from PEM-encoded data.\n" "\n" " The key must be in PKCS#8 format.\n" "\n" " ## Parameters\n" " - `pem`: PEM-encoded key string\n" "\n" " ## Returns\n" " `Ok(#(private_key, public_key))` on success, `Error(Nil)` on failure.\n" ). -spec from_pem(binary()) -> {ok, {private_key(), public_key()}} | {error, nil}. from_pem(Pem) -> kryptos_ffi:ec_import_private_key_pem(Pem). -file("src/kryptos/ec.gleam", 95). ?DOC( " Imports an EC private key from DER-encoded data.\n" "\n" " The key must be in PKCS#8 format.\n" "\n" " ## Parameters\n" " - `der`: DER-encoded key data\n" "\n" " ## Returns\n" " `Ok(#(private_key, public_key))` on success, `Error(Nil)` on failure.\n" ). -spec from_der(bitstring()) -> {ok, {private_key(), public_key()}} | {error, nil}. from_der(Der) -> kryptos_ffi:ec_import_private_key_der(Der). -file("src/kryptos/ec.gleam", 106). ?DOC( " Exports an EC private key to PEM format.\n" "\n" " The key is exported in PKCS#8 format.\n" "\n" " ## Parameters\n" " - `key`: The private key to export\n" "\n" " ## Returns\n" " `Ok(pem_string)` on success, `Error(Nil)` on failure.\n" ). -spec to_pem(private_key()) -> {ok, binary()} | {error, nil}. to_pem(Key) -> _pipe = kryptos_ffi:ec_export_private_key_pem(Key), gleam@result:map( _pipe, fun(Pem) -> <<(gleam@string:trim_end(Pem))/binary, "\n"/utf8>> end ). -file("src/kryptos/ec.gleam", 125). ?DOC( " Exports an EC private key to DER format.\n" "\n" " The key is exported in PKCS#8 format.\n" "\n" " ## Parameters\n" " - `key`: The private key to export\n" "\n" " ## Returns\n" " `Ok(der_data)` on success, `Error(Nil)` on failure.\n" ). -spec to_der(private_key()) -> {ok, bitstring()} | {error, nil}. to_der(Key) -> kryptos_ffi:ec_export_private_key_der(Key). -file("src/kryptos/ec.gleam", 138). ?DOC( " Imports an EC public key from PEM-encoded data.\n" "\n" " The key must be in SPKI format.\n" "\n" " ## Parameters\n" " - `pem`: PEM-encoded key string\n" "\n" " ## Returns\n" " `Ok(public_key)` on success, `Error(Nil)` on failure.\n" ). -spec public_key_from_pem(binary()) -> {ok, public_key()} | {error, nil}. public_key_from_pem(Pem) -> kryptos_ffi:ec_import_public_key_pem(Pem). -file("src/kryptos/ec.gleam", 151). ?DOC( " Imports an EC public key from DER-encoded data.\n" "\n" " The key must be in SPKI format.\n" "\n" " ## Parameters\n" " - `der`: DER-encoded key data\n" "\n" " ## Returns\n" " `Ok(public_key)` on success, `Error(Nil)` on failure.\n" ). -spec public_key_from_der(bitstring()) -> {ok, public_key()} | {error, nil}. public_key_from_der(Der) -> kryptos_ffi:ec_import_public_key_der(Der). -file("src/kryptos/ec.gleam", 167). ?DOC( " Imports an EC public key from an uncompressed SEC1 point.\n" "\n" " The point must be in uncompressed format: `0x04 || x || y`\n" " where x and y are the coordinates padded to the curve's coordinate size.\n" "\n" " ## Parameters\n" " - `curve`: The elliptic curve (P256, P384, P521, or Secp256k1)\n" " - `point`: The uncompressed point bytes (1 + 2 * coordinate_size bytes)\n" "\n" " ## Returns\n" " `Ok(public_key)` on success, `Error(Nil)` if the format is invalid\n" " or the point is not on the curve.\n" ). -spec public_key_from_raw_point(curve(), bitstring()) -> {ok, public_key()} | {error, nil}. public_key_from_raw_point(Curve, Point) -> kryptos_ffi:ec_public_key_from_raw_point(Curve, Point). -file("src/kryptos/ec.gleam", 184). ?DOC( " Exports a public key to uncompressed SEC1 point format.\n" "\n" " Returns a BitArray in the format: `0x04 || X || Y` where X and Y are\n" " the coordinates of the public key point, each padded to the curve's\n" " coordinate size.\n" "\n" " If the key was imported with a compressed point format, it will be\n" " automatically decompressed.\n" "\n" " This is the inverse of `public_key_from_raw_point`.\n" ). -spec public_key_to_raw_point(public_key()) -> bitstring(). public_key_to_raw_point(Key) -> kryptos_ffi:ec_public_key_to_raw_point(Key). -file("src/kryptos/ec.gleam", 195). ?DOC( " Exports an EC public key to PEM format.\n" "\n" " The key is exported in SPKI format.\n" "\n" " ## Parameters\n" " - `key`: The public key to export\n" "\n" " ## Returns\n" " `Ok(pem_string)` on success, `Error(Nil)` on failure.\n" ). -spec public_key_to_pem(public_key()) -> {ok, binary()} | {error, nil}. public_key_to_pem(Key) -> _pipe = kryptos_ffi:ec_export_public_key_pem(Key), gleam@result:map( _pipe, fun(Pem) -> <<(gleam@string:trim_end(Pem))/binary, "\n"/utf8>> end ). -file("src/kryptos/ec.gleam", 215). ?DOC( " Exports an EC public key to DER format.\n" "\n" " The key is exported in SPKI format.\n" "\n" " ## Parameters\n" " - `key`: The public key to export\n" "\n" " ## Returns\n" " `Ok(der_data)` on success, `Error(Nil)` on failure.\n" ). -spec public_key_to_der(public_key()) -> {ok, bitstring()} | {error, nil}. public_key_to_der(Key) -> kryptos_ffi:ec_export_public_key_der(Key). -file("src/kryptos/ec.gleam", 226). ?DOC( " Derives the public key from an EC private key.\n" "\n" " ## Parameters\n" " - `key`: The private key\n" "\n" " ## Returns\n" " The corresponding public key.\n" ). -spec public_key_from_private_key(private_key()) -> public_key(). public_key_from_private_key(Key) -> kryptos_ffi:ec_public_key_from_private(Key).