1
1
// Closed source not for private and or corporate use.
2
+ // KYBER KEY EXCHANGE WITH BUILT IN DOMAIN CERTIFICATE & SERVER AUTHENTICATION WITH Perfect Forward Secrecy
3
+ /*
4
+ Create User Kyber keypair send to server
5
+ Server creates Kyber shared Secret & encapsulates it via user's public kyber key
6
+ Server sends cipher text in the header & encrypted intro frame to the user
7
+ Server sets the session with the new secret keys
8
+ User first decapsulates ciphertext with user's private kyber key located in the header
9
+ User then sets the session with the new secret keys
10
+ Make sure to create a transmit and receive keys so both are unique to add an extra layer of security
11
+ */
2
12
import * as defaultCrypto from '#crypto' ;
3
13
import { assign , clear , isBuffer } from '@universalweb/acid' ;
4
14
import {
5
- decapsulate , encapsulate , encryptionKeypair , kyber768
15
+ decapsulate ,
16
+ encapsulate ,
17
+ encryptionKeypair ,
18
+ kyber768
6
19
} from '../keyExchange/kyber768.js' ;
7
20
import { decrypt , encrypt } from '../encryption/XChaCha.js' ;
21
+ import { extendedHandshakeHeaderRPC , introHeaderRPC } from '../../protocolHeaderRPCs.js' ;
22
+ import { extendedHandshakeRPC , introRPC } from '../../protocolFrameRPCs.js' ;
8
23
import { blake3 } from '@noble/hashes/blake3' ;
9
- import { extendedHandshakeRPC } from '../../../udsp/protocolFrameRPCs.js' ;
10
- import { introHeaderRPC } from '../../protocolHeaderRPCs.js' ;
11
24
import { ml_kem768 } from '@noble/post-quantum/ml-kem' ;
12
25
const {
13
26
randomConnectionId,
@@ -20,13 +33,6 @@ const {
20
33
} = defaultCrypto ;
21
34
const { id : encryptionKeypairID , } = kyber768 ;
22
35
const hash = blake3 ;
23
- // Create User Kyber keypair send to server
24
- // Server creates Kyber shared Secret & encapsulates it via user's public kyber key
25
- // Server sends cipher text in the header & encrypted intro frame to the user
26
- // Server sets the session with the new secret keys
27
- // User first decapsulates ciphertext with user's private kyber key located in the header
28
- // User then sets the session with the new secret keys
29
- // PRIORITY: Make sure to swap Transmit and Receive keys so both are unique to add an extra layer of security
30
36
export const kyber768_xChaCha = {
31
37
name : 'kyber768_xChaCha' ,
32
38
alias : 'kyber768' ,
@@ -43,45 +49,56 @@ export const kyber768_xChaCha = {
43
49
console . log ( 'clientInitializeSession Destination' , destination ) ;
44
50
console . log ( 'Public Key from destination' , destination . publicKey [ 0 ] ) ;
45
51
} ,
46
- async sendClientExtendedHandshake ( source , destination ) {
52
+ async clientSetSession ( source , destination , cipherData ) {
53
+ const kyberPrivateKey = source . privateKey ;
54
+ const sharedSecret = await decapsulate ( cipherData , kyberPrivateKey ) ;
55
+ console . log ( 'clientSetSession kyberSharedSecret' , sharedSecret [ 0 ] , sharedSecret . length ) ;
56
+ source . transmitKey = sharedSecret ;
57
+ source . receiveKey = hash ( sharedSecret ) ;
58
+ console . log ( 'New Session Keys' , source . transmitKey [ 0 ] , source . receiveKey [ 0 ] ) ;
59
+ } ,
60
+ async sendClientExtendedHandshake ( source , destination , frame , header ) {
47
61
const destinationPublicKey = destination . publicKey ;
48
62
console . log ( 'TRIGGERED sendClientExtendedHandshake' ) ;
49
63
console . log ( destinationPublicKey . length ) ;
50
64
const {
51
65
cipherText,
52
66
sharedSecret
53
67
} = await encapsulate ( destinationPublicKey ) ;
54
- const frame = [
55
- false ,
56
- extendedHandshakeRPC ,
57
- cipherText
58
- ] ;
68
+ frame . push ( cipherText ) ;
59
69
source . cipherData = cipherText ;
60
70
source . sharedSecret = sharedSecret ;
61
71
console . log ( 'sendClientExtendedHandshake kyberSharedSecret' , sharedSecret [ 0 ] , sharedSecret . length ) ;
62
72
console . log ( 'sendClientExtendedHandshake cipherText' , cipherText [ 0 ] , cipherText . length ) ;
63
- return frame ;
64
73
} ,
65
74
async clientExtendedHandshake ( source , destination ) {
66
75
console . log ( 'TRIGGERED client ExtendedHandshake' , source . transmitKey , source . sharedSecret ) ;
76
+ const sharedSecret = source . sharedSecret ;
67
77
const oldTransmitKey = source . transmitKey ;
78
+ const oldReceiveKey = source . receiveKey ;
68
79
source . transmitKey = combineKeys ( oldTransmitKey , source . sharedSecret ) ;
69
- source . receiveKey = source . transmitKey ;
80
+ source . receiveKey = combineKeys ( oldReceiveKey , source . sharedSecret ) ;
70
81
clearBuffer ( oldTransmitKey ) ;
82
+ clearBuffer ( oldReceiveKey ) ;
71
83
clearBuffer ( source . sharedSecret ) ;
72
84
clearBuffer ( source . cipherData ) ;
73
85
source . sharedSecret = null ;
74
86
source . cipherData = null ;
75
87
console . log ( 'TRIGGERED client ExtendedHandshake' , source . transmitKey ) ;
76
88
} ,
77
- async clientSetSession ( source , destination , cipherData ) {
78
- const kyberPrivateKey = source . privateKey ;
79
- const sharedSecret = await decapsulate ( cipherData , kyberPrivateKey ) ;
80
- source . transmitKey = sharedSecret ;
81
- source . receiveKey = source . transmitKey ;
82
- console . log ( 'clientSetSession kyberSharedSecret' , sharedSecret [ 0 ] , sharedSecret . length ) ;
83
- console . log ( 'Keys' , source . transmitKey [ 0 ] , source . receiveKey [ 0 ] ) ;
84
- } ,
89
+ // async clientSetSession(source, destination, cipherData) {
90
+ // const kyberPrivateKey = source.privateKey;
91
+ // const sharedSecret = await decapsulate(cipherData, kyberPrivateKey);
92
+ // console.log('clientSetSession kyberSharedSecret', sharedSecret[0], sharedSecret.length);
93
+ // const oldTransmitKey = source.transmitKey;
94
+ // const oldReceiveKey = source.receiveKey;
95
+ // console.log('Old Session Keys', source.transmitKey[0], source.receiveKey[0]);
96
+ // source.transmitKey = combineKeys(oldTransmitKey, source.sharedSecret);
97
+ // source.receiveKey = combineKeys(oldReceiveKey, source.sharedSecret);
98
+ // clearBuffer(oldTransmitKey);
99
+ // clearBuffer(oldReceiveKey);
100
+ // console.log('New Session Keys', source.transmitKey[0], source.receiveKey[0]);
101
+ // },
85
102
async serverInitializeSession ( source , destination , destinationPublicKey ) {
86
103
console . log ( 'server InitializeSession' ) ;
87
104
console . log ( destinationPublicKey ) ;
@@ -91,7 +108,7 @@ export const kyber768_xChaCha = {
91
108
} = await encapsulate ( destinationPublicKey ) ;
92
109
destination . publicKey = destinationPublicKey ;
93
110
source . cipherData = cipherText ;
94
- source . transmitKey = sharedSecret ;
111
+ source . transmitKey = hash ( sharedSecret ) ;
95
112
source . receiveKey = sharedSecret ;
96
113
console . log ( 'server kyberSharedSecret' , sharedSecret [ 0 ] , sharedSecret . length ) ;
97
114
console . log ( 'destinationPublicKey' , destinationPublicKey [ 0 ] ) ;
@@ -102,44 +119,43 @@ export const kyber768_xChaCha = {
102
119
header [ 1 ] = source . cipherData ;
103
120
} ,
104
121
async serverExtendedHandshake ( source , destination , frame , header ) {
105
- if ( ! source . sharedSecret ) {
106
- console . log ( 'serverExtendedHandshake CIPHER CALLED' , frame , header ) ;
107
- const [
108
- streamid_undefined ,
109
- rpc ,
110
- cipherData
111
- ] = frame ;
112
- const privateKey = source . privateKey ;
113
- const sharedSecret = await decapsulate ( cipherData , privateKey ) ;
114
- clearBuffer ( source . cipherData ) ;
115
- source . cipherData = null ;
116
- source . sharedSecret = sharedSecret ;
117
- source . nextSession = true ;
118
- console . log ( 'Keys' , source . transmitKey [ 0 ] , source . receiveKey [ 0 ] ) ;
119
- console . log ( 'sharedSecret' , source . sharedSecret [ 0 ] ) ;
120
- console . log ( 'server cipherText' , cipherData [ 0 ] , cipherData . length ) ;
121
- }
122
+ console . log ( 'serverExtendedHandshake CIPHER CALLED' , frame , header ) ;
123
+ const [
124
+ streamid_undefined ,
125
+ rpc ,
126
+ cipherData
127
+ ] = frame ;
128
+ const privateKey = source . privateKey ;
129
+ const sharedSecret = await decapsulate ( cipherData , privateKey ) ;
130
+ clearBuffer ( cipherData ) ;
131
+ source . cipherData = null ;
132
+ source . sharedSecret = sharedSecret ;
133
+ source . nextSession = true ;
134
+ console . log ( 'Keys' , source . transmitKey [ 0 ] , source . receiveKey [ 0 ] ) ;
135
+ console . log ( 'sharedSecret' , source . sharedSecret [ 0 ] ) ;
136
+ console . log ( 'server cipherText' , cipherData [ 0 ] , cipherData . length ) ;
122
137
} ,
123
138
async sendServerExtendedHandshake ( source , destination ) {
124
- const frame = [
125
- false ,
126
- extendedHandshakeRPC ,
127
- ] ;
128
- return frame ;
139
+ console . log ( 'Server Extended Handshake ack' ) ;
140
+ // Should be able to remove this
141
+ // const frame = [
142
+ // false,
143
+ // extendedHandshakeRPC,
144
+ // ];
145
+ // return frame;
129
146
} ,
130
147
async serverSetSession ( source , destination ) {
131
148
console . log ( 'serverSetSession' ) ;
132
149
const sharedSecret = source . sharedSecret ;
133
150
const oldTransmitKey = source . transmitKey ;
134
- source . transmitKey = combineKeys ( oldTransmitKey , sharedSecret ) ;
135
- source . receiveKey = source . transmitKey ;
151
+ const oldReceiveKey = source . receiveKey ;
152
+ source . transmitKey = combineKeys ( oldTransmitKey , source . sharedSecret ) ;
153
+ source . receiveKey = combineKeys ( oldReceiveKey , source . sharedSecret ) ;
136
154
clearBuffer ( oldTransmitKey ) ;
137
- clearBuffer ( source . sharedSecret ) ;
138
- clearBuffer ( source . cipherData ) ;
155
+ clearBuffer ( oldReceiveKey ) ;
139
156
clearBuffer ( source . sharedSecret ) ;
140
157
source . sharedSecret = null ;
141
158
source . nextSession = null ;
142
- console . log ( 'kyberSharedSecret' , sharedSecret [ 0 ] ) ;
143
159
console . log ( 'Keys' , source . transmitKey [ 0 ] , source . receiveKey [ 0 ] ) ;
144
160
} ,
145
161
generateSeed ( ) {
@@ -160,3 +176,4 @@ export const kyber768_xChaCha = {
160
176
extendedHandshake : true ,
161
177
encryptionKeypairID,
162
178
} ;
179
+ // copyright © Thomas Marchi
0 commit comments