写这篇文章是为了在SM2签名编码解析上少走弯路,签名长度会超出我们预期的不同。
一、常规理解
SM2算法正常不做编码的签名长度为64个字节,即 R + S,各32个字节;
即使经过了ASN.1 DER编码,通常理解签名长度只有3种可能性,即:70字节、71字节、72个字节,分别对应:
70个字节: 3044 + 02 20 + 32个字节R + 02 20 + 32个字节S
如果R和S的第一个字节的最高位为1时,需要分别前导补0,即产生71个字节和72个字节编码
71个字节:3045 + 02 21 00 + 32个字节R + 02 20 + 32个字节S
3045 + 02 20 + 32个字节R + 02 21 00 + 32个字节S
72个字节: 3046 + 02 21 00 + 32个字节R + 02 21 00 + 32个字节S
二、实际存在的情况
在ANS.1 编码中,有以下几种特殊情况存储:
(1)69个字节
情形1:
3043
021F
2DF69838E2E40DE378C9B8A2FD40FB87425AF4DB9297B9337A9B6586CBFAF3
0220
67301CAC496D878723EC946F570922A3D84A6B8D2E618C6AD907E36B13D4833F:
情形2:
3043
0220
53EB989118AD14E1CA91A93769CCE234079169A94BFF645240D7DF59FFEF8B5E
021F
3B27E6F7849714C6A8EFD43C9E8045BA9B01477C7ADC3C7AFDF8056EBE05CF
如果R或S的数据存在前导0时,在实际编码过码中,会删掉前导00的长度。
如上是1F,表明第一个字节为00
(2)70个字节
情形1:
3044
021F
638026332E9FCD750647AFCFC2A5CFD3639D5BF1C9D619F23740241257FD3C
022100
9862D169D9F5BDA16848DB5D1BEDE5A616914680B6CADF1AE373A3D03D365ACF
情形2:
3044
022100
E92A4B5821120820CE2F45DFD58C07B9F1D69C7483009ADA9206678661FC5A65
021F
1DBED6061F0AAEFB3B444EBA2361E0B28A1EB5D8AC789F5D218DA8A8616E2F
情形3:(特别注意)
3044
0220
36A245F75927E7B8B09C9827F92B3913117771679B70838273BA547751778FC5
0220
00B1E4BCF9FF3ABADC596936FFBA0CA59C1A0E812DD7F5A9BEDC36863C11D119
3044
0220
0A7BF6655422E053B7E2D4C5609ED88DD98DC7B52A618A6474D01F86FE2B5614
0220
0084D6C1A052FA6FBCA036EDFACFEBBAB90A53442C3DCEA748AABCD41E7E1C91
特别注意这个数据,S数据存在00,但实际编码长度时,并未删除。
针对以上现象,需要注意的是,R或S数据中存在前导0时,是否删除,取决于其后一个字节,是否存在补位(即第一个字节最高位是否为1),从上面数据可知:
021F2D、021F1D、021F3B、021F63删除了前导0
022000B1、02200084 保留了前导0
均符合了上面的规律,因此在数据解析和编码时,要特别注意。