您的位置:首页 > 运维架构

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

2016-01-25 11:55 886 查看

问题描述

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

[code]$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私钥格式,验证也没有问题。那说明字符串方式在构造私钥的时候有问题。

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


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

[code]    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工具生成,方法如下。

[code]#!/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"


具体也可以参考 测试代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: