UNPKG

1.83 kBJavaScriptView Raw
1/**
2 * Ach (Aes+Cbc+Hmac) (experimental)
3 * =================================
4 *
5 * An "encrypt-then-MAC" that uses Aes, Cbc and SHA256 Hmac. This is suitable
6 * for general encryption of data.
7 *
8 * The encrypted data takes the form:
9 * (256 bit hmac)(128 bit iv)(128+ bits Aes+Cbc encrypted message)
10 */
11'use strict'
12
13import { Aescbc } from './aescbc'
14import { Hash } from './hash'
15import { Random } from './random'
16import { Workers } from './workers'
17import { cmp } from './cmp'
18
19class Ach { }
20
21Ach.encrypt = function (messageBuf, cipherKeyBuf, ivBuf) {
22 const encBuf = Aescbc.encrypt(messageBuf, cipherKeyBuf, ivBuf)
23 const hmacbuf = Hash.sha256Hmac(encBuf, cipherKeyBuf)
24 return Buffer.concat([hmacbuf, encBuf])
25}
26
27Ach.asyncEncrypt = async function (messageBuf, cipherKeyBuf, ivBuf) {
28 if (!ivBuf) {
29 ivBuf = Random.getRandomBuffer(128 / 8)
30 }
31 const args = [messageBuf, cipherKeyBuf, ivBuf]
32 const workersResult = await Workers.asyncClassMethod(Ach, 'encrypt', args)
33 return workersResult.resbuf
34}
35
36Ach.decrypt = function (encBuf, cipherKeyBuf) {
37 if (encBuf.length < (256 + 128 + 128) / 8) {
38 throw new Error(
39 'The encrypted data must be at least 256+128+128 bits, which is the length of the Hmac plus the iv plus the smallest encrypted data size'
40 )
41 }
42 const hmacbuf = encBuf.slice(0, 256 / 8)
43 encBuf = encBuf.slice(256 / 8, encBuf.length)
44 const hmacbuf2 = Hash.sha256Hmac(encBuf, cipherKeyBuf)
45 if (!cmp(hmacbuf, hmacbuf2)) {
46 throw new Error(
47 'Message authentication failed - Hmacs are not equivalent'
48 )
49 }
50 return Aescbc.decrypt(encBuf, cipherKeyBuf)
51}
52
53Ach.asyncDecrypt = async function (encBuf, cipherKeyBuf) {
54 const args = [encBuf, cipherKeyBuf]
55 const workersResult = await Workers.asyncClassMethod(Ach, 'decrypt', args)
56 return workersResult.resbuf
57}
58
59export { Ach }