package su3 import ( "crypto" "crypto/dsa" "crypto/ecdsa" "crypto/rsa" "crypto/x509" "encoding/asn1" "errors" "math/big" ) type dsaSignature struct { R, S *big.Int } type ecdsaSignature dsaSignature func checkSignature(c *x509.Certificate, algo x509.SignatureAlgorithm, signed, signature []byte) (err error) { var hashType crypto.Hash switch algo { case x509.SHA1WithRSA, x509.DSAWithSHA1, x509.ECDSAWithSHA1: hashType = crypto.SHA1 case x509.SHA256WithRSA, x509.DSAWithSHA256, x509.ECDSAWithSHA256: hashType = crypto.SHA256 case x509.SHA384WithRSA, x509.ECDSAWithSHA384: hashType = crypto.SHA384 case x509.SHA512WithRSA, x509.ECDSAWithSHA512: hashType = crypto.SHA512 default: return x509.ErrUnsupportedAlgorithm } if !hashType.Available() { return x509.ErrUnsupportedAlgorithm } h := hashType.New() h.Write(signed) digest := h.Sum(nil) switch pub := c.PublicKey.(type) { case *rsa.PublicKey: // the digest is already hashed, so we force a 0 here return rsa.VerifyPKCS1v15(pub, 0, digest, signature) case *dsa.PublicKey: dsaSig := new(dsaSignature) if _, err := asn1.Unmarshal(signature, dsaSig); err != nil { return err } if dsaSig.R.Sign() <= 0 || dsaSig.S.Sign() <= 0 { return errors.New("x509: DSA signature contained zero or negative values") } if !dsa.Verify(pub, digest, dsaSig.R, dsaSig.S) { return errors.New("x509: DSA verification failure") } return case *ecdsa.PublicKey: ecdsaSig := new(ecdsaSignature) if _, err := asn1.Unmarshal(signature, ecdsaSig); err != nil { return err } if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { return errors.New("x509: ECDSA signature contained zero or negative values") } if !ecdsa.Verify(pub, digest, ecdsaSig.R, ecdsaSig.S) { return errors.New("x509: ECDSA verification failure") } return } return x509.ErrUnsupportedAlgorithm }