openssl中PEM_write_bio函数和PEM_read_bio函数的区别

openssl中PEM_write_bio函数和PEM_read_bio函数的区别,openssl,Openssl,我正在调试OpenSSL中的PEM_write_bio和PEM_read_bio函数 函数定义如下: int PEM_write_bio(BIO *bp, const char *name, char *header, unsigned char *data, long len) { int nlen,n,i,j,outl; unsigned char *buf = NULL; EVP_ENCODE_CTX ctx; int r

我正在调试OpenSSL中的
PEM_write_bio
PEM_read_bio
函数

函数定义如下:

int PEM_write_bio(BIO *bp, const char *name, char *header, unsigned char *data,
                  long len)
{
    int nlen,n,i,j,outl;
    unsigned char *buf = NULL;
    EVP_ENCODE_CTX ctx;
    int reason=ERR_R_BUF_LIB;

    EVP_EncodeInit(&ctx);
    nlen=strlen(name);
    ////////////////////////////////////////////////////////////////////
    if ((BIO_write(bp,"-----BEGIN ",11) != 11) ||
        (BIO_write(bp,name,nlen) != nlen) ||
        (BIO_write(bp,"-----\n",6) != 6))
        goto err;
    ////////////////////////////////////////////////////////////////////
    i=strlen(header);

    if (i > 0)
    {
        if (    (BIO_write(bp,header,i) != i) ||
            (BIO_write(bp,"\n",1) != 1))
            goto err;
    }

    buf = OPENSSL_malloc(PEM_BUFSIZE*8);
    if (buf == NULL)
    {
        reason=ERR_R_MALLOC_FAILURE;
        goto err;
    }

    i=j=0;
    while (len > 0)
    {
        n=(int)((len>(PEM_BUFSIZE*5))?(PEM_BUFSIZE*5):len);
        EVP_EncodeUpdate(&ctx,buf,&outl,&(data[j]),n);
        if ((outl) && (BIO_write(bp,(char *)buf,outl) != outl))
            goto err;
        i+=outl;
        len-=n;
        j+=n;
    }
    EVP_EncodeFinal(&ctx,buf,&outl);
    if ((outl > 0) && (BIO_write(bp,(char *)buf,outl) != outl)) goto err;
    OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
    OPENSSL_free(buf);
    buf = NULL;
    if (    (BIO_write(bp,"-----END ",9) != 9) ||
        (BIO_write(bp,name,nlen) != nlen) ||
        (BIO_write(bp,"-----\n",6) != 6))
        goto err;
    return(i+outl);
err:
    if (buf) {
        OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
        OPENSSL_free(buf);
    }
    PEMerr(PEM_F_PEM_WRITE_BIO,reason);
    return(0);
}

int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
                 long *len)
{
    EVP_ENCODE_CTX ctx;
    int end=0,i,k,bl=0,hl=0,nohead=0;
    char buf[256];
    BUF_MEM *nameB;
    BUF_MEM *headerB;
    BUF_MEM *dataB,*tmpB;

    nameB=BUF_MEM_new();
    headerB=BUF_MEM_new();
    dataB=BUF_MEM_new();
    if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL))
    {
        BUF_MEM_free(nameB);
        BUF_MEM_free(headerB);
        BUF_MEM_free(dataB);
        PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
        return(0);
    }

    buf[254]='\0';
    for (;;)
    {
        ////////////////////////////////////////////////////////////////////
        i=BIO_gets(bp,buf,254);
        ////////////////////////////////////////////////////////////////////
        if (i <= 0)
        {
            PEMerr(PEM_F_PEM_READ_BIO,PEM_R_NO_START_LINE);
            goto err;
        }

        while ((i >= 0) && (buf[i] <= ' ')) i--;
        buf[++i]='\n'; buf[++i]='\0';

        if (strncmp(buf,"-----BEGIN ",11) == 0)
        {
            i=strlen(&(buf[11]));

            if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0)
                continue;
            if (!BUF_MEM_grow(nameB,i+9))
            {
                PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
                goto err;
            }
            memcpy(nameB->data,&(buf[11]),i-6);
            nameB->data[i-6]='\0';
            break;
        }
    }
    hl=0;
    if (!BUF_MEM_grow(headerB,256))
    { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
    headerB->data[0]='\0';
    for (;;)
    {
        i=BIO_gets(bp,buf,254);
        if (i <= 0) break;

        while ((i >= 0) && (buf[i] <= ' ')) i--;
        buf[++i]='\n'; buf[++i]='\0';

        if (buf[0] == '\n') break;
        if (!BUF_MEM_grow(headerB,hl+i+9))
        { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
        if (strncmp(buf,"-----END ",9) == 0)
        {
            nohead=1;
            break;
        }
        memcpy(&(headerB->data[hl]),buf,i);
        headerB->data[hl+i]='\0';
        hl+=i;
    }

    bl=0;
    if (!BUF_MEM_grow(dataB,1024))
    { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
    dataB->data[0]='\0';
    if (!nohead)
    {
        for (;;)
        {
            i=BIO_gets(bp,buf,254);
            if (i <= 0) break;

            while ((i >= 0) && (buf[i] <= ' ')) i--;
            buf[++i]='\n'; buf[++i]='\0';

            if (i != 65) end=1;
            if (strncmp(buf,"-----END ",9) == 0)
                break;
            if (i > 65) break;
            if (!BUF_MEM_grow_clean(dataB,i+bl+9))
            {
                PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
                goto err;
            }
            memcpy(&(dataB->data[bl]),buf,i);
            dataB->data[bl+i]='\0';
            bl+=i;
            if (end)
            {
                buf[0]='\0';
                i=BIO_gets(bp,buf,254);
                if (i <= 0) break;

                while ((i >= 0) && (buf[i] <= ' ')) i--;
                buf[++i]='\n'; buf[++i]='\0';

                break;
            }
        }
    }
    else
    {
        tmpB=headerB;
        headerB=dataB;
        dataB=tmpB;
        bl=hl;
    }
    i=strlen(nameB->data);
    if (    (strncmp(buf,"-----END ",9) != 0) ||
        (strncmp(nameB->data,&(buf[9]),i) != 0) ||
        (strncmp(&(buf[9+i]),"-----\n",6) != 0))
    {
        PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_END_LINE);
        goto err;
    }

    EVP_DecodeInit(&ctx);
    i=EVP_DecodeUpdate(&ctx,
                       (unsigned char *)dataB->data,&bl,
                       (unsigned char *)dataB->data,bl);
    if (i < 0)
    {
        PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
        goto err;
    }
    i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k);
    if (i < 0)
    {
        PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
        goto err;
    }
    bl+=k;

    if (bl == 0) goto err;
    *name=nameB->data;
    *header=headerB->data;
    *data=(unsigned char *)dataB->data;
    *len=bl;
    OPENSSL_free(nameB);
    OPENSSL_free(headerB);
    OPENSSL_free(dataB);
    return(1);
err:
    BUF_MEM_free(nameB);
    BUF_MEM_free(headerB);
    BUF_MEM_free(dataB);
    return(0);
}
但是,当使用函数
PEM_read_bio
读取私钥时,它读取的是254块的值:

i=BIO_gets(bp,buf,254);
因此,我面临一个问题。我不明白它为什么要按254块读取文件

因此,我面临一个问题。我不明白它为什么要按254块读取文件

看来254是武断的。您可以选择或32、64、128或512

我希望看到一个更接近磁盘扇区大小的值,如1024或4096。至少,我希望它是2的幂

但是,在某些情况下,在现场遇到的线路有一个上限。其中一种情况是S/MIME,通过
BIO
BIO\u get
读取。在RFC 1421中:

4.3.1约束条件
...
2.由字符对分隔的文本行必须
长度不得超过1000个字符。
...
我不确定这个限制是否适用于你的情况,但这是我能找到的最接近限制或原因的限制


我想你应该把它换成适合你口味的。

你能描述一下你面临的问题吗?我不知道任何超过254字节的标准PEM头。实际上,当函数第一次读取254字节时。在if(strncmp(&(buf[11+i-6])之后,“----\n”,6)!=0)继续;请您也发布PEM文件的第一行(标题)好吗?上述条件不满足。----BEGIN PRIVATE KEY------谢谢您的回复。问题是,为什么在编写过程中不应用相同的概念?
i=BIO_gets(bp,buf,254);
   buf[254]='\0';
   for (;;)
   {
       i=BIO_gets(bp,buf,254);
       ...
   }
4.3.1 Constraints
...
    2.  Text lines, delimited by the character pair <CR><LF>, must
        be no more than 1000 characters long.
...