tslint fixes
This commit is contained in:
parent
7455b39835
commit
54a909ab24
|
@ -2,5 +2,5 @@ export enum BrowserType {
|
||||||
Chrome = 2,
|
Chrome = 2,
|
||||||
Firefox = 3,
|
Firefox = 3,
|
||||||
Opera = 4,
|
Opera = 4,
|
||||||
Edge = 5
|
Edge = 5,
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import SymmetricCryptoKey from './symmetricCryptoKey';
|
||||||
|
|
||||||
|
export default class EncryptedObject {
|
||||||
|
iv: Uint8Array;
|
||||||
|
ct: Uint8Array;
|
||||||
|
mac: Uint8Array;
|
||||||
|
key: SymmetricCryptoKey;
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
import { EncryptionType } from '../../enums/encryptionType.enum';
|
import { EncryptionType } from '../../enums/encryptionType.enum';
|
||||||
|
|
||||||
|
import SymmetricCryptoKeyBuffers from './symmetricCryptoKeyBuffers';
|
||||||
|
|
||||||
import UtilsService from '../../services/utils.service';
|
import UtilsService from '../../services/utils.service';
|
||||||
|
|
||||||
export default class SymmetricCryptoKey {
|
export default class SymmetricCryptoKey {
|
||||||
|
@ -11,27 +13,25 @@ export default class SymmetricCryptoKey {
|
||||||
keyBuf: SymmetricCryptoKeyBuffers;
|
keyBuf: SymmetricCryptoKeyBuffers;
|
||||||
|
|
||||||
constructor(keyBytes: string, b64KeyBytes?: boolean, encType?: EncryptionType) {
|
constructor(keyBytes: string, b64KeyBytes?: boolean, encType?: EncryptionType) {
|
||||||
let win = (window as any);
|
|
||||||
|
|
||||||
if (b64KeyBytes) {
|
if (b64KeyBytes) {
|
||||||
keyBytes = win.forge.util.decode64(keyBytes);
|
keyBytes = forge.util.decode64(keyBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!keyBytes) {
|
if (!keyBytes) {
|
||||||
throw new Error('Must provide keyBytes');
|
throw new Error('Must provide keyBytes');
|
||||||
}
|
}
|
||||||
|
|
||||||
let buffer = win.forge.util.createBuffer(keyBytes);
|
const buffer = forge.util.createBuffer(keyBytes);
|
||||||
if (!buffer || buffer.length() === 0) {
|
if (!buffer || buffer.length() === 0) {
|
||||||
throw new Error('Couldn\'t make buffer');
|
throw new Error('Couldn\'t make buffer');
|
||||||
}
|
}
|
||||||
|
|
||||||
let bufferLength: number = buffer.length();
|
const bufferLength: number = buffer.length();
|
||||||
|
|
||||||
if (encType == null) {
|
if (encType == null) {
|
||||||
if (bufferLength == 32) {
|
if (bufferLength === 32) {
|
||||||
encType = EncryptionType.AesCbc256_B64;
|
encType = EncryptionType.AesCbc256_B64;
|
||||||
} else if (bufferLength == 64) {
|
} else if (bufferLength === 64) {
|
||||||
encType = EncryptionType.AesCbc256_HmacSha256_B64;
|
encType = EncryptionType.AesCbc256_HmacSha256_B64;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Unable to determine encType.');
|
throw new Error('Unable to determine encType.');
|
||||||
|
@ -39,7 +39,7 @@ export default class SymmetricCryptoKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.key = keyBytes;
|
this.key = keyBytes;
|
||||||
this.keyB64 = win.forge.util.encode64(keyBytes);
|
this.keyB64 = forge.util.encode64(keyBytes);
|
||||||
this.encType = encType;
|
this.encType = encType;
|
||||||
|
|
||||||
if (encType === EncryptionType.AesCbc256_B64 && bufferLength === 32) {
|
if (encType === EncryptionType.AesCbc256_B64 && bufferLength === 32) {
|
||||||
|
@ -62,7 +62,7 @@ export default class SymmetricCryptoKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = UtilsService.fromB64ToArray(this.keyB64);
|
const key = UtilsService.fromB64ToArray(this.keyB64);
|
||||||
let keys = new SymmetricCryptoKeyBuffers(key.buffer);
|
const keys = new SymmetricCryptoKeyBuffers(key.buffer);
|
||||||
|
|
||||||
if (this.macKey) {
|
if (this.macKey) {
|
||||||
keys.encKey = key.slice(0, key.length / 2).buffer;
|
keys.encKey = key.slice(0, key.length / 2).buffer;
|
||||||
|
@ -76,13 +76,3 @@ export default class SymmetricCryptoKey {
|
||||||
return this.keyBuf;
|
return this.keyBuf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SymmetricCryptoKeyBuffers {
|
|
||||||
key: ArrayBuffer;
|
|
||||||
encKey?: ArrayBuffer;
|
|
||||||
macKey?: ArrayBuffer;
|
|
||||||
|
|
||||||
constructor(key: ArrayBuffer) {
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
export default class SymmetricCryptoKeyBuffers {
|
||||||
|
key: ArrayBuffer;
|
||||||
|
encKey?: ArrayBuffer;
|
||||||
|
macKey?: ArrayBuffer;
|
||||||
|
|
||||||
|
constructor(key: ArrayBuffer) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import UtilsService from '../../../services/utils.service';
|
import UtilsService from '../../../services/utils.service';
|
||||||
import * as template from './views/tools.html';
|
import * as template from './views/tools.html';
|
||||||
|
|
||||||
class ToolsController {
|
class ToolsController {
|
||||||
|
@ -7,7 +7,6 @@ class ToolsController {
|
||||||
|
|
||||||
constructor(private SweetAlert: any, private i18nService: any,
|
constructor(private SweetAlert: any, private i18nService: any,
|
||||||
private $analytics: any, private utilsService: UtilsService) {
|
private $analytics: any, private utilsService: UtilsService) {
|
||||||
|
|
||||||
this.i18n = i18nService;
|
this.i18n = i18nService;
|
||||||
this.showExport = !utilsService.isEdge();
|
this.showExport = !utilsService.isEdge();
|
||||||
}
|
}
|
||||||
|
@ -24,7 +23,10 @@ class ToolsController {
|
||||||
|
|
||||||
launchiOS() {
|
launchiOS() {
|
||||||
this.$analytics.eventTrack('Launch iOS');
|
this.$analytics.eventTrack('Launch iOS');
|
||||||
chrome.tabs.create({ url: 'https://itunes.apple.com/us/app/bitwarden-free-password-manager/id1137397744?mt=8' });
|
chrome.tabs.create({
|
||||||
|
url: 'https://itunes.apple.com/us/app/bitwarden-free-password-manager/' +
|
||||||
|
'id1137397744?mt=8',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
launchImport() {
|
launchImport() {
|
||||||
|
@ -33,14 +35,14 @@ class ToolsController {
|
||||||
text: this.i18nService.importItemsConfirmation,
|
text: this.i18nService.importItemsConfirmation,
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
confirmButtonText: this.i18nService.yes,
|
confirmButtonText: this.i18nService.yes,
|
||||||
cancelButtonText: this.i18nService.cancel
|
cancelButtonText: this.i18nService.cancel,
|
||||||
}, (confirmed: boolean) => {
|
}, (confirmed: boolean) => {
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
this.$analytics.eventTrack('Launch Web Vault For Import');
|
this.$analytics.eventTrack('Launch Web Vault For Import');
|
||||||
chrome.tabs.create({ url: 'https://help.bitwarden.com/article/import-data/' });
|
chrome.tabs.create({ url: 'https://help.bitwarden.com/article/import-data/' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ToolsComponent = {
|
export const ToolsComponent = {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { EncryptionType } from '../enums/encryptionType.enum';
|
import { EncryptionType } from '../enums/encryptionType.enum';
|
||||||
|
|
||||||
import { CipherString } from '../models/domain/cipherString';
|
import { CipherString } from '../models/domain/cipherString';
|
||||||
|
import EncryptedObject from '../models/domain/encryptedObject';
|
||||||
import SymmetricCryptoKey from '../models/domain/symmetricCryptoKey';
|
import SymmetricCryptoKey from '../models/domain/symmetricCryptoKey';
|
||||||
|
|
||||||
import ConstantsService from './constants.service';
|
import ConstantsService from './constants.service';
|
||||||
|
@ -17,13 +18,6 @@ const Keys = {
|
||||||
const Crypto = window.crypto;
|
const Crypto = window.crypto;
|
||||||
const Subtle = Crypto.subtle;
|
const Subtle = Crypto.subtle;
|
||||||
|
|
||||||
class EncryptedObject {
|
|
||||||
iv: Uint8Array;
|
|
||||||
ct: Uint8Array;
|
|
||||||
mac: Uint8Array;
|
|
||||||
key: SymmetricCryptoKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class CryptoService {
|
export default class CryptoService {
|
||||||
private key: SymmetricCryptoKey;
|
private key: SymmetricCryptoKey;
|
||||||
private encKey: SymmetricCryptoKey;
|
private encKey: SymmetricCryptoKey;
|
||||||
|
@ -73,8 +67,8 @@ export default class CryptoService {
|
||||||
|
|
||||||
// TODO: proper response model type for orgs
|
// TODO: proper response model type for orgs
|
||||||
setOrgKeys(orgs: any) {
|
setOrgKeys(orgs: any) {
|
||||||
let orgKeys: any = {};
|
const orgKeys: any = {};
|
||||||
for (let org of orgs) {
|
for (const org of orgs) {
|
||||||
orgKeys[org.id] = org.key;
|
orgKeys[org.id] = org.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,87 +102,71 @@ export default class CryptoService {
|
||||||
return this.utilsService.getObjFromStorage<string>(Keys.keyHash);
|
return this.utilsService.getObjFromStorage<string>(Keys.keyHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
getEncKey(): Promise<SymmetricCryptoKey> {
|
async getEncKey(): Promise<SymmetricCryptoKey> {
|
||||||
if (this.encKey != null) {
|
if (this.encKey != null) {
|
||||||
return Promise.resolve(this.encKey);
|
return this.encKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
const self = this;
|
const encKey = await this.utilsService.getObjFromStorage<string>(Keys.encKey);
|
||||||
let encKey: string = null;
|
if (encKey == null) {
|
||||||
return this.utilsService.getObjFromStorage<string>(Keys.encKey).then((theEncKey?: string) => {
|
|
||||||
if (theEncKey == null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
encKey = theEncKey;
|
const key = await this.getKey();
|
||||||
return self.getKey();
|
|
||||||
}).then((key: SymmetricCryptoKey) => {
|
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: decrypt with local func
|
const decEncKey = await this.decrypt(new CipherString(encKey), key, 'raw');
|
||||||
// return self.decrypt(new CipherString(encKey), key, 'raw');
|
|
||||||
}).then((decEncKey: string) => {
|
|
||||||
if (decEncKey == null) {
|
if (decEncKey == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.encKey = new SymmetricCryptoKey(decEncKey);
|
this.encKey = new SymmetricCryptoKey(decEncKey);
|
||||||
return self.encKey;
|
return this.encKey;
|
||||||
}, () => {
|
|
||||||
throw new Error('Cannot get enc key. Decryption failed.');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getPrivateKey(): Promise<ArrayBuffer> {
|
async getPrivateKey(): Promise<ArrayBuffer> {
|
||||||
if (this.privateKey != null) {
|
if (this.privateKey != null) {
|
||||||
return Promise.resolve(this.privateKey);
|
return Promise.resolve(this.privateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
const encPrivateKey = await this.utilsService.getObjFromStorage<string>(Keys.encPrivateKey);
|
||||||
return this.utilsService.getObjFromStorage<string>(Keys.encPrivateKey).then((encPrivateKey: string) => {
|
|
||||||
if (encPrivateKey == null) {
|
if (encPrivateKey == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// TODO: decrypt with local func
|
|
||||||
//return self.decrypt(new CipherString(encPrivateKey), null, 'raw');
|
const privateKey = await this.decrypt(new CipherString(encPrivateKey), null, 'raw');
|
||||||
}).then((privateKey: string) => {
|
const privateKeyB64 = forge.util.encode64(privateKey);
|
||||||
if (privateKey != null) {
|
|
||||||
let privateKeyB64 = forge.util.encode64(privateKey);
|
|
||||||
this.privateKey = UtilsService.fromB64ToArray(privateKeyB64).buffer;
|
this.privateKey = UtilsService.fromB64ToArray(privateKeyB64).buffer;
|
||||||
return this.privateKey;
|
return this.privateKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}, () => {
|
|
||||||
throw new Error('Cannot get private key. Decryption failed.');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getOrgKeys(): Promise<Map<string, SymmetricCryptoKey>> {
|
async getOrgKeys(): Promise<Map<string, SymmetricCryptoKey>> {
|
||||||
if (this.orgKeys != null && this.orgKeys.size > 0) {
|
if (this.orgKeys != null && this.orgKeys.size > 0) {
|
||||||
return this.orgKeys;
|
return this.orgKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
let encOrgKeys = await this.utilsService.getObjFromStorage<any>(Keys.encOrgKeys);
|
const encOrgKeys = await this.utilsService.getObjFromStorage<any>(Keys.encOrgKeys);
|
||||||
if (!encOrgKeys) {
|
if (!encOrgKeys) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let decPromises: Promise<any>[] = [];
|
const decPromises: Array<Promise<any>> = [];
|
||||||
let orgKeys: Map<string, SymmetricCryptoKey> = new Map<string, SymmetricCryptoKey>();
|
const orgKeys: Map<string, SymmetricCryptoKey> = new Map<string, SymmetricCryptoKey>();
|
||||||
let setKey = false;
|
let setKey = false;
|
||||||
|
|
||||||
for (var orgId in encOrgKeys) {
|
for (const orgId in encOrgKeys) {
|
||||||
if (encOrgKeys.hasOwnProperty(orgId)) {
|
if (encOrgKeys.hasOwnProperty(orgId)) {
|
||||||
/* jshint ignore:start */
|
/* jshint ignore:start */
|
||||||
|
// tslint:disable-next-line
|
||||||
(function (orgIdInstance) {
|
(function (orgIdInstance) {
|
||||||
const p = self.rsaDecrypt(encOrgKeys[orgIdInstance]).then((decValueB64: string) => {
|
const p = self.rsaDecrypt(encOrgKeys[orgIdInstance]).then((decValueB64: string) => {
|
||||||
orgKeys.set(orgIdInstance, new SymmetricCryptoKey(decValueB64, true));
|
orgKeys.set(orgIdInstance, new SymmetricCryptoKey(decValueB64, true));
|
||||||
setKey = true;
|
setKey = true;
|
||||||
}, (e: any) => {
|
}, (e: any) => {
|
||||||
|
// tslint:disable-next-line
|
||||||
console.log('getOrgKeys error: ' + e);
|
console.log('getOrgKeys error: ' + e);
|
||||||
});
|
});
|
||||||
decPromises.push(p);
|
decPromises.push(p);
|
||||||
|
@ -210,7 +188,7 @@ export default class CryptoService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var orgKeys = await this.getOrgKeys();
|
const orgKeys = await this.getOrgKeys();
|
||||||
if (orgKeys == null || !orgKeys.has(orgId)) {
|
if (orgKeys == null || !orgKeys.has(orgId)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -253,13 +231,12 @@ export default class CryptoService {
|
||||||
}
|
}
|
||||||
|
|
||||||
clearKeys(): Promise<any> {
|
clearKeys(): Promise<any> {
|
||||||
var self = this;
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
self.clearKey(),
|
this.clearKey(),
|
||||||
self.clearKeyHash(),
|
this.clearKeyHash(),
|
||||||
self.clearOrgKeys(),
|
this.clearOrgKeys(),
|
||||||
self.clearEncKey(),
|
this.clearEncKey(),
|
||||||
self.clearPrivateKey()
|
this.clearPrivateKey(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,17 +262,17 @@ export default class CryptoService {
|
||||||
// TODO: convert uses to promises
|
// TODO: convert uses to promises
|
||||||
async hashPassword(password: string, key: SymmetricCryptoKey): Promise<string> {
|
async hashPassword(password: string, key: SymmetricCryptoKey): Promise<string> {
|
||||||
const storedKey = await this.getKey();
|
const storedKey = await this.getKey();
|
||||||
key = key || storedKey
|
key = key || storedKey;
|
||||||
if (!password || !key) {
|
if (!password || !key) {
|
||||||
throw new Error('Invalid parameters.');
|
throw new Error('Invalid parameters.');
|
||||||
}
|
}
|
||||||
|
|
||||||
let hashBits = forge.pbkdf2(key.key, forge.util.encodeUtf8(password), 1, 256 / 8, 'sha256');
|
const hashBits = forge.pbkdf2(key.key, forge.util.encodeUtf8(password), 1, 256 / 8, 'sha256');
|
||||||
return forge.util.encode64(hashBits);
|
return forge.util.encode64(hashBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
makeEncKey(key: SymmetricCryptoKey): Promise<CipherString> {
|
makeEncKey(key: SymmetricCryptoKey): Promise<CipherString> {
|
||||||
let bytes = new Uint8Array(512 / 8);
|
const bytes = new Uint8Array(512 / 8);
|
||||||
Crypto.getRandomValues(bytes);
|
Crypto.getRandomValues(bytes);
|
||||||
return this.encrypt(bytes, key, 'raw');
|
return this.encrypt(bytes, key, 'raw');
|
||||||
}
|
}
|
||||||
|
@ -307,7 +284,7 @@ export default class CryptoService {
|
||||||
}
|
}
|
||||||
|
|
||||||
let plainValueArr: Uint8Array;
|
let plainValueArr: Uint8Array;
|
||||||
if (plainValueEncoding == 'utf8') {
|
if (plainValueEncoding === 'utf8') {
|
||||||
plainValueArr = this.fromUtf8ToArray(plainValue as string);
|
plainValueArr = this.fromUtf8ToArray(plainValue as string);
|
||||||
} else {
|
} else {
|
||||||
plainValueArr = plainValue as Uint8Array;
|
plainValueArr = plainValue as Uint8Array;
|
||||||
|
@ -336,9 +313,10 @@ export default class CryptoService {
|
||||||
encBytes.set(encValue.ct, 1 + encValue.iv.length + macLen);
|
encBytes.set(encValue.ct, 1 + encValue.iv.length + macLen);
|
||||||
|
|
||||||
return encBytes.buffer;
|
return encBytes.buffer;
|
||||||
};
|
}
|
||||||
|
|
||||||
async decrypt(cipherString: CipherString, key: SymmetricCryptoKey, outputEncoding: string = 'utf8'): Promise<string> {
|
async decrypt(cipherString: CipherString, key: SymmetricCryptoKey,
|
||||||
|
outputEncoding: string = 'utf8'): Promise<string> {
|
||||||
const ivBytes: string = forge.util.decode64(cipherString.initializationVector);
|
const ivBytes: string = forge.util.decode64(cipherString.initializationVector);
|
||||||
const ctBytes: string = forge.util.decode64(cipherString.cipherText);
|
const ctBytes: string = forge.util.decode64(cipherString.cipherText);
|
||||||
const macBytes: string = cipherString.mac ? forge.util.decode64(cipherString.mac) : null;
|
const macBytes: string = cipherString.mac ? forge.util.decode64(cipherString.mac) : null;
|
||||||
|
@ -348,7 +326,7 @@ export default class CryptoService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outputEncoding == 'utf8') {
|
if (outputEncoding === 'utf8') {
|
||||||
return decipher.output.toString('utf8');
|
return decipher.output.toString('utf8');
|
||||||
} else {
|
} else {
|
||||||
return decipher.output.getBytes();
|
return decipher.output.getBytes();
|
||||||
|
@ -397,12 +375,12 @@ export default class CryptoService {
|
||||||
let encType: EncryptionType = null;
|
let encType: EncryptionType = null;
|
||||||
let encPieces: string[];
|
let encPieces: string[];
|
||||||
|
|
||||||
if (headerPieces.length == 1) {
|
if (headerPieces.length === 1) {
|
||||||
encType = EncryptionType.Rsa2048_OaepSha256_B64;
|
encType = EncryptionType.Rsa2048_OaepSha256_B64;
|
||||||
encPieces = [headerPieces[0]];
|
encPieces = [headerPieces[0]];
|
||||||
} else if (headerPieces.length == 2) {
|
} else if (headerPieces.length === 2) {
|
||||||
try {
|
try {
|
||||||
encType = parseInt(headerPieces[0]);
|
encType = parseInt(headerPieces[0], null);
|
||||||
encPieces = headerPieces[1].split('|');
|
encPieces = headerPieces[1].split('|');
|
||||||
} catch (e) { }
|
} catch (e) { }
|
||||||
}
|
}
|
||||||
|
@ -450,14 +428,14 @@ export default class CryptoService {
|
||||||
case EncryptionType.Rsa2048_OaepSha256_HmacSha256_B64:
|
case EncryptionType.Rsa2048_OaepSha256_HmacSha256_B64:
|
||||||
padding = {
|
padding = {
|
||||||
name: 'RSA-OAEP',
|
name: 'RSA-OAEP',
|
||||||
hash: { name: 'SHA-256' }
|
hash: { name: 'SHA-256' },
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case EncryptionType.Rsa2048_OaepSha1_B64:
|
case EncryptionType.Rsa2048_OaepSha1_B64:
|
||||||
case EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64:
|
case EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64:
|
||||||
padding = {
|
padding = {
|
||||||
name: 'RSA-OAEP',
|
name: 'RSA-OAEP',
|
||||||
hash: { name: 'SHA-1' }
|
hash: { name: 'SHA-1' },
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -466,7 +444,7 @@ export default class CryptoService {
|
||||||
|
|
||||||
const privateKey = await Subtle.importKey('pkcs8', privateKeyBytes, padding, false, ['decrypt']);
|
const privateKey = await Subtle.importKey('pkcs8', privateKeyBytes, padding, false, ['decrypt']);
|
||||||
|
|
||||||
var ctArr = UtilsService.fromB64ToArray(encPieces[0]);
|
const ctArr = UtilsService.fromB64ToArray(encPieces[0]);
|
||||||
const decBytes = await Subtle.decrypt(padding, privateKey, ctArr.buffer);
|
const decBytes = await Subtle.decrypt(padding, privateKey, ctArr.buffer);
|
||||||
|
|
||||||
const b64DecValue = this.fromBufferToB64(decBytes);
|
const b64DecValue = this.fromBufferToB64(decBytes);
|
||||||
|
@ -488,7 +466,7 @@ export default class CryptoService {
|
||||||
obj.ct = new Uint8Array(encValue);
|
obj.ct = new Uint8Array(encValue);
|
||||||
|
|
||||||
if (keyBuf.macKey) {
|
if (keyBuf.macKey) {
|
||||||
let data = new Uint8Array(obj.iv.length + obj.ct.length);
|
const data = new Uint8Array(obj.iv.length + obj.ct.length);
|
||||||
data.set(obj.iv, 0);
|
data.set(obj.iv, 0);
|
||||||
data.set(obj.ct, obj.iv.length);
|
data.set(obj.ct, obj.iv.length);
|
||||||
const mac = await this.computeMacWC(data.buffer, keyBuf.macKey);
|
const mac = await this.computeMacWC(data.buffer, keyBuf.macKey);
|
||||||
|
@ -503,21 +481,23 @@ export default class CryptoService {
|
||||||
const keyForEnc = await this.getKeyForEncryption(key);
|
const keyForEnc = await this.getKeyForEncryption(key);
|
||||||
const theKey = this.resolveLegacyKey(encType, keyForEnc);
|
const theKey = this.resolveLegacyKey(encType, keyForEnc);
|
||||||
|
|
||||||
if (encType != theKey.encType) {
|
if (encType !== theKey.encType) {
|
||||||
|
// tslint:disable-next-line
|
||||||
console.error('encType unavailable.');
|
console.error('encType unavailable.');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theKey.macKey != null && macBytes != null) {
|
if (theKey.macKey != null && macBytes != null) {
|
||||||
var computedMacBytes = this.computeMac(ivBytes + ctBytes, theKey.macKey, false);
|
const computedMacBytes = this.computeMac(ivBytes + ctBytes, theKey.macKey, false);
|
||||||
if (!this.macsEqual(theKey.macKey, computedMacBytes, macBytes)) {
|
if (!this.macsEqual(theKey.macKey, computedMacBytes, macBytes)) {
|
||||||
|
// tslint:disable-next-line
|
||||||
console.error('MAC failed.');
|
console.error('MAC failed.');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var ctBuffer = forge.util.createBuffer(ctBytes);
|
const ctBuffer = forge.util.createBuffer(ctBytes);
|
||||||
var decipher = forge.cipher.createDecipher('AES-CBC', theKey.encKey);
|
const decipher = forge.cipher.createDecipher('AES-CBC', theKey.encKey);
|
||||||
decipher.start({ iv: ivBytes });
|
decipher.start({ iv: ivBytes });
|
||||||
decipher.update(ctBuffer);
|
decipher.update(ctBuffer);
|
||||||
decipher.finish();
|
decipher.finish();
|
||||||
|
@ -544,6 +524,7 @@ export default class CryptoService {
|
||||||
|
|
||||||
const macsMatch = await this.macsEqualWC(keyBuf.macKey, macBuf, computedMacBuf);
|
const macsMatch = await this.macsEqualWC(keyBuf.macKey, macBuf, computedMacBuf);
|
||||||
if (macsMatch === false) {
|
if (macsMatch === false) {
|
||||||
|
// tslint:disable-next-line
|
||||||
console.error('MAC failed.');
|
console.error('MAC failed.');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -560,7 +541,8 @@ export default class CryptoService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async computeMacWC(dataBuf: ArrayBuffer, macKeyBuf: ArrayBuffer): Promise<ArrayBuffer> {
|
private async computeMacWC(dataBuf: ArrayBuffer, macKeyBuf: ArrayBuffer): Promise<ArrayBuffer> {
|
||||||
const key = await Subtle.importKey('raw', macKeyBuf, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']);
|
const key = await Subtle.importKey('raw', macKeyBuf, { name: 'HMAC', hash: { name: 'SHA-256' } },
|
||||||
|
false, ['sign']);
|
||||||
return await Subtle.sign({ name: 'HMAC', hash: { name: 'SHA-256' } }, key, dataBuf);
|
return await Subtle.sign({ name: 'HMAC', hash: { name: 'SHA-256' } }, key, dataBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,21 +553,22 @@ export default class CryptoService {
|
||||||
|
|
||||||
hmac.start('sha256', macKey);
|
hmac.start('sha256', macKey);
|
||||||
hmac.update(mac1);
|
hmac.update(mac1);
|
||||||
let mac1Bytes = hmac.digest().getBytes();
|
const mac1Bytes = hmac.digest().getBytes();
|
||||||
|
|
||||||
hmac.start(null, null);
|
hmac.start(null, null);
|
||||||
hmac.update(mac2);
|
hmac.update(mac2);
|
||||||
let mac2Bytes = hmac.digest().getBytes();
|
const mac2Bytes = hmac.digest().getBytes();
|
||||||
|
|
||||||
return mac1Bytes == mac2Bytes;
|
return mac1Bytes === mac2Bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async macsEqualWC(macKeyBuf: ArrayBuffer, mac1Buf: ArrayBuffer, mac2Buf: ArrayBuffer): Promise<boolean> {
|
private async macsEqualWC(macKeyBuf: ArrayBuffer, mac1Buf: ArrayBuffer, mac2Buf: ArrayBuffer): Promise<boolean> {
|
||||||
const macKey = await Subtle.importKey('raw', macKeyBuf, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']);
|
const macKey = await Subtle.importKey('raw', macKeyBuf, { name: 'HMAC', hash: { name: 'SHA-256' } },
|
||||||
|
false, ['sign']);
|
||||||
const mac1 = await Subtle.sign({ name: 'HMAC', hash: { name: 'SHA-256' } }, macKey, mac1Buf);
|
const mac1 = await Subtle.sign({ name: 'HMAC', hash: { name: 'SHA-256' } }, macKey, mac1Buf);
|
||||||
const mac2 = await Subtle.sign({ name: 'HMAC', hash: { name: 'SHA-256' } }, macKey, mac2Buf);
|
const mac2 = await Subtle.sign({ name: 'HMAC', hash: { name: 'SHA-256' } }, macKey, mac2Buf);
|
||||||
|
|
||||||
if (mac1.byteLength != mac2.byteLength) {
|
if (mac1.byteLength !== mac2.byteLength) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,7 +594,7 @@ export default class CryptoService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private resolveLegacyKey(encType: EncryptionType, key: SymmetricCryptoKey): SymmetricCryptoKey {
|
private resolveLegacyKey(encType: EncryptionType, key: SymmetricCryptoKey): SymmetricCryptoKey {
|
||||||
if (encType == EncryptionType.AesCbc128_HmacSha256_B64 && key.encType == EncryptionType.AesCbc256_B64) {
|
if (encType === EncryptionType.AesCbc128_HmacSha256_B64 && key.encType === EncryptionType.AesCbc256_B64) {
|
||||||
// Old encrypt-then-mac scheme, make a new key
|
// Old encrypt-then-mac scheme, make a new key
|
||||||
this.legacyEtmKey = this.legacyEtmKey ||
|
this.legacyEtmKey = this.legacyEtmKey ||
|
||||||
new SymmetricCryptoKey(key.key, false, EncryptionType.AesCbc128_HmacSha256_B64);
|
new SymmetricCryptoKey(key.key, false, EncryptionType.AesCbc128_HmacSha256_B64);
|
||||||
|
@ -638,7 +621,7 @@ export default class CryptoService {
|
||||||
|
|
||||||
private fromUtf8ToArray(str: string): Uint8Array {
|
private fromUtf8ToArray(str: string): Uint8Array {
|
||||||
const strUtf8 = unescape(encodeURIComponent(str));
|
const strUtf8 = unescape(encodeURIComponent(str));
|
||||||
let arr = new Uint8Array(strUtf8.length);
|
const arr = new Uint8Array(strUtf8.length);
|
||||||
for (let i = 0; i < strUtf8.length; i++) {
|
for (let i = 0; i < strUtf8.length; i++) {
|
||||||
arr[i] = strUtf8.charCodeAt(i);
|
arr[i] = strUtf8.charCodeAt(i);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue