Skip to content

Commit

Permalink
first
Browse files Browse the repository at this point in the history
  • Loading branch information
calvinmetcalf committed Sep 26, 2015
0 parents commit 8fbd9e7
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["standard"]
}
71 changes: 71 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
var Transform = require('stream').Transform
var inherits = require('inherits')
var StringDecoder = require('string_decoder').StringDecoder
module.exports = CipherBase
inherits(CipherBase, Transform)
function CipherBase (hashMode) {
Transform.call(this)
this.hashMode = typeof hashMode === 'string';
if (this.hashMode) {
this[hashMode] = this._finalOrDigest
} else {
this.final = this._finalOrDigest
}
this._decoder = null
this._encoding = null
}
CipherBase.prototype.update = function (data, inputEnc, outputEnc) {
if (typeof data === 'string') {
data = new Buffer(data, inputEnc)
}
var outData = this._update(data)
if (this.hashMode) {
return this
}
if (outputEnc) {
outData = this._toString(outData, outputEnc)
}
return outData
}
CipherBase.prototype._transform = function (data, _, next) {
var err
try {
this.push(this._update(data))
} catch (e) {
err = e
} finally {
next(err)
}
}
CipherBase.prototype._flush = function (done) {
var err
try {
this.push(this._final())
} catch (e) {
err = e
} finally {
done(err)
}
}
CipherBase.prototype._finalOrDigest = function (outputEnc) {
var outData = this._final() || new Buffer('')
if (outputEnc) {
outData = this._toString(outData, outputEnc, true)
}
return outData
}

CipherBase.prototype._toString = function (value, enc, final) {
if (!this._decoder) {
this._decoder = new StringDecoder(enc)
this._encoding = enc
}
if (this._encoding !== enc) {
throw new Error('can\'t switch encodings')
}
var out = this._decoder.write(value)
if (final) {
out += this._decoder.end()
}
return out
}
30 changes: 30 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "cipher-base",
"version": "1.0.0",
"description": "abstract base class for crypto-streams",
"main": "index.js",
"scripts": {
"test": "node test.js | tspec"
},
"repository": {
"type": "git",
"url": "git+https://github.com/crypto-browserify/cipher-base.git"
},
"keywords": [
"cipher",
"stream"
],
"author": "Calvin Metcalf <[email protected]>",
"license": "MIT",
"bugs": {
"url": "https://github.com/crypto-browserify/cipher-base/issues"
},
"homepage": "https://github.com/crypto-browserify/cipher-base#readme",
"dependencies": {
"inherits": "^2.0.1"
},
"devDependencies": {
"tap-spec": "^4.1.0",
"tape": "^4.2.0"
}
}
15 changes: 15 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cipher-base
===

Abstract base class to inherit from if you want to create streams implementing
the same api as node crypto streams.

Requires you to implement 2 methods `_final` and `_update`. `_final` takes a
buffer and should return a buffer, `_final` takes no arguments and should return
a buffer.


The constructor takes one argument and that is a string which if present switches
it into hash mode, i.e. the object you get from crypto.createHash or
crypto.createSign, this switches the name of the final method to be the string
you passed instead of `final` and returns `this` from update.
83 changes: 83 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
var test = require('tape')
var CipherBase = require('./')
var inherits = require('inherits')

test('basic version', function (t) {
inherits(Cipher, CipherBase)
function Cipher () {
CipherBase.call(this)
}
Cipher.prototype._update = function (input) {
t.ok(Buffer.isBuffer(input))
return input
}
Cipher.prototype._final = function () {
// noop
}
var cipher = new Cipher()
var utf8 = 'abc123abcd'
var update = cipher.update(utf8, 'utf8', 'base64') + cipher.final('base64')
var string = (new Buffer(update, 'base64')).toString()
t.equals(utf8, string)
t.end()
})
test('hash mode', function (t) {
inherits(Cipher, CipherBase)
function Cipher () {
CipherBase.call(this, 'finalName')
this._cache = []
}
Cipher.prototype._update = function (input) {
t.ok(Buffer.isBuffer(input))
this._cache.push(input)
}
Cipher.prototype._final = function () {
return Buffer.concat(this._cache)
}
var cipher = new Cipher()
var utf8 = 'abc123abcd'
var update = cipher.update(utf8, 'utf8').finalName('base64')
var string = (new Buffer(update, 'base64')).toString()

t.equals(utf8, string)
t.end()
})
test('encodings', function (t) {
inherits(Cipher, CipherBase)
function Cipher () {
CipherBase.call(this)
}
Cipher.prototype._update = function (input) {
return input
}
Cipher.prototype._final = function () {
// noop
}
t.test('mix and match encoding', function (t) {
t.plan(2)

var cipher = new Cipher()
cipher.update('foo', 'utf8', 'utf8')
t.throws(function () {
cipher.update('foo', 'utf8', 'base64')
})
cipher = new Cipher()
cipher.update('foo', 'utf8', 'base64')
t.doesNotThrow(function () {
cipher.update('foo', 'utf8')
cipher.final('base64')
})
})
t.test('handle long uft8 plaintexts', function (t) {
t.plan(1)
var txt = 'ふっかつ あきる すぶり はやい つける まゆげ たんさん みんぞく ねほりはほり せまい たいまつばな ひはん'

var cipher = new Cipher()
var decipher = new Cipher()
var enc = decipher.update(cipher.update(txt, 'utf8', 'base64'), 'base64', 'utf8')
enc += decipher.update(cipher.final('base64'), 'base64', 'utf8')
enc += decipher.final('utf8')

t.equals(txt, enc)
})
})

0 comments on commit 8fbd9e7

Please sign in to comment.