curtain-web-api 1.0.76 → 1.0.78

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.
@@ -178,7 +178,7 @@ export declare class CurtainWebAPI {
178
178
  addOwner(linkId: string, owner: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
179
179
  removeOwner(linkId: string, owner: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
180
180
  getCurtainLinks(username: string, sessionDescription?: string, offset?: number, sessionType?: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
181
- getSiteProperties(): Promise<import("axios").AxiosResponse<SiteProperties, any, {}>>;
181
+ getSiteProperties(appType?: string): Promise<import("axios").AxiosResponse<SiteProperties, any, {}>>;
182
182
  saveDataFilterList(name: string, data: string, category?: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
183
183
  getDataFilterListByID(id: number, limit?: number): Promise<import("axios").AxiosResponse<any, any, {}>>;
184
184
  getDataFilterList(title?: string, searchTerm?: string, category?: string, limit?: number, offset?: number): Promise<import("axios").AxiosResponse<any, any, {}>>;
@@ -1,6 +1,6 @@
1
1
  import { User } from "./curtain-user";
2
2
  import axios, { AxiosHeaders } from "axios";
3
- import { arrayBufferToBase64String, base64ToArrayBuffer, encryptAESData, encryptAESKey, exportAESKey, generateAESKey } from "./curtain-encryption";
3
+ import { arrayBufferToBase64String, base64ToArrayBuffer, decodeJWTPayload, encryptAESData, encryptAESKey, exportAESKey, generateAESKey } from "./curtain-encryption";
4
4
  const base = "https://celsus.muttsu.xyz/";
5
5
  export const replacer = (key, value) => {
6
6
  if (value instanceof Map) {
@@ -175,6 +175,12 @@ export class CurtainWebAPI {
175
175
  });
176
176
  }
177
177
  checkIfRefreshTokenExpired() {
178
+ if (this.user.refresh_token) {
179
+ const payload = decodeJWTPayload(this.user.refresh_token);
180
+ if (payload && payload.exp) {
181
+ return Date.now() >= payload.exp * 1000;
182
+ }
183
+ }
178
184
  let now = new Date();
179
185
  let diff = (now.getTime() - this.user.lastRefreshTokenUpdate.getTime()) / 1000;
180
186
  diff = diff / 60 / 60;
@@ -414,10 +420,14 @@ export class CurtainWebAPI {
414
420
  return response;
415
421
  });
416
422
  }
417
- getSiteProperties() {
423
+ getSiteProperties(appType) {
418
424
  let headers = new AxiosHeaders();
419
425
  headers["Accept"] = "application/json";
420
- return this.axiosInstance.get(this.baseURL + "site-properties/", { headers: headers, responseType: "json" });
426
+ let params = new URLSearchParams();
427
+ if (appType) {
428
+ params.append("app", appType);
429
+ }
430
+ return this.axiosInstance.get(this.baseURL + "site-properties/", { headers: headers, params: params, responseType: "json" });
421
431
  }
422
432
  saveDataFilterList(name, data, category = "") {
423
433
  let headers = new AxiosHeaders();
@@ -37,3 +37,4 @@ export declare function encryptDataAES(data: string, publicKey: CryptoKey): Prom
37
37
  }>;
38
38
  export declare function decryptDataAES(encryptedKey: ArrayBuffer, encryptedData: string, iv: string, privateKey: CryptoKey): Promise<string>;
39
39
  export declare function hashData(data: string): Promise<string>;
40
+ export declare function decodeJWTPayload(token: string): any;
@@ -137,3 +137,24 @@ export async function hashData(data) {
137
137
  const hash = await crypto.subtle.digest("SHA-256", encoded);
138
138
  return arrayBufferToBase64String(hash);
139
139
  }
140
+ export function decodeJWTPayload(token) {
141
+ try {
142
+ const parts = token.split('.');
143
+ if (parts.length !== 3) {
144
+ return null;
145
+ }
146
+ const base64Url = parts[1];
147
+ let base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
148
+ const pad = base64.length % 4;
149
+ if (pad) {
150
+ base64 += new Array(5 - pad).join('=');
151
+ }
152
+ const jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) {
153
+ return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
154
+ }).join(''));
155
+ return JSON.parse(jsonPayload);
156
+ }
157
+ catch (e) {
158
+ return null;
159
+ }
160
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "curtain-web-api",
3
- "version": "1.0.76",
3
+ "version": "1.0.78",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./build/index.js",
@@ -3,6 +3,7 @@ import axios, {AxiosHeaders} from "axios";
3
3
  import {
4
4
  arrayBufferToBase64String, base64ToArrayBuffer,
5
5
  CurtainEncryption,
6
+ decodeJWTPayload,
6
7
  encryptAESData, encryptAESKey,
7
8
  encryptDataRSA, exportAESKey,
8
9
  generateAESKey
@@ -357,6 +358,12 @@ export class CurtainWebAPI {
357
358
  }
358
359
 
359
360
  checkIfRefreshTokenExpired() {
361
+ if (this.user.refresh_token) {
362
+ const payload = decodeJWTPayload(this.user.refresh_token);
363
+ if (payload && payload.exp) {
364
+ return Date.now() >= payload.exp * 1000;
365
+ }
366
+ }
360
367
  let now = new Date();
361
368
  let diff = (now.getTime() - this.user.lastRefreshTokenUpdate.getTime()) / 1000;
362
369
  diff = diff/60/60;
@@ -610,10 +617,14 @@ export class CurtainWebAPI {
610
617
  });
611
618
  }
612
619
 
613
- getSiteProperties() {
620
+ getSiteProperties(appType?: string) {
614
621
  let headers = new AxiosHeaders();
615
622
  headers["Accept"] = "application/json";
616
- return this.axiosInstance.get<SiteProperties>(this.baseURL + "site-properties/", {headers: headers, responseType:"json"});
623
+ let params = new URLSearchParams();
624
+ if (appType) {
625
+ params.append("app", appType);
626
+ }
627
+ return this.axiosInstance.get<SiteProperties>(this.baseURL + "site-properties/", {headers: headers, params: params, responseType:"json"});
617
628
  }
618
629
 
619
630
  saveDataFilterList(name: string, data: string, category: string = "") {
@@ -1,176 +1,198 @@
1
- export function encryptDataRSA(data: string, publicKey: CryptoKey) {
2
- return crypto.subtle.encrypt({name: 'RSA-OAEP'}, publicKey, new TextEncoder().encode(data))
3
- }
4
-
5
- export function decryptDataRSA(data: string, privateKey: CryptoKey) {
6
- return crypto.subtle.decrypt({name: 'RSA-OAEP'}, privateKey, new TextEncoder().encode(data))
7
- }
8
-
9
- export async function importPublicKey(key: ArrayBuffer) {
10
- return await crypto.subtle.importKey('spki', key, {name: 'RSA-OAEP', hash: 'SHA-256'}, true, ['encrypt'])
11
- }
12
-
13
- export async function importPrivateKey(key: ArrayBuffer) {
14
- return await crypto.subtle.importKey('pkcs8', key, {name: 'RSA-OAEP', hash: 'SHA-256'}, true, ['decrypt'])
15
- }
16
-
17
- export async function generateKeyPair(modulusLength: number = 2048, publicExponent: Uint8Array = new Uint8Array([1, 0, 1])) {
18
- return await crypto.subtle.generateKey(
19
- {
20
- name: "RSA-OAEP",
21
- modulusLength: modulusLength,
22
- publicExponent: publicExponent,
23
- hash: "SHA-256",
24
- } as RsaHashedKeyGenParams,
25
- true,
26
- ["encrypt", "decrypt"],
27
- )
28
- }
29
-
30
- export async function exportPublicKey(key: CryptoKey) {
31
- return await crypto.subtle.exportKey('spki', key)
32
- }
33
-
34
- export async function exportPrivateKey(key: CryptoKey) {
35
- return await crypto.subtle.exportKey('pkcs8', key)
36
- }
37
-
38
- export async function importKey(key: ArrayBuffer, type: "public"|"private") {
39
- if (type === "public") {
40
- return await importPublicKey(key)
41
- } else {
42
- return await importPrivateKey(key)
43
- }
44
- }
45
-
46
- export async function exportKeyString(key: CryptoKey, type: "public"|"private"): Promise<string> {
47
- if (type === "public") {
48
- const k = await exportPublicKey(key)
49
- return arrayBufferToBase64String(k)
50
- } else {
51
- const k = await exportPrivateKey(key)
52
- return arrayBufferToBase64String(k)
53
- }
54
- }
55
-
56
- export async function saveToLocalStorage(key: CryptoKey, type: "public"|"private") {
57
- const k = await exportKeyString(key, type)
58
- localStorage.setItem(type + "_key", k)
59
- }
60
-
61
- export async function loadFromLocalStorage(type: "public"|"private") {
62
- const k = localStorage.getItem(type + "_key")
63
- if (k) {
64
- return await importKey(pemToArrayBuffer(k), type)
65
- }
66
- return undefined
67
- }
68
-
69
- export interface CurtainEncryption {
70
- encrypted: boolean,
71
- publicKey?: CryptoKey,
72
- e2e: boolean,
73
- }
74
-
75
- export function arrayBufferToBase64String(arrayBuffer: ArrayBuffer) {
76
- const byteArray = new Uint8Array(arrayBuffer)
77
- let byteString = ''
78
- for (let i=0; i<byteArray.byteLength; i++) {
79
- byteString += String.fromCharCode(byteArray[i])
80
- }
81
- return btoa(byteString)
82
- }
83
-
84
- export function removeLines(str_data: string) {
85
- return str_data.replace("\n", "");
86
- }
87
-
88
- export function base64ToArrayBuffer(b64: string): ArrayBuffer {
89
- const byteString = atob(b64);
90
- const byteArray = new Uint8Array(byteString.length);
91
- for(let i=0; i < byteString.length; i++) {
92
- byteArray[i] = byteString.charCodeAt(i);
93
- }
94
-
95
- return byteArray.buffer;
96
- }
97
-
98
- export function pemToArrayBuffer(pem: string) {
99
- const b64Lines = removeLines(pem);
100
- let b64Prefix = b64Lines.replace('-----BEGIN PRIVATE KEY-----', '');
101
- b64Prefix = b64Prefix.replace('-----BEGIN PUBLIC KEY-----', '');
102
- let b64Final = b64Prefix.replace('-----END PRIVATE KEY-----', '');
103
- b64Final = b64Final.replace('-----END PUBLIC KEY-----', '');
104
-
105
- return base64ToArrayBuffer(b64Final);
106
- }
107
-
108
- // a function to generate to encrypt an aes key arraybuffer with a public key
109
- export async function encryptAESKey(publicKey: CryptoKey, aesKey: ArrayBuffer) {
110
- return await crypto.subtle.encrypt({name: "RSA-OAEP"}, publicKey, aesKey)
111
- }
112
-
113
- // a function to generate an aes key in GCM mode with a length of 256 bits
114
- export async function generateAESKey() {
115
- return await crypto.subtle.generateKey(
116
- {
117
- name: "AES-GCM",
118
- length: 256,
119
- },
120
- true,
121
- ["encrypt", "decrypt"],
122
- )
123
- }
124
-
125
- // a function to encrypt a string with an aes key
126
- export async function encryptAESData(aesKey: CryptoKey, data: string) {
127
- const iv = crypto.getRandomValues(new Uint8Array(12))
128
- const enc = new TextEncoder()
129
- const encoded = enc.encode(data)
130
- const encrypted = await crypto.subtle.encrypt({name: "AES-GCM", iv: iv}, aesKey, encoded)
131
- return {encrypted: arrayBufferToBase64String(encrypted), iv: arrayBufferToBase64String(iv.buffer)}
132
- }
133
-
134
- // a function to decrypt a string with an aes key
135
- export async function decryptAESData(aesKey: CryptoKey, data: string, iv: string) {
136
- const dec = new TextDecoder()
137
- const decrypted = await crypto.subtle.decrypt({name: "AES-GCM", iv: base64ToArrayBuffer(iv)}, aesKey, base64ToArrayBuffer(data))
138
- return dec.decode(decrypted)
139
- }
140
-
141
- // a function to decrypt an aes key with a private key
142
- export async function decryptAESKey(privateKey: CryptoKey, encryptedKey: ArrayBuffer) {
143
- return await crypto.subtle.decrypt({name: "RSA-OAEP"}, privateKey, encryptedKey)
144
- }
145
-
146
- // a function to export an aes key to a string
147
- export async function exportAESKey(key: CryptoKey) {
148
- return await crypto.subtle.exportKey("raw", key)
149
- }
150
- // a function to import an aes key from a string
151
- export async function importAESKey(key: ArrayBuffer) {
152
- return await crypto.subtle.importKey("raw", key, "AES-GCM", true, ["encrypt", "decrypt"])
153
- }
154
-
155
- // a function to encrypt aes key with a public key and also use the aes key to encrypt a large string then return the encrypted aes key and the encrypted string
156
- export async function encryptDataAES(data: string, publicKey: CryptoKey) {
157
- const aesKey = await generateAESKey()
158
- const encryptedKey = await encryptAESKey(publicKey, await exportAESKey(aesKey))
159
- const encryptedData = await encryptAESData(aesKey, data)
160
- return {encryptedKey: arrayBufferToBase64String(encryptedKey), encryptedData: encryptedData}
161
- }
162
-
163
- // a function to decrypt an aes key with a private key and use the aes key to decrypt a large string
164
- export async function decryptDataAES(encryptedKey: ArrayBuffer, encryptedData: string, iv: string, privateKey: CryptoKey) {
165
- const aesKey = await decryptAESKey(privateKey, encryptedKey)
166
- //import aes key
167
- return await decryptAESData(await importAESKey(aesKey), encryptedData, iv)
168
- }
169
-
170
- // a function to calculate sha-256 hash of a large string
171
- export async function hashData(data: string) {
172
- const enc = new TextEncoder()
173
- const encoded = enc.encode(data)
174
- const hash = await crypto.subtle.digest("SHA-256", encoded)
175
- return arrayBufferToBase64String(hash)
176
- }
1
+ export function encryptDataRSA(data: string, publicKey: CryptoKey) {
2
+ return crypto.subtle.encrypt({name: 'RSA-OAEP'}, publicKey, new TextEncoder().encode(data))
3
+ }
4
+
5
+ export function decryptDataRSA(data: string, privateKey: CryptoKey) {
6
+ return crypto.subtle.decrypt({name: 'RSA-OAEP'}, privateKey, new TextEncoder().encode(data))
7
+ }
8
+
9
+ export async function importPublicKey(key: ArrayBuffer) {
10
+ return await crypto.subtle.importKey('spki', key, {name: 'RSA-OAEP', hash: 'SHA-256'}, true, ['encrypt'])
11
+ }
12
+
13
+ export async function importPrivateKey(key: ArrayBuffer) {
14
+ return await crypto.subtle.importKey('pkcs8', key, {name: 'RSA-OAEP', hash: 'SHA-256'}, true, ['decrypt'])
15
+ }
16
+
17
+ export async function generateKeyPair(modulusLength: number = 2048, publicExponent: Uint8Array = new Uint8Array([1, 0, 1])) {
18
+ return await crypto.subtle.generateKey(
19
+ {
20
+ name: "RSA-OAEP",
21
+ modulusLength: modulusLength,
22
+ publicExponent: publicExponent,
23
+ hash: "SHA-256",
24
+ } as RsaHashedKeyGenParams,
25
+ true,
26
+ ["encrypt", "decrypt"],
27
+ )
28
+ }
29
+
30
+ export async function exportPublicKey(key: CryptoKey) {
31
+ return await crypto.subtle.exportKey('spki', key)
32
+ }
33
+
34
+ export async function exportPrivateKey(key: CryptoKey) {
35
+ return await crypto.subtle.exportKey('pkcs8', key)
36
+ }
37
+
38
+ export async function importKey(key: ArrayBuffer, type: "public"|"private") {
39
+ if (type === "public") {
40
+ return await importPublicKey(key)
41
+ } else {
42
+ return await importPrivateKey(key)
43
+ }
44
+ }
45
+
46
+ export async function exportKeyString(key: CryptoKey, type: "public"|"private"): Promise<string> {
47
+ if (type === "public") {
48
+ const k = await exportPublicKey(key)
49
+ return arrayBufferToBase64String(k)
50
+ } else {
51
+ const k = await exportPrivateKey(key)
52
+ return arrayBufferToBase64String(k)
53
+ }
54
+ }
55
+
56
+ export async function saveToLocalStorage(key: CryptoKey, type: "public"|"private") {
57
+ const k = await exportKeyString(key, type)
58
+ localStorage.setItem(type + "_key", k)
59
+ }
60
+
61
+ export async function loadFromLocalStorage(type: "public"|"private") {
62
+ const k = localStorage.getItem(type + "_key")
63
+ if (k) {
64
+ return await importKey(pemToArrayBuffer(k), type)
65
+ }
66
+ return undefined
67
+ }
68
+
69
+ export interface CurtainEncryption {
70
+ encrypted: boolean,
71
+ publicKey?: CryptoKey,
72
+ e2e: boolean,
73
+ }
74
+
75
+ export function arrayBufferToBase64String(arrayBuffer: ArrayBuffer) {
76
+ const byteArray = new Uint8Array(arrayBuffer)
77
+ let byteString = ''
78
+ for (let i=0; i<byteArray.byteLength; i++) {
79
+ byteString += String.fromCharCode(byteArray[i])
80
+ }
81
+ return btoa(byteString)
82
+ }
83
+
84
+ export function removeLines(str_data: string) {
85
+ return str_data.replace("\n", "");
86
+ }
87
+
88
+ export function base64ToArrayBuffer(b64: string): ArrayBuffer {
89
+ const byteString = atob(b64);
90
+ const byteArray = new Uint8Array(byteString.length);
91
+ for(let i=0; i < byteString.length; i++) {
92
+ byteArray[i] = byteString.charCodeAt(i);
93
+ }
94
+
95
+ return byteArray.buffer;
96
+ }
97
+
98
+ export function pemToArrayBuffer(pem: string) {
99
+ const b64Lines = removeLines(pem);
100
+ let b64Prefix = b64Lines.replace('-----BEGIN PRIVATE KEY-----', '');
101
+ b64Prefix = b64Prefix.replace('-----BEGIN PUBLIC KEY-----', '');
102
+ let b64Final = b64Prefix.replace('-----END PRIVATE KEY-----', '');
103
+ b64Final = b64Final.replace('-----END PUBLIC KEY-----', '');
104
+
105
+ return base64ToArrayBuffer(b64Final);
106
+ }
107
+
108
+ // a function to generate to encrypt an aes key arraybuffer with a public key
109
+ export async function encryptAESKey(publicKey: CryptoKey, aesKey: ArrayBuffer) {
110
+ return await crypto.subtle.encrypt({name: "RSA-OAEP"}, publicKey, aesKey)
111
+ }
112
+
113
+ // a function to generate an aes key in GCM mode with a length of 256 bits
114
+ export async function generateAESKey() {
115
+ return await crypto.subtle.generateKey(
116
+ {
117
+ name: "AES-GCM",
118
+ length: 256,
119
+ },
120
+ true,
121
+ ["encrypt", "decrypt"],
122
+ )
123
+ }
124
+
125
+ // a function to encrypt a string with an aes key
126
+ export async function encryptAESData(aesKey: CryptoKey, data: string) {
127
+ const iv = crypto.getRandomValues(new Uint8Array(12))
128
+ const enc = new TextEncoder()
129
+ const encoded = enc.encode(data)
130
+ const encrypted = await crypto.subtle.encrypt({name: "AES-GCM", iv: iv}, aesKey, encoded)
131
+ return {encrypted: arrayBufferToBase64String(encrypted), iv: arrayBufferToBase64String(iv.buffer)}
132
+ }
133
+
134
+ // a function to decrypt a string with an aes key
135
+ export async function decryptAESData(aesKey: CryptoKey, data: string, iv: string) {
136
+ const dec = new TextDecoder()
137
+ const decrypted = await crypto.subtle.decrypt({name: "AES-GCM", iv: base64ToArrayBuffer(iv)}, aesKey, base64ToArrayBuffer(data))
138
+ return dec.decode(decrypted)
139
+ }
140
+
141
+ // a function to decrypt an aes key with a private key
142
+ export async function decryptAESKey(privateKey: CryptoKey, encryptedKey: ArrayBuffer) {
143
+ return await crypto.subtle.decrypt({name: "RSA-OAEP"}, privateKey, encryptedKey)
144
+ }
145
+
146
+ // a function to export an aes key to a string
147
+ export async function exportAESKey(key: CryptoKey) {
148
+ return await crypto.subtle.exportKey ("raw", key)
149
+ }
150
+ // a function to import an aes key from a string
151
+ export async function importAESKey(key: ArrayBuffer) {
152
+ return await crypto.subtle.importKey("raw", key, "AES-GCM", true, ["encrypt", "decrypt"])
153
+ }
154
+
155
+ // a function to encrypt aes key with a public key and also use the aes key to encrypt a large string then return the encrypted aes key and the encrypted string
156
+ export async function encryptDataAES(data: string, publicKey: CryptoKey) {
157
+ const aesKey = await generateAESKey()
158
+ const encryptedKey = await encryptAESKey(publicKey, await exportAESKey(aesKey))
159
+ const encryptedData = await encryptAESData(aesKey, data)
160
+ return {encryptedKey: arrayBufferToBase64String(encryptedKey), encryptedData: encryptedData}
161
+ }
162
+
163
+ // a function to decrypt an aes key with a private key and use the aes key to decrypt a large string
164
+ export async function decryptDataAES(encryptedKey: ArrayBuffer, encryptedData: string, iv: string, privateKey: CryptoKey) {
165
+ const aesKey = await decryptAESKey(privateKey, encryptedKey)
166
+ //import aes key
167
+ return await decryptAESData(await importAESKey(aesKey), encryptedData, iv)
168
+ }
169
+
170
+ // a function to calculate sha-256 hash of a large string
171
+ export async function hashData(data: string) {
172
+ const enc = new TextEncoder()
173
+ const encoded = enc.encode(data)
174
+ const hash = await crypto.subtle.digest("SHA-256", encoded)
175
+ return arrayBufferToBase64String(hash)
176
+ }
177
+
178
+ export function decodeJWTPayload(token: string) {
179
+ try {
180
+ const parts = token.split('.');
181
+ if (parts.length !== 3) {
182
+ return null;
183
+ }
184
+ const base64Url = parts[1];
185
+ let base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
186
+ const pad = base64.length % 4;
187
+ if (pad) {
188
+ base64 += new Array(5 - pad).join('=');
189
+ }
190
+ const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
191
+ return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
192
+ }).join(''));
193
+
194
+ return JSON.parse(jsonPayload);
195
+ } catch (e) {
196
+ return null;
197
+ }
198
+ }