2018-04-15 05:20:37 +02:00
|
|
|
import * as crypto from 'crypto';
|
|
|
|
|
|
|
|
import { CryptoFunctionService } from '../abstractions/cryptoFunction.service';
|
|
|
|
|
|
|
|
export class NodeCryptoFunctionService implements CryptoFunctionService {
|
2018-04-18 14:50:02 +02:00
|
|
|
pbkdf2(password: string | ArrayBuffer, salt: string | ArrayBuffer, algorithm: 'sha256' | 'sha512',
|
2018-04-18 03:18:47 +02:00
|
|
|
iterations: number): Promise<ArrayBuffer> {
|
|
|
|
const len = algorithm === 'sha256' ? 256 : 512;
|
2018-04-17 21:59:38 +02:00
|
|
|
const nodePassword = this.toNodeValue(password);
|
|
|
|
const nodeSalt = this.toNodeValue(salt);
|
2018-04-15 05:20:37 +02:00
|
|
|
return new Promise<ArrayBuffer>((resolve, reject) => {
|
2018-04-16 18:07:51 +02:00
|
|
|
crypto.pbkdf2(nodePassword, nodeSalt, iterations, length, algorithm, (error, key) => {
|
2018-04-15 05:20:37 +02:00
|
|
|
if (error != null) {
|
|
|
|
reject(error);
|
|
|
|
} else {
|
|
|
|
resolve(key.buffer);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2018-04-17 21:59:38 +02:00
|
|
|
|
2018-04-18 14:50:02 +02:00
|
|
|
hash(value: string | ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512'): Promise<ArrayBuffer> {
|
2018-04-17 21:59:38 +02:00
|
|
|
const nodeValue = this.toNodeValue(value);
|
|
|
|
const hash = crypto.createHash(algorithm);
|
|
|
|
hash.update(nodeValue);
|
2018-04-18 14:50:02 +02:00
|
|
|
return Promise.resolve(hash.digest().buffer);
|
2018-04-17 21:59:38 +02:00
|
|
|
}
|
|
|
|
|
2018-04-18 14:50:02 +02:00
|
|
|
hmac(value: ArrayBuffer, key: ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512'): Promise<ArrayBuffer> {
|
|
|
|
const nodeValue = this.toNodeBuffer(value);
|
|
|
|
const nodeKey = this.toNodeBuffer(value);
|
|
|
|
const hmac = crypto.createHmac(algorithm, nodeKey);
|
|
|
|
hmac.update(nodeValue);
|
|
|
|
return Promise.resolve(hmac.digest().buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
aesEncrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> {
|
|
|
|
const nodeData = this.toNodeBuffer(data);
|
|
|
|
const nodeIv = this.toNodeBuffer(iv);
|
|
|
|
const nodeKey = this.toNodeBuffer(key);
|
|
|
|
const cipher = crypto.createCipheriv('aes-256-cbc', nodeKey, nodeIv);
|
|
|
|
const encBuf = Buffer.concat([cipher.update(nodeData), cipher.final()]);
|
|
|
|
return Promise.resolve(encBuf.buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
aesDecryptSmall(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> {
|
|
|
|
return this.aesDecryptLarge(data, iv, key);
|
|
|
|
}
|
|
|
|
|
|
|
|
aesDecryptLarge(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise<ArrayBuffer> {
|
|
|
|
const nodeData = this.toNodeBuffer(data);
|
|
|
|
const nodeIv = this.toNodeBuffer(iv);
|
|
|
|
const nodeKey = this.toNodeBuffer(key);
|
|
|
|
const decipher = crypto.createDecipheriv('aes-256-cbc', nodeKey, nodeIv);
|
|
|
|
const decBuf = Buffer.concat([decipher.update(nodeData), decipher.final()]);
|
|
|
|
return Promise.resolve(decBuf.buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
randomBytes(length: number): Promise<ArrayBuffer> {
|
|
|
|
return new Promise<ArrayBuffer>((resolve, reject) => {
|
|
|
|
crypto.randomBytes(length, (error, bytes) => {
|
|
|
|
if (error != null) {
|
|
|
|
reject(error);
|
|
|
|
} else {
|
|
|
|
resolve(bytes.buffer);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
2018-04-18 01:02:58 +02:00
|
|
|
}
|
|
|
|
|
2018-04-17 21:59:38 +02:00
|
|
|
private toNodeValue(value: string | ArrayBuffer): string | Buffer {
|
|
|
|
let nodeValue: string | Buffer;
|
|
|
|
if (typeof (value) === 'string') {
|
|
|
|
nodeValue = value;
|
|
|
|
} else {
|
2018-04-18 14:50:02 +02:00
|
|
|
nodeValue = this.toNodeBuffer(value);
|
2018-04-17 21:59:38 +02:00
|
|
|
}
|
|
|
|
return nodeValue;
|
|
|
|
}
|
2018-04-18 14:50:02 +02:00
|
|
|
|
|
|
|
private toNodeBuffer(value: ArrayBuffer): Buffer {
|
|
|
|
return Buffer.from(new Uint8Array(value) as any);;
|
|
|
|
}
|
2018-04-15 05:20:37 +02:00
|
|
|
}
|