[问题记录] openssl error:0906D064:PEM routines:PEM_read_bio:bad base64 decode

在使用C语言进行RSA签名计算时遇到openssl错误:0906D064。经过排查,问题出在构造PEM私钥字符串时多插入了换行符,导致私钥格式非法。解决方案是正确计算字符串长度,避免多余的换行。此外,介绍了一种使用`fold -w 64`命令格式化PEM私钥的技巧,并提到了RSA公私钥的openssl生成方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

之前使用C写了一个计算rsa签名的函数,最近在根据私钥计算签名的时候突然遇到如下错误:PEM_read_bio_PrivateKey err[error:0906D064:lib(9):func(109):reason(100)],虽然代码里是用openssl提供的ERR_error_string_n接口打印的详细错误描述,但是仍然看不懂错误的含义,后来man了下,可以通过openssl errstr 0906D064方法查看某个错误码对应的详细错误信息。

$openssl errstr 0906D064
error:0906D064:PEM routines:PEM_read_bio:bad base64 decode

原因分析

第一步:首先怀疑是rsa私钥格式的问题,因为openssl默认使用PEM的格式,而不是DER的格式,经确认私钥格式没问题。
第二步:因为计算rsa签名报错使用的是字符串方式PEM_read_bio_RSAPrivateKey,所以先考虑使用文件方式PEM_read_RSAPrivateKey看是否存在相同的错误。通过将字符串还原成标准的PEM私钥格式,验证也没有问题。那说明字符串方式在构造私钥的时候有问题。

-----BEGIN RSA PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCHLMCvgZGJuJ2I
...
qWW232xBX9o51hRgrr8y82OsBDrQ7epuuHhrbNZzAHEjUKnIlyc3eeSrmSL7FaiL
+Cs3Hxv0A==
-----END RSA PRIVATE KEY-----

检查代码找到了问题,在通过字符串构造PEM私钥的时候,因为每次迭代多插入了一个换行符多了一次++i操作,所以每次迭代比较时要计算实际的strPrivateKey长度。当RSA私钥比较长的时候,最后一次迭代长度可能超过64,导致私钥格式非法;而当私钥长度较短的时候,这个问题又不会出现。

    int keyLen = strPrivateKey.size();
    for (int i = 64; i < keyLen; i += 64)// <--- Problem! 应为 i < strPrivateKey.size() 
    {
        if (strPrivateKey[i] != '\n')
        {
            strPrivateKey.insert(i, "\n");
        }
        ++i;
    }

    strPrivateKey.insert(0, "-----BEGIN RSA PRIVATE KEY-----\n");
    strPrivateKey.append("\n-----END RSA PRIVATE KEY-----\n");

    char * szPrivateKey = const_cast<char *>(strPrivateKey.c_str());
    if ((bio = BIO_new_mem_buf(szPrivateKey, strPrivateKey.length())) == NULL)           
    {
        char errBuf[512] = {0};
        ERR_error_string_n(ERR_get_error(), errBuf, sizeof(errBuf));
        iResultCode   =  1;
        strResultInfo =  std::string("BIO_new_mem_buf err[") + errBuf + "]";;
        return -1;
    }

    rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);   
    if (NULL == rsa)
    {
        char errBuf[512] = {0};
        ERR_error_string_n(ERR_get_error(), errBuf, sizeof(errBuf));
        iResultCode   =  2;
        strResultInfo =  std::string("PEM_read_bio_PrivateKey err[") + errBuf + "]";
        return -1;
    }
    BIO_free(bio);

小技巧: 除了用代码生成,也可以使用工具fold -w 64格式化文本,简单方便。

其他

RSA的公私钥可以使用openssl工具生成,方法如下。

#!/bin/bash

echo "create rsa privatekey"
openssl genrsa -out privatekey.pem 1024

echo "create rsa publickey from privatekey"
openssl rsa -in privatekey.pem -out publickey.pem -outform PEM -pubout

echo "done"

具体也可以参考 测试代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值