如何在OpenSSL ECDSA签名中区分ASN.1与P1363编码并修复测试失败
区分ECDSA的P1363编码签名与垃圾数据的解决方案
问题背景
ECDSA签名的r、s值编码无统一标准:OpenSSL采用DER编码的ASN.1序列,Windows使用IEEE P1363编码。修改OpenSSL 3中ec/ecdsa_assl.c文件的ossl_ecdsa_verify函数添加P1363处理逻辑后,虽能验证P1363签名,但导致OpenSSL自带ECDSA测试全部失败——负测试用例中的垃圾数据被误判为P1363编码,未被拦截。
核心区分方法
1. 严格校验签名长度
P1363编码的签名长度是固定值:2倍的椭圆曲线密钥字节长度。比如secp256r1曲线(256位密钥)对应的P1363签名必须是64字节,secp384r1则是96字节。
- ASN.1解码失败后,先检查签名长度是否符合当前曲线的固定P1363长度,不符合直接判定为垃圾数据。
2. 校验r、s的数值合法性
提取出r和s后,必须满足以下条件:
- r、s均为正整数(不能全0,也不能高位全0后仅低位为0);
- r、s的数值必须小于当前椭圆曲线的阶(n)。
可调用OpenSSL内置的BN_cmp函数,将提取出的r、s与曲线的阶做比较,确保两者处于(0, n)区间内,不满足则判定为垃圾数据。
3. 可选:增加格式指定参数
如果业务场景有明确的签名格式来源(如已知请求来自Windows/OpenSSL),可以给ossl_ecdsa_verify函数新增一个格式参数(比如int format,可选ECDSA_ASN1或ECDSA_P1363),让调用方明确指定要验证的签名格式,避免自动检测时的误判。
4. 验证兜底
通过前两步校验后,尝试用P1363格式验证签名,若验证失败直接返回错误,不再做其他格式的重试,避免垃圾数据绕过校验。
内容的提问来源于stack exchange,提问作者kzi
相关产品推荐
相关产品推荐

