如何用libtasn1的asn1Coding将大整数以十六进制编码入SEQUENCE?
问题背景
需要用libtasn1的asn1Coding工具将两个大整数编码到SEQUENCE中,密码学场景下的整数通常非常大,必须支持十六进制传入,但官方文档无相关指导。尝试0x30、\x30、"\x30\x01"等格式均被工具拒绝;传入超大整数时,工具会自动将其截断为最大支持值0x7fffffffffffffff,不符合预期。
相关文件及操作
x962.asn1定义文件
ECDSA { } DEFINITIONS EXPLICIT TAGS ::= BEGIN Signature ::= SEQUENCE { r INTEGER, s INTEGER } END
asn1.test测试文件(原错误版本)
dp ECDSA.Signature r "\x30\x01" s "\x40\x03"
调用命令
asn1Coding x962.asn1 asn1.test
错误输出
asn1Coding x962.asn1 asn1.test Parse: done.
var=dp, value=ECDSA.Signature var=r, value="\x30\x01" libtasn1 ERROR:
VALUE_NOT_VALID
大整数截断问题输出
Parse: done.
var=dp, value=X962.Signature var=r,
value=175969581411011301664416044449972632849 var=s,
value=175969581411011301664416044449972632849name:NULL type:SEQUENCE name:r type:INTEGER
value:0x7fffffffffffffff name:s type:INTEGER
value:0x7fffffffffffffffCoding: SUCCESS
----------------- Number of bytes=22 30 14 02 08 7f ff ff ff ff ff ff ff 02 08 7f ff ff ff ff ff ff ff
OutputFile=asn1.out
Writing: done.
正确使用方式
1. 十六进制整数的正确格式
asn1Coding对INTEGER的十六进制输入有严格要求:
- 直接使用不带引号的
0x前缀十六进制字符串,无需转义字符或引号 - 遵循ASN.1 INTEGER编码规则:如果字节序列最高位是1(如
0x80),需要在前面补一个0x00作为符号位,避免被识别为负数
示例修正后的asn1.test:
dp ECDSA.Signature r 0x3001 s 0x4003
若要表示0x80对应的整数,需写成0x0080。
2. 解决超大整数截断问题
工具默认用64位有符号整数存储数值,会截断超过0x7fffffffffffffff的值。直接使用十六进制格式传入超大整数即可绕过这个限制——工具会按字节序列处理,不受64位范围约束。
示例传入256位大整数:
dp ECDSA.Signature r 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF s 0x0000000000000000000000000000000000000000000000000000000000000001
验证结果
使用修正后的测试文件执行命令,工具会正确编码SEQUENCE,输出的DER字节符合预期,无截断或格式错误。
内容的提问来源于stack exchange,提问作者k_o_

