Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › Programming Challenge #10: Fun with cryptography
New Posts  All Forums:Forum Nav:

Programming Challenge #10: Fun with cryptography - Page 2

post #11 of 36
The real challenge is for someone to use all the individual words here to piece together the original without decoding. I was a little disappointed you didn't use ROT13.

Here's the easy challenge as a one-liner using scheme.

word 25 = "Orbiting" Source Scheme (Click to show)
Code:
;;our string
(define encrypted "Gbs!pvu!jo!uif!vodibsufe!cbdlxbufst!pg!uif!vogbtijpobcmf!foe!pg!uif!xftufso!tqjsbm!bsn!pg!uif!Hbmbyz!mjft!b!tnbmm!vosfhbsefe!zfmmpx!tvo/!Pscjujoh!uijt!bu!b!ejtubodf!pg!spvhimz!ojofuz.uxp!njmmjpo!njmft!jt!bo!vuufsmz!jotjhojgjdbou!mjuumf!cmvf!hsffo!qmbofu!xiptf!bqf.eftdfoefe!mjgf!gpsnt!bsf!tp!bnb{johmz!qsjnjujwf!uibu!uifz!tujmm!uijol!ejhjubm!xbudift!bsf!b!qsfuuz!ofbu!jefb/")
;;get string-map. It's not needed, but is faster than the normal map function
(require (lib "string.ss" "srfi" "13"))
;;our one-liner. Note that 'λ' is syntactically equal to 'lambda'
(string-map (λ (x) (integer->char (- (char->integer x) 1))) encrypted)

Easy in Javascript using a recursive function Source Javascript (Click to show)
Code:
//(you can use ctrl-shift-i in chrome or FF and copy-paste into the console to test)
var encrypted = "Gbs!pvu!jo!uif!vodibsufe!cbdlxbufst!pg!uif!vogbtijpobcmf!foe!pg!uif!xftufso!tqjsbm!bsn!pg!uif!Hbmbyz!mjft!b!tnbmm!vosfhbsefe!zfmmpx!tvo/!Pscjujoh!uijt!bu!b!ejtubodf!pg!spvhimz!ojofuz.uxp!njmmjpo!njmft!jt!bo!vuufsmz!jotjhojgjdbou!mjuumf!cmvf!hsffo!qmbofu!xiptf!bqf.eftdfoefe!mjgf!gpsnt!bsf!tp!bnb{johmz!qsjnjujwf!uibu!uifz!tujmm!uijol!ejhjubm!xbudift!bsf!b!qsfuuz!ofbu!jefb/";
//self-executing lambda so I don't pollute the global namespace
(function (str) {
    //Kids, pay attention. Real recursion like this can overflow very easily. If this string were a few thousand characters, it would crash.
    var recurse = function (str) {
        if (str.length) {
            //JS really starts to look a lot like bad scheme code when you nest stuff
            return (String.fromCharCode(str.charCodeAt(0) - 1) + recurse(str.slice(1)));
        } else {
            return "";
        }
    };
    return recurse(str);
}(encrypted));

Medium challenge in scheme (also a one-liner).
word 25 = "the" Source Scheme (Click to show)
Code:
;;get our string
(define encrypted "55-69-66-21-49-6a-75-64-69-2e-49-6a-6c-66-73-28-74-21-48-76-6a-65-66-21-75-70-21-75-69-66-21-48-62-6d-62-79-7a-21-62-6d-74-70-21-6e-66-6f-75-6a-70-6f-74-21-62-6d-64-70-69-70-6d-2f-21-4a-75-21-74-62-7a-74-21-75-69-62-75-21-75-69-66-21-63-66-74-75-21-65-73-6a-6f-6c-21-6a-6f-21-66-79-6a-74-75-66-6f-64-66-21-6a-74-21-75-69-66-21-51-62-6f-21-48-62-6d-62-64-75-6a-64-21-48-62-73-68-6d-66-21-43-6d-62-74-75-66-73-2d-21-75-69-66-21-66-67-67-66-64-75-21-70-67-21-78-69-6a-64-69-21-6a-74-21-6d-6a-6c-66-21-69-62-77-6a-6f-68-21-7a-70-76-73-21-63-73-62-6a-6f-74-21-74-6e-62-74-69-66-65-21-70-76-75-21-78-6a-75-69-21-62-21-74-6d-6a-64-66-21-70-67-21-6d-66-6e-70-6f-21-78-73-62-71-71-66-65-21-73-70-76-6f-65-21-62-21-6d-62-73-68-66-21-68-70-6d-65-21-63-73-6a-64-6c-2f")
;;another one-liner. No need to import a string library since this map is built-in.
;;Note that string-split is actually from racket, but should be in R7RS-Large as well
(list->string (map (λ (str) (integer->char (- (string->number str 16) 1))) (string-split encrypted "-")))

Hard Challenge in Scheme recursively and a long one-liner
word 25 = "people" Warning: Spoiler! (Click to show)
Code:
(define encrypted "93e1d3d7a8c5dfcde759b5dad0e3a0b89881e2a1b58cd0dca5c98cd5d6a2bed381e2a1b1e081e59ebee081e2a1c2dbd6d5a170e0c9d359bdd5cfd259bfd281e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48e9ac38ccae259b6d1cdda59c7cdd48e88b88ccfdd6570dad0e259b1d3c2d7a77e8caecfa7c98cd1d3a8c0d8c68ea1b1e2c68eacc0d1c4e3a5b1e0c6d259c4d4c2e259b9d281e59e70d7cfd3b070d1d9cf9cc4d8da8eb0b8e581e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48ea1b1d081e2a1bfe1c8d6ad70e0c9cfad70e3c68eb0bfe1cdd259bbdad0e559b18ccdddad70d9d0e09e70cdc3ddaec48cd5d69e70dac2e2aec2d181dd9f70e0c9d359a5dacae49ec2dfc68eadb8cdcf8eb0b58cc5dd59bedbd89c")


(define (sym-decrypt str key)
  (let ((hex-str (regexp-match* #rx".." str))
        (key-len (string-length key)))
    (define (decrypt-rec hex-str key key-len cnt)
      (cond ((empty? hex-str) '())
            (else
             (cons (integer->char (- (string->number (car hex-str) 16)
                                     (char->integer (string-ref key cnt))))
                   (decrypt-rec (cdr hex-str) key key-len (if (< cnt key-len) (+ 1 cnt) 0))))))
    (list->string (decrypt-rec hex-str key (- key-len 1) 0))))
;;The closest I've gotten to a one-liner
(list->string (let ((i -1)) (map (λ (x) (set! i (+ 1 i)) (integer->char (- (string->number x 16) (char->integer (string-ref "Plan9" (modulo len 5)))))) (regexp-match* #rx".." encrypted))))
;;renaming some funcs takes it closer to one-line territory
(lst2str (let ((i -1)) (map (λ (x) (set! i (+ 1 i)) (int2char (- (str2num x 16) (char2int (str-ref "Plan9" (% len 5)))))) (regexp-match* #rx".." encrypted))))


Edited by hajile - 4/11/14 at 8:05am
post #12 of 36
Quote:
Originally Posted by hajile View Post

The real challenge is for someone to use all the individual words here to piece together the original without decoding. I was a little disappointed you didn't use ROT13.

Here's the easy challenge as a one-liner using scheme.

word 25 = "Orbiting" Source Scheme (Click to show)
Code:
;;our string
(define encrypted "Gbs!pvu!jo!uif!vodibsufe!cbdlxbufst!pg!uif!vogbtijpobcmf!foe!pg!uif!xftufso!tqjsbm!bsn!pg!uif!Hbmbyz!mjft!b!tnbmm!vosfhbsefe!zfmmpx!tvo/!Pscjujoh!uijt!bu!b!ejtubodf!pg!spvhimz!ojofuz.uxp!njmmjpo!njmft!jt!bo!vuufsmz!jotjhojgjdbou!mjuumf!cmvf!hsffo!qmbofu!xiptf!bqf.eftdfoefe!mjgf!gpsnt!bsf!tp!bnb{johmz!qsjnjujwf!uibu!uifz!tujmm!uijol!ejhjubm!xbudift!bsf!b!qsfuuz!ofbu!jefb/")
;;get string-map. It's not needed, but is faster than the normal map function
(require (lib "string.ss" "srfi" "13"))
;;our one-liner. Note that 'λ' is syntactically equal to 'lambda'
(string-map (λ (x) (integer->char (- (char->integer x) 1))) encrypted)

Easy in Javascript using a recursive function Source Javascript (Click to show)
Code:
//(you can use ctrl-shift-i in chrome or FF and copy-paste into the console to test)
var encrypted = "Gbs!pvu!jo!uif!vodibsufe!cbdlxbufst!pg!uif!vogbtijpobcmf!foe!pg!uif!xftufso!tqjsbm!bsn!pg!uif!Hbmbyz!mjft!b!tnbmm!vosfhbsefe!zfmmpx!tvo/!Pscjujoh!uijt!bu!b!ejtubodf!pg!spvhimz!ojofuz.uxp!njmmjpo!njmft!jt!bo!vuufsmz!jotjhojgjdbou!mjuumf!cmvf!hsffo!qmbofu!xiptf!bqf.eftdfoefe!mjgf!gpsnt!bsf!tp!bnb{johmz!qsjnjujwf!uibu!uifz!tujmm!uijol!ejhjubm!xbudift!bsf!b!qsfuuz!ofbu!jefb/";
//self-executing lambda so I don't pollute the global namespace
(function (str) {
    //Kids, pay attention. Real recursion like this can overflow very easily. If this string were a few thousand characters, it would crash.
    var recurse = function (str) {
        if (str.length) {
            //JS really starts to look a lot like bad scheme code when you nest stuff
            return (String.fromCharCode(str.charCodeAt(0) - 1) + recurse(str.slice(1)));
        } else {
            return "";
        }
    };
    return recurse(str);
}(encrypted));

Medium challenge in scheme (also a one-liner).
word 25 = "the" Source Scheme (Click to show)
Code:
;;get our string
(define encrypted "55-69-66-21-49-6a-75-64-69-2e-49-6a-6c-66-73-28-74-21-48-76-6a-65-66-21-75-70-21-75-69-66-21-48-62-6d-62-79-7a-21-62-6d-74-70-21-6e-66-6f-75-6a-70-6f-74-21-62-6d-64-70-69-70-6d-2f-21-4a-75-21-74-62-7a-74-21-75-69-62-75-21-75-69-66-21-63-66-74-75-21-65-73-6a-6f-6c-21-6a-6f-21-66-79-6a-74-75-66-6f-64-66-21-6a-74-21-75-69-66-21-51-62-6f-21-48-62-6d-62-64-75-6a-64-21-48-62-73-68-6d-66-21-43-6d-62-74-75-66-73-2d-21-75-69-66-21-66-67-67-66-64-75-21-70-67-21-78-69-6a-64-69-21-6a-74-21-6d-6a-6c-66-21-69-62-77-6a-6f-68-21-7a-70-76-73-21-63-73-62-6a-6f-74-21-74-6e-62-74-69-66-65-21-70-76-75-21-78-6a-75-69-21-62-21-74-6d-6a-64-66-21-70-67-21-6d-66-6e-70-6f-21-78-73-62-71-71-66-65-21-73-70-76-6f-65-21-62-21-6d-62-73-68-66-21-68-70-6d-65-21-63-73-6a-64-6c-2f")
;;another one-liner. No need to import a string library since this map is built-in.
;;Note that string-split is actually from racket, but should be in R7RS-Large as well
(list->string (map (λ (str) (integer->char (- (string->number str 16) 1))) (string-split encrypted "-")))

I'll have to wait a while on the hard challenge

I like the one-liners idea, it was more of a challenge playing that way.

easy, medium and hard all with one-liners Source python2.7 (Click to show)
Code:

easy

print "".join([chr(ord(a)-1) for a in 'Gbs!pvu!jo!uif!vodibsufe!cbdlxbufst!pg!uif!vogbtijpobcmf!foe!pg!uif!xftufso!tqjsbm!bsn!pg!uif!Hbmbyz!mjft!b!tnbmm!vosfhbsefe!zfmmpx!tvo/!Pscjujoh!uijt!bu!b!ejtubodf!pg!spvhimz!ojofuz.uxp!njmmjpo!njmft!jt!bo!vuufsmz!jotjhojgjdbou!mjuumf!cmvf!hsffo!qmbofu!xiptf!bqf.eftdfoefe!mjgf!gpsnt!bsf!tp!bnb{johmz!qsjnjujwf!uibu!uifz!tujmm!uijol!ejhjubm!xbudift!bsf!b!qsfuuz!ofbu!jefb/'])

medium

print "".join([chr(ord(a.decode('hex')) - 1) for a in '55-69-66-21-49-6a-75-64-69-2e-49-6a-6c-66-73-28-74-21-48-76-6a-65-66-21-75-70-21-75-69-66-21-48-62-6d-62-79-7a-21-62-6d-74-70-21-6e-66-6f-75-6a-70-6f-74-21-62-6d-64-70-69-70-6d-2f-21-4a-75-21-74-62-7a-74-21-75-69-62-75-21-75-69-66-21-63-66-74-75-21-65-73-6a-6f-6c-21-6a-6f-21-66-79-6a-74-75-66-6f-64-66-21-6a-74-21-75-69-66-21-51-62-6f-21-48-62-6d-62-64-75-6a-64-21-48-62-73-68-6d-66-21-43-6d-62-74-75-66-73-2d-21-75-69-66-21-66-67-67-66-64-75-21-70-67-21-78-69-6a-64-69-21-6a-74-21-6d-6a-6c-66-21-69-62-77-6a-6f-68-21-7a-70-76-73-21-63-73-62-6a-6f-74-21-74-6e-62-74-69-66-65-21-70-76-75-21-78-6a-75-69-21-62-21-74-6d-6a-64-66-21-70-67-21-6d-66-6e-70-6f-21-78-73-62-71-71-66-65-21-73-70-76-6f-65-21-62-21-6d-62-73-68-66-21-68-70-6d-65-21-63-73-6a-64-6c-2f'.split("-")])

hard

print ''.join([chr(ord(a.decode('hex')) - ord('Plan9'[b%5])) for b,a in enumerate(map(''.join, zip(* [iter('93e1d3d7a8c5dfcde759b5dad0e3a0b89881e2a1b58cd0dca5c98cd5d6a2bed381e2a1b1e081e59ebee081e2a1c2dbd6d5a170e0c9d359bdd5cfd259bfd281e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48e9ac38ccae259b6d1cdda59c7cdd48e88b88ccfdd6570dad0e259b1d3c2d7a77e8caecfa7c98cd1d3a8c0d8c68ea1b1e2c68eacc0d1c4e3a5b1e0c6d259c4d4c2e259b9d281e59e70d7cfd3b070d1d9cf9cc4d8da8eb0b8e581e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48ea1b1d081e2a1bfe1c8d6ad70e0c9cfad70e3c68eb0bfe1cdd259bbdad0e559b18ccdddad70d9d0e09e70cdc3ddaec48cd5d69e70dac2e2aec2d181dd9f70e0c9d359a5dacae49ec2dfc68eadb8cdcf8eb0b58cc5dd59bedbd89c')] * 2)),0)])
Core I7
(13 items)
 
  
CPUMotherboardGraphicsRAM
I7 920 rev. D0 @ 4.26Ghz EVGA X58 SLI EVGA GTX 285 OCZ XMP 3x2Gb (pc3 12800) 
Hard DriveOptical DriveOSMonitor
Western Digital Caviar Black 640Gb x 2 LG GH22LS30 openSuse 12.1 x64 HP F2105 
PowerCase
CORSAIR 850TX Cooler Master ATCS 840 
  hide details  
Reply
Core I7
(13 items)
 
  
CPUMotherboardGraphicsRAM
I7 920 rev. D0 @ 4.26Ghz EVGA X58 SLI EVGA GTX 285 OCZ XMP 3x2Gb (pc3 12800) 
Hard DriveOptical DriveOSMonitor
Western Digital Caviar Black 640Gb x 2 LG GH22LS30 openSuse 12.1 x64 HP F2105 
PowerCase
CORSAIR 850TX Cooler Master ATCS 840 
  hide details  
Reply
post #13 of 36
Thread Starter 
If anyone wants to add a few puzzles, I'll add them in as bonus challenges on the OP.
post #14 of 36
Quote:
Originally Posted by Plan9 View Post

If anyone wants to add a few puzzles, I'll add them in as bonus challenges on the OP.

I've got a couple interesting cyphers that aren't too complicated.

First up is Polybius's Checkerboard (named after the Greek historian). It is a monoalphabetic cypher that uses a table to find the answer. Unfortunately, this monoalphabetic cyphers are trivial to decode (the cypher puzzle in your local newspaper is based on this). This vulnerability lead to the creation of the first pseudo-polyalphabetic cyphers.
Warning: Spoiler! (Click to show)
Code:
Polybius's Checkerboard (j is not present and i is used instead)
-------------
| |1|2|3|4|5|
-------------
|1|a|b|c|d|e|
-------------
|2|f|g|h|i|k|
-------------
|3|l|m|n|o|p|
-------------
|4|q|r|s|t|u|
-------------
|5|v|w|x|y|z|
-------------

for example, "cypher" would become "13-54-35-23-15-42"


A variant of the pseudo-polyalphabetic cypher

           |1|2|3|4|5|6|7|8|9|
------------------------------
1,2,3,4,5,6|e|t|o|a|n|i|r|s|h|
           -------------------
        7,8|b|c|d|f|g|j|k|l|m|
           -------------------
          9|p|q|u|v|w|x|y|z| |
           -------------------

"cypher" could be:
"72-97-91-19-41-37" or
"82-97-91-69-21-57"

The big issue here is that some characters always have the same code
while others rely on the cracker not noticing the repetition in the last number (for example, all "e" end in a 1)

In 1553, Giovan Battista Bellaso created a polyalphabetic cypher variant known as Vigenere's Cypher (wrongly named after Blaise de Vigenere). It originally consisted of a 26x26 table containing the alphabet repeated over and over in different variations and was considered unbreakable for hundreds of years (until the discovery of the Kasiski Method made it's vulnerability well-known). You would input a key which would tell you which table to use for each character. This once "unbreakable" cypher will be the topic of our easy challenge. Warning: Spoiler! (Click to show)
Code:
 |A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|
------------------------------------------------------
A|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|
------------------------------------------------------
B|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|a|
------------------------------------------------------
C|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|a|b|
------------------------------------------------------
...
...
...
------------------------------------------------------
Z|z|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|
------------------------------------------------------
to encode "cypher" using the key "abc"
find the A row and then the C (which would give C)
find the B row and then the Y (which would give Z)
find the C row and then the P (which would give R) 
find the A row and then the H (which would give H)
find the B row and then the E (which would give F)
find the C row and then the R (which would give T)

so our encryption would be "czrhft" (note that we repeat the key as many times as needed)
to reverse the process, we would find the row, find our character in the row, and then look at the column to get the plaintext character.


Your goal is to make three functions. The first generates a Vigenere Table. The second accepts a key and a plaintext (and produces an encryption). The third accepts a key and an encrypted text and outputs the plaintext again. Don't forget to make sure the key is only letters and you need to ignore all non-letter characters. An easy way to test your functions is: Warning: Spoiler! (Click to show)
Code:
get_plaintext("mykey", get_encrypted_text("mykey", "this is plaintext. Remember to Accept CAPS too!!"))
//you should get back exactly what you put in

EDIT: I'd forgotten how difficult the following problem can be to implement. It's probably not the best for newer programmers to solve.
The next challenge is the block transposition cypher. A variant of this was used in ancient Greece where a piece of leather or papyrus was wrapped around a stick spiraling from one end to the other. A message would then be written across the spirals (and meaningless 'null' characters were inserted on unused lines). The papyrus would then be unwrapped and sent to the recipient. If it was intercepted, the interceptor would have to have the correct diameter stick otherwise the words would be scrambled (this worked because wartime messages would probably be useless by the time the right-diameter stick was found).

This type of cypher (called a transposition cypher) saw use in the 15-16th centuries and again in the 1860s United States during the civil war. It was normally used in combination with mono or polyalphabetic substitution and made it much harder to know when a guess was correct (an attempt at substitution would produce gibberish if the letters weren't transposed back into the correct order). Our discussion will be confined to the circular geometric block transposition cypher (because it seems more interesting programmatically) and we will not be using any substitution.
Warning: Spoiler! (Click to show)
Code:
Our plaintext = "One Ring to rule them all"
(We would fill in the extra places at the end with spaces if we needed)
-----------
|O|n|e| |R|
-----------
|i|n|g| |t|
-----------
|o| |r|u|l|
-----------
|e| |t|h|e|
-----------
|m| |a|l|l|
-----------

Next we output the characters going in a counter-clockwise direction
(starting at the $ and ending at the @) Warning: Spoiler! (Click to show)
Code:
-----------
|v|<|<|<|$|
-----------
|v|v|<|<|<|
-----------
|v|v|@|<|^|
-----------
|v|>|>|^|^|
-----------
|>|>|>|>|>|
-----------
Which gives us
our encryption = "R enoioem allelt gn  thur"
To solve, we need to start at the @ and work our way clockwise from the inside to the outside. If the text takes more than one box, we simply fill the additional boxes as needed.

The hard version of this is to assume a 5x5 box (you start in the middle, and follow the reverse of the above spiral).
edit: there is a space missing half-way through the plaintext. That's not your algorithm (it's my mistyping while learning the colmak keyboard) Test encryption (Click to show)
Code:
encrypted = "ibboHteurusivt ra s nobnatub e  eeoplepiyrevant cnrom ,ee erly msmun rforuo nahttao for ;t yehrday e yehtlp quiet e evoeandcag dnaoi h: a tdt dolearel-llewoedl-farlnredrd wea c demoy their ertnuswasdiovaf rh       t etia   nu"

The harder version is to take parameters for the size of the box and use recursion to solve (you will need to calculate the middle first). I haven't gotten around to solving this one yet (I solved it some years ago though). The encryption was manual, so I hope there were no errors (if there are, they should be relegated to only one block though).
. Test 4x8 encryption (Click to show)
Code:
encrypted = " roFt at p sma,oeieyeha tpleellrrell naset andt lewaht r:sous vDots c t,ehthey wvsa,ykt  nen eihera   vycher. tsulttonaa hor mlc

Given that the blocks are independent, I suppose extra credit is to make a multithreaded version.

For those interested, I added a couple more challenges two posts below this one
Edited by hajile - 4/14/14 at 9:44am
post #15 of 36
Thread Starter 
Thank you; added a reference in the OP (your post was too long to include verbatim and too informative to crop).

I might have a go of this myself this weekend - if I get time frown.gif
post #16 of 36
As simple polyalphabetic cyphers (such as Vigenere's Cypher) were being cracked, a new set of cyphers called fractationating cyphers were being played with. These cyphers (developed in the 1800s by Prof. Pliny Earl Chase) were based in the ideas of Polybius's Checkerboard, but with a twist to make them polyalphabetic. We will first look at a simpler version (Felix Delastelle's Bifid cypher) for our medium challenge. Later, we will look at ADFGVX which became probably the most famous field cypher in history during WWI (it will be a hard challenge).

The Bifid cypher starts with a randomized Polybius's Checkerboard
Warning: Spoiler! (Click to show)
Code:
-------------
| |1|2|3|4|5|
-------------
|1|a|v|m|q|d|
-------------
|2|u|l|r|h|y|
-------------
|3|p|n|o|f|c|
-------------
|4|z|s|w|b|k|
-------------
|5|e|i|t|g|x|

Next we separate our text into 5 character sections called periods (we ignore spaces and all "J" become "I"). Pad the end if necessary (I'll use "Z", but you should actually use random letters). We then put the row and column numbers below vertically.
Warning: Spoiler! (Click to show)
Code:
"this is our code" becomes

thisi    sourc    odezz
52545    43233    31544
34222    23135    35111

Next, we read the numbers (top then bottom) of each set one at a time into groups of two. Look these new numbers up in the chart
Warning: Spoiler! (Click to show)
Code:
The period
52545
34222

becomes
52 54 53 42 44 which becomes
i  g  t  s  b

and the other periods are:
43 23 32 31 35
w  r  n  p  c

31 54 43 51 11
p  g  w  e  a

which makes our cyphertext "igtsbwrnpcpgwea"
To decrypt, simply reverse this process.

The challenge is to make a function which takes a random alphabet (you need to make sure every letter except "J" is present) and a plaintext to decrypt. In addition, make a function which accepts an alphabet and a cypher and returns a plaintext.


Our final cypher (for a while anyway) is the ADFGVX. It was invented by Colonel Fritz Nebel as a replacement for ADFGX, but like its predecessor was broken (a major reason why Germany lost). This cypher uses a 6x6 matrix instead of a 5x5 which allows the use of numerals. Encrypting takes three stages. Our requirements before we start are a keyword and a random 6x6 matrix.
Warning: Spoiler! (Click to show)
Code:
Our key = "theshire"

Our plaintext = "At no time had Hobbits of any kind been warlike."

Our matrix

 |A D F G V X
 -------------
A|f|l|1|a|o|2|
 -------------
D|j|d|w|3|g|u|
 -------------
F|c|i|y|b|4|p|
 -------------
G|r|5|q|8|v|e|
 -------------
V|6|k|7|z|m|x|
 -------------
X|s|n|h|0|t|9|
 -------------

The first stage consists of converting the message into pairs, removing spaces and punctuation. This gives us our first monoalphabetic substitution and prepares us for the next stage.
Warning: Spoiler! (Click to show)
Code:
a  t  n  o  t  i  m  e  h  a  d
AG XV XD AV XV FD VV GX XF AG DD

h  o  b  b  i  t  s  o  f  a  n
XF AV FG FG FD XV XA AV AA AG XD

y  k  i  n  d  b  e  e  n  w  a
FF VD FD XD DD FG GX GX XD DF AG

r  l  i  k  e
DA AD FD VD GX


The second stage involves moving those characters into rows matching our keyword. I should note that the column numbers are obtained from our keyword based on a=1,b=2,c=3...z=26 except that the second a = 27 the third a=53, etc (in order of appearance in our keyword). The total number of columns match the total number of keyword characters. The characters are added from left to right and top to bottom in order of the text.
Warning: Spoiler! (Click to show)
Code:
t  h  e  s  h  i  r  e
20 8  5  19 34 9  18 31
A  G  X  V  X  D  A  V
X  V  F  D  V  V  G  X
X  F  A  G  D  D  X  F
A  V  F  G  F  G  F  D
X  V  X  A  A  V  A  A
A  G  X  D  F  F  V  D
F  D  X  D  D  D  F  G
G  X  G  X  X  D  D  F
A  G  D  A  A  D  F  D
V  D  G  X

The third and final step is to rewrite these by column from the lowest-numbered to the highest-numbered and separate them into 5 character periods.
Warning: Spoiler! (Click to show)
Code:
XFAFX XXGDG GVFVV GDXGD DVDGV FDDDA GXFAV FDFVD GGADD XAXAX XAXAF GAVVX FDADG FDXVD FAFDX A
As this is a hard challenge, I'm not giving any hints about decryption except to lookout for cols with different amounts of characters. As always, implement an encoder and decoder.
Edited by hajile - 4/13/14 at 4:04pm
post #17 of 36
Easy: word 9 = unfashionable Source code, written in F# (Click to show)
Code:
let easy = 
    let code = "Gbs!pvu!jo!uif!vodibsufe!cbdlxbufst!pg!uif!vogbtijpobcmf!foe!pg!uif!xftufso!tqjsbm!bsn!pg!uif!Hbmbyz!mjft!b!tnbmm!vosfhbsefe!zfmmpx!tvo/!Pscjujoh!uijt!bu!b!ejtubodf!pg!spvhimz!ojofuz.uxp!njmmjpo!njmft!jt!bo!vuufsmz!jotjhojgjdbou!mjuumf!cmvf!hsffo!qmbofu!xiptf!bqf.eftdfoefe!mjgf!gpsnt!bsf!tp!bnb{johmz!qsjnjujwf!uibu!uifz!tujmm!uijol!ejhjubm!xbudift!bsf!b!qsfuuz!ofbu!jefb/"
    code.ToCharArray()
    |> Array.map (fun x -> Convert.ToInt32 x - 1 |> Convert.ToChar) 
    |> fun s -> String(s)

Medium: word 2 = Hitch-Hiker's Source code, written in F# (Click to show)
Code:
let medium =
    let code = "55-69-66-21-49-6a-75-64-69-2e-49-6a-6c-66-73-28-74-21-48-76-6a-65-66-21-75-70-21-75-69-66-21-48-62-6d-62-79-7a-21-62-6d-74-70-21-6e-66-6f-75-6a-70-6f-74-21-62-6d-64-70-69-70-6d-2f-21-4a-75-21-74-62-7a-74-21-75-69-62-75-21-75-69-66-21-63-66-74-75-21-65-73-6a-6f-6c-21-6a-6f-21-66-79-6a-74-75-66-6f-64-66-21-6a-74-21-75-69-66-21-51-62-6f-21-48-62-6d-62-64-75-6a-64-21-48-62-73-68-6d-66-21-43-6d-62-74-75-66-73-2d-21-75-69-66-21-66-67-67-66-64-75-21-70-67-21-78-69-6a-64-69-21-6a-74-21-6d-6a-6c-66-21-69-62-77-6a-6f-68-21-7a-70-76-73-21-63-73-62-6a-6f-74-21-74-6e-62-74-69-66-65-21-70-76-75-21-78-6a-75-69-21-62-21-74-6d-6a-64-66-21-70-67-21-6d-66-6e-70-6f-21-78-73-62-71-71-66-65-21-73-70-76-6f-65-21-62-21-6d-62-73-68-66-21-68-70-6d-65-21-63-73-6a-64-6c-2f"
    code.Split [|'-'|]
    |> Array.map (fun x -> Convert.ToInt32(x, 16) - 1 |> Convert.ToChar) 
    |> fun s -> String(s)
BlackMesa
(14 items)
 
  
CPUMotherboardGraphicsRAM
Phenom II x6 Gigabyte XFX RF460 16gb G.Skill 
Hard DriveHard DriveOSMonitor
OCZ Vertex2 Sata II Coorsair Force GS Sata III Debian (testing) Shimian 27" 
KeyboardMouse
Filco w/ blue cherries Who needs a mouse? 
  hide details  
Reply
BlackMesa
(14 items)
 
  
CPUMotherboardGraphicsRAM
Phenom II x6 Gigabyte XFX RF460 16gb G.Skill 
Hard DriveHard DriveOSMonitor
OCZ Vertex2 Sata II Coorsair Force GS Sata III Debian (testing) Shimian 27" 
KeyboardMouse
Filco w/ blue cherries Who needs a mouse? 
  hide details  
Reply
post #18 of 36
Easy: word 23 = yellow
Medium: word 23 = Blaster
Hard: word 23 = again Source code, written in C (Click to show)
Code:
#include <stdio.h>
#include <stdlib.h>

// Tomo70 :)

// - 1 - **********************************
void cypher_ASCII_plus_1()
{
char* a="Gbs!pvu!jo!uif!vodibsufe!cbdlxbufst!pg!uif!vogbtijpobcmf!foe!pg!uif!xftufso!tqjsbm!bsn!pg!uif!Hbmbyz!mjft!b!tnbmm!vosfhbsefe!zfmmpx!tvo/!Pscjujoh!uijt!bu!b!ejtubodf!pg!spvhimz!ojofuz.uxp!njmmjpo!njmft!jt!bo!vuufsmz!jotjhojgjdbou!mjuumf!cmvf!hsffo!qmbofu!xiptf!bqf.eftdfoefe!mjgf!gpsnt!bsf!tp!bnb{johmz!qsjnjujwf!uibu!uifz!tujmm!uijol!ejhjubm!xbudift!bsf!b!qsfuuz!ofbu!jefb/";
int c, i=0;

    while(1)
    {
        c=a[i++];
        if(c==0)
            break;
        printf("%c",c-1);
    };
    printf("\r\n\r\n");
}

// - 2 - **********************************
void cypher_ASCII_plus_1hex()
{
char* a="55-69-66-21-49-6a-75-64-69-2e-49-6a-6c-66-73-28-74-21-48-76-6a-65-66-21-75-70-21-75-69-66-21-48-62-6d-62-79-7a-21-62-6d-74-70-21-6e-66-6f-75-6a-70-6f-74-21-62-6d-64-70-69-70-6d-2f-21-4a-75-21-74-62-7a-74-21-75-69-62-75-21-75-69-66-21-63-66-74-75-21-65-73-6a-6f-6c-21-6a-6f-21-66-79-6a-74-75-66-6f-64-66-21-6a-74-21-75-69-66-21-51-62-6f-21-48-62-6d-62-64-75-6a-64-21-48-62-73-68-6d-66-21-43-6d-62-74-75-66-73-2d-21-75-69-66-21-66-67-67-66-64-75-21-70-67-21-78-69-6a-64-69-21-6a-74-21-6d-6a-6c-66-21-69-62-77-6a-6f-68-21-7a-70-76-73-21-63-73-62-6a-6f-74-21-74-6e-62-74-69-66-65-21-70-76-75-21-78-6a-75-69-21-62-21-74-6d-6a-64-66-21-70-67-21-6d-66-6e-70-6f-21-78-73-62-71-71-66-65-21-73-70-76-6f-65-21-62-21-6d-62-73-68-66-21-68-70-6d-65-21-63-73-6a-64-6c-2f";
int c,d, i=0;

    while(1)
    {
// hex2dec
        c=a[i++];
        if(c>57)
            c-=87;    // "a-f"
        else
            c-=48;         // "0-9"

        d=a[i++];
        if(d>57)
            d-=87;
        else
            d-=48;
        c=c*16+d;

        printf("%c",c-1);

        if(a[i++]!=45)      // "-"
            break;
    };
    printf("\r\n\r\n");
}

// - 3 - **********************************
void cypher_ASCII_sym_key_Plan9()
{
char* a="93e1d3d7a8c5dfcde759b5dad0e3a0b89881e2a1b58cd0dca5c98cd5d6a2bed381e2a1b1e081e59ebee081e2a1c2dbd6d5a170e0c9d359bdd5cfd259bfd281e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48e9ac38ccae259b6d1cdda59c7cdd48e88b88ccfdd6570dad0e259b1d3c2d7a77e8caecfa7c98cd1d3a8c0d8c68ea1b1e2c68eacc0d1c4e3a5b1e0c6d259c4d4c2e259b9d281e59e70d7cfd3b070d1d9cf9cc4d8da8eb0b8e581e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48ea1b1d081e2a1bfe1c8d6ad70e0c9cfad70e3c68eb0bfe1cdd259bbdad0e559b18ccdddad70d9d0e09e70cdc3ddaec48cd5d69e70dac2e2aec2d181dd9f70e0c9d359a5dacae49ec2dfc68eadb8cdcf8eb0b58cc5dd59bedbd89c";
char* key="Plan9";
int c, d, i=0, ik=0;
//kl=5;
    while(1)
    {
// hex2dec
        c=a[i++];
        if(c==0)
            break;
        if(c>57)
            c-=87;    // "a-f"
        else
            c-=48;         // "0-9"

        d=a[i++];
        if(d>57)
            d-=87;
        else
            d-=48;
        c=c*16+d;

        d=key[ik++];
        if(ik==5)
            ik=0;
        c-=d;

        printf("%c",c);
    };
    printf("\r\n\r\n");
}


// - MAIN - **********************************
int main()
{
    printf("\r\n\r\n");

// - 1 -
    cypher_ASCII_plus_1();

// - 2 -
    cypher_ASCII_plus_1hex();

// - 3 -
    cypher_ASCII_sym_key_Plan9();

    return 0;
}
post #19 of 36
Easy: word 13 = western
Source Code written in PHP (Click to show)
Code:
$ascii = array(" ","!","\"","#","$","%","&","'","(",")","*","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~","DEL");

$test = "Gbs!pvu!jo!uif!vodibsufe!cbdlxbufst!pg!uif!vogbtijpobcmf!foe!pg!uif!xftufso!tqjsbm!bsn!pg!uif!Hbmbyz!mjft!b!tnbmm!vosfhbsefe!zfmmpx!tvo/!Pscjujoh!uijt!bu!b!ejtubodf!pg!spvhimz!ojofuz.uxp!njmmjpo!njmft!jt!bo!vuufsmz!jotjhojgjdbou!mjuumf!cmvf!hsffo!qmbofu!xiptf!bqf.eftdfoefe!mjgf!gpsnt!bsf!tp!bnb{johmz!qsjnjujwf!uibu!uifz!tujmm!uijol!ejhjubm!xbudift!bsf!b!qsfuuz!ofbu!jefb/";
$arr1 = str_split($test);

$length = count($ascii);


foreach($arr1 as $item) {
    for($i=0; $i < $length; $i++) {
        if($item == $ascii[$i]) {
            $item = $ascii[$i - 1];
            echo $item;
        }
    }
}


Not the best way to do it, but this is my first try at something like this.
Main Rig
(13 items)
 
BOINC
(15 items)
 
E5-26XX V2 2P
(12 items)
 
CPUMotherboardGraphicsGraphics
Intel 3770K MSI Z77 MPower MSI R7970 Lightning MSI R7950 Twin Frozr 
RAMHard DriveCoolingOS
G. Skill Trident seagate Baracuda Custom Liquid windows 7 64bit 
MonitorKeyboardPowerCase
ASUS VE248 Microsoft Wireless Corsair HX1000 Cosmos S 
Mouse
Microsoft Wireless 
CPUMotherboardGraphicsGraphics
Q9550 2.83Ghz @ 4.0Ghz 1.328v Gigabyte EP45T-DS3R Ati Radeon hd 6970 Sapphire HD 7970 
RAMHard DriveOptical DriveCooling
Corsair XMS3 seagate Baracuda LG Blu-Ray RW rosewill air cooler 
OSMonitorKeyboardPower
Windows Pro 64-Bit none Micosoft Wireless OCZ 1000w 
CaseMouse
Antec 900 Microsoft Wireless 
CPUCPUMotherboardGraphics
Xeon E5-26XX V2 2.3-2.7Ghz 10core/20 thread Xeon E5-26XX V2 2.3-2.7Ghz 10core/20 thread SuperMicro x9DAi EVGA GTX 580 
RAMRAMHard DriveCooling
G.SKILL Ripjaws X Series 8GB (4 x 2GB) 240-Pin ... G.SKILL Ripjaws X Series 8GB (4 x 2GB) 240-Pin ... Patriot 16gb Flash drive Hyper 212+ evo 
CoolingOSPowerCase
Hyper 212+ evo Ubuntu 12.04 OCZ Z series 1000w gold Fractal design define xl 
  hide details  
Reply
Main Rig
(13 items)
 
BOINC
(15 items)
 
E5-26XX V2 2P
(12 items)
 
CPUMotherboardGraphicsGraphics
Intel 3770K MSI Z77 MPower MSI R7970 Lightning MSI R7950 Twin Frozr 
RAMHard DriveCoolingOS
G. Skill Trident seagate Baracuda Custom Liquid windows 7 64bit 
MonitorKeyboardPowerCase
ASUS VE248 Microsoft Wireless Corsair HX1000 Cosmos S 
Mouse
Microsoft Wireless 
CPUMotherboardGraphicsGraphics
Q9550 2.83Ghz @ 4.0Ghz 1.328v Gigabyte EP45T-DS3R Ati Radeon hd 6970 Sapphire HD 7970 
RAMHard DriveOptical DriveCooling
Corsair XMS3 seagate Baracuda LG Blu-Ray RW rosewill air cooler 
OSMonitorKeyboardPower
Windows Pro 64-Bit none Micosoft Wireless OCZ 1000w 
CaseMouse
Antec 900 Microsoft Wireless 
CPUCPUMotherboardGraphics
Xeon E5-26XX V2 2.3-2.7Ghz 10core/20 thread Xeon E5-26XX V2 2.3-2.7Ghz 10core/20 thread SuperMicro x9DAi EVGA GTX 580 
RAMRAMHard DriveCooling
G.SKILL Ripjaws X Series 8GB (4 x 2GB) 240-Pin ... G.SKILL Ripjaws X Series 8GB (4 x 2GB) 240-Pin ... Patriot 16gb Flash drive Hyper 212+ evo 
CoolingOSPowerCase
Hyper 212+ evo Ubuntu 12.04 OCZ Z series 1000w gold Fractal design define xl 
  hide details  
Reply
post #20 of 36
Thread Starter 
Quote:
Originally Posted by nova4005 View Post

Easy: word 13 = western
Source Code written in PHP (Click to show)
Code:
$ascii = array(" ","!","\"","#","$","%","&","'","(",")","*","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~","DEL");

$test = "Gbs!pvu!jo!uif!vodibsufe!cbdlxbufst!pg!uif!vogbtijpobcmf!foe!pg!uif!xftufso!tqjsbm!bsn!pg!uif!Hbmbyz!mjft!b!tnbmm!vosfhbsefe!zfmmpx!tvo/!Pscjujoh!uijt!bu!b!ejtubodf!pg!spvhimz!ojofuz.uxp!njmmjpo!njmft!jt!bo!vuufsmz!jotjhojgjdbou!mjuumf!cmvf!hsffo!qmbofu!xiptf!bqf.eftdfoefe!mjgf!gpsnt!bsf!tp!bnb{johmz!qsjnjujwf!uibu!uifz!tujmm!uijol!ejhjubm!xbudift!bsf!b!qsfuuz!ofbu!jefb/";
$arr1 = str_split($test);

$length = count($ascii);


foreach($arr1 as $item) {
    for($i=0; $i < $length; $i++) {
        if($item == $ascii[$i]) {
            $item = $ascii[$i - 1];
            echo $item;
        }
    }
}


Not the best way to do it, but this is my first try at something like this.

Most languages have in built libraries for converting characters to integers (since strings are just byte arrays at the lowest level). In PHP, you'd want ord() and chr():
http://www.php.net/manual/en/function.ord.php
New Posts  All Forums:Forum Nav:
  Return Home
  Back to Forum: Coding and Programming
Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › Programming Challenge #10: Fun with cryptography