Skip to content

Commit

Permalink
fix(web-crypto): fix issues with cross SDK compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
parfeon committed Apr 19, 2024
1 parent 7850412 commit 6bc21fa
Show file tree
Hide file tree
Showing 14 changed files with 47 additions and 12 deletions.
17 changes: 15 additions & 2 deletions dist/web/pubnub.js
Original file line number Diff line number Diff line change
Expand Up @@ -1060,24 +1060,29 @@
return new PubNubFile(file);
}
constructor(file) {
let contentLength;
let fileMimeType;
let fileName;
let fileData;
if (file instanceof File) {
fileData = file;
fileName = file.name;
fileMimeType = file.type;
contentLength = file.size;
}
else if ('data' in file) {
const contents = file.data;
fileMimeType = file.mimeType;
fileName = file.name;
fileData = new File([contents], fileName, { type: fileMimeType });
contentLength = fileData.size;
}
if (fileData === undefined)
throw new Error("Couldn't construct a file out of supplied options.");
if (fileName === undefined)
throw new Error("Couldn't guess filename out of the options. Please provide one.");
if (contentLength)
this.contentLength = contentLength;
this.mimeType = fileMimeType;
this.data = fileData;
this.name = fileName;
Expand Down Expand Up @@ -2251,6 +2256,8 @@
// --------------------------------------------------------
// region Decryption
decrypt(encryptedData) {
if (typeof encryptedData.data === 'string')
throw new Error('Decryption error: data for decryption should be ArrayBuffed.');
const iv = this.bufferToWordArray(new Uint8ClampedArray(encryptedData.metadata));
const data = this.bufferToWordArray(new Uint8ClampedArray(encryptedData.data));
return AesCbcCryptor.encoder.encode(this.CryptoJS.AES.decrypt({ ciphertext: data }, this.encryptedKey, {
Expand All @@ -2260,6 +2267,8 @@
}
decryptFileData(encryptedData) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof encryptedData.data === 'string')
throw new Error('Decryption error: data for decryption should be ArrayBuffed.');
const key = yield this.getKey();
return crypto.subtle.decrypt({ name: this.algo, iv: encryptedData.metadata }, key, encryptedData.data);
});
Expand Down Expand Up @@ -2679,7 +2688,7 @@
encryptFile(key, file, File) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b;
if ((_a = file.contentLength) !== null && _a !== void 0 ? _a : 0 <= 0)
if (((_a = file.contentLength) !== null && _a !== void 0 ? _a : 0) <= 0)
throw new Error('encryption error. empty content');
const bKey = yield this.getKey(key);
const abPlaindata = yield file.toArrayBuffer();
Expand Down Expand Up @@ -2826,7 +2835,7 @@
encrypt(data) {
const stringData = typeof data === 'string' ? data : LegacyCryptor.decoder.decode(data);
return {
data: LegacyCryptor.encoder.encode(this.cryptor.encrypt(stringData)),
data: this.cryptor.encrypt(stringData),
metadata: null,
};
}
Expand Down Expand Up @@ -2925,6 +2934,8 @@
: this.defaultCryptor.encrypt(data);
if (!encrypted.metadata)
return encrypted.data;
else if (typeof encrypted.data === 'string')
throw new Error('Encryption error: encrypted data should be ArrayBuffed.');
const headerData = this.getHeaderData(encrypted);
return this.concatArrayBuffer(headerData, encrypted.data);
}
Expand All @@ -2938,6 +2949,8 @@
return this.defaultCryptor.encryptFile(file, File);
const fileData = yield this.getFileData(file);
const encrypted = yield this.defaultCryptor.encryptFileData(fileData);
if (typeof encrypted.data === 'string')
throw new Error('Encryption error: encrypted data should be ArrayBuffed.');
return File.create({
name: file.name,
mimeType: 'application/octet-stream',
Expand Down
2 changes: 1 addition & 1 deletion dist/web/pubnub.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lib/crypto/modules/NodeCryptoModule/nodeCryptoModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class CryptoModule extends AbstractCryptoModule {
});
}
if (file.data instanceof Readable) {
if (file.contentLength === 0)
if (!file.contentLength || file.contentLength === 0)
throw new Error('Encryption error: empty content');
const encryptedStream = yield this.defaultCryptor.encryptStream(file.data);
const header = CryptorHeader.from(this.defaultCryptor.identifier, encryptedStream.metadata);
Expand Down
2 changes: 1 addition & 1 deletion lib/crypto/modules/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class NodeCryptography {
});
}
if (file.data instanceof Readable) {
if (file.contentLength === 0)
if (!file.contentLength || file.contentLength === 0)
throw new Error('Encryption error: empty content.');
return File.create({
name: file.name,
Expand Down
7 changes: 6 additions & 1 deletion lib/file/modules/react-native.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,22 @@ export class PubNubFile {
return new PubNubFile(file);
}
constructor(file) {
let fileData;
let contentLength;
let fileMimeType;
let fileName;
let fileData;
if (file instanceof File) {
fileData = file;
fileName = file.name;
fileMimeType = file.type;
contentLength = file.size;
}
else if ('data' in file) {
const contents = file.data;
fileMimeType = file.mimeType;
fileName = file.name;
fileData = new File([contents], fileName, { type: fileMimeType });
contentLength = fileData.size;
}
else if ('uri' in file) {
fileMimeType = file.mimeType;
Expand All @@ -41,6 +44,8 @@ export class PubNubFile {
throw new Error("Couldn't construct a file out of supplied options.");
if (fileName === undefined)
throw new Error("Couldn't guess filename out of the options. Please provide one.");
if (contentLength)
this.contentLength = contentLength;
this.mimeType = fileMimeType;
this.data = fileData;
this.name = fileName;
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/modules/NodeCryptoModule/nodeCryptoModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export class CryptoModule extends AbstractCryptoModule<CryptorType> {
}

if (file.data instanceof Readable) {
if (file.contentLength === 0) throw new Error('Encryption error: empty content');
if (!file.contentLength || file.contentLength === 0) throw new Error('Encryption error: empty content');

const encryptedStream = await (this.defaultCryptor as ICryptor).encryptStream(file.data);
const header = CryptorHeader.from(this.defaultCryptor.identifier, encryptedStream.metadata!);
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/modules/WebCryptoModule/ICryptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export type EncryptedDataType = {
/**
* Encrypted data.
*/
data: ArrayBuffer;
data: ArrayBuffer | string;

/**
* Used cryptor's metadata.
Expand Down
6 changes: 6 additions & 0 deletions src/crypto/modules/WebCryptoModule/aesCbcCryptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ export default class AesCbcCryptor implements ICryptor {
// region Decryption

decrypt(encryptedData: EncryptedDataType) {
if (typeof encryptedData.data === 'string')
throw new Error('Decryption error: data for decryption should be ArrayBuffed.');

const iv = this.bufferToWordArray(new Uint8ClampedArray(encryptedData.metadata!));
const data = this.bufferToWordArray(new Uint8ClampedArray(encryptedData.data));

Expand All @@ -92,6 +95,9 @@ export default class AesCbcCryptor implements ICryptor {
}

async decryptFileData(encryptedData: EncryptedDataType): Promise<ArrayBuffer> {
if (typeof encryptedData.data === 'string')
throw new Error('Decryption error: data for decryption should be ArrayBuffed.');

const key = await this.getKey();
return crypto.subtle.decrypt({ name: this.algo, iv: encryptedData.metadata! }, key, encryptedData.data);
}
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/modules/WebCryptoModule/legacyCryptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default class LegacyCryptor implements ILegacyCryptor {
const stringData = typeof data === 'string' ? data : LegacyCryptor.decoder.decode(data);

return {
data: LegacyCryptor.encoder.encode(this.cryptor.encrypt(stringData)),
data: this.cryptor.encrypt(stringData),
metadata: null,
};
}
Expand Down
3 changes: 3 additions & 0 deletions src/crypto/modules/WebCryptoModule/webCryptoModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ export class WebCryptoModule extends AbstractCryptoModule<CryptorType> {
: (this.defaultCryptor as ICryptor).encrypt(data);

if (!encrypted.metadata) return encrypted.data;
else if (typeof encrypted.data === 'string')
throw new Error('Encryption error: encrypted data should be ArrayBuffed.');

const headerData = this.getHeaderData(encrypted);

Expand All @@ -103,6 +105,7 @@ export class WebCryptoModule extends AbstractCryptoModule<CryptorType> {

const fileData = await this.getFileData(file);
const encrypted = await (this.defaultCryptor as ICryptor).encryptFileData(fileData);
if (typeof encrypted.data === 'string') throw new Error('Encryption error: encrypted data should be ArrayBuffed.');

return File.create({
name: file.name,
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/modules/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export default class NodeCryptography implements Cryptography<string | ArrayBuff
}

if (file.data instanceof Readable) {
if (file.contentLength === 0) throw new Error('Encryption error: empty content.');
if (!file.contentLength || file.contentLength === 0) throw new Error('Encryption error: empty content.');

return File.create({
name: file.name,
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/modules/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export default class WebCryptography implements Cryptography<ArrayBuffer | strin
file: PubNubFile,
File: PubNubFileConstructor<PubNubFile, PubNubFileParameters>,
) {
if (file.contentLength ?? 0 <= 0) throw new Error('encryption error. empty content');
if ((file.contentLength ?? 0) <= 0) throw new Error('encryption error. empty content');
const bKey = await this.getKey(key);
const abPlaindata = await file.toArrayBuffer();
const abCipherdata = await this.encryptArrayBuffer(bKey, abPlaindata);
Expand Down
6 changes: 5 additions & 1 deletion src/file/modules/react-native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,21 +100,24 @@ export class PubNubFile implements PubNubFileInterface {
}

constructor(file: PubNubFileParameters) {
let fileData: PubNubFile['data'] | undefined;
let contentLength: number | undefined;
let fileMimeType: string | undefined;
let fileName: string | undefined;
let fileData: PubNubFile['data'] | undefined;

if (file instanceof File) {
fileData = file;

fileName = file.name;
fileMimeType = file.type;
contentLength = file.size;
} else if ('data' in file) {
const contents = file.data;

fileMimeType = file.mimeType;
fileName = file.name;
fileData = new File([contents], fileName, { type: fileMimeType });
contentLength = fileData.size;
} else if ('uri' in file) {
fileMimeType = file.mimeType;
fileName = file.name;
Expand All @@ -128,6 +131,7 @@ export class PubNubFile implements PubNubFileInterface {
if (fileData === undefined) throw new Error("Couldn't construct a file out of supplied options.");
if (fileName === undefined) throw new Error("Couldn't guess filename out of the options. Please provide one.");

if (contentLength) this.contentLength = contentLength;
this.mimeType = fileMimeType!;
this.data = fileData;
this.name = fileName;
Expand Down
4 changes: 4 additions & 0 deletions src/file/modules/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export class PubNubFile implements PubNubFileInterface {
}

constructor(file: PubNubFileParameters) {
let contentLength: number | undefined;
let fileMimeType: string | undefined;
let fileName: string | undefined;
let fileData: File | undefined;
Expand All @@ -102,17 +103,20 @@ export class PubNubFile implements PubNubFileInterface {

fileName = file.name;
fileMimeType = file.type;
contentLength = file.size;
} else if ('data' in file) {
const contents = file.data;

fileMimeType = file.mimeType;
fileName = file.name;
fileData = new File([contents], fileName, { type: fileMimeType });
contentLength = fileData.size;
}

if (fileData === undefined) throw new Error("Couldn't construct a file out of supplied options.");
if (fileName === undefined) throw new Error("Couldn't guess filename out of the options. Please provide one.");

if (contentLength) this.contentLength = contentLength;
this.mimeType = fileMimeType!;
this.data = fileData;
this.name = fileName;
Expand Down

0 comments on commit 6bc21fa

Please sign in to comment.