// 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) }
// Sign performs a signature using the PKCS #11 key. func (ps *PKCS11Key) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) { // Verify that the length of the hash is as expected hash := opts.HashFunc() hashLen := hash.Size() if len(msg) != hashLen { err = errors.New("input size does not match hash function output size") return } // Add DigestInfo prefix // TODO: Switch mechanisms based on CKA_KEY_TYPE mechanism := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS, nil)} prefix, ok := hashPrefixes[hash] if !ok { err = errors.New("unknown hash function") return } signatureInput := append(prefix, msg...) // Open a session session, err := ps.openSession() if err != nil { return } defer ps.closeSession(session) // Perform the sign operation err = ps.module.SignInit(session, mechanism, ps.privateKeyHandle) if err != nil { return } signature, err = ps.module.Sign(session, signatureInput) return }
// Sign signs the given message with priv. // Ed25519 performs two passes over messages to be signed and therefore cannot // handle pre-hashed messages. Thus opts.HashFunc() must return zero to // indicate the message hasn't been hashed. This can be achieved by passing // crypto.Hash(0) as the value for opts. func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { if opts.HashFunc() != crypto.Hash(0) { return nil, errors.New("ed25519: cannot sign hashed message") } return Sign(priv, message), nil }
// Sign performs a signature using the PKCS #11 key. func (ps *Key) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) { ps.sessionMu.Lock() defer ps.sessionMu.Unlock() if ps.session == nil { return nil, errors.New("Session was nil") } // When the alwaysAuthenticate bit is true (e.g. on a Yubikey NEO in PIV mode), // each Sign has to include a Logout/Login, or the next Sign request will get // CKR_USER_NOT_LOGGED_IN. This is very slow, but on the NEO it's not possible // to clear the CKA_ALWAYS_AUTHENTICATE bit, so this is the only available // workaround. // Also, since logged in / logged out is application state rather than session // state, we take a global lock while we do the logout and login, and during // the signing. if ps.alwaysAuthenticate { modulesMu.Lock() defer modulesMu.Unlock() if err := ps.module.Logout(*ps.session); err != nil { return nil, fmt.Errorf("logout: %s", err) } if err = ps.module.Login(*ps.session, pkcs11.CKU_USER, ps.pin); err != nil { return nil, fmt.Errorf("login: %s", err) } } // Verify that the length of the hash is as expected hash := opts.HashFunc() hashLen := hash.Size() if len(msg) != hashLen { err = fmt.Errorf("input size does not match hash function output size: %d vs %d", len(msg), hashLen) return } // Add DigestInfo prefix // TODO: Switch mechanisms based on CKA_KEY_TYPE mechanism := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS, nil)} prefix, ok := hashPrefixes[hash] if !ok { err = errors.New("unknown hash function") return } signatureInput := append(prefix, msg...) // Perform the sign operation err = ps.module.SignInit(*ps.session, mechanism, ps.privateKeyHandle) if err != nil { return nil, fmt.Errorf("sign init: %s", err) } signature, err = ps.module.Sign(*ps.session, signatureInput) if err != nil { return nil, fmt.Errorf("sign: %s", err) } return }
// Sign implements the crypto.Signer operation for the given key. func (key *PrivateKey) Sign(r io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) { if len(msg) != opts.HashFunc().Size() { return nil, errors.New("input must be hashed message") } op := signOpFromKeyHash(key, opts.HashFunc()) if op == gokeyless.OpError { return nil, errors.New("invalid key type or hash") } return key.execute(op, msg) }
// Sign implements the crypto.Signer operation for the given key. func (key *PrivateKey) Sign(r io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) { if len(msg) != opts.HashFunc().Size() { return nil, errors.New("input must be hashed message") } conn, err := key.client.DialAny(key.ski) if err != nil { return nil, err } op := signOpFromKeyHash(key, opts.HashFunc()) if op == gokeyless.OpError { return nil, errors.New("invalid key type or hash") } return conn.KeyOperation(op, msg, key.ski, key.digest) }
func (pks *PKSigner) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) { // RSA is kind of a small disaster because of the way that the // crypto.Signer interface is laid out. // // For PKCS1v1.5 RSA signatures, the input to the actual // signature function is an ASN.1 DER-encoded // structure. WebCrypto has hash-specific mechanisms which // know how to generate that structure, but they all assume // the data is un-hashed, which is not the case with the // crypto.Signer interface, so we have to ues {hash: {name: // 'none'}}, which just performs the raw signature operation. // // This means we have to generate the ASN.1 structure // ourselves, which we can do by just having the correct // prefixes for all the hashes we might want to use. Prefixes // are taken from src/crypto/rsa/pkcs1v15.go. No other // signatures require this song and dance hash := hashNames[opts.HashFunc()] var algorithm js.M switch k := pks.Public().(type) { case *rsa.PublicKey: if pssOpts, ok := opts.(*rsa.PSSOptions); ok { algorithm = js.M{ "name": "RSA-PSS", "saltLength": pssOpts.SaltLength, "hash": js.M{"name": hash}, } } else { algorithm = js.M{ "name": "RSASSA-PKCS1-v1_5", "hash": js.M{"name": "none"}, } prefix, ok := hashPrefixes[opts.HashFunc()] if !ok { return nil, ErrUnsupportedHash } msg = append(prefix, msg...) } case *ecdsa.PublicKey: curveName, ok := curveNames[k.Curve] if !ok { return nil, ErrUnsupported } algorithm = js.M{ "name": "ECDSA", "hash": js.M{"name": hash}, "namedCurve": curveName, } } _, privkey, err := pks.pk.GetKeyPair(pks.cert.Raw, algorithm) if err != nil { return nil, err } return pks.pk.Sign(algorithm, privkey, msg) }