From 9a8f1cd33f4060cc7fddf3beb72c6ff830ba06da Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Sat, 30 Dec 2017 13:20:25 +0000 Subject: [PATCH] Add AsymmetricCryptoManager for asymmetric encryption. --- package.json | 2 ++ src/api/Crypto.test.ts | 11 ++++++++++- src/api/Crypto.ts | 33 +++++++++++++++++++++++++++++++++ yarn.lock | 14 +++++++++++++- 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 0cc166d..d820389 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "localforage": "^1.5.5", "material-ui": "^0.20.0", "moment": "^2.19.3", + "node-rsa": "^0.4.2", "react": "^16.2.0", "react-big-calendar": "^0.17.0", "react-dom": "^16.2.0", @@ -38,6 +39,7 @@ "@types/jest": "^21.1.8", "@types/material-ui": "^0.18.5", "@types/node": "^8.0.53", + "@types/node-rsa": "^0.4.1", "@types/react": "^16.0.25", "@types/react-big-calendar": "^0.15.0", "@types/react-dom": "^16.0.3", diff --git a/src/api/Crypto.test.ts b/src/api/Crypto.test.ts index 0f27077..8b8becf 100644 --- a/src/api/Crypto.test.ts +++ b/src/api/Crypto.test.ts @@ -1,4 +1,4 @@ -import { CryptoManager, deriveKey } from './Crypto'; +import { CryptoManager, AsymmetricCryptoManager, deriveKey } from './Crypto'; import { USER, PASSWORD, keyBase64 } from './TestConstants'; import { stringToByteArray } from './Helpers'; @@ -27,3 +27,12 @@ it('Symmetric encryption v2', () => { const expected = 'XQ/A0gentOaE98R9wzf3zEIAHj4OH1GF8J4C6JiJupo='; expect(expected).toBe(cryptoManager.hmac64(stringToByteArray('Some test data'))); }); + +it('Asymmetric encryption', () => { + const keyPair = AsymmetricCryptoManager.generateKeyPair(); + const cryptoManager = new AsymmetricCryptoManager(keyPair); + + const clearText = [1, 2, 4, 5]; + const cipher = cryptoManager.encryptBytes(keyPair.publicKey, clearText); + expect(clearText).toEqual(cryptoManager.decryptBytes(cipher)); +}); diff --git a/src/api/Crypto.ts b/src/api/Crypto.ts index 96e5f4e..72ea122 100644 --- a/src/api/Crypto.ts +++ b/src/api/Crypto.ts @@ -1,4 +1,5 @@ import * as sjcl from 'sjcl'; +import * as NodeRSA from 'node-rsa'; import * as Constants from './Constants'; import { byte, base64 } from './Helpers'; @@ -114,3 +115,35 @@ export class CryptoManager { return hmac256(this.hmacKey, content); } } + +function bufferToArray(buffer: Buffer) { + return Array.prototype.slice.call(buffer); +} + +export class AsymmetricCryptoManager { + keyPair: NodeRSA; + + static generateKeyPair() { + const keyPair = new NodeRSA(); + keyPair.generateKeyPair(3072, 65537); + const pubkey = keyPair.exportKey('pkcs1-public-der') as Buffer; + const privkey = keyPair.exportKey('pkcs1-private-der') as Buffer; + return new AsymmetricKeyPair( + bufferToArray(pubkey), bufferToArray(privkey)); + } + + constructor(keyPair: AsymmetricKeyPair) { + this.keyPair = new NodeRSA(); + this.keyPair.importKey(Buffer.from(keyPair.privateKey), 'pkcs1-der'); + } + + encryptBytes(publicKey: byte[], content: byte[]): byte[] { + const key = new NodeRSA(); + key.importKey(Buffer.from(publicKey), 'pkcs1-public-der'); + return bufferToArray(key.encrypt(Buffer.from(content), 'buffer')); + } + + decryptBytes(content: byte[]): byte[] { + return bufferToArray(this.keyPair.decrypt(Buffer.from(content), 'buffer')); + } +} diff --git a/yarn.lock b/yarn.lock index 9b0cb16..c90ea06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,6 +25,12 @@ "@types/react" "*" "@types/react-addons-linked-state-mixin" "*" +"@types/node-rsa@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/node-rsa/-/node-rsa-0.4.1.tgz#7ac029af8080069539765c18e4b12277a7c3f3cb" + dependencies: + "@types/node" "*" + "@types/node@*", "@types/node@^8.0.53": version "8.0.53" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.53.tgz#396b35af826fa66aad472c8cb7b8d5e277f4e6d8" @@ -325,7 +331,7 @@ asn1.js@^4.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -asn1@~0.2.3: +asn1@0.2.3, asn1@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" @@ -3740,6 +3746,12 @@ node-pre-gyp@^0.6.36, node-pre-gyp@^0.6.39: tar "^2.2.1" tar-pack "^3.4.0" +node-rsa@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/node-rsa/-/node-rsa-0.4.2.tgz#d6391729ec16a830ed5a38042b3157d2d5d72530" + dependencies: + asn1 "0.2.3" + node-status-codes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f"