Skip to content

Commit 5e0c4ee

Browse files
refactor: applies suggestions
1 parent 79a9c97 commit 5e0c4ee

File tree

3 files changed

+34
-131
lines changed

3 files changed

+34
-131
lines changed

lib/protocol/constants.js

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,30 +34,21 @@ const curve25519Supported = (typeof crypto.diffieHellman === 'function'
3434

3535
const mlkemSupported = (() => {
3636
try {
37-
if (
38-
!curve25519Supported
39-
|| typeof crypto.encapsulate !== 'function'
40-
|| typeof crypto.decapsulate !== 'function'
41-
)
37+
if (!curve25519Supported
38+
|| typeof crypto.encapsulate !== 'function'
39+
|| typeof crypto.decapsulate !== 'function') {
4240
return false;
43-
44-
const algorithm = 'ml-kem-768';
45-
const test_clientKeys = crypto.generateKeyPairSync(algorithm);
46-
47-
const { ciphertext, sharedKey } = crypto.encapsulate(
48-
test_clientKeys.publicKey
41+
}
42+
const keys = crypto.generateKeyPairSync('ml-kem-768');
43+
const { ciphertext } = crypto.encapsulate(
44+
keys.publicKey
4945
);
5046

51-
const sharedSecret = crypto.decapsulate(
52-
test_clientKeys.privateKey,
47+
crypto.decapsulate(
48+
keys.privateKey,
5349
ciphertext
5450
);
5551

56-
for (let i = 0; i < sharedSecret.length && i < sharedKey.length; i++) {
57-
if (sharedSecret[i] !== sharedKey[i])
58-
return false;
59-
}
60-
6152
return true;
6253
} catch {
6354
return false;

lib/protocol/kex.js

Lines changed: 25 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,7 @@ const createKeyExchange = (() => {
624624

625625
// "H"
626626
const exchangeHash = hash.digest();
627+
627628
if (!isServer) {
628629
bufferParser.init(this._sig, 0);
629630
const sigType = bufferParser.readString(true);
@@ -1594,14 +1595,6 @@ const createKeyExchange = (() => {
15941595
this._x25519Keys = null;
15951596
this._mlkemKeys = null;
15961597

1597-
this._curve25519KeySize = 32;
1598-
this._encapsulationKeySize = 1184;
1599-
this._decapsulationKeySize = 2400;
1600-
this._ciphertextSize = 1088;
1601-
1602-
this.K_PQ = null;
1603-
this.K_CL = null;
1604-
16051598
this._S_CT2 = null; // needed for server
16061599
}
16071600

@@ -1611,7 +1604,6 @@ const createKeyExchange = (() => {
16111604

16121605
if (!this._mlkemKeys)
16131606
this._mlkemKeys = generateKeyPairSync('ml-kem-768');
1614-
16151607
}
16161608

16171609
convertPublicKey(key) {
@@ -1630,11 +1622,11 @@ const createKeyExchange = (() => {
16301622
// client
16311623
const C_PK1 = this._x25519Keys.publicKey
16321624
.export({ type: 'spki', format: 'der' })
1633-
.slice(-this._curve25519KeySize);
1625+
.slice(-32);
16341626

16351627
const C_PK2 = this._mlkemKeys.publicKey
16361628
.export({ type: 'spki', format: 'der' })
1637-
.slice(-this._encapsulationKeySize);
1629+
.slice(-1184);
16381630

16391631
return Buffer.concat([C_PK2, C_PK1]);
16401632
}
@@ -1646,7 +1638,7 @@ const createKeyExchange = (() => {
16461638
// one that initiates the kex
16471639
const S_PK1 = this._x25519Keys.publicKey
16481640
.export({ type: 'spki', format: 'der' })
1649-
.slice(-this._curve25519KeySize);
1641+
.slice(-32);
16501642

16511643
return Buffer.concat([this._S_CT2, S_PK1]);
16521644
}
@@ -1664,10 +1656,12 @@ const createKeyExchange = (() => {
16641656
asnWriter.writeByte(0x00);
16651657
// XXX: hack to write a raw buffer without a tag -- yuck
16661658
asnWriter._ensure(key.length);
1667-
key.copy(asnWriter._buf,
1659+
key.copy(
1660+
asnWriter._buf,
16681661
asnWriter._offset,
16691662
0,
1670-
key.length);
1663+
key.length
1664+
);
16711665
asnWriter._offset += key.length;
16721666
asnWriter.endSequence();
16731667
asnWriter.endSequence();
@@ -1683,17 +1677,14 @@ const createKeyExchange = (() => {
16831677
// server
16841678
const C_PK2 = otherPublicKey.slice(
16851679
0,
1686-
this._encapsulationKeySize
1687-
);
1688-
const C_PK1 = otherPublicKey.slice(
1689-
this._encapsulationKeySize
1680+
1184
16901681
);
1682+
const C_PK1 = otherPublicKey.slice(1184);
16911683

16921684
if (C_PK1.length !== 32) {
1693-
const expected = this._curve25519KeySize;
16941685
const got = C_PK1.length;
16951686
throw new Error(
1696-
`Invalid C_PK1 length: expected ${expected}, got ${got}`
1687+
`Invalid C_PK1 length: expected 32, got ${got}`
16971688
);
16981689
}
16991690

@@ -1708,8 +1699,6 @@ const createKeyExchange = (() => {
17081699
}),
17091700
});
17101701

1711-
this.K_CL = K_CL;
1712-
17131702
const templateDER = this._mlkemKeys.publicKey
17141703
.export({ type: 'spki', format: 'der' });
17151704

@@ -1719,12 +1708,12 @@ const createKeyExchange = (() => {
17191708
C_PK2_DER,
17201709
0,
17211710
0,
1722-
templateDER.length - this._encapsulationKeySize
1711+
templateDER.length - 1184
17231712
);
17241713

17251714
C_PK2.copy(
17261715
C_PK2_DER,
1727-
templateDER.length - this._encapsulationKeySize
1716+
templateDER.length - 1184
17281717
);
17291718

17301719
const { sharedKey: K_PQ, ciphertext: S_CT2 } = encapsulate(
@@ -1735,27 +1724,24 @@ const createKeyExchange = (() => {
17351724
})
17361725
);
17371726

1738-
this.K_PQ = K_PQ;
1739-
17401727
this._S_CT2 = S_CT2;
1741-
1728+
17421729
// K = HASH(K_PQ || K_CL) from 2.4 on draft
17431730
const K = createHash('sha256')
1744-
.update(K_PQ)
1745-
.update(K_CL)
1746-
.digest();
1747-
1731+
.update(K_PQ)
1732+
.update(K_CL)
1733+
.digest();
1734+
17481735
return K;
17491736
}
17501737
// client
1751-
const S_CT2 = otherPublicKey.slice(0, this._ciphertextSize);
1752-
const S_PK1 = otherPublicKey.slice(this._ciphertextSize);
1738+
const S_CT2 = otherPublicKey.slice(0, 1088);
1739+
const S_PK1 = otherPublicKey.slice(1088);
17531740

17541741
if (S_PK1.length !== 32) {
1755-
const expected = this._curve25519KeySize;
17561742
const got = S_PK1.length;
17571743
throw new Error(
1758-
`Invalid S_PK1 length: expected ${expected}, got ${got}`
1744+
`Invalid S_PK1 length: expected 32, got ${got}`
17591745
);
17601746
}
17611747

@@ -1770,27 +1756,22 @@ const createKeyExchange = (() => {
17701756
}),
17711757
});
17721758

1773-
this.K_CL = K_CL;
1774-
17751759
const K_PQ = decapsulate(
17761760
this._mlkemKeys.privateKey,
17771761
S_CT2
17781762
);
1779-
this.K_PQ = K_PQ;
17801763

17811764
// K = HASH(K_PQ || K_CL) from 2.4 on draft
17821765
const K = createHash('sha256')
1783-
.update(K_PQ)
1784-
.update(K_CL)
1785-
.digest();
1786-
1787-
return K;
1766+
.update(K_PQ)
1767+
.update(K_CL)
1768+
.digest();
17881769

1770+
return K;
17891771

17901772
} catch (error) {
17911773
return error;
17921774
}
1793-
17941775
}
17951776
}
17961777

test/test-misc-client-server.js

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,73 +1621,4 @@ if (mlkemSupported) {
16211621
.on('error', mustCall(onError))
16221622
.on('close', mustCall(() => { }));
16231623
}
1624-
1625-
{
1626-
const { client, server } = setup_(
1627-
'both sides should compute same secret when using mlkem768x25519-sha256',
1628-
{
1629-
client: {
1630-
...clientCfg,
1631-
algorithms: { kex: ['mlkem768x25519-sha256'] }
1632-
},
1633-
server: {
1634-
...serverCfg,
1635-
algorithms: { kex: ['mlkem768x25519-sha256'] }
1636-
}
1637-
},
1638-
);
1639-
1640-
let clientK_PQ = null;
1641-
let clientK_CL = null;
1642-
let serverK_PQ = null;
1643-
let serverK_CL = null;
1644-
1645-
server.on('connection', mustCall((conn) => {
1646-
conn.on('handshake', mustCall((_) => {
1647-
1648-
const kex = conn._protocol._kex;
1649-
serverK_PQ = kex.K_PQ;
1650-
serverK_CL = kex.K_CL;
1651-
1652-
})).on('authentication', mustCall((ctx) => {
1653-
ctx.accept();
1654-
})).on('ready', mustCall(() => {
1655-
1656-
assert(serverK_PQ !== null, 'server did not generate K_PQ');
1657-
assert(serverK_CL !== null, 'server did not generate K_CL');
1658-
1659-
assert(
1660-
clientK_PQ.equals(serverK_PQ),
1661-
'K_PQ mismatch'
1662-
);
1663-
assert(
1664-
clientK_CL.equals(serverK_CL),
1665-
'K_CL mismatch'
1666-
);
1667-
1668-
conn.end();
1669-
}));
1670-
}));
1671-
1672-
client.on('handshake', mustCall(() => {
1673-
1674-
const kex = client._protocol._kex;
1675-
clientK_PQ = kex.K_PQ;
1676-
clientK_CL = kex.K_CL;
1677-
1678-
})).on('ready', mustCall(() => {
1679-
1680-
assert(clientK_PQ !== null, 'client did not generate K_PQ');
1681-
assert(clientK_CL !== null, 'client did not generate K_CL');
1682-
assert(
1683-
clientK_PQ.equals(serverK_PQ),
1684-
'K_PQ mismatch between client and server'
1685-
);
1686-
assert(
1687-
clientK_CL.equals(serverK_CL),
1688-
'K_CL mismatch between client and server'
1689-
);
1690-
1691-
}));
1692-
}
16931624
}

0 commit comments

Comments
 (0)