Почему один и тот же ключ HSM каждый раз проверяет другой адрес ethereum? - PullRequest
1 голос
/ 24 апреля 2019

Я взаимодействую с HSM, который генерирует и подписывает с помощью стандарта ethereum (secp256k1). Я взаимодействую с HSM, используя пакет под названием Graphene. Я вытащил открытый ключ, используя его атрибут "pointEC": 0xc87c1d67c1909ebf8b54c9ce3d8e0f0cde41561c8115481321e45b364a8f3334b6e826363d8e895110fc9ca2d75e84cc7c56b8e9fbcd70c726cb44f5506848fa

Который я могу использовать для генерации адреса: 0x21d20b04719f25d2ba0c68e851bb64fa570a9465

Но когда я пытаюсь использовать ключ для подписания личного сообщения из приложения, подпись всегда оценивается по другому адресу. Например, одноразовый номер / сообщение: wAMqcOCD2KKz2n0Dfbu1nRYbeLw_qbLxrW1gpTBwkq Имеет подпись:

0x2413f8d2ab4df2f3d87560493f21f0dfd570dc61136c53c236731bf56a9ce02cb23692e6a5cec96c62359f6eb4080d80328a567d14387f487f3c50d9ce61503b1c

Но он восстанавливает действительный адрес 0xFC0561D848b0cDE5877068D94a4d803A0a933785

Это все предположительно с одним и тем же закрытым / открытым ключом. Конечно, я просто добавил значение восстановления «1с», но даже когда я пытаюсь использовать другие значения, мне не везет. Вот еще пара примеров:

Nonce: WRH_ApTkfN7yFAEpbGwU9BiE2M6eKTZMklPYK50djnx
Sig: 0x70242adabfe27c12e54abced8de87b45f511a194609eb27b215b153594b5697b7fb5e7279285663f80c82c2a2f2920916f76fd845cdecb45ace19f76b0622ac41c
Address: 0x1A086eD40FF90E75764260E2Eb42fab4Db519E53

Nonce: TZV6qhplddJgcKaN7qtpcIhudFhiQ
Sig: 0x3607beb3d58ff35ca1059f3ea44f41e79e76d8ffe35a4f716e78030f0fe2ca1da51f138c31d4ec4b9fc3546c4de1185736a4c4c7030a8b1965e30cb0af6ba2ee1c
Address: 0xa61A518cf73163Fd92461942c26C67c203bda379

Мой код для подписи сообщения:

        let alg: graphene.MechanismType;
        alg = graphene.MechanismEnum.ECDSA;
        const session = get_session();

        let key: graphene.Key | null = null;
        //#region Find signing key
        const objects = session.find({label: GEN_KEY_LABEL});
        for (let i = 0; i < objects.length; i++) {
            const obj = objects.items(i);
            if ((obj.class === graphene.ObjectClass.PRIVATE_KEY ||
                obj.class === graphene.ObjectClass.SECRET_KEY) &&
                obj.handle.toString('hex') == params.handle
            ) {
                key = obj.toType<graphene.Key>();
                break;
            }
        }
        if (!key) {
            throw new Error("Cannot find signing key");
        }
        var sign = session.createSign(alg,key);
        if (!params.data) {
            console.log("No data found. Signing 'test' string");
            params.data = 'test';
        }
        sign.update(Buffer.from(params.data.toString().trim()));
        var signature = sign.final();



        console.log(signature.toString('hex'));

Имейте в виду, что он не работает даже при наличии всего 1 ключа.

1 Ответ

2 голосов
/ 24 апреля 2019

Адрес только что рассчитывается по открытому ключу, а подпись генерируется с использованием ECDSA. ECDSA, который состоит из случайного значения r и сигнатуры s, характерной для этого случайного числа (и, конечно, личного ключа). Больше информации здесь (Википедия по ECDSA) .

Вы не видите этого, потому что они просто кодируются в значения статического размера (без знака, большое целое) и затем объединяются вместе, чтобы называться «подписью» (следовательно, размер подписи в два раза больше размера ключа , 64 байта вместо 32 байтов). Верификация проанализирует подпись и снова использует отдельные значения. С помощью ethereum и BitCoin к подписи может добавляться дополнительный байт, чтобы можно было вернуть открытый ключ и затем пересчитать адрес. Это также изменяет генерацию подписи , так что вы больше не говорите об ECDSA.

Существует также формат подписи X9.62, который по-прежнему состоит из двух отдельных целых чисел, закодированных с использованием кодировки ASN.1 / DER. Эти сигнатуры выглядят только частично случайными из-за накладных расходов, необходимых для разделения / кодирования двух целых чисел.

...