Skip to content

Commit a508cc0

Browse files
committed
add adapter for using the legacy crypto in RN
1 parent 9c66040 commit a508cc0

File tree

4 files changed

+161
-2
lines changed

4 files changed

+161
-2
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"use strict";
2+
/**
3+
* ICryptoModule adapter that delegates to the legacy Crypto implementation.
4+
*
5+
* This bridges the RN path to the endpoints that expect an ICryptoModule when
6+
* only a cipherKey is provided.
7+
*/
8+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
9+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
10+
return new (P || (P = Promise))(function (resolve, reject) {
11+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
12+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
13+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
14+
step((generator = generator.apply(thisArg, _arguments || [])).next());
15+
});
16+
};
17+
Object.defineProperty(exports, "__esModule", { value: true });
18+
const buffer_1 = require("buffer");
19+
class LegacyCryptoModuleAdapter {
20+
constructor(legacy) {
21+
this.legacy = legacy;
22+
}
23+
// Allow SDK to update logger on the underlying legacy crypto.
24+
set logger(logger) {
25+
// legacy logger setter accepts LoggerManager | undefined
26+
this.legacy.logger = logger;
27+
}
28+
// --------------------------------------------------------
29+
// --------------------- Encryption -----------------------
30+
// --------------------------------------------------------
31+
encrypt(data) {
32+
const plaintext = typeof data === 'string' ? data : buffer_1.Buffer.from(new Uint8Array(data)).toString('utf8');
33+
// Legacy crypto returns a base64 string.
34+
return this.legacy.encrypt(plaintext);
35+
}
36+
encryptFile(_file, _File) {
37+
return __awaiter(this, void 0, void 0, function* () {
38+
// Not used on RN when cipherKey is set: file endpoints take the cipherKey + cryptography path.
39+
return undefined;
40+
});
41+
}
42+
// --------------------------------------------------------
43+
// --------------------- Decryption -----------------------
44+
// --------------------------------------------------------
45+
decrypt(data) {
46+
let ciphertextB64;
47+
if (typeof data === 'string')
48+
ciphertextB64 = data;
49+
else
50+
ciphertextB64 = buffer_1.Buffer.from(new Uint8Array(data)).toString('base64');
51+
const decrypted = this.legacy.decrypt(ciphertextB64);
52+
// Legacy decrypt returns object or string; ICryptoModule allows returning ArrayBuffer | Payload | null.
53+
return decrypted;
54+
}
55+
decryptFile(_file, _File) {
56+
return __awaiter(this, void 0, void 0, function* () {
57+
// Not used on RN when cipherKey is set: file endpoints take the cipherKey + cryptography path.
58+
return undefined;
59+
});
60+
}
61+
}
62+
exports.default = LegacyCryptoModuleAdapter;

lib/react_native/index.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const middleware_1 = require("../transport/middleware");
1515
const base64_codec_1 = require("../core/components/base64_codec");
1616
const react_native_1 = __importDefault(require("../file/modules/react-native"));
1717
const cryptography_1 = __importDefault(require("../core/components/cryptography"));
18+
const legacy_crypto_module_adapter_1 = __importDefault(require("../core/components/cryptography/legacy-crypto-module-adapter"));
1819
const pubnub_common_1 = require("../core/pubnub-common");
1920
const configuration_2 = require("./configuration");
2021
const common_1 = __importDefault(require("../cbor/common"));
@@ -39,7 +40,23 @@ class PubNub extends pubnub_common_1.PubNubCore {
3940
if (process.env.FILE_SHARING_MODULE !== 'disabled')
4041
platformConfiguration.PubNubFile = react_native_1.default;
4142
// Prepare full client configuration.
42-
const clientConfiguration = (0, configuration_1.makeConfiguration)(platformConfiguration);
43+
// Install a CryptoModule on RN when a cipherKey is provided by adapting legacy Crypto.
44+
const clientConfiguration = (0, configuration_1.makeConfiguration)(platformConfiguration, (cryptoConfiguration) => {
45+
if (!cryptoConfiguration.cipherKey)
46+
return undefined;
47+
if (process.env.CRYPTO_MODULE !== 'disabled') {
48+
const legacy = new cryptography_1.default({
49+
secretKey: platformConfiguration.secretKey,
50+
cipherKey: cryptoConfiguration.cipherKey,
51+
useRandomIVs: platformConfiguration.useRandomIVs,
52+
customEncrypt: platformConfiguration.customEncrypt,
53+
customDecrypt: platformConfiguration.customDecrypt,
54+
logger: cryptoConfiguration.logger,
55+
});
56+
return new legacy_crypto_module_adapter_1.default(legacy);
57+
}
58+
return undefined;
59+
});
4360
// Prepare Token manager.
4461
let tokenManager;
4562
if (process.env.CRYPTO_MODULE !== 'disabled') {
@@ -63,6 +80,7 @@ class PubNub extends pubnub_common_1.PubNubCore {
6380
const transportMiddleware = new middleware_1.PubNubMiddleware({
6481
clientConfiguration,
6582
tokenManager,
83+
shaHMAC: process.env.CRYPTO_MODULE !== 'disabled' ? crypto === null || crypto === void 0 ? void 0 : crypto.HMACSHA256.bind(crypto) : undefined,
6684
transport: new react_native_transport_1.ReactNativeTransport(clientConfiguration.logger(), clientConfiguration.keepAlive),
6785
});
6886
super({
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* ICryptoModule adapter that delegates to the legacy Crypto implementation.
3+
*
4+
* This bridges the RN path to the endpoints that expect an ICryptoModule when
5+
* only a cipherKey is provided.
6+
*/
7+
8+
import type { ICryptoModule } from '../../interfaces/crypto-module';
9+
import type { PubNubFileConstructor, PubNubFileInterface } from '../../types/file';
10+
import type { Payload } from '../../types/api';
11+
import type { LoggerManager } from '../logger-manager';
12+
import LegacyCrypto from './index';
13+
import { Buffer } from 'buffer';
14+
15+
export default class LegacyCryptoModuleAdapter implements ICryptoModule {
16+
constructor(private readonly legacy: LegacyCrypto) {}
17+
18+
set logger(logger: LoggerManager) {
19+
this.legacy.logger = logger;
20+
}
21+
22+
// --------------------------------------------------------
23+
// --------------------- Encryption -----------------------
24+
// --------------------------------------------------------
25+
encrypt(data: ArrayBuffer | string): ArrayBuffer | string {
26+
const plaintext = typeof data === 'string' ? data : Buffer.from(new Uint8Array(data)).toString('utf8');
27+
return this.legacy.encrypt(plaintext) as string;
28+
}
29+
30+
async encryptFile(
31+
_file: PubNubFileInterface,
32+
_File: PubNubFileConstructor<PubNubFileInterface, unknown>,
33+
): Promise<PubNubFileInterface | undefined> {
34+
// Not used on RN when cipherKey is set: file endpoints take the cipherKey + cryptography path.
35+
return undefined;
36+
}
37+
38+
// --------------------------------------------------------
39+
// --------------------- Decryption -----------------------
40+
// --------------------------------------------------------
41+
decrypt(data: ArrayBuffer | string): ArrayBuffer | Payload | null {
42+
let ciphertextB64: string;
43+
if (typeof data === 'string') ciphertextB64 = data;
44+
else ciphertextB64 = Buffer.from(new Uint8Array(data)).toString('base64');
45+
46+
const decrypted = this.legacy.decrypt(ciphertextB64);
47+
return decrypted as Payload | null;
48+
}
49+
50+
async decryptFile(
51+
_file: PubNubFileInterface,
52+
_File: PubNubFileConstructor<PubNubFileInterface, unknown>,
53+
): Promise<PubNubFileInterface | undefined> {
54+
// Not used on RN when cipherKey is set: file endpoints take the cipherKey + cryptography path.
55+
return undefined;
56+
}
57+
}

src/react_native/index.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { decode } from '../core/components/base64_codec';
1414
import PubNubFile from '../file/modules/react-native';
1515
import { PubNubConfiguration } from './configuration';
1616
import Crypto from '../core/components/cryptography';
17+
import LegacyCryptoModuleAdapter from '../core/components/cryptography/legacy-crypto-module-adapter';
18+
import type { CryptorConfiguration, ICryptoModule } from '../core/interfaces/crypto-module';
1719
import { PubNubCore } from '../core/pubnub-common';
1820
import { setDefaults } from './configuration';
1921
import Cbor from '../cbor/common';
@@ -96,7 +98,26 @@ export default class PubNub extends PubNubCore<null, PubNubFileParameters> {
9698
if (process.env.FILE_SHARING_MODULE !== 'disabled') platformConfiguration.PubNubFile = PubNubFile;
9799

98100
// Prepare full client configuration.
99-
const clientConfiguration = makeConfiguration(platformConfiguration);
101+
// Install a CryptoModule on RN when a cipherKey is provided by adapting legacy Crypto.
102+
const clientConfiguration = makeConfiguration(
103+
platformConfiguration,
104+
(cryptoConfiguration: CryptorConfiguration): ICryptoModule | undefined => {
105+
if (!cryptoConfiguration.cipherKey) return undefined;
106+
107+
if (process.env.CRYPTO_MODULE !== 'disabled') {
108+
const legacy = new Crypto({
109+
secretKey: platformConfiguration.secretKey,
110+
cipherKey: cryptoConfiguration.cipherKey,
111+
useRandomIVs: platformConfiguration.useRandomIVs,
112+
customEncrypt: platformConfiguration.customEncrypt,
113+
customDecrypt: platformConfiguration.customDecrypt,
114+
logger: cryptoConfiguration.logger,
115+
});
116+
return new LegacyCryptoModuleAdapter(legacy);
117+
}
118+
return undefined;
119+
},
120+
);
100121

101122
// Prepare Token manager.
102123
let tokenManager: TokenManager | undefined;
@@ -125,6 +146,7 @@ export default class PubNub extends PubNubCore<null, PubNubFileParameters> {
125146
const transportMiddleware = new PubNubMiddleware({
126147
clientConfiguration,
127148
tokenManager,
149+
shaHMAC: process.env.CRYPTO_MODULE !== 'disabled' ? crypto?.HMACSHA256.bind(crypto) : undefined,
128150
transport: new ReactNativeTransport(clientConfiguration.logger(), clientConfiguration.keepAlive),
129151
});
130152

0 commit comments

Comments
 (0)