最近项目中需要通过C语言实现RSA算法,这里我通过Mbedtls库来进行实现。
1、下载Mbedtls
首先我们将Mbedtls代码放入到工程中,相关传送门如下:
官方网址是国外的下载慢,所以也附上本文使用到的Mbedtls代码,传送门如下:
2、引入Mbedtls头文件
这里我们在工程中的CMakeLists.txt中引入Mbedtls的头文件,代码如下:
# for debug
# add_compile_options(-g)
project("device-authentication")
cmake_minimum_required(VERSION 3.5)
INCLUDE_DIRECTORIES(
../include/
../../src/net/mbedtls/include
../../src/smalgo/sms4/include
)
SET(my_src_crypto
../../src/net/mbedtls/library/aes.c
../../src/net/mbedtls/library/aesni.c
../../src/net/mbedtls/library/base64.c
../../src/net/mbedtls/library/rsa.c
../../src/net/mbedtls/library/rsa_internal.c
../../src/net/mbedtls/library/entropy.c
../../src/net/mbedtls/library/entropy_poll.c
../../src/net/mbedtls/library/bignum.c
../../src/net/mbedtls/library/sha1.c
../../src/net/mbedtls/library/sha256.c
../../src/net/mbedtls/library/sha512.c
../../src/net/mbedtls/library/md.c
../../src/net/mbedtls/library/md5.c
../../src/net/mbedtls/library/md_wrap.c
../../src/net/mbedtls/library/ripemd160.c
../../src/net/mbedtls/library/platform_util.c
../../src/net/mbedtls/library/oid.c
../../src/net/mbedtls/library/timing.c
../../src/net/mbedtls/library/net_sockets.c
../../src/smalgo/sms4/cbc128.c
../../src/smalgo/sms4/sms4_cbc.c
../../src/smalgo/sms4/sms4_common.c
../../src/smalgo/sms4/sms4_enc.c
../../src/smalgo/sms4/sms4_setkey.c
)
SET(my_src_crypto_dbg
../../src/net/mbedtls/library/ctr_drbg.c
)
SET(SRC_LIST_ENCRYPT_BIN
oem_porting.c
sdk_porting.c
authref.c
test.c
${my_src_crypto}
${my_src_crypto_dbg}
)
SET(SRC_LIST_DECRYPT_LIB
oem_porting.c
sdk_porting.c
authref.c
auth.c
${my_src_crypto}
${my_src_crypto_dbg}
)
#SET(SRC_LIST_AUTH_DEV
# oem_porting.c
# sdk_porting.c
# authref.c
# ${my_src_crypto}
# ${my_src_crypto_dbg}
#)
add_definitions(-fPIC)
#ADD_LIBRARY(authd STATIC ${SRC_LIST_AUTH_DEV})
ADD_LIBRARY(authoal STATIC ${SRC_LIST_DECRYPT_LIB})
ADD_EXECUTABLE(eaidkAuth ${SRC_LIST_ENCRYPT_BIN})
工程结构如下:
引入完成之后我们就可以开始RSA代码编写。
3、RSA代码编写
authref.h 头文件代码如下:
#ifndef __AUTHREF_H__
#define __AUTHREF_H__
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#undef DEBUG
#define RSA_KEY_SIZE 1024 // RSA 公钥的位数
#define EXPONENT 65537
#define BUFFER_SIZE 1024
#define RSA_KEY_LEN 256
#define AES_KEY_DEC_LEN 8
#define LICENSE_DEC_LEN 64
typedef struct __rsa
{
uint8_t buf[BUFFER_SIZE*8];
uint8_t* rsa_n;
uint8_t* rsa_e;
uint8_t* rsa_d;
uint8_t* rsa_p;
uint8_t* rsa_q;
uint8_t* rsa_dp;
uint8_t* rsa_dq;
uint8_t* rsa_qp;
uint32_t n_len;
uint32_t e_len;
uint32_t d_len;
uint32_t p_len;
uint32_t q_len;
uint32_t dp_len;
uint32_t dq_len;
uint32_t qp_len;
}T_rsa;
void generate_rsa(T_rsa* r);
void init_rsa_keys(T_rsa* rsa);
void rsa_encrypt( const T_rsa *r,
const unsigned char* plaintext,
unsigned int plaintext_size,
unsigned char *ciphertext,
size_t *ciphertext_size);
void rsa_decrypt(
const T_rsa *r,
const unsigned char* ciphertext,
//unsigned int ciphertext_size,
unsigned char *plaintext,
size_t *plaintext_size);
#ifdef __cplusplus
}
#endif
#endif //__AUTHREF_H__
authref.c 代码如下:
#include "authref.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/rsa.h"
#define RSA_KEY_SIZE 1024 // RSA 公钥的位数
#define EXPONENT 65537
#define BUFFER_SIZE 1024
#define RSA_KEY_LEN 256
#define AES_KEY_DEC_LEN 8
#define LICENSE_DEC_LEN 64
void generate_rsa(T_rsa* r)
{
mbedtls_rsa_context rsa;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
mbedtls_rsa_gen_key(&rsa, mbedtls_ctr_drbg_random, &ctr_drbg, RSA_KEY_SIZE, EXPONENT);
mbedtls_mpi_write_binary(&rsa.N, r->rsa_n, BUFFER_SIZE);
mbedtls_mpi_write_binary(&rsa.E, r->rsa_e, BUFFER_SIZE);
mbedtls_mpi_write_binary(&rsa.D, r->rsa_d, BUFFER_SIZE);
mbedtls_mpi_write_binary(&rsa.P, r->rsa_p, BUFFER_SIZE);
mbedtls_mpi_write_binary(&rsa.Q, r->rsa_q, BUFFER_SIZE);
mbedtls_mpi_write_binary(&rsa.DP, r->rsa_dp, BUFFER_SIZE);
mbedtls_mpi_write_binary(&rsa.DQ, r->rsa_dq, BUFFER_SIZE);
mbedtls_mpi_write_binary(&rsa.QP, r->rsa_qp, BUFFER_SIZE);
mbedtls_rsa_free(&rsa);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
}
void init_rsa_keys(T_rsa *rsa) {
memset(rsa->buf, 0, BUFFER_SIZE * 8);
rsa->rsa_n = &rsa->buf[BUFFER_SIZE * 0];
rsa->rsa_e = &rsa->buf[BUFFER_SIZE * 1];
rsa->rsa_d = &rsa->buf[BUFFER_SIZE * 2];
rsa->rsa_p = &rsa->buf[BUFFER_SIZE * 3];
rsa->rsa_q = &rsa->buf[BUFFER_SIZE * 4];
rsa->rsa_dp = &rsa->buf[BUFFER_SIZE * 5];
rsa->rsa_dq = &rsa->buf[BUFFER_SIZE * 6];
rsa->rsa_qp = &rsa->buf[BUFFER_SIZE * 7];
rsa->n_len = BUFFER_SIZE;
rsa->e_len = BUFFER_SIZE;
rsa->d_len = BUFFER_SIZE;
rsa->p_len = BUFFER_SIZE;
rsa->q_len = BUFFER_SIZE;
rsa->dp_len = BUFFER_SIZE;
rsa->dq_len = BUFFER_SIZE;
rsa->qp_len = BUFFER_SIZE;
}
// 加密
void rsa_encrypt(
const T_rsa *r,
const unsigned char *plaintext,
unsigned int plaintext_size,
unsigned char *ciphertext,
size_t *ciphertext_size) {
mbedtls_rsa_context rsa;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
int rett = 0;
mbedtls_entropy_init(&entropy);
//assert(mbedtls_ctr_drbg_init(&ctr_drbg, mbedtls_entropy_func, &entropy, nullptr, 0) == 0);
mbedtls_ctr_drbg_init(&ctr_drbg);
assert(mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) == 0);
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
assert(mbedtls_mpi_read_binary(&rsa.N, r->rsa_n, BUFFER_SIZE) == 0);
assert(mbedtls_mpi_read_binary(&rsa.E, r->rsa_e, BUFFER_SIZE) == 0);
*ciphertext_size = rsa.len = (mbedtls_mpi_bitlen(&rsa.N) + 7) >> 3;
//assert(mbedtls_rsa_pkcs1_encrypt(&rsa, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PUBLIC, plaintext_size, plaintext, ciphertext) == 0);
rett = mbedtls_rsa_pkcs1_encrypt(&rsa, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PUBLIC, plaintext_size,
plaintext, ciphertext);
assert(rett == 0);
mbedtls_rsa_free(&rsa);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
}
// 解密
void rsa_decrypt(
const T_rsa *r,
const unsigned char *ciphertext,
//unsigned int ciphertext_size,
unsigned char *plaintext,
size_t *plaintext_size) {
mbedtls_rsa_context rsa;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_init(&entropy);
//assert(mbedtls_ctr_drbg_init(&ctr_drbg, mbedtls_entropy_func, &entropy, nullptr, 0) == 0);
mbedtls_ctr_drbg_init(&ctr_drbg);
assert(mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) == 0);
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
assert(mbedtls_mpi_read_binary(&rsa.N, r->rsa_n, BUFFER_SIZE) == 0);
assert(mbedtls_mpi_read_binary(&rsa.E, r->rsa_e, BUFFER_SIZE) == 0);
assert(mbedtls_mpi_read_binary(&rsa.D, r->rsa_d, BUFFER_SIZE) == 0);
assert(mbedtls_mpi_read_binary(&rsa.P, r->rsa_p, BUFFER_SIZE) == 0);
assert(mbedtls_mpi_read_binary(&rsa.Q, r->rsa_q, BUFFER_SIZE) == 0);
assert(mbedtls_mpi_read_binary(&rsa.DP, r->rsa_dp, BUFFER_SIZE) == 0);
assert(mbedtls_mpi_read_binary(&rsa.DQ, r->rsa_dq, BUFFER_SIZE) == 0);
assert(mbedtls_mpi_read_binary(&rsa.QP, r->rsa_qp, BUFFER_SIZE) == 0);
rsa.len = (mbedtls_mpi_bitlen(&rsa.N) + 7) >> 3;
assert(mbedtls_rsa_pkcs1_decrypt(&rsa, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PRIVATE, plaintext_size,
ciphertext, plaintext, *plaintext_size) == 0);
mbedtls_rsa_free(&rsa);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
}
int do_ras_encrypt(authhandle *hdl, uint8_t contract_id[CONTRACTID_LEN], uint8_t user_id[USERID_LEN],
uint8_t uid[FINAL_UID_LEN]) {
T_rsa r;
uint8_t uid_local[UID_LEN];
uint8_t ciphertext[SN_LEN];
size_t ciphertext_len = SN_LEN;
GenRawUID(hdl, contract_id, user_id, uid_local);
//encryp UID
init_rsa_keys(&r);
if (hdl->callback_func.GetServerPublicKey) {
hdl->callback_func.GetServerPublicKey(r.buf);
} else {
GetServerPublicKey(hdl, r.buf); //load 2048 bytes for public key
}
rsa_encrypt(&r, uid_local, UID_LEN, ciphertext, &ciphertext_len);
//printf("ciphertext_len: %ld\n", ciphertext_len);
//copy SWID
#if 0
int i;
printf("CipherUID: ");
for(i = 0; i < FINAL_UID_LEN; ++i){
printf("%02x, ", uid[i]);
}
printf("\n");
#endif
return 0; //OK
}
生成RSA公私钥的伪代码如下:
T_rsa r;
uint8_t pub_key[2048] = { 0 };
uint8_t prv_key[8192] = { 0 };
init_rsa_keys(&r);
generate_rsa(&r);
//1. public key
memcpy(pub_key, r.buf, 2048);
//2. private key
memcpy(prv_key, r.buf, 8192);
RSA加密代码如下:
int do_ras_encrypt(authhandle *hdl, uint8_t contract_id[CONTRACTID_LEN], uint8_t user_id[USERID_LEN],
uint8_t uid[FINAL_UID_LEN]) {
T_rsa r;
uint8_t uid_local[UID_LEN];
uint8_t ciphertext[SN_LEN];
size_t ciphertext_len = SN_LEN;
//encryp UID
init_rsa_keys(&r);
if (hdl->callback_func.GetServerPublicKey) {
hdl->callback_func.GetServerPublicKey(r.buf);
} else {
GetServerPublicKey(hdl, r.buf); //load 2048 bytes for public key
}
rsa_encrypt(&r, uid_local, UID_LEN, ciphertext, &ciphertext_len);
//printf("ciphertext_len: %ld\n", ciphertext_len);
//copy SWID
#if 0
int i;
printf("CipherUID: ");
for(i = 0; i < FINAL_UID_LEN; ++i){
printf("%02x, ", uid[i]);
}
printf("\n");
#endif
return 0; //OK
}
解密代码如下:
static int SetServerPrivateKey(T_rsa *r, uint8_t *prv_key)
{
memcpy(r->buf, prv_key, 8192);
//memset(&r->buf[0], 0, 1024-128);
//memset(&r->buf[1024], 0, 1024-4);
//memset(&r->buf[2048], 0, 1024-128);
//memset(&r->buf[3072], 0, 1024-64);
//memset(&r->buf[4096], 0, 1024-64);
//memset(&r->buf[5120], 0, 1024-64);
//memset(&r->buf[6144], 0, 1024-64);
//memset(&r->buf[7168], 0, 1024-64);
return 0; //OK
}
JNIEXPORT jbyteArray JNICALL Java_com_openailab_oascloud_security_jni_cloud_CloudAuthJNI_decrypUidOnServer
(JNIEnv *env, jobject obj, jstring uidEnc, jbyteArray privateKey)
{
uint8_t *uid_enc = (*env)->GetStringUTFChars(env, uidEnc, NULL);
uint8_t *private_key = (*env)->GetByteArrayElements(env, privateKey, NULL);
jbyteArray ret = NULL;
T_rsa r;
uint8_t plaintext[UID_LEN];
size_t plaintext_len = 256;
uint8_t UID_Recover[SN_LEN];
uint8_t uid_enc_c[FINAL_UID_LEN];
init_rsa_keys(&r);
SetServerPrivateKey(&r, private_key);
hex2array(uid_enc, FINAL_UID_LEN * 2, uid_enc_c);
recover(&uid_enc_c[FINAL_UID_LEN - SN_LEN], UID_Recover, SN_LEN);
rsa_decrypt(&r, UID_Recover, plaintext, &plaintext_len);
/*printf("plaintext=\n");
for (size_t i = 0; i < UID_LEN; i++)
{
if (i > 0 && i % 16 == 0) {
printf("\n");
}
printf("%02x,", plaintext[i]);
}
printf("\n");*/
ret = (*env)->NewByteArray(env, UID_LEN);
(*env)->SetByteArrayRegion(env, ret, 0, UID_LEN, (jbyte*)plaintext);
(*env)->ReleaseByteArrayElements(env, privateKey, private_key, 0);
(*env)->ReleaseStringUTFChars(env, uidEnc, uid_enc);
return ret;
}
到此C语言RSA加解密就介绍完毕了。
张志翔 博客专家 发布了343 篇原创文章 · 获赞 376 · 访问量 36万+ 关注