3
votes

I am facing an issue when I do the following :

  1. Created a Public Private key pair using python for ECDSA SECP256k1 curve and printed it on the terminal.
  2. Copy pasted the key pair in Python script and in visual studio (C coding that uses micro-ecc library). So that new key is not generated everytime I run the code.
  3. Sign a message ("Hello") in Python using the private key and print both the signature and message on the terminal. I know that the message has to be hashed first using a standard hashing algorithm such as SHA256, but in this case I am using the message directly for signing.
  4. Copy the signature and the same message (hash) into Visual studio.
  5. When I call the verify API in visual studio the verification fails all though it makes use of the same public key, message, signature and the curve.

Libraries I am using:

  1. micro-ecc for C in visual studio https://github.com/kmackay/micro-ecc
  2. ECDSA for python https://github.com/warner/python-ecdsa

Other things I have tested and ensured:

  1. Signing and verifying both in python works fine for a same key pair say (sk,vk).
  2. Signing and verifying both in visual studio works fine for a same key pair say (sk,vk).
  3. Signing using microECC in Visual Studio and verifying using ECDSA in python fails, also signing using ECDSA and verifying using microECC in fails.
  4. I am sure about the key Copy pasted from terminal is actually the intended key, because I have cross verified the verifying key from the copied signing Key and it is matching.

First I generate the keys by running this script

GenerateKeys.py

import ecdsa
from ecdsa import SigningKey, SECP256k1


sk  = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1) 
vk  = sk.get_verifying_key()

sklst = []
for e in bytearray(sk.to_string()):
    sklst.append(e)

vklst = []
for e in bytearray(vk.to_string()):
    vklst.append(e)

print("Private Key is:")
print(sklst)

print("Public Key is:")
print(vklst)

Output of GenerateKeys.py

Private Key is:
[38, 108, 90, 112, 230, 138, 62, 97, 107, 90, 227, 165, 207, 80, 251, 154, 17, 4, 73, 53, 33, 162, 33, 200, 243, 205, 116, 43, 36, 59, 201, 84]
Public Key is:
[163, 238, 83, 33, 229, 249, 105, 12, 141, 7, 214, 134, 148, 1, 198, 45, 13, 31, 9, 223, 85, 201, 98, 248, 73, 160, 40, 255, 64, 214, 250, 121, 234, 103, 212, 148, 197, 48, 210, 38, 166, 51, 30, 81, 119, 240, 125, 104, 237, 24, 3, 216, 229, 87, 45, 7, 115, 69, 94, 187, 236, 91, 142, 18]

Copy paste the Private key into the Sign.py python script and generate signature and a public key I have used "Hello" as the msg for creating signature

Sign.py

import ecdsa
from ecdsa import SigningKey, SECP256k1


signinKey_lst = [38, 108, 90, 112, 230, 138, 62, 97, 107, 90, 227, 165, 207, 80, 251, 154, 17, 4, 73, 53, 33, 162, 33, 200, 243, 205, 116, 43, 36, 59, 201, 84]
signinKey_lst = bytearray(signinKey_lst)
signinKey = ecdsa.SigningKey.from_string(signinKey_lst, curve=ecdsa.SECP256k1)
verifyKey = signinKey.get_verifying_key()

signinKey_lst = []
for e in bytearray(signinKey.to_string()):
    signinKey_lst.append(e)

verifyKey_lst = []
for e in bytearray(verifyKey.to_string()):
    verifyKey_lst.append(e)

print("Public Key is:")
print(verifyKey_lst)

msg = "Hello"

sign = signinKey.sign(msg)
sign_lst = []

verifyKey_lst = []
for e in bytearray(sign):
    sign_lst.append(e)

print("Signature is:")
print(sign_lst)

Output of Sign.py:

Private Key is:
[38, 108, 90, 112, 230, 138, 62, 97, 107, 90, 227, 165, 207, 80, 251, 154, 17, 4, 73, 53, 33, 162, 33, 200, 243, 205, 116, 43, 36, 59, 201, 84]
Public Key is:
[163, 238, 83, 33, 229, 249, 105, 12, 141, 7, 214, 134, 148, 1, 198, 45, 13, 31, 9, 223, 85, 201, 98, 248, 73, 160, 40, 255, 64, 214, 250, 121, 234, 103, 212, 148, 197, 48, 210, 38, 166, 51, 30, 81, 119, 240, 125, 104, 237, 24, 3, 216, 229, 87, 45, 7, 115, 69, 94, 187, 236, 91, 142, 18]
Signature is:
[47, 107, 101, 228, 187, 209, 97, 180, 83, 149, 133, 71, 62, 15, 86, 186, 192, 222, 108, 221, 249, 128, 124, 7, 139, 110, 103, 108, 62, 89, 136, 152, 226, 43, 104, 166, 92, 247, 9, 201, 135, 96, 19, 75, 55, 229, 67, 198, 188, 90, 246, 17, 157, 1, 229, 71, 151, 206, 211, 95, 41, 51, 96, 42]

Copy paste the Signature and use the same message in visual studio with micro ecc library:-

source.c

#include "stdio.h"
#include <stdlib.h>
#include <string.h>
#include "uECC.h"
#include "constants.h"

uint8_t privateKey[32] = { 0 };
uint8_t publicKey[64] = { 163, 238, 83, 33, 229, 249, 105, 12, 141, 7, 214, 134, 148, 1, 198, 45, 13, 31, 9, 223, 85, 201, 98, 248, 73, 160, 40, 255, 64, 214, 250, 121, 234, 103, 212, 148, 197, 48, 210, 38, 166, 51, 30, 81, 119, 240, 125, 104, 237, 24, 3, 216, 229, 87, 45, 7, 115, 69, 94, 187, 236, 91, 142, 18 };
uint8_t msg[5] = { 'H','e','l','l','o' };
uint8_t sign[64] = { 47, 107, 101, 228, 187, 209, 97, 180, 83, 149, 133, 71, 62, 15, 86, 186, 192, 222, 108, 221, 249, 128, 124, 7, 139, 110, 103, 108, 62, 89, 136, 152, 226, 43, 104, 166, 92, 247, 9, 201, 135, 96, 19, 75, 55, 229, 67, 198, 188, 90, 246, 17, 157, 1, 229, 71, 151, 206, 211, 95, 41, 51, 96, 42 };

void printArray(uint8_t* pToArr, uint32_t u16ArrSize)
{
    uint32_t c = 0;
    printf("[ ");
    for (c = 0; c < u16ArrSize; c++)
    {
        if (c != (u16ArrSize - 1))
        {
            printf(" %u,", *pToArr);
        }
        else
        {
            printf(" %u", *pToArr);
        }
        pToArr++;
    }
    printf(" ]");
    return;
}

int main()
{
    const struct uECC_Curve_t* curve;
    #if uECC_SUPPORTS_secp256k1
    curve = uECC_secp256k1();
    #endif

    const char* m = "Hello World"; //{0xff, 0xff, 0xff, 0xff, 0xff,0xff }

    printf("\n/*************************************************************************************************\n");
    printf("Validating the Encrypted hash with the public key and the hash used\n");

    printf("\n\nPublic Key:\n");
    printArray(publicKey, sizeof(publicKey));

    printf("\n\nMsg:\n");
    printArray(msg, sizeof(msg));

    printf("\n\nsignature:\n");
    printArray(sign, sizeof(sign));

    printf("\n");
    if (!uECC_verify(publicKey, msg, sizeof(msg), sign, curve))
    {
        printf("\nuECC_verify() failed\n");
    }
    else
    {
        printf("\nuECC_verify() succeeded\n");

    }
    printf("\n/*************************************************************************************************/\n");
    return 0;
}

Output of the visual studio by running source.c:-

/*************************************************************************************************
Validating the Encrypted hash with the public key and the hash used


Public Key:
[  148, 49, 144, 80, 185, 77, 185, 14, 186, 168, 164, 110, 123, 192, 55, 219, 184, 133, 153, 65, 144, 169, 175, 171, 203, 225, 88, 134, 51, 199, 254, 215, 237, 144, 141, 137, 80, 190, 25, 35, 33, 136, 248, 190, 114, 60, 128, 34, 155, 157, 83, 68, 187, 154, 137, 9, 51, 112, 155, 54, 88, 104, 82, 138 ]

Msg:
[  72, 101, 108, 108, 111 ]

signature:
[  186, 247, 43, 62, 152, 84, 40, 197, 74, 135, 80, 18, 152, 150, 121, 177, 155, 242, 1, 11, 171, 155, 45, 19, 174, 171, 190, 66, 31, 125, 214, 136, 41, 116, 139, 82, 71, 208, 4, 80, 47, 154, 100, 173, 110, 164, 25, 19, 7, 253, 175, 123, 34, 1, 99, 86, 241, 241, 211, 45, 15, 35, 210, 69 ]

uECC_verify() failed

/*************************************************************************************************/

C:\Users\prajwal.bv\source\repos\Crypt_sample1\x64\Debug\Crypt_sample1.exe (process 17160) exited with code 0.
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
Press any key to close this window . . .

I expected the output of running source.c to be uECC_verify() succeeded. But it prints uECC_verify() failed.

1

1 Answers

4
votes

The ECDSA signing procedure is a two-stage process:

  • a hash digest is calculated from the message
  • this digest is then signed.

Python ECDSA uses SHA-1 by default unless otherwise stated.

The SHA-1 digest for the message 'Hello' is hex encoded: f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0.

This means you need to use this digest when calling the uECC_verify function.

Validation

Replace in your .c code the msg array with the following line of code:

uint8_t msg[] = { 0xf7, 0xff, 0x9e, 0x8b, 0x7b, 0xb2, 0xe0, 0x9b, 0x70, 0x93, 0x5a, 0x5d, 0x78, 0x5e, 0x0c, 0xc5, 0xd9, 0xd0, 0xab, 0xf0};

Then the verfiy function succeeds.

Output

The output in the debug console looks like this:

uECC_verify output