Skip to content

Commit f6c8fef

Browse files
committed
Update module
1 parent f7dd8dd commit f6c8fef

File tree

1 file changed

+163
-63
lines changed

1 file changed

+163
-63
lines changed

index.js

Lines changed: 163 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,190 @@
1+
'use strict'
12
var Transform = require('stream').Transform
23
var inherits = require('inherits')
34
var StringDecoder = require('string_decoder').StringDecoder
4-
module.exports = CipherBase
5-
inherits(CipherBase, Transform)
6-
function CipherBase (hashMode) {
5+
6+
exports.CipherBase = CipherBase
7+
exports.CipherivBase = CipherivBase
8+
exports.DecipherBase = DecipherBase
9+
exports.DecipherivBase = DecipherivBase
10+
11+
var K_CIPHER = 0
12+
var K_DECIPHER = 1
13+
14+
function throwIfNotStringOrBuffer (val, prefix) {
15+
if (!Buffer.isBuffer(val) && typeof val !== 'string') throw new TypeError(prefx + ' must be a string or a buffer')
16+
}
17+
18+
function throwIfNotBuffer (val, prefix) {
19+
if (!Buffer.isBuffer(val)) throw new TypeError(prefix + ' must be a buffer')
20+
}
21+
22+
function getDecoder (decoder, encoding) {
23+
if (encoding === 'utf-8') encoding = 'utf8'
24+
decoder = decoder || new StringDecoder(encoding)
25+
if (decoder.encoding !== encoding) throw new Error('Cannot change encoding')
26+
return decoder
27+
}
28+
29+
function toBuf (str, prefix) {
30+
throwIfNotStringOrBuffer(str, prefix)
31+
if (typeof str === 'string') return new Buffer(str, 'utf8')
32+
else return str
33+
}
34+
35+
function CipherBase (cipher, password) {
736
Transform.call(this)
8-
this.hashMode = typeof hashMode === 'string'
9-
if (this.hashMode) {
10-
this[hashMode] = this._finalOrDigest
11-
} else {
12-
this.final = this._finalOrDigest
13-
}
37+
38+
this._kind = K_CIPHER
39+
this._authTag = null
1440
this._decoder = null
15-
this._encoding = null
16-
}
17-
CipherBase.prototype.update = function (data, inputEnc, outputEnc) {
18-
if (typeof data === 'string') {
19-
data = new Buffer(data, inputEnc)
20-
}
21-
var outData = this._update(data)
22-
if (this.hashMode) {
23-
return this
24-
}
25-
if (outputEnc) {
26-
outData = this._toString(outData, outputEnc)
27-
}
28-
return outData
41+
this._finalized = false
42+
43+
this._init(toBuf(cipher, 'Cipher type'), toBuf(password, 'Password'))
2944
}
3045

31-
CipherBase.prototype.setAutoPadding = function () {}
46+
inherits(CipherBase, Transform)
3247

33-
CipherBase.prototype.getAuthTag = function () {
34-
throw new Error('trying to get auth tag in unsupported state')
48+
CipherBase.prototype._init = function () {
49+
throw new Error('_init is not implemented')
3550
}
3651

37-
CipherBase.prototype.setAuthTag = function () {
38-
throw new Error('trying to set auth tag in unsupported state')
52+
CipherBase.prototype._initiv = function () {
53+
throw new Error('_initiv is not implemented')
3954
}
4055

41-
CipherBase.prototype.setAAD = function () {
42-
throw new Error('trying to set aad in unsupported state')
56+
CipherBase.prototype._isAuthenticatedMode = function () {
57+
throw new Error('_isAuthenticatedMode is not implemented')
4358
}
4459

45-
CipherBase.prototype._transform = function (data, _, next) {
46-
var err
60+
CipherBase.prototype._transform = function (chunk, encoding, callback) {
61+
var error = null
4762
try {
48-
if (this.hashMode) {
49-
this._update(data)
50-
} else {
51-
this.push(this._update(data))
52-
}
53-
} catch (e) {
54-
err = e
55-
} finally {
56-
next(err)
63+
if (encoding !== 'buffer') chunk = new Buffer(chunk, encoding)
64+
this.push(this.update(chunk))
65+
} catch (err) {
66+
error = err
5767
}
68+
69+
callback(error)
5870
}
59-
CipherBase.prototype._flush = function (done) {
60-
var err
71+
72+
CipherBase.prototype._flush = function (callback) {
73+
var error = null
6174
try {
6275
this.push(this._final())
63-
} catch (e) {
64-
err = e
65-
} finally {
66-
done(err)
76+
} catch (err) {
77+
error = err
6778
}
79+
80+
callback(error)
6881
}
69-
CipherBase.prototype._finalOrDigest = function (outputEnc) {
70-
var outData = this._final() || new Buffer('')
71-
if (outputEnc) {
72-
outData = this._toString(outData, outputEnc, true)
82+
83+
CipherBase.prototype.update = function (data, inputEncoding, outputEncoding) {
84+
throwIfNotStringOrBuffer(data, 'Cipher data')
85+
if (this._finalized) throw new Error('Trying to add data in unsupported state')
86+
87+
if (!Buffer.isBuffer(data)) data = new Buffer(data, inputEncoding || 'binary')
88+
89+
data = this._update(data)
90+
if (outputEncoding && outputEncoding !== 'buffer') {
91+
this._decoder = getDecoder(this._decoder, outputEncoding)
92+
data = this._decoder.write(data)
7393
}
74-
return outData
94+
return data
7595
}
7696

77-
CipherBase.prototype._toString = function (value, enc, final) {
78-
if (!this._decoder) {
79-
this._decoder = new StringDecoder(enc)
80-
this._encoding = enc
81-
}
82-
if (this._encoding !== enc) {
83-
throw new Error('can\'t switch encodings')
97+
CipherBase.prototype._update = function (data) {
98+
throw new Error('_update is not implemented')
99+
}
100+
101+
CipherBase.prototype.final = function (encoding) {
102+
if (this._finalized) {
103+
var msg = this._isAuthenticatedMode()
104+
? 'Unsupported state or unable to authenticate data'
105+
: 'Unsupported state'
106+
throw new Error(msg)
84107
}
85-
var out = this._decoder.write(value)
86-
if (final) {
87-
out += this._decoder.end()
108+
this._finalized = true
109+
110+
var data = this._final()
111+
if (encoding && encoding !== 'buffer') {
112+
this._decoder = getDecoder(this._decoder, encoding)
113+
data = this._decoder.end(data)
88114
}
89-
return out
115+
return data
116+
}
117+
118+
CipherBase.prototype._final = function (data) {
119+
throw new Error('_final is not implemented')
90120
}
121+
122+
CipherBase.prototype.setAAD = function (aadbuf) {
123+
throwIfNotBuffer(aadbuf, 'AAD')
124+
if (!this._isAuthenticatedMode() || this._finalized) throw new Error('Attempting to set AAD in unsupported state')
125+
this._setAAD(aadbuf)
126+
}
127+
128+
CipherBase.prototype._setAAD = function (aadbuf) {
129+
throw new Error('_setAAD is not implemented')
130+
}
131+
132+
CipherBase.prototype.getAuthTag = function () {
133+
// only after final and if encrypting
134+
if (this._kind !== K_CIPHER || this._authTag === null) throw new Error('Attempting to get auth tag in unsupported state')
135+
return new Buffer(this._authTag)
136+
}
137+
138+
CipherBase.prototype.setAuthTag = function (tagbuf) {
139+
if (!Buffer.isBuffer(tagbuf)) throw new TypeError('Not a buffer')
140+
if (!this._isAuthenticatedMode() || this._kind !== K_DECIPHER || this._finalized) throw new Error('Attempting to set auth tag in unsupported state')
141+
this._authTag = new Buffer(tagbuf)
142+
}
143+
144+
CipherBase.prototype.setAutoPadding = function (ap) {
145+
if (this._finalized) throw new Error('Attempting to set auto padding in unsupported state')
146+
this._setAutoPadding(!!ap)
147+
}
148+
149+
CipherBase.prototype._setAutoPadding = function (ap) {
150+
throw new Error('_setAutoPadding is not implemented')
151+
}
152+
153+
function CipherivBase (cipher, password, iv) {
154+
Transform.call(this)
155+
156+
this._kind = K_CIPHER
157+
this._authTag = null
158+
this._decoder = null
159+
this._finalized = false
160+
161+
this._initiv(toBuf(cipher, 'Cipher type'), toBuf(password, 'Password'), toBuf(iv, 'IV'))
162+
}
163+
164+
inherits(CipherivBase, Transform)
165+
166+
function DecipherBase (cipher, password, iv) {
167+
Transform.call(this)
168+
169+
this._kind = K_DECIPHER
170+
this._authTag = null
171+
this._decoder = null
172+
this._finalized = false
173+
174+
this._init(toBuf(cipher, 'Cipher type'), toBuf(password, 'Password'))
175+
}
176+
177+
inherits(DecipherBase, Transform)
178+
179+
function DecipherivBase (cipher, password, iv) {
180+
Transform.call(this)
181+
182+
this._kind = K_DECIPHER
183+
this._authTag = null
184+
this._decoder = null
185+
this._finalized = false
186+
187+
this._initiv(toBuf(cipher, 'Cipher type'), toBuf(password, 'Password'), toBuf(iv, 'IV'))
188+
}
189+
190+
inherits(DecipherivBase, Transform)

0 commit comments

Comments
 (0)