blockstack
Version:
The Blockstack Javascript library for authentication, identity, and storage.
78 lines (66 loc) • 2.25 kB
text/typescript
import { sha256, sha512 } from 'sha.js'
import { getCryptoLib } from './cryptoUtils'
type NodeCryptoCreateHash = typeof import('crypto').createHash
export interface Sha2Hash {
digest(data: Buffer, algorithm?: 'sha256' | 'sha512'): Promise<Buffer>;
}
export class NodeCryptoSha2Hash {
createHash: NodeCryptoCreateHash
constructor(createHash: NodeCryptoCreateHash) {
this.createHash = createHash
}
async digest(data: Buffer, algorithm = 'sha256'): Promise<Buffer> {
try {
const result = this.createHash(algorithm)
.update(data)
.digest()
return Promise.resolve(result)
} catch (error) {
console.log(error)
console.log(`Error performing ${algorithm} digest with Node.js 'crypto.createHash', falling back to JS implementation.`)
return Promise.resolve(algorithm === 'sha256' ? hashSha256Sync(data) : hashSha512Sync(data))
}
}
}
export class WebCryptoSha2Hash implements Sha2Hash {
subtleCrypto: SubtleCrypto
constructor(subtleCrypto: SubtleCrypto) {
this.subtleCrypto = subtleCrypto
}
async digest(data: Buffer, algorithm = 'sha256'): Promise<Buffer> {
let algo: string
if (algorithm === 'sha256') {
algo = 'SHA-256'
} else if (algorithm === 'sha512') {
algo = 'SHA-512'
} else {
throw new Error(`Unsupported hash algorithm ${algorithm}`)
}
try {
const hash = await this.subtleCrypto.digest(algo, data)
return Buffer.from(hash)
} catch (error) {
console.log(error)
console.log(`Error performing ${algorithm} digest with WebCrypto, falling back to JS implementation.`)
return Promise.resolve(algorithm === 'sha256' ? hashSha256Sync(data) : hashSha512Sync(data))
}
}
}
export async function createSha2Hash(): Promise<Sha2Hash> {
const cryptoLib = await getCryptoLib()
if (cryptoLib.name === 'subtleCrypto') {
return new WebCryptoSha2Hash(cryptoLib.lib)
} else {
return new NodeCryptoSha2Hash(cryptoLib.lib.createHash)
}
}
export function hashSha256Sync(data: Buffer) {
const hash = new sha256()
hash.update(data)
return hash.digest()
}
export function hashSha512Sync(data: Buffer) {
const hash = new sha512()
hash.update(data)
return hash.digest()
}