Files
2026-05-27 23:03:00 +08:00

163 lines
4.5 KiB
Go

package bn256
import (
"encoding/asn1"
"golang.org/x/crypto/cryptobyte"
"xdx.jelly/xgcl/gerrors"
"xdx.jelly/xgcl/sm/sm9/errors"
)
// return the bytes 04||x||y or 02(03)||x
func MarshalG1(p *G1, compressed bool) []byte {
data := make([]byte, 2*numBytes+1)
// infinity point is encoded as '00'
if p.IsInfinity() {
return []byte{0}
}
data[0] = 4
copy(data[1:], p.Marshal())
if compressed {
data[0] = 2 + data[2*numBytes]&1
data = data[:1+numBytes]
}
return data
}
func UnmarshalG1(p *G1, b []byte) (rest []byte, err error) {
// infinity case
if b[0] == 0 {
p.SetInfinity()
return b[1:], nil
}
if ((b[0] == 2 || b[0] == 3) && (len(b) < 1+numBytes)) ||
((b[0] == 4 || b[0] == 6 || b[0] == 7) && (len(b) < 1+2*numBytes)) {
return b, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse G1 ASN.1 data failed")
}
switch b[0] {
case 2:
_, _ = p.UnmarshalCompressed(b[1:1+numBytes], 0)
b = b[1+numBytes:]
case 3:
_, _ = p.UnmarshalCompressed(b[1:1+numBytes], 1)
b = b[1+numBytes:]
case 6, 7:
if (b[0] & 1) != b[len(b)-1]&1 {
return b, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse G1 ASN.1 data failed")
}
fallthrough
case 4:
_, err := p.Unmarshal(b[1:])
if err != nil {
return b, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse G1 ASN.1 data failed")
}
b = b[1+2*numBytes:]
default:
return b, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse G1 ASN.1 data failed, the leading byte of a EC point must be 2,3,4,6 or 7")
}
return b, nil
}
func MarshalG2(p *G2, compressed bool) []byte {
data := make([]byte, 4*numBytes+1)
// infinity case, the point is encoded as '00'
if p.IsInfinity() {
return []byte{0}
}
data[0] = 4
copy(data[1:], p.Marshal())
if compressed {
data[0] = 2 + data[4*numBytes]&1
data = data[:1+2*numBytes]
}
return data
}
func UnmarshalG2(p *G2, b []byte) (rest []byte, err error) {
// infinity case
if b[0] == 0 {
p.SetInfinity()
return b[1:], nil
}
if ((b[0] == 2 || b[0] == 3) && (len(b) < 1+2*numBytes)) ||
((b[0] == 4 || b[0] == 6 || b[0] == 7) && (len(b) < 1+4*numBytes)) {
return b, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse G2 ASN.1 data failed")
}
switch b[0] {
case 2:
_, _ = p.UnmarshalCompressed(b[1:1+numBytes], b[1+numBytes:1+2*numBytes], 0)
b = b[1+2*numBytes:]
case 3:
_, _ = p.UnmarshalCompressed(b[1:1+numBytes], b[1+numBytes:1+2*numBytes], 1)
b = b[1+2*numBytes:]
case 6, 7:
if (b[0] & 1) != b[len(b)-1]&1 {
return b, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse G2 ASN.1 data failed, the leading byte of a EC point must be 2,3,4,6 or 7")
}
fallthrough
case 4:
_, err := p.Unmarshal(b[1:])
if err != nil {
return b, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse G2 ASN.1 data failed")
}
b = b[1+4*numBytes:]
default:
return b, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse G2 ASN.1 data failed, the leading byte of a EC point must be 2,3,4,6 or 7")
}
return b, nil
}
// //////////////////////////////////////////////////////////////
//
// ASN.1 编解码G1,G2,
//
// //////////////////////////////////////////////////////////////
func (g *G1) MarshalASN1(compressed bool) ([]byte, error) {
var b cryptobyte.Builder
b.AddASN1BitString(MarshalG1(g, compressed))
return b.Bytes()
}
// UnmarshalASN1 ASN.1解码MastSignPublicKey
//
// 注:支持tag为0,2,3,4,6,7即无穷远点(0),非压缩形式(4),压缩形式(2,3),混合形式(6,7)
func (g *G1) UnmarshalASN1(data []byte) (rest []byte, err error) {
input := cryptobyte.String(data)
var b asn1.BitString
if ok := input.ReadASN1BitString(&b); !ok {
return data, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse G1 ASN.1 data failed")
}
_, err = UnmarshalG1(g, b.RightAlign())
if err != nil {
return data, err
}
return []byte(input), nil
}
func (g *G2) MarshalASN1(compressed bool) ([]byte, error) {
var b cryptobyte.Builder
b.AddASN1BitString(MarshalG2(g, compressed))
return b.Bytes()
}
// UnmarshalASN1 ASN.1解码MastSignPublicKey
//
// 注:支持tag为0,2,3,4,6,7即无穷远点(0),非压缩形式(4),压缩形式(2,3),混合形式(6,7)
func (g *G2) UnmarshalASN1(data []byte) (rest []byte, err error) {
input := cryptobyte.String(data)
var b asn1.BitString
if ok := input.ReadASN1BitString(&b); !ok {
return data, gerrors.WithAnnotating(errors.ErrDecodeASN1Failed, "parse G2 ASN.1 data failed")
}
_, err = UnmarshalG2(g, b.RightAlign())
if err != nil {
return data, err
}
return []byte(input), nil
}