// 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},
- "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},
+ "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.
func checkApprovedHashName(hash string) {
switch hash {
- case "SHA-224", "SHA-256", "SHA-384", "SHA-512":
+ case "SHA-224", "SHA-256", "SHA-384", "SHA-512", "SHA-512/224", "SHA-512/256",
+ "SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512":
default:
fips.RecordNonApproved()
}
--- /dev/null
+// Copyright 2024 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
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "testing"
+)
+
+func TestHashPrefixes(t *testing.T) {
+ prefixes := map[crypto.Hash]asn1.ObjectIdentifier{
+ // RFC 3370, Section 2.1 and 2.2
+ //
+ // sha-1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+ // oiw(14) secsig(3) algorithm(2) 26 }
+ //
+ // md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
+ // rsadsi(113549) digestAlgorithm(2) 5 }
+ crypto.MD5: {1, 2, 840, 113549, 2, 5},
+ crypto.SHA1: {1, 3, 14, 3, 2, 26},
+
+ // https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
+ //
+ // nistAlgorithms OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) country(16) us(840)
+ // organization(1) gov(101) csor(3) nistAlgorithm(4) }
+ //
+ // hashAlgs OBJECT IDENTIFIER ::= { nistAlgorithms 2 }
+ //
+ // id-sha256 OBJECT IDENTIFIER ::= { hashAlgs 1 }
+ // id-sha384 OBJECT IDENTIFIER ::= { hashAlgs 2 }
+ // id-sha512 OBJECT IDENTIFIER ::= { hashAlgs 3 }
+ // id-sha224 OBJECT IDENTIFIER ::= { hashAlgs 4 }
+ // id-sha512-224 OBJECT IDENTIFIER ::= { hashAlgs 5 }
+ // id-sha512-256 OBJECT IDENTIFIER ::= { hashAlgs 6 }
+ // id-sha3-224 OBJECT IDENTIFIER ::= { hashAlgs 7 }
+ // id-sha3-256 OBJECT IDENTIFIER ::= { hashAlgs 8 }
+ // id-sha3-384 OBJECT IDENTIFIER ::= { hashAlgs 9 }
+ // id-sha3-512 OBJECT IDENTIFIER ::= { hashAlgs 10 }
+ crypto.SHA224: {2, 16, 840, 1, 101, 3, 4, 2, 4},
+ crypto.SHA256: {2, 16, 840, 1, 101, 3, 4, 2, 1},
+ crypto.SHA384: {2, 16, 840, 1, 101, 3, 4, 2, 2},
+ crypto.SHA512: {2, 16, 840, 1, 101, 3, 4, 2, 3},
+ crypto.SHA512_224: {2, 16, 840, 1, 101, 3, 4, 2, 5},
+ crypto.SHA512_256: {2, 16, 840, 1, 101, 3, 4, 2, 6},
+ crypto.SHA3_224: {2, 16, 840, 1, 101, 3, 4, 2, 7},
+ crypto.SHA3_256: {2, 16, 840, 1, 101, 3, 4, 2, 8},
+ crypto.SHA3_384: {2, 16, 840, 1, 101, 3, 4, 2, 9},
+ crypto.SHA3_512: {2, 16, 840, 1, 101, 3, 4, 2, 10},
+ }
+
+ for h, oid := range prefixes {
+ want, err := asn1.Marshal(struct {
+ HashAlgorithm pkix.AlgorithmIdentifier
+ Hash []byte
+ }{
+ HashAlgorithm: pkix.AlgorithmIdentifier{
+ Algorithm: oid,
+ Parameters: asn1.NullRawValue,
+ },
+ Hash: make([]byte, h.Size()),
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+ want = want[:len(want)-h.Size()]
+ got := hashPrefixes[h.String()]
+ if !bytes.Equal(got, want) {
+ t.Errorf("%s: got %x, want %x", h, got, want)
+ }
+ }
+}