Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the CryptoJS library #1326

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ module.exports = function (grunt) {
fragments: 'src/platform/web/fragments',
static: 'build',
dest: 'build',
crypto_js: 'node_modules/crypto-js/src',
tools_compiler: __dirname + '/node_modules/google-closure-compiler/compiler.jar',
};

Expand Down
27 changes: 0 additions & 27 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
},
"devDependencies": {
"@ably/vcdiff-decoder": "1.0.4",
"@types/crypto-js": "^4.0.1",
"@types/node": "^18.0.0",
"@types/request": "^2.48.7",
"@types/ws": "^8.2.0",
Expand All @@ -42,7 +41,6 @@
"chai": "^4.2.0",
"copy-webpack-plugin": "^11.0.0",
"cors": "~2.7",
"crypto-js": "ably-forks/crypto-js#crypto-lite",
"eslint": "^7.13.0",
"eslint-plugin-jsdoc": "^40.0.0",
"eslint-plugin-security": "^1.4.0",
Expand Down
34 changes: 3 additions & 31 deletions src/common/lib/util/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,37 +461,9 @@ export function cheapRandStr(): string {
* include, not the length of the string. String length produced is not
* guaranteed. */
export const randomString = (numBytes: number): string => {
if (Platform.Config.getRandomValues && typeof Uint8Array !== 'undefined') {
const uIntArr = new Uint8Array(numBytes);
(Platform.Config.getRandomValues as Function)(uIntArr);
return Platform.BufferUtils.base64Encode(uIntArr);
}
/* Old browser; fall back to Math.random. Could just use a
* CryptoJS version of the above, but want this to still work in nocrypto
* versions of the library */
const charset = Platform.BufferUtils.base64CharSet;
/* base64 has 33% overhead; round length up */
const length = Math.round((numBytes * 4) / 3);
let result = '';
for (let i = 0; i < length; i++) {
result += charset[randomPosn(charset)];
}
return result;
};

export const randomHexString = (numBytes: number): string => {
if (Platform.Config.getRandomValues && typeof Uint8Array !== 'undefined') {
const uIntArr = new Uint8Array(numBytes);
(Platform.Config.getRandomValues as Function)(uIntArr);
return Platform.BufferUtils.hexEncode(uIntArr);
}
const charset = Platform.BufferUtils.hexCharSet;
const length = numBytes * 2;
let result = '';
for (let i = 0; i < length; i++) {
result += charset[randomPosn(charset)];
}
return result;
const uIntArr = new Uint8Array(numBytes);
Platform.Config.getRandomValues(uIntArr);
return Platform.BufferUtils.base64Encode(uIntArr);
};

/* Pick n elements at random without replacement from an array */
Expand Down
3 changes: 1 addition & 2 deletions src/common/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import * as NodeBufferUtils from '../platform/nodejs/lib/util/bufferutils';
type Bufferlike = WebBufferUtils.Bufferlike | NodeBufferUtils.Bufferlike;
type BufferUtilsOutput = WebBufferUtils.Output | NodeBufferUtils.Output;
type ToBufferOutput = WebBufferUtils.ToBufferOutput | NodeBufferUtils.ToBufferOutput;
type WordArrayLike = WebBufferUtils.WordArrayLike | NodeBufferUtils.WordArrayLike;

export default class Platform {
static Config: IPlatformConfig;
Expand All @@ -22,7 +21,7 @@ export default class Platform {
BufferUtils object that accepts a broader range of data types than it
can in reality handle.
*/
static BufferUtils: IBufferUtils<Bufferlike, BufferUtilsOutput, ToBufferOutput, WordArrayLike>;
static BufferUtils: IBufferUtils<Bufferlike, BufferUtilsOutput, ToBufferOutput>;
/*
This should be a class whose static methods implement the ICryptoStatic
interface, but (for the same reasons as described in the BufferUtils
Expand Down
6 changes: 2 additions & 4 deletions src/common/types/IBufferUtils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
export default interface IBufferUtils<Bufferlike, Output, ToBufferOutput, WordArrayLike> {
export default interface IBufferUtils<Bufferlike, Output, ToBufferOutput> {
base64CharSet: string;
hexCharSet: string;
isBuffer: (buffer: unknown) => buffer is Bufferlike;
isWordArray: (val: unknown) => val is WordArrayLike;
// On browser this returns a Uint8Array, on node a Buffer
toBuffer: (buffer: Bufferlike) => ToBufferOutput;
toArrayBuffer: (buffer: Bufferlike | WordArrayLike) => ArrayBuffer;
toArrayBuffer: (buffer: Bufferlike) => ArrayBuffer;
base64Encode: (buffer: Bufferlike) => string;
base64Decode: (string: string) => Output;
hexEncode: (buffer: Bufferlike) => string;
Expand All @@ -15,6 +14,5 @@ export default interface IBufferUtils<Bufferlike, Output, ToBufferOutput, WordAr
areBuffersEqual: (buffer1: Bufferlike, buffer2: Bufferlike) => boolean;
byteLength: (buffer: Bufferlike) => number;
arrayBufferViewToBuffer: (arrayBufferView: ArrayBufferView) => Bufferlike;
toWordArray: (buffer: Bufferlike | number[]) => WordArrayLike;
hmacSha256(message: Bufferlike, key: Bufferlike): Output;
}
2 changes: 1 addition & 1 deletion src/common/types/IPlatformConfig.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface IPlatformConfig {
stringByteSize: Buffer.byteLength;
addEventListener?: typeof window.addEventListener | typeof global.addEventListener | null;
Promise: typeof Promise;
getRandomValues?: (arr: ArrayBufferView, callback?: (error: Error | null) => void) => void;
getRandomValues: (arr: ArrayBufferView, callback?: (error: Error | null) => void) => void;
userAgent?: string | null;
inherits?: typeof import('util').inherits;
currentUrl?: string;
Expand Down
15 changes: 0 additions & 15 deletions src/common/types/crypto-js.d.ts

This file was deleted.

15 changes: 2 additions & 13 deletions src/platform/nodejs/lib/util/bufferutils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import crypto from 'crypto';
export type Bufferlike = Buffer | ArrayBuffer | ArrayBufferView;
export type Output = Buffer;
export type ToBufferOutput = Buffer;
export type WordArrayLike = never;

class BufferUtils implements IBufferUtils<Bufferlike, Output, ToBufferOutput, WordArrayLike> {
class BufferUtils implements IBufferUtils<Bufferlike, Output, ToBufferOutput> {
base64CharSet: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
hexCharSet: string = '0123456789abcdef';

Expand Down Expand Up @@ -41,7 +40,7 @@ class BufferUtils implements IBufferUtils<Bufferlike, Output, ToBufferOutput, Wo
return Buffer.isBuffer(buffer) || buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer);
}

toArrayBuffer(buffer: Bufferlike | WordArrayLike): ArrayBuffer {
toArrayBuffer(buffer: Bufferlike): ArrayBuffer {
const nodeBuffer = this.toBuffer(buffer);
return nodeBuffer.buffer.slice(nodeBuffer.byteOffset, nodeBuffer.byteOffset + nodeBuffer.byteLength);
}
Expand Down Expand Up @@ -71,16 +70,6 @@ class BufferUtils implements IBufferUtils<Bufferlike, Output, ToBufferOutput, Wo
return Buffer.from(string, 'utf8');
}

// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
toWordArray(buffer: ArrayBufferView | WordArrayLike | number[] | ArrayBuffer): never {
throw new Error('Not implemented');
}

// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
isWordArray(val: unknown): val is never {
return false;
}

hmacSha256(message: Bufferlike, key: Bufferlike): Output {
const messageBuffer = this.toBuffer(message);
const keyBuffer = this.toBuffer(key);
Expand Down
39 changes: 29 additions & 10 deletions src/platform/react-native/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ import { IPlatformConfig } from '../../common/types/IPlatformConfig';
import BufferUtils from '../web/lib/util/bufferutils';

export default function (bufferUtils: typeof BufferUtils): IPlatformConfig {
const getRandomArrayBuffer = (function (RNRandomBytes) {
return function (byteLength: number, callback: (err: Error | null, result: ArrayBuffer | null) => void) {
RNRandomBytes.randomBytes(byteLength, function (err: Error | null, base64String: string | null) {
callback(err, base64String ? bufferUtils.toArrayBuffer(bufferUtils.base64Decode(base64String)) : null);
});
};
// Installing @types/react-native would fix this but conflicts with @types/node
// See https://github.com/DefinitelyTyped/DefinitelyTyped/issues/15960
// eslint-disable-next-line @typescript-eslint/no-var-requires
})(require('react-native').NativeModules.RNRandomBytes);

return {
agent: 'reactnative',
logTimestamps: true,
Expand Down Expand Up @@ -33,15 +44,23 @@ export default function (bufferUtils: typeof BufferUtils): IPlatformConfig {
TextEncoder: global.TextEncoder,
TextDecoder: global.TextDecoder,
Promise: global.Promise,
getRandomArrayBuffer: (function (RNRandomBytes) {
return function (byteLength: number, callback: (err: Error | null, result: ArrayBuffer | null) => void) {
RNRandomBytes.randomBytes(byteLength, function (err: Error | null, base64String: string | null) {
callback(err, base64String ? bufferUtils.toArrayBuffer(bufferUtils.base64Decode(base64String)) : null);
});
};
// Installing @types/react-native would fix this but conflicts with @types/node
// See https://github.com/DefinitelyTyped/DefinitelyTyped/issues/15960
// eslint-disable-next-line @typescript-eslint/no-var-requires
})(require('react-native').NativeModules.RNRandomBytes),
getRandomArrayBuffer,
getRandomValues: (arr: ArrayBufferView, callback?: (error: Error | null) => void) => {
getRandomArrayBuffer(arr.byteLength, (err, randomArrayBuffer) => {
if (err) {
if (callback) {
callback(err);
}
return;
}

const randomArrayBufferDataView = new DataView(randomArrayBuffer!);
const outputDataView = new DataView(arr.buffer, arr.byteOffset, arr.byteLength);

for (let i = 0; i < randomArrayBufferDataView.byteLength; i++) {
outputDataView.setUint8(i, randomArrayBufferDataView.getUint8(i));
}
});
},
};
}
17 changes: 5 additions & 12 deletions src/platform/web/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import * as Utils from 'common/lib/util/utils';
// Workaround for salesforce lightning locker compat
const globalObject = Utils.getGlobalObject();

declare var msCrypto: typeof crypto; // for IE11

if (typeof Window === 'undefined' && typeof WorkerGlobalScope === 'undefined') {
console.log(
"Warning: this distribution of Ably is intended for browsers. On nodejs, please use the 'ably' package on npm"
Expand Down Expand Up @@ -60,17 +58,12 @@ const Config: IPlatformConfig = {
TextEncoder: globalObject.TextEncoder,
TextDecoder: globalObject.TextDecoder,
Promise: globalObject.Promise,
getRandomValues: (function (crypto) {
if (crypto === undefined) {
return undefined;
getRandomValues: function (arr: ArrayBufferView, callback?: (error: Error | null) => void) {
crypto.getRandomValues(arr);
if (callback) {
callback(null);
}
return function (arr: ArrayBufferView, callback?: (error: Error | null) => void) {
crypto.getRandomValues(arr);
if (callback) {
callback(null);
}
};
})(globalObject.crypto || msCrypto),
},
};

export default Config;
29 changes: 2 additions & 27 deletions src/platform/web/lib/util/bufferutils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import WordArray from 'crypto-js/build/lib-typedarrays';
import Platform from 'common/platform';
import IBufferUtils from 'common/types/IBufferUtils';
import { hmac as hmacSha256 } from './hmac-sha256';
Expand All @@ -10,16 +9,11 @@ import { hmac as hmacSha256 } from './hmac-sha256';
export type Bufferlike = BufferSource;
export type Output = Bufferlike;
export type ToBufferOutput = Uint8Array;
export type WordArrayLike = WordArray;

class BufferUtils implements IBufferUtils<Bufferlike, Output, ToBufferOutput, WordArrayLike> {
class BufferUtils implements IBufferUtils<Bufferlike, Output, ToBufferOutput> {
base64CharSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
hexCharSet = '0123456789abcdef';

isWordArray(ob: unknown): ob is WordArray {
return ob !== null && ob !== undefined && (ob as WordArray).sigBytes !== undefined;
}

// // https://gist.githubusercontent.com/jonleighton/958841/raw/f200e30dfe95212c0165ccf1ae000ca51e9de803/gistfile1.js
uint8ViewToBase64(bytes: Uint8Array) {
let base64 = '';
Expand Down Expand Up @@ -104,32 +98,13 @@ class BufferUtils implements IBufferUtils<Bufferlike, Output, ToBufferOutput, Wo
throw new Error('BufferUtils.toBuffer expected an ArrayBuffer or a view onto one');
}

toArrayBuffer(buffer: Bufferlike | WordArrayLike): ArrayBuffer {
toArrayBuffer(buffer: Bufferlike): ArrayBuffer {
if (buffer instanceof ArrayBuffer) {
return buffer;
}
if (this.isWordArray(buffer)) {
/* Backported from unreleased CryptoJS
* https://code.google.com/p/crypto-js/source/browse/branches/3.x/src/lib-typedarrays.js?r=661 */
var arrayBuffer = new ArrayBuffer(buffer.sigBytes);
var uint8View = new Uint8Array(arrayBuffer);

for (var i = 0; i < buffer.sigBytes; i++) {
uint8View[i] = (buffer.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
}

return uint8View;
}
return this.toBuffer(buffer).buffer;
}

toWordArray(buffer: Bufferlike | number[]) {
if (ArrayBuffer.isView(buffer)) {
buffer = buffer.buffer;
}
return this.isWordArray(buffer) ? buffer : WordArray.create(buffer as number[]);
}

base64Encode(buffer: Bufferlike) {
return this.uint8ViewToBase64(this.toBuffer(buffer));
}
Expand Down
Loading