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 }