写一个RSA签名与验签的Demo

一、RSA私钥及公钥生成

OpenSSL工具安装
RSA私钥及公钥生成
OpenSSL工具安装


Linux用户(以Ubuntu为例)
sudo apt-get install openssl

RSA私钥及公钥生成

Linux用户(以Ubuntu为例)
$ openssl 进入OpenSSL程序
OpenSSL> genrsa -out rsa_private_key.pem 1024 生成私钥


OpenSSL> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem 生成公钥
OpenSSL> exit ## 退出OpenSSL程序

二、以下是Demo



签名验证签名函数原形:
/**
* @brief 签名函数
* text : 待签名字符串
* signature : 签名结果
* size : 分配存储签名结果内存大小
* sk_filename : 私钥文件名(pem格式,openssl直接生成的结果)
*/
 char*   alipay_rsa_sign(const char *text, char *signature, size_t size, const char *sk_filename)
 
 
  /**
 * @brief 验签函数
 * text : 待验签字符串
 * sig : 签名值
 * pk_filename : 公钥文件名(pem格式,openssl直接生成的结果)
 */
int  alipay_rsa_verify(const char *text, char *sig, const char *pk_filename)




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

#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>


 char *base64(const char *input, size_t length, char *result, size_t size)
{
	BIO * bmem = NULL;
	BIO * b64 = NULL;
	BUF_MEM * bptr = NULL;
	assert(NULL != input);
	b64 = BIO_new(BIO_f_base64());
	bmem = BIO_new(BIO_s_mem());
	if (NULL == b64 || NULL == bmem) {
		perror("BIO_new");
		return NULL;
	}
	BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);

	b64 = BIO_push(b64, bmem);
	BIO_write(b64, input, length);
	BIO_flush(b64);
	BIO_get_mem_ptr(b64, &bptr);

	if ((unsigned int)(bptr->length + 1) > size) {
		BIO_free_all(b64);
		return NULL;
	}
	memcpy(result, bptr->data, bptr->length);
	result[bptr->length] = 0;

	BIO_free_all(b64);

	return result;
}

char *debase64(char *input, size_t length, char *result, size_t size)
{
	BIO * b64 = NULL;
	BIO * bmem = NULL;
	assert(NULL != input);
	if (length > size)
		return NULL;
	memset(result, 0, size);

	b64 = BIO_new(BIO_f_base64());
	bmem = BIO_new_mem_buf(input, length);
	BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
	if (NULL == b64 || NULL == bmem) {
		perror("BIO_new");
		return NULL;
	}
	bmem = BIO_push(b64, bmem);
	BIO_read(bmem, result, length);

	BIO_free_all(b64);

	return result;
}

char *rsa_sign(const char *text, char *signature, size_t size, const char *sk_filename)
{
	RSA *rsa;
	unsigned char *sig;
	unsigned int len;

	assert(text != NULL && sk_filename != NULL);
	OpenSSL_add_all_algorithms();
	BIO* in = NULL;
	in = BIO_new(BIO_s_file());
	BIO_read_filename(in, sk_filename);
	if (in == NULL) {
		perror(sk_filename);
		return NULL;
	}

	//将IO中数据以PEM格式读入EVP_PKEY结构中
	rsa = PEM_read_bio_RSAPrivateKey(in, NULL, NULL, NULL);
	if (in != NULL)
		BIO_free(in);
	if (rsa == NULL) {
		perror("PEM_read_bio_RSAPrivateKey");
		return NULL;
	}
	if (NULL == (sig = (unsigned char*)malloc(RSA_size(rsa)))) {
		RSA_free(rsa);
		return NULL;
	}

	unsigned char sha1[20] = { '\0' };
	//result len of sha1:20 bytes
	SHA1((const unsigned char *)text, strlen(text), sha1);
	if (1 != RSA_sign(NID_sha1, sha1, 20, sig, &len, rsa)) {
		free(sig);
		RSA_free(rsa);
		printf("RSA_sign error.\n");
		return NULL;
	}
	//base64((char *) sig, strlen((char *) sig), signature, size);
	// do you know why can not use strlen 
	if (NULL == base64((char *)sig, 128, signature, size)) {
		free(sig);
		RSA_free(rsa);
		printf("base64 error.\n");
		return NULL;
	}
	free(sig);
	RSA_free(rsa);

	return signature;
}

int rsa_verify(const char *text, char *signature, const char *pk_filename)
{
	RSA *rsa;
	BIO* in = NULL;
	assert(NULL != text && NULL != signature);
	in = BIO_new(BIO_s_file());
	BIO_read_filename(in, pk_filename);
	if (NULL == in) {
		printf("BIO_read_filename error.\n");
		return 1;
	}
	//将IO中数据以PEM格式读入EVP_PKEY结构中
	//rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL);
	rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL);

	if (in != NULL) BIO_free(in);
	if (rsa == NULL) {
		printf("PEM_read_bio_RSA_PUBKEY error.\n");
		return 1;
	}

	//unsigned char sig_temp[250];
	char * sig_debase = (char *)malloc(250 * sizeof(char));
	if (NULL == debase64(signature, strlen((char *)signature), sig_debase, 250)) {
		RSA_free(rsa);
		printf("debase64 error.\n");
		return 1;
	}

	unsigned char sha1[20];
	SHA1((const unsigned char *)text, strlen(text), sha1);
	if (1 != RSA_verify(NID_sha1, sha1, 20, (unsigned char *)sig_debase, 128, rsa)) {
		free(sig_debase);
		RSA_free(rsa);
		printf("RSA_verify error.\n");
		return 1;
	}
	free(sig_debase);
	RSA_free(rsa);

	return 0;
}
 
/*url enconding */
char *alpayex_URLencode(char *s, int len, int *new_length, char *start )
{
    char c;
    char *to;
    unsigned char const *from, *end;
    printf("len:%d\n", len);
    from = s;
    end = s + len;
    /* start = to = (unsigned char *) malloc(3 * len + 1); */
    to = start;
    unsigned char hexchars[] = "0123456789ABCDEF";

    while (from < end)
    {
        c = *from++;
        if (c == ' ')
        {
            *to++ = '+';
        }
        else if ((c < '0' && c != '-' && c != '.')
                   ||(c < 'A' && c > '9')
                   ||(c > 'Z' && c < 'a' && c != '_')
                   ||(c > 'z')) {
            to[0] = '%';
            to[1] = hexchars[((c >> 4)+16)%16];
            to[2] = hexchars[c & 15];
            to += 3;
        }
        else
        {
            *to++ = c;
        }
    }
    *to = 0;
    if (new_length)
    {
        *new_length = to - start;
    }
    return (char *) start;
}


int  main()
{
	char *in="hello";
	char out[20]={0};
	int len=10;
	base64(in,5,out,len);
	printf("out = %s, len = %d \n",out,len);
	return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值