Проблема ECDSA в подписи и проверке между библиотекой python ECDSA и C micro-ecc - PullRequest
3 голосов
/ 15 мая 2019

Я сталкиваюсь с проблемой, когда выполняю следующие действия:

  1. Создаю пару открытого частного ключа с использованием python для кривой ECDSA SECP256k1 и печатаю ее на терминале.
  2. Копия вставила пару ключей в скрипт Python и в Visual Studio (C-кодирование, использующее библиотеку micro-ecc).Так что новый ключ не генерируется каждый раз, когда я запускаю код.
  3. Подпишите сообщение («Hello») в Python с помощью закрытого ключа и напечатайте на терминале как подпись, так и сообщение.Я знаю, что сообщение должно быть сначала хэшировано с использованием стандартного алгоритма хеширования, такого как SHA256, но в этом случае я использую сообщение непосредственно для подписания.
  4. Скопируйте подпись и то же сообщение (хэш) в Visual Studio.
  5. Когда я вызываю API проверки в Visual Studio, проверка завершается неудачно, хотя она использует один и тот же открытый ключ, сообщение, подпись и кривая.

Библиотеки, которые я использую:

  1. микро-ecc для C в visual studio https://github.com/kmackay/micro-ecc
  2. ECDSAдля python https://github.com/warner/python-ecdsa

Другие вещи, которые я проверял и проверял:

  1. Подписание и проверка обоих в python отлично работает для одной и той же пары ключей (sk, vk),
  2. Подписание и проверка обоих в Visual Studio прекрасно работает для одной и той же пары ключей (sk, vk).
  3. Сбой подписи с помощью microECC в Visual Studio и проверки с использованием ECDSA в python, также подписи с использованиемECDSA и проверка с использованием microECC в случае сбоя.
  4. Я уверен, что ключ, скопированный с терминала, на самом деле является предполагаемым ключом, потому что я перепроверял проверочный ключ из скопированного подписывающего ключа, и он совпадает.

Сначала я сгенерирую ключи с помощью этого скрипта

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)

Вывод 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]

Копировать вставитьзакрытый ключ в сценарии Python Sign.py и генерировать подпись и открытый ключ. Я использовал «Hello» в качестве сообщения для создания подписи

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)

Вывод 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]

Скопируйте, вставьте подпись и используйте то же сообщение в visual studio с библиотекой micro ecc: -

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;
}

Выводвизуальная студияидущий 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 . . .

Я ожидал, что выходной файл source.c будет uECC_verify () успешным.Но он печатает uECC_verify () не удалось.

1 Ответ

2 голосов
/ 16 мая 2019

Процедура подписания ECDSA является двухэтапной:

  • хеш-дайджест вычисляется из сообщения
  • этот дайджест подписывается.

Python ECDSA использует SHA-1 по умолчанию, если не указано иное.

Дайджест SHA-1 для сообщения 'Hello' имеет шестнадцатеричное кодирование: f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0.

Это означает, что вам нужно использовать этот дайджест при вызове функции uECC_verify.

Валидация

Замените в своем коде .c массив msg следующей строкой кода:

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

Тогда функция verfiy завершается успешно.

выход

Вывод в консоли отладки выглядит следующим образом:

uECC_verify output

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...