首页 > 其他分享 >C语言RsaUtil,C语言Rsa验证签名,验签----自测OK

C语言RsaUtil,C语言Rsa验证签名,验签----自测OK

时间:2023-11-29 11:32:50浏览次数:32  
标签:OK 自测 RSA len C语言 length key signature data


摘自:https://www.dandelioncloud.cn/article/details/1498198300963708930

 

// RsaUtil.c
#include <string>
using namespace std;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/sha.h>
#include "Base64Util.h"


#define KEY_LENGTH 2048
#define PUB_EXP 65537


static string hex_2_string(unsigned char *data, unsigned int data_len)
{
    string str = "";
    size_t malloc_len = 2 * data_len + 1;

    char *tmp_str = (char *)calloc(1, malloc_len);
    if (NULL == tmp_str) {
        return "";
    }

    for (unsigned int index = 0; index < data_len; index++) {
        snprintf(tmp_str + strlen(tmp_str), malloc_len - strlen(tmp_str) - 1, "%02x", data[index]);
    }


    str = tmp_str;

    free(tmp_str);

    return str;
}

// 加载公钥
static RSA *load_publicKey(string path_public_key)
{
    FILE *fp = fopen(path_public_key.c_str(), "r");
    if (NULL == fp) {
        printf("Failed to load public key\n");
        return NULL;
    }

    RSA *rsa_pub = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL); // 千万不要调用PEM_read_RSA_PUBKEY()接口, 必现: 会导致RSA_verify() 函数内部 coredump
    fclose(fp);

    return rsa_pub;
}

// 加载私钥
static RSA *load_privateKey(string path_private_key)
{
    FILE *fp = fopen(path_private_key.c_str(), "r");
    if (NULL == fp) {
        printf("Failed to load private key\n");
        return NULL;
    }

    RSA *rsa_priv = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
    fclose(fp);
    printf("RSA_size=%d\r\n", RSA_size(rsa_priv));
    return rsa_priv;
}


static string __rsa_sign(RSA *private_key, const unsigned char *data, size_t data_len)
{
    unsigned char *signature = NULL;
    unsigned int signature_length = 0;
    string out_signature = "";

    printf("=========================================================\n");

    printf("__rsa_sign        data=%s, len=%lu\n", data, data_len);

    signature_length = RSA_size(private_key);
    printf("__rsa_sign        signature_length=%d\n", signature_length);
    signature = (unsigned char *)malloc(signature_length);

    // 计算哈希值
    signature_length = RSA_size(private_key);

    if (1 != RSA_sign(NID_sha256, data, data_len, signature, &signature_length, private_key)) {
        printf("Failed to generate RSA signature.\n");
        return "";
    }

    printf("__rsa_sign signature_length=%d|\n%s\n", signature_length, hex_2_string(signature, signature_length).c_str());
    out_signature = base64_encode(signature, signature_length);

    free(signature);
    printf("=========================================================\n\n\n");

    return out_signature;
}

static int __rsa_verify(RSA *public_key, const unsigned char *data, size_t data_len, string signature_base64)
{
    unsigned char *signature = NULL;
    int signature_length = 0;
    int ret = 0;

    printf("=========================================================\n");

    signature_length = RSA_size(public_key);
    printf("rsa_verify() signature_length=%d|%lu\n", signature_length, signature_base64.length());
    ret = base64_decode(signature_base64, &signature, &signature_length);
    if (0 != ret) {
        printf("base64_decode() failed.\n");
        return -1;
    }

    printf("rsa_verify() signature_length=%d|%lu|\n%s\n", signature_length, signature_base64.length(), hex_2_string(signature, signature_length).c_str());

    if (1 != RSA_verify(NID_sha256, data, data_len, signature, signature_length, public_key)) {
        printf("RSA signature verification failed.\n");
        return -1;
    }

    printf("RSA signature verification succeeded.\n");
    free(signature);
    printf("=========================================================\n\n\n");

    return 0;
}

string rsa_sign(string path_private_key, const unsigned char *data, size_t data_len)
{
    RSA *private_key = NULL;
    string out_signature = "";

    private_key = load_privateKey(path_private_key);
    out_signature = __rsa_sign(private_key, data, data_len);

    RSA_free(private_key);

    return out_signature;
}

int rsa_verify(string path_public_key, const unsigned char *data, size_t data_len, string signature_base64)
{
    int ret = 0;
    RSA *public_key = NULL;

    public_key = load_publicKey(path_public_key);

    ret = __rsa_verify(public_key, data, data_len, signature_base64);

    RSA_free(public_key);

    return ret;
}

#if 1
int main() {
    string sig = "";
    string path_public_key = "/root/test/81/lanxin_public.pem";
    string path_private_key = "/root/test/81/lanxin_private.pem";
    string data = "This is a test message.";
    int ret = 0;

    //RSA *rsa = RSA_generate_key(KEY_LENGTH, PUB_EXP, NULL, NULL);

    RSA *private_key = load_privateKey(path_private_key);
    RSA *public_key  = load_publicKey(path_public_key);

    sig = __rsa_sign(private_key, (const unsigned char*)data.c_str(), data.length());
    if (sig.length() <= 0) {
        printf("RSA_sign Failed.\n");
        return -1;
    }
    printf("sig=%s|\n", sig.c_str());
    ret = __rsa_verify(public_key, (const unsigned char*)data.c_str(), data.length(), sig);
    if (0 != ret) {
        printf("rsa_verify Failed.\n");
        return -1;
    }

    return 0;
}
#endif

 

// Base64Util.c

#include <string>
using namespace std;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/evp.h>


#include "Base64Util.h"

/*****************************************************************

    Base64编码

    参数 : data, 输入参数, 输入数据
           data_len, 输入参数, 输入数据长度

     return : 长度>0, 成功, 返回 base64 字符串
              长度=0, 失败

*****************************************************************/
string base64_encode(const unsigned char *data, int data_len)
{
    BIO *bio = NULL;
    BIO *b64 = NULL;
    char *buffer = NULL;
    int buf_len = 0;

    if (NULL == data || 0 >= data_len) {
        return "";
    }

    // 创建Base64编码的BIO
    b64 = BIO_new(BIO_f_base64());
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); // 去掉所有换行符

    bio = BIO_new(BIO_s_mem());
    bio = BIO_push(b64, bio);


    // 写入数据并刷新BIO
    BIO_write(bio, data, data_len);
    (void)BIO_flush(bio);

    // 读取Base64编码后的数据
    buf_len = BIO_get_mem_data(bio, &buffer);
    if (0 <= buf_len) {
        buffer[buf_len] = '\0';
    }

    string base64_str = (NULL == buffer) ? "" : buffer;

    // 清理资源
    BIO_free_all(bio); // 内部已经 释放buffer

    return base64_str;
}

/*****************************************************************

    Base64解码

    参数 : base64_str, 输入参数, base64 字符串
           output, 输出参数, 输出数据(请调用者自行free)
           out_len, 输出参数, 输出数据长度

     return :  0, 成功
              -1, 失败

*****************************************************************/
int base64_decode(string base64_str, unsigned char **output, int *out_len)
{
    BIO *bio = NULL;
    BIO *b64 = NULL;
    char *buffer = NULL;
    int buf_len = 0;
    int decoded_len = 0;

    if (NULL == output || NULL == out_len) {
        return -1;
    }

    // 创建Base64解码的BIO
    b64 = BIO_new(BIO_f_base64());
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); // 没有换行符

    bio = BIO_new_mem_buf(base64_str.c_str(), base64_str.length());
    bio = BIO_push(b64, bio);


    // 读取Base64解码后的数据
    buf_len = base64_str.length() * 3 / 4;
    buffer = (char *)calloc(1, buf_len + 1);
    decoded_len = BIO_read(b64, buffer, base64_str.length());
    if (0 <= decoded_len) {
        buffer[decoded_len] = '\0';
    }

    *output = (unsigned char *)buffer;
    *out_len = decoded_len;
    //printf("decoded_len=%d, buf_len=%d, buffer=%s\r\n", decoded_len, buf_len, buffer);

    // 清理资源
    BIO_free_all(bio);

    return 0;
}

#if 0
// 主函数测试Base64编码和解码函数
int main() {
    const char *str = "Hello, World!我爱你";
    string base64_str = "";
    unsigned char *output = NULL;
    int out_len = 0;
    int ret = 0;

    base64_str = base64_encode((const unsigned char *)str, strlen(str));
    ret = base64_decode(base64_str, &output, &out_len);

    printf("base64=%s\r\n", base64_str.c_str());
    printf("ret=%d, out_len=%d, str=%s\r\n", ret, out_len, output);

    free(output);

    return 0;
}
#endif

 

g++ Base64Util.c RsaUtil.c -lcrypto -g -Wall ; ./a.out

 



标签:OK,自测,RSA,len,C语言,length,key,signature,data
From: https://blog.51cto.com/u_3078781/8613049

相关文章

  • Base64编码、解码 C语言例子(使用OpenSSL库)
    #include<stdio.h>#include<string.h>#include<unistd.h>#include<openssl/pem.h>#include<openssl/bio.h>#include<openssl/evp.h>intbase64_encode(char*in_str,intin_len,char*out_str){BIO*b64,*bio;......
  • identityserver4 刷新token接口返回空
    如题,查看日志发现错误信息:Nosigningcredentialforalgorithms(rs256)registered而客户端的配置里的“身份令牌算法”没有rs256于是加上就ok了。 ......
  • C语言字节对齐 __align(),__attribute((aligned (n))),#pragma pack(n)
    例子:__align(),__attribute((aligned(n))),#pragmapack(n)#include<stdio.h>main(){structA{inta;charb;shortc;};structB{charb;inta;shortc;};#pragmapack(2)/*指定按2字节对齐*/......
  • vue+iframe 添加请求头,自适应宽度和高度,iframe将token放在请求头不是src的url中
    1<template>2<divclass="iframe">3<iframe4v-if="isRequestHeader"5id="myIframe"6name="myIframe"7src=""8frameborder="0&qu......
  • Docker + supervisor在同一容器中部署zookeeper和kafka
    使用supervisor进程管理工具,在同一个容器中部署zookeeper和kafka目录Dockerfilejdk1.8.0_181.tar.gzkafka_2.12-1.1.0.tgzconf.ddocker-compose.ymlkafka_conf.dconf.d中为supervisor配置文件kafka_conf.d中为kafka配置文件,解压kafka_2.12-1.1.0.tgz中的配置文件,拷贝......
  • [good]c语言数组的运算
    #include<stdio.h>#include<stdlib.h>#include<time.h>#defineMAX10int**createRandom2DArray(introws,intcols){srand(time(NULL));//初始化随机数生成器int**arr=(int**)(malloc(sizeof(int*)*rows));if(arr==NULL)......
  • SystemSettingsBroker.exe这个奇怪的进程
    系统版本:22621.2715做完PBRReset之后,进入系统,CheckSystemSettingsBroker.exe并没有存在,点击网络图标(TaskBar)后,SystemSettingsBroker.exe进程被拉起了。然后重启系统。 重启系统之后,放置一段时间,系统进入熄屏状态,通过键盘唤醒系统,进入S0,这时发现SystemSettingsBroker.exe又......
  • class lombok.javac.apt.LombokProcessor
    classlombok.javac.apt.LombokProcessor(inunnamedmodule@0x4587f0f9)cannotaccessclasscom.sun.tools.javac.processing.JavacProcessingEnvironment(inmodulejdk.compiler)becausemodulejdk.compilerdoesnotexportcom.sun.tools.javac.processingtounn......
  • 《初学C语言第9天》
    //如何写出好的、易调试的代码//#define_CRT_SECURE_NO_WARNINGS//#include<stdio.h>//#include<string.h>//strcpy所需头文件//intmain()//{// //strcpy——字符串拷贝// chararr1[]="##########";// chararr2[]="bit";// strcpy(arr1,arr2);//将arr......
  • 《初学C语言第9天》
    //如何写出好的、易调试的代码//#define_CRT_SECURE_NO_WARNINGS//#include<stdio.h>//#include<string.h>//strcpy所需头文件//intmain()//{// //strcpy——字符串拷贝// chararr1[]="##########";// chararr2[]="bit";// strcpy(arr1,arr2);//将arr......