Openssl RSA使用n e d q p等私钥指数生成私钥

本文介绍了RSA算法的基本原理,包括公钥和私钥的概念。在OpenSSL中,详细阐述了如何通过n、e、d、q、p等私钥指数来生成私钥,特别强调了在操作BIGNUM结构体时的注意事项,如正确处理BIGNUM的复制和释放,以及如何使用OpenSSL提供的API进行RSA密钥的读写操作。
摘要由CSDN通过智能技术生成

RSA算法简述

n:模数
e:公钥指数
d:私钥指数
(n,e)是公钥,(n,d)是私钥

公钥:是公布出去给别人用的,可以被很多人获取。用来加密和验签
私钥:只能自己持有,并且不可以被其他人知道,用来解密和签名

openssl中私钥结构RSA定义如下。其中BIGNUM结构体存储了密钥的具体内容

struct rsa_st {
   
    /*
     * #legacy
     * The first field is used to pickup errors where this is passed
     * instead of an EVP_PKEY.  It is always zero.
     * THIS MUST REMAIN THE FIRST FIELD.
     */
    int dummy_zero;

    OSSL_LIB_CTX *libctx;
    int32_t version;
    const RSA_METHOD *meth;
    /* functional reference if 'meth' is ENGINE-provided */
    ENGINE *engine;
    BIGNUM *n;
    BIGNUM *e;
    BIGNUM *d;
    BIGNUM *p;
    BIGNUM *q;
    BIGNUM *dmp1;
    BIGNUM *dmq1;
    BIGNUM *iqmp;
   
    /*
     * If a PSS only key this contains the parameter restrictions.
     * There are two structures for the same thing, used in different cases.
     */
    /* This is used uniquely by OpenSSL provider implementations. */
    RSA_PSS_PARAMS_30 pss_params;

#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
    RSA_ACVP_TEST *acvp_test;
#endif

#ifndef FIPS_MODULE
    /* This is used uniquely by rsa_ameth.c and rsa_pmeth.c. */
    RSA_PSS_PARAMS *pss;
    /* for multi-prime RSA, defined in RFC 8017 */
    STACK_OF(RSA_PRIME_INFO) *prime_infos;
    /* Be careful using this if the RSA structure is shared */
    CRYPTO_EX_DATA ex_data;
#endif
    CRYPTO_REF_COUNT references;
    int flags;
    /* Used to cache montgomery values */
    BN_MONT_CTX *_method_mod_n;
    BN_MONT_CTX *_method_mod_p;
    BN_MONT_CTX *_method_mod_q;
    BN_BLINDING *blinding;
    BN_BLINDING *mt_blinding;
    CRYPTO_RWLOCK *lock;

    int dirty_cnt;
};

openssl基础操作

API

基础

//初始化一个RSA结构
RSA * RSA_new(void);
 
//RSA私钥产生函数
//产生一个模为num位的密钥对,e为公开的加密指数,一般为65537(0x10001)
RSA *RSA_generate_key(int num, unsigned long e,void (*callback)(int,int,void *), void *cb_arg);

/*  flen: 要加密信息长度
    from: 要加密信息
    to: 加密后的信息
    padding: 采取的加密方案, 分为: RSA_PKCS1_PADDING, RSA_PKCS1_OAEP_PADDING, RSA_SSLV23_PADDING, RSA_NO_PADDING  */
int RSA_public_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding);

/*  flen: 要解密的信息长度
    from: 要解密的信息
    to: 解密后的信息
    padding: 采取的解密方案 */
int RSA_private_decrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding);

//释放一个RSA结构
void RSA_free(RSA *rsa);

//判断位数函数, 返回RSA模的位数
int RSA_size(const RSA *rsa);

//测试RSA是否合法可用
int RSA_check_key(RSA *rsa);

读写

//RSA 私钥读写
RSA *     
你可以使用OpenSSL库来读取RSA私钥文件,并将其转换为JWK格式。以下是一个简单的示例代码,你可以根据自己的需要进行修改: ```c++ #include <openssl/rsa.h> #include <openssl/pem.h> #include <openssl/evp.h> #include <openssl/bio.h> #include <openssl/buffer.h> #include <iostream> // 将二进制数据编码为Base64字符串 std::string base64_encode(const unsigned char* input, size_t length) { BIO *bmem = nullptr, *b64 = nullptr; BUF_MEM *bptr = nullptr; b64 = BIO_new(BIO_f_base64()); bmem = BIO_new(BIO_s_mem()); b64 = BIO_push(b64, bmem); BIO_write(b64, input, length); BIO_flush(b64); BIO_get_mem_ptr(b64, &bptr); std::string result(bptr->data, bptr->length - 1); BIO_free_all(b64); return result; } int main() { RSA *rsa = nullptr; EVP_PKEY *pkey = nullptr; std::string private_key_file = "/path/to/private/key/file.pem"; // 读取RSA私钥文件 FILE *fp = fopen(private_key_file.c_str(), "rb"); if (!fp) { std::cerr << "Failed to open private key file." << std::endl; return 1; } rsa = PEM_read_RSAPrivateKey(fp, nullptr, nullptr, nullptr); fclose(fp); if (!rsa) { std::cerr << "Failed to load RSA private key." << std::endl; return 1; } // 将RSA私钥转换为EVP格式 pkey = EVP_PKEY_new(); if (!pkey) { std::cerr << "Failed to create EVP_PKEY object." << std::endl; return 1; } if (EVP_PKEY_assign_RSA(pkey, rsa) != 1) { std::cerr << "Failed to assign RSA to EVP_PKEY." << std::endl; EVP_PKEY_free(pkey); return 1; } // 将EVP格式私钥转换为JWK格式 std::cout << "{"; std::cout << "\"kty\": \"RSA\","; std::cout << "\"n\": \"" << base64_encode(rsa->n->data, rsa->n->length) << "\","; std::cout << "\"e\": \"" << base64_encode(rsa->e->data, rsa->e->length) << "\","; std::cout << "\"d\": \"" << base64_encode(rsa->d->data, rsa->d->length) << "\","; std::cout << "\"p\": \"" << base64_encode(rsa->p->data, rsa->p->length) << "\","; std::cout << "\"q\": \"" << base64_encode(rsa->q->data, rsa->q->length) << "\","; std::cout << "\"dp\": \"" << base64_encode(rsa->dmp1->data, rsa->dmp1->length) << "\","; std::cout << "\"dq\": \"" << base64_encode(rsa->dmq1->data, rsa->dmq1->length) << "\","; std::cout << "\"qi\": \"" << base64_encode(rsa->iqmp->data, rsa->iqmp->length) << "\""; std::cout << "}" << std::endl; // 释放资源 EVP_PKEY_free(pkey); RSA_free(rsa); return 0; } ``` 在上面的代码中,我们首先使用PEM_read_RSAPrivateKey函数从私钥文件中读取RSA私钥,然后将其转换为EVP_PKEY格式。最后,我们将EVP_PKEY格式的私钥转换为JWK格式,并使用base64_encode函数将二进制数据编码为Base64字符串。 需要注意的是,JWK格式中的各个字段都需要进行Base64编码。在上面的代码中,我们使用了base64_encode函数来实现这一功能。你需要自己实现这个函数或者使用现成的Base64库来完成编码操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值