| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- package p256
- import (
- "crypto/elliptic"
- "errors"
- "math/big"
- "filippo.io/bigmod"
- "golang.org/x/crypto/cryptobyte"
- "golang.org/x/crypto/cryptobyte/asn1"
- )
- var halfN = new(big.Int).Rsh(elliptic.P256().Params().N, 1)
- var nMod *bigmod.Modulus
- func init() {
- n, err := bigmod.NewModulus(elliptic.P256().Params().N.Bytes())
- if err != nil {
- panic(err)
- }
- nMod = n
- }
- func IsNormalized(sig []byte) (bool, error) {
- r, s, err := parseSignature(sig)
- if err != nil {
- return false, err
- }
- return checkLowS(r, s), nil
- }
- func checkLowS(_, s []byte) bool {
- bigS := new(big.Int).SetBytes(s)
- // Check if S <= (N/2), because we want to include the midpoint in the set of low-s
- return bigS.Cmp(halfN) <= 0
- }
- func swap(r, s []byte) ([]byte, []byte, error) {
- var err error
- bigS, err := bigmod.NewNat().SetBytes(s, nMod)
- if err != nil {
- return nil, nil, err
- }
- sNormalized := nMod.Nat().Sub(bigS, nMod)
- return r, sNormalized.Bytes(nMod), nil
- }
- func Normalize(sig []byte) ([]byte, error) {
- r, s, err := parseSignature(sig)
- if err != nil {
- return nil, err
- }
- if checkLowS(r, s) {
- return sig, nil
- }
- newR, newS, err := swap(r, s)
- if err != nil {
- return nil, err
- }
- return encodeSignature(newR, newS)
- }
- // Swap will change sig between its current form to the opposite high or low form.
- func Swap(sig []byte) ([]byte, error) {
- r, s, err := parseSignature(sig)
- if err != nil {
- return nil, err
- }
- newR, newS, err := swap(r, s)
- if err != nil {
- return nil, err
- }
- return encodeSignature(newR, newS)
- }
- // parseSignature taken exactly from crypto/ecdsa/ecdsa.go
- func parseSignature(sig []byte) (r, s []byte, err error) {
- var inner cryptobyte.String
- input := cryptobyte.String(sig)
- if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
- !input.Empty() ||
- !inner.ReadASN1Integer(&r) ||
- !inner.ReadASN1Integer(&s) ||
- !inner.Empty() {
- return nil, nil, errors.New("invalid ASN.1")
- }
- return r, s, nil
- }
- func encodeSignature(r, s []byte) ([]byte, error) {
- var b cryptobyte.Builder
- b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
- addASN1IntBytes(b, r)
- addASN1IntBytes(b, s)
- })
- return b.Bytes()
- }
- // addASN1IntBytes encodes in ASN.1 a positive integer represented as
- // a big-endian byte slice with zero or more leading zeroes.
- func addASN1IntBytes(b *cryptobyte.Builder, bytes []byte) {
- for len(bytes) > 0 && bytes[0] == 0 {
- bytes = bytes[1:]
- }
- if len(bytes) == 0 {
- b.SetError(errors.New("invalid integer"))
- return
- }
- b.AddASN1(asn1.INTEGER, func(c *cryptobyte.Builder) {
- if bytes[0]&0x80 != 0 {
- c.AddUint8(0)
- }
- c.AddBytes(bytes)
- })
- }
|