Obtaining ECDSA r and s values correctly
Closed this issue · 3 comments
talentlessguy commented
Hey, sorry for another noob question. I'm trying to sign a message and extract r and s values from it correctly but I'm failing with getting the values right.
Here's an identical code in TypeScript using viem:
const { address } = privateKeyToAccount(pk)
console.log(`Address: ${address}`)
const hash = hashMessage('Hello World')
const signature = await sign({ hash, privateKey: pk })
console.log(`\nSignature:\nr = ${signature.r}\ns = ${signature.s}`)
It produces the following output:
Address: 0x765E2DA311bB2CC31B6FCd868A25cD6E99FA15Ae
Signature:
r = 0xafc74bc20e99cf4596bd71568010f2e2af4d5ae47eb2fd8a1b81e77023de8713
s = 0x12b445d37912241b557612657cf39cc4da8f65b931d86c9ba41f3e1029fd7
Internally it does something similar to keccak256p by appending eth prefix
I'm trying to achieve the same result with libethc:
#include <stdio.h>
#include <stdlib.h>
#include <ethc/account.h>
#include <ethc/hex.h>
#include <string.h>
#include <ethc/keccak256.h>
int main() {
const char *hexstr = getenv("PK"); // 0x9ef...
uint8_t *privkey;
struct eth_account acc;
// Call the function with the correct parameters
eth_hex_to_bytes(&privkey, hexstr, strlen(hexstr));
eth_account_from_privkey(&acc, privkey);
char addr[40];
eth_account_address_get(&addr, &acc);
printf("Address: 0x%s", addr);
struct eth_signed signature;
char str[] = "Hello World"; // Example string
uint8_t result = (uint8_t)atoi(str);
// Compute keccak256 + prefix hash;
uint8_t keccak[32];
eth_keccak256p(keccak, &result, strlen(str));
eth_account_sign(&signature, &acc, keccak, 32);
printf("\n\nSignature: ");
printf("\nr = 0x");
char *r;
eth_hex_from_bytes(&r, signature.r, 32);
printf(r);
printf("\ns = 0x");
char *s;
eth_hex_from_bytes(&s, signature.s, 32);
printf(s);
}
But the output is different from viem's:
Address: 0x765e2da311bb2cc31b6fcd868a25cd6e99fa15ae
Signature:
r = 0x45161301e875d1389fcc738e944ce8310c8ce3ed51e0c2cc45a29ba9abe28eab
s = 0x0e28f678a3b4ec4d077011b8a8ceab7c115614aafc1bc1f800937d2ac92934c6
mhw0 commented
Hello @talentlessguy!
Try passing raw str
not the hash of it:
eth_account_sign(&signature, &acc, str, strlen(str));
mhw0 commented
Because eth_account_sign internally hashes the input with eth_keccak256p
talentlessguy commented
Okay it worked, thanks!
sorry once again for bothering 🙏