Skip to content

Instantly share code, notes, and snippets.

@rhoot
Last active July 7, 2017 04:27
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save rhoot/3117067 to your computer and use it in GitHub Desktop.
Save rhoot/3117067 to your computer and use it in GitHub Desktop.
Node.js RC4 encryption/decryption
###
Copyright (c) 2012 rhoot <https://github.com/rhoot>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
###
###
Sample usage:
rc4 = require 'rc4'
engine = new rc4.Engine()
# Encrypt 'Plaintext' with key 'Key'.
# 'encrypted' contains a node.js Buffer with the results
engine.init 'Key'
encrypted = engine.encrypt 'Plaintext'
# Encryption also works on byte arrays and node.js Buffer objects
# This would give the same results as the above
engine.init [ 0x4b, 0x65, 0x79 ]
encrypted = engine.encrypt new Buffer([ 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74 ])
# Decrypting is just as easy 'Attack at dawn' with key 'Secret'
engine.init 'Secret'
message = [ 0x45, 0xA0, 0x1F, 0x64, 0x5F, 0xC3, 0x5B, 0x38, 0x35, 0x52, 0x54, 0x4B, 0x9B, 0xF5 ]
decrypted = engine.decrypt(message).toString()
# Some encrypted messages require dropping the first x bytes of the keystream.
engine.init 'Key'
engine.drop 3072
decrypted = engine.decrypt [ 0x36, 0x49, 0xbe, 0xa0, 0xdf, 0xb1, 0xd3, 0xcd, 0x3f ]
###
isArrayIsh = (obj) ->
Array.isArray(obj) or
Buffer.isBuffer(obj) or
(obj? and typeof obj is 'object' and typeof obj.length is 'number')
stringToArray = (str) ->
str.charCodeAt i for i in [0...str.length]
class Rc4Engine
# @public
constructor: (key) ->
@state = new Array 256
@i1 = 0
@i2 = 0
@init key if key?
# @private
swap = (state, i1, i2) ->
temp = state[i1]
state[i1] = state[i2]
state[i2] = temp
# @private
step = (e) ->
e.i1 = (e.i1 + 1) & 255
e.i2 = (e.i2 + e.state[e.i1]) & 255
swap e.state, e.i1, e.i2
# @public
init: (key) ->
key = stringToArray key if typeof key is 'string'
throw new TypeError 'Invalid key type' if not isArrayIsh key
@state = [0...256]
@i1 = 0
@i2 = 0
j = 0
for i in [0...256]
j = (j + @state[i] + key[i % key.length]) & 255
swap @state, i, j
# @public
drop: (num) ->
throw new TypeError 'Invalid num argument.' unless typeof num is 'number'
step this for i in [0...num]
# @public
encrypt: (bytes) ->
bytes = stringToArray bytes if typeof bytes is 'string'
throw new TypeError 'Invalid data type.' if not isArrayIsh bytes
encrypted = new Buffer bytes.length
for i in [0...bytes.length]
step this
key = @state[(@state[@i1] + @state[@i2]) & 0xff]
encrypted[i] = bytes[i] ^ key
encrypted
# @public
decrypt: (bytes) ->
# RC4 encryption and decryption algorithms are exactly the same
@encrypt bytes
module.exports =
Engine: Rc4Engine
@vodolaz095
Copy link

Can you write this module without coffer script in raw javascript or explain, how to convert it onto javascript

Copy link

ghost commented Jul 7, 2017

@vodolaz095 I will convert it soon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment