github.com/letsencrypt/trillian@v1.1.2-0.20180615153820-ae375a99d36a/crypto/verifier.go (about)

     1  // Copyright 2017 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package crypto
    16  
    17  import (
    18  	"crypto"
    19  	"crypto/ecdsa"
    20  	"crypto/rsa"
    21  	"encoding/asn1"
    22  	"errors"
    23  	"fmt"
    24  	"math/big"
    25  
    26  	"github.com/google/trillian"
    27  	"github.com/google/trillian/types"
    28  )
    29  
    30  var errVerify = errors.New("signature verification failed")
    31  
    32  // VerifySignedLogRoot verifies the SignedLogRoot and returns its contents.
    33  func VerifySignedLogRoot(pub crypto.PublicKey, hash crypto.Hash, r *trillian.SignedLogRoot) (*types.LogRootV1, error) {
    34  	if err := Verify(pub, hash, r.LogRoot, r.LogRootSignature); err != nil {
    35  		return nil, err
    36  	}
    37  
    38  	var logRoot types.LogRootV1
    39  	if err := logRoot.UnmarshalBinary(r.LogRoot); err != nil {
    40  		return nil, err
    41  	}
    42  	return &logRoot, nil
    43  }
    44  
    45  // VerifySignedMapRoot verifies the signature on the SignedMapRoot.
    46  // VerifySignedMapRoot returns MapRootV1 to encourage safe API use.
    47  // It should be the only function available to clients that returns MapRootV1.
    48  func VerifySignedMapRoot(pub crypto.PublicKey, hash crypto.Hash, smr *trillian.SignedMapRoot) (*types.MapRootV1, error) {
    49  	if err := Verify(pub, hash, smr.MapRoot, smr.Signature); err != nil {
    50  		return nil, err
    51  	}
    52  	var root types.MapRootV1
    53  	if err := root.UnmarshalBinary(smr.MapRoot); err != nil {
    54  		return nil, err
    55  	}
    56  	return &root, nil
    57  }
    58  
    59  // Verify cryptographically verifies the output of Signer.
    60  func Verify(pub crypto.PublicKey, hasher crypto.Hash, data, sig []byte) error {
    61  	if sig == nil {
    62  		return errors.New("signature is nil")
    63  	}
    64  
    65  	h := hasher.New()
    66  	h.Write(data)
    67  	digest := h.Sum(nil)
    68  
    69  	switch pub := pub.(type) {
    70  	case *ecdsa.PublicKey:
    71  		return verifyECDSA(pub, digest, sig)
    72  	case *rsa.PublicKey:
    73  		return verifyRSA(pub, digest, sig, hasher, hasher)
    74  	default:
    75  		return fmt.Errorf("unknown private key type: %T", pub)
    76  	}
    77  }
    78  
    79  func verifyRSA(pub *rsa.PublicKey, hashed, sig []byte, hasher crypto.Hash, opts crypto.SignerOpts) error {
    80  	if pssOpts, ok := opts.(*rsa.PSSOptions); ok {
    81  		return rsa.VerifyPSS(pub, hasher, hashed, sig, pssOpts)
    82  	}
    83  	return rsa.VerifyPKCS1v15(pub, hasher, hashed, sig)
    84  }
    85  
    86  func verifyECDSA(pub *ecdsa.PublicKey, hashed, sig []byte) error {
    87  	var ecdsaSig struct {
    88  		R, S *big.Int
    89  	}
    90  	rest, err := asn1.Unmarshal(sig, &ecdsaSig)
    91  	if err != nil {
    92  		return errVerify
    93  	}
    94  	if len(rest) != 0 {
    95  		return errVerify
    96  	}
    97  
    98  	if !ecdsa.Verify(pub, hashed, ecdsaSig.R, ecdsaSig.S) {
    99  		return errVerify
   100  	}
   101  	return nil
   102  
   103  }