@freesignal/protocol 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/crypto.d.ts CHANGED
@@ -16,61 +16,7 @@
16
16
  * You should have received a copy of the GNU General Public License
17
17
  * along with this program. If not, see <https://www.gnu.org/licenses/>
18
18
  */
19
- export type HashAlgorithms = 'sha224' | 'sha256' | 'sha384' | 'sha512';
20
- export type HmacAlgorithms = 'kmac128' | 'kmac256';
21
- interface UUIDv4 {
22
- toString(): string;
23
- toJSON(): string;
24
- toBuffer(): Uint8Array;
25
- }
26
- export interface Crypto {
27
- hash(message: Uint8Array, algorithm?: HashAlgorithms): Uint8Array;
28
- hmac(key: Uint8Array, message: Uint8Array, length?: number, algorithm?: HmacAlgorithms): Uint8Array;
29
- hkdf(key: Uint8Array, salt: Uint8Array, info?: Uint8Array | string, length?: number): Uint8Array;
30
- readonly KeyPair: typeof Crypto.KeyPair;
31
- readonly box: Crypto.box;
32
- readonly ECDH: Crypto.ECDH;
33
- readonly EdDSA: Crypto.EdDSA;
34
- readonly UUID: Crypto.UUID;
35
- randomBytes(n: number): Uint8Array;
36
- scalarMult(n: Uint8Array, p: Uint8Array): Uint8Array;
37
- }
38
- export declare namespace Crypto {
39
- type KeyPair = {
40
- readonly publicKey: Uint8Array;
41
- readonly secretKey: Uint8Array;
42
- };
43
- namespace KeyPair {
44
- function isKeyPair(obj: any): boolean;
45
- }
46
- interface box {
47
- readonly keyLength: number;
48
- readonly nonceLength: number;
49
- encrypt(msg: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array;
50
- decrypt(msg: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array | undefined;
51
- }
52
- interface ECDH {
53
- readonly publicKeyLength: number;
54
- readonly secretKeyLength: number;
55
- keyPair(secretKey?: Uint8Array): KeyPair;
56
- sharedKey(publicKey: Uint8Array, secretKey: Uint8Array): Uint8Array;
57
- }
58
- interface EdDSA {
59
- readonly publicKeyLength: number;
60
- readonly secretKeyLength: number;
61
- readonly signatureLength: number;
62
- readonly seedLength: number;
63
- keyPair(secretKey?: Uint8Array): KeyPair;
64
- keyPairFromSeed(seed: Uint8Array): KeyPair;
65
- sign(msg: Uint8Array, secretKey: Uint8Array): Uint8Array;
66
- verify(msg: Uint8Array, sig: Uint8Array, publicKey: Uint8Array): boolean;
67
- }
68
- interface UUID {
69
- generate(): UUIDv4;
70
- stringify(arr: Uint8Array, offset?: number): string;
71
- parse(uuid: string): Uint8Array;
72
- }
73
- }
19
+ import { Crypto } from './types';
74
20
  declare const crypto: Crypto;
75
21
  declare namespace crypto {
76
22
  type KeyPair = Crypto.KeyPair;
package/crypto.js CHANGED
@@ -21,14 +21,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
21
21
  return (mod && mod.__esModule) ? mod : { "default": mod };
22
22
  };
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
- exports.Crypto = void 0;
25
24
  const js_sha3_1 = require("js-sha3");
26
25
  const tweetnacl_1 = __importDefault(require("tweetnacl"));
27
26
  const uuid_1 = require("uuid");
28
27
  const utils_1 = require("./utils");
29
- var Crypto;
30
- (function (Crypto) {
31
- })(Crypto || (exports.Crypto = Crypto = {}));
32
28
  class CryptoConstructor {
33
29
  constructor() {
34
30
  this.KeyPair = {
@@ -72,9 +68,6 @@ class CryptoConstructor {
72
68
  hkdf(key, salt, info, length = 32) {
73
69
  return new Uint8Array(js_sha3_1.kmac256.digest(key, salt, length * 8, info !== null && info !== void 0 ? info : new Uint8Array()));
74
70
  }
75
- scalarMult(n, p) {
76
- return tweetnacl_1.default.scalarMult(n, p);
77
- }
78
71
  }
79
72
  (function (CryptoConstructor) {
80
73
  class box {
@@ -102,7 +95,10 @@ class CryptoConstructor {
102
95
  return tweetnacl_1.default.box.keyPair();
103
96
  }
104
97
  sharedKey(publicKey, secretKey) {
105
- return tweetnacl_1.default.scalarMult(publicKey, secretKey);
98
+ return tweetnacl_1.default.box.before(publicKey, secretKey);
99
+ }
100
+ scalarMult(n, p) {
101
+ return tweetnacl_1.default.scalarMult(n, p);
106
102
  }
107
103
  }
108
104
  CryptoConstructor.ECDH = ECDH;
package/data.d.ts CHANGED
@@ -16,26 +16,12 @@
16
16
  * You should have received a copy of the GNU General Public License
17
17
  * along with this program. If not, see <https://www.gnu.org/licenses/>
18
18
  */
19
- import { Encodable } from "./types";
20
- export declare enum Protocols {
21
- NULL = "",
22
- MESSAGE = "/freesignal/message/1.0.0",
23
- RELAY = "/freesignal/relay/1.0.0"
24
- }
25
- export declare namespace Protocols {
26
- function isProtocol(protocol: any): boolean;
27
- function fromCode(code: number): Protocols;
28
- function toCode(protocol: Protocols): number;
29
- function encode(protocol: Protocols, length?: number): Uint8Array;
30
- function decode(array: Uint8Array): Protocols;
31
- }
19
+ import { Encodable, Protocols } from "./types";
32
20
  export interface Datagram {
33
21
  readonly id: string;
34
22
  readonly version: number;
35
- readonly senderKey: string;
36
- readonly senderRelay?: string;
37
- readonly receiverKey: string;
38
- readonly receiverRelay?: string;
23
+ readonly sender: string;
24
+ readonly receiver: string;
39
25
  readonly protocol: Protocols;
40
26
  readonly createdAt: number;
41
27
  payload?: Uint8Array;
@@ -44,15 +30,13 @@ export declare namespace Datagram {
44
30
  const version = 1;
45
31
  function create(sender: Uint8Array | string, receiver: Uint8Array | string, protocol: Protocols, payload?: Uint8Array | Encodable): DatagramConstructor;
46
32
  function isDatagram(obj: any): boolean;
47
- function from(data: Uint8Array): DatagramConstructor;
33
+ function from(data: Uint8Array | Datagram | string): DatagramConstructor;
48
34
  }
49
35
  declare class DatagramConstructor implements Encodable, Datagram {
50
36
  readonly id: string;
51
37
  readonly version: number;
52
- readonly senderKey: string;
53
- readonly senderRelay?: string;
54
- readonly receiverKey: string;
55
- readonly receiverRelay?: string;
38
+ readonly sender: string;
39
+ readonly receiver: string;
56
40
  readonly protocol: Protocols;
57
41
  readonly createdAt: number;
58
42
  payload?: Uint8Array;
package/data.js CHANGED
@@ -21,43 +21,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
21
21
  return (mod && mod.__esModule) ? mod : { "default": mod };
22
22
  };
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
- exports.Datagram = exports.Protocols = void 0;
24
+ exports.Datagram = void 0;
25
25
  const utils_1 = require("./utils");
26
26
  const crypto_1 = __importDefault(require("./crypto"));
27
27
  const fflate_1 = __importDefault(require("fflate"));
28
- var Protocols;
29
- (function (Protocols) {
30
- Protocols["NULL"] = "";
31
- Protocols["MESSAGE"] = "/freesignal/message/1.0.0";
32
- Protocols["RELAY"] = "/freesignal/relay/1.0.0";
33
- })(Protocols || (exports.Protocols = Protocols = {}));
34
- (function (Protocols) {
35
- function isProtocol(protocol) {
36
- return Object.values(Protocols).includes(protocol);
37
- }
38
- Protocols.isProtocol = isProtocol;
39
- function fromCode(code) {
40
- return Object.values(Protocols)[code];
41
- }
42
- Protocols.fromCode = fromCode;
43
- function toCode(protocol) {
44
- return Object.values(Protocols).indexOf(protocol);
45
- }
46
- Protocols.toCode = toCode;
47
- function encode(protocol, length) {
48
- /*const raw = numberToUint8Array(Protocols.toCode(protocol), length).reverse();
49
- raw[0] |= (raw.length - 1) << 6;
50
- return raw;*/
51
- return (0, utils_1.numberToUint8Array)(Protocols.toCode(protocol), length !== null && length !== void 0 ? length : 4, 'big');
52
- }
53
- Protocols.encode = encode;
54
- function decode(array) {
55
- array[0] &= 63;
56
- array = array.reverse();
57
- return Protocols.fromCode((0, utils_1.numberFromUint8Array)(array));
58
- }
59
- Protocols.decode = decode;
60
- })(Protocols || (exports.Protocols = Protocols = {}));
28
+ const types_1 = require("./types");
61
29
  var Datagram;
62
30
  (function (Datagram) {
63
31
  Datagram.version = 1;
@@ -70,7 +38,12 @@ var Datagram;
70
38
  }
71
39
  Datagram.isDatagram = isDatagram;
72
40
  function from(data) {
73
- return new DatagramConstructor(data);
41
+ if (typeof data === 'string') {
42
+ const decoded = (0, utils_1.decodeBase64)(data);
43
+ return new DatagramConstructor(decoded);
44
+ }
45
+ else
46
+ return new DatagramConstructor(data);
74
47
  }
75
48
  Datagram.from = from;
76
49
  })(Datagram || (exports.Datagram = Datagram = {}));
@@ -79,35 +52,29 @@ class DatagramConstructor {
79
52
  if (!receiver && !protocol && !payload) {
80
53
  if (data instanceof Uint8Array) {
81
54
  this.version = data[0] & 63;
82
- this.protocol = Protocols.decode(data.subarray(1, 4));
83
- this.id = crypto_1.default.UUID.stringify(data.subarray(4, 20));
84
- this.createdAt = (0, utils_1.numberFromUint8Array)(data.subarray(20, 28));
85
- this.senderKey = (0, utils_1.encodeBase64)(data.subarray(28, 28 + crypto_1.default.EdDSA.publicKeyLength));
86
- this.receiverKey = (0, utils_1.encodeBase64)(data.subarray(28 + crypto_1.default.EdDSA.publicKeyLength, DatagramConstructor.headerOffset));
87
- const senderRelayOffset = data.indexOf(255, DatagramConstructor.headerOffset);
88
- const receiverRelayOffset = data.indexOf(255, senderRelayOffset + 1);
89
- this.senderRelay = (0, utils_1.encodeUTF8)(data.subarray(DatagramConstructor.headerOffset, senderRelayOffset)) ? "" : undefined;
90
- this.receiverRelay = (0, utils_1.encodeUTF8)(data.subarray(senderRelayOffset + 1, receiverRelayOffset)) ? "" : undefined;
55
+ this.protocol = types_1.Protocols.decode(data.subarray(1, 2));
56
+ this.id = crypto_1.default.UUID.stringify(data.subarray(2, 18));
57
+ this.createdAt = (0, utils_1.numberFromUint8Array)(data.subarray(18, 26));
58
+ this.sender = (0, utils_1.encodeBase64)(data.subarray(26, 26 + crypto_1.default.EdDSA.publicKeyLength));
59
+ this.receiver = (0, utils_1.encodeBase64)(data.subarray(26 + crypto_1.default.EdDSA.publicKeyLength, DatagramConstructor.headerOffset));
91
60
  if (data[0] & 128) {
92
61
  const signature = data.subarray(data.length - crypto_1.default.EdDSA.signatureLength);
93
- if (!crypto_1.default.EdDSA.verify(data.subarray(0, data.length - crypto_1.default.EdDSA.signatureLength), signature, data.subarray(28, 28 + crypto_1.default.EdDSA.publicKeyLength)))
62
+ if (!crypto_1.default.EdDSA.verify(data.subarray(0, data.length - crypto_1.default.EdDSA.signatureLength), signature, data.subarray(26, 26 + crypto_1.default.EdDSA.publicKeyLength)))
94
63
  throw new Error('Invalid signature for Datagram');
95
64
  }
96
65
  if (data[0] & 64)
97
- this.payload = fflate_1.default.inflateSync(data.subarray(receiverRelayOffset + 1, data.length));
66
+ this.payload = fflate_1.default.inflateSync(data.subarray(DatagramConstructor.headerOffset, data.length));
98
67
  else
99
- this.payload = data.subarray(receiverRelayOffset + 1, data.length);
68
+ this.payload = data.subarray(DatagramConstructor.headerOffset, data.length);
100
69
  }
101
70
  else if (Datagram.isDatagram(data)) {
102
71
  const datagram = data;
103
72
  this.id = datagram.id;
104
73
  this.version = datagram.version;
105
- this.senderKey = datagram.senderKey;
106
- this.receiverKey = datagram.receiverKey;
74
+ this.sender = datagram.sender;
75
+ this.receiver = datagram.receiver;
107
76
  this.protocol = datagram.protocol;
108
77
  this.createdAt = datagram.createdAt;
109
- this.senderRelay = datagram.senderRelay;
110
- this.receiverRelay = datagram.receiverRelay;
111
78
  this.payload = datagram.payload;
112
79
  }
113
80
  else
@@ -116,20 +83,8 @@ class DatagramConstructor {
116
83
  else if (typeof data === 'string' || data instanceof Uint8Array) {
117
84
  this.id = crypto_1.default.UUID.generate().toString();
118
85
  this.version = Datagram.version;
119
- if (typeof data === 'string') {
120
- const address = data.split('@');
121
- this.senderKey = address[0];
122
- this.senderRelay = address[1];
123
- }
124
- else
125
- this.senderKey = (0, utils_1.encodeBase64)(data);
126
- if (typeof receiver === 'string') {
127
- const address = receiver.split('@');
128
- this.receiverKey = address[0];
129
- this.receiverRelay = address[1];
130
- }
131
- else
132
- this.receiverKey = (0, utils_1.encodeBase64)(receiver);
86
+ this.sender = typeof data === 'string' ? data : (0, utils_1.encodeBase64)(data);
87
+ this.receiver = typeof receiver === 'string' ? receiver : (0, utils_1.encodeBase64)(receiver);
133
88
  this.protocol = protocol;
134
89
  this.createdAt = Date.now();
135
90
  this.payload = payload instanceof Uint8Array ? payload : payload === null || payload === void 0 ? void 0 : payload.encode();
@@ -141,12 +96,12 @@ class DatagramConstructor {
141
96
  var _a;
142
97
  compression = compression && this.payload != undefined && this.payload.length > 1024;
143
98
  return (0, utils_1.concatUint8Array)(new Uint8Array(1).fill(this.version | (compression ? 64 : 0)), //1
144
- Protocols.encode(this.protocol, 3), //3
99
+ types_1.Protocols.encode(this.protocol), //1
145
100
  (_a = crypto_1.default.UUID.parse(this.id)) !== null && _a !== void 0 ? _a : [], //16
146
101
  (0, utils_1.numberToUint8Array)(this.createdAt, 8), //8
147
- (0, utils_1.decodeBase64)(this.senderKey), //32
148
- (0, utils_1.decodeBase64)(this.receiverKey), //32
149
- ...(this.senderRelay ? [(0, utils_1.decodeUTF8)(this.senderRelay)] : []), new Uint8Array(1).fill(255), ...(this.receiverRelay ? [(0, utils_1.decodeUTF8)(this.receiverRelay)] : []), new Uint8Array(1).fill(255), ...(this.payload ? [compression ? fflate_1.default.deflateSync(this.payload) : this.payload] : []));
102
+ (0, utils_1.decodeBase64)(this.sender), //32
103
+ (0, utils_1.decodeBase64)(this.receiver), //32
104
+ ...(this.payload ? [compression ? fflate_1.default.deflateSync(this.payload) : this.payload] : []));
150
105
  }
151
106
  encodeSigned(secretKey, compression) {
152
107
  //if (!this.payload) throw new Error('Cannot sign a datagram without payload');
@@ -173,4 +128,4 @@ class DatagramConstructor {
173
128
  return this.toString();
174
129
  }
175
130
  }
176
- DatagramConstructor.headerOffset = 28 + crypto_1.default.EdDSA.publicKeyLength * 2;
131
+ DatagramConstructor.headerOffset = 26 + crypto_1.default.EdDSA.publicKeyLength * 2;
package/double-ratchet.js CHANGED
@@ -69,7 +69,7 @@ class KeySession {
69
69
  ratchetKeys(info) {
70
70
  if (!this._remoteKey)
71
71
  throw new Error();
72
- const sharedKey = crypto_1.default.scalarMult(this.keyPair.secretKey, this._remoteKey);
72
+ const sharedKey = crypto_1.default.ECDH.scalarMult(this.keyPair.secretKey, this._remoteKey);
73
73
  if (!this.rootKey)
74
74
  this.rootKey = crypto_1.default.hash(sharedKey);
75
75
  const hashkey = crypto_1.default.hkdf(sharedKey, this.rootKey, info, KeySession.keyLength * 2);
package/index.d.ts CHANGED
@@ -42,5 +42,5 @@ export declare function createKeySession(opts?: {
42
42
  */
43
43
  export declare function createKeyExchange(signSecretKey: Uint8Array, boxSecretKey: Uint8Array, bundleStore?: LocalStorage<string, crypto.KeyPair>): KeyExchange;
44
44
  export * from "./types";
45
- export { Protocols, Datagram } from "./data";
45
+ export { Datagram } from "./data";
46
46
  export { EncryptedData } from "./double-ratchet";
package/index.js CHANGED
@@ -32,7 +32,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
32
32
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
33
33
  };
34
34
  Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.EncryptedData = exports.Datagram = exports.Protocols = void 0;
35
+ exports.EncryptedData = exports.Datagram = void 0;
36
36
  exports.createKeySession = createKeySession;
37
37
  exports.createKeyExchange = createKeyExchange;
38
38
  const double_ratchet_1 = require("./double-ratchet");
@@ -60,7 +60,6 @@ function createKeyExchange(signSecretKey, boxSecretKey, bundleStore) {
60
60
  }
61
61
  __exportStar(require("./types"), exports);
62
62
  var data_1 = require("./data");
63
- Object.defineProperty(exports, "Protocols", { enumerable: true, get: function () { return data_1.Protocols; } });
64
63
  Object.defineProperty(exports, "Datagram", { enumerable: true, get: function () { return data_1.Datagram; } });
65
64
  var double_ratchet_2 = require("./double-ratchet");
66
65
  Object.defineProperty(exports, "EncryptedData", { enumerable: true, get: function () { return double_ratchet_2.EncryptedData; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@freesignal/protocol",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Signal Protocol implementation in javascript",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "author": "Christian Braghette",
package/test.js CHANGED
@@ -7,6 +7,7 @@ const _1 = require(".");
7
7
  const crypto_1 = __importDefault(require("./crypto"));
8
8
  const data_1 = require("./data");
9
9
  const utils_1 = require("./utils");
10
+ const types_1 = require("./types");
10
11
  const bob = (0, _1.createKeyExchange)(crypto_1.default.EdDSA.keyPair().secretKey, crypto_1.default.ECDH.keyPair().secretKey);
11
12
  const alice = (0, _1.createKeyExchange)(crypto_1.default.EdDSA.keyPair().secretKey, crypto_1.default.ECDH.keyPair().secretKey);
12
13
  const bobmessage = bob.generateData();
@@ -15,7 +16,7 @@ bob.digestMessage(aliceack).then(({ session: bobsession, cleartext }) => {
15
16
  var _a;
16
17
  if (bobsession && cleartext) {
17
18
  console.log("Session established successfully between Alice and Bob.");
18
- const datagram = data_1.Datagram.create(bob.signatureKey, alice.signatureKey, data_1.Protocols.MESSAGE, (_a = bobsession.encrypt((0, utils_1.decodeUTF8)("Hi Alice!"))) === null || _a === void 0 ? void 0 : _a.encode());
19
+ const datagram = data_1.Datagram.create(bob.signatureKey, alice.signatureKey, types_1.Protocols.MESSAGE, (_a = bobsession.encrypt((0, utils_1.decodeUTF8)("Hi Alice!"))) === null || _a === void 0 ? void 0 : _a.encode());
19
20
  //console.log(datagram.payload);
20
21
  const msg = datagram.encode();
21
22
  console.log((0, utils_1.encodeUTF8)(alicesession.decrypt(data_1.Datagram.from(msg).payload)));
@@ -23,7 +24,7 @@ bob.digestMessage(aliceack).then(({ session: bobsession, cleartext }) => {
23
24
  console.log("Successfully handshaked");
24
25
  else
25
26
  console.log("Error during handshake");
26
- const longmsg = data_1.Datagram.create(alice.signatureKey, bob.signatureKey, data_1.Protocols.MESSAGE, alicesession.encrypt(new Uint8Array(1000000).fill(33).map(val => val + Math.floor(Math.random() * 93))));
27
+ const longmsg = data_1.Datagram.create(alice.signatureKey, bob.signatureKey, types_1.Protocols.MESSAGE, alicesession.encrypt(new Uint8Array(1000000).fill(33).map(val => val + Math.floor(Math.random() * 93))));
27
28
  console.log(longmsg.encode().length);
28
29
  console.log(longmsg.encode(false).length);
29
30
  }
package/types.d.ts CHANGED
@@ -25,6 +25,18 @@ export interface Encodable {
25
25
  export declare namespace Encodable {
26
26
  function isEncodable(obj: any): boolean;
27
27
  }
28
+ export declare enum Protocols {
29
+ NULL = "",
30
+ MESSAGE = "/freesignal/message/1.0.0",
31
+ RELAY = "/freesignal/relay/1.0.0"
32
+ }
33
+ export declare namespace Protocols {
34
+ function isProtocol(protocol: any): boolean;
35
+ function fromCode(code: number): Protocols;
36
+ function toCode(protocol: Protocols): number;
37
+ function encode(protocol: Protocols, length?: number): Uint8Array;
38
+ function decode(array: Uint8Array): Protocols;
39
+ }
28
40
  type LocalStorageIterator<T> = Iterable<T>;
29
41
  export interface LocalStorage<K, T> {
30
42
  set(key: K, value: T): Promise<this>;
@@ -58,4 +70,59 @@ export interface KeyExchangeDataBundle {
58
70
  readonly signature: string;
59
71
  readonly onetimePreKey: string[];
60
72
  }
73
+ interface UUIDv4 {
74
+ toString(): string;
75
+ toJSON(): string;
76
+ toBuffer(): Uint8Array;
77
+ }
78
+ export interface Crypto {
79
+ hash(message: Uint8Array, algorithm?: Crypto.HashAlgorithms): Uint8Array;
80
+ hmac(key: Uint8Array, message: Uint8Array, length?: number, algorithm?: Crypto.HmacAlgorithms): Uint8Array;
81
+ hkdf(key: Uint8Array, salt: Uint8Array, info?: Uint8Array | string, length?: number): Uint8Array;
82
+ readonly KeyPair: typeof Crypto.KeyPair;
83
+ readonly box: Crypto.box;
84
+ readonly ECDH: Crypto.ECDH;
85
+ readonly EdDSA: Crypto.EdDSA;
86
+ readonly UUID: Crypto.UUID;
87
+ randomBytes(n: number): Uint8Array;
88
+ }
89
+ export declare namespace Crypto {
90
+ type HashAlgorithms = 'sha224' | 'sha256' | 'sha384' | 'sha512';
91
+ type HmacAlgorithms = 'kmac128' | 'kmac256';
92
+ type KeyPair = {
93
+ readonly publicKey: Uint8Array;
94
+ readonly secretKey: Uint8Array;
95
+ };
96
+ namespace KeyPair {
97
+ function isKeyPair(obj: any): boolean;
98
+ }
99
+ interface box {
100
+ readonly keyLength: number;
101
+ readonly nonceLength: number;
102
+ encrypt(msg: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array;
103
+ decrypt(msg: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array | undefined;
104
+ }
105
+ interface ECDH {
106
+ readonly publicKeyLength: number;
107
+ readonly secretKeyLength: number;
108
+ keyPair(secretKey?: Uint8Array): KeyPair;
109
+ sharedKey(publicKey: Uint8Array, secretKey: Uint8Array): Uint8Array;
110
+ scalarMult(n: Uint8Array, p: Uint8Array): Uint8Array;
111
+ }
112
+ interface EdDSA {
113
+ readonly publicKeyLength: number;
114
+ readonly secretKeyLength: number;
115
+ readonly signatureLength: number;
116
+ readonly seedLength: number;
117
+ keyPair(secretKey?: Uint8Array): KeyPair;
118
+ keyPairFromSeed(seed: Uint8Array): KeyPair;
119
+ sign(msg: Uint8Array, secretKey: Uint8Array): Uint8Array;
120
+ verify(msg: Uint8Array, sig: Uint8Array, publicKey: Uint8Array): boolean;
121
+ }
122
+ interface UUID {
123
+ generate(): UUIDv4;
124
+ stringify(arr: Uint8Array, offset?: number): string;
125
+ parse(uuid: string): Uint8Array;
126
+ }
127
+ }
61
128
  export {};
package/types.js CHANGED
@@ -18,7 +18,8 @@
18
18
  * along with this program. If not, see <https://www.gnu.org/licenses/>
19
19
  */
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.Encodable = void 0;
21
+ exports.Crypto = exports.Protocols = exports.Encodable = void 0;
22
+ const utils_1 = require("./utils");
22
23
  var Encodable;
23
24
  (function (Encodable) {
24
25
  const properties = ['encode', 'toString', 'toJSON'];
@@ -27,3 +28,39 @@ var Encodable;
27
28
  }
28
29
  Encodable.isEncodable = isEncodable;
29
30
  })(Encodable || (exports.Encodable = Encodable = {}));
31
+ var Protocols;
32
+ (function (Protocols) {
33
+ Protocols["NULL"] = "";
34
+ Protocols["MESSAGE"] = "/freesignal/message/1.0.0";
35
+ Protocols["RELAY"] = "/freesignal/relay/1.0.0";
36
+ })(Protocols || (exports.Protocols = Protocols = {}));
37
+ (function (Protocols) {
38
+ function isProtocol(protocol) {
39
+ return Object.values(Protocols).includes(protocol);
40
+ }
41
+ Protocols.isProtocol = isProtocol;
42
+ function fromCode(code) {
43
+ return Object.values(Protocols)[code];
44
+ }
45
+ Protocols.fromCode = fromCode;
46
+ function toCode(protocol) {
47
+ return Object.values(Protocols).indexOf(protocol);
48
+ }
49
+ Protocols.toCode = toCode;
50
+ function encode(protocol, length) {
51
+ /*const raw = numberToUint8Array(Protocols.toCode(protocol), length).reverse();
52
+ raw[0] |= (raw.length - 1) << 6;
53
+ return raw;*/
54
+ return (0, utils_1.numberToUint8Array)(Protocols.toCode(protocol), length);
55
+ }
56
+ Protocols.encode = encode;
57
+ function decode(array) {
58
+ //array[0] &= 63;
59
+ //array = array.reverse();
60
+ return Protocols.fromCode((0, utils_1.numberFromUint8Array)(array));
61
+ }
62
+ Protocols.decode = decode;
63
+ })(Protocols || (exports.Protocols = Protocols = {}));
64
+ var Crypto;
65
+ (function (Crypto) {
66
+ })(Crypto || (exports.Crypto = Crypto = {}));
package/x3dh.d.ts CHANGED
@@ -16,8 +16,7 @@
16
16
  * You should have received a copy of the GNU General Public License
17
17
  * along with this program. If not, see <https://www.gnu.org/licenses/>
18
18
  */
19
- import crypto from "./crypto";
20
- import { KeyExchangeData, KeyExchangeDataBundle, KeyExchangeSynMessage, LocalStorage } from "./types";
19
+ import { KeyExchangeData, KeyExchangeDataBundle, KeyExchangeSynMessage, LocalStorage, Crypto } from "./types";
21
20
  import { KeySession } from "./double-ratchet";
22
21
  export declare class KeyExchange {
23
22
  static readonly version = 1;
@@ -26,7 +25,7 @@ export declare class KeyExchange {
26
25
  private readonly _signatureKey;
27
26
  private readonly _identityKey;
28
27
  private readonly bundleStore;
29
- constructor(signSecretKey: Uint8Array, boxSecretKey: Uint8Array, bundleStore?: LocalStorage<string, crypto.KeyPair>);
28
+ constructor(signSecretKey: Uint8Array, boxSecretKey: Uint8Array, bundleStore?: LocalStorage<string, Crypto.KeyPair>);
30
29
  get signatureKey(): Uint8Array;
31
30
  get identityKey(): Uint8Array;
32
31
  private generateSPK;
package/x3dh.js CHANGED
@@ -88,10 +88,10 @@ class KeyExchange {
88
88
  const signedPreKeyHash = crypto_1.default.hash(signedPreKey);
89
89
  const onetimePreKeyHash = onetimePreKey ? crypto_1.default.hash(onetimePreKey) : new Uint8Array();
90
90
  const rootKey = crypto_1.default.hkdf(new Uint8Array([
91
- ...crypto_1.default.scalarMult(this._identityKey.secretKey, signedPreKey),
92
- ...crypto_1.default.scalarMult(ephemeralKey.secretKey, identityKey),
93
- ...crypto_1.default.scalarMult(ephemeralKey.secretKey, signedPreKey),
94
- ...onetimePreKey ? crypto_1.default.scalarMult(ephemeralKey.secretKey, onetimePreKey) : new Uint8Array()
91
+ ...crypto_1.default.ECDH.scalarMult(this._identityKey.secretKey, signedPreKey),
92
+ ...crypto_1.default.ECDH.scalarMult(ephemeralKey.secretKey, identityKey),
93
+ ...crypto_1.default.ECDH.scalarMult(ephemeralKey.secretKey, signedPreKey),
94
+ ...onetimePreKey ? crypto_1.default.ECDH.scalarMult(ephemeralKey.secretKey, onetimePreKey) : new Uint8Array()
95
95
  ]), new Uint8Array(double_ratchet_1.KeySession.rootKeyLength).fill(0), KeyExchange.hkdfInfo, double_ratchet_1.KeySession.rootKeyLength);
96
96
  const session = new double_ratchet_1.KeySession({ remoteKey: identityKey, rootKey });
97
97
  const cyphertext = session.encrypt((0, utils_1.concatUint8Array)(crypto_1.default.hash(this._identityKey.publicKey), crypto_1.default.hash(identityKey)));
@@ -122,10 +122,10 @@ class KeyExchange {
122
122
  const identityKey = (0, utils_1.decodeBase64)(message.identityKey);
123
123
  const ephemeralKey = (0, utils_1.decodeBase64)(message.ephemeralKey);
124
124
  const rootKey = crypto_1.default.hkdf(new Uint8Array([
125
- ...crypto_1.default.scalarMult(signedPreKey.secretKey, identityKey),
126
- ...crypto_1.default.scalarMult(this._identityKey.secretKey, ephemeralKey),
127
- ...crypto_1.default.scalarMult(signedPreKey.secretKey, ephemeralKey),
128
- ...onetimePreKey ? crypto_1.default.scalarMult(onetimePreKey.secretKey, ephemeralKey) : new Uint8Array()
125
+ ...crypto_1.default.ECDH.scalarMult(signedPreKey.secretKey, identityKey),
126
+ ...crypto_1.default.ECDH.scalarMult(this._identityKey.secretKey, ephemeralKey),
127
+ ...crypto_1.default.ECDH.scalarMult(signedPreKey.secretKey, ephemeralKey),
128
+ ...onetimePreKey ? crypto_1.default.ECDH.scalarMult(onetimePreKey.secretKey, ephemeralKey) : new Uint8Array()
129
129
  ]), new Uint8Array(double_ratchet_1.KeySession.rootKeyLength).fill(0), KeyExchange.hkdfInfo, double_ratchet_1.KeySession.rootKeyLength);
130
130
  const session = new double_ratchet_1.KeySession({ secretKey: this._identityKey.secretKey, rootKey });
131
131
  const cleartext = session.decrypt((0, utils_1.decodeBase64)(message.associatedData));