1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package subtle
import (
"errors"
"fmt"
"math/big"
"github.com/tink-crypto/tink-go/v2/internal/signature/ecdsa"
)
var errUnsupportedEncoding = errors.New("ecdsa: unsupported encoding")
// ECDSASignature is a struct holding the r and s values of an ECDSA signature.
type ECDSASignature struct {
R, S *big.Int
}
// NewECDSASignature creates a new ECDSASignature instance.
func NewECDSASignature(r, s *big.Int) *ECDSASignature {
return &ECDSASignature{R: r, S: s}
}
// EncodeECDSASignature converts the signature to the given encoding format.
func (sig *ECDSASignature) EncodeECDSASignature(encoding, curveName string) ([]byte, error) {
s := &ecdsa.Signature{R: sig.R, S: sig.S}
var enc []byte
var err error
switch encoding {
case "IEEE_P1363":
enc, err = ecdsa.IEEEP1363Encode(s, curveName)
case "DER":
enc, err = ecdsa.ASN1Encode(s)
default:
err = errUnsupportedEncoding
}
if err != nil {
return nil, fmt.Errorf("ecdsa: can't convert ECDSA signature to %s encoding: %v", encoding, err)
}
return enc, nil
}
// DecodeECDSASignature creates a new ECDSA signature using the given byte slice.
// The function assumes that the byte slice is the concatenation of the BigEndian
// representation of two big integer r and s.
func DecodeECDSASignature(encodedBytes []byte, encoding string) (*ECDSASignature, error) {
var sig *ecdsa.Signature
var err error
switch encoding {
case "IEEE_P1363":
sig, err = ecdsa.IEEEP1363Decode(encodedBytes)
case "DER":
sig, err = ecdsa.ASN1Decode(encodedBytes)
default:
err = errUnsupportedEncoding
}
if err != nil {
return nil, fmt.Errorf("ecdsa: %s", err)
}
return &ECDSASignature{R: sig.R, S: sig.S}, nil
}
// ValidateECDSAParams validates ECDSA parameters.
// The hash's strength must not be weaker than the curve's strength.
// DER and IEEE_P1363 encodings are supported.
func ValidateECDSAParams(hashAlg string, curve string, encoding string) error {
switch encoding {
case "DER":
case "IEEE_P1363":
default:
return errUnsupportedEncoding
}
switch curve {
case "NIST_P256":
if hashAlg != "SHA256" {
return errors.New("invalid hash type, expect SHA-256")
}
case "NIST_P384":
if hashAlg != "SHA384" && hashAlg != "SHA512" {
return errors.New("invalid hash type, expect SHA-384 or SHA-512")
}
case "NIST_P521":
if hashAlg != "SHA512" {
return errors.New("invalid hash type, expect SHA-512")
}
default:
return fmt.Errorf("unsupported curve: %s", curve)
}
return nil
}
|