Overclock.net banner

Programming Challenge #10: Fun with cryptography

5K views 35 replies 20 participants last post by  thyfartismurder 
#1 ·
Fun with cryptography

(Previous challenge: Programming Challenge 9: Writing a basic game)

Before you read on:
A huge disclaim needs to be made. NEVER EVER roll your own encryption ciphers. I can guarantee you that as smart and talented programmer as you may be, you will make a mistake somewhere that will leave your cipher vulnerable. The challenges here are just for fun. If anyone does have any questions about how securely encrypt data, then please feel free to ask.

How post your answers:
Do NOT post the complete decoded string because others might want to try the same challenge. Instead, post 1 word from the decoded string and it's word number. eg "word 2 = NOT" would be your reply if this paragraph was the answer. Also please post your source code inside [ code ] and [ spoiler ] tags as it keeps the thread tidy. eg:
Quote:
easy challenge: word 2 = NOT
Code:
<br><span style="color:#008B00;">// code be here</span><br>
Easy challenge:
In the spoiler below, I've encoded an extract from my favourite book. Each ASCII character has been incrimented by one. So the letter A -> B. Decode the string; but don't post the entire answer (see How post your answers above)
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 challenge:
In the spoiler below, I've encoded an extract from my favourite book. Each ASCII character has been incrimented by one (so the letter A -> B) and then converted to hex. Decode the string but don't post the entire answer (see How post your answers above)
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

Hard challenge:
I've encoded an extract from my favourite book. I've used a symmetric-key stream cipher, the key is my user name. Use this to decode the string in the spoiler below. I've deliberately kept things vague here to present a challenge, however I will give a hint in that the encryption is very basic.
93e1d3d7a8c5dfcde759b5dad0e3a0b89881e2a1b58cd0dca5c98cd5d6a2bed381e2a1b1e081e59ebee081e2a1c2dbd6d5a170e0c9d359bdd5cfd259bfd281e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48e9ac38ccae259b6d1cdda59c7cdd48e88b88ccfdd6570dad0e259b1d3c2d7a77e8caecfa7c98cd1d3a8c0d8c68ea1b1e2c68eacc0d1c4e3a5b1e0c6d259c4d4c2e259b9d281e59e70d7cfd3b070d1d9cf9cc4d8da8eb0b8e581e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48ea1b1d081e2a1bfe1c8d6ad70e0c9cfad70e3c68eb0bfe1cdd259bbdad0e559b18ccdddad70d9d0e09e70cdc3ddaec48cd5d69e70dac2e2aec2d181dd9f70e0c9d359a5dacae49ec2dfc68eadb8cdcf8eb0b58cc5dd59bedbd89c

I've kept all the challenges pretty basic, so that everyone has a chance to solve them.

Happy coding and please remember to post your answers using the etiquette outlined in How post your answers (above)

Bonus Challenges:
  1. Can you answer any challenges with 1 liners?
  2. 2 challenges using Block Transposition Cyphers (post #14) courtesy of hajile.
 
See less See more
#4 ·
easy challenge: word 2 = uncharted
Code:

Code:
import sys
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/'
for b in a:
    sys.stdout.write(chr(ord(b)-1))

sys.stdout.write('\n')

medium challenge: word 10 = alcohol.
Code:

Code:
import sys

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'.split('-')
for b in a:
    sys.stdout.write(chr(ord(b.decode('hex')) - 1))

sys.stdout.write('\n')

hard challenge: word 15 = petunias
Code:

Code:
import sys
import re

a =re.findall('..?', '93e1d3d7a8c5dfcde759b5dad0e3a0b89881e2a1b58cd0dca5c98cd5d6a2bed381e2a1b1e081e59ebee081e2a1c2dbd6d5a170e0c9d359bdd5cfd259bfd281e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48e9ac38ccae259b6d1cdda59c7cdd48e88b88ccfdd6570dad0e259b1d3c2d7a77e8caecfa7c98cd1d3a8c0d8c68ea1b1e2c68eacc0d1c4e3a5b1e0c6d259c4d4c2e259b9d281e59e70d7cfd3b070d1d9cf9cc4d8da8eb0b8e581e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48ea1b1d081e2a1bfe1c8d6ad70e0c9cfad70e3c68eb0bfe1cdd259bbdad0e559b18ccdddad70d9d0e09e70cdc3ddaec48cd5d69e70dac2e2aec2d181dd9f70e0c9d359a5dacae49ec2dfc68eadb8cdcf8eb0b58cc5dd59bedbd89c')
b = 0

for c in a:
    sys.stdout.write(chr(ord(c.decode('hex')) - ord('Plan9'[b])))
    b = b + 1 if b < 4 else 0

sys.stdout.write('\n')

(edit) adding java version

easy challenge: word 6 = backwaters
medium challenge: word 7 = Galaxy.
hard challenge: word 10 = mind
Code:

Code:
public class Cha10 {

    public static void main(String[] args) {
        Easy();
        Medium();
        Hard();
    }

    public static void Easy(){
        String 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/";
        for (int b = 0;b < a.length();b++){
            System.out.print( (char) ((int) a.charAt(b) - 1));
        }
        System.out.println();
    }

    public static void Medium(){
       String[] 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".split("\\-");
       for (String b:a){
           System.out.print((char) (Integer.parseInt(b,16) -1));
       }
        System.out.println();
    }

    public static void Hard(){
        String[] a = "93e1d3d7a8c5dfcde759b5dad0e3a0b89881e2a1b58cd0dca5c98cd5d6a2bed381e2a1b1e081e59ebee081e2a1c2dbd6d5a170e0c9d359bdd5cfd259bfd281e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48e9ac38ccae259b6d1cdda59c7cdd48e88b88ccfdd6570dad0e259b1d3c2d7a77e8caecfa7c98cd1d3a8c0d8c68ea1b1e2c68eacc0d1c4e3a5b1e0c6d259c4d4c2e259b9d281e59e70d7cfd3b070d1d9cf9cc4d8da8eb0b8e581e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48ea1b1d081e2a1bfe1c8d6ad70e0c9cfad70e3c68eb0bfe1cdd259bbdad0e559b18ccdddad70d9d0e09e70cdc3ddaec48cd5d69e70dac2e2aec2d181dd9f70e0c9d359a5dacae49ec2dfc68eadb8cdcf8eb0b58cc5dd59bedbd89c".split("(?<=\\G.{2})");
        int b = 0;
        for (String c : a){
            System.out.print((char) ((Integer.parseInt(c,16) - (int) "Plan9".charAt(b))));
            b = (b < 4) ? b + 1 : 0;
        }
        System.out.println();
    }
}
 
#5 ·
Hard Challenge: Word 13 = bowl

Code:

Code:
#!/usr/bin/env python

from __future__ import print_function
import re

string = '93e1d3d7a8c5dfcde759b5dad0e3a0b89881e2a1b58cd0dca5c98cd5d6a2bed381e2a1b1e081e59ebee081e2a1c2dbd6d5a170e0c9d359bdd5cfd259bfd281e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48e9ac38ccae259b6d1cdda59c7cdd48e88b88ccfdd6570dad0e259b1d3c2d7a77e8caecfa7c98cd1d3a8c0d8c68ea1b1e2c68eacc0d1c4e3a5b1e0c6d259c4d4c2e259b9d281e59e70d7cfd3b070d1d9cf9cc4d8da8eb0b8e581e2a1b58cc3ddb0bc8cd0d459c0d1d5e3a7b9cdd48ea1b1d081e2a1bfe1c8d6ad70e0c9cfad70e3c68eb0bfe1cdd259bbdad0e559b18ccdddad70d9d0e09e70cdc3ddaec48cd5d69e70dac2e2aec2d181dd9f70e0c9d359a5dacae49ec2dfc68eadb8cdcf8eb0b58cc5dd59bedbd89c'
x = re.findall('..', string)
i = 0

for z in x:
    print(chr(ord(z.decode('hex')) - ord('Plan9'[i])), end='')
    i = i + 1 if i < 4 else 0

print('')

EDIT: Your user title @Plan9
lachen.gif

.
 
#6 ·
Easy Challenge: Word #2 = out
Code:

Code:
public class Main {

        public static void main(String[] args) {
                String encrypt = "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 length = encrypt.length();
                int j = 0;
                String answer = "";
                while (j < length) {
                        //Convert String to char at position j
                        char a = encrypt.charAt(j);
                        //Decrypt char
                        int y = a - 1;
                        //Convert back to char
                        char converted = (char) y;
                        //Convert back to String
                        answer = answer + converted;
                        j++;
                }
                System.out.println(answer);

        }

}

Medium Challenge: Word #3: Guide
Code:

Code:
import java.util.StringTokenizer;

public class Main {

        public static void main(String[] args) {
                String encrypt = "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";
                StringTokenizer st = new StringTokenizer(encrypt, "-");
                String answer = "";
                while (st.hasMoreTokens()) {
                        // Convert hex back to char
                        char a = (char)Integer.parseInt(st.nextToken(), 16);
                        // Decrypt char
                        int y = a - 1;
                        // Convert back to char
                        char converted = (char) y;
                        // Convert back to String
                        answer = answer + converted;
                }
                System.out.println(answer);

        }

}
 
#7 ·
Easy: 61 = idea
Code:

Code:
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/";
var decrypted = "";
for(var i = 0; i < encrypted.length; i++){
        decrypted += String.fromCharCode(encrypted[i].charCodeAt() - 1);
}

Medium: 45 = brick
Code:

Code:
var 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";
var decrypted = "";
var chars = String.split(encrypted, "-");
for(var i = 0; i < chars.length; i++){
        decrypted += String.fromCharCode(parseInt(chars[i], 16) - 1);
}
 
#8 ·
Ooo just found this thread!

Easy: 18 = Galaxy
Code:

Code:
            //Code context is for an event handler.
            String temp = textBox1.Text;
            String output = "";

            Int32 charNumb = 0;

            temp.Replace("!", " ");

            foreach(char chartemp in temp)
            {
                charNumb = System.Convert.ToInt32(chartemp);

                charNumb--;

                output += System.Convert.ToChar(charNumb);
            }

            textBox2.Text = output;

Medium: 9 = Alcohol
Code:

Code:
            //Code context is for an event handler.
            String temp = textBox3.Text;
            String output = "";

            int charNumb = 0;

            foreach(String hex in temp.Split('-'))
            {
                if (!(String.IsNullOrEmpty(hex)))
                {
                    charNumb = System.Convert.ToInt32(hex, 16);

                    charNumb--;

                    output += System.Convert.ToChar(charNumb);
                }
            }

            textBox2.Text = output;

Hard: 10 = Mind
Code:

Code:
            //Code context is for an event handler.
            textBox2.Text = "";

            String encrypted = textBox4.Text;

            List<String> newList = new List<String>();

            Char[] cipher = { 'P', 'l', 'a', 'n', '9' };

            String output = "";
            String temp = "";

            int listCounter = 0;

            //Traveller
            Int32 ciphNumb = 0;

            //Encoded Letter
            Int32 charNumb = 0;

            //Result
            Int32 result = 0;

            foreach(Char charTemp in encrypted)
            {        
                if (listCounter == 2)
                {
                    listCounter = 0;
                    newList.Add(temp);
                    temp = "";
                }

                temp += charTemp;
                listCounter++;
            }

            foreach (String strTemp in newList)
            {
                if (ciphNumb > 4)
                {
                    ciphNumb = 0;
                }

                charNumb = System.Convert.ToInt32(strTemp, 16);
                result = charNumb - System.Convert.ToInt32(cipher[ciphNumb]);

                output += System.Convert.ToChar(result);

                ciphNumb++;
            }

            textBox2.Text = output;

I did notice that there are some characters missing in my Hard output. Was very strange.
 
#9 ·
Easy Challenge
word 19 = lies
Code:

Code:
import System.IO

main = do
        putStrLn "Input the Encrypted String: " 
        encrypted <- getLine 
        let decrypted = [ pred(l) | l <- encrypted]
        writeFile "decrypted.txt" decrypted

Trying to teach myself Haskell, so if anyone sees something I did improperly please tell me. I'm going to try to work on the harder challenges as I get time.
 
#10 ·
Easy Challenge: 9 = unfashionable
Code:

Code:
$encoded = '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/';
$decoded = '';

$chars = str_split($encoded);
foreach ($chars as $char)
    $decoded .= chr(ord($char) - 1);

echo $decoded;

Medium Challenge: 22 = Gargle
Code:

Code:
$encoded = "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";
$decoded = '';

$chars = explode ('-', $encoded);
foreach ($chars as $char)
    $decoded .= chr(hexdec($char) - 1);

echo $decoded;
 
#11 ·
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"
Code:

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
Code:

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"
Code:

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"
Code:

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))))
 
#12 ·
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"
Code:

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
Code:

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"
Code:

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
Code:

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)])
 
#14 ·
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.
Code:

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.
Code:

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:
Code:

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.
Code:

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 @)
Code:

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)
Code:

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).
.
Code:

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
 
#16 ·
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
Code:

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.
Code:

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
Code:

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.
Code:

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.
Code:

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.
Code:

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.
Code:

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.
 
#17 ·
Easy: word 9 = unfashionable
Code:

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
Code:

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)
 
#18 ·
Easy: word 23 = yellow
Medium: word 23 = Blaster
Hard: word 23 = again
Code:

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;
}
 
#19 ·
Easy: word 13 = western
Code:

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.
 
#20 ·
Quote:
Originally Posted by nova4005 View Post

Easy: word 13 = western
Code:

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
 
#21 ·
Two one-liner solutions here.

Note: I used the 'input' variable just to keep the lines readable. The input values could just as easily be put in line.
Also: If programming languages were characters in some kind of fighting game, everyone would play as C# because LINQ would be OP as hell.

One-liner medium challenge: word 20 = Pan
Code:

Code:
var mediumresult = new string(input.Split('-').Select(s => (char)(int.Parse(s, NumberStyles.HexNumber) - 1)).ToArray());

One-liner hard challenge: word 20 = Oh
Code:

Code:
var hardresult = new string(Regex.Matches(input, "..").Cast<Match>().Select((s, i) => (char)(int.Parse(s.Value, NumberStyles.HexNumber) - (int)"Plan9"[i % 5])).ToArray());

EDIT: Actually this is a better one-line solution for the hard. The line is a bit longer, but it doesn't use RegEx and does less casting, so it executes 3x faster:
I give myself bonus points for optimizing my code.
tongue.gif


One-liner hard challenge: word 20 = Oh
Code:

Code:
var hardresult = new string(Enumerable.Range(0, input.Length / 2).Select(i => input.Substring(i * 2, 2)).Select((s, i) => (char)(int.Parse(s, NumberStyles.HexNumber) - (int)"Plan9"[i % 5])).ToArray());

Quote:
Originally Posted by hajile View Post

(it's my mistyping while learning the colmak keyboard)
+Rep for that. I made the switch over a year ago. Totally worth it. The teething period is tough, you have to force yourself through it. Just stick with it and profit my friend.
 
#22 ·
Thanks to codepad.org, I've done the Vigenere part completely by using my phone only
smile.gif

Here we go:
Code:

Code:
// Vigenere.c
// Tomo70 :)

#include "stdio.h";
#include "string.h";
char* str="THisISaPlainTeXt";

char* encrypt(char* key, char* buff)
{
    int c, e, i=0, ik=0, k;
    while(1)
    {
        c=buff[i];
        if(c==0)
            break;
        k=key[ik++];
        if(k==0)
          {  k=key[0];
              ik=1; }
        e=(c|32)-97+(k|32);
        if (e>122)
            e-=26;
        buff[i++]=e;
    }
    return buff;
}

char* decrypt(char* key, char* buff)
{
    int c, e, i=0, ik=0, k;
    while(1)
    {
        c=buff[i];
        if(c==0)
            break;
        k=key[ik++];
        if(k==0)
          {  k=key[0];
              ik=1; }
        e=(c|32)+97-(k|32);
        if (e<97)
            e+=26;
        buff[i++]=e;
    }
    return buff;
}

int main()
{
    char *buffer = malloc(200);

    strcpy(buffer, str);

    printf("%s\r\n", buffer);
    printf("%s\r\n", encrypt("mykey", buffer));
    printf("%s\r\n", decrypt("mYkeY", buffer));

    printf("%s\r\n", decrypt("mykEy", encrypt("myKey", buffer)));

    free(buffer);
    return 0;
}
 
#23 ·
Quote:
Originally Posted by Plan9 View Post

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
Thanks Plan9, I have not had much experience with them and I did see where others had used those. I will definitely read up on them for the next one.
smile.gif
 
#24 ·
(The file handling functions in the code are because I'm storing the text in an input file, a little more versatile that way but probably unnecessary unless more ciphertexts are inbound
tongue.gif
)

Easy challenge, source code in C:
Code:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Compiled using gcc in Linux

int main(int argc, char *argv[])
{
  FILE *fp;
  char infile[80] = "";
  int c;

  strcpy(infile, argv[1]);

  fp = fopen(infile, "r");

    while ((c = getc(fp)) != EOF)
        putchar(c-1); // Output not sanitized, will probably do strange things if the ASCII text accidentally includes control characters
    fclose(fp);
    printf("\n\n");
}

The result:
Far

Medium challenge, source code in C:
Code:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// Compiled using gcc in Linux

int string_to_array(const char *str, int *output)
{
    int *out = output;
    for (; *str; str++) {
        if (isxdigit(*str & 0xff)) {
            char ch = tolower(*str & 0xff);
            *out++ = (ch >= 'a' && ch <= 'z') ? ch - 'a' + 10 : ch - '0';
        }
    }
    return out - output;
}

int main(int argc, char *argv[])
{
  FILE *fp;
  char infile[80] = "";
  char buff[2] = "";
  char i;
  int output;
  int numc[2];
  int index = 0;
  int j;

  strcpy(infile, argv[1]);

  fp = fopen(infile, "r");

  while ((i = getc(fp)) != EOF)
    {
      if(i != '-')
        {
          buff[index] = i;
          index++;
        } else  {
          index = 0;
          j = string_to_array(buff, numc);
          output = numc[0]*16 + numc[1] - 1;
          putchar(output); // Again, not sanitized so could do strange things
      }
    }
  fclose(fp);
  printf("\n");
}

The result:
brick

The hard challenge was indeed hard, because I kept getting junk before I realized the nature of the ciphertext.
Code:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// Compiled using gcc in Linux

int string_to_array(const char *str, int *output)
{
    int *out = output;
    for (; *str; str++) {
        if (isxdigit(*str & 0xff)) {
            char ch = tolower(*str & 0xff);
            *out++ = (ch >= 'a' && ch <= 'z') ? ch - 'a' + 10 : ch - '0';
        }
    }
    return out - output;
}

int main(int argc, char *argv[])
{
  FILE *fp;
  char infile[80] = "";
  char buff[2] = "";
  char key[] = "Plan9";
  char i;
  int output;
  int shift = 0;
  int numc[2];
  int index1 = 0;
  int index2 = 0;
  int j;

  strcpy(infile, argv[1]);

  fp = fopen(infile, "r");

  while ((i = getc(fp)) != EOF)
    {
      buff[index1++] = i;
      if (index1 ==  2)
        {
          index1 = 0;
          j = string_to_array(buff, numc);
          output = numc[0]*16 + numc[1];
          shift = (int)key[index2++];
          j = (char)(output-shift);
          putchar(j); // Again, not sanitized so could do strange things
        }
      if (index2 > 4) { index2 = 0; }
    }
  fclose(fp);
  printf("\n");
}

The result:
petunias

Wheeeeeew! I'm not gonna try the more complicated challenges.
tongue.gif
 
#25 ·
Made a GUI around it, here is relevant code.
6th last word "watches"
Code:

Code:
StringBuilder sb = new StringBuilder();
            foreach (char c in BeforeConv)
            {
                sb.Append((char)((short)c - 1));
            }
            AfterConv = sb.ToString();

6th last word "wrapped"
Code:

Code:
            StringBuilder sb = new StringBuilder();
            string input = BeforeConv.Replace("-", "").ToUpper();
            int length = input.Length;
            for (int i = 0; i < length - 1; i += 2)
            {
                int dec = Convert.ToInt32(input.Substring(i,2), 16)-1;
                sb.Append(Char.ConvertFromUtf32(dec));
            }
            AfterConv = sb.ToString();

5th last word "Universe":
Code:

Code:
            StringBuilder sb = new StringBuilder();
            string plan9 = "Plan9";
            int length = BeforeConv.Length;
            for (int i = 0; i < length - 1; i += 2)
            {
                int dec = Convert.ToInt32(BeforeConv.Substring(i, 2),16) - Convert.ToInt32(plan9[i/2 % 5]);
                sb.Append(Char.ConvertFromUtf32(dec));
            }
            AfterConv = sb.ToString();

Even with looking at the other's their code last one still took me 20 minutes -,-. Took me way too long to realise i had to do i/2 instead of i.
 
#26 ·
I decided to take a shot at the Polybius Square, this time in Visual Studio 2010 in C++ as a Win32 console application.
Code:

Code:
// Polybius.cpp : Encrypt text using the Polybius cipher.

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <ctype.h>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
        char polybius[5][5] = {{'a', 'b', 'c', 'd', 'e'},
                                                   {'f', 'g', 'h', 'i', 'k'},
                                                   {'l', 'm', 'n', 'o', 'p'},
                                                   {'q', 'r', 's', 't', 'u'},
                                                   {'v', 'w', 'x', 'y', 'z'}};

        string line;
        char plaintext;
        int i, j, k, z;
        ifstream myfile;
        myfile.open(argv[1], ios::in);
        if (myfile.is_open())
                {
                        while ( getline (myfile,line) )
                                {
                                        z = line.length();
                                        for(i = 0; i < z; i++)
                                                {
                                                        plaintext = tolower(line[i]);
                                                        // Try to reasonably sanitize the input so the Polybius Square doesn't do funny things.
                                                        if (isalpha(plaintext))
                                                                {       
                                                                        if (plaintext == 'j') { plaintext = 'i'; }
                                                                        for (j = 0; j < 5; j++)
                                                                                {
                                                                                        for(k = 0; k < 5; k++)
                                                                                                {
                                                                                                        if(plaintext == polybius[k][j]) { break; }
                                                                                                }
                                                                                        if(plaintext == polybius[k][j]) { break; }
                                                                                }
                                                                        cout << k+1 << j+1 << "-" ;
                                                                }
                                                        if (plaintext == ' ') { cout << "00-"; }
                                                        // Unfortunately while this makes the output "cleaner" it also makes the cryptanalysis way easier,
                                                        // since it's such an obvious outlier
                                                }
                                        cout << endl;
                                }
                }
    myfile.close();
        return 0;
}

The input:

Code:

Code:
1cypher0
CYPHER
CYPHER cypher
abcdefghijklmnopqrstuvwxyz
The output:

Code:

Code:
13-54-35-23-15-42-
13-54-35-23-15-42-
13-54-35-23-15-42-00-13-54-35-23-15-42-
11-12-13-14-15-21-22-23-24-24-25-31-32-33-34-35-41-42-43-44-45-51-52-53-54-55-
(I have yet to figure out an elegant solution to avoid trailing dashes at the end of a line
frown.gif
)

Next step will of course be the DEcryption end of this.
smile.gif
 
This is an older thread, you may not receive a response, and could be reviving an old thread. Please consider creating a new thread.
Top