python ECDSA和C micro-ecc库之间的ECDSA签名和验证问题 [英] ECDSA Signing and Verifying issue between python ECDSA and C micro-ecc library
问题描述
我在执行以下操作时遇到问题:
- 使用 Python 为 ECDSA SECP256k1 曲线创建了一个公私钥对并将其打印在终端上.
- 在 Python 脚本和 Visual Studio(使用 micro-ecc 库的 C 编码)中复制粘贴密钥对.这样每次运行代码时都不会生成新密钥.
- 使用私钥在 Python 中签署消息(Hello"),并在终端上打印签名和消息.我知道必须首先使用标准哈希算法(例如 SHA256)对消息进行哈希处理,但在这种情况下,我直接使用消息进行签名.
- 将签名和相同的消息(哈希)复制到 Visual Studio.
- 当我在 Visual Studio 中调用验证 API 时,虽然它使用相同的公钥、消息、签名和曲线,但验证全部失败.
我正在使用的库:
- Visual Studio 中用于 C 的 micro-ecc
I am facing an issue when I do the following :
- Created a Public Private key pair using python for ECDSA SECP256k1 curve and printed it on the terminal.
- 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.
- 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.
- Copy the signature and the same message (hash) into Visual studio.
- 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:
- micro-ecc for C in visual studio https://github.com/kmackay/micro-ecc
- ECDSA for python https://github.com/warner/python-ecdsa
Other things I have tested and ensured:
- Signing and verifying both in python works fine for a same key pair say (sk,vk).
- Signing and verifying both in visual studio works fine for a same key pair say (sk,vk).
- Signing using microECC in Visual Studio and verifying using ECDSA in python fails, also signing using ECDSA and verifying using microECC in fails.
- 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屋!