这个代码如何提取签名? [英] How does this code extract the signature?

查看:162
本文介绍了这个代码如何提取签名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须从离开公司的开发人员中调试旧的PHP脚本。我理解大部分的代码,除了以下函数。我的问题:...


if($ seq == 0x03 || $ seq == 0x30)

b $ b

...在从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;
}


解决方案

X.509证书数据(称为标签长度 - 值三元组)。每个部分以一个标记字节开始,表示该部分的数据格式。您可以查看这些数据类型的列表此处 a 是 /library/windows/desktop/bb540792%28v=vs.85%29.aspx\">比特STRING 数据类型, 0x30 SEQUENCE 数据类型。



所以这段代码设计用来处理BIT STRING和SEQUENCE数据类型。如果你看这部分:

  if($ seq == 0x03)
{
($ bin,3 + $ bytes,$ len);
}
else // $ seq == 0x30
{
$ bin = substr($ bin,2 + $ bytes + $ len);
}

您可以看到该函数旨在跳过序列直到找到位串(0x03),此时它返回位串的值。



您可能想知道为什么幻数为 3 用于位字符串 2 用于序列。这是因为在位串中,第一个值字节是一个特殊的额外字段,指示在数据的最后一个字节中未使用多少位。 (例如,如果您要发送13位数据,则​​它将占用2个字节= 16位,并且未使用位字段将为3)。



下一个问题:长度字段。当值的长度小于128字节时,长度只使用单个字节指定(最高有效位为0)。如果长度是128或更大,则第一长度字节具有位7设置,并且剩余的7位指示多少后面的字节包含长度(以大端顺序)。更多说明这里。长度字段的解析发生在代码的这一部分:

  $ len = ord($ bin [1]); 
$ bytes = 0;

if($ len& 0x80)
{
// length大于127!
$ bytes =($ len& 0x0f);
$ len = 0;
for($ i = 0; $ i <$ bytes; $ i ++)
{
$ len =($ len << 8)| ord($ bin [$ i + 2]);
}
}

之后, $ bytes 包含长度字段使用的额外字节数, $ len 包含值字段的长度(以字节为单位)。



您发现代码中的错误吗?记住,


如果长度为128或更大,则第一个长度字节设置为位7
, strong> 7位表示多少以下字节
包含长度。


c $ c> $ bytes =($ len& 0x0f),它只接收字节的低4位!应为:

  $ bytes =($ len& 0x7f); 

当然,这个错误只是它将工作正常,只要长度值将适合0x0f = 15字节,意味着数据必须小于256 ^ 15字节。这是一万亿亿字节,这对于任何人都是足够的。


I have to debug an old PHP script from a developer who has left the company. I understand the most part of the code, except the following function. My question: What does...

if($seq == 0x03 || $seq == 0x30)

...mean in context of extracting the signature out of an X.509 certificate?

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;
}

解决方案

An X.509 certificate contains data in multiple sections (called Tag-Length-Value triplets). Each section starts with a Tag byte, which indicates the data format of the section. You can see a list of these data types here.

0x03 is the Tag byte for the BIT STRING data type, and 0x30 is the Tag byte for the SEQUENCE data type.

So this code is designed to handle the BIT STRING and SEQUENCE data types. If you look at this part:

if($seq == 0x03)
{
    return substr($bin,3 + $bytes, $len);
}
else // $seq == 0x30
{
    $bin = substr($bin,2 + $bytes + $len);                  
}

you can see that the function is designed to skip over Sequences (0x30), until it finds a Bit String (0x03), at which point it returns the value of the Bit String.

You might be wondering why the magic number is 3 for Bit String and 2 for Sequence. That is because in a Bit String, the first value byte is a special extra field which indicates how many bits are unused in the last byte of the data. (For example, if you're sending 13 bits of data, it will take up 2 bytes = 16 bits, and the "unused bits" field will be 3.)

Next issue: the Length field. When the length of the Value is less than 128 bytes, the length is simply specified using a single byte (the most significant bit will be 0). If the length is 128 or greater, then the first length byte has bit 7 set, and the remaining 7 bits indicates how many following bytes contain the length (in big-endian order). More description here. The parsing of the length field happens in this section of the code:

$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]);
    }
}

After that, $bytes contains the number of extra bytes used by the length field, and $len contains the length of the Value field (in bytes).

Did you spot the error in the code? Remember,

If the length is 128 or greater, then the first length byte has bit 7 set, and the remaining 7 bits indicates how many following bytes contain the length.

but the code says $bytes = ($len & 0x0f), which only takes the lower 4 bits of the byte! It should be:

$bytes = ($len & 0x7f);

Of course, this error is only a problem for extremely long messages: it will work fine as long as the length value will fit within 0x0f = 15 bytes, meaning the data has to be less than 256^15 bytes. That's about a trillion yottabytes, which ought to be enough for anybody.

这篇关于这个代码如何提取签名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆