1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | 'use strict'
|
13 |
|
14 | import { cmp } from './cmp'
|
15 |
|
16 | class Cbc {}
|
17 |
|
18 | Cbc.buf2BlocksBuf = function (buf, blockSize) {
|
19 | const bytesize = blockSize / 8
|
20 | const blockBufs = []
|
21 |
|
22 | for (let i = 0; i <= buf.length / bytesize; i++) {
|
23 | let blockBuf = buf.slice(i * bytesize, i * bytesize + bytesize)
|
24 |
|
25 | if (blockBuf.length < blockSize) {
|
26 | blockBuf = Cbc.pkcs7Pad(blockBuf, blockSize)
|
27 | }
|
28 |
|
29 | blockBufs.push(blockBuf)
|
30 | }
|
31 |
|
32 | return blockBufs
|
33 | }
|
34 |
|
35 | Cbc.blockBufs2Buf = function (blockBufs) {
|
36 | let last = blockBufs[blockBufs.length - 1]
|
37 | last = Cbc.pkcs7Unpad(last)
|
38 | blockBufs[blockBufs.length - 1] = last
|
39 |
|
40 | const buf = Buffer.concat(blockBufs)
|
41 |
|
42 | return buf
|
43 | }
|
44 |
|
45 | Cbc.encrypt = function (messageBuf, ivBuf, blockCipher, cipherKeyBuf) {
|
46 | const blockSize = ivBuf.length * 8
|
47 | const blockBufs = Cbc.buf2BlocksBuf(messageBuf, blockSize)
|
48 | const encBufs = Cbc.encryptBlocks(blockBufs, ivBuf, blockCipher, cipherKeyBuf)
|
49 | const encBuf = Buffer.concat(encBufs)
|
50 | return encBuf
|
51 | }
|
52 |
|
53 | Cbc.decrypt = function (encBuf, ivBuf, blockCipher, cipherKeyBuf) {
|
54 | const bytesize = ivBuf.length
|
55 | const encBufs = []
|
56 | for (let i = 0; i < encBuf.length / bytesize; i++) {
|
57 | encBufs.push(encBuf.slice(i * bytesize, i * bytesize + bytesize))
|
58 | }
|
59 | const blockBufs = Cbc.decryptBlocks(encBufs, ivBuf, blockCipher, cipherKeyBuf)
|
60 | const buf = Cbc.blockBufs2Buf(blockBufs)
|
61 | return buf
|
62 | }
|
63 |
|
64 | Cbc.encryptBlock = function (blockBuf, ivBuf, blockCipher, cipherKeyBuf) {
|
65 | const xorbuf = Cbc.xorBufs(blockBuf, ivBuf)
|
66 | const encBuf = blockCipher.encrypt(xorbuf, cipherKeyBuf)
|
67 | return encBuf
|
68 | }
|
69 |
|
70 | Cbc.decryptBlock = function (encBuf, ivBuf, blockCipher, cipherKeyBuf) {
|
71 | const xorbuf = blockCipher.decrypt(encBuf, cipherKeyBuf)
|
72 | const blockBuf = Cbc.xorBufs(xorbuf, ivBuf)
|
73 | return blockBuf
|
74 | }
|
75 |
|
76 | Cbc.encryptBlocks = function (blockBufs, ivBuf, blockCipher, cipherKeyBuf) {
|
77 | const encBufs = []
|
78 |
|
79 | for (let i = 0; i < blockBufs.length; i++) {
|
80 | const blockBuf = blockBufs[i]
|
81 | const encBuf = Cbc.encryptBlock(blockBuf, ivBuf, blockCipher, cipherKeyBuf)
|
82 |
|
83 | encBufs.push(encBuf)
|
84 |
|
85 | ivBuf = encBuf
|
86 | }
|
87 |
|
88 | return encBufs
|
89 | }
|
90 |
|
91 | Cbc.decryptBlocks = function (encBufs, ivBuf, blockCipher, cipherKeyBuf) {
|
92 | const blockBufs = []
|
93 |
|
94 | for (let i = 0; i < encBufs.length; i++) {
|
95 | const encBuf = encBufs[i]
|
96 | const blockBuf = Cbc.decryptBlock(encBuf, ivBuf, blockCipher, cipherKeyBuf)
|
97 |
|
98 | blockBufs.push(blockBuf)
|
99 |
|
100 | ivBuf = encBuf
|
101 | }
|
102 |
|
103 | return blockBufs
|
104 | }
|
105 |
|
106 | Cbc.pkcs7Pad = function (buf, blockSize) {
|
107 | const bytesize = blockSize / 8
|
108 | const padbytesize = bytesize - buf.length
|
109 | const pad = Buffer.alloc(padbytesize)
|
110 | pad.fill(padbytesize)
|
111 | const paddedbuf = Buffer.concat([buf, pad])
|
112 | return paddedbuf
|
113 | }
|
114 |
|
115 | Cbc.pkcs7Unpad = function (paddedbuf) {
|
116 | const padlength = paddedbuf[paddedbuf.length - 1]
|
117 | const padbuf = paddedbuf.slice(paddedbuf.length - padlength, paddedbuf.length)
|
118 | const padbuf2 = Buffer.alloc(padlength)
|
119 | padbuf2.fill(padlength)
|
120 | if (!cmp(padbuf, padbuf2)) {
|
121 | throw new Error('invalid padding')
|
122 | }
|
123 | return paddedbuf.slice(0, paddedbuf.length - padlength)
|
124 | }
|
125 |
|
126 | Cbc.xorBufs = function (buf1, buf2) {
|
127 | if (buf1.length !== buf2.length) {
|
128 | throw new Error('bufs must have the same length')
|
129 | }
|
130 |
|
131 | const buf = Buffer.alloc(buf1.length)
|
132 |
|
133 | for (let i = 0; i < buf1.length; i++) {
|
134 | buf[i] = buf1[i] ^ buf2[i]
|
135 | }
|
136 |
|
137 | return buf
|
138 | }
|
139 |
|
140 | export { Cbc }
|