Scripts/ArcFour

From J Wiki
Jump to: navigation, search

Download the script here: File:Arc4.ijs

NB. arc4.ijs
NB. **************************************************************************
NB. arc4 (V2.0) - J (V6.01) OO implementation of Arcfour
NB.
NB. Copyright: Kym Farnik, 2006-02-17
NB. Free to use/abuse as you want.
NB. No guarantee or warantee expressed or implied.
NB. If this does anything useful, good luck!
NB. Thanks to Devon McCormick and Roger Hui for help and ideas.
NB.
NB. Update 2.0 - J6.01 (y. is now y etc)
NB.
NB. Compatible with the RC4 algorithm.
NB.  RC4 encryption/decryption, per Schneier's
NB.  "Applied Cryptography, 2nd edition".
NB.
NB. Download J from:
NB.  http://www.jsoftware.com
NB.
NB. Refer:
NB.  http://en.wikipedia.org/wiki/CipherSaber
NB.  http://ciphersaber.gurus.com/
NB.
NB. Installation:
NB.  copy 'arc4.ijs' file to J 'user/classes/' directory
NB.
NB. arc4 Notes...
NB. 1. Key can be string or numbers
NB. 2. PlainText is string
NB. 3. Result is string
NB. 4. For reasonable security follow these rules:
NB. 4.1 Only use a key once (for a single message or session) as the same
NB.     key with multiple messages can be decoded with xor !!
NB. 4.2 Key should be at least 128bits (16 items in the key list)
NB. **************************************************************************
NB.
NB.     NB. Usage and test:
NB.
NB.     require 'user/classes/arc4.ijs'    NB. load class definition
NB.
NB.     PlainText =: 'AbCdE 0123/*&^%'     NB. test string
NB.     Key =:  16b01 16b23 16b45 16b67 16b89 16bab 16bcd 16bef
NB.                                        NB. Test key (values < 256)
NB.     Expected =:  53 246 129 131 85 107 56 72 63 120 250 121 20 209 59 { a.
NB.                                        NB. Expected result string
NB.
NB.     c1 =: Key conew 'arc4'             NB. Instantiate arc4 object
NB.     Result =: encrypt__c1 PlainText
NB.
NB.     Result = Expected                  NB. Test, should return 1's (true)
NB.
NB.     NB. Decrypt is encrypt in reverse...
NB.     NB. Create a new object with key again
NB.     NB. (You may want to destroy the old one)
NB.     NB. Apply encrypt to the Result to get the PlainText
NB.
NB.     NB. If processing multiple part message or session
NB.     NB. keep applying encrypt as required.
NB.
NB.     c2 =: Key conew 'arc4'             NB. Instantiate another arc4 object
NB.     [ Decrypted =: encrypt__c2 Result  NB. Should display plain text
NB.
NB.     destroy__c1''                      NB. clean up encryption objects
NB.     destroy__c2''
NB.
NB.
NB.     NB. Cipher Saber implementation using arc4...
NB.
NB.     require 'user/classes/arc4.ijs'    NB. load class definition
NB.     require 'numeric'                  NB. We need randomize
NB.
NB.     PlainTextMessage =: 'This is my message; can you read it?'
NB.
NB.     NB. Cipher Saber Encode...
NB.
NB.     randomize''                        NB. Change the random seed
NB.     IV =: 10 ? 256                     NB. IV as 10 random bytes (0..255)
NB.     Key128 =: 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150
NB.                                        NB. test key, use your own values
NB.                                        NB.  (16 bytes = 128 bits)
NB.     c1 =: (Key128,IV) conew 'arc4'     NB. Instantiate arc4 object
NB.     CipherSaberMessage =: (IV { a.), encrypt__c1 PlainTextMessage
NB.                                        NB. Put IV as plain text on front
NB.                                        NB.   of encypted message
NB.     destroy__c1''                      NB. clean up encyrption object
NB.
NB.     NB. the CipherSaberMessage can now be written to a file etc.
NB.
NB.
NB.     NB. Cipher Saber Decode...
NB.
NB.     ExtractIV =: a. i. (i.10) { CipherSaberMessage
NB.                                        NB. Extract IV (1st ten chars)
NB.     Encoded =: (10+i.(10-~#CipherSaberMessage)){CipherSaberMessage
NB.                                        NB. Extract encoded part of message
NB.     c2 =: (Key128,IV) conew 'arc4'     NB. Instantiate arc4 object
NB.     DecodedMessage =: encrypt__c2 Encoded
NB.                                        NB. Decrypt message
NB.     destroy__c2''                      NB. clean up encyrption object
NB.     DecodedMessage = PlainTextMessage  NB. Should be 1's
NB.
NB. **************************************************************************
NB.
NB. How come I've written an essay of comments and very little code? :-)
NB.

coclass 'arc4'                             NB. Define class name

NB. Object destructor
destroy =: codestroy                       NB. Standard object destroyer

NB. Object create, takes a right parameter (y) the key
NB. Key is a list of integers < 256 up to 256 items in length
NB. Object attributes: state, i, j
create =: 3 : 0
  state =: i. 256                          NB. list of 256 integers 0..255
  s2 =. y                                 NB. Get key number list or string
  if. ' '={.0$s2 do.                       NB. If type is string then
    s2 =. a. i. s2                         NB.    make into list of numbers
  end.
  s2 =. 256 $ s2                           NB. vector 256 of the reapeting key
  i =: j =: 0                              NB. set i,j to zero
  while. i < 256 do.                       NB. Setup state vector
    j =: 256 | j + (i{ state) + i{ s2      NB. j = (j+state[i]+S2[i]) % 256
    state =: ((i,j){state) (j,i)}state     NB. Swap state [i] and [j]
    i =: >: i                              NB. Increment i
  end.
  i =: j=: 0                               NB. set i,j to zero
)
NB. end of create object


NB. a J thing, we define integer bitwise xor as...
xor =: 22 b.


NB. arc4 encrypt (and decrypt) method
NB. Right parameter y is a string to be processed
encrypt =: 3 : 0
  a =. a. i. y                             NB. string as integer list ASCII
  n =. 0                                   NB. set counter to zero
  while. n < #a do.                        NB. Traverse string
    i =: 256 | >: i                        NB. Increment i mod 256
    j =: 256 | j + i{state                 NB. next J (j = j+state[i]) % 256)
    swaps =. (i,j){state                   NB. Bytes to swap
    state =: swaps (j,i)}state             NB. store in swap order
    a =. (((256|+/swaps){state) xor n{a) n}a
                                           NB. k XOR string element[n]
    n =. >: n                              NB. Increment n
  end.
                                           NB. Result is encrypted string
  a { a.                                   NB. Convert integers to ascii
)
NB. end of encrypt

NB. end of arc4.ijs