Подписание ECDSA с закрытым ключом с кривой secp224k1 - PullRequest
2 голосов
/ 17 октября 2019

Я хочу получить знак ECDSA secp224k1. Я не могу получить ту же подпись, что и в примере CoinFLEX Authentication Process из руководства. Я использую C # BouncyCastle.

Почему я не могу получить подпись страницы руководства своим кодом?

// manual page's step 7
byte[] fortyByteMessage  = fromHexStringToByteArr("0x00000000 00000001").Concat(fromHexStringToByteArr("0x6b347302 2e6b9b5a f2fe5d1d ae7cf5bf")).Concat(fromHexStringToByteArr("0xf08c98ca f1fd82e8 cea9825d bff04fd0")).ToArray();

// manual page's step 9
byte[] privateKey = fromHexStringToByteArr("0xb89ea7fc d22cc059 c2673dc2 4ff40b97 83074646 86560d0a d7561b83");

// manual page's step 10
X9ECParameters spec = ECNamedCurveTable.GetByName("secp224k1");
ECDomainParameters domain = new ECDomainParameters(spec.Curve, spec.G, spec.N);
ECDsaSigner signer = new ECDsaSigner(new HMacDsaKCalculator(new Sha224Digest()));
signer.Init(true, new ECPrivateKeyParameters(new BigInteger(privateKey), domain));
BigInteger[] signature = signer.GenerateSignature(fortyByteMessage);
byte[] r = signature[0].ToByteArray().SkipWhile(b => b == 0x00).Reverse().ToArray(); // (r) r should be 0x3fb77a9d 7b5b2a68 209e76f6 872078c5 791340d5 989854ad a3ab735e, but not.

Console.WriteLine(BitConverter.ToString(r).Replace("-", string.Empty).ToLower());

Ожидаемый byteArr (значение шага 10 r):

r = 0x3fb77a9d 7b5b2a68 209e76f6 872078c5 791340d5 989854ad a3ab735e<br>

My byteArr (это неверное значение, потому что оно отличается от значения шага 10 r)

r = 0x1e3b3f4f 7401ff9d 827b7222 47823919 452d3adb effa7aa4 52a0879e<br>

Другая функция:

static byte[] fromHexStringToByteArr(string paramHexString)
{
    string hexString = paramHexString.Substring(2).Replace(" ", "");
    byte[] result = new byte[hexString.Length / 2];

    int cur = 0;

    for (int i = 0; i < hexString.Length; i = i + 2)
    {
        string w = hexString.Substring(i, 2);
        result[cur] = Convert.ToByte(w, 16);
        cur++;
    }
    return result;
}

1 Ответ

1 голос
/ 17 октября 2019
  • В соответствии с шагом 10 инструкций следует подписать не 40-байтовое сообщение, а хэш SHA224 этого сообщения: Клиент подписывает28-байтовый дайджест SHA-224 40-байтового сообщения ... . Обратите внимание, что данные не автоматически хешируются с помощью GenerateSignature -метода, то есть они должны хешироваться явно , см. Также здесь и эти примеры .

  • Метод Org.BouncyCastle.Math.BigInteger.ToByteArray (который используется в C # -коде) выводит байтовый массив в формате с прямым порядком байтов(в отличие от .Net, чей System.Numerics.BigInteger.ToByteArray -метод использует формат little-endian). Следовательно, нет необходимости изменять порядок следования байтов (используя Reverse -метод).

  • С этими изменениями подпись:

    r = 0x1781ff4997b48d389f518df75001c4b6564082956228d74dd0321656
    s = 0x0aadc68cf78dc75d44fb300f200465e72a70826ec2d5577d49b62e59
    

    который, тем не менее, отличается от подписи, показанной в инструкциях.

    В C # -коде экземпляр ECDsaSigner создается с HMacDsaKCalculator -экземпляр, генерирующий детерминированную подпись на основе RFC6979 . При создании подписи с ECDSA параметр k выбирается случайным образом для недетерминированного ECDSA, тогда как в детерминированном варианте он создается из сообщения и личного ключа в соответствии с определенным алгоритмом (описано в RFC6979), см. здесь . Таким образом, детерминированный вариант генерирует одну и ту же сигнатуру для одного и того же сообщения и личного ключа, а недетерминированный вариант генерирует разные сигнатуры.

    Возможно, разница между сигнатурами вызвана использованием недетерминированного вариантаот CoinFLEX. К сожалению, инструкции не содержат подробных сведений об используемой ECDSA-процедуре.

    Обновление:

    Оба варианта, детерминистические и недетерминированные, предоставьте действительные ECDSA-подписи! До того, как детерминированный вариант ( RFC6979 относится к августу 2013 года) был только недетерминированным вариантом, см. здесь .

    Я установил и протестировал sign_secp224k1 -инструмент на компьютере с Linux (Debian). Как и предполагалось, инструмент генерирует разных подписей для одного и того же закрытого ключа и того же сообщения, очевидно, используя недетерминированный вариант. Это также может быть легко проверено из исходного кода: подпись рассчитывается с использованием ecp_sign -метода, который случайным образом определяет k -значение с использованием /dev/urandom.

    Таким образом, ясно, что сигнатура, сгенерированная C # -кодом с использованием детерминированного варианта , обычно не может соответствовать сигнатуре, сгенерированной sign_secp224k1 -инструментом с использованием недетерминированного варианта.

...