Skip to content

Commit ccab89b

Browse files
authored
Merge pull request #107 from datapartyjs/pq-sockets
post quantum sockets
2 parents ee66740 + 00dee41 commit ccab89b

39 files changed

Lines changed: 1910 additions & 222 deletions

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,13 @@
5757
"build-test": "node ./examples/party/example-build.js",
5858
"watch-test": "DEBUG=* nodemon --ignore service test/test-service-compile.js",
5959
"build-docs": "./scripts/build-docs.sh",
60-
"generate-docs": "npx jsdoc --configure jsdoc.json --verbose"
60+
"build-venue": "node ./src/venue/build.js",
61+
"generate-docs": "npx jsdoc --configure jsdoc.json --verbose",
62+
"mkssl": "openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem"
6163
},
6264
"dependencies": {
6365
"@dataparty/bouncer-db": "1.0.1",
64-
"@dataparty/crypto": "git://github.com/datapartyjs/dataparty-crypto.git",
66+
"@dataparty/crypto": "github:datapartyjs/dataparty-crypto#postquantum-bson",
6567
"@dataparty/tasker": "^0.0.3",
6668
"@diva.exchange/i2p-sam": "^4.1.8",
6769
"@markwylde/liferaft": "^1.3.4",
@@ -79,6 +81,7 @@
7981
"dom-storage": "^2.1.0",
8082
"eventemitter3": "^4.0.7",
8183
"express": "^4.17.1",
84+
"express-ipfilter": "^1.3.2",
8285
"express-list-routes": "^1.1.9",
8386
"git-repo-info": "^2.1.1",
8487
"joi": "^17.9.1",

src/comms/host/host-protocol-scheme.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,31 @@ const OP_HEADER = Joi.object().keys({
1919
const AUTH_OP = Joi.object().keys({
2020
id: ID_SCHEME.required(),
2121
op: Joi.string().valid('auth').required(),
22-
session: Joi.string().required(), //Joi.objectId().required(),
22+
session: Joi.string().required(),
23+
offer: Joi.object().keys({
24+
sender: Joi.object().keys({
25+
id: Joi.string(),
26+
key: Joi.object().keys({
27+
type: Joi.string().required(),
28+
hash: Joi.string().required(),
29+
public: Joi.object().keys({
30+
box: Joi.string().required(),
31+
sign: Joi.string().required(),
32+
pqkem: Joi.string().required(),
33+
pqsign_ml: Joi.string().required(),
34+
pqsign_slh: Joi.string().required()
35+
}).required()
36+
}).required(),
37+
seed: Joi.allow(null)
38+
}).required(),
39+
pqCipherText: Joi.string().required(),
40+
streamNonce: Joi.string().required()
41+
}).required(),
42+
signature: Joi.object().keys({
43+
timestamp: Joi.number().required(),
44+
type: Joi.string().required(),
45+
value: Joi.string().required()
46+
}).required()
2347
})
2448

2549
const CALL_OP = Joi.object().keys({

src/comms/isocket-comms.js

Lines changed: 82 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const {Message, Routines} = require('@dataparty/crypto')
77

88
const AuthOp = require('./op/auth-op')
99
const RosShim = require('./ros-shim')
10-
const IParty = require('../party/iparty')
10+
1111

1212

1313
/**
@@ -38,6 +38,9 @@ class ISocketComms extends EventEmitter {
3838

3939
this.socket = undefined
4040

41+
//this.aesOffer = null
42+
this.aesStream = null
43+
4144
this._ros = undefined
4245
}
4346

@@ -80,49 +83,70 @@ class ISocketComms extends EventEmitter {
8083
op.run().then((status)=>{
8184
debug(status)
8285
debug('authed')
83-
this.emit('open')
86+
//this.aesOffer = op.offer
87+
this.aesStream = op.stream
8488
this.authed = true
89+
this.emit('open')
8590
}).catch(error=>{
8691
this.authed = false
8792
debug('auth error', error)
8893
this.emit('close')
8994
})
9095
}
9196

92-
decrypt(reply, sender){
97+
async decrypt(reply, sender){
98+
if(this.aesStream){
99+
debug('decrypting quantum aes')
100+
console.log(reply, typeof reply)
101+
console.log(typeof reply.data)
102+
103+
let buf = reply.data
104+
105+
if(buf instanceof Blob){
106+
debug('reply.data is a blob')
107+
buf = await reply.data.arrayBuffer();
108+
} else {
109+
//buf = reply.data
110+
}
111+
112+
const contentBSON = await this.aesStream.decrypt( new Uint8Array(buf) )
113+
const content = Routines.BSON.parseObject(new Routines.BSON.BaseParser( contentBSON ))
114+
115+
return content
116+
117+
} else {
118+
debug('decrypting classic')
93119
const replyObj = JSON.parse(reply.data)
94-
let dataPromise = new Promise((resolve, reject)=>{
95-
if(replyObj.enc && replyObj.sig){
96-
let msg = new Message(replyObj)
97-
98-
return resolve(msg.decrypt(this.party._identity).then(content=>{
99-
const senderPub = Routines.extractPublicKeys(msg.enc)
100-
debug('sender', sender, '\tdiscover', this.discoverRemoteIdentity)
101-
if(this.discoverRemoteIdentity && !sender){
102-
debug('discovered remote identity', senderPub)
103-
this.remoteIdentity = {
104-
key: {
105-
public: senderPub
106-
}
107-
}
108-
sender = this.remoteIdentity
109-
}
110-
debug(`sender from - ${msg.from}`)
111-
debug(`senderPub - ${senderPub}`)
112-
113-
if(senderPub.box != sender.key.public.box || senderPub.sign != sender.key.public.sign){
114-
return Promise.reject('TRUST - reply is not from expected remote')
115-
}
116-
117-
debug('decrypted data')
118-
return content
119-
}))
120-
}
121-
122-
reject( Promise.reject('TRUST - reply is not encrypted') )
123-
})
124-
125-
return dataPromise
120+
121+
if(replyObj.enc && replyObj.sig){
122+
let msg = new Message({})
123+
msg.fromJSON(replyObj)
124+
125+
let content = await msg.decrypt(this.party.privateIdentity)
126+
127+
const senderPub = Routines.extractPublicKeys(msg.enc)
128+
debug('sender', sender, '\tdiscover', this.discoverRemoteIdentity)
129+
if(this.discoverRemoteIdentity && !sender){
130+
debug('discovered remote identity', senderPub)
131+
this.remoteIdentity = {
132+
key: {
133+
public: senderPub
134+
}
135+
}
136+
sender = this.remoteIdentity
137+
}
138+
debug(`sender from - ${msg.from}`)
139+
debug(`senderPub - ${senderPub}`)
140+
141+
if(senderPub.box != sender.key.public.box || senderPub.sign != sender.key.public.sign){
142+
throw new Error('TRUST - reply is not from expected remote')
143+
}
144+
145+
debug('decrypted data')
146+
return content
147+
}
148+
}
149+
126150
}
127151

128152
onmessage(message){
@@ -142,28 +166,37 @@ class ISocketComms extends EventEmitter {
142166
})
143167
}
144168

145-
send(input){
146-
debug('send - ', typeof input, input)
169+
async send(input){
170+
debug('send - ', typeof input, input)
147171

148-
if(typeof input != 'object'){
149-
input = JSON.parse(input)
150-
}
172+
if(typeof input != 'object'){
173+
input = JSON.parse(input)
174+
}
151175

152-
const content = new Message({msg: input})
176+
let content = null
153177

154-
return content.encrypt(this.party._identity, this.remoteIdentity.key)
155-
.then(JSON.stringify)
156-
.then(this.socket.send.bind(this.socket))
178+
if(this.aesStream && input.id.indexOf('auth') == -1){
179+
debug('sending quantum aes')
180+
const contentBSON = Routines.BSON.serializeBSONWithoutOptimiser( input )
181+
content = await this.aesStream.encrypt( contentBSON )
182+
} else {
157183

184+
debug('sending classic')
185+
const msg = new Message({msg: input})
186+
await msg.encrypt(this.party._identity, this.remoteIdentity.key)
187+
content = JSON.stringify(msg.toJSON())
188+
}
189+
190+
await this.socket.send(content)
158191
}
159192

160193
get ros(){
161-
if(!this._ros){
162-
this._ros = new RosShim(this)
163-
this._ros.connect()
164-
}
194+
if(!this._ros){
195+
this._ros = new RosShim(this)
196+
this._ros.connect()
197+
}
165198

166-
return this._ros
199+
return this._ros
167200
}
168201
}
169202

src/comms/op/auth-op.js

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,48 @@
11
const debug = require('debug')('dataparty.op.auth-op')
22
const SocketOp = require('./socket-op')
33

4+
const {Routines} = require('@dataparty/crypto')
5+
46

57
class AuthOp extends SocketOp {
6-
constructor(socket){
7-
super('auth', {}, socket)
8+
constructor(socket){
9+
super('auth', {}, socket)
10+
11+
this.offer=null
12+
this.stream=null
13+
}
14+
15+
async run(){
16+
const actor = this.socket.party.privateIdentity
17+
const aesStreamOffer = await actor.createStream( this.socket.remoteIdentity )
18+
19+
this.stream = aesStreamOffer.stream
20+
21+
const offer = {
22+
sender: aesStreamOffer.sender,
23+
pqCipherText: aesStreamOffer.pqCipherText,
24+
streamNonce: aesStreamOffer.streamNonce
25+
}
26+
27+
const offerBSON = Routines.BSON.serializeBSONWithoutOptimiser( offer )
28+
29+
const { timestamp, value, type } = await Routines.signDataPQ(actor, offerBSON, 'pqsign_ml')
30+
31+
const authPkt = {
32+
offer,
33+
signature: {
34+
timestamp, type,
35+
value: Routines.Utils.base64.encode(value)
36+
}
837
}
38+
39+
debug('created authPkt', authPkt)
40+
41+
this.offer = offer
42+
this.data = authPkt
43+
44+
return super.run()
45+
}
946
}
1047

1148
module.exports = AuthOp

0 commit comments

Comments
 (0)