python ECDSA和C micro-ecc库之间的ECDSA签名和验证问题 [英] ECDSA Signing and Verifying issue between python ECDSA and C micro-ecc library

查看:85
本文介绍了python ECDSA和C micro-ecc库之间的ECDSA签名和验证问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在执行以下操作时遇到问题:

  1. 使用 Python 为 ECDSA SECP256k1 曲线创建了一个公私钥对并将其打印在终端上.
  2. 在 Python 脚本和 Visual Studio(使用 micro-ecc 库的 C 编码)中复制粘贴密钥对.这样每次运行代码时都不会生成新密钥.
  3. 使用私钥在 Python 中签署消息(Hello"),并在终端上打印签名和消息.我知道必须首先使用标准哈希算法(例如 SHA256)对消息进行哈希处理,但在这种情况下,我直接使用消息进行签名.
  4. 将签名和相同的消息(哈希)复制到 Visual Studio.
  5. 当我在 Visual Studio 中调用验证 API 时,虽然它使用相同的公钥、消息、签名和曲线,但验证全部失败.

我正在使用的库:

  1. Visual Studio 中用于 C 的 micro-ecc

    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.

    解决方案

    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:

    这篇关于python ECDSA和C micro-ecc库之间的ECDSA签名和验证问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆