decrypter.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. var aes = require('./aes')
  2. var Transform = require('cipher-base')
  3. var inherits = require('inherits')
  4. var modes = require('./modes')
  5. var StreamCipher = require('./streamCipher')
  6. var AuthCipher = require('./authCipher')
  7. var ebtk = require('evp_bytestokey')
  8. inherits(Decipher, Transform)
  9. function Decipher (mode, key, iv) {
  10. if (!(this instanceof Decipher)) {
  11. return new Decipher(mode, key, iv)
  12. }
  13. Transform.call(this)
  14. this._cache = new Splitter()
  15. this._last = void 0
  16. this._cipher = new aes.AES(key)
  17. this._prev = new Buffer(iv.length)
  18. iv.copy(this._prev)
  19. this._mode = mode
  20. this._autopadding = true
  21. }
  22. Decipher.prototype._update = function (data) {
  23. this._cache.add(data)
  24. var chunk
  25. var thing
  26. var out = []
  27. while ((chunk = this._cache.get(this._autopadding))) {
  28. thing = this._mode.decrypt(this, chunk)
  29. out.push(thing)
  30. }
  31. return Buffer.concat(out)
  32. }
  33. Decipher.prototype._final = function () {
  34. var chunk = this._cache.flush()
  35. if (this._autopadding) {
  36. return unpad(this._mode.decrypt(this, chunk))
  37. } else if (chunk) {
  38. throw new Error('data not multiple of block length')
  39. }
  40. }
  41. Decipher.prototype.setAutoPadding = function (setTo) {
  42. this._autopadding = !!setTo
  43. return this
  44. }
  45. function Splitter () {
  46. if (!(this instanceof Splitter)) {
  47. return new Splitter()
  48. }
  49. this.cache = new Buffer('')
  50. }
  51. Splitter.prototype.add = function (data) {
  52. this.cache = Buffer.concat([this.cache, data])
  53. }
  54. Splitter.prototype.get = function (autoPadding) {
  55. var out
  56. if (autoPadding) {
  57. if (this.cache.length > 16) {
  58. out = this.cache.slice(0, 16)
  59. this.cache = this.cache.slice(16)
  60. return out
  61. }
  62. } else {
  63. if (this.cache.length >= 16) {
  64. out = this.cache.slice(0, 16)
  65. this.cache = this.cache.slice(16)
  66. return out
  67. }
  68. }
  69. return null
  70. }
  71. Splitter.prototype.flush = function () {
  72. if (this.cache.length) {
  73. return this.cache
  74. }
  75. }
  76. function unpad (last) {
  77. var padded = last[15]
  78. var i = -1
  79. while (++i < padded) {
  80. if (last[(i + (16 - padded))] !== padded) {
  81. throw new Error('unable to decrypt data')
  82. }
  83. }
  84. if (padded === 16) {
  85. return
  86. }
  87. return last.slice(0, 16 - padded)
  88. }
  89. var modelist = {
  90. ECB: require('./modes/ecb'),
  91. CBC: require('./modes/cbc'),
  92. CFB: require('./modes/cfb'),
  93. CFB8: require('./modes/cfb8'),
  94. CFB1: require('./modes/cfb1'),
  95. OFB: require('./modes/ofb'),
  96. CTR: require('./modes/ctr'),
  97. GCM: require('./modes/ctr')
  98. }
  99. function createDecipheriv (suite, password, iv) {
  100. var config = modes[suite.toLowerCase()]
  101. if (!config) {
  102. throw new TypeError('invalid suite type')
  103. }
  104. if (typeof iv === 'string') {
  105. iv = new Buffer(iv)
  106. }
  107. if (typeof password === 'string') {
  108. password = new Buffer(password)
  109. }
  110. if (password.length !== config.key / 8) {
  111. throw new TypeError('invalid key length ' + password.length)
  112. }
  113. if (iv.length !== config.iv) {
  114. throw new TypeError('invalid iv length ' + iv.length)
  115. }
  116. if (config.type === 'stream') {
  117. return new StreamCipher(modelist[config.mode], password, iv, true)
  118. } else if (config.type === 'auth') {
  119. return new AuthCipher(modelist[config.mode], password, iv, true)
  120. }
  121. return new Decipher(modelist[config.mode], password, iv)
  122. }
  123. function createDecipher (suite, password) {
  124. var config = modes[suite.toLowerCase()]
  125. if (!config) {
  126. throw new TypeError('invalid suite type')
  127. }
  128. var keys = ebtk(password, false, config.key, config.iv)
  129. return createDecipheriv(suite, keys.key, keys.iv)
  130. }
  131. exports.createDecipher = createDecipher
  132. exports.createDecipheriv = createDecipheriv