Commit d4dec323 authored by Frauke's avatar Frauke
Browse files

Refactored code to use libsodium library

parent e4c11c54
...@@ -3062,6 +3062,19 @@ ...@@ -3062,6 +3062,19 @@
"astw": "2.2.0" "astw": "2.2.0"
} }
}, },
"libsodium": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.3.tgz",
"integrity": "sha512-ld+deUNqSsZYbAobUs63UyduPq8ICp/Ul/5lbvBIYpuSNWpPRU0PIxbW+xXipVZtuopR6fIz9e0tTnNuPMNeqw=="
},
"libsodium-wrappers": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.3.tgz",
"integrity": "sha512-dw5Jh6TZ5qc5rQVZe3JrSO/J05CE+DmAPnqD7Q2glBUE969xZ6o3fchnUxyPlp6ss3x0MFxmdJntveFN+XTg1g==",
"requires": {
"libsodium": "0.7.3"
}
},
"liftoff": { "liftoff": {
"version": "2.5.0", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz",
......
...@@ -2,9 +2,11 @@ ...@@ -2,9 +2,11 @@
"name": "libsodium-spike", "name": "libsodium-spike",
"version": "1.0.0", "version": "1.0.0",
"description": "Use libsodium to implement Spike 1: OpenCrypto", "description": "Use libsodium to implement Spike 1: OpenCrypto",
"main": "index.js", "main": "./server/index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1",
"watch": "nodemon",
"start": "node ./server/index.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
...@@ -22,6 +24,7 @@ ...@@ -22,6 +24,7 @@
"dependencies": { "dependencies": {
"axios": "^0.17.1", "axios": "^0.17.1",
"body-parser": "^1.18.2", "body-parser": "^1.18.2",
"express": "^4.16.2" "express": "^4.16.2",
"libsodium-wrappers": "^0.7.3"
} }
} }
const fs = require('fs')
const express = require('express') const express = require('express')
const app = express() const app = express()
const path = require('path') const path = require('path')
...@@ -11,9 +10,9 @@ app.use(bodyParser.json()) ...@@ -11,9 +10,9 @@ app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: false})) app.use(bodyParser.urlencoded({extended: false}))
app.post('/register', (req, res) => { app.post('/register', (req, res) => {
const salt = JSON.stringify({salt: req.body.salt}) const salt = Buffer.from(JSON.stringify(req.body.salt))
const publicKey = JSON.stringify({publickKey: req.body.publicKey}) const publicKey = Buffer.from(JSON.stringify(req.body.publicKey))
const privateKey = JSON.stringify({privateKey: req.body.privateKey}) const privateKey = Buffer.from(JSON.stringify(req.body.privateKey))
const writeSalt = fileUtils.writeFile('./server/files/salt.json', salt) const writeSalt = fileUtils.writeFile('./server/files/salt.json', salt)
const writePublicKey = fileUtils.writeFile('./server/files/publickey.json', publicKey) const writePublicKey = fileUtils.writeFile('./server/files/publickey.json', publicKey)
...@@ -22,6 +21,7 @@ app.post('/register', (req, res) => { ...@@ -22,6 +21,7 @@ app.post('/register', (req, res) => {
Promise.all([writeSalt, writePublicKey, writePrivateKey]).then(() => { Promise.all([writeSalt, writePublicKey, writePrivateKey]).then(() => {
res.status(200).end() res.status(200).end()
}).catch((er) => { }).catch((er) => {
console.log(er)
res.status(500).send('Ooops, something went wrong') res.status(500).send('Ooops, something went wrong')
}) })
}) })
......
...@@ -3,26 +3,27 @@ const fs = require('fs') ...@@ -3,26 +3,27 @@ const fs = require('fs')
// Writes a string to the filesystem. // Writes a string to the filesystem.
function writeFile (fileName, value) { function writeFile (fileName, value) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
fs.writeFile(fileName, value, (err) => { let wstream = fs.createWriteStream(fileName)
if (err) { wstream.write(value)
reject(err) wstream.end()
}
resolve() wstream.on('finish', () => { resolve() })
}) wstream.on('error', (err) => { reject(err) })
}) })
} }
// Reads a file from the filesystem. // Reads a file from the filesystem.
function readFile (fileName) { function readFile (fileName) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
fs.readFile(fileName, 'utf8', (err, data) => { let readStream = fs.createReadStream(fileName)
if (err) {
reject(err) readStream.on('error', (err) => { reject(err) })
} readStream.on('data', (chunk) => {
resolve(data) resolve(chunk)
}) })
}) })
} }
module.exports = { module.exports = {
writeFile, writeFile,
readFile readFile
......
const crypt = new OpenCrypto()
const axios = require('axios') const axios = require('axios')
const sodium = require('libsodium-wrappers')
// Custom modules // Custom modules
const indexedDB = require('./indexedDB') const indexedDB = require('./indexedDB')
...@@ -19,43 +19,30 @@ loadedKeyPair() ...@@ -19,43 +19,30 @@ loadedKeyPair()
form.addEventListener('submit', (e) => { form.addEventListener('submit', (e) => {
e.preventDefault() e.preventDefault()
var saltValue = ''
const password = e.target.password.value const password = e.target.password.value
const salt = crypt.getRandomSalt() const salt = sodium.randombytes_buf(sodium.crypto_pwhash_SALTBYTES)
const keyPair = sodium.crypto_box_keypair()
salt.then((salt) => {
const keys = crypt.getKeyPair(undefined, undefined, undefined, true) const keyLength = sodium.crypto_pwhash_BYTES_MIN
const pass = crypt.keyFromPassphrase(password, salt, 300000) const opslimit = sodium.crypto_pwhash_OPSLIMIT_MAX
saltValue = salt const memlimit = sodium.crypto_pwhash_MEMLIMIT_MAX
return Promise.all([keys, pass]) const algorithm = sodium.crypto_pwhash_ALG_DEFAULT
}).then((values) => {
const keyPair = values[0] const encryptPassword = sodium.crypto_pwhash(keyLength, password, salt, opslimit, memlimit, algorithm)
const hash = values[1] const encryptedPrivateKey = sodium.crypto_pwhash(keyLength, keyPair.privateKey, encryptPassword, opslimit, memlimit, algorithm)
const encryptedPrivateKey = crypt.encryptPrivateKey(keyPair.privateKey, hash)
const publicKeyValue = crypt.cryptoPublicToPem(keyPair.publicKey) const postKeys = axios.post('register',
{
// Export key as an arraybuffer to import later as unextractable private key. salt: salt,
const exportedPrivateKey = crypto.subtle.exportKey('pkcs8', keyPair.privateKey) publicKey: keyPair.publicKey,
privateKey: encryptedPrivateKey
return Promise.all([encryptedPrivateKey, publicKeyValue, exportedPrivateKey]) })
}).then((values) => {
// Import arraybuffer as an unextractable private key.
const nonExtractablePrivateKey = crypto.subtle.importKey('pkcs8', values[2], {name: 'RSA-OAEP', hash: {name: 'SHA-512'}, modulusLength: 2048, publicExponent: new Uint8Array([0x01, 0x00, 0x01])}, false, ['decrypt', 'unwrapKey'])
const postKeys = axios.post('register',
{
salt: saltValue,
publicKey: values[1],
privateKey: values[0]
})
return Promise.all([nonExtractablePrivateKey, postKeys]) postKeys.then((values) => {
}).then((values) => { indexedDB.callOnStore('libsodium_testkeystore', 'keyStore', (store) => {
// Save unextractable private key to indexedDB.
indexedDB.callOnStore('testkeystore', 'keyStore', (store) => {
store.put({ store.put({
id: 1, id: 1,
keys: values[0] keys: keyPair.privateKey
}) })
}) })
}).catch((err) => { }).catch((err) => {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment