openssl engine引擎 实现RSA引擎 (4)

openssl engine引擎 实现RSA引擎 (4)

通过对openssl rsa_st结构体进行重新赋值并导入到引擎中,在使用openssl与rsa相关的算法中都会调用引擎中的rsa算法

rsa算法中主要包括

  1. public_encrypto //公钥加密
  2. public_decrypto //公钥解密
  3. private_encrypto //私钥加密
  4. private_decrypto //私钥解密
  5. sign //签名
  6. verify //验签
  7. gen_key //生成密钥
rangine.h
#ifndef __RANG_ENG_H__
#define __RANG_ENG_H__
#include <openssl/engine.h>
#include <stdio.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/ecdh.h>
#include <openssl/crypto.h>
#include <string.h>

#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include <openssl/ssl.h>

const char *eng_id="randeng";
const char *eng_name="rand engines for OpenSSL";

/*需要声明一下结构体*/

typedef volatile int CRYPTO_REF_COUNT;
struct rsa_st {
    /*
     * The first parameter is used to pickup errors where this is passed
     * instead of an EVP_PKEY, it is set to 0
     */
    int pad;
    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;
    /* for multi-prime RSA, defined in RFC 8017 */
    STACK_OF(RSA_PRIME_INFO) *prime_infos;
    /* If a PSS only key this contains the parameter restrictions */
    RSA_PSS_PARAMS *pss;
    /* be careful using this if the RSA structure is shared */
    CRYPTO_EX_DATA ex_data;
    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;
    /*
     * all BIGNUM values are actually in the following data, if it is not
     * NULL
     */
    char *bignum_data;
    BN_BLINDING *blinding;
    BN_BLINDING *mt_blinding;
    CRYPTO_RWLOCK *lock;
};


struct rsa_meth_st {
    char *name;
    int (*rsa_pub_enc) (int flen, const unsigned char *from,
                        unsigned char *to, RSA *rsa, int padding);
    int (*rsa_pub_dec) (int flen, const unsigned char *from,
                        unsigned char *to, RSA *rsa, int padding);
    int (*rsa_priv_enc) (int flen, const unsigned char *from,
                         unsigned char *to, RSA *rsa, int padding);
    int (*rsa_priv_dec) (int flen, const unsigned char *from,
                         unsigned char *to, RSA *rsa, int padding);
    /* Can be null */
    int (*rsa_mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
    /* Can be null */
    int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
                       const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
    /* called at new */
    int (*init) (RSA *rsa);
    /* called at free */
    int (*finish) (RSA *rsa);
    /* RSA_METHOD_FLAG_* things */
    int flags;
    /* may be needed! */
    char *app_data;
    /*
     * New sign and verify functions: some libraries don't allow arbitrary
     * data to be signed/verified: this allows them to be used. Note: for
     * this to work the RSA_public_decrypt() and RSA_private_encrypt() should
     * *NOT* be used RSA_sign(), RSA_verify() should be used instead.
     */
    int (*rsa_sign) (int type,
                     const unsigned char *m, unsigned int m_length,
                     unsigned char *sigret, unsigned int *siglen,
                     const RSA *rsa);
    int (*rsa_verify) (int dtype, const unsigned char *m,
                       unsigned int m_length, const unsigned char *sigbuf,
                       unsigned int siglen, const RSA *rsa);
    /*
     * If this callback is NULL, the builtin software RSA key-gen will be
     * used. This is for behavioural compatibility whilst the code gets
     * rewired, but one day it would be nice to assume there are no such
     * things as "builtin software" implementations.
     */
    int (*rsa_keygen) (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
    int (*rsa_multi_prime_keygen) (RSA *rsa, int bits, int primes,
                                   BIGNUM *e, BN_GENCB *cb);
};


#endif // DEBUG
rangine.c
#include "rangeng.h"

static int myrand_init(ENGINE *e)
{
    printf("myrand_init\n");
    return 1;
}
static int myrand_finish(ENGINE *e)
{
    printf("myrand_finish\n");
    return 1;
}
static int myrand_destroy(ENGINE *e)
{
    printf("myrand_destroy\n");
    return 1;
}
//自己写的一个加密算法 askii+10
static int my_rsa_pub_enc(int flen, const unsigned char *from,
                        unsigned char *to, RSA *rsa, int padding)
{
    printf("my_rsa_pub_enc\n");
    for (int i = 0; i < flen; i++)
    {
        to[i]=from[i]+10;
    }
    return flen;
}

static int my_rsa_pub_dec(int flen, const unsigned char *from,
                        unsigned char *to, RSA *rsa, int padding)
{
    printf("my_rsa_pub_dec\n");
    for (int i = 0; i < flen; i++)
    {
        to[i]=from[i]-10;
    }
    return flen;
}

static int my_rsa_priv_enc(int flen, const unsigned char *from,
                        unsigned char *to, RSA *rsa, int padding)
{
    printf("my_rsa_priv_enc\n");
    return 1;
}

static int my_rsa_priv_dec(int flen, const unsigned char *from,
                        unsigned char *to, RSA *rsa, int padding)
{
    printf("my_rsa_priv_dec\n");
    return 1;
}

static int my_rsa_sign (int type,const unsigned char *m, unsigned int m_length,
unsigned char *sigret, unsigned int *siglen,const RSA *rsa)
{
    printf("my_rsa_sign\n");
    return 1;
}

static int my_rsa_verify (int type,const unsigned char *m, unsigned int m_length,
unsigned char *sigret, unsigned int *siglen,const RSA *rsa)
{
    printf("my_rsa_verify\n");
    return 1;
}

static int my_rsa_init(RSA *rsa)
{
    printf("my_rsa_init\n");
    return 1;
}

static int my_rsa_finish(RSA *rsa)
{
    printf("my_rsa_finish\n");
    return 1;
}

//对照引擎rsa_st结构体一一对应,必须保持参数一致
const RSA_METHOD rsa_method = {
    "rsa_engine_test",
    my_rsa_pub_enc,
    my_rsa_pub_dec,
    NULL,
    NULL,
    NULL,
    NULL,
    my_rsa_init,
    my_rsa_finish,
    ENGINE_METHOD_RSA,
    NULL,
    my_rsa_sign,
    my_rsa_verify,
    NULL,
    NULL
};

/*绑定函数*/
static int bind_pp(ENGINE *e)
{
     if(!ENGINE_set_id(e,eng_id)||
    !ENGINE_set_name(e,eng_name)||   
    !ENGINE_set_destroy_function(e,myrand_destroy)||
    !ENGINE_set_init_function(e,myrand_init)||
    !ENGINE_set_finish_function(e,myrand_finish)||
    !ENGINE_set_RSA(e,&rsa_method))
        return 0;
    printf("ERR_load_rsa success\n");
    return 1;
}


static ENGINE *enging_range(void)
{
    ENGINE*e =ENGINE_new();
    if(!e)
        return NULL;
    if(!bind_pp(e))
    {
        ENGINE_free(e);
		return NULL;
    }
    return e;
}
void ENGINE_load_rand()
{
    ENGINE* e=enging_range();
    if(!e)
        return ;
    ENGINE_add(e);
    ENGINE_free(e);
}
static void display_engine_list()
{
	ENGINE *h;
	int loop;
	
	h = ENGINE_get_first();
	loop = 0;
	printf("start:\n");
	while(h)
	{
		printf("engine %i, id = \"%s\", name = \"%s\"\n",
			loop++, ENGINE_get_id(h), ENGINE_get_name(h));
		h = ENGINE_get_next(h);
	}
	printf("end of list\n");
	ENGINE_free(h);
}

int main()
{
    
    // 初始化 OpenSSL 引擎系统
    ENGINE_load_builtin_engines();
    ENGINE_register_all_complete();
    //加载引擎
    ENGINE_load_rand();
    display_engine_list();	
    ENGINE *e=NULL;
    e=ENGINE_by_id(eng_id);
    if(!e)
    {
        printf("err load engine failed\n");
        return 0;
    }    

    ENGINE_init(e);
    printf("RSA-----BEGIN---END\n");
    ENGINE_register_RSA(e); //
    RSA *rsa = RSA_new();
    BIGNUM *bn = BN_new();
    BN_set_word(bn, RSA_F4);
    RSA_generate_key_ex(rsa, 2048, bn, NULL);
    printf("RSA Key Pair:\n");
    RSA_print_fp(stdout, rsa, 0); //打印密钥

    // 使用引擎进行 RSA 加密
    unsigned char plaintext[] = "Hello, World!";
    unsigned char ciphertext[256]={0}; // 注意,缓冲区大小可能需要根据您的密钥长度进行调整
    unsigned char plaintext1[256]={0};
    int len = RSA_public_encrypt(sizeof(plaintext), plaintext, ciphertext, rsa, RSA_PKCS1_PADDING);
    len=RSA_public_decrypt(len, ciphertext, plaintext1, rsa, RSA_PKCS1_PADDING);


    // 打印加密后的数据
    printf("Encrypted data: ");
    for (int i = 0; i < len; i++) {
        printf("%02x ", ciphertext[i]);
    }
    printf("\n");
    printf("ciphertext=%s\n",ciphertext);

    // 打印加密后的数据
    printf("decrypted data: ");
    for (int i = 0; i < len; i++) {
        printf("%02x ", plaintext1[i]);
    }
    printf("\n");
    printf("ciphertext=%s\n",plaintext1);
    // 清理引擎资源
    ENGINE_finish(e);
    ENGINE_free(e);
}

编译
gcc rangine.c -ldl -lpthread -lcrypto -lssl -o engINE
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用 OpenSSL 库可以更方便地实现 RSA 加密算法。以下是一个简单的示例程序,展示了如何使用 OpenSSL 库进行 RSA 1024 加密。 首先,需要安装 OpenSSL 库,并在程序中包含相应的头文件: ```c++ #include <openssl/rsa.h> #include <openssl/pem.h> ``` 接着,可以使用 OpenSSL 库中的函数生成 RSA 密钥对: ```c++ RSA *keypair = RSA_new(); BIGNUM *e = BN_new(); int bits = 1024; unsigned long e_value = RSA_F4; BN_set_word(e, e_value); RSA_generate_key_ex(keypair, bits, e, NULL); ``` 这里使用了 `RSA_new()` 函数创建了一个 RSA 结构体,使用 `BN_new()` 函数创建了一个大数结构体 `e`,表示公钥指数 `e` 的值,使用 `RSA_generate_key_ex()` 函数生成了 RSA 密钥对,其中 `bits` 表示密钥长度,`e` 表示公钥指数,`NULL` 表示使用默认的随机数生成器。 生成密钥对后,就可以使用公钥加密数据了。以下是一个示例函数,用于 RSA 加密: ```c++ // 使用公钥加密数据 // 返回加密后的数据长度,加密失败返回0 int rsa_encrypt(const unsigned char *src, int src_len, unsigned char *dst, RSA *key) { int flen = RSA_size(key); int ret = RSA_public_encrypt(src_len, src, dst, key, RSA_PKCS1_PADDING); if (ret != flen) { return 0; } return ret; } ``` 其中,`src` 表示要加密的数据,`src_len` 表示数据长度,`dst` 表示加密后的数据,`key` 表示公钥。 接着,可以使用私钥解密数据。以下是一个示例函数,用于 RSA 解密: ```c++ // 使用私钥解密数据 // 返回解密后的数据长度,解密失败返回0 int rsa_decrypt(const unsigned char *src, int src_len, unsigned char *dst, RSA *key) { int flen = RSA_size(key); int ret = RSA_private_decrypt(src_len, src, dst, key, RSA_PKCS1_PADDING); if (ret <= 0 || ret >= flen) { return 0; } return ret; } ``` 其中,`src` 表示要解密的数据,`src_len` 表示数据长度,`dst` 表示解密后的数据,`key` 表示私钥。 完整的示例程序如下: ```c++ #include <iostream> #include <cstring> #include <openssl/rsa.h> #include <openssl/pem.h> using namespace std; // 使用公钥加密数据 // 返回加密后的数据长度,加密失败返回0 int rsa_encrypt(const unsigned char *src, int src_len, unsigned char *dst, RSA *key) { int flen = RSA_size(key); int ret = RSA_public_encrypt(src_len, src, dst, key, RSA_PKCS1_PADDING); if (ret != flen) { return 0; } return ret; } // 使用私钥解密数据 // 返回解密后的数据长度,解密失败返回0 int rsa_decrypt(const unsigned char *src, int src_len, unsigned char *dst, RSA *key) { int flen = RSA_size(key); int ret = RSA_private_decrypt(src_len, src, dst, key, RSA_PKCS1_PADDING); if (ret <= 0 || ret >= flen) { return 0; } return ret; } int main() { RSA *keypair = RSA_new(); BIGNUM *e = BN_new(); int bits = 1024; unsigned long e_value = RSA_F4; BN_set_word(e, e_value); RSA_generate_key_ex(keypair, bits, e, NULL); // 输出公钥和私钥 BIO *bp_private = BIO_new(BIO_s_mem()); BIO *bp_public = BIO_new(BIO_s_mem()); PEM_write_bio_RSAPrivateKey(bp_private, keypair, NULL, NULL, 0, NULL, NULL); PEM_write_bio_RSAPublicKey(bp_public, keypair); char *private_key; char *public_key; long private_key_len = BIO_get_mem_data(bp_private, &private_key); long public_key_len = BIO_get_mem_data(bp_public, &public_key); cout << "Private Key: " << endl << string(private_key, private_key_len) << endl; cout << "Public Key: " << endl << string(public_key, public_key_len) << endl; // 加密 const unsigned char *msg = (const unsigned char *)"Hello, world!"; int msg_len = strlen((const char *)msg); unsigned char ciphertext[4096]; int ciphertext_len = rsa_encrypt(msg, msg_len, ciphertext, keypair); cout << "Encrypted Message: " << endl; for (int i = 0; i < ciphertext_len; i++) { printf("%02x", ciphertext[i]); } cout << endl; // 解密 unsigned char plaintext[4096]; int plaintext_len = rsa_decrypt(ciphertext, ciphertext_len, plaintext, keypair); cout << "Decrypted Message: " << endl; cout << string((const char *)plaintext, plaintext_len) << endl; RSA_free(keypair); BN_free(e); BIO_free_all(bp_private); BIO_free_all(bp_public); return 0; } ``` 该程序使用 OpenSSL 库生成 RSA 密钥对,并使用公钥加密和私钥解密数据。注意,为了方便输出公钥和私钥,该程序使用了 `PEM_write_bio_RSAPrivateKey()` 和 `PEM_write_bio_RSAPublicKey()` 函数将密钥转换成 PEM 格式输出。在实际应用中,可以直接使用 RSA 结构体表示密钥。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值