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

Relays and mailboxes #3

Merged
merged 88 commits into from
May 12, 2021
Merged
Show file tree
Hide file tree
Changes from 78 commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
6745b72
initial Relay implementation
pavlo-liapin Jan 14, 2021
c2ef4eb
fix some linter errors
pavlo-liapin Jan 14, 2021
709655c
stub for Mailbox
pavlo-liapin Jan 14, 2021
24f1e8f
move some more code from CoffeeScript
pavlo-liapin Jan 15, 2021
5857792
encode/decode UTF8 strings in mailboxes
pavlo-liapin Jan 15, 2021
98de3c1
add more options to create a mailbox
pavlo-liapin Jan 18, 2021
cde5a2c
add initial relay operations
pavlo-liapin Jan 18, 2021
2f80539
add message status test
pavlo-liapin Jan 19, 2021
08ac31a
fix the count test
pavlo-liapin Jan 19, 2021
b8b10dd
add mailbox download test
pavlo-liapin Jan 19, 2021
58ecec8
add delete tests
pavlo-liapin Jan 20, 2021
fae838e
add message status test
pavlo-liapin Jan 20, 2021
54e5555
add first file commands and tests
pavlo-liapin Jan 20, 2021
f1dd9f1
add file status and metadata test
pavlo-liapin Jan 20, 2021
beeb6ff
add download file logic
pavlo-liapin Jan 22, 2021
9a82e36
add delete file command
pavlo-liapin Jan 22, 2021
9501b5e
refactor Relay code
pavlo-liapin Jan 25, 2021
9968b08
more Relay refactorings
pavlo-liapin Jan 25, 2021
37b04db
further Relay optimizations
pavlo-liapin Jan 25, 2021
5e2c7c5
remove unneeded private method
pavlo-liapin Jan 25, 2021
20701aa
optimize _makeNonce method
pavlo-liapin Jan 25, 2021
d2fb5a2
better itoa method
pavlo-liapin Jan 25, 2021
987f8bb
move test.zip out of src
pavlo-liapin Jan 25, 2021
f98f780
move file commands from Relay to Mailbox API
pavlo-liapin Jan 26, 2021
9032e83
move message Zax commands to Mailbox
pavlo-liapin Jan 26, 2021
bf74890
optimize some constructors
pavlo-liapin Jan 26, 2021
e30403b
further constructor optimizations
pavlo-liapin Jan 26, 2021
d0fe25c
optimize optional properties
pavlo-liapin Jan 26, 2021
0616af3
move mailbox tests to appropriate directory
pavlo-liapin Jan 27, 2021
5db0c0d
incremental improvents
pavlo-liapin Jan 27, 2021
4309d67
decrypt messages after download
pavlo-liapin Jan 27, 2021
32b6fcb
optimize h2() input
pavlo-liapin Jan 27, 2021
3e36536
optimize base64 conversions
pavlo-liapin Jan 27, 2021
ff212f5
optimize symmetric encryption
pavlo-liapin Jan 27, 2021
7960f9e
optmize Zax command response parsing
pavlo-liapin Jan 27, 2021
05dbfbf
fix some linter warnings
pavlo-liapin Jan 28, 2021
9bbb6dd
move runCommand encryption logic to Mailbox
pavlo-liapin Jan 28, 2021
4b001e9
refactor Relay
pavlo-liapin Jan 28, 2021
dbfd697
optimize Relay code
pavlo-liapin Jan 28, 2021
883b8e1
move connectMailbox logic to Mailbox
pavlo-liapin Jan 28, 2021
36205df
add some comments
pavlo-liapin Jan 29, 2021
7553575
add more comments and typings to Mailbox
pavlo-liapin Jan 29, 2021
9a34563
more comments for Mailbox
pavlo-liapin Jan 29, 2021
cf61133
add more comments to Mailbox
pavlo-liapin Jan 29, 2021
f1dbdcd
move Zax interfaces to a separate file
pavlo-liapin Feb 1, 2021
5290d41
improvements to Relay class per CR
pavlo-liapin Feb 1, 2021
e9ca70c
extend some Mailbox tests
pavlo-liapin Feb 1, 2021
118429c
make Mailbox.download method more readable
pavlo-liapin Feb 1, 2021
2aea172
optimize Mailbox file test
pavlo-liapin Feb 2, 2021
42a5d8f
generate a file for Mailbox file test in the test itself
pavlo-liapin Feb 2, 2021
6ceb987
move test relay URL to config and add README section about tests
pavlo-liapin Feb 2, 2021
48d6896
refactor Mailbox static intializers
pavlo-liapin Feb 2, 2021
807d20a
add some eslint exceptions
pavlo-liapin Feb 2, 2021
1c889db
some minor refactoring
pavlo-liapin Feb 3, 2021
27bfe8c
add an ability to upload encrypted plaintext messages
pavlo-liapin Feb 3, 2021
b003ca3
remove RELAY_SESSION_TIMEOUT usage from KeyRing
pavlo-liapin Feb 3, 2021
72c42ae
don't store relayPublicKey in Relay
pavlo-liapin Feb 3, 2021
bdfbed5
add RelaysService
pavlo-liapin Feb 9, 2021
cc314fb
remove useless verification
pavlo-liapin Feb 9, 2021
b9e7a4b
make Relay constuctor private and add a static `new` method
pavlo-liapin Feb 26, 2021
47e8460
move nonce helper to NaCl driver
pavlo-liapin Feb 26, 2021
3980443
move raw encode/decode methods to NaCl driver
pavlo-liapin Mar 1, 2021
742622b
refactor Relay/Mailbox
pavlo-liapin Mar 1, 2021
d26f8b5
fix lint errors
pavlo-liapin Mar 1, 2021
ae06043
further optimizations to Mailbox/Relay
pavlo-liapin Mar 1, 2021
98c0b05
more refactoring
pavlo-liapin Mar 1, 2021
6cceaca
fixes per CR
pavlo-liapin Mar 15, 2021
475b73e
update dependencies
pavlo-liapin Mar 16, 2021
acb252c
turn off some ESLint rules
pavlo-liapin Mar 16, 2021
93f1d66
fixes per CR
pavlo-liapin Mar 18, 2021
94ef178
tag all comments with the class name
pavlo-liapin Mar 18, 2021
cae01ea
fixes per CR
pavlo-liapin Mar 18, 2021
542d43e
fixes per CR
pavlo-liapin Mar 18, 2021
1858e28
remove temporary keys
pavlo-liapin Apr 23, 2021
a5e9608
log network errors
pavlo-liapin Apr 23, 2021
4029aa2
add mutex
pavlo-liapin Apr 26, 2021
cba87a8
move relay factory to Relay class as a static method
pavlo-liapin Apr 26, 2021
0a19d2d
consider session timeouts
pavlo-liapin Apr 27, 2021
5099039
fixes per CR
pavlo-liapin May 5, 2021
1b290da
update NaclDriver interface to be more consistent
pavlo-liapin May 5, 2021
7b0aee2
move RelayCommand to zax.interface.ts
pavlo-liapin May 6, 2021
60f12c1
move some method wrappers from NaCl Driver to NaCl singleton
pavlo-liapin May 6, 2021
3318841
optimize httpCall error message
pavlo-liapin May 6, 2021
777f17b
remove try-catch for HTTP calls
pavlo-liapin May 11, 2021
15c1d31
minor refactorings per CR
pavlo-liapin May 12, 2021
05046a8
make NaCl constructor private to prevent unintended usage
pavlo-liapin May 12, 2021
5c10662
remove unnecessary methods
pavlo-liapin May 12, 2021
9da743c
Move static encryption methods to a separate helper
pavlo-liapin May 12, 2021
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: 4 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
"@typescript-eslint"
],
"rules": {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-empty-function": [
"error",
{ "allow" : ["constructors"] }
],
"indent": [
"error",
2
2,
{ "SwitchCase": 1 }
],
"linebreak-style": [
"error",
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
# glow.ts
Client library for interacting with Zax Cryptographic Relay

## Running tests

Unit tests are powered by [Jest](https://jestjs.io). The engine runs all the tests in each `describe` section serially in the order they are described in the `.spec.ts` file.
By default, unit tests connect to a remote [Zax](https://github.com/vault12/zax) Cryptographic Relay Server on `https://z.vault12.com`.
You may also run tests on a local or any other test server by modifying the code in [src/tests.helper.ts#L1](src/tests.helper.ts#L1).
1 change: 1 addition & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const config: Config.InitialOptions = {
setupFiles: ['jest-localstorage-mock'],
preset: 'ts-jest',
testEnvironment: 'jsdom', // TODO: run tests through both 'node' and 'jsdom'
testTimeout: 10000,
verbose: true
};
export default config;
520 changes: 311 additions & 209 deletions package-lock.json

Large diffs are not rendered by default.

18 changes: 11 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,21 @@
"main": "dist/glow.js",
"types": "dist/types/index.d.ts",
"dependencies": {
"async-mutex": "0.3.1",
"axios": "0.21.1",
"js-sha256": "0.9.0",
"tweetnacl": "1.0.3"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "4.8.2",
"@typescript-eslint/parser": "4.8.2",
"eslint": "7.14.0",
"@types/jest": "26.0.20",
"@typescript-eslint/eslint-plugin": "4.18.0",
"@typescript-eslint/parser": "4.18.0",
"axios-mock-adapter": "1.19.0",
"eslint": "7.22.0",
"jest": "26.6.3",
"jest-localstorage-mock": "2.4.4",
"ts-jest": "26.4.4",
"ts-node": "9.0.0",
"typescript": "4.1.2"
"jest-localstorage-mock": "2.4.8",
"ts-jest": "26.5.3",
"ts-node": "9.1.1",
"typescript": "4.2.3"
}
}
12 changes: 3 additions & 9 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
export const config = {

COMM_KEY_TAG: '__::commKey::__',
NONCE_TAG: '__nc',
STORAGE_ROOT: '.v2.stor.vlt12',
// Relay tokens, keys and hashes are 32 bytes
RELAY_TOKEN_LEN: 32,

RELAY_TOKEN_B64: 44,

// 5 min - Matched with config.x.relay.token_timeout
// 5 min - Token expiration on the server side, matched with config.x.relay.token_timeout on Zax server
RELAY_TOKEN_TIMEOUT: 5 * 60 * 1000,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

never used

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used now, Mailbox reconnects when Relay's token expires


// 15 min - Matched with config.x.relay.session_timeout
RELAY_SESSION_TIMEOUT: 15 * 60 * 1000
// 5 sec - Ajax request timeout
RELAY_AJAX_TIMEOUT: 5 * 1000
};
3 changes: 0 additions & 3 deletions src/crypto-storage/crypto-storage.spec.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { CryptoStorage } from './crypto-storage';
import { LocalStorageDriver } from './local-storage.driver';
import { NaCl } from '../nacl/nacl';
import { NaClDriver } from '../nacl/nacl-driver.interface';

describe('CryptoStorage', () => {
let nacl: NaClDriver;
let storage: CryptoStorage;

beforeAll(async () => {
NaCl.setInstance();
nacl = NaCl.getInstance();
storage = await CryptoStorage.new(new LocalStorageDriver(), 'test');
});

Expand Down
12 changes: 6 additions & 6 deletions src/crypto-storage/crypto-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ export class CryptoStorage {

async save(tag: string, data: unknown): Promise<boolean> {
if (!this.driver) {
throw new Error('Storage driver is not set');
throw new Error('[CryptoStorage] Storage driver is not set');
}
if (!this.storageKey) {
throw new Error('Storage key is not set');
throw new Error('[CryptoStorage] Storage key is not set');
}
// Convert the data to JSON, then convert that string to a byte array
const input = JSON.stringify(data);
Expand All @@ -48,10 +48,10 @@ export class CryptoStorage {

async get(tag: string): Promise<unknown> {
if (!this.driver) {
throw new Error('Storage driver is not set');
throw new Error('[CryptoStorage] Storage driver is not set');
}
if (!this.storageKey) {
throw new Error('Storage key is not set');
throw new Error('[CryptoStorage] Storage key is not set');
}
// Get cipher text and nonce from the storage
const data = await this.driver.get(this.addPrefix(tag));
Expand All @@ -67,13 +67,13 @@ export class CryptoStorage {
const decoded = await this.nacl.decode_utf8(source);
return JSON.parse(decoded);
} else {
throw new Error('crypto_secretbox_open: decryption error');
throw new Error('[CryptoStorage] crypto_secretbox_open: decryption error');
}
}

async remove(tag: string): Promise<boolean> {
if (!this.driver) {
throw new Error('Storage driver is not set');
throw new Error('[CryptoStorage] Storage driver is not set');
}
await this.driver.remove(this.addPrefix(tag));
await this.driver.remove(this.addNonceTag(tag));
Expand Down
26 changes: 2 additions & 24 deletions src/keyring/keyring.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { KeyRing } from './keyring';
import { NaCl } from '../nacl/nacl';
import { NaClDriver } from '../nacl/nacl-driver.interface';
import { Keys } from '../keys/keys';
import { config } from '../config';
import { Utils } from '../utils/utils';

describe('Keyring', () => {
Expand Down Expand Up @@ -40,7 +39,7 @@ describe('Keyring', () => {

const aliceKey = new Keys(await nacl.crypto_box_keypair());
await ring.addGuest('Alice', aliceKey.publicKey);
const hpk = Utils.toBase64(await nacl.h2(aliceKey.publicKey));
const hpk = Utils.toBase64(await nacl.h2(Utils.fromBase64(aliceKey.publicKey)));
expect(ring.getTagByHpk(hpk)).not.toBeNull();
expect(ring.getTagByHpk('Bob')).toBeNull();
});
Expand All @@ -61,29 +60,8 @@ describe('Keyring', () => {
for (let i = 0; i < 10; i++) {
expect(originalRing.getGuestKey(`keys${i}`)).toEqual(restored.getGuestKey(`keys${i}`));
}
expect(originalRing.getHpk()).toEqual(restored.getHpk());
expect(await originalRing.getHpk()).toEqual(await restored.getHpk());

expect(backup).toBe(backedUpAgain);
});

it('temporary keys', async () => {
jest.useFakeTimers();
// mock config value
config.RELAY_SESSION_TIMEOUT = 100;
const ring = await KeyRing.new('test5');
const keys = new Keys(await nacl.crypto_box_keypair());
await ring.addTempGuest('temp', keys.publicKey);
// the key has to exist before we run the timer
expect(ring.getGuestKey('temp')).not.toBeNull();
// the key should not have expired yet
expect(ring.getTimeToGuestExpiration('temp')).toBeGreaterThan(0);

jest.runAllTimers();

expect(setTimeout).toHaveBeenCalledTimes(1);
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 100);
// the key and timeout are erased
expect(ring.getNumberOfGuests()).toBe(0);
expect(ring.getTimeToGuestExpiration('temp')).toBe(0);
});
});
Loading