mbedtls學習(9)數字簽名RSA、DSA、ECDSA

數字簽名作用

數字簽名是爲了識別消息是否被篡改並驗證消息可靠性,也可以防止否認。這裏注意下和消息驗證碼的不同,數字簽名還可以防止否認,因爲數字簽名的私鑰只有簽名者才持有,而消息認證碼中的密鑰是雙方都有。mnedtls中的數字簽名有3種,RSA、DSA、ECDSA

RSA數字簽名

RSA數字簽名是基於RSA密鑰系統,主要步驟如下

  • Alice生成RSA密鑰對
  • Alice將公鑰發送給Bob,自己保留私鑰
  • Alice使用私鑰對消息進行加密簽名,並將消息和簽名結果發送給Bob
  • Bob使用RSA公鑰對簽名進行解密,判斷消息是否又被篡改。
RSA數字簽名填充方法

與RSA加解密部分類似,RSA數字簽名也有2種填充方案:

  • PKCS1-v1_5
  • PSS
DSA數字簽名

DSA算法是數字簽名標準規範DSS(Digital Signature Standard)的一部分,與RSA不同,DSA算法只能提供數字簽名功能,而不能用於加密或密鑰交換,步驟如下

  • Alice生成密鑰,其中私鑰(x),公鑰(p,q,g,y),其中素數p的長度位數爲L位,q的長度位數爲N位,則簽名長度見下表
  • Alice用DSA簽名結果有2部分r和s 記(r,s)
  • Bob用公鑰、Alice發來的消息、和(r,s)驗籤判斷是否通過。這裏只能得到一個是否通過的結果不能用於加密或密鑰交換。
ECDSA數子簽名

ECDSA就是再DSA基礎上加上橢圓曲線算法,和ECDH與DH的關係一樣,用較短的密鑰長度便可以提供與RSA和DSA算法相同的安全等級,步驟如下

  • ECDSA生成密鑰對
    Alice密鑰對的生成依賴橢圓曲線參數,常用的有secp256r1和secp384r1,橢圓曲線參數有(p,a,b,G,n,h)。得到私鑰(d),公鑰(p,a,b,G,Q)
  • ECDSA簽名
    Alice ECDSA簽名結果爲r和s,記做(r,s),其中r和s的長度與n相同,例如再escp256r1中,n長度位256比特,則r和s也是256比特
  • ECDSA驗籤
    Bob在拿到公鑰、消息、以及(r,s)後驗籤判斷是否通過。這裏只能得到一個是否通過的結果不能用於加密或密鑰交換。
mbedtls RSA數字簽名例子

先要打開如下宏

#define MBEDTLS_AES_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_MD_C
#define MBEDTLS_OID_C           開啓OID數據結構塊
#define MBEDTLS_BIGNUM_C 
#define MBEDTLS_GENPRIME 
#define MBEDTLS_RSA_C
#define MBEDTLS_PKCS1_V21
#define MBEDTLS_AES_ROM_TABLES
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/rsa.h"
#include "mbedtls/platform.h"

#define mbedtls_printf printf

#define assert_exit(cond, ret) \
    do { if (!(cond)) { \
        printf("  !. assert: failed [line: %d, error: -0x%04X]\n", __LINE__, -ret); \
        goto cleanup; \
    } } while (0)
/*
static int entropy_source(void *data, uint8_t *output, size_t len, size_t *olen)
{
    uint32_t seed;

    seed = sys_rand32_get();
    if (len > sizeof(seed)) {
        len = sizeof(seed);
    }

    memcpy(output, &seed, len);

    *olen = len;
    return 0;
}*/

static void dump_buf(char *info, uint8_t *buf, uint32_t len)
{
    mbedtls_printf("%s", info);
    for (int i = 0; i < len; i++) {
        mbedtls_printf("%s%02X%s", i % 16 == 0 ? "\n     ":" ", 
                        buf[i], i == len - 1 ? "\n":"");
    }
}

static void dump_rsa_key(mbedtls_rsa_context *ctx)
{
    size_t olen;
    uint8_t buf[516];
    mbedtls_printf("\n  +++++++++++++++++ rsa keypair +++++++++++++++++\n\n");
    mbedtls_mpi_write_string(&ctx->N , 16, buf, sizeof(buf), &olen);
    mbedtls_printf("N: %s\n", buf); 

    mbedtls_mpi_write_string(&ctx->E , 16, buf, sizeof(buf), &olen);
    mbedtls_printf("E: %s\n", buf);

    mbedtls_mpi_write_string(&ctx->D , 16, buf, sizeof(buf), &olen);
    mbedtls_printf("D: %s\n", buf);

    mbedtls_mpi_write_string(&ctx->P , 16, buf, sizeof(buf), &olen);
    mbedtls_printf("P: %s\n", buf);

    mbedtls_mpi_write_string(&ctx->Q , 16, buf, sizeof(buf), &olen);
    mbedtls_printf("Q: %s\n", buf);

    mbedtls_mpi_write_string(&ctx->DP, 16, buf, sizeof(buf), &olen);
    mbedtls_printf("DP: %s\n", buf);

    mbedtls_mpi_write_string(&ctx->DQ, 16, buf, sizeof(buf), &olen);
    mbedtls_printf("DQ: %s\n", buf);

    mbedtls_mpi_write_string(&ctx->QP, 16, buf, sizeof(buf), &olen);
    mbedtls_printf("QP: %s\n", buf);
    mbedtls_printf("\n  +++++++++++++++++ rsa keypair +++++++++++++++++\n\n");
}

int main(void)
{
    int ret = 0;
    uint8_t msg[100];
    uint8_t sig[2048/8];
    uint8_t *pers = "simple_rsa_sign";

    mbedtls_platform_set_printf(printf);
    mbedtls_platform_set_snprintf(snprintf);
    
    mbedtls_rsa_context ctx;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;

    mbedtls_entropy_init(&entropy);
    mbedtls_ctr_drbg_init(&ctr_drbg);
	//RSA密鑰對初始化       填充方式PSS,散列算法SHA256
    mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);

    /*mbedtls_entropy_add_source(&entropy, entropy_source, NULL,
                   MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG);*/
    ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, 
                                (const uint8_t *) pers, strlen(pers));
    assert_exit(ret == 0, ret);
    mbedtls_printf("\n  . setup rng ... ok\n\n");
    //產生RSA密鑰對
    mbedtls_printf("  ! RSA Generating large primes may take minutes! \n");
    ret = mbedtls_rsa_gen_key(&ctx, mbedtls_ctr_drbg_random, 
                                        &ctr_drbg, 
                                        2048,  //RSA2048
                                        65537);//公開指數
    assert_exit(ret == 0, ret);
    mbedtls_printf("  1. rsa generate keypair ... ok\n");
    dump_rsa_key(&ctx);
    //RSA用私鑰簽名 輸出sig簽名結果
    ret = mbedtls_rsa_pkcs1_sign(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, 
                                    MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256,
                                    sizeof(msg), msg, sig);
    assert_exit(ret == 0, ret);
    dump_buf("  2. rsa generate signature:", sig, sizeof(sig));
    //RSA公鑰驗籤 返回0則驗證成功
    ret = mbedtls_rsa_pkcs1_verify(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, 
                                        MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, 
                                        sizeof(msg), msg, sig);
    assert_exit(ret == 0, ret);
    mbedtls_printf("  3. rsa verify signature ... ok\n\n");

cleanup:
    mbedtls_rsa_free(&ctx);
    mbedtls_ctr_drbg_free(&ctr_drbg);
    mbedtls_entropy_free(&entropy);

    return ret;
}

運行結果


  . setup rng ... ok

  ! RSA Generating large primes may take minutes! 
  1. rsa generate keypair ... ok

  +++++++++++++++++ rsa keypair +++++++++++++++++

N: C776EB2FD3D1C7044E21233960EDA1CCC0F1CE5132C3C9CBBF0D81B2150BBEBCF55B7FA0BAE96D74BC10E2B583BC4E1D565E4838D73420A43FB4FD67BFBF4109C1F4F9D19C61003A730EA2A331879F5C758D5A92DAAEC18BF0BFACEE9E56E684C66F3BF8B85EEF54172B1EEE0C0960DC2D39D075C09B4B43E7831AD965D6DD2181A40DD5A00615D0C61C3F9DF6AC1D440A9264917E26B8E9DEAA9E9C3CE9B9408D854202FD9612E6C074EE7439EBFDDF0AA827A5070EDF4B65D90086815079912F4CC2AA1AA28B843BE7DCFA6004D8D93011C05BC6B480597582C1E73C900CB63575E92FA8275E72C4FF09B3C25097B762EDCFAED82F9B3AEC4816E288310EA7
E: 010001
D: 052FAA5DCBFC2058944F7842FDAA3012CAD17EB3CDC619711ABE9728B23363FA35C6F34292998F2701DCCE8839ACA3BB4F8B940526534CA5F8A21414A67FAA893E69C8351303D2A5B2682702673F477D77F0FCF1E48DB6AA94CFE7072D46C5279EA135C5F9C53E23C9966D6F7310AB5C0E30FAA295277485877779333DDAA0553AF05E78610FF10962D0777AE351059A3A5BBB459AD38EA96C2A885976C73F82D7FFD00840160AA00C014517DE350EB51281215E63E494A38C681A2C40DBBE6C5571D6C3BC28B100BD10CF7AFCFE64A4BE234AEE6A3031B415F18F6FAB2BD88BD62F6BD3FDD9BAA0434934CCCD776C0A33BA57AD3F643D52802A0AB5D2EB6F81
P: E81DB8236DFE06B3FCAAA3275898D58966AE3E1607DE3071AEED968F1C0D68BD756125DE66C063DC4F9E0993E841E29BEF37C09804DB92B7CFF58B0070170D90E3955E8B51FE0381CA41FC99F40701585F4FA057490CC10DF6BFF660A9E0871D9ED3E3E777B5C312D614AD37D4B06772EE675F96C43682FDEC9D514D8120854F
Q: DBFD1BE4BE9A5F7056FCAF307D0986F0BB08900BF91D0AB9DD6AA016DFDA2AF089EB9DEFB054ACEC9981654E655B3EFF9EB6BB4119CAA7E65BA6606FFA6398757FABF11ABD292A0C5960AFBB17A70F85348243D13E2A2AD2289450BFDF13EBCDA95F9D686343DD2DC4A108A6DAF67F58EC07BAAC0C89D0509B3A90B83CF5BB29
DP: 72BD1E25055E28DA17F011AE8571273D4070A968228386D6EB6DAE9B1776D96BADF653CDD86509F801B35170B7C2B9CDF3365011D574E4D5D00AC4A776C12E878CB86D7FD90C0397C8EF4D7A9CD249ABF1915EE546CAF3337FE1EC5C641D052D7331B2DADCA610C3E2E75DA8D78E4BD4D85C693811CE107A8CD8473454BC4AA9
DQ: 0F13323523A69A81AD44559102108411BD0F62279FE390979A07B37EBDCA4A84FF3E892D22AD3AC85FE0911BA5307289BBCB93DB6B340AFB6B2E648F67DE29556BF1516D5EA7127D94265F0478237799CE365B055CB8310503C8DE1BB7E2BA96F6535A0B0C3A5B4EC699AE6918BA2991E362C835000AF59E8074ABF4242146B9
QP: CE3B9361BA3301C86485B1105BF71D4DD6F45E2380E954DD4B0045C94BAAD18B48C628059A5E97F69D5C888BA7D2FF9EDBA0145EA87B09725A250F9CD8527D62D0A212065970192EB2A7BD511F0D12D7B545FFF3672556D613C362E4D1E3712592EF9DB789D64BD4CB1020254E450E2F277F2D1EBF5364C8980E8CE0C0145B1C

  +++++++++++++++++ rsa keypair +++++++++++++++++

  2. rsa generate signature:
     AF D8 AB 09 7E 45 89 FF DB F4 D1 3B D4 73 CC 72
     4D 9E BD 8C 71 A0 DF F5 EF 80 66 A2 CD 1B 1F 16
     C2 87 D7 D5 CB 64 03 16 36 C7 F4 3E E3 6D C5 B4
     38 A1 09 38 E1 B2 40 74 DA 76 BE B2 4F 39 06 FF
     EB FE F2 89 35 87 85 92 51 35 A1 2D 62 EE E2 38
     50 43 C9 88 44 35 B5 FA 44 C0 9A 77 65 9F FF E8
     F6 E4 FC 0B 51 09 81 98 F7 71 06 43 ED F9 2C 09
     BC 2C FB A0 4F 85 BE A1 7C 7F FC 32 3E 03 A0 A8
     C8 4D 40 D1 DC 44 75 12 61 D4 D9 D6 B2 39 9C B8
     AD 17 EE BE 41 6B 49 45 B2 66 3D DD 4F 11 21 45
     83 46 AE 17 AB 9C FC F2 1F 01 24 51 38 6B 2E F4
     BB 22 07 96 CE 70 5C 8A 20 E2 85 6E 7C F2 BA 61
     27 57 2E 08 63 46 B1 23 7B 45 41 2D 0A A0 BC 5F
     CF 8A 0B 92 FE 63 E4 09 36 D9 54 50 B4 CE 06 FE
     17 31 F8 95 3C E1 12 5F 48 68 8F 6B 29 0F 8E 47
     E2 6B 73 8A DA 96 76 AE B7 16 14 39 C0 D0 21 18
  3. rsa verify signature ... ok

mbedtls ECDSA簽名例子

先打開這些宏

#define MBEDTLS_AES_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_MD_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_ECP_C      
#define MBEDTLS_ASN1_PARSE_C   開啓ASN1結構解析
#define MBEDTLS_ASN1_WRITE_C   開啓ASN1結構寫入
#define MBEDTLS_ECDSA_C        開啓ECDSA算法
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED  
#define MBEDTLS_AES_ROM_TABLES
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/md.h"
#include "mbedtls/ecdsa.h"
#include "mbedtls/platform.h"

#define assert_exit(cond, ret) \
    do { if (!(cond)) { \
        printf("  !. assert: failed [line: %d, error: -0x%04X]\n", __LINE__, -ret); \
        goto cleanup; \
    } } while (0)

static void dump_buf(char *info, uint8_t *buf, uint32_t len)
{
    mbedtls_printf("%s", info);
    for (int i = 0; i < len; i++) {
        mbedtls_printf("%s%02X%s", i % 16 == 0 ? "\n     ":" ", 
                        buf[i], i == len - 1 ? "\n":"");
    }
}
/*
static int entropy_source(void *data, uint8_t *output, size_t len, size_t *olen)
{
    uint32_t seed;

    seed = sys_rand32_get();
    if (len > sizeof(seed)) {
        len = sizeof(seed);
    }

    memcpy(output, &seed, len);

    *olen = len;
    return 0;
}*/

int main(void)
{
    int ret = 0;
    char buf[97];
    uint8_t hash[32], msg[100];
    uint8_t *pers = "simple_ecdsa";
    size_t rlen, slen, qlen, dlen;
    memset(msg, 0x12, sizeof(msg));
    
    //mbedtls_platform_set_printf(printf);

    mbedtls_mpi r, s;
    mbedtls_ecdsa_context ctx;
    mbedtls_md_context_t md_ctx;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;

    mbedtls_mpi_init(&r);
    mbedtls_mpi_init(&s);
    mbedtls_ecdsa_init(&ctx);  //初始化ECDSA結構體
    mbedtls_entropy_init(&entropy);
    mbedtls_ctr_drbg_init(&ctr_drbg);
    /*
    mbedtls_entropy_add_source(&entropy, entropy_source, NULL,
                   MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG);*/
    ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, 
                                (const uint8_t *) pers, strlen(pers));
    assert_exit(ret == 0, ret);
    mbedtls_printf("\n  . setup rng ... ok\n\n");

    mbedtls_md_init(&md_ctx);
    mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), msg, sizeof(msg), hash);
    mbedtls_printf("  1. hash msg ... ok\n");//計算出msg的hash值
    //產生ECDSA密鑰對
    ret = mbedtls_ecdsa_genkey(&ctx, MBEDTLS_ECP_DP_SECP256R1,//選擇SECP256R1
                              mbedtls_ctr_drbg_random, &ctr_drbg);
    assert_exit(ret == 0, ret);
    mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, 
                            MBEDTLS_ECP_PF_UNCOMPRESSED, &qlen, buf, sizeof(buf));
    dlen = mbedtls_mpi_size(&ctx.d);
    mbedtls_mpi_write_binary(&ctx.d, buf + qlen, dlen);
    dump_buf("  2. ecdsa generate keypair:", buf, qlen + dlen);
    //ECDSA簽名,得到r , s
    ret = mbedtls_ecdsa_sign(&ctx.grp, &r, &s, &ctx.d, 
                        hash, sizeof(hash), mbedtls_ctr_drbg_random, &ctr_drbg);
    assert_exit(ret == 0, ret);
    rlen = mbedtls_mpi_size(&r);
    slen = mbedtls_mpi_size(&s);
    mbedtls_mpi_write_binary(&r, buf, rlen);
    mbedtls_mpi_write_binary(&s, buf + rlen, slen);
    dump_buf("  3. ecdsa generate signature:", buf, rlen + slen);
	//ECDSA驗籤,返回0表示驗證成功
    ret = mbedtls_ecdsa_verify(&ctx.grp, hash, sizeof(hash), &ctx.Q, &r, &s);
    assert_exit(ret == 0, ret);
    mbedtls_printf("  4. ecdsa verify signature ... ok\n\n");

cleanup:
    mbedtls_mpi_free(&r);
    mbedtls_mpi_free(&s);
    mbedtls_md_free(&md_ctx);
    mbedtls_ecdsa_free(&ctx);
    mbedtls_ctr_drbg_free(&ctr_drbg);
    mbedtls_entropy_free(&entropy);

    return(ret != 0);
}

運行結果

  . setup rng ... ok

  1. hash msg ... ok
  2. ecdsa generate keypair:
     04 21 1D 44 28 F1 02 4D 70 3A 0B F9 01 AA 98 55
     4F A5 48 44 54 E5 A4 11 58 B7 37 CF B8 B7 15 78
     5C 22 43 65 B0 DD CA 4D 03 8D A4 3B 33 3C 16 A2
     3B E1 F9 51 A7 6F 6D 74 36 49 89 2F 55 1F 31 F4
     3E 93 0C 09 45 A9 58 D0 B4 A9 58 EF A4 D9 B9 87
     06 AD F0 0A 5E AA C0 87 A8 70 06 F3 34 A8 52 E9
     84
  3. ecdsa generate signature:
     23 2E 03 50 32 D8 16 BB AA E1 F8 25 59 A7 B7 C5
     6D 58 9D D7 2E 28 ED E9 07 8D BB DB E5 B8 EA 49
     65 45 10 42 19 EF BC E0 9B B2 28 18 AC 50 42 86
     78 79 2B 02 68 74 C6 EF 90 06 DF C6 E9 00 C6 2B
  4. ecdsa verify signature ... ok
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章