return checkSignature(algo, signed, signature, c.PublicKey)
}
+func signaturePublicKeyAlgoMismatchError(expectedPubKeyAlgo PublicKeyAlgorithm, pubKey interface{}) error {
+ return fmt.Errorf("x509: signature algorithm specifies an %s public key, but have public key of type %T", expectedPubKeyAlgo.String(), pubKey)
+}
+
// CheckSignature verifies that signature is a valid signature over signed from
// a crypto.PublicKey.
func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey crypto.PublicKey) (err error) {
var hashType crypto.Hash
+ var pubKeyAlgo PublicKeyAlgorithm
- switch algo {
- case SHA1WithRSA, DSAWithSHA1, ECDSAWithSHA1:
- hashType = crypto.SHA1
- case SHA256WithRSA, SHA256WithRSAPSS, DSAWithSHA256, ECDSAWithSHA256:
- hashType = crypto.SHA256
- case SHA384WithRSA, SHA384WithRSAPSS, ECDSAWithSHA384:
- hashType = crypto.SHA384
- case SHA512WithRSA, SHA512WithRSAPSS, ECDSAWithSHA512:
- hashType = crypto.SHA512
- case MD2WithRSA, MD5WithRSA:
- return InsecureAlgorithmError(algo)
- default:
+ for _, details := range signatureAlgorithmDetails {
+ if details.algo == algo {
+ hashType = details.hash
+ pubKeyAlgo = details.pubKeyAlgo
+ }
+ }
+
+ switch hashType {
+ case crypto.Hash(0):
return ErrUnsupportedAlgorithm
+ case crypto.MD5:
+ return InsecureAlgorithmError(algo)
}
if !hashType.Available() {
switch pub := publicKey.(type) {
case *rsa.PublicKey:
+ if pubKeyAlgo != RSA {
+ return signaturePublicKeyAlgoMismatchError(pubKeyAlgo, pub)
+ }
if algo.isRSAPSS() {
return rsa.VerifyPSS(pub, hashType, digest, signature, &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash})
} else {
return rsa.VerifyPKCS1v15(pub, hashType, digest, signature)
}
case *dsa.PublicKey:
+ if pubKeyAlgo != DSA {
+ return signaturePublicKeyAlgoMismatchError(pubKeyAlgo, pub)
+ }
dsaSig := new(dsaSignature)
if rest, err := asn1.Unmarshal(signature, dsaSig); err != nil {
return err
}
return
case *ecdsa.PublicKey:
+ if pubKeyAlgo != ECDSA {
+ return signaturePublicKeyAlgoMismatchError(pubKeyAlgo, pub)
+ }
ecdsaSig := new(ecdsaSignature)
if rest, err := asn1.Unmarshal(signature, ecdsaSig); err != nil {
return err
}
}
+func TestMismatchedSignatureAlgorithm(t *testing.T) {
+ der, _ := pem.Decode([]byte(rsaPSSSelfSignedPEM))
+ if der == nil {
+ t.Fatal("Failed to find PEM block")
+ }
+
+ cert, err := ParseCertificate(der.Bytes)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err = cert.CheckSignature(ECDSAWithSHA256, nil, nil); err == nil {
+ t.Fatal("CheckSignature unexpectedly return no error")
+ }
+
+ const expectedSubstring = " but have public key of type "
+ if !strings.Contains(err.Error(), expectedSubstring) {
+ t.Errorf("Expected error containing %q, but got %q", expectedSubstring, err)
+ }
+}
+
var certBytes = "308203223082028ba00302010202106edf0d9499fd4533dd1297fc42a93be1300d06092a864886" +
"f70d0101050500304c310b3009060355040613025a4131253023060355040a131c546861777465" +
"20436f6e73756c74696e67202850747929204c74642e311630140603550403130d546861777465" +