Confuse the Dakotas

20

1

You have been hired by the government of North Dakota to encrypt the state's communications. Write two programs, one to encrypt a message and one to decrypt that message.

The government is not really tech-savvy, so the encryption algorithm does not need to be sophisticated; just make sure the result doesn't look similar to the original at first glance.

However, you're secretly loyal to the South Dakotan government. Your job is to mix up the communications, so that every mention of North Dakota becomes South Dakota upon decryption, and vice versa. This also applies to North/South Dakotan and North/South Dakotans.

For example:

North Dakota is the wealthiest county in North America, while South Dakotans are poorer than southern Florida. - the North Dakotan government

will undergo encryption and then decryption, resulting in:

South Dakota is the wealthiest county in North America, while North Dakotans are poorer than southern Florida. - the South Dakotan government

The algorithm which accomplishes this in the most secretive, tricky manner, as evidenced by having the most upvotes, will be accepted.

Ypnypn

Posted 2014-12-15T14:29:32.950

Reputation: 10 485

Question was closed 2017-10-01T23:33:32.203

Would a simple string.replace work? Because you said the people are not really into technologie ;) – Knerd – 2014-12-15T14:43:01.597

@Knerd I'd imagine you could, but it is a popcon... – Sp3000 – 2014-12-15T14:52:48.283

@Sp3000 yeah, you are right... – Knerd – 2014-12-15T14:54:18.503

Case sensitive ? – Optimizer – 2014-12-15T15:09:04.677

@Optimizer Your choice. – Ypnypn – 2014-12-15T17:31:01.693

6I'm voting to close this question as off-topic because underhanded questions are no longer allowed under site policy. – caird coinheringaahing – 2017-10-01T23:23:29.353

Answers

13

Ruby

class Dakota

  PRIVATE_KEY = 8411088

  def self.encrypt(str)
    str.gsub(/[A-Z]/){|c|"0#{c.downcase}"}.gsub(/[a-z]+/){|s|xor(s.to_i(36),$')}
  end

  def self.decrypt(str)
    str.gsub(/\d+/){|s|out = s.to_i.to_s(36);out[0] = out[0].upcase if s[0]==?0; out}
  end

  def self.xor(n, config)
    n^=PRIVATE_KEY if private_env?(config)
    n
  end

  def self.private_env?(config)
    config =~ /^ .#{private}/i
  end

end

puts code = Dakota.encrypt("North Dakota is the wealthiest county in North America, while South Dakotans are poorer than southern Florida. - the North Dakotan government")

puts out = Dakota.decrypt(code)

Demo

histocrat

Posted 2014-12-15T14:29:32.950

Reputation: 20 600

This took me ages to figure out. Well done, sir! – Chowlett – 2014-12-16T14:21:32.263

8

CJam

This is the encoder:

232375064392749269032321519657657089927649992440902190178063558812627752920796248165803740235420850037801568815744960725761679066919872746899310628404239458 128b:c~

and this is the decoder:

364380128038419794871782113211824472986419260504039724627500790722811712426518562428698978399810134993565366126560239807690210155343815201005388714282 128b:c~

Try it online here

This only works with capital N, S and D in North/South Dakota

Pass the input string to the first function from STDIN. Get the encoded string, pass it to the second function to get the decoded and converted output.

Optimizer

Posted 2014-12-15T14:29:32.950

Reputation: 25 836

@Rainbolt LOL. Its WinterBash. Everything goes! (Surprised that you even had votes left) – Optimizer – 2014-12-15T19:55:21.337

As I said. LOL. – Optimizer – 2014-12-15T19:57:16.023

"This does nothing. HaHaHaHa! . The main logic lies in the decoder."; Why is there a . between HaHaHaHa! and The? – TheNumberOne – 2014-12-17T18:28:37.743

@TheBestOne because ... reasons. – Optimizer – 2014-12-17T18:30:23.303

Try decoding this: 364380128038419794871782113211824472986419260504039724627500790722811712426518562428698978399810134993565366126560239807690210155343815201005388714282. – TheNumberOne – 2014-12-17T18:46:24.403

7

Java

I discovered that division by zero does not cause errors in this program. This program fully encodes the Strings into a form that cannot be traced to the North Dakotan government. Due to the strange behaviour mentioned above, encoding and decoding might not work correctly in all cases.

class Program{

    public static void main(String[] args){
        String input = String.join(" ", args);
        String encode = encode(input);
        System.out.println("Encoded: " + encode);
        System.out.println("Decoded: " + decode(encode));
    }


    static String encode(String input){
        String answer = "";
        input = input.replaceAll("North Dakota", "☃");//Temporarily switch these so that spies
        input = input.replaceAll("South Dakota", "North Dakota");//think the message is from South Dakota
        input = input.replaceAll("☃", "South Dakota");//if they decode the message.
        for(int i =0; i < input.length(); i++){
            answer += (char)(~input.charAt(i)) + "";
        }
        return answer;
    }

    static String decode(String input){
        String answer = "";
        int i;
        for(i=0; i < input.length(); i++){
            answer += (char)(~input.charAt(i)) + "";
        }
        int funnyNumber = (i+\u002f*0)/0;//Division by 0 should cause an error???
        answer.replaceAll("South Dakota", "☃");
        answer.replaceAll("North Dakota", "South Dakota");
        answer.replaceAll("☃", "North Dakota");
        //For some reason, this does not cause errors either:
        funnyNumber = ((500/0)*\u002f+-2);
        return answer;
    }
}

Question: What does funnyNumber equal?

TheNumberOne

Posted 2014-12-15T14:29:32.950

Reputation: 10 855

5Whoa, did Java 8 add a static method join to the String class? *Silent celebration!* – Justin – 2014-12-16T00:31:50.173

Ah, I see what you did there. funnyNumber has a value of i - 2. I personally don't feel that hiding characters in unicode is very underhanded, though. – Justin – 2014-12-16T00:36:25.477

@Quincunx Correct, funnyNumber does equal i - 2. – TheNumberOne – 2014-12-16T01:27:08.343

Cool; I never knew that \u works outside of strings. – Ypnypn – 2014-12-16T14:10:39.773

@Ypnypn - Java is viewing it as a character, and has built-in conversion from char to int. – Xynariz – 2014-12-16T18:42:37.537

It won't compile in Java 7 for a few reasons... out of curiosity I reduced it to printing the output of this: int funnyNumber = (147+'\u002f'*0)/0; ...Which does cause a division by zero error. – Desty – 2014-12-17T18:18:01.080

@Desty This won't compile in Java 7 because of String.join. \u002f is not meant to be interpreted as a character literal. – TheNumberOne – 2014-12-17T18:20:41.340

Yes, I had to snip calls to String.join, although I'm sure it's not hard to work around it. The \u002f literal also will not compile as-is in Java 7, hence why I tried writing it as a character literal. Why does it work in Java 8? – Desty – 2014-12-17T18:28:27.890

1@Desty Try System.out.println(2+\u002f*2/0*\u002f+-2). – TheNumberOne – 2014-12-17T18:32:50.197

Ah, I understand what it's doing now... no wonder it didn't work in isolation :) – Desty – 2014-12-18T17:18:06.697

The really funny thing about this answer is that (presumably accidentally) it still answers the question if you totally remove both the lines with the funnyNumber stuff... – Sharkos – 2017-02-12T14:19:42.937

2

JavaScript

function encrypt (input) {
    input = input.replace(/north d/gi, 'hisdf')
    input = input.replace(/south d/gi, 'hisde')
    var data = input    
    var res = []
    for (var i = 0; i < data.length; i++) {
        res.push(~data.charCodeAt(i))
    }
    return res.toString()
}
function decrypt (input) {
    console.log(input)
    input = input.replace(/-105,-106,-116,-101,-102/g, '-79,-112,-115,-117,-105,-33,-69').replace(/-105,-106,-116,-101,-103/g, '-84,-112,-118,-117,-105,-33,-69 ')
    input = input.split(',')
    var res = ""
    for (var i = 0; i < input.length; i++) {
        var itm = input[i]
        res += String.fromCharCode(~parseInt(itm))
    }
    return res
}
var data = encrypt(prompt('What do you want to encrypt?'))
var data = decrypt(data)
alert(data)

My solution is probably not the most clever one. But it works :) Here is a fiddle

First I replace north d with hisdf and south d with hisde, then I invert all the characters bitwise and push them in an array. The array I convert into a string and then replace the inverted character values with the correct ones. Before that, I replace the values of hisdf and hisde switched.

Knerd

Posted 2014-12-15T14:29:32.950

Reputation: 1 251

What if my actual string contained hisde somewhere ? – Optimizer – 2014-12-15T16:10:42.407

@Optimizer well, than we it breaks :D – Knerd – 2014-12-15T16:12:24.320

@Roger Nope, becuase it replaces north d and south d :) – Knerd – 2014-12-15T16:37:11.627

@Knerd Yep, I saw the 'd' at the end just as you posted that. /facepalm – Roger – 2014-12-15T16:37:37.380

2

AWK: Encoder: 165 bytes, Decoder: 61 bytes

The encoder (also in charge of replacing South by North and vice versa):

{a="(th Dakota(ns?)?)";b="\\1";split(gensub("@"a,"Sou"b,"g",gensub("Sou"a,"Nor"b,"g",gensub("Nor"a,"@"b,"g")))" ",y,"");for(i=1;i<length(y);i+=2)printf(y[i+1] y[i])}

The decoder:

{split($0,y,"");for(i=1;i<length(y);i+=2)printf(y[i+1] y[i])}

Some test:

North Dakota is the wealthiest county in North America, while South Dakotans are poorer than southern Florida. - the North Dakotan government

encodes into:

oStu haDokati sht eewlahteitsc uotn yniN rohtA emirac ,hwli eoNtr haDokatsna erp ooer rhtnas uohtre nlFrodi.a- t ehS uohtD katonag voremnne t

(that should be scrambled enough for a not really tech-savvy government :o) )

It then decodes into:

South Dakota is the wealthiest county in North America, while North Dakotans are poorer than southern Florida. - the South Dakotan government

But that was expected :o)

Note: North Dakota, North Dakotan, North Dakotans, South Dakota, South Dakotan and South Dakotans have to be correctly capitalized.

LeFauve

Posted 2014-12-15T14:29:32.950

Reputation: 402

0

C

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

#define MASK_B 0xFFFFFFULL
#define MASK_C 0xFFULL
#define ll unsigned long long int
#define transform(a,b) ((a)>(b))?(a):(b)
static const ll magic_num = 0x756f736874726f6e;
#define BITS(a,b) (magic_num&(MASK_C<<((a+b)*8)))>>((a+b)*8)

char * key;
ll keylen;
FILE * file;

char * encrypt(in)
char * in;
{
    char * out;
    size_t length = strlen(in);
    out = (char *) malloc(sizeof (char) * (length + 1));
    for (ll i = 0; i < length; i++)out[i] = key[i % keylen]^in[i];
    out[length] = '\0';
    return out;
}

char * decrypt() {
    size_t len = 0;
    fpos_t pos;
    char * out;
    fgetpos(file, &pos);
    do if (fgetc(file) == EOF) break; else len++; while (1);
    out = (char *) malloc(sizeof (char) * (len + 1));
    fsetpos(file, &pos);
    char chr;
    ll idx = 0;
    do {
        chr = fgetc(file);
        if (chr == EOF) break;
        out[idx++] = chr^key[idx % keylen];
    } while (1);
    out[len] = '\0';
    return out;
}

void * bits(flag, mask)
ll flag;
char * mask;
{
    int dx = (flag & (~0&MASK_C)<<16) ? 5 : 0;
    key[0] = BITS(dx, 0),key[1] = BITS(dx, 1),key[2] = BITS(dx, 2),key[3] = BITS(3, 0),key[4] = BITS(3, 1);
    strncpy(&key[5], " dakota", 8);
    if (flag & ~(MASK_B^MASK_C)) {
        dx = (char)flag & MASK_C;
        if (islower(*mask)) *mask = key[dx - 1];
        else *mask = toupper(key[dx - 1]);
    } else if (!(flag & ~~0))
        return (void *) key;
    return (void*) key[transform(arc4random_uniform(12), 12)];
}

int genkey(in)
char * in;
{
    size_t bound_upper = strlen(in);
    char * index1 = malloc(sizeof(char) * (bound_upper + 1));
    char * index2 = malloc(sizeof(char) * (bound_upper + 1));
    char * index;
    index1 = strcpy(index1,in);
    index2 = strcpy(index2,in);
    ll spice = 0;
    key = (char *) malloc(sizeof (char) * 13);
    char *hits = (char *) malloc(sizeof (char) * bound_upper);
    for (unsigned long j = 0; j < bound_upper; j++){
        hits[j] = 0;
    }

    for (int iter = 0; iter < 2; iter++) {
        ll rotation = 0, flag = MASK_C << (8 * (iter + 1)), flag2 = MASK_C << (8 * (2 - iter)),abs=0;
        char * tmpstr;
        index = iter ? index2 : index1;
        do {
            spice = spice + arc4random_uniform(bound_upper) % bound_upper;
            if (!rotation) {
                tmpstr = strcasestr(index, bits(flag, in));
                if (tmpstr == NULL)
                    goto out;
                index = tmpstr;
            } else {
                bits(flag2 | rotation, index++);
                hits[abs] = iter + 1;
            }
            rotation = (rotation + 1) % (4);
            abs = index - (iter ? index2 : index1);
        } while (flag);
out:
        index = in;
        rotation = 0;
    }
    for(int k = 0;k < bound_upper;k++){
        index[k]=(hits[k]==1?index1[k]:(hits[k] ? index2[k]: index[k]));
        spice += arc4random_uniform(spice)|spice^arc4random();
    }
    free(key);
    spice = spice % bound_upper;
    if (!spice)
        spice = bound_upper;
    keylen = (keylen | spice) & MASK_B;
    key = (char *) malloc(sizeof (char) * (keylen + 1));
    for (ll i = 0; i < keylen; i++)
        key[i] = (arc4random_uniform(126 - ' ') % (126 - ' ')) + ' ';
    key[keylen] = '\0';
    return keylen;
}

int main(argc, argv)
int argc;
char *argv[];
{
    if (argc != 4) return 1;
    char * result;
    if (!strcmp(argv[1], "encrypt")) {
        (void) genkey(argv[2]);
        result = encrypt(argv[2]);
        printf("Decryption Key: '%s'\n", key);
        file = fopen(argv[3], "wb");
        if (file == NULL) printf("Could not open file for writing: %s", argv[3]);
        if (fwrite(result, sizeof (char), strlen(result), file) != strlen(result)) printf("Error occurred while writing ciphertext to file!");
    }
    if (!strcmp(argv[1], "decrypt")) {
        file = fopen(argv[3], "rb");
        if (file == NULL) printf("Could not open file for reading: %s", argv[3]);
        key = argv[2];
        keylen = strlen(argv[2]);
        result = decrypt();
        printf("Plaintext: '%s'\n", result);
    }
    return 0 & fclose(file);
}

Compile with: gcc -Wall -Wextra -Wno-missing-field-initializers -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wwrite-strings -DGCC_WARN -ansi -pedantic file.c

For maximum evil, written in K&R C with a dash of pointer abuse.
Lasciate ogni speranza, voi ch'entrate.
Buśhaīila rukgâī, naǵkxarańga ba tdhuløk.
Also, everything's in the bits function and the genkey function.

Run:

[...@...] testing_golf$ ./a.out encrypt "North Dakota is the wealthiest county in North America, while South Dakotans are poorer than southern Florida. - the North Dakotan government" cipher
Decryption Key: ')=1aj3'
[...@...]: testing_golf$ ./a.out decrypt ")=1aj3" cipher
Plaintext: 'South Dakota is the wealthiest county in North America, while North Dakotans are poorer than southern Florida. - the South Dakotan government'

Note: When specifying the key in decrypt mode, it may be necessary to escape some of the characters in the key with backslashes.

Élektra

Posted 2014-12-15T14:29:32.950

Reputation: 284

-1

JavaScript, ES6

Sweet and simple to begin with.

Encoder:

E=a=>btoa(a)

Decoder:

D=a=>atob(a_.replace(/(nor|sou)(th dakota)/gi, (_,x,y)=>({n:"sou",s:"nor",N:"Sou",S:"Nor"})[x[0]]+y)

Try it below on a latest Firefox:

E=a=>btoa(a)
D=a=>atob(a).replace(/(nor|sou)(th dakota)/gi, (_,x,y)=>({n:"sou",s:"nor",N:"Sou",S:"Nor"})[x[0]]+y)
var string = prompt()
alert("Encoded string: " + E(string));
alert("Decode string: " + D(E(string)));

Optimizer

Posted 2014-12-15T14:29:32.950

Reputation: 25 836

3Your code doesn't work, you should replace dakotan with dakota :) – Knerd – 2014-12-15T16:05:44.570

3@Knerd no, you should not. – Optimizer – 2014-12-15T16:10:03.063

Yes you should, with your code you only replace North Dakotan not North Dakota same goes for south – Knerd – 2014-12-15T16:11:54.790

@Knerd, oh that's what you meant. I though you meant I should replace occurance of dakotan with dakota – Optimizer – 2014-12-15T16:13:02.690

Yep, I see you canged it, you solution is so smooth :D Do you actually encrypt or just replace? – Knerd – 2014-12-15T16:14:09.300

@Knerd Just replace. – Optimizer – 2014-12-15T16:15:56.567

1Cause, I think the OP wanted the code to encrypt a message and then with another code to decrypt it. – Knerd – 2014-12-15T16:16:44.583

@Knerd Ah, let me fix that. – Optimizer – 2014-12-15T16:18:12.160

9This is not really underhanded at all. I'd be tempted to downvote but not sure if that's cool in a popularity contest? – Claudiu – 2014-12-15T17:24:53.843