<p>ECDSA签名由两个数字组成,r和s是在[1..n-1]范围内的数字,其中n是曲线的顺序。n是[2^(k-1)…2^k-1]范围内的(已知)数字,其中k是密钥大小。因此r和s的大小通常是相同的,有时会比密钥大小(字节)小一些。在</p>
<p>现在r和s可以用多种方式编码,其中有两种是常见的:</p>
<ol>
<li>r和s在一个ASN.1序列中被DER编码为两个ASN.1有符号整数类型。在</li>
<li>r和s被编码为两个静态大小的无符号整数,其大小与密钥大小(或顺序)相同(以八位字节或字节为单位)。在</li>
</ol>
<p>所以大小的不同仅仅是因为r和s的编码方式不同。当然,在验证签名之前,您需要知道编码的类型。在</p>
<p>由于r和s完全独立于编码,所以在两个版本之间转换相对简单(如果您可以将任何需要生成或解析DER编码的ASN.1结构称为“simple”)。在</p>
<p>类型1在ansix9.62中已经被标准化,而类型2,通常称为平面编码,通常用于嵌入式平台或智能卡。在</p>
<hr/>
<p>r和s很可能与n/密钥大小相同,但原则上,它们可以是数字3。这种情况发生的可能性微乎其微。但是,您应该对r和s的大小执行任何测试。如果其中任何一个小于8字节,那么您可能会开始挠头,因为发生这种情况的可能性在1/2^63和1/2^64之间,即<em>极不可能</em>。在</p>
<hr/>
<p>所以:</p>
<ul>
<li>我误解了维基的文章。在</li>
</ul>
<p>不,wiki文章假设标准化编码是ansix9.62。在</p>
<ul>
<li>我错误地使用了python ecdsa</li>
</ul>
<p>不,python ecdsa包只是使用了不同的编码,您会感到惊讶。在</p>
<ul>
<li>比特币维基不正确</li>
</ul>
<p>不,比特币wiki假设他们的协议选择了一种特定的编码方式。在</p>
<ul>
<li>python ecdsa未正确实现</li>
</ul>
<p>绝对没有;至少在签名的大小上没有。在</p>
<hr/>
<p>现在了解实施细节;文档中包含以下内容:</p>
<blockquote>
<p>There are also multiple ways to represent a signature. The default <code>sk.sign()</code> and <code>vk.verify()</code> methods present it as a short string, for simplicity and minimal overhead. To use a different scheme, use the sk.sign(sigencode=) and vk.verify(sigdecode=) arguments. There are helper functions in the "ecdsa.util" module that can be useful here.</p>
</blockquote>
<p>所以尝试使用<code>sigencode=sigencode_der</code>来获得wiki文章所期望的格式。<a href="https://github.com/warner/python-ecdsa/blob/master/src/ecdsa/util.py" rel="nofollow noreferrer">^{<cd2>}</a>源具有您可能需要的所有转换。它使用<code>number_to_string</code>来创建静态大小的数字。此函数在PKCS#1(RSA)中也称为I2OSP或整数到八位字节字符串原语。请注意,代码中的“字符串”指的是八位字节字符串,也称为字节数组,而不是文本字符串。在</p>