Hom*_*der 2 php certificate x509certificate x509
我必须从离开公司的开发人员那里调试一个旧的PHP脚本.我理解代码的大部分内容,除了以下函数.我的问题:什么......
if($ seq == 0x03 || $ seq == 0x30)
...是指从X.509证书中提取签名的上下文?
public function extractSignature($certPemString) {
$bin = $this->ConvertPemToBinary($certPemString);
if(empty($certPemString) || empty($bin))
{
return false;
}
$bin = substr($bin,4);
while(strlen($bin) > 1)
{
$seq = ord($bin[0]);
if($seq == 0x03 || $seq == 0x30)
{
$len = ord($bin[1]);
$bytes = 0;
if ($len & 0x80)
{
$bytes = ($len & 0x0f);
$len = 0;
for ($i = 0; $i < $bytes; $i++)
{
$len = ($len << 8) | ord($bin[$i + 2]);
}
}
if($seq == 0x03)
{
return substr($bin,3 + $bytes, $len);
}
else
{
$bin = substr($bin,2 + $bytes + $len);
}
}
else
{
return false;
}
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
X.509证书包含多个部分中的数据(称为Tag-Length-Value三元组).每个部分都以Tag字节开头,表示该部分的数据格式.您可以在此处查看这些数据类型的列表.
0x03是BIT STRING数据类型的Tag字节,0x30是SEQUENCE数据类型的Tag字节.
因此,此代码旨在处理BIT STRING和SEQUENCE数据类型.如果你看这个部分:
if($seq == 0x03)
{
return substr($bin,3 + $bytes, $len);
}
else // $seq == 0x30
{
$bin = substr($bin,2 + $bytes + $len);
}
Run Code Online (Sandbox Code Playgroud)
你可以看到该函数被设计为跳过序列(0x30),直到它找到一个位串(0x03),此时它返回位串的值.
您可能想知道为什么神奇数字对于位串为3而对于序列为2.这是因为在比特串中,第一个值字节是一个特殊的额外字段,表示在数据的最后一个字节中未使用的位数.(例如,如果您要发送13位数据,则需要2个字节= 16位," 未使用位 "字段将为3.)
下一期:长度字段.当Value的长度小于128个字节时,使用单个字节简单地指定长度(最高有效位将为0).如果长度为128或更大,则第一个长度字节的位设置为7,其余7个位表示后续字节包含的长度(以大端顺序排列).这里有更多描述.解析长度字段发生在代码的这一部分:
$len = ord($bin[1]);
$bytes = 0;
if ($len & 0x80)
{
// length is greater than 127!
$bytes = ($len & 0x0f);
$len = 0;
for ($i = 0; $i < $bytes; $i++)
{
$len = ($len << 8) | ord($bin[$i + 2]);
}
}
Run Code Online (Sandbox Code Playgroud)
之后,$bytes包含length字段使用的额外字节数,并$len包含Value字段的长度(以字节为单位).
您是否发现了代码中的错误?记得,
如果长度为128或更大,则第一个长度字节的位设置为7,其余7位表示后续字节包含的长度.
但代码说$bytes = ($len & 0x0f),只占用字节的低4位!它应该是:
$bytes = ($len & 0x7f);
Run Code Online (Sandbox Code Playgroud)
当然,这个错误只是极长消息的问题:只要长度值适合0x0f = 15字节,它就能正常工作,这意味着数据必须小于256 ^ 15字节.这大约是一万亿个字节,对任何人来说都应该足够了.
| 归档时间: |
|
| 查看次数: |
718 次 |
| 最近记录: |