Skip to content

Commit 76e8bb4

Browse files
committed
CipherSuite
1 parent efe8ae3 commit 76e8bb4

9 files changed

Lines changed: 223 additions & 19 deletions

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Implemented (interface files) — ordered by RFC section
5151

5252
Enums / identifiers
5353

54+
- [`src/MLS/Enums/CipherSuite.php`](src/MLS/Enums/CipherSuite.php) — RFC 9420: Cipher Suites ([Table 6](https://www.rfc-editor.org/rfc/rfc9420.html#table-6) & [Table 7](https://www.rfc-editor.org/rfc/rfc9420.html#table-7))
5455
- [`src/MLS/Enums/MessageWireFormat.php`](src/MLS/Enums/MessageWireFormat.php) — RFC 9420: MLS Wire Formats ([Table 8](https://www.rfc-editor.org/rfc/rfc9420.html#table-9))
5556
- [`src/MLS/Enums/ExtensionType.php`](src/MLS/Enums/ExtensionType.php) — RFC 9420: MLS Extension Types ([Table 9](https://www.rfc-editor.org/rfc/rfc9420.html#table-9))
5657
- [`src/MLS/Enums/ProposalType.php`](src/MLS/Enums/ProposalType.php) — RFC 9420: MLS Proposal Types ([Table 10](https://www.rfc-editor.org/rfc/rfc9420.html#table-9))

src/MLS/Enums/CipherSuite.php

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MLS\Enums;
6+
7+
/**
8+
* MLS Cipher Suites (RFC 9420 - Section 17.1, Tables 6 & 7)
9+
*/
10+
final class CipherSuite
11+
{
12+
public const RESERVED = 0x0000;
13+
14+
public const MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 = 0x0001;
15+
public const MLS_128_DHKEMP256_AES128GCM_SHA256_P256 = 0x0002;
16+
public const MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519 = 0x0003;
17+
public const MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448 = 0x0004;
18+
public const MLS_256_DHKEMP521_AES256GCM_SHA512_P521 = 0x0005;
19+
public const MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448 = 0x0006;
20+
public const MLS_256_DHKEMP384_AES256GCM_SHA384_P384 = 0x0007;
21+
22+
// GREASE values
23+
public const GREASE_0A0A = 0x0A0A;
24+
public const GREASE_1A1A = 0x1A1A;
25+
public const GREASE_2A2A = 0x2A2A;
26+
public const GREASE_3A3A = 0x3A3A;
27+
public const GREASE_4A4A = 0x4A4A;
28+
public const GREASE_5A5A = 0x5A5A;
29+
public const GREASE_6A6A = 0x6A6A;
30+
public const GREASE_7A7A = 0x7A7A;
31+
public const GREASE_8A8A = 0x8A8A;
32+
public const GREASE_9A9A = 0x9A9A;
33+
public const GREASE_AAAA = 0xAAAA;
34+
public const GREASE_BABA = 0xBABA;
35+
public const GREASE_CACA = 0xCACA;
36+
public const GREASE_DADA = 0xDADA;
37+
public const GREASE_EAEA = 0xEAEA;
38+
39+
public const PRIVATE_USE_START = 0xF000;
40+
public const PRIVATE_USE_END = 0xFFFF;
41+
42+
protected const NAME_MAP = [
43+
self::RESERVED => 'reserved',
44+
self::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 => 'MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519',
45+
self::MLS_128_DHKEMP256_AES128GCM_SHA256_P256 => 'MLS_128_DHKEMP256_AES128GCM_SHA256_P256',
46+
self::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519 => 'MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519',
47+
self::MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448 => 'MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448',
48+
self::MLS_256_DHKEMP521_AES256GCM_SHA512_P521 => 'MLS_256_DHKEMP521_AES256GCM_SHA512_P521',
49+
self::MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448 => 'MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448',
50+
self::MLS_256_DHKEMP384_AES256GCM_SHA384_P384 => 'MLS_256_DHKEMP384_AES256GCM_SHA384_P384',
51+
self::GREASE_0A0A => 'grease_0a0a',
52+
self::GREASE_1A1A => 'grease_1a1a',
53+
self::GREASE_2A2A => 'grease_2a2a',
54+
self::GREASE_3A3A => 'grease_3a3a',
55+
self::GREASE_4A4A => 'grease_4a4a',
56+
self::GREASE_5A5A => 'grease_5a5a',
57+
self::GREASE_6A6A => 'grease_6a6a',
58+
self::GREASE_7A7A => 'grease_7a7a',
59+
self::GREASE_8A8A => 'grease_8a8a',
60+
self::GREASE_9A9A => 'grease_9a9a',
61+
self::GREASE_AAAA => 'grease_aaaa',
62+
self::GREASE_BABA => 'grease_baba',
63+
self::GREASE_CACA => 'grease_caca',
64+
self::GREASE_DADA => 'grease_dada',
65+
self::GREASE_EAEA => 'grease_eaea',
66+
];
67+
68+
// Recommended flags per registry (true = recommended)
69+
protected const RECOMMENDED = [
70+
self::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 => true,
71+
self::MLS_128_DHKEMP256_AES128GCM_SHA256_P256 => true,
72+
self::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519 => true,
73+
self::MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448 => true,
74+
self::MLS_256_DHKEMP521_AES256GCM_SHA512_P521 => true,
75+
self::MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448 => true,
76+
self::MLS_256_DHKEMP384_AES256GCM_SHA384_P384 => true,
77+
self::GREASE_0A0A => true,
78+
self::GREASE_1A1A => true,
79+
self::GREASE_2A2A => true,
80+
self::GREASE_3A3A => true,
81+
self::GREASE_4A4A => true,
82+
self::GREASE_5A5A => true,
83+
self::GREASE_6A6A => true,
84+
self::GREASE_7A7A => true,
85+
self::GREASE_8A8A => true,
86+
self::GREASE_9A9A => true,
87+
self::GREASE_AAAA => true,
88+
self::GREASE_BABA => true,
89+
self::GREASE_CACA => true,
90+
self::GREASE_DADA => true,
91+
self::GREASE_EAEA => true,
92+
];
93+
94+
// Component mapping per cipher suite (Table 7)
95+
protected const COMPONENTS = [
96+
self::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 => [
97+
'kem' => 0x0020,
98+
'kdf' => 0x0001,
99+
'aead' => 0x0001,
100+
'hash' => 'SHA256',
101+
'signature' => 'ed25519',
102+
],
103+
self::MLS_128_DHKEMP256_AES128GCM_SHA256_P256 => [
104+
'kem' => 0x0010,
105+
'kdf' => 0x0001,
106+
'aead' => 0x0001,
107+
'hash' => 'SHA256',
108+
'signature' => 'ecdsa_secp256r1_sha256',
109+
],
110+
self::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519 => [
111+
'kem' => 0x0020,
112+
'kdf' => 0x0001,
113+
'aead' => 0x0003,
114+
'hash' => 'SHA256',
115+
'signature' => 'ed25519',
116+
],
117+
self::MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448 => [
118+
'kem' => 0x0021,
119+
'kdf' => 0x0003,
120+
'aead' => 0x0002,
121+
'hash' => 'SHA512',
122+
'signature' => 'ed448',
123+
],
124+
self::MLS_256_DHKEMP521_AES256GCM_SHA512_P521 => [
125+
'kem' => 0x0012,
126+
'kdf' => 0x0003,
127+
'aead' => 0x0002,
128+
'hash' => 'SHA512',
129+
'signature' => 'ecdsa_secp521r1_sha512',
130+
],
131+
self::MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448 => [
132+
'kem' => 0x0021,
133+
'kdf' => 0x0003,
134+
'aead' => 0x0003,
135+
'hash' => 'SHA512',
136+
'signature' => 'ed448',
137+
],
138+
self::MLS_256_DHKEMP384_AES256GCM_SHA384_P384 => [
139+
'kem' => 0x0011,
140+
'kdf' => 0x0002,
141+
'aead' => 0x0002,
142+
'hash' => 'SHA384',
143+
'signature' => 'ecdsa_secp384r1_sha384',
144+
],
145+
];
146+
147+
private function __construct()
148+
{
149+
}
150+
151+
public static function nameOf(int $value): ?string
152+
{
153+
if (isset(self::NAME_MAP[$value])) {
154+
return self::NAME_MAP[$value];
155+
}
156+
157+
if ($value >= self::PRIVATE_USE_START && $value <= self::PRIVATE_USE_END) {
158+
return 'private_use';
159+
}
160+
161+
return null;
162+
}
163+
164+
public static function isRecommended(int $value): ?bool
165+
{
166+
return self::RECOMMENDED[$value] ?? null;
167+
}
168+
169+
public static function isPrivateUse(int $value): bool
170+
{
171+
return $value >= self::PRIVATE_USE_START && $value <= self::PRIVATE_USE_END;
172+
}
173+
174+
public static function componentsOf(int $value): ?array
175+
{
176+
return self::COMPONENTS[$value] ?? null;
177+
}
178+
179+
public static function kemOf(int $value): ?int
180+
{
181+
return isset(self::COMPONENTS[$value]) ? self::COMPONENTS[$value]['kem'] : null;
182+
}
183+
184+
public static function kdfOf(int $value): ?int
185+
{
186+
return isset(self::COMPONENTS[$value]) ? self::COMPONENTS[$value]['kdf'] : null;
187+
}
188+
189+
public static function aeadOf(int $value): ?int
190+
{
191+
return isset(self::COMPONENTS[$value]) ? self::COMPONENTS[$value]['aead'] : null;
192+
}
193+
194+
public static function hashOf(int $value): ?string
195+
{
196+
return isset(self::COMPONENTS[$value]) ? self::COMPONENTS[$value]['hash'] : null;
197+
}
198+
199+
public static function signatureOf(int $value): ?string
200+
{
201+
return isset(self::COMPONENTS[$value]) ? self::COMPONENTS[$value]['signature'] : null;
202+
}
203+
}

src/MLS/Enums/CredentialType.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ final class CredentialType
3333
public const PRIVATE_USE_START = 0xF000;
3434
public const PRIVATE_USE_END = 0xFFFF;
3535

36-
private const NAME_MAP = [
36+
protected const NAME_MAP = [
3737
self::RESERVED => 'reserved',
3838
self::BASIC => 'basic',
3939
self::X509 => 'x509',
@@ -54,7 +54,7 @@ final class CredentialType
5454
self::GREASE_EAEA => 'grease_eaea',
5555
];
5656

57-
private const RECOMMENDED = [
57+
protected const RECOMMENDED = [
5858
self::BASIC => true,
5959
self::X509 => true,
6060
];

src/MLS/Enums/ExtensionType.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ final class ExtensionType
3636
public const PRIVATE_USE_START = 0xF000;
3737
public const PRIVATE_USE_END = 0xFFFF;
3838

39-
private const NAME_MAP = [
39+
protected const NAME_MAP = [
4040
self::RESERVED => 'reserved',
4141
self::APPLICATION_ID => 'application_id',
4242
self::RATCHET_TREE => 'ratchet_tree',
@@ -60,7 +60,7 @@ final class ExtensionType
6060
self::GREASE_EAEA => 'grease_eaea',
6161
];
6262

63-
private const MESSAGE_MAP = [
63+
protected const MESSAGE_MAP = [
6464
self::APPLICATION_ID => ['LN'],
6565
self::RATCHET_TREE => ['GI'],
6666
self::REQUIRED_CAPABILITIES => ['GC'],
@@ -83,7 +83,7 @@ final class ExtensionType
8383
self::GREASE_EAEA => ['KP','GI','LN'],
8484
];
8585

86-
private const RECOMMENDED = [
86+
protected const RECOMMENDED = [
8787
self::APPLICATION_ID => true,
8888
self::RATCHET_TREE => true,
8989
self::REQUIRED_CAPABILITIES => true,

src/MLS/Enums/MessageWireFormat.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,26 @@ final class MessageWireFormat
1212
{
1313
public const RESERVED = 0x0000;
1414
public const MLS_PUBLIC_MESSAGE = 0x0001;
15-
public const MLS_protected_MESSAGE = 0x0002;
15+
public const MLS_PRIVATE_MESSAGE = 0x0002;
1616
public const MLS_WELCOME = 0x0003;
1717
public const MLS_GROUP_INFO = 0x0004;
1818
public const MLS_KEY_PACKAGE = 0x0005;
1919

20-
public const protected_USE_START = 0xF000;
21-
public const protected_USE_END = 0xFFFF;
20+
public const PRIVATE_USE_START = 0xF000;
21+
public const PRIVATE_USE_END = 0xFFFF;
2222

2323
protected const NAME_MAP = [
2424
self::RESERVED => 'reserved',
2525
self::MLS_PUBLIC_MESSAGE => 'mls_public_message',
26-
self::MLS_protected_MESSAGE => 'mls_protected_message',
26+
self::MLS_PRIVATE_MESSAGE => 'mls_private_message',
2727
self::MLS_WELCOME => 'mls_welcome',
2828
self::MLS_GROUP_INFO => 'mls_group_info',
2929
self::MLS_KEY_PACKAGE => 'mls_key_package',
3030
];
3131

3232
protected const RECOMMENDED = [
3333
self::MLS_PUBLIC_MESSAGE => true,
34-
self::MLS_protected_MESSAGE => true,
34+
self::MLS_PRIVATE_MESSAGE => true,
3535
self::MLS_WELCOME => true,
3636
self::MLS_GROUP_INFO => true,
3737
self::MLS_KEY_PACKAGE => true,
@@ -47,8 +47,8 @@ public static function nameOf(int $value): ?string
4747
return self::NAME_MAP[$value];
4848
}
4949

50-
if ($value >= self::protected_USE_START && $value <= self::protected_USE_END) {
51-
return 'protected_use';
50+
if ($value >= self::PRIVATE_USE_START && $value <= self::PRIVATE_USE_END) {
51+
return 'private_use';
5252
}
5353

5454
return null;
@@ -63,8 +63,8 @@ public static function isRecommended(int $value): ?bool
6363
return self::RECOMMENDED[$value] ?? null;
6464
}
6565

66-
public static function isprotectedUse(int $value): bool
66+
public static function isPrivateUse(int $value): bool
6767
{
68-
return $value >= self::protected_USE_START && $value <= self::protected_USE_END;
68+
return $value >= self::PRIVATE_USE_START && $value <= self::PRIVATE_USE_END;
6969
}
7070
}

src/MLS/Enums/ProposalType.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ final class ProposalType
3737
public const GREASE_DADA = 0xDADA;
3838
public const GREASE_EAEA = 0xEAEA;
3939

40-
// Private use range
40+
// protected use range
4141
public const PRIVATE_USE_START = 0xF000;
4242
public const PRIVATE_USE_END = 0xFFFF;
4343

@@ -71,7 +71,7 @@ final class ProposalType
7171
* Metadata per proposal type: [recommended(bool), external(?bool), pathRequired(?bool)]
7272
* Where "?bool" can be null when RFC marks '-' (not applicable/unspecified).
7373
*/
74-
private const META = [
74+
protected const META = [
7575
self::RESERVED => [false, null, null],
7676
self::ADD => [true, true, false],
7777
self::UPDATE => [true, false, true],

src/MLS/Enums/PublicKeyEncryptionLabels.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ final class PublicKeyEncryptionLabels
1212
public const UPDATE_PATH_NODE = 'UpdatePathNode';
1313
public const WELCOME = 'Welcome';
1414

15-
private const RECOMMENDED = [
15+
protected const RECOMMENDED = [
1616
self::UPDATE_PATH_NODE => true,
1717
self::WELCOME => true,
1818
];

src/MLS/Enums/SignatureLabels.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ final class SignatureLabels
1414
public const KEY_PACKAGE_TBS = 'KeyPackageTBS';
1515
public const GROUP_INFO_TBS = 'GroupInfoTBS';
1616

17-
private const RECOMMENDED = [
17+
protected const RECOMMENDED = [
1818
self::FRAMED_CONTENT_TBS => true,
1919
self::LEAF_NODE_TBS => true,
2020
self::KEY_PACKAGE_TBS => true,

src/MLS/Signature/SignatureSchemeInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ interface SignatureSchemeInterface
1717
{
1818
public function getId(): int;
1919

20-
public function sign(string $message, string $privateKey): string;
20+
public function sign(string $message, string $protectedKey): string;
2121

2222
public function verify(string $message, string $signature, string $publicKey): bool;
2323
}

0 commit comments

Comments
 (0)