Projekt

Obecné

Profil

Stáhnout (6.1 KB) Statistiky
| Větev: | Revize:
1
// based on the aes implimentation in triple sec
2
// https://github.com/keybase/triplesec
3
// which is in turn based on the one from crypto-js
4
// https://code.google.com/p/crypto-js/
5

    
6
var Buffer = require('safe-buffer').Buffer
7

    
8
function asUInt32Array (buf) {
9
  if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf)
10

    
11
  var len = (buf.length / 4) | 0
12
  var out = new Array(len)
13

    
14
  for (var i = 0; i < len; i++) {
15
    out[i] = buf.readUInt32BE(i * 4)
16
  }
17

    
18
  return out
19
}
20

    
21
function scrubVec (v) {
22
  for (var i = 0; i < v.length; v++) {
23
    v[i] = 0
24
  }
25
}
26

    
27
function cryptBlock (M, keySchedule, SUB_MIX, SBOX, nRounds) {
28
  var SUB_MIX0 = SUB_MIX[0]
29
  var SUB_MIX1 = SUB_MIX[1]
30
  var SUB_MIX2 = SUB_MIX[2]
31
  var SUB_MIX3 = SUB_MIX[3]
32

    
33
  var s0 = M[0] ^ keySchedule[0]
34
  var s1 = M[1] ^ keySchedule[1]
35
  var s2 = M[2] ^ keySchedule[2]
36
  var s3 = M[3] ^ keySchedule[3]
37
  var t0, t1, t2, t3
38
  var ksRow = 4
39

    
40
  for (var round = 1; round < nRounds; round++) {
41
    t0 = SUB_MIX0[s0 >>> 24] ^ SUB_MIX1[(s1 >>> 16) & 0xff] ^ SUB_MIX2[(s2 >>> 8) & 0xff] ^ SUB_MIX3[s3 & 0xff] ^ keySchedule[ksRow++]
42
    t1 = SUB_MIX0[s1 >>> 24] ^ SUB_MIX1[(s2 >>> 16) & 0xff] ^ SUB_MIX2[(s3 >>> 8) & 0xff] ^ SUB_MIX3[s0 & 0xff] ^ keySchedule[ksRow++]
43
    t2 = SUB_MIX0[s2 >>> 24] ^ SUB_MIX1[(s3 >>> 16) & 0xff] ^ SUB_MIX2[(s0 >>> 8) & 0xff] ^ SUB_MIX3[s1 & 0xff] ^ keySchedule[ksRow++]
44
    t3 = SUB_MIX0[s3 >>> 24] ^ SUB_MIX1[(s0 >>> 16) & 0xff] ^ SUB_MIX2[(s1 >>> 8) & 0xff] ^ SUB_MIX3[s2 & 0xff] ^ keySchedule[ksRow++]
45
    s0 = t0
46
    s1 = t1
47
    s2 = t2
48
    s3 = t3
49
  }
50

    
51
  t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]
52
  t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]
53
  t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]
54
  t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]
55
  t0 = t0 >>> 0
56
  t1 = t1 >>> 0
57
  t2 = t2 >>> 0
58
  t3 = t3 >>> 0
59

    
60
  return [t0, t1, t2, t3]
61
}
62

    
63
// AES constants
64
var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]
65
var G = (function () {
66
  // Compute double table
67
  var d = new Array(256)
68
  for (var j = 0; j < 256; j++) {
69
    if (j < 128) {
70
      d[j] = j << 1
71
    } else {
72
      d[j] = (j << 1) ^ 0x11b
73
    }
74
  }
75

    
76
  var SBOX = []
77
  var INV_SBOX = []
78
  var SUB_MIX = [[], [], [], []]
79
  var INV_SUB_MIX = [[], [], [], []]
80

    
81
  // Walk GF(2^8)
82
  var x = 0
83
  var xi = 0
84
  for (var i = 0; i < 256; ++i) {
85
    // Compute sbox
86
    var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4)
87
    sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63
88
    SBOX[x] = sx
89
    INV_SBOX[sx] = x
90

    
91
    // Compute multiplication
92
    var x2 = d[x]
93
    var x4 = d[x2]
94
    var x8 = d[x4]
95

    
96
    // Compute sub bytes, mix columns tables
97
    var t = (d[sx] * 0x101) ^ (sx * 0x1010100)
98
    SUB_MIX[0][x] = (t << 24) | (t >>> 8)
99
    SUB_MIX[1][x] = (t << 16) | (t >>> 16)
100
    SUB_MIX[2][x] = (t << 8) | (t >>> 24)
101
    SUB_MIX[3][x] = t
102

    
103
    // Compute inv sub bytes, inv mix columns tables
104
    t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100)
105
    INV_SUB_MIX[0][sx] = (t << 24) | (t >>> 8)
106
    INV_SUB_MIX[1][sx] = (t << 16) | (t >>> 16)
107
    INV_SUB_MIX[2][sx] = (t << 8) | (t >>> 24)
108
    INV_SUB_MIX[3][sx] = t
109

    
110
    if (x === 0) {
111
      x = xi = 1
112
    } else {
113
      x = x2 ^ d[d[d[x8 ^ x2]]]
114
      xi ^= d[d[xi]]
115
    }
116
  }
117

    
118
  return {
119
    SBOX: SBOX,
120
    INV_SBOX: INV_SBOX,
121
    SUB_MIX: SUB_MIX,
122
    INV_SUB_MIX: INV_SUB_MIX
123
  }
124
})()
125

    
126
function AES (key) {
127
  this._key = asUInt32Array(key)
128
  this._reset()
129
}
130

    
131
AES.blockSize = 4 * 4
132
AES.keySize = 256 / 8
133
AES.prototype.blockSize = AES.blockSize
134
AES.prototype.keySize = AES.keySize
135
AES.prototype._reset = function () {
136
  var keyWords = this._key
137
  var keySize = keyWords.length
138
  var nRounds = keySize + 6
139
  var ksRows = (nRounds + 1) * 4
140

    
141
  var keySchedule = []
142
  for (var k = 0; k < keySize; k++) {
143
    keySchedule[k] = keyWords[k]
144
  }
145

    
146
  for (k = keySize; k < ksRows; k++) {
147
    var t = keySchedule[k - 1]
148

    
149
    if (k % keySize === 0) {
150
      t = (t << 8) | (t >>> 24)
151
      t =
152
        (G.SBOX[t >>> 24] << 24) |
153
        (G.SBOX[(t >>> 16) & 0xff] << 16) |
154
        (G.SBOX[(t >>> 8) & 0xff] << 8) |
155
        (G.SBOX[t & 0xff])
156

    
157
      t ^= RCON[(k / keySize) | 0] << 24
158
    } else if (keySize > 6 && k % keySize === 4) {
159
      t =
160
        (G.SBOX[t >>> 24] << 24) |
161
        (G.SBOX[(t >>> 16) & 0xff] << 16) |
162
        (G.SBOX[(t >>> 8) & 0xff] << 8) |
163
        (G.SBOX[t & 0xff])
164
    }
165

    
166
    keySchedule[k] = keySchedule[k - keySize] ^ t
167
  }
168

    
169
  var invKeySchedule = []
170
  for (var ik = 0; ik < ksRows; ik++) {
171
    var ksR = ksRows - ik
172
    var tt = keySchedule[ksR - (ik % 4 ? 0 : 4)]
173

    
174
    if (ik < 4 || ksR <= 4) {
175
      invKeySchedule[ik] = tt
176
    } else {
177
      invKeySchedule[ik] =
178
        G.INV_SUB_MIX[0][G.SBOX[tt >>> 24]] ^
179
        G.INV_SUB_MIX[1][G.SBOX[(tt >>> 16) & 0xff]] ^
180
        G.INV_SUB_MIX[2][G.SBOX[(tt >>> 8) & 0xff]] ^
181
        G.INV_SUB_MIX[3][G.SBOX[tt & 0xff]]
182
    }
183
  }
184

    
185
  this._nRounds = nRounds
186
  this._keySchedule = keySchedule
187
  this._invKeySchedule = invKeySchedule
188
}
189

    
190
AES.prototype.encryptBlockRaw = function (M) {
191
  M = asUInt32Array(M)
192
  return cryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX, this._nRounds)
193
}
194

    
195
AES.prototype.encryptBlock = function (M) {
196
  var out = this.encryptBlockRaw(M)
197
  var buf = Buffer.allocUnsafe(16)
198
  buf.writeUInt32BE(out[0], 0)
199
  buf.writeUInt32BE(out[1], 4)
200
  buf.writeUInt32BE(out[2], 8)
201
  buf.writeUInt32BE(out[3], 12)
202
  return buf
203
}
204

    
205
AES.prototype.decryptBlock = function (M) {
206
  M = asUInt32Array(M)
207

    
208
  // swap
209
  var m1 = M[1]
210
  M[1] = M[3]
211
  M[3] = m1
212

    
213
  var out = cryptBlock(M, this._invKeySchedule, G.INV_SUB_MIX, G.INV_SBOX, this._nRounds)
214
  var buf = Buffer.allocUnsafe(16)
215
  buf.writeUInt32BE(out[0], 0)
216
  buf.writeUInt32BE(out[3], 4)
217
  buf.writeUInt32BE(out[2], 8)
218
  buf.writeUInt32BE(out[1], 12)
219
  return buf
220
}
221

    
222
AES.prototype.scrub = function () {
223
  scrubVec(this._keySchedule)
224
  scrubVec(this._invKeySchedule)
225
  scrubVec(this._key)
226
}
227

    
228
module.exports.AES = AES
(4-4/13)