|
11 | 11 | // |
12 | 12 | // Last updated: 2026-03-25 |
13 | 13 |
|
14 | | -export const TLS_VERSIONS: Record<number, string> = { |
| 14 | +// Lookup table type: known numeric keys return definite string literals, |
| 15 | +// arbitrary numeric keys return string | undefined. |
| 16 | +type LookupTable<T extends Record<number, string>> = Readonly<T> & { readonly [key: number]: string | undefined }; |
| 17 | +function lookupTable<const T extends Record<number, string>>(table: T): LookupTable<T> { |
| 18 | + return table as LookupTable<T>; |
| 19 | +} |
| 20 | + |
| 21 | +export const TLS_VERSIONS = lookupTable({ |
15 | 22 | 0x0300: 'SSL 3.0', |
16 | 23 | 0x0301: 'TLS 1.0', |
17 | 24 | 0x0302: 'TLS 1.1', |
18 | 25 | 0x0303: 'TLS 1.2', |
19 | 26 | 0x0304: 'TLS 1.3', |
20 | | -}; |
| 27 | +}); |
21 | 28 |
|
22 | 29 | // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 |
23 | | -export const CIPHER_SUITES: Record<number, string> = { |
| 30 | +export const CIPHER_SUITES = lookupTable({ |
24 | 31 | 0x0000: 'TLS_NULL_WITH_NULL_NULL', |
25 | 32 | 0x0001: 'TLS_RSA_WITH_NULL_MD5', |
26 | 33 | 0x0002: 'TLS_RSA_WITH_NULL_SHA', |
@@ -382,10 +389,10 @@ export const CIPHER_SUITES: Record<number, string> = { |
382 | 389 | 0xD002: 'TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384', |
383 | 390 | 0xD003: 'TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256', |
384 | 391 | 0xD005: 'TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256', |
385 | | -}; |
| 392 | +}); |
386 | 393 |
|
387 | 394 | // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml |
388 | | -export const EXTENSIONS: Record<number, string> = { |
| 395 | +export const EXTENSIONS = lookupTable({ |
389 | 396 | 0: 'server_name', |
390 | 397 | 1: 'max_fragment_length', |
391 | 398 | 2: 'client_certificate_url', |
@@ -452,10 +459,10 @@ export const EXTENSIONS: Record<number, string> = { |
452 | 459 | 65281: 'renegotiation_info', |
453 | 460 | // Non-IANA but widely deployed |
454 | 461 | 17513: 'application_settings', |
455 | | -}; |
| 462 | +}); |
456 | 463 |
|
457 | 464 | // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 |
458 | | -export const SUPPORTED_GROUPS: Record<number, string> = { |
| 465 | +export const SUPPORTED_GROUPS = lookupTable({ |
459 | 466 | 1: 'sect163k1', |
460 | 467 | 2: 'sect163r1', |
461 | 468 | 3: 'sect163r2', |
@@ -516,11 +523,11 @@ export const SUPPORTED_GROUPS: Record<number, string> = { |
516 | 523 | // Legacy explicit curves |
517 | 524 | 65281: 'arbitrary_explicit_prime_curves', |
518 | 525 | 65282: 'arbitrary_explicit_char2_curves', |
519 | | -}; |
| 526 | +}); |
520 | 527 |
|
521 | 528 | // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme |
522 | 529 | // Also includes legacy TLS 1.2 (hash, signature) byte-pair values from RFC 5246 section 7.4.1.4.1 |
523 | | -export const SIGNATURE_ALGORITHMS: Record<number, string> = { |
| 530 | +export const SIGNATURE_ALGORITHMS = lookupTable({ |
524 | 531 | // Legacy TLS 1.2 byte-pair schemes (hash << 8 | sig): hash 2=SHA-1, 3=SHA-224, 4=SHA-256, |
525 | 532 | // 5=SHA-384, 6=SHA-512; sig 1=RSA, 2=DSA, 3=ECDSA |
526 | 533 | 0x0201: 'rsa_pkcs1_sha1', |
@@ -581,36 +588,36 @@ export const SIGNATURE_ALGORITHMS: Record<number, string> = { |
581 | 588 | 0x091A: 'slhdsa_shake_192f', |
582 | 589 | 0x091B: 'slhdsa_shake_256s', |
583 | 590 | 0x091C: 'slhdsa_shake_256f', |
584 | | -}; |
| 591 | +}); |
585 | 592 |
|
586 | 593 | // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-9 |
587 | | -export const EC_POINT_FORMATS: Record<number, string> = { |
| 594 | +export const EC_POINT_FORMATS = lookupTable({ |
588 | 595 | 0: 'uncompressed', |
589 | 596 | 1: 'ansiX962_compressed_prime', |
590 | 597 | 2: 'ansiX962_compressed_char2', |
591 | | -}; |
| 598 | +}); |
592 | 599 |
|
593 | 600 | // https://www.iana.org/assignments/comp-meth-ids/comp-meth-ids.xhtml |
594 | | -export const COMPRESSION_METHODS: Record<number, string> = { |
| 601 | +export const COMPRESSION_METHODS = lookupTable({ |
595 | 602 | 0: 'null', |
596 | 603 | 1: 'DEFLATE', |
597 | | -}; |
| 604 | +}); |
598 | 605 |
|
599 | 606 | // RFC 8446 section 4.2.9 |
600 | | -export const PSK_KEY_EXCHANGE_MODES: Record<number, string> = { |
| 607 | +export const PSK_KEY_EXCHANGE_MODES = lookupTable({ |
601 | 608 | 0: 'psk_ke', |
602 | 609 | 1: 'psk_dhe_ke', |
603 | | -}; |
| 610 | +}); |
604 | 611 |
|
605 | 612 | // https://www.iana.org/assignments/tls-certificate-compression/tls-certificate-compression.xhtml |
606 | | -export const CERTIFICATE_COMPRESSION_ALGORITHMS: Record<number, string> = { |
| 613 | +export const CERTIFICATE_COMPRESSION_ALGORITHMS = lookupTable({ |
607 | 614 | 1: 'zlib', |
608 | 615 | 2: 'brotli', |
609 | 616 | 3: 'zstd', |
610 | | -}; |
| 617 | +}); |
611 | 618 |
|
612 | 619 | // RFC 6066 / RFC 6961 |
613 | | -export const CERTIFICATE_STATUS_TYPES: Record<number, string> = { |
| 620 | +export const CERTIFICATE_STATUS_TYPES = lookupTable({ |
614 | 621 | 1: 'ocsp', |
615 | 622 | 2: 'ocsp_multi', |
616 | | -}; |
| 623 | +}); |
0 commit comments