import (
        "hash"
+       "io"
        "strconv"
 )
 
 // package.
 type Hash uint
 
+// HashFunc simply returns the value of h so that Hash implements SignerOpts.
+func (h Hash) HashFunc() Hash {
+       return h
+}
+
 const (
        MD4       Hash = 1 + iota // import code.google.com/p/go.crypto/md4
        MD5                       // import crypto/md5
 
 // PrivateKey represents a private key using an unspecified algorithm.
 type PrivateKey interface{}
+
+// Signer is an interface for an opaque private key that can be used for
+// signing operations. For example, an RSA key kept in a hardware module.
+type Signer interface {
+       // Public returns the public key corresponding to the opaque,
+       // private key.
+       Public() PublicKey
+
+       // Sign signs msg with the private key, possibly using entropy from
+       // rand. For an RSA key, the resulting signature should be either a
+       // PKCS#1 v1.5 or PSS signature (as indicated by opts). For an (EC)DSA
+       // key, it should be a DER-serialised, ASN.1 signature structure.
+       //
+       // Hash implements the SignerOpts interface and, in most cases, one can
+       // simply pass in the hash function used as opts. Sign may also attempt
+       // to type assert opts to other types in order to obtain algorithm
+       // specific values. See the documentation in each package for details.
+       Sign(rand io.Reader, msg []byte, opts SignerOpts) (signature []byte, err error)
+}
+
+// SignerOpts contains options for signing with a Signer.
+type SignerOpts interface {
+       // HashFunc returns an identifier for the hash function used to produce
+       // the message passed to Signer.Sign, or else zero to indicate that no
+       // hashing was done.
+       HashFunc() Hash
+}
 
 //     http://www.secg.org/download/aid-780/sec1-v2.pdf
 
 import (
+       "crypto"
        "crypto/elliptic"
+       "encoding/asn1"
        "io"
        "math/big"
 )
        D *big.Int
 }
 
+type ecdsaSignature struct {
+       R, S *big.Int
+}
+
+// Public returns the public key corresponding to priv.
+func (priv *PrivateKey) Public() crypto.PublicKey {
+       return &priv.PublicKey
+}
+
+// Sign signs msg with priv, reading randomness from rand. This method is
+// intended to support keys where the private part is kept in, for example, a
+// hardware module. Common uses should use the Sign function in this package
+// directly.
+func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
+       r, s, err := Sign(rand, priv, msg)
+       if err != nil {
+               return nil, err
+       }
+
+       return asn1.Marshal(ecdsaSignature{r, s})
+}
+
 var one = new(big.Int).SetInt64(1)
 
 // randFieldElement returns a random element of the field underlying the given
 
        // signature. It can either be a number of bytes, or one of the special
        // PSSSaltLength constants.
        SaltLength int
+
+       // Hash, if not zero, overrides the hash function passed to SignPSS.
+       // This is the only way to specify the hash function when using the
+       // crypto.Signer interface.
+       Hash crypto.Hash
+}
+
+// HashFunc returns pssOpts.Hash so that PSSOptions implements
+// crypto.SignerOpts.
+func (pssOpts *PSSOptions) HashFunc() crypto.Hash {
+       return pssOpts.Hash
 }
 
 func (opts *PSSOptions) saltLength() int {
                saltLength = hash.Size()
        }
 
+       if opts.Hash != 0 {
+               hash = opts.Hash
+       }
+
        salt := make([]byte, saltLength)
        if _, err = io.ReadFull(rand, salt); err != nil {
                return
 
 package rsa
 
 import (
+       "crypto"
        "crypto/rand"
        "crypto/subtle"
        "errors"
        Precomputed PrecomputedValues
 }
 
+// Public returns the public key corresponding to priv.
+func (priv *PrivateKey) Public() crypto.PublicKey {
+       return &priv.PublicKey
+}
+
+// Sign signs msg with priv, reading randomness from rand. If opts is a
+// *PSSOptions then the PSS algorithm will be used, otherwise PKCS#1 v1.5 will
+// be used. This method is intended to support keys where the private part is
+// kept in, for example, a hardware module. Common uses should use the Sign*
+// functions in this package.
+func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
+       if pssOpts, ok := opts.(*PSSOptions); ok {
+               return SignPSS(rand, priv, pssOpts.Hash, msg, pssOpts)
+       }
+
+       return SignPKCS1v15(rand, priv, opts.HashFunc(), msg)
+}
+
 type PrecomputedValues struct {
        Dp, Dq *big.Int // D mod (P-1) (or mod Q-1)
        Qinv   *big.Int // Q^-1 mod P
 
 // A Certificate is a chain of one or more certificates, leaf first.
 type Certificate struct {
        Certificate [][]byte
-       PrivateKey  crypto.PrivateKey // supported types: *rsa.PrivateKey, *ecdsa.PrivateKey
+       // PrivateKey contains the private key corresponding to the public key
+       // in Leaf. For a server, this must be a *rsa.PrivateKey or
+       // *ecdsa.PrivateKey. For a client doing client authentication, this
+       // can be any type that implements crypto.Signer (which includes RSA
+       // and ECDSA private keys).
+       PrivateKey crypto.PrivateKey
        // OCSPStaple contains an optional OCSP response which will be served
        // to clients that request it.
        OCSPStaple []byte
 
 
 import (
        "bytes"
+       "crypto"
        "crypto/ecdsa"
        "crypto/rsa"
        "crypto/subtle"
        "crypto/x509"
-       "encoding/asn1"
        "errors"
        "fmt"
        "io"
                }
 
                // We need to search our list of client certs for one
-               // where SignatureAlgorithm is RSA and the Issuer is in
-               // certReq.certificateAuthorities
+               // where SignatureAlgorithm is acceptable to the server and the
+               // Issuer is in certReq.certificateAuthorities
        findCert:
                for i, chain := range c.config.Certificates {
                        if !rsaAvail && !ecdsaAvail {
 
                                if len(certReq.certificateAuthorities) == 0 {
                                        // they gave us an empty list, so just take the
-                                       // first RSA cert from c.config.Certificates
+                                       // first cert from c.config.Certificates
                                        chainToSend = &chain
                                        break findCert
                                }
                        hasSignatureAndHash: c.vers >= VersionTLS12,
                }
 
-               switch key := c.config.Certificates[0].PrivateKey.(type) {
-               case *ecdsa.PrivateKey:
-                       digest, _, hashId := hs.finishedHash.hashForClientCertificate(signatureECDSA)
-                       r, s, err := ecdsa.Sign(c.config.rand(), key, digest)
-                       if err == nil {
-                               signed, err = asn1.Marshal(ecdsaSignature{r, s})
-                       }
+               key, ok := chainToSend.PrivateKey.(crypto.Signer)
+               if !ok {
+                       c.sendAlert(alertInternalError)
+                       return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey)
+               }
+               switch key.Public().(type) {
+               case *ecdsa.PublicKey:
+                       digest, hashFunc, hashId := hs.finishedHash.hashForClientCertificate(signatureECDSA)
+                       signed, err = key.Sign(c.config.rand(), digest, hashFunc)
                        certVerify.signatureAndHash.signature = signatureECDSA
                        certVerify.signatureAndHash.hash = hashId
-               case *rsa.PrivateKey:
+               case *rsa.PublicKey:
                        digest, hashFunc, hashId := hs.finishedHash.hashForClientCertificate(signatureRSA)
-                       signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest)
+                       signed, err = key.Sign(c.config.rand(), digest, hashFunc)
                        certVerify.signatureAndHash.signature = signatureRSA
                        certVerify.signatureAndHash.hash = hashId
                default:
-                       err = errors.New("unknown private key type")
+                       err = fmt.Errorf("tls: unknown client certificate key type: %T", key)
                }
                if err != nil {
                        c.sendAlert(alertInternalError)
 
        // Mathematical crypto: dependencies on fmt (L4) and math/big.
        // We could avoid some of the fmt, but math/big imports fmt anyway.
        "crypto/dsa":      {"L4", "CRYPTO", "math/big"},
-       "crypto/ecdsa":    {"L4", "CRYPTO", "crypto/elliptic", "math/big"},
+       "crypto/ecdsa":    {"L4", "CRYPTO", "crypto/elliptic", "math/big", "encoding/asn1"},
        "crypto/elliptic": {"L4", "CRYPTO", "math/big"},
        "crypto/rsa":      {"L4", "CRYPTO", "crypto/rand", "math/big"},