Перейти к содержимому
ecdsa.com
C

Mbed TLS (TF-PSA-Crypto)

Mbed TLS 4.x — стек TLS для встраиваемых систем, криптография которого теперь построена на PSA Crypto API: подписи ECDSA в формате raw r‖s, детерминированный ECDSA как отдельный алгоритм и политики ключей, которые закрепляют за каждым ключом свой алгоритм.
Лицензия
Apache-2.0 OR GPL-2.0-or-later
Проверенная версия
4.1.1 ·
Исходный код
github.com/Mbed-TLS/mbedtls
Документация
mbed-tls.readthedocs.io/

Совместимость вкратце

ECDSAПостквантовая криптография

Кривые ECDSA
P-256P-384P-521secp256k1brainpoolP256r1brainpoolP384r1brainpoolP512r1
EdDSA
none

В Mbed TLS 4 криптография вынесена в TF-PSA-Crypto и PSA Crypto API (psa_sign_message, psa_verify_message, psa_generate_key) — тот же API, что использует Trusted Firmware от Arm. Факты на этой странице проверены на пакете Alpine 3.24.2 с Mbed TLS 4.1.1 (сам проект к тому времени выпустил 4.2.0); набор возможностей зависит от конфигурации сборки, как у любой библиотеки для встраиваемых систем.

От кода, производного от OpenSSL, библиотека отличается кодировкой подписи: PSA возвращает форму raw r‖s (64 байта на P-256), а не DER. Подписи для X.509, CMS или проверяющей стороны на OpenSSL нужно упаковать в DER, а подписи DER от этих сторон — распаковать перед вызовом psa_verify_message, иначе функция вернёт PSA_ERROR_INVALID_SIGNATURE, тот же статус, что и для поддельной подписи или 3-байтового фрагмента данных. Преобразуйте подписи конвертером DER ⇄ raw.

У каждого ключа есть политика с одним разрешённым алгоритмом, поэтому выбор между PSA_ALG_ECDSA (случайный nonce) и PSA_ALG_DETERMINISTIC_ECDSA (RFC 6979; тестовый вектор из RFC воспроизвёлся) делается при создании ключа, как показано в примере. s не нормализуется, а проверка принимает high-S. psa_sign_hash подписывает заранее вычисленный дайджест.

В этой сборке подпись и проверка работали на P-256, P-384, P-521, secp256k1 и кривых Brainpool r1; P-224 недоступна, а генерация ключа Ed25519 была отклонена (PSA_ERROR_NOT_SUPPORTED). Из постквантовых алгоритмов есть только проверка подписей на основе хеш-функций LMS (MBEDTLS_LMS_C); типов ключей ML-KEM и ML-DSA нет, а экспериментальный драйвер ML-DSA из mldsa-native (TF_PSA_CRYPTO_PQCP_MLDSA_ENABLED) в конфигурации этой сборки закомментирован. Открытые ключи экспортируются как несжатые точки SEC1 через PSA и как SPKI DER через слой pk.

Факты и проверки, на которых они основаны

Ничего из приведённого ниже не скопировано из документации. 20 октября 2026 г. проверка content/libraries/verify/mbedtls/run.sh запустила Mbed TLS (TF-PSA-Crypto) 4.1.1 в образе контейнера alpine:3.24.2; содержимое страницы должно совпадать с выводом проверки, а у каждого факта приведены соответствующие строки вывода.

  • Кодировка подписи ECDSA

    raw

    psa_sign_message вернула 64 байта raw r‖s на P-256.

    Что записала проверка
    fact ecdsa-signature-encoding = raw
    evidence ecdsa-signature-encoding: psa_sign_message returned 64 bytes
  • Nonce в ECDSA

    rfc6979-opt-in

    PSA_ALG_ECDSA использует случайный nonce; PSA_ALG_DETERMINISTIC_ECDSA воспроизвёл результат из приложения A.2.5 RFC 6979.

    Что записала проверка
    fact ecdsa-nonce = rfc6979-opt-in
    evidence ecdsa-nonce: PSA_ALG_ECDSA repeats: no; PSA_ALG_DETERMINISTIC_ECDSA reproduces the RFC 6979 A.2.5 r: yes (status 0)
  • Low-S при подписи

    either

    s не нормализуется: среди 64 подписей встретились значения high-S.

    Что записала проверка
    fact ecdsa-low-s-sign = either
  • High-S при проверке

    accepts-high-s

    Подпись, в которой s заменили на n − s, прошла проверку.

    Что записала проверка
    fact ecdsa-low-s-verify = accepts-high-s
  • Что хеширует вызов подписи

    hashes-message-or-digest

    psa_sign_message хеширует данные; psa_sign_hash подписывает дайджест, и такая подпись прошла проверку через psa_verify_message.

    Что записала проверка
    fact ecdsa-prehash = hashes-message-or-digest
  • Некорректная подпись ECDSA

    returns-false

    Для подписи в DER, 3-байтового фрагмента данных и верной подписи других данных одинаково вернулся PSA_ERROR_INVALID_SIGNATURE (-149).

    Что записала проверка
    fact ecdsa-malformed-signature = returns-false
    evidence ecdsa-malformed-signature: psa_verify_message status: DER -149, 3 bytes -149, wrong message -149 (PSA_ERROR_INVALID_SIGNATURE = -149)
  • Кривые ECDSA

    P-256P-384P-521secp256k1brainpoolP256r1brainpoolP384r1brainpoolP512r1

    Подпись и проверка работают на P-256, P-384, P-521, secp256k1 и brainpoolP256r1/P384r1/P512r1; генерация ключа P-224 в этой сборке завершилась ошибкой.

    Что записала проверка
    fact ecdsa-curves = P-256, P-384, P-521, secp256k1, brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
  • EdDSA

    none

    Генерация ключа Ed25519 вернула PSA_ERROR_NOT_SUPPORTED (-134).

    Что записала проверка
    fact eddsa = none
    evidence eddsa: psa_generate_key for an Ed25519 key: status -134
  • Постквантовые алгоритмы

    LMS

    MBEDTLS_LMS_C включён (проверка подписей LMS); типы ключей PSA для ML-KEM и ML-DSA не определены, а экспериментальный драйвер mldsa-native не собран.

    Что записала проверка
    fact pqc = LMS
    evidence pqc: MBEDTLS_LMS_C is enabled (LMS hash-based signature verification, <mbedtls/lms.h>)
    evidence pqc: no ML-DSA or ML-KEM PSA key type is defined in these headers
    evidence pqc: psa/crypto_config.h of this build: //#define TF_PSA_CRYPTO_PQCP_MLDSA_ENABLED;//#define TF_PSA_CRYPTO_PQCP_MLDSA_87_ENABLED (commented out = the experimental mldsa-native driver is not built)
  • Форматы открытых ключей

    spki-dersec1-uncompressed

    psa_export_public_key возвращает 65-байтовую несжатую точку SEC1; SPKI DER записывается и разбирается через слой pk.

    Что записала проверка
    fact public-key-formats = spki-der, sec1-uncompressed
    evidence public-key-formats: psa_export_public_key returns 65 bytes starting 0x04 (an uncompressed SEC1 point)

Использование

Создайте ключ P-256, политика которого разрешает детерминированный ECDSA, подпишите сообщение и проверьте 64-байтовую подпись в формате raw.
#include <psa/crypto.h>
#include <stdio.h>

int main(void) {
    if (psa_crypto_init() != PSA_SUCCESS) return 1;
    /* The algorithm is part of the key policy: here deterministic ECDSA (RFC 6979) with SHA-256. */
    psa_algorithm_t alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256);
    psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
    psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
    psa_set_key_bits(&attr, 256);
    psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
    psa_set_key_algorithm(&attr, alg);
    psa_key_id_t key;
    if (psa_generate_key(&attr, &key) != PSA_SUCCESS) return 1;

    const uint8_t msg[] = "order #1042 approved";
    uint8_t sig[PSA_SIGNATURE_MAX_SIZE];
    size_t sig_len;
    psa_sign_message(key, alg, msg, sizeof msg - 1, sig, sizeof sig, &sig_len);

    /* PSA signatures are raw r||s (64 bytes on P-256): wrap them in DER for X.509 or OpenSSL peers. */
    psa_status_t status = psa_verify_message(key, alg, msg, sizeof msg - 1, sig, sig_len);
    printf("signature bytes: %zu, verified: %d\n", sig_len, status == PSA_SUCCESS);
    psa_destroy_key(key);
    return 0;
}

Тестовый стенд для фрагментов кода запускает каждый пример без изменений в образе контейнера alpine:3.24.2, и запуск завершается ошибкой, если вывод не совпадает.

Подготовка
apk add --no-cache -q build-base mbedtls-dev=4.1.1-r0 >/dev/null
Команда
cc -o usage usage.c -lmbedcrypto -ltfpsacrypto && ./usage
Вывод должен совпадать (регулярное выражение)
signature bytes: 64, verified: 1

Библиотеки