package sm9 import ( encoding_asn1 "encoding/asn1" "math/big" "time" "golang.org/x/crypto/cryptobyte" cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" "xdx.jelly/xgcl/gerrors" "xdx.jelly/xgcl/gmath" oid "xdx.jelly/xgcl/identifier" "xdx.jelly/xgcl/sm/sm9/errors" "xdx.jelly/xgcl/sm/sm9/internal/bn256" ) // GM/T 0080 SM9密码算法使用规范 // ASN.1编解码 // GMT/T 0006 OID定义 var ( OidSm9 = oid.OIDSM9 OidSm9Sign = oid.OIDSM9Signature OidSm9KeyExchange = oid.OIDSM9KeyExchange OidSm9Encryption = oid.OIDSM9Encryption OidSm9EncryptionEcb = oid.OIDSM9EncryptionECB OidSm9EncryptionCbc = oid.OIDSM9EncryptionCBC OidSm9EncryptionCfb = oid.OIDSM9EncryptionCFB OidSm9EncryptionOfb = oid.OIDSM9EncryptionOFB OidSM9KeyEncupsulate = oid.OIDSM9KeyEncupsulate ) const numBytes = 32 // Identifier GM/T 0090定义身份标识 // // deprecated: Identifier moves to package xdx.jelly/xibc type Identifier struct { // 标准中多了一个explicit Version int `asn1:"default:0"` IdentityType encoding_asn1.ObjectIdentifier Alias string `asn1:"utf8"` IdentityData []byte Serial *big.Int `asn1:"optional,explicit,tag:0"` ValidStart time.Time `asn1:"generalized"` ValidEnd time.Time `asn1:"optional,explicit,generalized,tag:1"` IdExtentions []byte `asn1:"optional,explicit,tag:2"` } func (id *Identifier) MarshalASN1() ([]byte, error) { return encoding_asn1.Marshal(*id) } func (id *Identifier) UnmarshalASN1(b []byte) (rest []byte, err error) { return encoding_asn1.Unmarshal(b, id) } //////////////////////////////////////////////////////////////// // // 主签名密钥 // //////////////////////////////////////////////////////////////// func (k *MastSignPrivateKey) MarshalASN1() ([]byte, error) { var b cryptobyte.Builder b.AddASN1BigInt(&k.Int) return b.Bytes() } func (k *MastSignPrivateKey) UnmarshalASN1(data []byte) (rest []byte, err error) { input := cryptobyte.String(data) ok := input.ReadASN1Integer(&k.Int) if !ok { return data, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse MastSignPrivateKey failed, read ASN.1 Integer error") } return []byte(input), nil } // MarshalASN1 返回ASN.1编码,如果compressed为true,则返回的是压缩形式 // // 注:不支持混合形式输出 func (k *MastSignPublicKey) MarshalASN1(compressed bool) ([]byte, error) { return k.G2.MarshalASN1(compressed) } // UnmarshalASN1 ASN.1解码MastSignPublicKey // // 注:支持tag为0,2,3,4,6,7即无穷远点(0),非压缩形式(4),压缩形式(2,3),混合形式(6,7) func (k *MastSignPublicKey) UnmarshalASN1(data []byte) (rest []byte, err error) { return k.G2.UnmarshalASN1(data) } //////////////////////////////////////////////////////////////// // // 主加密密钥 // //////////////////////////////////////////////////////////////// func (k *MastEncPrivateKey) MarshalASN1() ([]byte, error) { var b cryptobyte.Builder b.AddASN1BigInt(&k.Int) return b.Bytes() } func (k *MastEncPrivateKey) UnmarshalASN1(data []byte) (rest []byte, err error) { input := cryptobyte.String(data) ok := input.ReadASN1Integer(&k.Int) if !ok { return data, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse MastEncPrivateKey failed, read ASN.1 Integer error") } return []byte(input), nil } // MarshalASN1 返回ASN.1编码,如果compressed为true,则返回的是压缩形式 // // 注:不支持混合形式 func (k *MastEncPublicKey) MarshalASN1(compressed bool) ([]byte, error) { return k.G1.MarshalASN1(compressed) } // UnmarshalASN1 ASN.1解码MastSignPublicKey // // 注:支持tag为0,2,3,4,6,7即无穷远点(0),非压缩形式(4),压缩形式(2,3),混合形式(6,7) func (k *MastEncPublicKey) UnmarshalASN1(data []byte) (rest []byte, err error) { return k.G1.UnmarshalASN1(data) } //////////////////////////////////////////////////////////////// // // 用户密钥 // //////////////////////////////////////////////////////////////// func (u *UserSignKey) MarshalASN1(compressed bool) ([]byte, error) { return u.G1.MarshalASN1(compressed) } func (u *UserSignKey) UnmarshalASN1(data []byte) (rest []byte, err error) { return u.G1.UnmarshalASN1(data) } func (u *UserEncKey) MarshalASN1(compressed bool) ([]byte, error) { return u.G2.MarshalASN1(compressed) } func (u *UserEncKey) UnmarshalASN1(data []byte) (rest []byte, err error) { return u.G2.UnmarshalASN1(data) } //////////////////////////////////////////////////////////////// // // 签名结构 // //////////////////////////////////////////////////////////////// // SM9Signature ::= SEQUENCE{ // H OCTET STRING, ——杂凑分量,算法是H2(见GB/T 38635.2—2020) // S BIT STRING ——签名结果(见GB/T 38635.2—2020) // } func (s *Signature) MarshalASN1(compressed bool) ([]byte, error) { var b cryptobyte.Builder h := make([]byte, numBytes) err := gmath.FillBytes(&s.H, h) if err != nil { return nil, gerrors.WithAnnotating( gerrors.ChainErrors(errors.ErrDecodeASN1Failed, err), "Signature.H is bigger than 256 bits", ) } b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { b.AddASN1OctetString(h) b.AddASN1BitString(bn256.MarshalG1(&s.S, compressed)) }) return b.Bytes() } func (s *Signature) UnmarshalASN1(data []byte) (rest []byte, err error) { input := cryptobyte.String(data) var inner, hBytes cryptobyte.String var sBitString encoding_asn1.BitString if !input.ReadASN1(&inner, cryptobyte_asn1.SEQUENCE) || inner.Empty() || !inner.ReadASN1(&hBytes, cryptobyte_asn1.OCTET_STRING) || !inner.ReadASN1BitString(&sBitString) || !inner.Empty() { return data, errors.ErrDecodeASN1Failed } s.H.SetBytes(hBytes) _, err = bn256.UnmarshalG1(&s.S, sBitString.RightAlign()) if err != nil { return data, err } return []byte(input), err } //////////////////////////////////////////////////////////////// // // 密文结构 // //////////////////////////////////////////////////////////////// // SM9Cipher ::= SEQUENCE{ // EnType INTEGER, ——加密方式 // C1 BIT STRING, ——密文第一部分C1(见GB/T 38635.2—2020) // C3 OCTET STRING, ——密文杂凑值 // C2 OCTET STRING ——密文 // } func (c *Cipher) MarshalASN1(compressed bool) ([]byte, error) { var b cryptobyte.Builder c2Bytes := make([]byte, len(c.C)+len(c.IV)) n := 0 if c.EncType > 1 { n += copy(c2Bytes, c.IV[:]) } n += copy(c2Bytes[n:], c.C) c2Bytes = c2Bytes[:n] b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { b.AddASN1Int64(int64(c.EncType)) b.AddASN1BitString(bn256.MarshalG1(&c.C1, compressed)) b.AddASN1OctetString(c.H[:]) b.AddASN1OctetString(c2Bytes) }) return b.Bytes() } func (c *Cipher) UnmarshalASN1(data []byte) (rest []byte, err error) { input := cryptobyte.String(data) var inner, c3Bytes, c2Bytes cryptobyte.String var c1BitString encoding_asn1.BitString var encType uint32 if !input.ReadASN1(&inner, cryptobyte_asn1.SEQUENCE) || !inner.ReadASN1Integer(&encType) || !inner.ReadASN1BitString(&c1BitString) || !inner.ReadASN1(&c3Bytes, cryptobyte_asn1.OCTET_STRING) || !inner.ReadASN1(&c2Bytes, cryptobyte_asn1.OCTET_STRING) || !inner.Empty() { return data, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse Cipher ASN.1 data failed") } c.EncType = EncType(encType) _, err = bn256.UnmarshalG1(&c.C1, c1BitString.RightAlign()) if err != nil { return data, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse Cipher ASN.1 data failed") } if len(c3Bytes) != len(c.H) { return data, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse Cipher ASN.1 data failed") } copy(c.H[:], c3Bytes) if c.EncType > 1 { if len(c2Bytes) < len(c.IV) { return data, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse Cipher ASN.1 data failed") } copy(c.IV[:], c2Bytes) c2Bytes = c2Bytes[len(c.IV):] } c.C = append(c.C[:0], c2Bytes...) return []byte(input), nil } //////////////////////////////////////////////////////////////// // // 密文封装结构 // //////////////////////////////////////////////////////////////// // SM9KeyPackage ::= SEQUENCE{ // K OCTET STRING, ——生成的密钥 // C BIT STRING ——封装的交换密文 // } // K作为用户A保留的密钥。C作为交换密文传递给B用户,B用户利用C可以生成K。 // 这里与标准不同,只是封装C. 密钥不进行封装。即 // // SM9KeyPackage := OCTET STRING func (k *KeyPackage) MarshalASN1(compressed bool) ([]byte, error) { var b cryptobyte.Builder b.AddASN1BitString(bn256.MarshalG1(&k.G1, compressed)) return b.Bytes() } func (k *KeyPackage) UnmarshalASN1(data []byte) (rest []byte, err error) { input := cryptobyte.String(data) var b encoding_asn1.BitString if ok := input.ReadASN1BitString(&b); !ok { return data, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse KeyPackage ASN.1 data failed") } _, err = bn256.UnmarshalG1(&k.G1, b.RightAlign()) if err != nil { return data, gerrors.WithAnnotating( gerrors.ChainErrors(errors.ErrDecodeASN1Failed, err), "parse KeyPackage ASN.1 data failed", ) } return []byte(input), nil }