1// Copyright 2018 Google LLC 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//////////////////////////////////////////////////////////////////////////////// 16 17package signature 18 19import ( 20 "errors" 21 "fmt" 22 23 "github.com/google/tink/go/core/cryptofmt" 24 "github.com/google/tink/go/core/primitiveset" 25 "github.com/google/tink/go/internal/internalregistry" 26 "github.com/google/tink/go/internal/monitoringutil" 27 "github.com/google/tink/go/keyset" 28 "github.com/google/tink/go/monitoring" 29 "github.com/google/tink/go/tink" 30 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 31) 32 33// NewVerifier returns a Verifier primitive from the given keyset handle. 34func NewVerifier(handle *keyset.Handle) (tink.Verifier, error) { 35 ps, err := handle.Primitives() 36 if err != nil { 37 return nil, fmt.Errorf("verifier_factory: cannot obtain primitive set: %s", err) 38 } 39 return newWrappedVerifier(ps) 40} 41 42// verifierSet is a Verifier implementation that uses the 43// underlying primitive set for verifying. 44type wrappedVerifier struct { 45 ps *primitiveset.PrimitiveSet 46 logger monitoring.Logger 47} 48 49// Asserts that verifierSet implements the Verifier interface. 50var _ tink.Verifier = (*wrappedVerifier)(nil) 51 52func newWrappedVerifier(ps *primitiveset.PrimitiveSet) (*wrappedVerifier, error) { 53 if _, ok := (ps.Primary.Primitive).(tink.Verifier); !ok { 54 return nil, fmt.Errorf("verifier_factory: not a Verifier primitive") 55 } 56 57 for _, primitives := range ps.Entries { 58 for _, p := range primitives { 59 if _, ok := (p.Primitive).(tink.Verifier); !ok { 60 return nil, fmt.Errorf("verifier_factory: not an Verifier primitive") 61 } 62 } 63 } 64 logger, err := createVerifierLogger(ps) 65 if err != nil { 66 return nil, err 67 } 68 return &wrappedVerifier{ 69 ps: ps, 70 logger: logger, 71 }, nil 72} 73 74func createVerifierLogger(ps *primitiveset.PrimitiveSet) (monitoring.Logger, error) { 75 // only keysets which contain annotations are monitored. 76 if len(ps.Annotations) == 0 { 77 return &monitoringutil.DoNothingLogger{}, nil 78 } 79 keysetInfo, err := monitoringutil.KeysetInfoFromPrimitiveSet(ps) 80 if err != nil { 81 return nil, err 82 } 83 return internalregistry.GetMonitoringClient().NewLogger(&monitoring.Context{ 84 KeysetInfo: keysetInfo, 85 Primitive: "public_key_verify", 86 APIFunction: "verify", 87 }) 88} 89 90var errInvalidSignature = errors.New("verifier_factory: invalid signature") 91 92// Verify checks whether the given signature is a valid signature of the given data. 93func (v *wrappedVerifier) Verify(signature, data []byte) error { 94 prefixSize := cryptofmt.NonRawPrefixSize 95 if len(signature) < prefixSize { 96 return errInvalidSignature 97 } 98 99 // try non-raw keys 100 prefix := signature[:prefixSize] 101 signatureNoPrefix := signature[prefixSize:] 102 entries, err := v.ps.EntriesForPrefix(string(prefix)) 103 if err == nil { 104 for i := 0; i < len(entries); i++ { 105 var signedData []byte 106 if entries[i].PrefixType == tinkpb.OutputPrefixType_LEGACY { 107 signedData = make([]byte, 0, len(data)+1) 108 signedData = append(signedData, data...) 109 signedData = append(signedData, byte(0)) 110 } else { 111 signedData = data 112 } 113 114 verifier, ok := (entries[i].Primitive).(tink.Verifier) 115 if !ok { 116 return fmt.Errorf("verifier_factory: not an Verifier primitive") 117 } 118 119 if err = verifier.Verify(signatureNoPrefix, signedData); err == nil { 120 v.logger.Log(entries[i].KeyID, len(signedData)) 121 return nil 122 } 123 } 124 } 125 126 // try raw keys 127 entries, err = v.ps.RawEntries() 128 if err == nil { 129 for i := 0; i < len(entries); i++ { 130 verifier, ok := (entries[i].Primitive).(tink.Verifier) 131 if !ok { 132 return fmt.Errorf("verifier_factory: not an Verifier primitive") 133 } 134 135 if err = verifier.Verify(signature, data); err == nil { 136 v.logger.Log(entries[i].KeyID, len(data)) 137 return nil 138 } 139 } 140 } 141 v.logger.LogFailure() 142 return errInvalidSignature 143} 144