openssl中PEM_write_bio函数和PEM_read_bio函数的区别
我正在调试OpenSSL中的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
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.
...