Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASN1 SM2密文含扩展部分 #90

Closed
Trisia opened this issue Oct 27, 2022 · 7 comments
Closed

ASN1 SM2密文含扩展部分 #90

Trisia opened this issue Oct 27, 2022 · 7 comments

Comments

@Trisia
Copy link
Contributor

Trisia commented Oct 27, 2022

以下是一个含有扩展填充2个字节0x00的ASN1 SM2 加密密文 C1C3C2

3081980220298ED52AE2A0EBA8B7567D54DF41C5F9B310EDFA4A8E15ECCB44EDA94F9F1FC20220116BE33B0833C95D8E5FF9483CD2D7EFF7033C92FE5DEAB6197D809FF1EEE05F042097A90979A6FCEBDE883C2E07E9C286818E694EDE37C3CDAA70E4CD481BE883E00430D62160BB179CB20CE3B5ECA0F5A535BEB6E221566C78FEA92105F71BD37F3F850AD2F86F2D1E35F15E9356557DAC026A0000

image

ASN1 是 TLV - Tag - Lenght - Value 的方式,理论上来说应该能够解析上述密文,忽略额外填充的0x00

目前该密文在使用在解析时

gmsm/sm2/sm2.go

Lines 452 to 469 in 9ba3e69

func unmarshalASN1Ciphertext(ciphertext []byte) (*big.Int, *big.Int, []byte, []byte, error) {
var (
x1, y1 = &big.Int{}, &big.Int{}
c2, c3 []byte
inner cryptobyte.String
)
input := cryptobyte.String(ciphertext)
if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
!input.Empty() ||
!inner.ReadASN1Integer(x1) ||
!inner.ReadASN1Integer(y1) ||
!inner.ReadASN1Bytes(&c3, asn1.OCTET_STRING) ||
!inner.ReadASN1Bytes(&c2, asn1.OCTET_STRING) ||
!inner.Empty() {
return nil, nil, nil, nil, errors.New("sm2: invalid asn1 format ciphertext")
}
return x1, y1, c2, c3, nil
}

将会出现错误 sm2: invalid asn1 format ciphertext"

在TLCP应用过程中我发现由于厂家不规范这样的问题频出,作者是否考虑 放宽对格式的校验?

emmansun added a commit that referenced this issue Oct 28, 2022
@emmansun
Copy link
Owner

v0.15.1

@Trisia Trisia closed this as completed Oct 28, 2022
@Trisia Trisia reopened this Oct 28, 2022
@Trisia
Copy link
Contributor Author

Trisia commented Oct 28, 2022

由于厂家不同,目前适配的厂家我发现他们的填充和也不一样,有时是0x00,有时是一串无意义的值,推测与动态内存分配有关,这里暂且不管这个。

建议在解析时对忽略C1C3C2长度以外的部分校验,只关心 C1 C3 C2 这样兼容性可能更好。

目前在TLCP库中我特判了类似情况。

这里想和作者讨论一下这个应该是业务层保证,输入数据的正确,还是您的库这边做兼容更合适?

@emmansun
Copy link
Owner

由于厂家不同,目前适配的厂家我发现他们的填充和也不一样,有时是0x00,有时是一串无意义的值,推测与动态内存分配有关,这里暂且不管这个。

建议在解析时对忽略C1C3C2长度以外的部分校验,只关心 C1 C3 C2 这样兼容性可能更好。

目前在TLCP库中我特判了类似情况。

这里想和作者讨论一下这个应该是业务层保证,输入数据的正确,还是您的库这边做兼容更合适?

严格来讲,如果密文不符合ASN.1规范,譬如有多余字节,应该是错误的。不过可以考虑在结构:

// DecrypterOpts decryption options
type DecrypterOpts struct {
	CiphertextEncoding      ciphertextEncoding
	CipherTextSplicingOrder ciphertextSplicingOrder
}

中增加一个flag,来容忍这种情况,忽略除第一个Sequence Tag以外的字节。

@emmansun
Copy link
Owner

签名没有这种情况?

@Trisia
Copy link
Contributor Author

Trisia commented Oct 28, 2022

签名似乎没有出现该问题,不过理论上来说也是存在的可能。

我推测该问题可能是类似于C程序的预分配内存导致,由于点坐标的不一定满足256比特,部分可能会存在前置的0x00的填充,这造成了在ASN.1 DER编码时,原来分配给256位的空间,可能会多出几位,预分配内存可能会出现多余的部分,这些多余的部分就随着协议直接发送了过来。

image

原则上来说却是含有就应该是不符合的数据。

您说的这个Tag是需要用户手动设置的吧,我认为这种类型也是可行的,我看有的做法是解析ASN1时,如果还有额外字节,那么吧这些额外的字节作为解析返回的额外参数 rest 字节交给用户,由用户来判断额外字节如何处理,类似于 pem 包的处理方式。

@emmansun
Copy link
Owner

emmansun commented Oct 28, 2022

如果只是纯粹的通用ASN.1解析工具,那么您说的类似pem解析的方式是可行的,不过调用方通常会判定rest长度是否为0,不是0会返回error。通常情况下,曲线点坐标如果位数不够,序列化时要前补0,有些实现反序列化时会检查长度,不够会直接报错。无论如何,这个厂家的实现不说错误(说错误也没毛病),至少是不规范的。golang SDK中NIST曲线签名ASN.1解析时处理一样严格。

@Trisia
Copy link
Contributor Author

Trisia commented Oct 29, 2022

那我认为该问题还是应该由应用侧来保证,而不是您的程序库。

该问题就是因为不规范的厂商导致,实际上这类类似问题在应用侧频出,所以应用侧完善最好。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants