ecrecover/c_src/ecrecover.c
2023-01-12 14:52:32 +01:00

102 lines
2.4 KiB
C

#include "erl_nif.h"
#include "secp256k1_recovery.h"
static secp256k1_context *ctx = NULL;
static ERL_NIF_TERM error_result(ErlNifEnv* env, char* error_msg)
{
return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, error_msg, ERL_NIF_LATIN1));
}
static ERL_NIF_TERM ok_result(ErlNifEnv* env, ERL_NIF_TERM *r)
{
return enif_make_tuple2(env, enif_make_atom(env, "ok"), *r);
}
static ERL_NIF_TERM
recover(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM r;
ErlNifBinary message, csignature;
int result;
int compressed = SECP256K1_EC_UNCOMPRESSED;
size_t pubkeylen = 65;
int recid;
unsigned char* finished_recpubkey_buf;
secp256k1_ecdsa_recoverable_signature signature;
secp256k1_pubkey recpubkey;
if (!enif_inspect_binary(env, argv[0], &message)) {
return enif_make_badarg(env);
}
if (!enif_inspect_binary(env, argv[1], &csignature)) {
return enif_make_badarg(env);
}
if (!enif_get_int(env, argv[2], &recid)) {
return error_result(env, "Recovery id invalid 0-3");
}
if (recid < 0 || recid > 3) {
error_result(env, "Recovery id invalid 0-3x");
}
printf("xx1\r\n");
result = secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &signature, csignature.data, recid);
printf("xx2\r\n");
if (!result) {
return error_result(env, "ecdsa_signature_parse_compact returned 0");
}
// Now do ECDSA recovery
result = secp256k1_ecdsa_recover(ctx, &recpubkey, &signature, message.data);
if (!result) {
return error_result(env, "ecdsa recovery problem");
}
// Now serialize recpubkey based on the compression flag
finished_recpubkey_buf = enif_make_new_binary(env, pubkeylen, &r);
printf("pubker[0] = %d\r\n", recpubkey.data[0]);
result = secp256k1_ec_pubkey_serialize(ctx, finished_recpubkey_buf,
&pubkeylen, &recpubkey, compressed);
if (!result) {
return error_result(env, "ecdsa pubkey serialize error");
}
return ok_result(env, &r);
}
static int
load(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info)
{
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
return 0;
}
static int
upgrade(ErlNifEnv* env, void** priv, void** old_priv, ERL_NIF_TERM load_info)
{
return 0;
}
static void
unload(ErlNifEnv* env, void* priv)
{
secp256k1_context_destroy(ctx);
return;
}
static ErlNifFunc nif_funcs[] =
{
{"recover", 3, recover}
};
ERL_NIF_INIT(ecrecover, nif_funcs, &load, NULL, NULL, &unload);