blob: e4c2bb6e2a078ea97e0c92d7848bf2f98ef78c07 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package security
import (
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"v.io/v23/verror"
)
var (
errSignCantHash = verror.Register(pkgPath+".errSignCantHash", verror.NoRetry, "{1:}{2:}unable to create bytes to sign from message with hashing function {3}{:_}")
)
// Verify returns true iff sig is a valid signature for a message.
func (sig *Signature) Verify(key PublicKey, message []byte) bool {
if message = messageDigest(sig.Hash, sig.Purpose, message, key); message == nil {
return false
}
return key.verify(message, sig)
}
func (sig *Signature) digest(hashfn Hash) []byte {
var fields []byte
w := func(data []byte) {
fields = append(fields, hashfn.sum(data)...)
}
w([]byte(sig.Hash))
w(sig.Purpose)
w([]byte("ECDSA")) // The signing algorithm
w(sig.R)
w(sig.S)
return hashfn.sum(fields)
}
func messageDigest(hash Hash, purpose, message []byte, key PublicKey) []byte {
var fields []byte
w := func(data []byte) bool {
h := hash.sum(data)
if h == nil {
return false
}
fields = append(fields, h...)
return true
}
// In order to defend agains "Duplicate Signature Key Selection (DSKS)" attacks
// as defined in the paper "Another look at Security Definition" by Neal Koblitz
// and Alfred Menzes, we also include the public key of the signer in the message
// being signed.
keybytes, err := key.MarshalBinary()
if err != nil {
return nil
}
if !w(keybytes) {
return nil
}
if !w(message) {
return nil
}
if !w(purpose) {
return nil
}
return hash.sum(fields)
}
// sum returns the hash of data using hash as the cryptographic hash function.
// Returns nil if the hash function is not recognized.
func (hash Hash) sum(data []byte) []byte {
switch hash {
case SHA1Hash:
h := sha1.Sum(data)
return h[:]
case SHA256Hash:
h := sha256.Sum256(data)
return h[:]
case SHA384Hash:
h := sha512.Sum384(data)
return h[:]
case SHA512Hash:
h := sha512.Sum512(data)
return h[:]
}
return nil
}