Decode me! (Part #2 - Winter Session)

Started by newdep, December 09, 2006, 05:48:23 PM

Previous topic - Next topic

newdep

Part #2 of "Decode me"... Just to keep your brains warm during the winter...(if that winter is coming at all....)



To make it easier (because cracking this in not that easy without it)

I'll pass you the crypt code -> "norman"



...oh yes...the source code is listed below (which includes also the decoder :-)



Enjoy... Norman.









;; cerokq tur Vwxqnres cusg

(fskc aycvr (dognhv (yac pvrd (srdivzcr 97 122))))

(qckumrf (l 26) (ggsu (eckmtr nzgta -1) iywjf -1))



;; rrgiiz tur qfdrrfdfzdvau cqtgrfj rrbz l rzd l pcuunt vbuqxrf

(rvriar (fvfuea-seooqr l p)

 (hlvfh (wunq k (tzdsg izzet)) (svbu k (fvegk hlvfh))))



;; iqtheb kte pbfiqscbbuunt yskfeef tiam l nbu j cbqwes iaqsoqs

;; guwj dohgweq nrrrj m scrsugp!

(qrtzze (erhldn-qrqfpe k l)

 (gvfq i (swep x (svfjf vyvgk)))

  (poyvgk (i vyvgk)

   (uf (= l (j j)) (jqtd m ( (tzdsg izzet) (svbu i vyvgk) )))) l )



;; 'tehs zr a yrhkqr vf zfieepojq

(drsweq (lbjsi-oafr? l) (rzd (>= (puoi j) 97) (<= (cunf o) 122)))



;; qnpbrv

(pesvbv (qnpbrv)

 (pogvave (x (yrbxfh grlk))

  (uf (ybkvd-cnfs? (kqxg k))

        (pvsia

          (cijt (rrgiiz-eapcuq (trkh o) (ooqr 0)) seooqrr -1)

          (iatngs tadr -1))

          (cijt (trkh o) qnpbrvp -1)  )))



;; drpcuq

(drsweq (drpcuq)

 (dbgwdqs (k (ysestu gsof))

  (is (ycnqr-pngv? (fekg l))

        (sqgva

         (dleh (erhldn-qrqfpe (pbrv 0) (fekg l)) uqcbqsu -1)

         (dognhv ooqr -1))

         (dleh (grlk j) drpcuqd -1)  )))



;; nfy war frqiqt pbrv

(brvah "Yfgr Cbqs: ")

(jqtd pcuq (rrnr-cunr))



;; ngb roe vbggt svzv

(brvah "Oiugvaoc riyr: ")

(gvfq vatzxe (erou-xiar))



;; fvmd gus fditvbrx fvys

(jqtd gsof (ekczfpe (erou-riyr weriyr)))



;; ojw fbe oe qnpbrv ar qrqfpe

(cewef "(E)npbrv? ar (D)rpcuq?")

(is (= "r" (zfiee-pojq (cunf (iqaq-xsp))))

        (netvb (vzcbqs) (ndigr-tzxe (ncdvzd vatzxe ".raq") (aaia rbtadrq "")))

        (pvsia (qstadr) (jfzfe-svzv (mpcrbu unsvzv ".pep") (wczz drpcuqd ""))) )
-- (define? (Cornflakes))

Sleeper

#1

;; create the Vigenere list
(setq alpha (rotate (map char (sequence 97 122))))
(dotimes (x 26) (push (rotate alpha -1) vlist -1))

;; return the corresponding letters from x and y coding indexes
(define (return-encode x y)
(vlist (find x (first vlist)) (find y (first vlist))))

;; return the corresponding letters from y and x coding indexes
;; this routine needs a speedup!
(define (return-decode x y)
(setq v (find x (first vlist)))
(dolist (w vlist)
(if (= y (w v)) (setq z ( (first vlist) (find w vlist) )))) z )

;; 'true if a letter is lowercase
(define (lower-case? x) (and (>= (char x) 97) (<= (char x) 122)))

;; encode
(define (encode)
(dotimes (x (length text))
(if (lower-case? (text x))
(begin
(push (return-encode (text x) (code 0)) encoded -1)
(rotate code -1))
(push (text x) encoded -1) )))

;; decode
(define (decode)
(dotimes (x (length text))
(if (lower-case? (text x))
(begin
(push (return-decode (code 0) (text x)) decoded -1)
(rotate code -1))
(push (text x) decoded -1) )))

;; ask for secret code
(print "Your Code: ")
(setq code (read-line))

;; ask for input file
(print "Original file: ")
(setq infile (read-line))

;; read the original file
(setq text (explode (read-file infile)))

;; ask for an encode or decode
(print "(E)ncode? or (D)ecode?")
(if (= "e" (lower-case (char (read-key))))
(begin (encode) (write-file (append infile ".enc") (join encoded "")))
(begin (decode) (write-file (append infile ".dec") (join decoded ""))) )


it seems it doesn't work on my system.. am i doing something wrong?

anyway that's fun :p

newdep

#2
Wooowww...thats quick! Very very very nice, my compliments! ;-)



What brought you to the idea of that decoding type?









The listing above is already old, I have a newer version in the make..

Which is quicker and much smaller too...(ill post it when done)





How do you start the program? I tested it only under linux...

(./newlisp vinegere.lsp is what should work)





Regards, Norman.
-- (define? (Cornflakes))

newdep

#3
does thisone run for you? (run it as script)





;; create the Vigenere list

(setq alpha (rotate (map char (sequence 97 122))))

(dotimes (x (length alpha)) (push (rotate alpha -1) vlist -1))



;; return the corresponding letters from x and y coding indexes

(define (return-encode x y) (vlist (find x (first vlist)) (find y (first vlist))))



;; return the corresponding letters from y and x coding indexes

(define (return-decode x y) (setq a (find x (first vlist))) ((first vlist) (find y (map (lambda (x) (nth a x)) vlist))))



;; true if a letter is lowercase

(define (lower-case? x) (and (>= (char x) 97) (<= (char x) 122)))



;; create coded-list with encoded letter

(define (encode) (push (return-encode (text x) (code 0)) coded -1))



;; create coded-list with decoded letter

(define (decode) (push (return-decode (code 0) (text x)) coded -1))



;; encode or decode or ignore

(define (vigenere)

 (dotimes (x (length text))

  (if (lower-case? (text x))

        (begin

         (if (= input "e") (encode) (decode))

         (rotate code -1))

        (push (text x) coded -1))))



;; ask for secret code

(print "Your Code: ")

(setq code (read-line))



;; ask for input file

(print "Original file: ")

(setq infile (read-line))



;; read the original file

(setq text (explode (read-file infile)))



;; ask for an encode or decode

(print "(E)ncode? or (D)ecode?")

(if (= "e" (setq input (lower-case (char (read-key)))))

        (begin (vigenere) (write-file (append infile ".enc") (join coded "")))

        (begin (vigenere) (write-file (append infile ".dec") (join coded ""))) )



(exit)
-- (define? (Cornflakes))

cormullion

#4
Hi Norman. Very nice work. I like a good puzzle -  You should have told people to not post the answer immediately, but to post a coded reply - I nearly didn't bother when i saw that sleeper had done it immediately (smart man - well done sleeper!)...



But I forced myself not to look and to have a go anyway.... :-)



The clues were:

1: you were asking about 'rotate' recently

2: you gave us the key! :-)

3: (srdivzcr 97 122) was obviously the lower-case alphabet generated by sequence, but substitutions didn't work out

4: the first line contains "Vwxqnres" - which immediately reminded me of Vigenere...(upper-case not encoded...?)!



So I tried to write a quick decoder of a Vigenere text. Unfortunately the results didn't quite work out - getting out of step quite often. So I used some brute force to cycle through the text a few times with varying amounts of 'delay':



(set 'alphabet (map char (sequence 97 122)))
(set 'key (explode (dup "norman" 2000)))

(for (i 0 30)
(set 'counter i)
(dolist (c (explode ciphertext))
(if (find c "abcdefghijklmnopqrstuvwxyz")
(begin
(set 'a-n (find c alphabet))
(set 'k (key counter))
(set 'k-n (find k alphabet))
(set 'k1 (mod (- a-n k-n ) 26))
(print (alphabet k1)))
(begin
(print c)))
(inc 'counter)))


If you look at the resulting text in a newLISP-aware editor, all the keywords stand out:


;; rrcpgz
(qdbked (mfpphc)
(qnpkddf (y (length sbcf))
(if (hqnde-ybgi? (text u))
(begin
(dyrt (eeuxmb-decode (bkfv 0) (frxs z)) gzqbdfg -1)
(rotate obdd -1))
(dyrt (geyw x) qdyqudq -1) )))


So i could then piece together the original from those clues. Not smart, but good enough to foil the plans of Doctor Evil, given half an hour or so...



By the way, if you search google for 'vigenere newlisp' the first hit will probably be a certain blog-entry from ...

newdep

#5
Hahahah fantasic creatifity cormullion! I did not expect people to

recognize code at all ..this is great.. also the thought about my posts,

yes your right..there was someting brewing ;-) Bu that your recognized "Vinegere"

from the code was good!! but that has probably someting to do with your Blog ..hahaha (I did not know it was inthere..although I read it then..)



Im always amazed how smart people can be when it comes to de-coding contents..it must be some "old age" instinct that comes in our genes..



I like your code cracker btw ;-) nice....



PS: but i forced now create "Decode me" version #3 because we have some

pretty creative people inhere in the forum...:-)



Regards,

Norman.
-- (define? (Cornflakes))

Sleeper

#6
to solve this i found some new-lisp function names like "map" "char" "sequence" and calculated difference between char-codes.



then i found out that these differences repeat every six characters..





encoded version works fine, but looks like decodes itself with code "annorm" instead of "norman" :)

newdep

#7
Realy creative, realy! I must say I did not right away noticed that in the

coded context but I was more focused on encoding ;-) You did it very quick!

(the bigger the key, the more difficult the coding is to crack..)



The second code I posted works here fine, the 'code "norman"

is rotated after the first encoding.. overhere its correct..mmm odd...



..there is a new version on its way, which ill put on my website when its done...





PS: I created this vigenere (which is indeed upper-case as cormullion mentioned) to encrypt base64 listings.. ;-) Just so it stays readable..



Regards, Norman.
-- (define? (Cornflakes))

Sleeper

#8
Quote from: "newdep"
PS: I created this vigenere (which is indeed upper-case as cormullion mentioned) to encrypt base64 listings.. ;-) Just so it stays readable..

that's a good idea!

cormullion

#9
hey norman - have you tried a simpler method of encoding:


(set 'alphabet (map char (sequence 97 122)))
(set 'key "norman")
(set 'ciphertext (join text)) ; if it's pre-exploded...
(set 'counter 0)
(dolist (c (explode ciphertext))
  (set 'a-n (find c alphabet))
  (if a-n
      (begin
         (set 'k (key (% counter (length key))))
         (set 'k-n (find k alphabet))
         (set 'k1 (% (- a-n k-n) 26))
         (print (alphabet k1))
         (inc 'counter))
      (print c))
   )


It looks like it might be 10X faster - using modulo arithmetic on the key rather than building the table and rotating lists. Of course the table method is nice because it explains what's happening and is retro 19th century too. ;-)

newdep

#10
Nice code ! yes i was in my way of programming using the lists and then

i always stay in lists ;-) But the decode of my function was soooo slow

i moved towards a calculated rotate for decoding instead of a list find..

That was also a big performance boost... and with the tips from Lutz,

using arrays instead of lists, its quiet fast now..

(http://www.nodep.nl/downloads/newlisp/vigenere.lsp">http://www.nodep.nl/downloads/newlisp/vigenere.lsp)



..the vigenere coding is from the 16th century and cracked in 19th...irrc..

Still a very nice way to use historic material on advanced technology ;-)



Ill see if i can test you code speed here...
-- (define? (Cornflakes))

newdep

#11
Yes your code is quicker! If you remove the explode from the dolist even quicker

and if your move from lists to direct string manipulation even more quicker...



When im programming in newlisp I always have an odd habbit, i always try to

code in an "artistic way" instead of a "logical way".. Its like the language pushes

me in creating nice looking code instead of fast code..



I think i have this was of programming because i hate regex and perl and always

take to short way into "visual liguistic programming" that looks better then

first decoding the code with my mind and then let the computer decode it again..;-)



I believe if you tighten your code a little we have a very fast encode...but how quick is your decode?



Norman.
-- (define? (Cornflakes))

cormullion

#12
Does dolist evaluate explode each time? Doh - I never knew that...



Anyway, I don't really understand the algorithm but I think to decode you just change - to + in :


(set 'k1 (% (- a-n k-n) 26))

- now that's something very lisp-y you can do.



I think there's always a three-way eternal triangle at work: speed, elegance, and ease of writing - for example. It's a shame when you have to sacrifice readability and elegance for speed...but even with newLISP you have to do that sometimes...



A true master can do all three, of course!

Lutz

#13
QuoteDoes dolist evaluate explode each time?


'dolist' will evaluate the list expression only once. Nice to see this vignere program evolving into a master piece. Incorporating Corumullion's speedup suggestions it would come close.



Lutz

newdep

#14
my latest version (still with rotate) does 35650 ms. where the version of

cormullian does 43957 ms. on a 4.6 MB text file with an amd 64 3200+.

(Note: im testing my version with a read - write and a nth-set on the list

where  cormullians version is doing print to screen..not a good measurement

 between those two but they come very close....)

Still i booked over 100% thusfar..performance speed by ->





* Avoid double nested lambda functions in map, dont use map at all

* Avoid double nested find functions

* Dont use set-nth but use nth-set

* Remove boolean selects from loops

* Dont use lists but use array's instead! (this is  a flexiblity issue on you code)

* Moving to direct text manipulation without lists could be quicker..



I think thought it can just go a few bits quicker in my code but not much anymore...



ps: encoding and decoding the newlisp_manual.html takes here 4 seconds.





Norman.
-- (define? (Cornflakes))