Permalink
Browse files

Support `rc4-md5` cipher.

  • Loading branch information...
mrluanma committed Jan 24, 2015
1 parent 38e24ac commit 882f62153d84615e7d529e8f2eca44fb9dad318f
Showing with 231 additions and 37 deletions.
  1. +1 −1 LICENSE
  2. +5 −17 README.md
  3. +1 −1 config.json
  4. +122 −9 encrypt.js
  5. +102 −9 src/encrypt.coffee
View
@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2014 Zhao Xiaohong
Copyright (c) 2012 clowwindy
Copyright (c) 2012-2014 clowwindy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
View
@@ -174,29 +174,17 @@ Supported Ciphers
-----------------
- rc4
- rc4-md5
- table
- bf-cfb
- rc2-cfb
- des-cfb
- rc2-cfb
- idea-cfb
- seed-cfb
- cast5-cfb
- aes-256-cfb
- aes-128-cfb
- aes-192-cfb
- aes-256-ofb
- aes-128-ofb
- aes-192-ofb
- aes-128-ctr
- aes-192-ctr
- aes-256-ctr
- salsa20-ctr
- aes-128-cfb8
- aes-192-cfb8
- aes-256-cfb8
- aes-128-cfb1
- aes-192-cfb1
- aes-256-cfb1
- camellia-128-cfb
- camellia-192-cfb
- aes-256-cfb
- camellia-256-cfb
- camellia-192-cfb
- camellia-128-cfb
View
@@ -6,5 +6,5 @@
"remote_port": 8080,
"password": "`try*(^^$some^$%^complex>:<>?~password/",
"timeout": 600,
"method": "rc4"
"method": "rc4-md5"
}
View

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
View
@@ -35,33 +35,126 @@ getTable = (key) ->
cachedTables[key] = result
result
encrypt = (table, buf) ->
substitute = (table, buf) ->
i = 0
while i < buf.length
buf[i] = table[buf[i]]
i++
buf
bytes_to_key_results = {}
EVP_BytesToKey = (password, key_len, iv_len) ->
if bytes_to_key_results["#{password}:#{key_len}:#{iv_len}"]
return bytes_to_key_results["#{password}:#{key_len}:#{iv_len}"]
m = []
i = 0
count = 0
while count < key_len + iv_len
md5 = crypto.createHash('md5')
data = password
if i > 0
data = Buffer.concat([m[i - 1], password])
md5.update(data)
d = md5.digest()
m.push(d)
count += d.length
i += 1
ms = Buffer.concat(m)
key = ms.slice(0, key_len)
iv = ms.slice(key_len, key_len + iv_len)
bytes_to_key_results[password] = [key, iv]
return [key, iv]
method_supported =
'aes-128-cfb': [16, 16]
'aes-192-cfb': [24, 16]
'aes-256-cfb': [32, 16]
'bf-cfb': [16, 8]
'camellia-128-cfb': [16, 16]
'camellia-192-cfb': [24, 16]
'camellia-256-cfb': [32, 16]
'cast5-cfb': [16, 8]
'des-cfb': [8, 8]
'idea-cfb': [16, 8]
'rc2-cfb': [16, 8]
'rc4': [16, 0]
'rc4-md5': [16, 16]
'seed-cfb': [16, 16]
create_rc4_md5_cipher = (key, iv, op) ->
md5 = crypto.createHash('md5')
md5.update(key)
md5.update(iv)
rc4_key = md5.digest()
if op == 1
return crypto.createCipheriv('rc4', rc4_key, '')
else
return crypto.createDecipheriv('rc4', rc4_key, '')
class Encryptor
constructor: (key, @method) ->
constructor: (@key, @method) ->
@iv_sent = false
if @method == 'table'
@method = null
if @method?
@cipher = crypto.createCipher @method, key
@decipher = crypto.createDecipher @method, key
@cipher = @get_cipher(@key, @method, 1, crypto.randomBytes(32))
else
[@encryptTable, @decryptTable] = getTable(key)
[@encryptTable, @decryptTable] = getTable(@key)
get_cipher_len: (method) ->
method = method.toLowerCase()
m = method_supported[method]
return m
get_cipher: (password, method, op, iv) ->
method = method.toLowerCase()
password = new Buffer(password, 'binary')
m = @get_cipher_len(method)
if m?
[key, iv_] = EVP_BytesToKey(password, m[0], m[1])
if not iv?
iv = iv_
if op == 1
@cipher_iv = iv.slice(0, m[1])
iv = iv.slice(0, m[1])
if method == 'rc4-md5'
return create_rc4_md5_cipher(key, iv, op)
else
if op == 1
return crypto.createCipheriv(method, key, iv)
else
return crypto.createDecipheriv(method, key, iv)
encrypt: (buf) ->
if @method?
@cipher.update(buf)
result = @cipher.update buf
if @iv_sent
return result
else
@iv_sent = true
return Buffer.concat([@cipher_iv, result])
else
encrypt @encryptTable, buf
substitute @encryptTable, buf
decrypt: (buf) ->
if @method?
@decipher.update(buf)
if not @decipher?
decipher_iv_len = @get_cipher_len(@method)[1]
decipher_iv = buf.slice(0, decipher_iv_len)
@decipher = @get_cipher(@key, @method, 0, decipher_iv)
result = @decipher.update(buf.slice(decipher_iv_len))
return result
else
result = @decipher.update(buf)
return result
else
encrypt @decryptTable, buf
substitute @decryptTable, buf
exports.Encryptor = Encryptor
exports.getTable = getTable

0 comments on commit 882f621

Please sign in to comment.