C语言解析pem私钥文件

本文提供了一段C语言代码,用于从PEM文件中读取并解析私钥信息,包括模块、指数等数据,适用于RSA 2048位密钥。代码首先将PEM文件转换为字符串,然后进行Base64解码,最后解析出关键的RSA私钥组件。
摘要由CSDN通过智能技术生成

直接上代码。。。

/*按行读取一个pem文件所有字符并拼接为一整个字符串返回,去除首行、尾行及换行符*/
char* LoadPemFile(char* pemFilePath,int* length)
{
    FILE* file;
    size_t size = 0;
    char* buff;

    file = fopen(pemFilePath,"rb");
    if(file==NULL)
    {
        return NULL;
    }

    fseek(file,0L,SEEK_END); /*定位至文件尾*/
    size = ftell(file); /*获取文件大小*/
    buff = (char*)malloc(size);
    fseek(file,0L,SEEK_SET); /*定位至文件首*/
    size = 0;

    char line[1024]; //假设单行最长不超过1024,pem文件单行不会超过此限制

    while (!feof(file) && !ferror(file))
    {
        memset(line,0,sizeof(line));
        fgets(line, sizeof(line), file);
        int len=strlen(line);
        line[len-1]=0;//为了去除行尾的\n
        if(line[0]!='-') //去除首行和尾行
        {
            memcpy(buff+size,line,strlen(line));
            size += strlen(line);
        }
    }

    fclose(file);
    *length = size;
    //printf("%s",buff);
    return buff;
}


/*解码Base64,参数bindata需预先分配足够内存。返回值为解码后的实际长度*/
int base64_decode( const char * base64, unsigned char * bindata )
{
    int i, j;
    unsigned char k;
    unsigned char temp[4];
    const char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    for ( i = 0, j = 0; base64[i] != '\0' ; i += 4 )
    {
        memset( temp, 0xFF, sizeof(temp) );
        for ( k = 0 ; k < 64 ; k ++ )
        {
            if ( base64char[k] == base64[i] )
                temp[0]= k;
        }
        for ( k = 0 ; k < 64 ; k ++ )
        {
            if ( base64char[k] == base64[i+1] )
                temp[1]= k;
        }
        for ( k = 0 ; k < 64 ; k ++ )
        {
            if ( base64char[k] == base64[i+2] )
                temp[2]= k;
        }
        for ( k = 0 ; k < 64 ; k ++ )
        {
            if ( base64char[k] == base64[i+3] )
                temp[3]= k;
        }

        bindata[j++] = ((unsigned char)(((unsigned char)(temp[0] << 2))&0xFC)) |
                ((unsigned char)((unsigned char)(temp[1]>>4)&0x03));
        if ( base64[i+2] == '=' )
            break;

        bindata[j++] = ((unsigned char)(((unsigned char)(temp[1] << 4))&0xF0)) |
                ((unsigned char)((unsigned char)(temp[2]>>2)&0x0F));
        if ( base64[i+3] == '=' )
            break;

        bindata[j++] = ((unsigned char)(((unsigned char)(temp[2] << 6))&0xF0)) |
                ((unsigned char)(temp[3]&0x3F));
    }
    return j;
}

/*从一个私钥pem文件中解析出module、exp数据至rsa_sk_t结构体*/
int ParseRsa2048PrivatePemFile(char* pemFilePath,rsa_sk_t *sk)
{
    int length=0;
    char* srcData = LoadPemFile(pemFilePath,&length);
    if(srcData==NULL)
    {
        return -2; //打开文件错误
    }
    uint8_t destData[1193];
    memset(destData,0,sizeof(destData));
    length = base64_decode(srcData,destData);
    free(srcData);

    if(length>=1191)
    {
        int startIndex = 0;
        if(destData[10]==1)
        {
            startIndex = 12;
        }
        else
        {
            startIndex = 11;
        }
        sk->bits = 2048;
        memcpy(&sk->modulus         [RSA_MAX_MODULUS_LEN-256 ],  destData + startIndex,  256);
        startIndex = startIndex + 256 + 2;
        memcpy(&sk->public_exponet  [RSA_MAX_MODULUS_LEN-3],  destData + startIndex,  3);
        if(destData[startIndex + 6]==1)
        {
            startIndex = startIndex + 8;
        }
        else
        {
            startIndex = startIndex + 7;
        }
        memcpy(&sk->exponent        [RSA_MAX_MODULUS_LEN-256 ],  destData + startIndex,  256);
        if(destData[startIndex + 259]==1)
        {
            startIndex = startIndex + 261;
        }
        else
        {
            startIndex = startIndex + 260;
        }
        memcpy(&sk->prime1          [RSA_MAX_PRIME_LEN - 128 ],  destData + startIndex,  128);
        if(destData[startIndex + 131]==1)
        {
            startIndex = startIndex + 133;
        }
        else
        {
            startIndex = startIndex + 132;
        }
        memcpy(&sk->prime2          [RSA_MAX_PRIME_LEN - 128 ],  destData + startIndex, 128);
        if(destData[startIndex + 131]==1)
        {
            startIndex = startIndex + 133;
        }
        else if(destData[startIndex + 131]==0)
        {
            startIndex = startIndex + 132;
        }
        else
        {
            startIndex = startIndex + 131;
        }
        memcpy(&sk->prime_exponent1 [RSA_MAX_PRIME_LEN - 128 ],  destData + startIndex, 128);
        if(destData[startIndex + 131]==1)
        {
            startIndex = startIndex + 133;
        }
        else if(destData[startIndex + 131]==0)
        {
            startIndex = startIndex + 132;
        }
        else
        {
            startIndex = startIndex + 131;
        }
        memcpy(&sk->prime_exponent2 [RSA_MAX_PRIME_LEN - 128 ],  destData + startIndex, 128);
        if(destData[startIndex + 131]==1)
        {
            startIndex = startIndex + 133;
        }
        else if(destData[startIndex + 131]==0)
        {
            startIndex = startIndex + 132;
        }
        else
        {
            startIndex = startIndex + 131;
        }
        memcpy(&sk->coefficient     [RSA_MAX_PRIME_LEN - 128 ],  destData + startIndex,  128);

        return 0;
    }
    else
    {
        return -1; //文件长度错误
    }
    return 0;
}

C语言解析pem公钥文件在上一篇文章里

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值