Sorry there was a minor typo in the last script, use this one instead!

 

rebol[
title: "String Encryption/Decryption Function (cipher)"
version: 0.1.0
author: "alan parman"
email: [EMAIL PROTECTED]
comment: {This encryption is only as good as your passphrase.  Your passphrase may be upto 246 characters. The longer the passphrase, stronger the encryption}
]

cipher: func [{Candidate Function to encrypt/decrypt a string.
 Uses CipherSaber (copyright Arnold Reinhold), a version of ARC4}
string [string!] "string to en-decrypt"
/decrypt "decrypt the string"
/pass "supply a passphrase without being prompted"
supplied-pass [string!]  "pre-supplied passphrase"
/local passphrase initvector plaintextlength
][
; this function both encrypts and decrypts, for the purposes of this function what goes in is plaintext what comes out is ciphertext
;regardless if you are encrypting or decrypting

;series swap, define a swapping function, needed for encryption engine*******
s-swap: func ["swaps the elements of two series at the given index positions"
 a [series!] {1st series}
 index-a [integer!] {index position to swap in 1st series}
 b [series!] {2nd series}
 index-b [integer!] {index position to swap in 2nd series}
 /local holder
] [
 holder: pick a index-a
 poke a index-a pick b index-b
 poke b index-b holder
]

;***** begin true works of function here

either decrypt [
 plaintext: decompress load string
] [
 plaintext: string
]

 ;*****make or extract initvector,  then set plaintext length
 initvector: make block! 10
 either decrypt  [
  for n 1 10 1 [
   append initvector to-char (pick plaintext n)
  ]
  remove/part plaintext 10
 ] [
  random/seed to-integer checksum/secure form now ; reduces chances of deciphering the date from initvector
  loop 10 [
   append initvector to-char ((random 256) - 1) ;REBOL's random does 1 to N
  ]
 ]

 plaintextlength: length? plaintext

 ;*****get passphrase
 either pass [
  passphrase: supplied-pass
 ][
  passphrase: ""
 ]

 while [any [
  (length? passphrase) > 246
  passphrase = ""
  ]
 ][
  if (length? passphrase) > 246 [print "Passphrase must be 246 characters or less"]
  passphrase: ask/hide "passphrase :>> "
 ]

 ;*****make key
 key: make block! []
 foreach letter passphrase [
  append key letter
 ]
 append key initvector
 keylength: length? key

 ;*****make state, a block from 0 to 255, in order
 state: make block! 256
 for i 0 255 1 [append state i]

 ;*****mix state
 ;*******try a cs2 type addition, mixing 3 times
 for number 1 3 1 [
  j: 0 ; remember do 0 to 255, not 1 to 256
  ;i will index state i.e. each element is state(i)
  ;n is the index to cycle thru the key (i modulo keylength)
  ;j is the "randomly" choosen element of state

  for i 0 255 1 [; must add + 1 to index i as the arrays are accessed 1 2 3 ... 256
   ;i.e. first element "0" is element 1 not element 0
   n: i // keylength

   state-i: to-integer pick state (i + 1)
   key-n: to-integer pick key (n + 1)

   j: (j + state-i + key-n) // 256

   s-swap state (i + 1) state (j + 1)

  ] ;end of for
 ] ;***** end of 'for' of cs2 addition

 ;***** produce the ciphertext
 i: j: n: 0

 ciphertext: make block! [] ; contents of file going out

 if (not decrypt) [
  append ciphertext initvector
 ]

 for count 0 (plaintextlength - 1) 1 [
  i: ((count + 1) // 256) ; this "+1" is shown, but not clearly, on the instructions
  ; this is _not_ an indexing adjustment, it is an integral part of the ciphersaber process

  state-i: pick state (i + 1)

  j: ((j + state-i) // 256)

  s-swap state (i + 1) state (j + 1)

  n: (((pick state (i + 1)) + (pick state (j + 1))) // 256)

  append ciphertext  (xor (to-char pick state (n + 1)) (to-char pick plaintext (count + 1)))

 ] ;end of for


 either decrypt [
  ciphertext:  to-string ciphertext  
 ][
  ciphertext: form compress to-string ciphertext
 ]
unset [plaintext]
return ciphertext

] ; end cipher

Reply via email to