Я хочу проверить некоторые пакеты данных, которые содержат подпись ECDSA, не закодированную ASN.1 DER.
Я пытаюсь выполнить задачу с помощью openSSL (версия 1.1.0), поскольку он, кажется, обеспечивает все необходимые функции.
В настоящее время я застрял с импортом подписи из пакета данных. Подпись выглядит так:
(Последние 4 байта не должны быть отмечены как часть подписи)
TShark показывает соответствующую часть следующим образом:
"gn.sh.sig": { "gn.st.pka": "0", "gn.st.eccpointtype": "3", "gn.st.opaque": "1f:f8:ad:a7:fd:99:b2:a8:a2:69:d4:d6:67:e5:ee:5b:3f:8b:e8:7f:49:fc:b4:79:95:98:15:0d:cb:bd:06:3c", "gn.st.opaque": "61:a4:6a:c9:a7:dd:bd:0d:9c:0a:0e:73:db:52:06:bb:79:53:99:51:16:45:45:81:4e:df:94:5c:58:59:40:14" }
Кодировка соответствует ETSI TS 103 097 v1.2.1.
Первая запись opaque
вместе с ECC Point type
образуют EccPoint с именем R
, а второе поле opaque
называется s
.
Мой первый шаг — создать подпись в openSSL и импортировать в нее данные.
Мой код (обработка ошибок удалена для уменьшения размера) выглядит так:
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/bn.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
void verify_signature(void)
{
int res;
// Which value is correct for r-part?
static const char sig_r_hex[] = "1ff8ada7fd99b2a8a269d4d667e5ee5b3f8be87f49fcb4799598150dcbbd063c";
static const char sig_s_hex[] = "61a46ac9a7ddbd0d9c0a0e73db5206bb79539951164545814edf945c58594014";
BN_CTX *bn_ctx = BN_CTX_new();
BN_CTX_start(bn_ctx);
// Create signature and import from packet.
BIGNUM *bn_r = BN_CTX_get(bn_ctx);
BIGNUM *bn_s = BN_CTX_get(bn_ctx);
res = BN_hex2bn(&bn_r, sig_r_hex);
res = BN_hex2bn(&bn_s, sig_s_hex);
ECDSA_SIG *signature = ECDSA_SIG_new();
res = ECDSA_SIG_set0(signature, bn_r, bn_s);
printf("ECDSA_SIG_set0(): %d\n", res);
// ...
// Create hash of message and verify signature with public key
//...
}
int main(int arc, char *argv[])
{
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
verify_signature();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
ERR_free_strings();
return 0;
}
Чего мне сейчас не хватает, так это того, как правильно обрабатывать значение R
. Какие части сжатого CurvePoint следует использовать как r
для инициализации подписи? Нужно ли распаковывать часть y
? Должен ли я добавить некоторое указание для сжатого значения y
?
Любые подсказки приветствуются.
Редактировать:
Из того, что я прочитал в IEEE1609.2 и SEC-1, можно добавить дополнительную информацию, чтобы обеспечить более быстрое вычисление R
из r
. Это может быть сама точка R
. Поскольку r = xR mod n
должно быть возможно вычислить r
из EccPoint.
Поддерживает ли openSSL этот механизм для ускорения проверки или мне действительно нужно удалить дополнительную информацию (и узнать, как это сделать), чтобы передать r
в openSSL?