@freesignal/protocol 0.2.1 → 0.2.2

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/api.d.ts CHANGED
@@ -2,6 +2,8 @@ import { Crypto, LocalStorage } from "@freesignal/interfaces";
2
2
  import { KeySession } from "./double-ratchet";
3
3
  import { KeyExchange } from "./x3dh";
4
4
  import { Datagram, IdentityKeys, EncryptedData, UserId } from "./types";
5
+ export declare const FREESIGNAL_MIME = "application/x-freesignal";
6
+ type DatagramId = string;
5
7
  export declare class FreeSignalAPI {
6
8
  protected readonly signKey: Crypto.KeyPair;
7
9
  protected readonly boxKey: Crypto.KeyPair;
@@ -16,25 +18,21 @@ export declare class FreeSignalAPI {
16
18
  users: LocalStorage<UserId, IdentityKeys>;
17
19
  });
18
20
  get userId(): Uint8Array;
21
+ get identityKeys(): IdentityKeys;
19
22
  encryptData(data: Uint8Array, userId: string): Promise<EncryptedData>;
20
23
  decryptData(data: Uint8Array, userId: string): Promise<Uint8Array>;
24
+ getDatagrams(publicKey: string | Uint8Array, url: string): Promise<Datagram[]>;
25
+ postDatagrams(datagrams: Datagram[], publicKey: string | Uint8Array, url: string): Promise<number>;
26
+ deleteDatagrams(datagramIds: DatagramId[], publicKey: string | Uint8Array, url: string): Promise<number>;
27
+ createToken(publicKey: Uint8Array): string;
21
28
  protected digestToken(auth?: string): Promise<{
22
29
  identityKeys: IdentityKeys;
23
30
  userId: UserId;
24
31
  }>;
25
- createToken(publicKey: Uint8Array): string;
32
+ protected packIdList(datagramIds: DatagramId[]): Uint8Array;
33
+ protected unpackIdList(data: Uint8Array): DatagramId[];
26
34
  protected packDatagrams(messages: Datagram[]): Uint8Array;
27
35
  protected unpackDatagrams(data: Uint8Array): Datagram[];
28
- get identityKeys(): {
29
- readonly publicKey: string;
30
- readonly identityKey: string;
31
- encode(): Uint8Array;
32
- toString(): string;
33
- toJSON(): string;
34
- };
35
- static createSecretIdentityKeys(): {
36
- secretSignKey: Uint8Array;
37
- secretBoxKey: Uint8Array;
38
- };
39
36
  static getUserId(publicKey: string | Uint8Array): string;
40
37
  }
38
+ export {};
package/api.js CHANGED
@@ -12,12 +12,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.FreeSignalAPI = void 0;
15
+ exports.FreeSignalAPI = exports.FREESIGNAL_MIME = void 0;
16
16
  const crypto_1 = __importDefault(require("@freesignal/crypto"));
17
17
  const x3dh_1 = require("./x3dh");
18
18
  const utils_1 = require("@freesignal/utils");
19
19
  const types_1 = require("./types");
20
20
  const fflate_1 = __importDefault(require("fflate"));
21
+ exports.FREESIGNAL_MIME = "application/x-freesignal";
21
22
  class FreeSignalAPI {
22
23
  constructor(opts) {
23
24
  const { secretSignKey, secretBoxKey, sessions, keyExchange, users } = opts;
@@ -30,6 +31,12 @@ class FreeSignalAPI {
30
31
  get userId() {
31
32
  return crypto_1.default.hash(this.signKey.publicKey);
32
33
  }
34
+ get identityKeys() {
35
+ return {
36
+ publicKey: (0, utils_1.encodeBase64)(this.signKey.publicKey),
37
+ identityKey: (0, utils_1.encodeBase64)(this.boxKey.publicKey)
38
+ };
39
+ }
33
40
  encryptData(data, userId) {
34
41
  return __awaiter(this, void 0, void 0, function* () {
35
42
  const session = yield this.sessions.get(userId);
@@ -52,6 +59,50 @@ class FreeSignalAPI {
52
59
  return decrypted;
53
60
  });
54
61
  }
62
+ getDatagrams(publicKey, url) {
63
+ return __awaiter(this, void 0, void 0, function* () {
64
+ const res = yield fetch(url, {
65
+ method: 'GET',
66
+ headers: {
67
+ authorization: this.createToken(publicKey instanceof Uint8Array ? publicKey : (0, utils_1.decodeBase64)(publicKey))
68
+ }
69
+ });
70
+ return this.unpackDatagrams(yield this.decryptData(new Uint8Array(yield res.arrayBuffer()), FreeSignalAPI.getUserId(publicKey)));
71
+ });
72
+ }
73
+ postDatagrams(datagrams, publicKey, url) {
74
+ return __awaiter(this, void 0, void 0, function* () {
75
+ const data = yield this.encryptData(this.packDatagrams(datagrams), FreeSignalAPI.getUserId(publicKey));
76
+ const res = yield fetch(url, {
77
+ method: 'POST',
78
+ headers: {
79
+ 'Content-Type': exports.FREESIGNAL_MIME,
80
+ authorization: this.createToken(publicKey instanceof Uint8Array ? publicKey : (0, utils_1.decodeBase64)(publicKey))
81
+ },
82
+ body: data.encode()
83
+ });
84
+ return (0, utils_1.numberFromUint8Array)(yield this.decryptData(new Uint8Array(yield res.arrayBuffer()), FreeSignalAPI.getUserId(publicKey)));
85
+ });
86
+ }
87
+ deleteDatagrams(datagramIds, publicKey, url) {
88
+ return __awaiter(this, void 0, void 0, function* () {
89
+ const data = yield this.encryptData(this.packIdList(datagramIds), FreeSignalAPI.getUserId(publicKey));
90
+ const res = yield fetch(url, {
91
+ method: 'DELETE',
92
+ headers: {
93
+ 'Content-Type': exports.FREESIGNAL_MIME,
94
+ authorization: this.createToken(publicKey instanceof Uint8Array ? publicKey : (0, utils_1.decodeBase64)(publicKey))
95
+ },
96
+ body: data.encode()
97
+ });
98
+ return (0, utils_1.numberFromUint8Array)(yield this.decryptData(new Uint8Array(yield res.arrayBuffer()), FreeSignalAPI.getUserId(publicKey)));
99
+ });
100
+ }
101
+ createToken(publicKey) {
102
+ const sharedId = crypto_1.default.hash(crypto_1.default.ECDH.scalarMult(publicKey, this.boxKey.secretKey));
103
+ return `Bearer ${(0, utils_1.encodeBase64)(this.userId)}:${(0, utils_1.encodeBase64)(sharedId)}`;
104
+ }
105
+ ;
55
106
  digestToken(auth) {
56
107
  return __awaiter(this, void 0, void 0, function* () {
57
108
  if (auth && auth.startsWith("Bearer ")) {
@@ -67,11 +118,16 @@ class FreeSignalAPI {
67
118
  throw new Error('Authorization header is required');
68
119
  });
69
120
  }
70
- createToken(publicKey) {
71
- const sharedId = crypto_1.default.hash(crypto_1.default.ECDH.scalarMult(publicKey, this.boxKey.secretKey));
72
- return `Bearer ${(0, utils_1.encodeBase64)(this.userId)}:${(0, utils_1.encodeBase64)(sharedId)}`;
121
+ packIdList(datagramIds) {
122
+ return datagramIds.map(datagramId => crypto_1.default.UUID.parse(datagramId)).reduce((prev, curr) => new Uint8Array([...prev, ...curr]), new Uint8Array());
123
+ }
124
+ unpackIdList(data) {
125
+ const ids = [];
126
+ for (let i = 0; i < data.length; i += 16) {
127
+ ids.push(crypto_1.default.UUID.stringify(data.subarray(i, i + 16)));
128
+ }
129
+ return ids;
73
130
  }
74
- ;
75
131
  packDatagrams(messages) {
76
132
  return fflate_1.default.deflateSync((0, utils_1.concatUint8Array)(...messages.flatMap(datagram => {
77
133
  const encoded = types_1.Datagram.from(datagram).encode();
@@ -104,18 +160,6 @@ class FreeSignalAPI {
104
160
  }
105
161
  return messages;
106
162
  }
107
- get identityKeys() {
108
- return types_1.IdentityKeys.from({
109
- publicKey: (0, utils_1.encodeBase64)(this.signKey.publicKey),
110
- identityKey: (0, utils_1.encodeBase64)(this.boxKey.publicKey)
111
- });
112
- }
113
- static createSecretIdentityKeys() {
114
- return {
115
- secretSignKey: crypto_1.default.EdDSA.keyPair().secretKey,
116
- secretBoxKey: crypto_1.default.ECDH.keyPair().secretKey
117
- };
118
- }
119
163
  static getUserId(publicKey) {
120
164
  return (0, utils_1.encodeBase64)(crypto_1.default.hash(publicKey instanceof Uint8Array ? publicKey : (0, utils_1.decodeBase64)(publicKey)));
121
165
  }
package/index.d.ts CHANGED
@@ -20,8 +20,6 @@ import crypto from "@freesignal/crypto";
20
20
  import { LocalStorage, Crypto } from "@freesignal/interfaces";
21
21
  import { KeySession } from "./double-ratchet";
22
22
  import { KeyExchange } from "./x3dh";
23
- import { IdentityKeys, UserId } from "./types";
24
- import { FreeSignalAPI } from "./api";
25
23
  /**
26
24
  * Creates a new Double Ratchet session.
27
25
  *
@@ -43,11 +41,8 @@ export declare function createKeySession(opts?: {
43
41
  * @returns A new X3DH session.
44
42
  */
45
43
  export declare function createKeyExchange(signSecretKey: Uint8Array, boxSecretKey: Uint8Array, bundleStore?: LocalStorage<string, crypto.KeyPair>): KeyExchange;
46
- export declare function createAPI(opts: {
47
- secretSignKey: Uint8Array;
48
- secretBoxKey: Uint8Array;
49
- sessions: LocalStorage<UserId, KeySession>;
50
- keyExchange: LocalStorage<string, Crypto.KeyPair>;
51
- users: LocalStorage<UserId, IdentityKeys>;
52
- }): FreeSignalAPI;
44
+ export declare function createIdentityKeys(signSecretKey?: Uint8Array, boxSecretKey?: Uint8Array): {
45
+ sign: Crypto.KeyPair;
46
+ box: Crypto.KeyPair;
47
+ };
53
48
  export { IdentityKeys, Protocols, EncryptedData, Datagram } from "./types";
package/index.js CHANGED
@@ -17,14 +17,17 @@
17
17
  * You should have received a copy of the GNU General Public License
18
18
  * along with this program. If not, see <https://www.gnu.org/licenses/>
19
19
  */
20
+ var __importDefault = (this && this.__importDefault) || function (mod) {
21
+ return (mod && mod.__esModule) ? mod : { "default": mod };
22
+ };
20
23
  Object.defineProperty(exports, "__esModule", { value: true });
21
24
  exports.Datagram = exports.EncryptedData = exports.Protocols = exports.IdentityKeys = void 0;
22
25
  exports.createKeySession = createKeySession;
23
26
  exports.createKeyExchange = createKeyExchange;
24
- exports.createAPI = createAPI;
27
+ exports.createIdentityKeys = createIdentityKeys;
28
+ const crypto_1 = __importDefault(require("@freesignal/crypto"));
25
29
  const double_ratchet_1 = require("./double-ratchet");
26
30
  const x3dh_1 = require("./x3dh");
27
- const api_1 = require("./api");
28
31
  /**
29
32
  * Creates a new Double Ratchet session.
30
33
  *
@@ -46,9 +49,21 @@ function createKeySession(opts) {
46
49
  function createKeyExchange(signSecretKey, boxSecretKey, bundleStore) {
47
50
  return new x3dh_1.KeyExchange(signSecretKey, boxSecretKey, bundleStore);
48
51
  }
49
- function createAPI(opts) {
50
- return new api_1.FreeSignalAPI(opts);
52
+ function createIdentityKeys(signSecretKey, boxSecretKey) {
53
+ return {
54
+ sign: crypto_1.default.EdDSA.keyPair(signSecretKey),
55
+ box: crypto_1.default.ECDH.keyPair(boxSecretKey)
56
+ };
51
57
  }
58
+ /*export function createAPI(opts: {
59
+ secretSignKey: Uint8Array;
60
+ secretBoxKey: Uint8Array;
61
+ sessions: LocalStorage<UserId, KeySession>;
62
+ keyExchange: LocalStorage<string, Crypto.KeyPair>;
63
+ users: LocalStorage<UserId, IdentityKeys>;
64
+ }): FreeSignalAPI {
65
+ return new FreeSignalAPI(opts);
66
+ }*/
52
67
  var types_1 = require("./types");
53
68
  Object.defineProperty(exports, "IdentityKeys", { enumerable: true, get: function () { return types_1.IdentityKeys; } });
54
69
  Object.defineProperty(exports, "Protocols", { enumerable: true, get: function () { return types_1.Protocols; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@freesignal/protocol",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Signal Protocol implementation in javascript",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "author": "Christian Braghette",