Files
xgcl/sm/sm9/asn1.go
T
2026-05-27 23:03:00 +08:00

302 lines
9.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}