From 9acb00272f6cc76085dab91ad4e8b957af80f1d9 Mon Sep 17 00:00:00 2001 From: RNEvok <81921589+RNEvok@users.noreply.github.com> Date: Sun, 19 Mar 2023 03:11:43 +0300 Subject: [PATCH] SourceMap disabled, declaration updated, encrypt made module --- Connector.ts | 50 +++++++++++-------------------------------- encryption/index.ts | 52 +++++++++++++++++++++++++++++++++++++++++++++ index.d.ts | 40 +++++++++++++++++++++++++++++++++- package.json | 18 +++++++++++----- tsconfig.json | 2 +- types.ts | 4 ++-- 6 files changed, 119 insertions(+), 47 deletions(-) create mode 100644 encryption/index.ts diff --git a/Connector.ts b/Connector.ts index 1bafb86..58f40ad 100644 --- a/Connector.ts +++ b/Connector.ts @@ -23,8 +23,6 @@ import { api, SOCKET_EVENTS_LISTEN, SOCKET_EVENTS_EMIT } from './api/api'; import { SPECIAL_INSTRUCTIONS_TABLE, SPECIAL_INSTRUCTIONS } from './constants/events'; import { io, Socket } from "socket.io-client"; import { stringifyIfNotString } from './helperFunctions'; -import { box, randomBytes } from 'tweetnacl'; -import { decodeUTF8, encodeBase64 } from 'tweetnacl-util'; import moment from 'moment'; export class Connector { @@ -41,9 +39,7 @@ export class Connector { private _dataToForward: null | {[key: string]: any} = null; private _socket: Socket; private _currentReduxStateCopy: any = null; - private _keyPair: nacl.BoxKeyPair; - private _adminPanelPublicKey: Uint8Array | null = null; - private _sharedKey: Uint8Array | null = null; + private _encryption: any = null; public static lastEvent: RemoteEvent | null = null; public readonly instanceId: number; @@ -64,30 +60,11 @@ export class Connector { delete Connector._remoteSettingsListenersTable[key]; }; - private _newNonce() { - return randomBytes(box.nonceLength); - }; - private _encryptData(json: any) { - try { - if (!this._sharedKey) - throw new Error("Shared key not generated"); - - const nonce = this._newNonce(); - const messageUint8 = decodeUTF8(JSON.stringify(json)); - - const encrypted = box.after(messageUint8, nonce, this._sharedKey); - - const fullMessage = new Uint8Array(nonce.length + encrypted.length); - fullMessage.set(nonce); - fullMessage.set(encrypted, nonce.length); + if (!this._encryption) + return JSON.stringify(json); - const base64FullMessage = encodeBase64(fullMessage); - return base64FullMessage; - } catch (e) { - console.log(e); - return JSON.stringify({msg: "Data encryption error"}); - } + return this._encryption.encryptData(json); }; private _fillInstructionsTable(instructions: Instruction[]) { @@ -238,10 +215,6 @@ export class Connector { } private async _setupNetworkMonitor(config: PackageConfig) { - if (!config.Interceptor) { - console.warn("Error: no network interceptor passed!"); - } - this._networkInterceptor = new config.Interceptor({ onRequest: ({ request, requestId }: NetworkInterceptorOnRequestPayload) => { // console.log(`Intercepted request ${requestId}`, request); @@ -272,12 +245,14 @@ export class Connector { this._fillInstructionsTable(instructions); this._onEventUsersCustomCallback = usersCustomCallback; - this._keyPair = box.keyPair(); + if (config?.EncryptionPlugin) { + this._encryption = new config.EncryptionPlugin(); + } this._connectionInfoPacket = { apiKey, clientType: "CLIENT", - publicKey: this._keyPair.publicKey, + publicKey: this._encryption?.publicKey, availableInstructions: this._getInstructionsPublicFields(instructions), specialInstructions: this._getInstructionsPublicFields(SPECIAL_INSTRUCTIONS) }; @@ -289,7 +264,7 @@ export class Connector { query: {apiKey: this._apiKey} }); - if (config?.enableNetworkMonitor) { + if (config?.Interceptor) { this._setupNetworkMonitor(config); } if (config?.ReactNativePlugin) { @@ -309,8 +284,8 @@ export class Connector { return; } - this._adminPanelPublicKey = new Uint8Array(data.publicKey.data); - this._sharedKey = box.before(this._adminPanelPublicKey, this._keyPair.secretKey); + if (this._encryption) + this._encryption.setAdminPanelPublicKey(data.publicKey.data); }); this._socket.on(SOCKET_EVENTS_LISTEN.EVENT, (event: RemoteEvent) => this._innerHandleEvent(event)); @@ -369,8 +344,7 @@ export class Connector { this._lastEventLog = undefined; this._dataToForward = null; this._currentReduxStateCopy = null; - this._adminPanelPublicKey = null; - this._sharedKey = null; + this._encryption = null; if (this._networkInterceptor) { this._networkInterceptor.dispose(); diff --git a/encryption/index.ts b/encryption/index.ts new file mode 100644 index 0000000..9bad4c7 --- /dev/null +++ b/encryption/index.ts @@ -0,0 +1,52 @@ +import { box, randomBytes } from 'tweetnacl'; +import { decodeUTF8, encodeBase64 } from 'tweetnacl-util'; + +export class EncryptionPlugin { + private _keyPair: nacl.BoxKeyPair | null = null; + private _adminPanelPublicKey: Uint8Array | null = null; + private _sharedKey: Uint8Array | null = null; + + public newNonce() { + return randomBytes(box.nonceLength); + }; + + public encryptData(json: any) { + try { + if (!this._sharedKey) + throw new Error("Shared key not generated"); + + const nonce = this.newNonce(); + const messageUint8 = decodeUTF8(JSON.stringify(json)); + + const encrypted = box.after(messageUint8, nonce, this._sharedKey); + + const fullMessage = new Uint8Array(nonce.length + encrypted.length); + fullMessage.set(nonce); + fullMessage.set(encrypted, nonce.length); + + const base64FullMessage = encodeBase64(fullMessage); + return base64FullMessage; + } catch (e) { + console.log(e); + return JSON.stringify({msg: "Data encryption error"}); + } + }; + + constructor() { + this._keyPair = box.keyPair(); + }; + + public get publicKey() { + return this._keyPair?.publicKey; + }; + + public setAdminPanelPublicKey(data: number[]) { + if (this._keyPair) { + this._adminPanelPublicKey = new Uint8Array(data); + this._sharedKey = box.before(this._adminPanelPublicKey, this._keyPair.secretKey); + console.log('this._sharedKey',this._sharedKey) + } else { + console.warn("No keypair generated!"); + } + } +}; \ No newline at end of file diff --git a/index.d.ts b/index.d.ts index ccda75e..89aad11 100644 --- a/index.d.ts +++ b/index.d.ts @@ -2,8 +2,8 @@ declare module '@appklaar/appklaar_sdk' { export type ObjectT = {[key: string]: T}; export type PackageConfig = { - enableNetworkMonitor?: boolean; Interceptor?: any; + EncryptionPlugin?: any; ReactNativePlugin?: any; }; @@ -149,4 +149,42 @@ declare module '@appklaar/appklaar_sdk' { } export const AppKlaarSdk: AppKlaarSdk; +} + +declare module '@appklaar/appklaar_sdk/react' { + export type RemoteEvent = { + id: string; + eventType: "default" | "special"; + instructionId: string; + args?: any[]; + }; + + export type RemoteSettings = {[key: string]: string}; + + export function useEvent( + handler: (event: RemoteEvent) => any, + instructionIds: ReadonlyArray + ): void; + + export function useRemoteSettings(): RemoteSettings | null; +} + +declare module '@appklaar/appklaar_sdk/Network/NetworkInterceptorClassic' { + export class NetworkInterceptorClassic {} +} + +declare module '@appklaar/appklaar_sdk/Network/NetworkInterceptorRN' { + export class NetworkInterceptorRN {} +} + +declare module '@appklaar/appklaar_sdk/Network/NetworkInterceptorXMLHttp' { + export class NetworkInterceptorXMLHttp {} +} + +declare module '@appklaar/appklaar_sdk/rn' { + export const ReactNativePlugin: any; +} + +declare module '@appklaar/appklaar_sdk/encryption' { + export class EncryptionPlugin {} } \ No newline at end of file diff --git a/package.json b/package.json index a0ea342..6ca2b11 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@appklaar/appklaar_sdk", - "version": "1.4.26", + "version": "1.5.3", "private": false, "description": "App Klaar remote testing SDK", "main": "index.ts", @@ -16,9 +16,7 @@ "apisauce": "^2.1.6", "moment": "^2.29.4", "socket.io-client": "^4.5.4", - "ts-node": "^10.8.1", - "tweetnacl": "^1.0.3", - "tweetnacl-util": "^0.15.1" + "ts-node": "^10.8.1" }, "devDependencies": { "@babel/cli": "^7.17.10", @@ -31,11 +29,15 @@ "@typescript-eslint/eslint-plugin": "^5.55.0", "@typescript-eslint/parser": "^5.55.0", "react-native": "^0.71.4", + "tweetnacl": "^1.0.3", + "tweetnacl-util": "^0.15.1", "typescript": "^4.9.5" }, "peerDependencies": { "react": "*", - "react-native": "*" + "react-native": "*", + "tweetnacl": "^1.0.3", + "tweetnacl-util": "^0.15.1" }, "peerDependenciesMeta": { "react": { @@ -43,6 +45,12 @@ }, "react-native": { "optional": true + }, + "tweetnacl": { + "optional": true + }, + "tweetnacl-util": { + "optional": true } }, "resolutions": { diff --git a/tsconfig.json b/tsconfig.json index 987bc8b..3e5e271 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,7 @@ "strict": true, /* Enable all strict type-checking options. */ "skipLibCheck": true, /* Skip type checking all .d.ts files. */ "moduleResolution": "node", - "sourceMap": true, + "sourceMap": false, "noImplicitAny": false, "noEmitOnError": true, "outDir": "build" diff --git a/types.ts b/types.ts index 10e8a02..d59f377 100644 --- a/types.ts +++ b/types.ts @@ -3,8 +3,8 @@ import { EventHandleError, ScenarioHandleError } from "./Errors"; export type ObjectT = {[key: string]: T}; export type PackageConfig = { - enableNetworkMonitor?: boolean; Interceptor?: any; + EncryptionPlugin?: any; ReactNativePlugin?: any; }; @@ -82,7 +82,7 @@ export type ClientType = "CLIENT" | "ADMIN_PANEL"; export type ConnectionInfoPacket = { apiKey: string; clientType: ClientType; - publicKey: Uint8Array; + publicKey?: Uint8Array; availableInstructions: InstructionPublicFields[]; specialInstructions: InstructionPublicFields[]; };