• OpenSSL之RSA用法


    RSA公开密钥密码体制是一种使用不同的加密密钥与解密密钥,“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制 。在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK 。
    正是基于这种理论,1978年出现了著名的RSA算法,它通常是先生成一对RSA密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要 。

    RSA算法是一个广泛使用的公钥算法。其密钥包括公钥和私钥。它能用于数字签名、身份认证以及密钥交换。RSA密钥长度一般使用1024位或者更高。RSA密钥信息主要包括:
    n:模数
    e:公钥指数
    d:私钥指数
    p:最初的大素数
    q:最初的大素数
    其中,公钥为n和e;私钥为n和d。

    本文假设你已经安装好了OpenSSL,并且持有一份1.1.1的源码。
    RSA相关的头文件在rsa.h中、源文件在crypto/rsa目录中。

    主要结构:

    1. struct rsa_st {
    2. /*
    3. * The first parameter is used to pickup errors where this is passed
    4. * instead of an EVP_PKEY, it is set to 0
    5. */
    6. int pad;
    7. int32_t version;
    8. const RSA_METHOD *meth;
    9. /* functional reference if 'meth' is ENGINE-provided */
    10. ENGINE *engine;
    11. BIGNUM *n;
    12. BIGNUM *e;
    13. BIGNUM *d;
    14. BIGNUM *p;
    15. BIGNUM *q;
    16. BIGNUM *dmp1;
    17. BIGNUM *dmq1;
    18. BIGNUM *iqmp;
    19. /* for multi-prime RSA, defined in RFC 8017 */
    20. STACK_OF(RSA_PRIME_INFO) *prime_infos;
    21. /* If a PSS only key this contains the parameter restrictions */
    22. RSA_PSS_PARAMS *pss;
    23. /* be careful using this if the RSA structure is shared */
    24. CRYPTO_EX_DATA ex_data;
    25. CRYPTO_REF_COUNT references;
    26. int flags;
    27. /* Used to cache montgomery values */
    28. BN_MONT_CTX *_method_mod_n;
    29. BN_MONT_CTX *_method_mod_p;
    30. BN_MONT_CTX *_method_mod_q;
    31. /*
    32. * all BIGNUM values are actually in the following data, if it is not
    33. * NULL
    34. */
    35. char *bignum_data;
    36. BN_BLINDING *blinding;
    37. BN_BLINDING *mt_blinding;
    38. CRYPTO_RWLOCK *lock;
    39. };
    40. typedef struct rsa_st RSA;

    这个结构定义了RSA内部数据信息。主要字段含义:
    version —— 版本。
    meth —— RSA运算抽象方法集合。
    n,e,d,p,q,dmp1,dmq1,iqmp —— 密钥相关的大数。

    1. struct rsa_meth_st {
    2. char *name;
    3. int (*rsa_pub_enc) (int flen, const unsigned char *from,
    4. unsigned char *to, RSA *rsa, int padding);
    5. int (*rsa_pub_dec) (int flen, const unsigned char *from,
    6. unsigned char *to, RSA *rsa, int padding);
    7. int (*rsa_priv_enc) (int flen, const unsigned char *from,
    8. unsigned char *to, RSA *rsa, int padding);
    9. int (*rsa_priv_dec) (int flen, const unsigned char *from,
    10. unsigned char *to, RSA *rsa, int padding);
    11. /* Can be null */
    12. int (*rsa_mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
    13. /* Can be null */
    14. int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
    15. const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
    16. /* called at new */
    17. int (*init) (RSA *rsa);
    18. /* called at free */
    19. int (*finish) (RSA *rsa);
    20. /* RSA_METHOD_FLAG_* things */
    21. int flags;
    22. /* may be needed! */
    23. char *app_data;
    24. /*
    25. * New sign and verify functions: some libraries don't allow arbitrary
    26. * data to be signed/verified: this allows them to be used. Note: for
    27. * this to work the RSA_public_decrypt() and RSA_private_encrypt() should
    28. * *NOT* be used RSA_sign(), RSA_verify() should be used instead.
    29. */
    30. int (*rsa_sign) (int type,
    31. const unsigned char *m, unsigned int m_length,
    32. unsigned char *sigret, unsigned int *siglen,
    33. const RSA *rsa);
    34. int (*rsa_verify) (int dtype, const unsigned char *m,
    35. unsigned int m_length, const unsigned char *sigbuf,
    36. unsigned int siglen, const RSA *rsa);
    37. /*
    38. * If this callback is NULL, the builtin software RSA key-gen will be
    39. * used. This is for behavioural compatibility whilst the code gets
    40. * rewired, but one day it would be nice to assume there are no such
    41. * things as "builtin software" implementations.
    42. */
    43. int (*rsa_keygen) (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
    44. int (*rsa_multi_prime_keygen) (RSA *rsa, int bits, int primes,
    45. BIGNUM *e, BN_GENCB *cb);
    46. };
    47. typedef struct rsa_meth_st RSA_METHOD;

    这个结构定义了RSA内部各种运算抽象方法集合。主要字段含义:
    name —— 名称描述。
    rsa_pub_enc —— 公钥加密方法。
    rsa_pub_dec —— 公钥解密方法。
    rsa_priv_enc —— 私钥加密方法。
    rsa_priv_dec —— 公钥解密方法。
    rsa_sign —— 签名方法。
    rsa_verify —— 验签方法。
    rsa_keygen —— 生成密钥对方法。

    在1.1.1中,大多数的数据结构已经不再向使用者开放,从封装的角度来看,这是更合理的。如果你在头文件中找不到结构定义,不妨去源码中搜一搜。

    主要函数:

    RSA *RSA_new(void);
    生成一个RSA密钥结构,采用默认的rsa_pkcs1_ossl_meth方法。

    void RSA_free(RSA *r);
    释放RSA结构。

    RSA *RSA_generate_key(int bits, unsigned long e, void (*callback) (int, int, void *), void *cb_arg);
    生成RSA密钥(旧版本)。
    bits为密钥位数,e为公钥指数。
    callback为密钥生成过程中的干预回调函数,通常传入NULL。cb_arg为回调参数。
    成功返回RSA指针,失败返回NULL。

    int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
    生成RSA密钥(新版本)。
    rsa为RSA对象指针。bits为密钥位置,e为公钥指数的大数形式指针。cb为干预回调函数,通常传入NULL。
    成功返回1,失败返回0。
    关于公钥指数e,主要有两个取值:
    # define RSA_3 0x3L
    # define RSA_F4 0x10001L

    RSA *RSAPublicKey_dup(RSA *rsa);
    复制RSA公钥部分。
    成功返回RSA指针,失败返回NULL。

    RSA *RSAPrivateKey_dup(RSA *rsa);
    复制RSA私钥部分。
    成功返回RSA指针,失败返回NULL。

    int RSA_bits(const RSA *rsa);
    获取RSA密钥位数。
    int RSA_size(const RSA *rsa);
    获取RSA密钥长度。

    int RSA_check_key(const RSA *);
    int RSA_check_key_ex(const RSA *, BN_GENCB *cb);
    检查RSA的有效性,必须为完整的密钥对。
    成功返回1,失败返回0。

    int RSA_print(BIO *bp, const RSA *r, int offset);
    int RSA_print_fp(FILE *fp, const RSA *r, int offset);
    将RSA信息输出到bp/fp中,off为输出信息在bp/fp中的偏移量,比如是屏幕bp/fp,则表示打印信息的位置离左边屏幕边缘的距离。

    int RSA_public_encrypt(int flen, const unsigned char *from,
    unsigned char *to, RSA *rsa, int padding);
    RSA公钥加密。
    成功返回密文的长度,失败返回-1。

    int RSA_public_decrypt(int flen, const unsigned char *from,
    unsigned char *to, RSA *rsa, int padding);
    RSA公钥解密。
    成功返回明文的长度,失败返回-1。

    int RSA_private_encrypt(int flen, const unsigned char *from,
    unsigned char *to, RSA *rsa, int padding);
    RSA私钥加密。
    成功返回密文的长度,失败返回-1。

    int RSA_private_decrypt(int flen, const unsigned char *from,
    unsigned char *to, RSA *rsa, int padding);
    RSA私钥解密。
    成功返回明文的长度,失败返回-1。

    关于padding填充方式,取值:

    1. # define RSA_PKCS1_PADDING 1
    2. # define RSA_SSLV23_PADDING 2
    3. # define RSA_NO_PADDING 3
    4. # define RSA_PKCS1_OAEP_PADDING 4
    5. # define RSA_X931_PADDING 5
    6. /* EVP_PKEY_ only */
    7. # define RSA_PKCS1_PSS_PADDING 6

    其中PKCS1填充大小为11字节,所以加密明文长度必须不大于(密钥大小-11字节)。
    # define RSA_PKCS1_PADDING_SIZE 11

    int RSA_sign(int type, const unsigned char *m, unsigned int m_length,
    unsigned char *sigret, unsigned int *siglen, RSA *rsa);
    对数据m生成RSA签名,生成的签名长度与key的长度相同,如512位密钥生成64字节签名。
    type指定摘要算法的NID,如NID_sha1。
    成功返回1,失败返回0。

    int RSA_verify(int type, const unsigned char *m, unsigned int m_length,
    const unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
    对数据m验证RSA签名。
    type指定摘要算法的NID,如NID_sha1。
    成功返回1,失败返回0。

    公私钥的编码转换:

    以下函数在x509.h中定义:

    1. int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa)
    2. {
    3. return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
    4. }

    将RSA公钥转换为DER编码,并写入到bp抽象IO中。
    成功返回1,失败返回0。

    1. RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa)
    2. {
    3. return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
    4. }

    从bp抽象IO中读取DER编码,并转换为rsa结构私钥。
    成功返回有效指定,失败返回NULL。

    1. int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa)
    2. {
    3. return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa);
    4. }

    将RSA公钥转换为DER编码,并写入到bp抽象IO中。
    成功返回1,失败返回0。

    1. RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa)
    2. {
    3. return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa);
    4. }

    从bp抽象IO中读取DER编码,并转换为rsa结构公钥。
    成功返回有效指定,失败返回NULL。

    使用举例1:

    下面这个例子演示了RSA密钥对的生成、公私钥的复制、公钥加密和私钥解密的用法。

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. namespace dakuang {}
    8. int main(int argc, char* argv[])
    9. {
    10. ERR_load_RSA_strings();
    11. RSA* pRSA = RSA_generate_key(512, RSA_3, NULL, NULL);
    12. RSA_print_fp(stdout, pRSA , 0);
    13. RSA_free(pRSA);
    14. pRSA = RSA_new();
    15. BIGNUM* pBNe = BN_new();
    16. BN_set_word(pBNe, RSA_3);
    17. int ret = RSA_generate_key_ex(pRSA, 512, pBNe, NULL);
    18. printf("RSA_generate_key_ex() ret:%d \n", ret);
    19. BN_free(pBNe);
    20. RSA_print_fp(stdout, pRSA , 0);
    21. RSA* pRSApub = RSAPublicKey_dup(pRSA);
    22. printf("copy pub key:%p \n", pRSApub);
    23. RSA_print_fp(stdout, pRSApub , 0);
    24. RSA_free(pRSApub);
    25. RSA* pRSApri = RSAPrivateKey_dup(pRSA);
    26. printf("copy pri key:%p \n", pRSApri);
    27. RSA_print_fp(stdout, pRSApri , 0);
    28. RSA_free(pRSApri);
    29. int bits = RSA_bits(pRSA);
    30. printf("bits:%d \n", bits);
    31. int bytes = RSA_size(pRSA);
    32. printf("bytes:%d \n", bytes);
    33. ret = RSA_check_key(pRSA);
    34. printf("RSA_check_key() ret:%d \n", ret);
    35. char sText[] = "1234567890";
    36. unsigned char* pCipher = (unsigned char*)malloc(bytes);
    37. ret = RSA_public_encrypt(strlen(sText), (const unsigned char*)sText, pCipher, pRSA, RSA_PKCS1_PADDING);
    38. printf("RSA_public_encrypt() ret:%d \n", ret);
    39. if (ret <= 0)
    40. {
    41. unsigned long err = ERR_get_error();
    42. printf("err:[%ld] \n", err);
    43. char sBuf[128] = {0};
    44. char* pErrStr = ERR_error_string(err, sBuf);
    45. printf("errstr:[%s] \n", pErrStr);
    46. }
    47. unsigned char* pText = (unsigned char*)malloc(bytes);
    48. ret = RSA_private_decrypt(ret, (const unsigned char*)pCipher, pText, pRSA, RSA_PKCS1_PADDING);
    49. printf("RSA_private_decrypt() ret:%d \n", ret);
    50. if (ret > 0)
    51. {
    52. printf("text:[%s] \n", pText);
    53. }
    54. free(pCipher);
    55. free(pText);
    56. RSA_free(pRSA);
    57. return 0;
    58. }

    输出:

    1. RSA Private-Key: (512 bit, 2 primes)
    2. modulus:
    3. 00:9f:d4:b7:53:c9:22:30:8d:52:31:13:67:61:ce:
    4. 12:bc:25:85:44:94:0e:87:e2:b9:8c:87:dd:ca:d0:
    5. df:1c:84:51:c7:ac:ec:a3:3f:2b:48:81:74:18:22:
    6. 9a:c2:a8:11:03:8c:19:b6:a6:45:2d:81:d4:18:65:
    7. bb:90:59:e6:d5
    8. publicExponent: 3 (0x3)
    9. privateExponent:
    10. 6a:8d:cf:8d:30:c1:75:b3:8c:20:b7:9a:41:34:0c:
    11. 7d:6e:58:d8:62:b4:5a:97:26:5d:af:e9:31:e0:94:
    12. bd:ac:7d:e2:9e:a3:b3:4c:e9:23:41:bf:3c:ca:4d:
    13. 3e:ee:b6:f5:36:1c:7a:9c:2d:70:e3:20:94:53:b6:
    14. e9:0a:13:eb
    15. prime1:
    16. 00:d3:69:55:a1:b4:24:1d:11:56:18:3e:b4:bf:06:
    17. 23:05:69:d2:12:78:1e:b5:45:47:8c:3f:8a:6e:02:
    18. 48:d5:4d
    19. prime2:
    20. 00:c1:8a:69:55:62:27:b0:82:48:bc:fe:3e:67:de:
    21. 1e:f9:29:e8:dc:86:9d:4b:be:e5:96:fa:5d:bb:30:
    22. 81:f3:a9
    23. exponent1:
    24. 00:8c:f0:e3:c1:22:c2:be:0b:8e:ba:d4:78:7f:59:
    25. 6c:ae:46:8c:0c:50:14:78:d8:da:5d:7f:b1:9e:ac:
    26. 30:8e:33
    27. exponent2:
    28. 00:81:06:f0:e3:96:c5:20:56:db:28:a9:7e:ef:e9:
    29. 69:fb:71:45:e8:59:be:32:7f:43:b9:fc:3e:7c:cb:
    30. 01:4d:1b
    31. coefficient:
    32. 00:cb:09:a1:95:b6:64:0c:d0:50:50:58:cb:20:fd:
    33. bc:7c:e6:fb:56:22:73:75:34:7b:44:6d:a5:94:87:
    34. 59:8f:58
    35. RSA_generate_key_ex() ret:1
    36. RSA Private-Key: (512 bit, 2 primes)
    37. modulus:
    38. 00:ac:3b:05:ad:53:48:42:fb:8e:a0:52:53:29:71:
    39. 3b:30:a6:47:74:99:7b:9f:94:48:93:92:1f:57:78:
    40. 01:07:6c:db:bd:34:f0:c9:35:42:7e:20:c1:ec:94:
    41. 7d:0b:cc:c7:70:56:52:87:cc:04:66:30:4b:06:fb:
    42. 49:ee:78:eb:af
    43. publicExponent: 3 (0x3)
    44. privateExponent:
    45. 72:d2:03:c8:e2:30:2c:a7:b4:6a:e1:8c:c6:4b:7c:
    46. cb:19:84:f8:66:52:6a:62:db:0d:0c:14:e4:fa:ab:
    47. 5a:47:7a:64:2a:7b:1c:27:0b:c2:37:a0:7f:52:fc:
    48. 53:17:3e:ba:9f:cb:0b:4d:5b:94:0f:38:f1:97:67:
    49. eb:d7:a3:ab
    50. prime1:
    51. 00:d8:79:81:07:43:58:8f:a7:ab:db:04:bf:e5:a0:
    52. 03:35:7c:13:76:5b:22:2c:de:e0:c7:29:4b:66:65:
    53. e3:aa:ef
    54. prime2:
    55. 00:cb:ad:74:30:db:a2:21:33:21:76:28:d8:1c:ef:
    56. 26:b3:dc:53:2b:9b:b5:ce:29:38:ae:73:4c:c7:a6:
    57. d1:cb:41
    58. exponent1:
    59. 00:90:51:00:af:82:3b:0a:6f:c7:e7:58:7f:ee:6a:
    60. ac:ce:52:b7:a4:3c:c1:73:3f:40:84:c6:32:44:43:
    61. ed:1c:9f
    62. exponent2:
    63. 00:87:c8:f8:20:92:6c:16:22:16:4e:c5:e5:68:9f:
    64. 6f:22:92:e2:1d:12:79:34:1b:7b:1e:f7:88:85:19:
    65. e1:32:2b
    66. coefficient:
    67. 00:bd:69:e1:82:71:0e:e3:e6:bb:c3:55:2a:10:f7:
    68. b1:26:1e:c2:9a:d7:44:9f:88:be:aa:3e:7d:d1:7c:
    69. c0:94:ba
    70. copy pub key:0x203f770
    71. RSA Public-Key: (512 bit)
    72. Modulus:
    73. 00:ac:3b:05:ad:53:48:42:fb:8e:a0:52:53:29:71:
    74. 3b:30:a6:47:74:99:7b:9f:94:48:93:92:1f:57:78:
    75. 01:07:6c:db:bd:34:f0:c9:35:42:7e:20:c1:ec:94:
    76. 7d:0b:cc:c7:70:56:52:87:cc:04:66:30:4b:06:fb:
    77. 49:ee:78:eb:af
    78. Exponent: 3 (0x3)
    79. copy pri key:0x203f770
    80. RSA Private-Key: (512 bit, 2 primes)
    81. modulus:
    82. 00:ac:3b:05:ad:53:48:42:fb:8e:a0:52:53:29:71:
    83. 3b:30:a6:47:74:99:7b:9f:94:48:93:92:1f:57:78:
    84. 01:07:6c:db:bd:34:f0:c9:35:42:7e:20:c1:ec:94:
    85. 7d:0b:cc:c7:70:56:52:87:cc:04:66:30:4b:06:fb:
    86. 49:ee:78:eb:af
    87. publicExponent: 3 (0x3)
    88. privateExponent:
    89. 72:d2:03:c8:e2:30:2c:a7:b4:6a:e1:8c:c6:4b:7c:
    90. cb:19:84:f8:66:52:6a:62:db:0d:0c:14:e4:fa:ab:
    91. 5a:47:7a:64:2a:7b:1c:27:0b:c2:37:a0:7f:52:fc:
    92. 53:17:3e:ba:9f:cb:0b:4d:5b:94:0f:38:f1:97:67:
    93. eb:d7:a3:ab
    94. prime1:
    95. 00:d8:79:81:07:43:58:8f:a7:ab:db:04:bf:e5:a0:
    96. 03:35:7c:13:76:5b:22:2c:de:e0:c7:29:4b:66:65:
    97. e3:aa:ef
    98. prime2:
    99. 00:cb:ad:74:30:db:a2:21:33:21:76:28:d8:1c:ef:
    100. 26:b3:dc:53:2b:9b:b5:ce:29:38:ae:73:4c:c7:a6:
    101. d1:cb:41
    102. exponent1:
    103. 00:90:51:00:af:82:3b:0a:6f:c7:e7:58:7f:ee:6a:
    104. ac:ce:52:b7:a4:3c:c1:73:3f:40:84:c6:32:44:43:
    105. ed:1c:9f
    106. exponent2:
    107. 00:87:c8:f8:20:92:6c:16:22:16:4e:c5:e5:68:9f:
    108. 6f:22:92:e2:1d:12:79:34:1b:7b:1e:f7:88:85:19:
    109. e1:32:2b
    110. coefficient:
    111. 00:bd:69:e1:82:71:0e:e3:e6:bb:c3:55:2a:10:f7:
    112. b1:26:1e:c2:9a:d7:44:9f:88:be:aa:3e:7d:d1:7c:
    113. c0:94:ba
    114. bits:512
    115. bytes:64
    116. RSA_check_key() ret:1
    117. RSA_public_encrypt() ret:64
    118. RSA_private_decrypt() ret:10
    119. text:[1234567890]

    使用举例2:

    下面这个例子演示了公私钥的分开保存、读取,以及使用公私钥加解密。

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. namespace dakuang {}
    9. int main(int argc, char* argv[])
    10. {
    11. ERR_load_RSA_strings();
    12. RSA* pRSA = RSA_new();
    13. BIGNUM* pBNe = BN_new();
    14. BN_set_word(pBNe, RSA_3);
    15. int ret = RSA_generate_key_ex(pRSA, 512, pBNe, NULL);
    16. printf("RSA_generate_key_ex() ret:%d \n", ret);
    17. BN_free(pBNe);
    18. BIO* pBIOpri = BIO_new_file("rsa.key","w");
    19. BIO* pBIOpub = BIO_new_file("rsa.pub","w");
    20. ret = i2d_RSAPrivateKey_bio(pBIOpri, pRSA);
    21. printf("i2d_RSAPrivateKey_bio() ret:%d \n", ret);
    22. ret = i2d_RSAPublicKey_bio(pBIOpub, pRSA);
    23. printf("i2d_RSAPublicKey_bio() ret:%d \n", ret);
    24. BIO_free(pBIOpri);
    25. BIO_free(pBIOpub);
    26. RSA* pRSApri = RSA_new();
    27. RSA* pRSApub = RSA_new();
    28. BIO* pBIOpri2 = BIO_new_file("rsa.key","r");
    29. BIO* pBIOpub2 = BIO_new_file("rsa.pub","r");
    30. d2i_RSAPrivateKey_bio(pBIOpri2, &pRSApri);
    31. d2i_RSAPublicKey_bio(pBIOpub2, &pRSApub);
    32. BIO_free(pBIOpri2);
    33. BIO_free(pBIOpub2);
    34. int bytes = RSA_size(pRSApri);
    35. printf("copy' private key size:%d \n", bytes);
    36. int bytes2 = RSA_size(pRSApub);
    37. printf("copy' public key size:%d \n", bytes2);
    38. char sText[] = "1234567890";
    39. unsigned char* pCipher = (unsigned char*)malloc(bytes);
    40. ret = RSA_public_encrypt(strlen(sText), (const unsigned char*)sText, pCipher, pRSApub, RSA_PKCS1_PADDING);
    41. printf("RSA_public_encrypt() ret:%d \n", ret);
    42. if (ret <= 0)
    43. {
    44. unsigned long err = ERR_get_error();
    45. printf("err:[%ld] \n", err);
    46. char sBuf[128] = {0};
    47. char* pErrStr = ERR_error_string(err, sBuf);
    48. printf("errstr:[%s] \n", pErrStr);
    49. }
    50. unsigned char* pText = (unsigned char*)malloc(bytes);
    51. ret = RSA_private_decrypt(ret, (const unsigned char*)pCipher, pText, pRSApri, RSA_PKCS1_PADDING);
    52. printf("RSA_private_decrypt() ret:%d \n", ret);
    53. if (ret > 0)
    54. {
    55. printf("text:[%s] \n", pText);
    56. }
    57. free(pCipher);
    58. free(pText);
    59. RSA_free(pRSApri);
    60. RSA_free(pRSApub);
    61. RSA_free(pRSA);
    62. return 0;
    63. }

    输出:
    RSA_generate_key_ex() ret:1
    i2d_RSAPrivateKey_bio() ret:1
    i2d_RSAPublicKey_bio() ret:1
    copy' private key size:64
    copy' public key size:64
    RSA_public_encrypt() ret:64
    RSA_private_decrypt() ret:10
    text:[1234567890]

    使用举例3:

    下面这个例子演示了签名的生成和验证操作。


     

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. namespace dakuang {}
    9. void printHex(const unsigned char* pBuf, int nLen)
    10. {
    11. for (int i = 0; i < nLen; ++i)
    12. {
    13. printf("%02x", pBuf[i]);
    14. }
    15. printf("\n");
    16. }
    17. int main(int argc, char* argv[])
    18. {
    19. ERR_load_RSA_strings();
    20. RSA* pRSA = RSA_new();
    21. BIGNUM* pBNe = BN_new();
    22. BN_set_word(pBNe, RSA_3);
    23. int ret = RSA_generate_key_ex(pRSA, 512, pBNe, NULL);
    24. printf("ret:%d \n", ret);
    25. BN_free(pBNe);
    26. char sData[] = "1234567890";
    27. char sSign[512] = {0};
    28. unsigned int nSignLen = 512;
    29. ret = RSA_sign(NID_sha1, (unsigned char *)sData, 10, (unsigned char *)sSign, &nSignLen, pRSA);
    30. printf("RSA_sign() ret:%d \n", ret);
    31. printf("sign %d \n", nSignLen);
    32. printHex((const unsigned char*)sSign, nSignLen);
    33. //sSign[0] = 0;
    34. ret = RSA_verify(NID_sha1, (unsigned char *)sData, 10, (unsigned char *)sSign, nSignLen, pRSA);
    35. printf("RSA_verify() ret:%d \n", ret);
    36. RSA_free(pRSA);
    37. return 0;
    38. }

    输出:
    ret:1
    RSA_sign() ret:1

    sign 64
    4ec0af099c49646b72fda88a4fb11e8deb3898da9c3f611a5f25f05d9d005631858239bbb732cd5060dbc975363fc1b9cdfdc5a04554115a916f06f98163189f

    RSA_verify() ret:1

  • 相关阅读:
    【PyTorch】深度学习实践之CNN高级篇——实现复杂网络
    java计算机毕业设计基于安卓Android的校园单车租赁App(源码+系统+mysql数据库+Lw文档)
    vue 侦听器
    java毕业设计跨境电商网站源码+lw文档+mybatis+系统+mysql数据库+调试
    PostgreSQL JIT(Just-In-Time Compilation)With LLVM 的实现原理
    闲来无事,造了一个物联IOT平台
    【算法】中缀表达式转成后缀表达式(逆波兰表达式)再计算得出结果
    开发必备Liunx常用的几个命令
    芒果YOLOv8改进104:主干Backbone篇之DCNv3结构:即插即用|使用pytorch代码实现,并针对YOLOv8专门优化模块
    js获取最近7天的日期
  • 原文地址:https://blog.csdn.net/qicaiyuwu/article/details/127450507