% SPDX-FileCopyrightText: 2025 Emerald % % SPDX-License-Identifier: GPL-3.0-or-later -module(public_key_ffi). -export([generate_key_pair/0, decode_public_key/1, decode_private_key/1, encode_public_key/1, encode_private_key/1, do_sign/2, do_verify/3 ]). -include_lib("public_key/include/public_key.hrl"). encode_public_key(Ent) -> Entry = public_key:pem_entry_encode('RSAPublicKey', Ent), public_key:pem_encode([Entry]). encode_private_key(Ent) -> Entry = public_key:pem_entry_encode('RSAPrivateKey', Ent), public_key:pem_encode([Entry]). decode_public_key(Pem) -> case do_decode_pem(Pem) of {ok, Key} -> case Key of Key = #'RSAPublicKey'{ } -> {ok, Key}; _Other -> {error, expected_public_key} end; Other -> Other end. decode_private_key(Pem) -> case do_decode_pem(Pem) of {ok, Key} -> case Key of Key = #'RSAPrivateKey'{ } -> {ok, Key}; _Other -> {error, expected_private_key} end; Other -> Other end. do_decode_pem(Pem) -> [PemEntry] = public_key:pem_decode(Pem), case public_key:pem_entry_decode(PemEntry) of Key = #'RSAPublicKey'{ } -> {ok, Key}; Key = #'RSAPrivateKey'{ } -> {ok, Key}; _ -> {error, unexpected_key_format} end. do_sign(Message, Key) -> try {ok, public_key:sign(Message, sha256, Key)} catch _:Reason:_ -> {error, {runtime_error, Reason }} end. do_verify(Message, Signature, Key) -> try {ok, public_key:verify(Message, sha256, Signature, Key)} catch _:Reason:_ -> {error, {runtime_error, Reason}} end. generate_key_pair() -> case public_key:generate_key({rsa, 2048, 65537}) of PrivateKey = #'RSAPrivateKey'{ } -> PublicKey = #'RSAPublicKey'{ modulus = PrivateKey#'RSAPrivateKey'.modulus, publicExponent = PrivateKey#'RSAPrivateKey'.publicExponent }, {ok, {PublicKey, PrivateKey}}; _ -> {error, unexpected_key_format} end.