1. 程式人生 > >基於mbedtls-1.3.14庫的rsa公鑰與私鑰生成與加解密,base64編碼與解碼用法介紹

基於mbedtls-1.3.14庫的rsa公鑰與私鑰生成與加解密,base64編碼與解碼用法介紹

1.1 之前總結了一篇關於AES加密與解密,base64編碼與解碼用法介紹,順便把rsa的用法也總結一下

1.2 用法

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "polarssl/base64.h"
#include "polarssl/entropy.h"
#include "polarssl/ctr_drbg.h"
#include "polarssl/rsa.h"

#define DEBUG_INFO(fmt, args...) printf("\033[33m[%s:%s:%d]\033[0m "#fmt"\r\n", __FILE__,__FUNCTION__, __LINE__, ##args)

#define KEY_SIZE 1024
#define BUFFER_SIZE 1024
#define EXPONENT 65537
//公鑰
uint8_t rsa_n[BUFFER_SIZE];

uint8_t rsa_e[BUFFER_SIZE];
uint8_t rsa_d[BUFFER_SIZE];
uint8_t rsa_p[BUFFER_SIZE];
uint8_t rsa_q[BUFFER_SIZE];
uint8_t rsa_dp[BUFFER_SIZE];
uint8_t rsa_dq[BUFFER_SIZE];
uint8_t rsa_qp[BUFFER_SIZE];

//公鑰長度
int RSA_N_Len; 

uint8_t PubKey[1024]; 
char PubPem[2048]={0};

//讀取rsa key
int ReadRsaKey(void)
{
    int ret = 0;
    rsa_context rsa;
    FILE *fpriv;

    RSA_N_Len = 0;
	memset(rsa_n , 0 ,BUFFER_SIZE);
	memset(rsa_e , 0 ,BUFFER_SIZE);
	memset(rsa_d , 0 ,BUFFER_SIZE);
	memset(rsa_p , 0 ,BUFFER_SIZE);
	memset(rsa_q , 0 ,BUFFER_SIZE);
	memset(rsa_dp, 0 ,BUFFER_SIZE);
	memset(rsa_dq, 0 ,BUFFER_SIZE);
	memset(rsa_qp, 0 ,BUFFER_SIZE);
    
    rsa_init(&rsa, RSA_PKCS_V15, 0);
    if (( fpriv = fopen("./rsa_key.txt", "rb")) == NULL)  {
        DEBUG_INFO("fopen rsa file failed\n");
        ret = -1;
        goto exit;
    }
    
     if( ( ret = mpi_read_file( &rsa.N , 16, fpriv ) ) != 0 ||
        ( ret = mpi_read_file( &rsa.E , 16, fpriv) ) != 0 ||
        ( ret = mpi_read_file( &rsa.D , 16, fpriv) ) != 0 ||
        ( ret = mpi_read_file( &rsa.P , 16, fpriv ) ) != 0 ||
        ( ret = mpi_read_file( &rsa.Q , 16, fpriv ) ) != 0 ||
        ( ret = mpi_read_file( &rsa.DP, 16, fpriv ) ) != 0 ||
        ( ret = mpi_read_file( &rsa.DQ, 16, fpriv ) ) != 0 ||
        ( ret = mpi_read_file( &rsa.QP, 16, fpriv ) ) != 0 ) {
        DEBUG_INFO("read rsa file failed\n");
        ret = -1;
        goto exit;
    }

    mpi_write_binary(&rsa.N, rsa_n , BUFFER_SIZE);
	mpi_write_binary(&rsa.E, rsa_e , BUFFER_SIZE);
	mpi_write_binary(&rsa.D, rsa_d , BUFFER_SIZE);
	mpi_write_binary(&rsa.P, rsa_p , BUFFER_SIZE);
	mpi_write_binary(&rsa.Q, rsa_q , BUFFER_SIZE);
	mpi_write_binary(&rsa.DP, rsa_dp ,BUFFER_SIZE);
	mpi_write_binary(&rsa.DQ, rsa_dq, BUFFER_SIZE);
	mpi_write_binary(&rsa.QP, rsa_qp , BUFFER_SIZE);

    RSA_N_Len = (mpi_msb(&rsa.N)+7) >> 3;
	memset(PubKey , 0 , BUFFER_SIZE);	
	memcpy(PubKey , &rsa_n[1024-RSA_N_Len] , RSA_N_Len);
	int  n;
    #if 1
	for( n= 1024-RSA_N_Len; n< 1024 ;n++) {
		printf("%02x" , rsa_n[n]);
	}
	printf("\n");
    #endif
    
exit:
    if (fpriv) {
        fclose(fpriv);
    }
    rsa_free(&rsa);
    return ret;
}


//生成或者讀取rsa公鑰與私鑰
int CreateRsaKey(void)
{
    int ret = -1;

    ret = ReadRsaKey();
    if (ret == 0) {
        DEBUG_INFO("ret=%d",ret);
        return ret;
    }

    DEBUG_INFO("ret=%d",ret);
    
	RSA_N_Len = 0;
	memset(rsa_n , 0 ,BUFFER_SIZE);
	memset(rsa_e , 0 ,BUFFER_SIZE);
	memset(rsa_d , 0 ,BUFFER_SIZE);
	memset(rsa_p , 0 ,BUFFER_SIZE);
	memset(rsa_q , 0 ,BUFFER_SIZE);
	memset(rsa_dp, 0 ,BUFFER_SIZE);
	memset(rsa_dq, 0 ,BUFFER_SIZE);
	memset(rsa_qp, 0 ,BUFFER_SIZE);
	rsa_context rsa;
	entropy_context entropy;
	ctr_drbg_context ctr_drbg;
	const char *pers = "rsa_genkey";
	entropy_init(&entropy);
	
	if((ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,(const unsigned char *) pers, strlen( pers))) != 0) {
   
        DEBUG_INFO( " failed ! ctr_drbg_init returned %d\n", ret );
        goto exit;
    }
	DEBUG_INFO( " ok  . Generating the RSA key [ %d-bit ]...\n", KEY_SIZE);
	rsa_init( &rsa, RSA_PKCS_V15, 0 );
	if ((ret = rsa_gen_key( &rsa, ctr_drbg_random, &ctr_drbg, KEY_SIZE, EXPONENT)) != 0) {
		DEBUG_INFO( " failed	! rsa_gen_key returned %d\n\n", ret );
		goto exit;
	}
	
	mpi_write_binary(&rsa.N, rsa_n , BUFFER_SIZE);
	mpi_write_binary(&rsa.E, rsa_e , BUFFER_SIZE);
	mpi_write_binary(&rsa.D, rsa_d , BUFFER_SIZE);
	mpi_write_binary(&rsa.P, rsa_p , BUFFER_SIZE);
	mpi_write_binary(&rsa.Q, rsa_q , BUFFER_SIZE);
	mpi_write_binary(&rsa.DP, rsa_dp ,BUFFER_SIZE);
	mpi_write_binary(&rsa.DQ, rsa_dq, BUFFER_SIZE);
	mpi_write_binary(&rsa.QP, rsa_qp , BUFFER_SIZE);
	RSA_N_Len = (mpi_msb(&rsa.N)+7) >> 3;
	memset(PubKey , 0 , BUFFER_SIZE);	
	memcpy(PubKey , &rsa_n[1024-RSA_N_Len] , RSA_N_Len);
	int  n;
	DEBUG_INFO("rsa.N: ");
	for( n= 1024-RSA_N_Len; n< 1024 ;n++) {
		printf("%02x" , rsa_n[n]);
	}
	printf("\n");
	FILE * fpriv = NULL;
	if ((fpriv = fopen("./rsa_key.txt", "wb+")) == NULL) {
        ret = 1;
        goto exit;
    }
	 if( ( ret = mpi_write_file( "N = " , &rsa.N , 16, fpriv ) ) != 0 ||
        ( ret = mpi_write_file( "E = " , &rsa.E , 16, fpriv ) ) != 0 ||
        ( ret = mpi_write_file( "D = " , &rsa.D , 16, fpriv ) ) != 0 ||
        ( ret = mpi_write_file( "P = " , &rsa.P , 16, fpriv ) ) != 0 ||
        ( ret = mpi_write_file( "Q = " , &rsa.Q , 16, fpriv ) ) != 0 ||
        ( ret = mpi_write_file( "DP = ", &rsa.DP, 16, fpriv ) ) != 0 ||
        ( ret = mpi_write_file( "DQ = ", &rsa.DQ, 16, fpriv ) ) != 0 ||
        ( ret = mpi_write_file( "QP = ", &rsa.QP, 16, fpriv ) ) != 0 )  {
        DEBUG_INFO( " failed  ! mpi_write_file returned %d\n", ret );
        goto exit;
    }
exit:
	if( fpriv != NULL ) {
        fclose( fpriv );
	}
	rsa_free( &rsa );
    ctr_drbg_free( &ctr_drbg );
    entropy_free( &entropy );
	return ret;
}

//rsa 用私鑰解密
int RsaDecrypt(const unsigned      char *InBuf , unsigned char* OutBuf)
{
	int ret, c;
	size_t i;
	rsa_context rsa;
	entropy_context entropy;
	ctr_drbg_context ctr_drbg;
	const unsigned char *pers = "rsa_decrypt";
	ret = 1;
	entropy_init(&entropy);
	if(( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy, (const unsigned char *) pers,strlen(pers))) != 0)  {
        DEBUG_INFO( " failed\n  ! ctr_drbg_init returned %d\n", ret );
        goto exit;
    }
	rsa_init(&rsa , RSA_PKCS_V15 , 0);
	mpi_read_binary(&rsa.N , rsa_n , BUFFER_SIZE);
	mpi_read_binary(&rsa.E , rsa_e , BUFFER_SIZE);
	mpi_read_binary(&rsa.D , rsa_d , BUFFER_SIZE);
	mpi_read_binary(&rsa.P , rsa_p , BUFFER_SIZE);
	mpi_read_binary(&rsa.Q , rsa_q , BUFFER_SIZE);
	mpi_read_binary(&rsa.DP , rsa_dp , BUFFER_SIZE);
	mpi_read_binary(&rsa.DQ , rsa_dq , BUFFER_SIZE);
	mpi_read_binary(&rsa.QP , rsa_qp , BUFFER_SIZE);
	rsa.len = (mpi_msb(&rsa.N)+7) >> 3;
	DEBUG_INFO("rsa.len: %d\n", rsa.len);
	if( ( ret = rsa_pkcs1_decrypt( &rsa, ctr_drbg_random, &ctr_drbg, RSA_PRIVATE, &i, InBuf, OutBuf, 1024)) != 0 )
    {
        DEBUG_INFO( " failed\n  ! rsa_pkcs1_decrypt returned %d\n\n", ret );
        goto exit;
    }
    DEBUG_INFO( "The RSA decrypted OutBuf is: '%s'\n\n", OutBuf);
    
exit:
	rsa_free( &rsa );
    ctr_drbg_free( &ctr_drbg );
    entropy_free( &entropy );
	return ret;
}


//base64解碼,rsa私鑰解密
int Base64DeAndRsa(const unsigned char *Base64, unsigned char *OutBuf)
{
    int ret = -1;
	size_t num =0;
	char DataOut2[8000]={0};
	base64_decode(NULL , &num , Base64 , strlen(Base64));
	ret = base64_decode(DataOut2 , &num , Base64 , strlen(Base64));
	if (ret != 0) {
        DEBUG_INFO("base64 decode failed,ret=%d",ret);
        return ret;
    }
	
	ret = RsaDecrypt(DataOut2, OutBuf);
	return ret;
}


//公鑰轉換pkcs1輸出
void RsaNToPkcs1(char * PemData)
{	 
	char DataOut[1024]={0};
	char PkcsANS[512]={0};
	uint8_t Head[]=  {
		0x30 , 0x81 ,0x9F ,0x30 ,0x0D ,0x06 , 0x09 ,0x2A ,
		0x86 ,0x48 ,0x86 ,0xF7 ,0x0D ,0x01 ,0x01 ,0x01,
		0x05 ,0x00 ,0x03 ,0x81 ,0x8D ,0x00 ,0x30 ,0x81,
		0x89 ,0x02 ,0x81 ,0x81, 0x00
	};
	uint8_t Last[]={0x02 ,0x03 ,0x01, 0x00, 0x01};
	memcpy(PkcsANS , Head , sizeof(Head));
	memcpy(&PkcsANS[sizeof(Head)], PubKey , RSA_N_Len);
	memcpy(&PkcsANS[sizeof(Head)+RSA_N_Len] , Last , sizeof(Last));
	int size = sizeof(Head) + RSA_N_Len + sizeof(Last);
	char Base64[1024]={0} ;
	size_t num = 0;
    //NULL ,num設為0 ,是為了獲取num
	base64_encode(NULL , &num, PkcsANS, size);  
	//真正base64編碼
	base64_encode(Base64 , &num,  PkcsANS, size); 	
	int n , i =0 ;
	for (n = 0 ; n<  num ; n++) {
	
		if (n!=0 && (n+1)%64 == 0) {
			DataOut[i] = '\n';
			i++;
		}
		DataOut[i]= Base64[n];
		i++;
	}
	sprintf( PemData ,"\n-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----\n" , DataOut);
	DEBUG_INFO("%s" , PemData);
}


//測試
void TestRsa(void)
{
  CreateRsaKey();
  RsaNToPkcs1(PubKey);

  //採用rsa公鑰加密base64編碼之後的密文,明文是12345678
  unsigned char buf[1024] = "qpkO85wYitHwZ/HTm3+DKZmfVm1jZkjwowMIY3rOsXnj6WMSNSKyCRX6aEOUqDHDX7JlqjPctzHYsMBGQyZ5jvKuiLIjIGDQsZtFWg29iXwSz09jhAdixCmiP6JqfMho9zek5FUydqM9tyMQppv8h3ilM8kiFCXRZ2+76PmhSg0=";
  unsigned char OutBuf[2048] = {0};
  //base64解碼,rsa私鑰解密
  Base64DeAndRsa(buf,OutBuf);
  //使用rsa私鑰解密之後
  DEBUG_INFO("%s",OutBuf);
}

int main(void)
{
   TestRsa();
    
	return 0;
}

1.3 rsa生成的公鑰,採用pkcs1填充之後,採用網站工具線上加密明文,把加密的密文複製到程式碼中採用私鑰解密

http://tool.chacuo.net/cryptrsapubkey

1.4 解密結果測試,成功解密

1.5 程式碼完整github連結

https://github.com