// Copyright 2009 The Go 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 rsa // This file implements signing and verification using PKCS #1 v1.5 signatures. import ( "bytes" "crypto/internal/fips140" "errors" ) // These are ASN1 DER structures: // // DigestInfo ::= SEQUENCE { // digestAlgorithm AlgorithmIdentifier, // digest OCTET STRING // } // // For performance, we don't use the generic ASN1 encoder. Rather, we // precompute a prefix of the digest value that makes a valid ASN1 DER string // with the correct contents. var hashPrefixes = map[string][]byte{ "MD5": {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}, "SHA-1": {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}, "SHA-224": {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c}, "SHA-256": {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}, "SHA-384": {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}, "SHA-512": {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}, "SHA-512/224": {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x05, 0x05, 0x00, 0x04, 0x1C}, "SHA-512/256": {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x06, 0x05, 0x00, 0x04, 0x20}, "SHA3-224": {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x07, 0x05, 0x00, 0x04, 0x1C}, "SHA3-256": {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08, 0x05, 0x00, 0x04, 0x20}, "SHA3-384": {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09, 0x05, 0x00, 0x04, 0x30}, "SHA3-512": {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0a, 0x05, 0x00, 0x04, 0x40}, "MD5+SHA1": {}, // A special TLS case which doesn't use an ASN1 prefix. "RIPEMD-160": {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14}, } // SignPKCS1v15 calculates an RSASSA-PKCS1-v1.5 signature. // // hash is the name of the hash function as returned by [crypto.Hash.String] // or the empty string to indicate that the message is signed directly. func SignPKCS1v15(priv *PrivateKey, hash string, hashed []byte) ([]byte, error) { fipsSelfTest() fips140.RecordApproved() checkApprovedHashName(hash) return signPKCS1v15(priv, hash, hashed) } func signPKCS1v15(priv *PrivateKey, hash string, hashed []byte) ([]byte, error) { em, err := pkcs1v15ConstructEM(&priv.pub, hash, hashed) if err != nil { return nil, err } return decrypt(priv, em, withCheck) } func pkcs1v15ConstructEM(pub *PublicKey, hash string, hashed []byte) ([]byte, error) { // Special case: "" is used to indicate that the data is signed directly. var prefix []byte if hash != "" { var ok bool prefix, ok = hashPrefixes[hash] if !ok { return nil, errors.New("crypto/rsa: unsupported hash function") } } // EM = 0x00 || 0x01 || PS || 0x00 || T k := pub.Size() if k < len(prefix)+len(hashed)+2+8+1 { return nil, ErrMessageTooLong } em := make([]byte, k) em[1] = 1 for i := 2; i < k-len(prefix)-len(hashed)-1; i++ { em[i] = 0xff } copy(em[k-len(prefix)-len(hashed):], prefix) copy(em[k-len(hashed):], hashed) return em, nil } // VerifyPKCS1v15 verifies an RSASSA-PKCS1-v1.5 signature. // // hash is the name of the hash function as returned by [crypto.Hash.String] // or the empty string to indicate that the message is signed directly. func VerifyPKCS1v15(pub *PublicKey, hash string, hashed []byte, sig []byte) error { fipsSelfTest() fips140.RecordApproved() checkApprovedHashName(hash) return verifyPKCS1v15(pub, hash, hashed, sig) } func verifyPKCS1v15(pub *PublicKey, hash string, hashed []byte, sig []byte) error { if fipsApproved, err := checkPublicKey(pub); err != nil { return err } else if !fipsApproved { fips140.RecordNonApproved() } // RFC 8017 Section 8.2.2: If the length of the signature S is not k // octets (where k is the length in octets of the RSA modulus n), output // "invalid signature" and stop. if pub.Size() != len(sig) { return ErrVerification } em, err := encrypt(pub, sig) if err != nil { return ErrVerification } expected, err := pkcs1v15ConstructEM(pub, hash, hashed) if err != nil { return ErrVerification } if !bytes.Equal(em, expected) { return ErrVerification } return nil } func checkApprovedHashName(hash string) { switch hash { case "SHA-224", "SHA-256", "SHA-384", "SHA-512", "SHA-512/224", "SHA-512/256", "SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512": default: fips140.RecordNonApproved() } }