Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add encryption and decryption #12

Merged
merged 1 commit into from
Aug 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,7 @@
}
var html = makeHTMLMessage(text);
addMessageToHistory(html, 'mine');
let uint8Array = new TextEncoder().encode(text);
send(uint8Array);
send(text);
}

function makeManifestLink(linkHash, sharedPrivateKey) {
Expand Down Expand Up @@ -155,7 +154,7 @@
messageCallback: function(msg) {
log('messageCallback', msg);
if (msg.type == 'message') {
addMessageToHistory(makeHTMLMessage(new TextDecoder().decode(msg.message)), 'your');
addMessageToHistory(makeHTMLMessage(msg.message), 'your');
} else if (msg.type == 'disconnect') {
addMessageToHistory('Your peer is disconnected', 'bot');
}
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
"@erebos/secp256k1": "^0.7.0",
"@erebos/swarm": "^0.12.0",
"@erebos/swarm-node": "^0.12.0",
"dfeeds": "git+https://gitlab.com/dznt/dfeeds.git",
"eccrypto": "^1.1.3",
"secp256k1": "^3.8.0",
"swarm-lowlevel": "git+https://gitlab.com/nolash/swarm-lowlevel-js",
Expand Down
16 changes: 4 additions & 12 deletions src/crypto.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import * as ec from 'eccrypto'; // TODO: move derive to wallet
import * as keccak from 'keccak';

import { hexToArray, stripHexPrefix } from './common';

// TODO remove nodejs hack
const crypto = require('crypto');
crypto.getRandomValues = crypto.randomBytes

export const encryptAesGcm = async (message: string, secretHex: string): Promise<Uint8Array> => {
export const encryptAesGcm = async (message: string, secret: Uint8Array): Promise<Uint8Array> => {
try {
const iv = crypto.getRandomValues(new Uint8Array(12));
const secretArray = hexToArray(stripHexPrefix(secretHex));
const data = new TextEncoder().encode(message);
const secretKey = await crypto.subtle.importKey('raw', secretArray, 'AES-GCM', true, ['encrypt', 'decrypt']);
const secretKey = await crypto.subtle.importKey('raw', secret, 'AES-GCM', true, ['encrypt', 'decrypt']);
const ciphertext = await crypto.subtle.encrypt({
name: 'AES-GCM',
iv,
Expand All @@ -26,12 +19,11 @@ export const encryptAesGcm = async (message: string, secretHex: string): Promise
}
}

export const decryptAesGcm = async (encryptedData: Uint8Array, secretHex: string): Promise<string> => {
export const decryptAesGcm = async (encryptedData: Uint8Array, secret: Uint8Array): Promise<string> => {
try {
const iv = encryptedData.slice(0, 12);
const ciphertext = encryptedData.slice(12);
const secretArray = hexToArray(secretHex);
const secretKey = await crypto.subtle.importKey('raw', secretArray, 'AES-GCM', true, ['encrypt', 'decrypt']);
const secretKey = await crypto.subtle.importKey('raw', secret, 'AES-GCM', true, ['encrypt', 'decrypt']);
const cleartext = await crypto.subtle.decrypt({
name: 'AES-GCM',
iv,
Expand Down
106 changes: 17 additions & 89 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import * as dfeeds from 'dfeeds';
import * as swarm from 'swarm-lowlevel';
import * as wallet from 'swarm-lowlevel/unsafewallet';
import { hexToArray, arrayToHex, waitMillisec, waitUntil, stripHexPrefix } from './common';
import { hexToArray, arrayToHex, waitUntil, stripHexPrefix } from './common';
import { Session } from './session';
import { BeeClient } from 'bee-client-lib';
import { encryptAesGcm as encrypt } from './crypto';
Expand All @@ -11,8 +9,6 @@ import { hash, derive } from './crypto';
type ManifestCallback = (manifest: string, sharedPrivateKey: string) => void;
type StateCallback = (topicHex: string) => void;

const REQUEST_PUBLIC_KEY_INDEX = 0;
const RESPONSE_PUBLIC_KEY_INDEX = 1;
const MSGPERIOD = 1000;

let log = console.log;
Expand Down Expand Up @@ -60,7 +56,7 @@ topicTmpArray = topicTmpArray.slice(0, 20);
console.log('topic', arrayToHex(topicTmpArray));

// the master session
let chatSession = undefined;
let chatSession: Session = undefined;


// if bz is supplied, will update tmp feed
Expand Down Expand Up @@ -89,14 +85,6 @@ async function connectToPeerTwo(session: any, handshakeOther:any) {
return otherWallet;
}

async function downloadFromFeed(session: any, wallet: wallet.Wallet, socId:string):Promise<any|Buffer> {
let otherAddress = wallet.getAddress('binary');
let s = new swarm.soc(socId, undefined, undefined);
s.setOwnerAddress(otherAddress);
let socAddress = s.getAddress();
return await chatSession.client.downloadChunk(arrayToHex(socAddress));
}

async function checkResponse(session: any):Promise<string|undefined> {
try {
const soc = await session.getHandshake();
Expand All @@ -107,25 +95,6 @@ async function checkResponse(session: any):Promise<string|undefined> {
}
}

async function updateFeed(ch) {
return await chatSession.client.uploadChunk(ch);
}

async function updateData(ch) {
let dataLength = ch.span.length + ch.data.length;
let data = new Uint8Array(dataLength);
for (let i = 0; i < ch.span.length; i++) {
data[i] = ch.span[i];
}
for (let i = 0; i < ch.data.length; i++) {
data[i+ch.span.length] = ch.data[i];
}
let h = await chatSession.client.uploadChunk({
data: data,
reference: ch.reference
});
}

// Handle the handshake from the peer that responds to the invitation
async function startRequest(session: Session, manifestCallback: ManifestCallback):Promise<any> {
session.sendHandshake();
Expand All @@ -134,9 +103,8 @@ async function startRequest(session: Session, manifestCallback: ManifestCallback
session.client.feeds[session.tmpWallet.address].index++;
for (;;) {
const nextCheckTime = Date.now() + 1000;
const userOther = await checkResponse(session); //;, bobSocId);
const userOther = await checkResponse(session);
if (userOther !== undefined) {
//connectToPeerTwo(session, userOther);
return;
}
await waitUntil(nextCheckTime);
Expand All @@ -151,18 +119,9 @@ async function startResponse(session: any):Promise<any> {


const newSession = (gatewayAddress: string, messageCallback: any) => {
const client = new BeeClient(gatewayAddress);

let secretHex = undefined;
const sendEnvelope = async (envelope) => {
const envelopeJson = JSON.stringify(envelope)
//const encryptedMessage = await encryptAesGcm(envelopeJson, secretHex);
//const messageReference = await bzz.upload(Buffer.from(encryptedMessage));
//const encryptedReference = await encryptAesGcm(messageReference, secretHex);
//const encryptedReferenceBytes = Buffer.from(encryptedReference)
//const r = await uploadToRawFeed(bzz, userSelf, topicTmp, writeIndex, encryptedReferenceBytes);
console.debug('I would have sent this message', envelope);
//writeIndex += 1;
}
const sendMessage = async (message: string) => {
const envelope = {
Expand All @@ -183,63 +142,34 @@ const newSession = (gatewayAddress: string, messageCallback: any) => {
}
return sendEnvelope(envelope)
}
//const poll = async (otherFeed: any) => {
const poll = async (session:any) => {
while (true) {
try {
console.debug('poll', session.otherFeed);
const message = await session.getOtherFeed();
//const encryptedReference = await downloadFromFeed(client, otherWallet, socId); //topicTmp); //, readIndex);
//const messageReference = await decrypt(encryptedReference, secretHex);
//const response = await client.downloadChunk(messageReference);
//const encryptedArrayBuffer = await response.arrayBuffer();
//const message = await decrypt(new Uint8Array(encryptedArrayBuffer), secretHex);
console.debug('got', message);
// console.debug('poll', session.otherFeed);
const soc = await session.getOtherFeed();
console.debug('got', soc);
const message = await decrypt(soc.chunk.data, session.secret);
messageCallback({
type: 'message',
message: message.chunk.data
message,
});
} catch (e) {
console.log('polled in vain for other...' + e);
// console.log('polled in vain for other...' + e);
break;
}
}
setTimeout(poll, MSGPERIOD, session);
}
//const address = selfWallet.getAddress('binary')
chatSession = new Session(client, selfWallet, tmpWallet, keyTmpRequestPriv != undefined); //topicTmpArray, address);
chatSession.sendMessage = async (message: any) => {
// const encryptedMessage = await encrypt(message, secretHex);
//const encryptedMessage = new TextEncoder().encode(message);

//const messageReference = await bzz.upload(Buffer.from(encryptedMessage));
// const messageReference = await client.uploadChunk(Buffer.from(encryptedMessage));
// const encryptedReference = await encrypt(messageReference, secretHex);
// const encryptedReferenceBytes = Buffer.from(encryptedReference)
//const r = await uploadToRawFeed(bzz, userSelf, topicTmp, writeIndex, encryptedReferenceBytes);

//const otherSocId = chatSession.selfFeed.next();
//const soc = new swarm.soc(otherSocId, undefined, selfWallet);

//let h = new swarm.fileSplitter(soc.setChunk);
//h.split(message);

//soc.sign();
const client = new BeeClient(gatewayAddress);
chatSession = new Session(client, selfWallet, tmpWallet, keyTmpRequestPriv != undefined);
chatSession.sendMessage = async (message: string) => {
const encryptedMessage = await encrypt(message, chatSession.secret);
let r = await chatSession.client.updateFeedWithSalt(chatSession.secret, encryptedMessage, chatSession.selfWallet);
};

//let chunkData = soc.serializeData();
//let chunkAddress = soc.getAddress();
// let resultAddress = await updateFeed({
// data: chunkData,
// reference: chunkAddress,
// });
let r = await chatSession.client.updateFeedWithSalt(chatSession.secret, message, chatSession.selfWallet);
console.log(r);
};
// TODO: move def to session, with polling as part of constructor
//chatSession.start = async (userOther: string, secret: string) => {
//chatSession.start = async (session: any, secret: string) => {
chatSession.start = async (session: any) => {
await poll(session); //;chatSession.otherFeed);
await poll(session);
};
return chatSession;
}
Expand All @@ -261,7 +191,6 @@ export function init(params: {
startRequest(chatSession, params.manifestCallback).then(() => {
let topicHex = arrayToHex(topicTmpArray);
params.stateCallback(topicHex);
// setTimeout(() => chatSession.sendMessage("alice"), 5 * 1000)
}).catch((e) => {
console.error("error starting request: ", e);
log("error starting request: ", e);
Expand All @@ -271,7 +200,6 @@ export function init(params: {
startResponse(chatSession).then(() => {
let topicHex = arrayToHex(topicTmpArray);
params.stateCallback(topicHex);
// setTimeout(() => chatSession.sendMessage("bob"), 5 * 1000)
}).catch((e) => {
console.error("error starting response: ", e);
log("error starting response: ", e);
Expand All @@ -289,7 +217,7 @@ export function send(message: string) {

export function disconnect() {
try {
chatSession.sendDisconnect();
// chatSession.sendDisconnect();
} catch(e) {
console.error(e);
}
Expand Down