crypto function implementations for hash
This commit is contained in:
parent
d6474aee0e
commit
5d085b74f5
|
@ -1,4 +1,5 @@
|
||||||
export abstract class CryptoFunctionService {
|
export abstract class CryptoFunctionService {
|
||||||
pbkdf2: (password: string | ArrayBuffer, salt: string | ArrayBuffer, algorithm: 'sha256' | 'sha512',
|
pbkdf2: (password: string | ArrayBuffer, salt: string | ArrayBuffer, algorithm: 'sha256' | 'sha512',
|
||||||
iterations: number, length: number) => Promise<ArrayBuffer>;
|
iterations: number, length: number) => Promise<ArrayBuffer>;
|
||||||
|
hash: (value: string | ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512') => Promise<ArrayBuffer>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,20 +5,8 @@ import { CryptoFunctionService } from '../abstractions/cryptoFunction.service';
|
||||||
export class NodeCryptoFunctionService implements CryptoFunctionService {
|
export class NodeCryptoFunctionService implements CryptoFunctionService {
|
||||||
async pbkdf2(password: string | ArrayBuffer, salt: string | ArrayBuffer, algorithm: 'sha256' | 'sha512',
|
async pbkdf2(password: string | ArrayBuffer, salt: string | ArrayBuffer, algorithm: 'sha256' | 'sha512',
|
||||||
iterations: number, length: number): Promise<ArrayBuffer> {
|
iterations: number, length: number): Promise<ArrayBuffer> {
|
||||||
let nodePassword: string | Buffer;
|
const nodePassword = this.toNodeValue(password);
|
||||||
if (typeof (password) === 'string') {
|
const nodeSalt = this.toNodeValue(salt);
|
||||||
nodePassword = password;
|
|
||||||
} else {
|
|
||||||
nodePassword = Buffer.from(new Uint8Array(password) as any);
|
|
||||||
}
|
|
||||||
|
|
||||||
let nodeSalt: string | Buffer;
|
|
||||||
if (typeof (salt) === 'string') {
|
|
||||||
nodeSalt = salt;
|
|
||||||
} else {
|
|
||||||
nodeSalt = Buffer.from(new Uint8Array(salt) as any);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise<ArrayBuffer>((resolve, reject) => {
|
return new Promise<ArrayBuffer>((resolve, reject) => {
|
||||||
crypto.pbkdf2(nodePassword, nodeSalt, iterations, length, algorithm, (error, key) => {
|
crypto.pbkdf2(nodePassword, nodeSalt, iterations, length, algorithm, (error, key) => {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
|
@ -29,4 +17,21 @@ export class NodeCryptoFunctionService implements CryptoFunctionService {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async hash(value: string | ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512'): Promise<ArrayBuffer> {
|
||||||
|
const nodeValue = this.toNodeValue(value);
|
||||||
|
const hash = crypto.createHash(algorithm);
|
||||||
|
hash.update(nodeValue);
|
||||||
|
return hash.digest().buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private toNodeValue(value: string | ArrayBuffer): string | Buffer {
|
||||||
|
let nodeValue: string | Buffer;
|
||||||
|
if (typeof (value) === 'string') {
|
||||||
|
nodeValue = value;
|
||||||
|
} else {
|
||||||
|
nodeValue = Buffer.from(new Uint8Array(value) as any);
|
||||||
|
}
|
||||||
|
return nodeValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,23 +17,14 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||||
async pbkdf2(password: string | ArrayBuffer, salt: string | ArrayBuffer, algorithm: 'sha256' | 'sha512',
|
async pbkdf2(password: string | ArrayBuffer, salt: string | ArrayBuffer, algorithm: 'sha256' | 'sha512',
|
||||||
iterations: number, length: number): Promise<ArrayBuffer> {
|
iterations: number, length: number): Promise<ArrayBuffer> {
|
||||||
if (this.platformUtilsService.isEdge()) {
|
if (this.platformUtilsService.isEdge()) {
|
||||||
// TODO
|
const passwordBytes = this.toForgeBytes(password);
|
||||||
return new Uint8Array([]).buffer;
|
const saltBytes = this.toForgeBytes(salt);
|
||||||
|
const derivedKeyBytes = (forge as any).pbkdf2(passwordBytes, saltBytes, iterations, length / 8, algorithm);
|
||||||
|
return this.fromForgeBytesToBuf(derivedKeyBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
let passwordBuf: ArrayBuffer;
|
const passwordBuf = this.toBuf(password);
|
||||||
if (typeof (password) === 'string') {
|
const saltBuf = this.toBuf(salt);
|
||||||
passwordBuf = UtilsService.fromUtf8ToArray(password).buffer;
|
|
||||||
} else {
|
|
||||||
passwordBuf = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
let saltBuf: ArrayBuffer;
|
|
||||||
if (typeof (salt) === 'string') {
|
|
||||||
saltBuf = UtilsService.fromUtf8ToArray(salt).buffer;
|
|
||||||
} else {
|
|
||||||
saltBuf = salt;
|
|
||||||
}
|
|
||||||
|
|
||||||
const importedKey = await this.subtle.importKey('raw', passwordBuf, { name: 'PBKDF2' },
|
const importedKey = await this.subtle.importKey('raw', passwordBuf, { name: 'PBKDF2' },
|
||||||
false, ['deriveKey', 'deriveBits']);
|
false, ['deriveKey', 'deriveBits']);
|
||||||
|
@ -54,21 +45,51 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||||
return await this.subtle.exportKey('raw', derivedKey);
|
return await this.subtle.exportKey('raw', derivedKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
async hash(value: string | ArrayBuffer, algorithm: 'sha1' | 'sha256'): Promise<ArrayBuffer> {
|
async hash(value: string | ArrayBuffer, algorithm: 'sha1' | 'sha256' | 'sha512'): Promise<ArrayBuffer> {
|
||||||
if (this.platformUtilsService.isEdge()) {
|
if (this.platformUtilsService.isEdge()) {
|
||||||
// TODO
|
let md: forge.md.MessageDigest;
|
||||||
return new Uint8Array([]).buffer;
|
if (algorithm === 'sha1') {
|
||||||
}
|
md = forge.md.sha1.create();
|
||||||
|
} else if (algorithm === 'sha256') {
|
||||||
let valueBuf: ArrayBuffer;
|
md = forge.md.sha256.create();
|
||||||
if (typeof (value) === 'string') {
|
|
||||||
valueBuf = UtilsService.fromUtf8ToArray(value).buffer;
|
|
||||||
} else {
|
} else {
|
||||||
valueBuf = value;
|
md = (forge as any).md.sha512.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const valueBytes = this.toForgeBytes(value);
|
||||||
|
md.update(valueBytes, 'raw');
|
||||||
|
return this.fromForgeBytesToBuf(md.digest().data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const valueBuf = this.toBuf(value);
|
||||||
return await this.subtle.digest({
|
return await this.subtle.digest({
|
||||||
name: algorithm === 'sha256' ? 'SHA-256' : 'SHA-1'
|
name: algorithm === 'sha1' ? 'SHA-1' : algorithm === 'sha256' ? 'SHA-256' : 'SHA-512'
|
||||||
}, valueBuf);
|
}, valueBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private toBuf(value: string | ArrayBuffer): ArrayBuffer {
|
||||||
|
let buf: ArrayBuffer;
|
||||||
|
if (typeof (value) === 'string') {
|
||||||
|
buf = UtilsService.fromUtf8ToArray(value).buffer;
|
||||||
|
} else {
|
||||||
|
buf = value;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
private toForgeBytes(value: string | ArrayBuffer): string {
|
||||||
|
let bytes: string;
|
||||||
|
if (typeof (value) === 'string') {
|
||||||
|
bytes = forge.util.encodeUtf8(value);
|
||||||
|
} else {
|
||||||
|
const value64 = UtilsService.fromBufferToB64(value);
|
||||||
|
bytes = forge.util.encode64(value64);
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private fromForgeBytesToBuf(byteString: string): ArrayBuffer {
|
||||||
|
const b64 = forge.util.decode64(byteString);
|
||||||
|
return UtilsService.fromB64ToArray(b64).buffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue