github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/primitive/secp256k1/subtle/encoding.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package subtle
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/asn1"
    12  	"fmt"
    13  	"math/big"
    14  
    15  	"github.com/btcsuite/btcd/btcec/v2"
    16  )
    17  
    18  // asn1encode encodes the given ECDSA signature using ASN.1 encoding.
    19  func asn1encode(sig *Secp256k1Signature) ([]byte, error) {
    20  	ret, err := asn1.Marshal(*sig)
    21  	if err != nil {
    22  		return nil, fmt.Errorf("asn.1 encoding failed")
    23  	}
    24  
    25  	return ret, nil
    26  }
    27  
    28  var errAsn1Decoding = fmt.Errorf("asn.1 decoding failed")
    29  
    30  // asn1decode verifies the given ECDSA signature and decodes it if it is valid.
    31  // Since asn1.Unmarshal() doesn't do a strict verification on its input, it will
    32  // accept signatures with trailing data. Therefore, we add an additional check to make sure
    33  // that the input follows strict DER encoding: after unmarshalling the signature bytes,
    34  // we marshal the obtained signature object again. Since DER encoding is deterministic,
    35  // we expect that the obtained bytes would be equal to the input.
    36  func asn1decode(b []byte) (*Secp256k1Signature, error) {
    37  	sig := new(Secp256k1Signature)
    38  
    39  	_, err := asn1.Unmarshal(b, sig) // der encoding does not work for Secp256k1 keys.
    40  	if err != nil {
    41  		return nil, errAsn1Decoding
    42  	}
    43  
    44  	// encode the signature again
    45  	encoded, err := asn1.Marshal(*sig)
    46  	if err != nil {
    47  		return nil, errAsn1Decoding
    48  	}
    49  
    50  	if !bytes.Equal(b, encoded) {
    51  		return nil, errAsn1Decoding
    52  	}
    53  
    54  	return sig, nil
    55  }
    56  
    57  func ieeeSignatureSize(curveName string) (int, error) {
    58  	switch curveName {
    59  	case btcec.S256().Params().Name:
    60  		return 64, nil //nolint:gomnd
    61  	default:
    62  		return 0, fmt.Errorf("ieeeP1363 unsupported curve name: %q", curveName)
    63  	}
    64  }
    65  
    66  func ieeeP1363Encode(sig *Secp256k1Signature, curveName string) ([]byte, error) {
    67  	two := 2
    68  
    69  	sigSize, err := ieeeSignatureSize(curveName)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	enc := make([]byte, sigSize)
    75  
    76  	// sigR and sigS must be half the size of the signature. If not, we need to pad them with zeros.
    77  	offset := 0
    78  	if len(sig.R.Bytes()) < (sigSize / two) {
    79  		offset += (sigSize / two) - len(sig.R.Bytes())
    80  	}
    81  
    82  	// Copy sigR after any zero-padding.
    83  	copy(enc[offset:], sig.R.Bytes())
    84  
    85  	// Skip the bytes of sigR.
    86  	offset = sigSize / two
    87  	if len(sig.S.Bytes()) < (sigSize / two) {
    88  		offset += (sigSize / two) - len(sig.S.Bytes())
    89  	}
    90  
    91  	// Copy sigS after sigR and any zero-padding.
    92  	copy(enc[offset:], sig.S.Bytes())
    93  
    94  	return enc, nil
    95  }
    96  
    97  func ieeeP1363Decode(encodedBytes []byte) (*Secp256k1Signature, error) {
    98  	if len(encodedBytes) == 0 || len(encodedBytes) > 132 || len(encodedBytes)%2 != 0 {
    99  		return nil, fmt.Errorf("ecdsa: Invalid IEEE_P1363 encoded bytes")
   100  	}
   101  
   102  	r := new(big.Int).SetBytes(encodedBytes[:len(encodedBytes)/2])
   103  	s := new(big.Int).SetBytes(encodedBytes[len(encodedBytes)/2:])
   104  
   105  	return &Secp256k1Signature{R: r, S: s}, nil
   106  }