如何使用 ECDSA 測試向量?
我想通過執行 ECDSA NIST 測試向量來驗證我的系統,但我沒有得到預期的輸出。我能夠計算簽名,但它是不正確的,或者至少“r”和“s”分量包含與 nist 向量不同的值。我做錯了什麼?
測試向量:NIST:FIPS 186-4 ECDSA - 186-3ecdsasiggencomponenttestvectors.zip
#include <mbedtls/ecdsa.h> #include <mbedtls/ecp.h> #include <mbedtls/bignum.h> #include <mbedtls/entropy.h> #include <mbedtls/ctr_drbg.h> //All error checks removed //The first of [P-256,SHA-256]-vectors uint8_t ecc_d_p256[] = "\x51\x9b\x42..."; uint8_t ecc_hash_p256[] = "\x44\xac\xf6...": const char *pers = "test"; mbedtls_mpi r, s, d; mbedtls_ecp_group grp; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_entropy_context mbedtls_entropy; //Init mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); mbedtls_mpi_init(&d); mbedtls_ecp_group_init(&grp); mbedtls_ctr_drbg_init(&ctr_drbg); mbedtls_entropy_init(&mbedtls_entropy); //Setup values mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &mbedtls_entropy, pers, 4); mbedtls_mpi_read_binary(&d, ecc_d_p256, (sizeof(ecc_d_p256)-1)); mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1); //Sign mbedtls_ecdsa_sign_det_ext(&grp, &r, &s, &d, ecc_hash_p256, sizeof(ecc_hash_p256)-1, MBEDTLS_MD_SHA256, mbedtls_ctr_drbg_random, &ot_mbedtls_ctr_drbg); //Output //"r" and "s" contains 32 byte outputs, but not "correct" ones
ECDSA 有兩種變體:隨機或確定。簽名的計算涉及一個數字 $ k $ 對於具有相同密鑰的不同消息,絕不能重複。有兩種方法可以實現:生成 $ k $ 隨機或生成 $ k $ 以從密鑰和消息確定的方式。(我在這裡省略了細節,只關注與這個問題相關的內容。)這兩個變體產生兼容的簽名:不可能分辨出哪個變體用於產生給定的簽名。(當然,您可以通過要求實現對同一消息進行兩次簽名並比較輸出來判斷。)
ECDSA 的原始定義僅考慮了隨機變數,這是 NIST 唯一允許的變數,從FIPS 186-4 開始(參見 §6.3 和 §6.4)。RFC 6979是確定性變體的規範。
NIST 測試向量是使用隨機 ECDSA 生成的。使用隨機算法的結果是您無法對其進行已知答案測試。每次執行簽名計算時,都會得到不同的結果。您所能做的就是測試簽名計算的輸出是一個有效的簽名,而不是一個特定的字節序列。
mbedtls_ecdsa_sign_det_ext
實現確定性 ECDSA。您可以將已知答案測試用於確定性 ECDSA。但是 NIST 沒有為其提供測試向量,因為 NIST 沒有標準化確定性 ECDSA。如果您稍微擴展一下,您可以說如果您完全指定算法如何使用隨機生成器的輸出,則可以進行已知答案測試。但是從理論上講,您現在正在測試一種確定性算法,該算法正在接受一些在現實世界中應該來自隨機生成器的輸入。實際上,在實際實現中,並不總是可以更換隨機生成器進行測試。在任何情況下,FIPS 184-4 允許在隨機生成器的輸出在生成時的消耗方式有一些變化 $ k $ 用於 ECDSA 簽名。