orgnote-api 0.14.1 → 0.15.0

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.ts CHANGED
@@ -103,7 +103,11 @@ export interface OrgNoteConfig {
103
103
  language: string;
104
104
  };
105
105
  synchronization: {
106
- type: 'none' | 'api' | 'filesystem';
106
+ type: 'none' | 'api';
107
+ };
108
+ vault: {
109
+ /* File system available only for mobile devices */
110
+ type: 'inmemory' | 'filesystem';
107
111
  path?: string;
108
112
  };
109
113
  ui: {
@@ -4,7 +4,6 @@ exports[`Should decrypt note content via password 1`] = `
4
4
  [
5
5
  {
6
6
  "encrypted": false,
7
- "encryptionType": "gpgPassword",
8
7
  "id": "id",
9
8
  "meta": {
10
9
  "headings": [
@@ -28,7 +27,6 @@ exports[`Should decrypt note via provided keys 1`] = `
28
27
  [
29
28
  {
30
29
  "encrypted": false,
31
- "encryptionType": "gpgKeys",
32
30
  "id": "id",
33
31
  "meta": {
34
32
  "headings": [
@@ -48,6 +46,22 @@ exports[`Should decrypt note via provided keys 1`] = `
48
46
  ]
49
47
  `;
50
48
 
49
+ exports[`Should encrypt note and decrypt it into binary format 1`] = `
50
+ {
51
+ "author": {
52
+ "email": "test@mail.com",
53
+ "id": "1",
54
+ "name": "John Doe",
55
+ },
56
+ "encrypted": true,
57
+ "id": "id",
58
+ "meta": {
59
+ "id": undefined,
60
+ "published": false,
61
+ },
62
+ }
63
+ `;
64
+
51
65
  exports[`Should encrypt note content via password 1`] = `
52
66
  {
53
67
  "author": {
@@ -56,7 +70,38 @@ exports[`Should encrypt note content via password 1`] = `
56
70
  "name": "John Doe",
57
71
  },
58
72
  "encrypted": true,
59
- "encryptionType": "gpgPassword",
73
+ "id": "id",
74
+ "meta": {
75
+ "id": undefined,
76
+ "published": false,
77
+ },
78
+ }
79
+ `;
80
+
81
+ exports[`Should encrypt note content via password to binary format 1`] = `
82
+ {
83
+ "author": {
84
+ "email": "test@mail.com",
85
+ "id": "1",
86
+ "name": "John Doe",
87
+ },
88
+ "encrypted": true,
89
+ "id": "id",
90
+ "meta": {
91
+ "id": undefined,
92
+ "published": false,
93
+ },
94
+ }
95
+ `;
96
+
97
+ exports[`Should encrypt note to binary format 1`] = `
98
+ {
99
+ "author": {
100
+ "email": "test@mail.com",
101
+ "id": "1",
102
+ "name": "John Doe",
103
+ },
104
+ "encrypted": true,
60
105
  "id": "id",
61
106
  "meta": {
62
107
  "id": undefined,
@@ -73,7 +118,6 @@ exports[`Should encrypt note via keys 1`] = `
73
118
  "name": "John Doe",
74
119
  },
75
120
  "encrypted": true,
76
- "encryptionType": "gpgKeys",
77
121
  "id": "id",
78
122
  "meta": {
79
123
  "id": undefined,
@@ -130,7 +174,6 @@ exports[`Should not encrypt public note 1`] = `
130
174
  "name": "John Doe",
131
175
  },
132
176
  "encrypted": false,
133
- "encryptionType": "gpgPassword",
134
177
  "id": "id",
135
178
  "meta": {
136
179
  "description": "Awesome description",
@@ -145,7 +188,6 @@ exports[`Should set not encrypted status when params type does not provided 1`]
145
188
  [
146
189
  {
147
190
  "encrypted": true,
148
- "encryptionType": "gpgKeys",
149
191
  "id": "id",
150
192
  "meta": {
151
193
  "description": "Awesome description",
@@ -8,6 +8,7 @@ import {
8
8
  IncorrectOrMissingPrivateKeyPasswordError,
9
9
  encrypt,
10
10
  decrypt,
11
+ _encryptViaKeys,
11
12
  } from '../encryption';
12
13
  import { test, expect } from 'vitest';
13
14
 
@@ -16,21 +17,35 @@ import {
16
17
  armoredPrivateKey,
17
18
  privateKeyPassphrase,
18
19
  } from './encryption-keys';
20
+ // import { armor } from 'openpgp';
21
+
22
+ test('Should encrypt text as armored message via keys', async () => {
23
+ const res = await encryptViaKeys({
24
+ content: 'Hello world',
25
+ publicKey: armoredPublicKey,
26
+ privateKey: armoredPrivateKey,
27
+ privateKeyPassphrase: privateKeyPassphrase,
28
+ format: 'armored',
29
+ });
30
+
31
+ expect(res.startsWith('-----BEGIN PGP MESSAGE-----')).toBeTruthy();
32
+ });
19
33
 
20
34
  test('Should encrypt text via keys', async () => {
21
- const res = await encryptViaKeys(
22
- 'Hello world',
23
- armoredPublicKey,
24
- armoredPrivateKey,
25
- privateKeyPassphrase
26
- );
35
+ const res = await encryptViaKeys({
36
+ content: 'Hello world',
37
+ publicKey: armoredPublicKey,
38
+ privateKey: armoredPrivateKey,
39
+ privateKeyPassphrase,
40
+ format: 'armored',
41
+ });
27
42
 
28
43
  expect(res.startsWith('-----BEGIN PGP MESSAGE-----')).toBeTruthy();
29
44
  });
30
45
 
31
46
  test('Should decrypt via provided keys', async () => {
32
- const decryptedMessage = await decryptViaKeys(
33
- `-----BEGIN PGP MESSAGE-----
47
+ const decryptedMessage = await decryptViaKeys({
48
+ content: `-----BEGIN PGP MESSAGE-----
34
49
 
35
50
  wcFMA/vryg+TTn0rARAAhXuEjOHa856iCNVmdeIGHF+IEoeEwTc5tIcr6Lri
36
51
  V6xs//3WnwVwUlyxYrum3yCpx8t5gyWTXFfTNH08VoVqPVP45fkk1H7jdC6Q
@@ -62,15 +77,19 @@ YQ==
62
77
  =f4F1
63
78
  -----END PGP MESSAGE-----
64
79
  `,
65
- armoredPrivateKey,
66
- privateKeyPassphrase
67
- );
80
+ privateKey: armoredPrivateKey,
81
+ privateKeyPassphrase,
82
+ });
68
83
  expect(decryptedMessage).toEqual('Hello world');
69
84
  });
70
85
 
71
86
  test('Should encrypt via password', async () => {
72
87
  const password = 'test';
73
- const res = await encryptViaPassword('Hello world', password);
88
+ const res = await encryptViaPassword({
89
+ content: 'Hello world',
90
+ password,
91
+ format: 'armored',
92
+ });
74
93
 
75
94
  expect(res.startsWith('-----BEGIN PGP MESSAGE-----')).toBeTruthy();
76
95
  });
@@ -86,7 +105,7 @@ aGW80jwBXEQ7uTjT8akpOKiH7BIuhEUZIXh+vDveG0Uwf63s2dIklznAEo+E
86
105
  -----END PGP MESSAGE-----
87
106
  `;
88
107
 
89
- expect(await decryptViaPassword(encryptedMsg, password)).toEqual(
108
+ expect(await decryptViaPassword({ content: encryptedMsg, password })).toEqual(
90
109
  'Hello world'
91
110
  );
92
111
  });
@@ -125,14 +144,13 @@ YQ==
125
144
  -----END PGP MESSAGE-----`;
126
145
 
127
146
  try {
128
- await decryptViaPassword(encryptedMsg, 'password');
147
+ await decryptViaPassword({ content: encryptedMsg, password: 'password' });
129
148
  } catch (e) {
130
149
  expect(e).toBeInstanceOf(NoKeysProvidedError);
131
150
  }
132
151
  });
133
152
 
134
153
  test('Should raise IncorrectOrMissingPrivateKeyPasswordError error when incorrect armored key provided', async () => {
135
- const password = 'test';
136
154
  const encryptedMsg = `-----BEGIN PGP MESSAGE-----
137
155
 
138
156
  wy4ECQMI6KFWGqyVV+DgYl0qUEeTe1kAdjkoR4FxFJxx+6QiOP+sZ6h7bn//
@@ -143,7 +161,11 @@ aGW80jwBXEQ7uTjT8akpOKiH7BIuhEUZIXh+vDveG0Uwf63s2dIklznAEo+E
143
161
  `;
144
162
 
145
163
  try {
146
- await decryptViaKeys(encryptedMsg, armoredPublicKey, privateKeyPassphrase);
164
+ await decryptViaKeys({
165
+ content: encryptedMsg,
166
+ publicKey: armoredPublicKey,
167
+ privateKey: privateKeyPassphrase,
168
+ });
147
169
  } catch (e) {
148
170
  expect(e).toBeInstanceOf(IncorrectOrMissingPrivateKeyPasswordError);
149
171
  }
@@ -160,7 +182,11 @@ aGW80jwBXEQ7uTjT8akpOKiH7BIuhEUZIXh+vDveG0Uwf63s2dIklznAEo+E
160
182
  `;
161
183
 
162
184
  try {
163
- await decryptViaKeys(encryptedMsg, armoredPrivateKey, privateKeyPassphrase);
185
+ await decryptViaKeys({
186
+ content: encryptedMsg,
187
+ privateKey: armoredPrivateKey,
188
+ privateKeyPassphrase,
189
+ });
164
190
  } catch (e) {
165
191
  expect(e).toBeInstanceOf(NoPasswordProvidedError);
166
192
  }
@@ -170,14 +196,17 @@ test('Should encrypt and decrypt text by provided configs via password', async (
170
196
  const text = 'Hello world';
171
197
  const password = '123';
172
198
 
173
- const res = await encrypt(text, {
199
+ const res = await encrypt({
200
+ content: text,
174
201
  type: 'gpgPassword',
175
202
  password,
203
+ format: 'armored',
176
204
  });
177
205
 
178
206
  expect(res.startsWith('-----BEGIN PGP MESSAGE-----')).toBeTruthy();
179
207
 
180
- const decryptedMessage = await decrypt(res, {
208
+ const decryptedMessage = await decrypt({
209
+ content: res,
181
210
  type: 'gpgPassword',
182
211
  password,
183
212
  });
@@ -187,8 +216,10 @@ test('Should encrypt and decrypt text by provided configs via password', async (
187
216
 
188
217
  test('Should encrypt and decrypt text by provided configs via keys', async () => {
189
218
  const text = 'Hello world';
190
- const res = await encrypt(text, {
219
+ const res = await encrypt({
220
+ content: text,
191
221
  type: 'gpgKeys',
222
+ format: 'armored',
192
223
  publicKey: armoredPublicKey,
193
224
  privateKey: armoredPrivateKey,
194
225
  privateKeyPassphrase,
@@ -196,12 +227,82 @@ test('Should encrypt and decrypt text by provided configs via keys', async () =>
196
227
 
197
228
  expect(res.startsWith('-----BEGIN PGP MESSAGE-----')).toBeTruthy();
198
229
 
199
- const decryptedMessage = await decrypt(res, {
230
+ const decryptedMessage = await decrypt({
231
+ content: res,
200
232
  type: 'gpgKeys',
201
233
  publicKey: armoredPublicKey,
202
234
  privateKey: armoredPrivateKey,
203
235
  privateKeyPassphrase,
236
+ format: 'utf8',
237
+ });
238
+
239
+ expect(decryptedMessage).toEqual(text);
240
+ });
241
+
242
+ test('Should encrypt to binary and decrypt to format armored!', async () => {
243
+ const text = 'Hello world';
244
+
245
+ const res = await encrypt({
246
+ content: text,
247
+ type: 'gpgPassword',
248
+ password: '123',
249
+ format: 'binary',
250
+ });
251
+
252
+ expect(res).toBeInstanceOf(Uint8Array);
253
+
254
+ const decryptedMessage = await decrypt({
255
+ content: res,
256
+ type: 'gpgPassword',
257
+ format: 'utf8',
258
+ password: '123',
204
259
  });
205
260
 
206
261
  expect(decryptedMessage).toEqual(text);
207
262
  });
263
+
264
+ test('Should encrypt to binary and decrypt to binary format', async () => {
265
+ const text = 'Hello world';
266
+
267
+ const res = await encrypt({
268
+ content: text,
269
+ type: 'gpgPassword',
270
+ password: '123',
271
+ format: 'binary',
272
+ });
273
+
274
+ expect(res).toBeInstanceOf(Uint8Array);
275
+
276
+ const decryptedMessage = await decrypt({
277
+ content: res,
278
+ type: 'gpgPassword',
279
+ format: 'binary',
280
+ password: '123',
281
+ });
282
+
283
+ expect(decryptedMessage.toString()).toMatchInlineSnapshot(
284
+ `"72,101,108,108,111,32,119,111,114,108,100"`
285
+ );
286
+ });
287
+
288
+ test('Should encrypt to armored text and decrypt as binary format', async () => {
289
+ const text = 'Hello world';
290
+
291
+ const res = await encrypt({
292
+ content: text,
293
+ type: 'gpgPassword',
294
+ password: '123',
295
+ format: 'armored',
296
+ });
297
+
298
+ expect(res).toBeTypeOf('string');
299
+
300
+ const decryptedMessage = await decrypt({
301
+ content: res,
302
+ type: 'gpgPassword',
303
+ format: 'binary',
304
+ password: '123',
305
+ });
306
+
307
+ expect(decryptedMessage).toBeInstanceOf(Uint8Array);
308
+ });
@@ -17,7 +17,6 @@ test('Should encrypt note content via password', async () => {
17
17
 
18
18
  const note: Note = {
19
19
  id: 'id',
20
- encryptionType: 'gpgPassword',
21
20
  meta: {
22
21
  title: 'My note title',
23
22
  images: [],
@@ -31,9 +30,11 @@ test('Should encrypt note content via password', async () => {
31
30
  },
32
31
  };
33
32
 
34
- const [encryptedNote, encryptedNoteText] = await encryptNote(note, noteText, {
33
+ const [encryptedNote, encryptedNoteText] = await encryptNote(note, {
34
+ content: noteText,
35
35
  type: 'gpgPassword',
36
36
  password: '123',
37
+ format: 'armored',
37
38
  });
38
39
 
39
40
  expect(encryptedNoteText.startsWith('-----BEGIN PGP MESSAGE-----')).toBe(
@@ -42,6 +43,39 @@ test('Should encrypt note content via password', async () => {
42
43
  expect(encryptedNote).toMatchSnapshot();
43
44
  });
44
45
 
46
+ test('Should encrypt note content via password to binary format', async () => {
47
+ const noteText = `#+ID: qweqwe
48
+
49
+ #+TITLE: Hello worlld
50
+
51
+ * Hello?`;
52
+
53
+ const note: Note = {
54
+ id: 'id',
55
+ meta: {
56
+ title: 'My note title',
57
+ images: [],
58
+ published: false,
59
+ description: 'Awesome description',
60
+ },
61
+ author: {
62
+ id: '1',
63
+ name: 'John Doe',
64
+ email: 'test@mail.com',
65
+ },
66
+ };
67
+
68
+ const [encryptedNote, encryptedNoteText] = await encryptNote(note, {
69
+ content: noteText,
70
+ type: 'gpgPassword',
71
+ password: '123',
72
+ format: 'binary',
73
+ });
74
+
75
+ expect(encryptedNote).toMatchSnapshot();
76
+ expect(encryptedNoteText).toBeInstanceOf(Uint8Array);
77
+ });
78
+
45
79
  test('Should decrypt note content via password', async () => {
46
80
  const noteText = `-----BEGIN PGP MESSAGE-----
47
81
 
@@ -51,9 +85,9 @@ zt3v0mABvaBJA7corlU8su21TpPApOs/+DMWpVlbI3Zer7QfQK1fSBoSTbCR
51
85
  5Bjlwt4ZhxFsh+c=
52
86
  =csID
53
87
  -----END PGP MESSAGE-----`;
88
+
54
89
  const note: Note = {
55
90
  id: 'id',
56
- encryptionType: 'gpgPassword',
57
91
  meta: {
58
92
  title: 'My note title',
59
93
  images: [],
@@ -62,7 +96,8 @@ zt3v0mABvaBJA7corlU8su21TpPApOs/+DMWpVlbI3Zer7QfQK1fSBoSTbCR
62
96
  },
63
97
  };
64
98
 
65
- const decryptedNote = await decryptNote(note, noteText, {
99
+ const decryptedNote = await decryptNote(note, {
100
+ content: noteText,
66
101
  type: 'gpgPassword',
67
102
  password: '123',
68
103
  });
@@ -70,7 +105,7 @@ zt3v0mABvaBJA7corlU8su21TpPApOs/+DMWpVlbI3Zer7QfQK1fSBoSTbCR
70
105
  expect(decryptedNote).toMatchSnapshot();
71
106
  });
72
107
 
73
- test.skip('Should encrypt note via keys', async () => {
108
+ test('Should encrypt note via keys', async () => {
74
109
  const noteText = `#+ID: qweqwe
75
110
  #+TITLE: Hello worlld
76
111
 
@@ -78,7 +113,6 @@ test.skip('Should encrypt note via keys', async () => {
78
113
 
79
114
  const note: Note = {
80
115
  id: 'id',
81
- encryptionType: 'gpgKeys',
82
116
  meta: {
83
117
  title: 'My note title for encryption via keys',
84
118
  images: [],
@@ -92,11 +126,13 @@ test.skip('Should encrypt note via keys', async () => {
92
126
  },
93
127
  };
94
128
 
95
- const [encryptedNote, encryptedNoteText] = await encryptNote(note, noteText, {
129
+ const [encryptedNote, encryptedNoteText] = await encryptNote(note, {
130
+ content: noteText,
96
131
  type: ModelsPublicNoteEncryptionTypeEnum.GpgKeys,
97
132
  publicKey: armoredPublicKey,
98
133
  privateKey: armoredPrivateKey,
99
134
  privateKeyPassphrase,
135
+ format: 'armored',
100
136
  });
101
137
 
102
138
  expect(encryptedNoteText.startsWith('-----BEGIN PGP MESSAGE-----')).toBe(
@@ -140,7 +176,6 @@ yEN8xpFUs7A9xryVZOosp9Sfe3IbBkO99sAQ7jV4EoMYk3/GKA==
140
176
 
141
177
  const note: Note = {
142
178
  id: 'id',
143
- encryptionType: 'gpgKeys',
144
179
  meta: {
145
180
  title: 'My note title for decryption via keys',
146
181
  images: [],
@@ -149,7 +184,8 @@ yEN8xpFUs7A9xryVZOosp9Sfe3IbBkO99sAQ7jV4EoMYk3/GKA==
149
184
  },
150
185
  };
151
186
 
152
- const decryptedNote = await decryptNote(note, encryptedNoteText, {
187
+ const decryptedNote = await decryptNote(note, {
188
+ content: encryptedNoteText,
153
189
  type: 'gpgKeys',
154
190
  publicKey: armoredPublicKey,
155
191
  privateKey: armoredPrivateKey,
@@ -167,7 +203,6 @@ test('Should not encrypt public note', async () => {
167
203
 
168
204
  const note: Note = {
169
205
  id: 'id',
170
- encryptionType: 'gpgPassword',
171
206
  meta: {
172
207
  title: 'My note title',
173
208
  images: [],
@@ -181,9 +216,11 @@ test('Should not encrypt public note', async () => {
181
216
  },
182
217
  };
183
218
 
184
- const [encryptedNote, encryptedNoteText] = await encryptNote(note, noteText, {
219
+ const [encryptedNote, encryptedNoteText] = await encryptNote(note, {
220
+ content: noteText,
185
221
  type: 'gpgPassword',
186
222
  password: '123',
223
+ format: 'armored',
187
224
  });
188
225
 
189
226
  expect(encryptedNoteText.startsWith('-----BEGIN PGP MESSAGE-----')).toBe(
@@ -213,9 +250,11 @@ test('Should encrypt note with empty encrypted property', async () => {
213
250
  },
214
251
  };
215
252
 
216
- const [encryptedNote, encryptedNoteText] = await encryptNote(note, noteText, {
253
+ const [encryptedNote, encryptedNoteText] = await encryptNote(note, {
254
+ content: noteText,
217
255
  type: 'gpgPassword',
218
256
  password: '123',
257
+ format: 'armored',
219
258
  });
220
259
 
221
260
  expect(encryptedNoteText.startsWith('-----BEGIN PGP MESSAGE-----')).toBe(
@@ -246,9 +285,11 @@ test('Should not decrypt note without provided encrypted type', async () => {
246
285
  },
247
286
  };
248
287
 
249
- const decryptedInfo = await decryptNote(note, noteText, {
288
+ const decryptedInfo = await decryptNote(note, {
289
+ content: noteText,
250
290
  type: 'gpgPassword',
251
291
  password: '123',
292
+ format: 'armored',
252
293
  });
253
294
 
254
295
  expect(decryptedInfo).toMatchSnapshot();
@@ -265,7 +306,6 @@ test('Should decrypt note and note meta', async () => {
265
306
  const note: Note = {
266
307
  id: 'id',
267
308
  meta: { ...meta },
268
- encryptionType: 'gpgPassword',
269
309
  };
270
310
 
271
311
  const noteText = `#+TITLE: My note title
@@ -277,19 +317,17 @@ test('Should decrypt note and note meta', async () => {
277
317
 
278
318
  Hello world`;
279
319
 
280
- const [encryptedNote, encryptedNoteText] = await encryptNote(note, noteText, {
320
+ const [encryptedNote, encryptedNoteText] = await encryptNote(note, {
321
+ content: noteText,
281
322
  type: 'gpgPassword',
282
323
  password: '123',
283
324
  });
284
325
 
285
- const [decryptedNote, decryptedNoteText] = await decryptNote(
286
- encryptedNote,
287
- encryptedNoteText,
288
- {
289
- type: 'gpgPassword',
290
- password: '123',
291
- }
292
- );
326
+ const [decryptedNote, decryptedNoteText] = await decryptNote(encryptedNote, {
327
+ content: encryptedNoteText,
328
+ type: 'gpgPassword',
329
+ password: '123',
330
+ });
293
331
 
294
332
  expect(decryptedNote.meta).toEqual(meta);
295
333
  expect(decryptedNoteText).toEqual(noteText);
@@ -298,7 +336,6 @@ Hello world`;
298
336
  test('Should set not encrypted status when params type does not provided', async () => {
299
337
  const note: Note = {
300
338
  id: 'id',
301
- encryptionType: 'gpgKeys',
302
339
  meta: {
303
340
  title: 'My note title for decryption via keys',
304
341
  images: [],
@@ -339,9 +376,50 @@ yEN8xpFUs7A9xryVZOosp9Sfe3IbBkO99sAQ7jV4EoMYk3/GKA==
339
376
  =LjkG
340
377
  -----END PGP MESSAGE-----`;
341
378
 
342
- const decryptedNote = await decryptNote(note, noteText, {
379
+ const decryptedNote = await decryptNote(note, {
380
+ content: noteText,
343
381
  type: 'disabled',
344
382
  });
345
383
 
346
384
  expect(decryptedNote).toMatchSnapshot();
347
385
  });
386
+
387
+ test('Should encrypt note to binary format', async () => {
388
+ const noteText = `#+ID: qweqwe
389
+ #+TITLE: Hello worlld
390
+
391
+ * Hello?`;
392
+
393
+ const note: Note = {
394
+ id: 'id',
395
+ meta: {
396
+ title: 'My note title',
397
+ images: [],
398
+ published: false,
399
+ description: 'Awesome description',
400
+ },
401
+ author: {
402
+ id: '1',
403
+ name: 'John Doe',
404
+ email: 'test@mail.com',
405
+ },
406
+ };
407
+
408
+ const [encryptedNote, encryptedNoteText] = await encryptNote(note, {
409
+ content: noteText,
410
+ type: 'gpgPassword',
411
+ password: '123',
412
+ format: 'binary',
413
+ });
414
+
415
+ expect(encryptedNoteText).toBeInstanceOf(Uint8Array);
416
+ expect(encryptedNote).toMatchSnapshot();
417
+
418
+ const [_, decryptedNoteText] = await decryptNote(encryptedNote, {
419
+ content: encryptedNoteText,
420
+ type: 'gpgPassword',
421
+ password: '123',
422
+ });
423
+
424
+ expect(decryptedNoteText).toEqual(noteText);
425
+ });
@@ -8,7 +8,12 @@ import {
8
8
  readPrivateKey,
9
9
  } from 'openpgp';
10
10
  import { ModelsPublicNoteEncryptionTypeEnum } from '../remote-api';
11
- import { OrgNoteEncryption } from '../models/encryption';
11
+ import {
12
+ OrgNoteEncryption,
13
+ OrgNotePasswordEncryption,
14
+ WithDecryptionContent,
15
+ } from '../models/encryption';
16
+ import { OrgNoteGpgEncryption, WithEncryptionContent } from 'src/models';
12
17
 
13
18
  export class IncorrectOrMissingPrivateKeyPasswordError extends Error {}
14
19
  export class ImpossibleToDecryptWithProvidedKeysError extends Error {}
@@ -43,74 +48,84 @@ export const encryptViaPassword = withCustomErrors(_encryptViaPassword);
43
48
  export const decryptViaPassword = withCustomErrors(_decryptViaPassword);
44
49
  export const decryptViaKeys = withCustomErrors(_decryptViaKeys);
45
50
 
46
- export const encrypt = async (
47
- text: string,
48
- encryptionParams: OrgNoteEncryption
49
- ): Promise<string> => {
51
+ export const encrypt = async <
52
+ T extends WithEncryptionContent<OrgNoteEncryption>,
53
+ >(
54
+ encryptionParams: T
55
+ ): Promise<T['format'] extends 'binary' ? Uint8Array : string> => {
50
56
  if (
51
57
  !encryptionParams.type ||
52
58
  encryptionParams.type === ModelsPublicNoteEncryptionTypeEnum.Disabled
53
59
  ) {
54
- return text;
60
+ return encryptionParams.content as any;
55
61
  }
56
- return encryptionParams.type === ModelsPublicNoteEncryptionTypeEnum.GpgKeys
57
- ? await encryptViaKeys(
58
- text,
59
- encryptionParams.publicKey,
60
- encryptionParams.privateKey,
61
- encryptionParams.privateKeyPassphrase
62
- )
63
- : await encryptViaPassword(text, encryptionParams.password);
62
+
63
+ const res = (encryptionParams.type ===
64
+ ModelsPublicNoteEncryptionTypeEnum.GpgKeys
65
+ ? await encryptViaKeys(encryptionParams)
66
+ : await encryptViaPassword(encryptionParams)) as unknown as Promise<
67
+ T['format'] extends 'binary' ? Uint8Array : string
68
+ >;
69
+
70
+ return res;
64
71
  };
65
72
 
66
- export const decrypt = async (
67
- text: string,
68
- encryptionParams: OrgNoteEncryption
69
- ): Promise<string> => {
73
+ export const decrypt = async <
74
+ T extends WithDecryptionContent<OrgNoteEncryption>,
75
+ >(
76
+ decryptionParams: T
77
+ ): Promise<T['format'] extends 'binary' ? Uint8Array : string> => {
70
78
  if (
71
- !encryptionParams.type ||
72
- encryptionParams.type === ModelsPublicNoteEncryptionTypeEnum.Disabled
79
+ !decryptionParams.type ||
80
+ decryptionParams.type === ModelsPublicNoteEncryptionTypeEnum.Disabled
73
81
  ) {
74
- return text;
82
+ return decryptionParams.content as any;
75
83
  }
76
- const decryptedNote =
77
- encryptionParams.type === ModelsPublicNoteEncryptionTypeEnum.GpgKeys
78
- ? await decryptViaKeys(
79
- text,
80
- encryptionParams.privateKey,
81
- encryptionParams.privateKeyPassphrase
82
- )
83
- : await decryptViaPassword(text, encryptionParams.password);
84
+ const decryptedNote = (decryptionParams.type ===
85
+ ModelsPublicNoteEncryptionTypeEnum.GpgKeys
86
+ ? await decryptViaKeys(decryptionParams)
87
+ : await decryptViaPassword(decryptionParams)) as unknown as Promise<
88
+ T['format'] extends 'binary' ? Uint8Array : string
89
+ >;
90
+
84
91
  return decryptedNote;
85
92
  };
86
93
 
87
- async function _encryptViaPassword(
88
- text: string,
89
- password: string
90
- ): Promise<string> {
94
+ async function _encryptViaPassword<
95
+ T extends WithEncryptionContent<OrgNotePasswordEncryption>,
96
+ >({
97
+ content,
98
+ password,
99
+ format = 'binary',
100
+ }: T): Promise<T['format'] extends 'binary' ? Uint8Array : string> {
91
101
  const message = await createMessage({
92
- text,
102
+ text: content,
93
103
  });
94
104
 
95
105
  const encryptedMessage = await _encrypt({
96
106
  message,
97
- format: 'armored',
107
+ format: format as any,
98
108
  passwords: [password],
99
109
  });
100
110
 
101
- return encryptedMessage.toString();
111
+ return encryptedMessage as Promise<
112
+ T['format'] extends 'binary' ? Uint8Array : string
113
+ >;
102
114
  }
103
115
 
104
- async function _encryptViaKeys(
105
- text: string,
106
- armoredPublicKey: string,
107
- armoredPrivateKey: string,
108
- privateKeyPassphrase?: string
109
- ): Promise<string> {
116
+ export async function _encryptViaKeys<
117
+ T extends WithEncryptionContent<OrgNoteGpgEncryption>,
118
+ >({
119
+ content,
120
+ publicKey: armoredPublicKey,
121
+ privateKey: armoredPrivateKey,
122
+ privateKeyPassphrase,
123
+ format = 'binary',
124
+ }: T): Promise<T['format'] extends 'binary' ? Uint8Array : string> {
110
125
  const publicKey = await readKey({ armoredKey: armoredPublicKey });
111
126
 
112
127
  const message = await createMessage({
113
- text,
128
+ text: content,
114
129
  });
115
130
 
116
131
  const encryptedPrivateKey = await readPrivateKey({
@@ -126,52 +141,73 @@ async function _encryptViaKeys(
126
141
 
127
142
  const encryptedMessage = await _encrypt({
128
143
  message,
129
- format: 'armored',
144
+ format: format as any,
130
145
  encryptionKeys: publicKey,
131
146
  signingKeys: privateKey,
132
147
  });
133
148
 
134
- return encryptedMessage.toString();
149
+ return encryptedMessage as Promise<
150
+ T['format'] extends 'binary' ? Uint8Array : string
151
+ >;
135
152
  }
136
153
 
137
- async function _decryptViaPassword(
138
- data: string,
139
- password: string
140
- ): Promise<string> {
141
- const message = await readMessage({ armoredMessage: data });
154
+ async function _decryptViaPassword<
155
+ T extends Omit<WithDecryptionContent<OrgNotePasswordEncryption>, 'type'>,
156
+ >({
157
+ content,
158
+ password,
159
+ format = 'utf8',
160
+ }: T): Promise<T['format'] extends 'binary' ? Uint8Array : string> {
161
+ const isArmoredContent = typeof content === 'string';
162
+
163
+ const message = await (isArmoredContent
164
+ ? readMessage({ armoredMessage: content })
165
+ : readMessage({ binaryMessage: content }));
142
166
 
143
167
  const { data: decryptedText } = await _decrypt({
144
168
  message,
169
+ format,
145
170
  passwords: password,
146
171
  });
147
172
 
148
- return decryptedText.toString();
173
+ return decryptedText as Promise<
174
+ T['format'] extends 'binary' ? Uint8Array : string
175
+ >;
149
176
  }
150
177
 
151
- async function _decryptViaKeys(
152
- data: string,
153
- armoredPrivateKey: string,
154
- privateKeyPassword?: string
155
- ): Promise<string> {
178
+ async function _decryptViaKeys<
179
+ T extends Omit<WithDecryptionContent<OrgNoteGpgEncryption>, 'type'>,
180
+ >({
181
+ privateKey: armoredPrivateKey,
182
+ privateKeyPassphrase,
183
+ content,
184
+ format = 'utf8',
185
+ }: T): Promise<T['format'] extends 'binary' ? Uint8Array : string> {
156
186
  const encryptedPrivateKey = await readPrivateKey({
157
187
  armoredKey: armoredPrivateKey,
158
188
  });
159
189
 
160
- const privateKey = privateKeyPassword
190
+ const privateKey = privateKeyPassphrase
161
191
  ? await decryptKey({
162
192
  privateKey: encryptedPrivateKey,
163
- passphrase: privateKeyPassword,
193
+ passphrase: privateKeyPassphrase,
164
194
  })
165
195
  : encryptedPrivateKey;
166
196
 
167
- const message = await readMessage({ armoredMessage: data });
197
+ const isString = typeof content === 'string';
198
+ const message = await (isString
199
+ ? readMessage({ armoredMessage: content })
200
+ : readMessage({ binaryMessage: content }));
168
201
 
169
202
  const { data: decryptedText } = await _decrypt({
170
203
  message,
204
+ format,
171
205
  decryptionKeys: privateKey,
172
206
  });
173
207
 
174
- return decryptedText.toString();
208
+ return decryptedText as Promise<
209
+ T['format'] extends 'binary' ? Uint8Array : string
210
+ >;
175
211
  }
176
212
 
177
213
  function withCustomErrors<P extends unknown[], T>(
@@ -4,19 +4,23 @@ import {
4
4
  } from '../remote-api';
5
5
 
6
6
  import {
7
+ decrypt,
7
8
  decryptViaKeys,
8
9
  decryptViaPassword,
10
+ encrypt,
9
11
  encryptViaKeys,
10
12
  encryptViaPassword,
11
13
  } from './encryption';
12
- import { OrgNoteEncryption } from '../models/encryption';
14
+ import {
15
+ OrgNoteEncryption,
16
+ WithDecryptionContent,
17
+ WithEncryptionContent,
18
+ WithNoteDecryptionContent,
19
+ } from '../models/encryption';
13
20
  import { parse, withMetaInfo } from 'org-mode-ast';
14
21
  import { isGpgEncrypted } from '..';
15
22
 
16
- export type NoteEncryptionType = `${ModelsPublicNote['encryptionType']}`;
17
-
18
23
  export interface AbstractEncryptedNote {
19
- encryptionType?: NoteEncryptionType;
20
24
  encrypted?: boolean;
21
25
  meta: {
22
26
  [key: string]: any;
@@ -29,8 +33,7 @@ export type EncryptionResult<T> = Promise<[T, string]>;
29
33
  // TODO: master change signature for encrypt notes without content
30
34
  export async function encryptNote<T extends AbstractEncryptedNote>(
31
35
  note: T,
32
- noteText: string,
33
- encryptionParams: OrgNoteEncryption
36
+ encryptionParams: WithEncryptionContent<OrgNoteEncryption>
34
37
  ): EncryptionResult<T> {
35
38
  note.encrypted = false;
36
39
  if (
@@ -38,132 +41,47 @@ export async function encryptNote<T extends AbstractEncryptedNote>(
38
41
  encryptionParams.type === ModelsPublicNoteEncryptionTypeEnum.Disabled ||
39
42
  note.meta.published
40
43
  ) {
41
- return [note, noteText];
44
+ return [note, encryptionParams.content];
42
45
  }
43
46
 
44
47
  note.meta = { id: note.meta.id, published: note.meta.published };
45
48
 
46
- const [encryptedNote, encryptedNoteText] =
47
- encryptionParams.type === ModelsPublicNoteEncryptionTypeEnum.GpgKeys
48
- ? await encryptNoteViaKeys(
49
- note,
50
- encryptionParams.publicKey,
51
- encryptionParams.privateKey,
52
- encryptionParams.privateKeyPassphrase
53
- )
54
- : await encryptNoteViaPassword(note, noteText, encryptionParams.password);
49
+ const encryptedContent = await encrypt(encryptionParams);
55
50
 
56
- encryptedNote.encrypted = true;
57
- return [encryptedNote, encryptedNoteText];
58
- }
59
- export async function encryptNoteViaPassword<T extends AbstractEncryptedNote>(
60
- note: T,
61
- noteText: string,
62
- password: string
63
- ): Promise<[T, string]> {
64
- const encryptedNoteText = await encryptViaPassword(noteText, password);
65
- return [
66
- {
67
- ...note,
68
- encrypted: ModelsPublicNoteEncryptionTypeEnum.GpgPassword,
69
- },
70
- encryptedNoteText,
71
- ];
72
- }
51
+ const encryptedNote = { ...note, encrypted: true };
73
52
 
74
- export async function encryptNoteViaKeys<T extends AbstractEncryptedNote>(
75
- note: T,
76
- noteText: string,
77
- publicKey: string,
78
- privateKey: string,
79
- privateKeyPassphrase?: string
80
- ): Promise<[T, string]> {
81
- const encryptedNoteText = await encryptViaKeys(
82
- noteText,
83
- publicKey,
84
- privateKey,
85
- privateKeyPassphrase
86
- );
87
-
88
- return [
89
- {
90
- ...note,
91
- encrypted: ModelsPublicNoteEncryptionTypeEnum.GpgKeys,
92
- },
93
- encryptedNoteText,
94
- ];
53
+ return [encryptedNote, encryptedContent];
95
54
  }
96
55
 
97
56
  export async function decryptNote<T extends AbstractEncryptedNote>(
98
57
  note: T,
99
- noteText: string,
100
- encryptionParams: OrgNoteEncryption
58
+ encryptionParams: WithNoteDecryptionContent<OrgNoteEncryption>
101
59
  ): EncryptionResult<T> {
102
- const isContentEncrypted = isGpgEncrypted(noteText);
60
+ const isContentEncrypted = isGpgEncrypted(encryptionParams.content);
103
61
  if (
104
62
  note.meta.published ||
105
- !note.encryptionType ||
106
63
  !encryptionParams.type ||
107
64
  encryptionParams.type === ModelsPublicNoteEncryptionTypeEnum.Disabled ||
108
65
  !isContentEncrypted
109
66
  ) {
110
67
  note.encrypted = isContentEncrypted;
111
- return [note, noteText];
68
+ return [note, encryptionParams.content];
112
69
  }
113
70
  note.encrypted = true;
114
- const [decryptedNote, decryptedNoteText] =
115
- encryptionParams.type === ModelsPublicNoteEncryptionTypeEnum.GpgKeys
116
- ? await decryptNoteViaKeys(
117
- note,
118
- noteText,
119
- encryptionParams.privateKey,
120
- encryptionParams.privateKeyPassphrase
121
- )
122
- : await decryptNoteViaPassword(note, noteText, encryptionParams.password);
71
+ const decryptionParams = {
72
+ ...encryptionParams,
73
+ format: 'utf8',
74
+ } as WithDecryptionContent<OrgNoteEncryption>;
123
75
 
76
+ const decryptedNoteText = await decrypt(decryptionParams);
124
77
  const parsed = withMetaInfo(parse(decryptedNoteText));
125
78
 
126
79
  return [
127
80
  {
128
- ...decryptedNote,
81
+ ...note,
129
82
  encrypted: false,
130
83
  meta: parsed.meta,
131
84
  },
132
85
  decryptedNoteText,
133
86
  ];
134
87
  }
135
-
136
- export async function decryptNoteViaPassword<T extends AbstractEncryptedNote>(
137
- note: T,
138
- noteText: string,
139
- password: string
140
- ): EncryptionResult<T> {
141
- const decryptedNoteText = await decryptViaPassword(noteText, password);
142
- return [
143
- {
144
- ...note,
145
- encrypted: ModelsPublicNoteEncryptionTypeEnum.GpgPassword,
146
- },
147
- decryptedNoteText,
148
- ];
149
- }
150
-
151
- export async function decryptNoteViaKeys<T extends AbstractEncryptedNote>(
152
- note: T,
153
- noteText: string,
154
- privateKey: string,
155
- privateKeyPassphrase?: string
156
- ): EncryptionResult<T> {
157
- const decryptedNoteText = await decryptViaKeys(
158
- noteText,
159
- privateKey,
160
- privateKeyPassphrase
161
- );
162
- return [
163
- {
164
- ...note,
165
- encrypted: ModelsPublicNoteEncryptionTypeEnum.GpgKeys,
166
- },
167
- decryptedNoteText,
168
- ];
169
- }
@@ -1,8 +1,20 @@
1
1
  import type { ModelsPublicNoteEncryptionTypeEnum } from '../remote-api';
2
2
 
3
+ export type EcnryptionFormat = 'binary' | 'armored';
4
+
5
+ export interface BaseOrgNoteEncryption {
6
+ format?: 'binary' | 'armored';
7
+ }
8
+
9
+ export interface BaseOrgNoteDecryption {
10
+ format?: 'utf8' | 'binary';
11
+ }
12
+
3
13
  export interface OrgNoteGpgEncryption {
4
14
  type: typeof ModelsPublicNoteEncryptionTypeEnum.GpgKeys;
15
+ /* Armored private key */
5
16
  privateKey: string;
17
+ /* Armored public key */
6
18
  publicKey: string;
7
19
  privateKeyPassphrase?: string;
8
20
  }
@@ -20,3 +32,19 @@ export type OrgNoteEncryption =
20
32
  | OrgNoteGpgEncryption
21
33
  | OrgNotePasswordEncryption
22
34
  | OrgNoteDisabledEncryption;
35
+
36
+ export type EncryptionData = {
37
+ content: string;
38
+ };
39
+
40
+ export type WithEncryptionContent<
41
+ T extends OrgNoteEncryption = OrgNoteEncryption,
42
+ > = T & EncryptionData & BaseOrgNoteEncryption;
43
+
44
+ export type WithDecryptionContent<
45
+ T extends OrgNoteEncryption = OrgNoteEncryption,
46
+ > = T & EncryptionData & BaseOrgNoteDecryption;
47
+
48
+ export type WithNoteDecryptionContent<
49
+ T extends OrgNoteEncryption = OrgNoteEncryption,
50
+ > = T & EncryptionData;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orgnote-api",
3
- "version": "0.14.1",
3
+ "version": "0.15.0",
4
4
  "description": "Official API for creating extensions for OrgNote app",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
@@ -1,3 +1,6 @@
1
- export function isGpgEncrypted(text: string): boolean {
1
+ export function isGpgEncrypted(text: string | Uint8Array): boolean {
2
+ if (text instanceof Uint8Array) {
3
+ return true;
4
+ }
2
5
  return text.startsWith('-----BEGIN PGP MESSAGE-----');
3
6
  }