sm2: fix enveloped key issue #188

This commit is contained in:
Sun Yimin 2023-12-13 13:43:05 +08:00 committed by GitHub
parent fefb280170
commit 0f3d76705b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 24 deletions

View File

@ -4,6 +4,7 @@ import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509/pkix"
"encoding/asn1"
"errors"
"fmt"
@ -23,12 +24,12 @@ var (
// MarshalEnvelopedPrivateKey, returns sm2 key pair protected data with ASN.1 format:
//
// SM2EnvelopedKey ::= SEQUENCE {
// symAlgID AlgorithmIdentifier,
// symEncryptedKey SM2Cipher,
// sm2PublicKey SM2PublicKey,
// sm2EncryptedPrivateKey BIT STRING,
// }
// SM2EnvelopedKey ::= SEQUENCE {
// symAlgID AlgorithmIdentifier,
// symEncryptedKey SM2Cipher,
// sm2PublicKey SM2PublicKey,
// sm2EncryptedPrivateKey BIT STRING,
// }
//
// This implementation follows GB/T 35276-2017, uses SM4 cipher to encrypt sm2 private key.
// Please note the standard did NOT clarify if the ECB mode requires padding or not.
@ -59,10 +60,16 @@ func MarshalEnvelopedPrivateKey(rand io.Reader, pub *ecdsa.PublicKey, tobeEnvelo
return nil, err
}
symAlgID := pkix.AlgorithmIdentifier{
Algorithm: oidSM4ECB,
Parameters: asn1.NullRawValue,
}
symAlgIDBytes, _ := asn1.Marshal(symAlgID)
// marshal the result
var b cryptobyte.Builder
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
b.AddASN1ObjectIdentifier(oidSM4ECB) // use oidSM4?
b.AddBytes(symAlgIDBytes)
b.AddBytes(encryptedKey)
b.AddASN1BitString(elliptic.Marshal(tobeEnveloped.Curve, tobeEnveloped.X, tobeEnveloped.Y))
b.AddASN1BitString(encryptedPrivateKey)
@ -75,14 +82,14 @@ func MarshalEnvelopedPrivateKey(rand io.Reader, pub *ecdsa.PublicKey, tobeEnvelo
func ParseEnvelopedPrivateKey(priv *PrivateKey, enveloped []byte) (*PrivateKey, error) {
// unmarshal the asn.1 data
var (
symAlgId asn1.ObjectIdentifier
symAlgId pkix.AlgorithmIdentifier
encryptedPrivateKey, pub asn1.BitString
inner, symEncryptedKey cryptobyte.String
inner, symEncryptedKey, symAlgIdBytes cryptobyte.String
)
input := cryptobyte.String(enveloped)
if !input.ReadASN1(&inner, cryptobyte_asn1.SEQUENCE) ||
!input.Empty() ||
!inner.ReadASN1ObjectIdentifier(&symAlgId) ||
!inner.ReadASN1Element(&symAlgIdBytes, cryptobyte_asn1.SEQUENCE) ||
!inner.ReadASN1Element(&symEncryptedKey, cryptobyte_asn1.SEQUENCE) ||
!inner.ReadASN1BitString(&pub) ||
!inner.ReadASN1BitString(&encryptedPrivateKey) ||
@ -90,8 +97,12 @@ func ParseEnvelopedPrivateKey(priv *PrivateKey, enveloped []byte) (*PrivateKey,
return nil, errors.New("sm2: invalid asn1 format enveloped key")
}
if !(symAlgId.Equal(oidSM4) || symAlgId.Equal(oidSM4ECB)) {
return nil, fmt.Errorf("sm2: unsupported symmetric cipher <%v>", symAlgId)
if _, err := asn1.Unmarshal(symAlgIdBytes, &symAlgId); err != nil {
return nil, err
}
if !(symAlgId.Algorithm.Equal(oidSM4) || symAlgId.Algorithm.Equal(oidSM4ECB)) {
return nil, fmt.Errorf("sm2: unsupported symmetric cipher <%v>", symAlgId.Algorithm)
}
// parse public key

View File

@ -27,7 +27,7 @@ func TestMarshalEnvelopedPrivateKey(t *testing.T) {
}
func TestParseEnvelopedPrivateKey(t *testing.T) {
key, _ := hex.DecodeString("622dddddf4658c971e6485f1599a814a9aa0161aadcbc4f880d5841ea79561cb")
key, _ := hex.DecodeString("5cbd96822bb1491ec835ae9c09d4d3825e30bd9955e3c7031fbbe0e72d6fddf6")
sm2Key := new(sm2.PrivateKey)
sm2Key.D = new(big.Int).SetBytes(key)
sm2Key.Curve = sm2.P256()
@ -38,13 +38,13 @@ func TestParseEnvelopedPrivateKey(t *testing.T) {
t.Errorf("expected asn1 error, got %s", err)
}
decryptErr, _ := hex.DecodeString("3081ed06082a811ccf55016801307a022100e5ef46b1d4ebd964852e4166d345027625a38e0a17ad41c9febc7bf024f5efc7022100ca5bf589d32f8e9312196fcbb2624442f16e78470ee09dcf770e54eb28a2f3a9042084c55d419c24dbaa5814e9fde8f74e43c0a876a2055f9900ec6d25fd81e1a42104103c6ca06f337cfc666bf59fb02ad1d8d503420004e82a429129f2d73231edcf06f4dad403de94cae7ad565dd3dd511f7d404bef9edcf4e4c856808d797db90bae9ff1f77f6041435ded07b5d783605f5681c17681032100002f5ba3a33feb59e67be3ae4b087bcc42fec46e2d7f15f3b86162ab83965c74")
if _, err := sm2.ParseEnvelopedPrivateKey(sm2Key, decryptErr); err.Error() != "sm2: decryption error" {
t.Errorf("expected decrypt error, got %s", err)
}
invalidOID, _ := hex.DecodeString("3081ec06082a811ccf550168023079022010cae556013f072ae40873b3e0a4cef6bc841277da233b12f3d8676bb9b0f8a8022100f626c7122e8b7d977d60694bf876433a5a1a9298c109b541d35b928b8eed43550420423c303ec2c8ee14dcea529ffb887c781dcc2e0fc7b77acd1d355d6d344f62700410b9365ed091fde6bbd8152d09fa3a24e10342000445b8fadb3e0f932bfebfead4d686e8b3b7d215d60c4893b18152e3cf35eede1b06e62ca4943bfc8fd47d5651605b808bdde3f701e4d51783485903cfba6cc812032100c9fd8695e09d25c9974ae82f519aa1cdd7b7a7f29c0a5aa8cc93ec6384222fca")
invalidOID, _ := hex.DecodeString("3081ef300c06082a811ccf55016802050030780220760c5d4eb80f7ec4bb12026586e4badcd41c293b416618575894d9278214aa6c02203fea869801f94f1cf3839e9b666482703c86cef160af8a540daf9c6b9adff5b20420685f05616055daf4948e44d76c366b16745f7a487614c0542d16871baa34be8704104abfcab6cea65caf2c130b222ebe519903420004944a5887f6fad9808516755e81c62f41566dab0f56ca55ad7909880acc051ce157694b11557eba725291166508868e6988c596a30472bef32e03a3dcef6866270321003ec6b59fece00ca37336c12f6d529aa84be07597e315eda1b7b58b0bef2fead9")
if _, err := sm2.ParseEnvelopedPrivateKey(sm2Key, invalidOID); err.Error() != "sm2: unsupported symmetric cipher <1.2.156.10197.1.104.2>" {
t.Errorf("expected invalid oid error, got %s", err)
}
decryptErr, _ := hex.DecodeString("308183300c06082a811ccf550168010500300c06082a811ccf55016801050003420004cb51edb59a99b3b6bc894f203465bf04045eb8a85f5a14ba7c894aadbba7f7b5093e568351675d4ffd6d90be77ae182656eb98a80289358cd4ad4d65fafec5dc03210074bd8d993eeeb0220a664087b80478c43ddf322dd75e16db1642f5938ca34a0c")
if _, err := sm2.ParseEnvelopedPrivateKey(sm2Key, decryptErr); err.Error() != "sm2: ciphertext too short" {
t.Errorf("expected decrypt error, got %s", err)
}
}

View File

@ -1,9 +1,16 @@
## SM9 current supported functions:
1.Keys generation
2.Sign/Verify
3.Key Exchange
4.Wrap/Unwrap Key
5.Encryption/Decryption
* Keys generation密钥生成
* Sign/Verify (数字签名算法)
* Key Exchange (密钥交换协议)
* Wrap/Unwrap Key (密钥封装机制)
* Encryption/Decryption (公钥加密算法)
## Reference
* Information security technology—Identity-based cryptographic algorithms SM9—Part 1General《GB/T 38635.1-2020 信息安全技术 SM9标识密码算法 第1部分总则》
* Information security technology—Identity-based cryptographic algorithms SM9—Part 2Algorithms《GB/T 38635.2-2020 信息安全技术 SM9标识密码算法 第2部分算法》
* Information security technology—SM9 cryptographic algorithm application specification《GB/T 41389-2022 信息安全技术 SM9密码算法使用规范》
您可以从[国家标准全文公开系统](https://openstd.samr.gov.cn/)在线阅读这些标准。
## SM9 current performance (for reference only):

View File

@ -1,3 +1,10 @@
## Reference
* Information security technology—ZUC stream cipher algorithm—Part 1: Algorithm description 《GB/T 33133.1-2016 信息安全技术 祖冲之序列密码算法 第1部分算法描述》
* Information security technology—ZUC stream cipher algorithm—Part 2: Confidentiality algorithm 《GB/T 33133.2-2021 信息安全技术 祖冲之序列密码算法 第2部分保密性算法》
* Information security technology—ZUC stream cipher algorithm—Part 3: Integrity algorithm 《GB/T 33133.3-2021 信息安全技术 祖冲之序列密码算法 第3部分完整性算法》
您可以从[国家标准全文公开系统](https://openstd.samr.gov.cn/)在线阅读这些标准。
## ZUC original performance:
goos: windows