写一个RSA签名与验签的Demo
2015-12-28 15:07
302 查看
一、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)
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; }
相关文章推荐
- HandlerThread类应用
- 提示用户打开某些权限 (打开设置页面)
- data.getData()返回的Uri
- Web平台能从Node.js学到什么
- Problem J: 写一个函数,使给定的一个二维数组(3×3)转置,即行列互换
- 初装vs2010旗舰版 遇到的错误
- Spark Streaming实时计算框架介绍
- iOS--修改导航栏的背景色
- mysql 内连接、左连接、右连接
- 删除CocoaPods中已经配置的类库、移除项目中CocoaPods
- 兄弟会
- 【Unity编辑器】面板中显示Private修饰的变量
- 关于BufferedInputStream和BufferedOutputStream的实现原理的理解
- LCIS 最长公共上升子序列
- java.lang.OutOfMemoryError: PermGen space
- 从文件 I/O 看 Linux 的虚拟文件系统
- 4. Phpstorm svn
- ]利用shell脚本,crontab,scp实现将一台服务器的目录备份到另一台服务器
- JSON与XML的区别比较
- 实现一个函数,将一个数的二进制序列逆序,然后输出逆序所得二进制序列所对应的数字