Libdogecoin Signing API
Table of Contents
Abstract
This document describes the process of message signing within libdogecoin. It aims to meet the standards defined in BIP-137 although the implementation is only applicable to P2PKH addresses.
Basic Signing API
sign_message:
char* sign_message(char* privkey, char* msg) {
if (!privkey || !msg) return false;
uint256 message_bytes;
hash_message(msg, message_bytes);
size_t compact_signature_length = 65;
unsigned char* compact_signature = dogecoin_uchar_vla(compact_signature_length);
dogecoin_key key;
dogecoin_pubkey pubkey;
if (!init_keypair(privkey, &key, &pubkey)) return false;
int recid = -1;
if (!dogecoin_key_sign_hash_compact_recoverable_fcomp(&key, message_bytes, compact_signature, &compact_signature_length, &recid)) return false;
if (!dogecoin_key_recover_pubkey((const unsigned char*)compact_signature, message_bytes, recid, &pubkey)) return false;
char p2pkh_address[P2PKHLEN];
if (!dogecoin_pubkey_getaddr_p2pkh(&pubkey, &dogecoin_chainparams_main, p2pkh_address)) return false;
unsigned char* base64_encoded_output = dogecoin_uchar_vla(1+(sizeof(char)*base64_encoded_size(compact_signature_length)));
base64_encode((unsigned char*)compact_signature, compact_signature_length, base64_encoded_output);
dogecoin_free(compact_signature);
dogecoin_privkey_cleanse(&key);
dogecoin_pubkey_cleanse(&pubkey);
return (char*)base64_encoded_output;
}
This function signs a message with a private key.
C usage:
char* sig = sign_message("QUtnMFjt3JFk1NfeMe6Dj5u4p25DHZA54FsvEFAiQxcNP4bZkPu2", "This is just a test message");
verify_message:
int verify_message(char* sig, char* msg, char* address) {
if (!(sig || msg || address)) return false;
uint256 message_bytes;
hash_message(msg, message_bytes);
size_t encoded_length = strlen((const char*)sig);
unsigned char* decoded_signature = dogecoin_uchar_vla(base64_decoded_size(encoded_length+1)+1);
base64_decode((unsigned char*)sig, encoded_length, decoded_signature);
dogecoin_pubkey pub_key;
dogecoin_pubkey_init(&pub_key);
pub_key.compressed = false;
int header = decoded_signature[0] & 0xFF;
if (header < 27 || header > 42) return false;
if (header >= 31) {
pub_key.compressed = true;
header -= 4;
}
int recid = header - 27;
if (!dogecoin_key_recover_pubkey((const unsigned char*)decoded_signature, message_bytes, recid, &pub_key)) return false;
if (!dogecoin_pubkey_verify_sigcmp(&pub_key, message_bytes, decoded_signature)) return false;
char p2pkh_address[P2PKHLEN];
const dogecoin_chainparams* chain = chain_from_b58_prefix(address);
if (!dogecoin_pubkey_getaddr_p2pkh(&pub_key, chain, p2pkh_address)) return false;
dogecoin_free(decoded_signature);
dogecoin_pubkey_cleanse(&pub_key);
return strcmp(p2pkh_address, address)==0;
}
This function verifies a signed message using a P2PKH address.
C usage:
char* address = "DA8aeVkgQWwo78y3VCXtLqoWe8uWRoFuc1";
int ret = verify_message(sig, msg, address);
if (!ret) {
return false;
}