Encryption challenge

The fear of every surveillance society: citizens protecting their own privacy with strong cryptography

Encryption challenge

Good morning HTS,

I'm bored today, so I present to you a simple encryption algorithm that I came up with a while back.

What the algorithm does is it splits each byte into 2 bytes, the first being the byte AND the mask, the second being the byte NOR the mask.

Code: Select all
`Given mask M and byte array A,Encrypt a new array Bfor i = 1 -> A.length * 2     B[i * 2] = A[i] AND M     B[i * 2 + 1] = A[i] NOR M`

This way, to decrypt it, you know where the byte definitely has 1's and where it definitely has 0's, any spots that you aren't defined in the AND or NOR, will be the inverse bits of the mask.

Now this by itself is unsafe because you can easily pin point where the mask has what bits. So, to make it more secure, the algorithm randomly salts any bits in the AND that will always be 0's, and any bits in the NOR that will always be 0's.

This is the Java code that encrypts a byte array according to this algorithm, given byte mXORMask = mask

Code: Select all
`public byte [] transformBytes(byte [] vByteArray) {            byte [] nByteArray = new byte [vByteArray.length * 2];            nByteArray[0] = mXORMask;            for(int i = 0; i < vByteArray.length; i++) {                  nByteArray[i * 2] = (byte)(mXORMask & vByteArray[i]);         nByteArray[i * 2 + 1] = (byte)(0xFF ^ (mXORMask | vByteArray[i]));               }            return nByteArray;         }`

This is the Java code that salts the bytes given byte [] aSalterMask = {mXORMask ^ 0xFF, mXORMask};

Code: Select all
`   public byte[] transformBytes(byte[] vByteArray) {            byte [] nByteArray = new byte [vByteArray.length];               int tIndex = 0;            for(int i = 0; i < vByteArray.length; i++) {                  nByteArray[i] = (byte)(((aSalterMask[tIndex] ^ 0xFF) & vByteArray[i]) | (aSalterMask[tIndex] & ByteLib.getRandomByte()));                  tIndex++;                  if(tIndex == mNumMasks) {                        tIndex = 0;                     }               }            return nByteArray;         }`

The challenge to everyone is to find a way to crack this encryption without the mask available. Or possibly find the mask. A cookie to the first person to crack it without brute forcing.

Here's some encrypted 'hello world's for you:

Code: Select all
`51 B3 04 9A 5C 91 0D 95 5E B2 69 DF 0F AE 17 14 1A AF 14 11 15 B9 29 DC 68 5E 39 78 78 5E 45 52 4A D3 39 17 7C 98 65 31 24 B7 3F 36 60 7B 66 2E 2E 30 63 AB 24 33 75 1B 60 58 68 5A 68 F8 05 D2 1A D5 5D 50 12 55 70 35 61 17 2D 1C 2D 1A 2D 91 25 13 2D 91 2C 15 67 B0 77 96 69 FB 3E 88 66 AC 3F 16 7E 14 7B 2F 2B 0B 35 31 74 35 75 9F 6C BB 28 5E 20 DA 29 F8 69 DC 31 5E 78 FC 79 5E 20 DE 04 F4 42 55 15 F4 5A 71 59 B1 3D 3C 15 37 6D 13 46 10 38 DF 17 A8 2E B4 02 2D 7D 13 4C 39 31 DC 39 6E 38 58 79 EC`

-- Thu Jul 19, 2012 11:51 pm --

Does no one have a solution for this?

Contributor

Posts: 686
Joined: Tue Mar 06, 2012 9:37 pm
Blog: View Blog (0)

Re: Encryption challenge

Ok, so I might be wrong in this, but doesn't including a random number generator to encryption produce unreadable text? I mean, what are you using as a key when that same key is random and so undetermined? I think that would be akin to a one time pad, which also uses a never used before key. Of course, it's different, you use other functions (no XOR) and a random number generator is not entirely random. But I do question the feasibility of this. Just a question: can you decrypt it yourself without knowing the used RNG data?
Free your mind / Think clearly

cyberdrain
Expert

Posts: 2160
Joined: Sun Nov 27, 2011 1:58 pm
Blog: View Blog (0)

Re: Encryption challenge

Knowing the key that was used to encrypt it, yes, I can decode it. I want to see if anyone can figure out a way to attack it without the use of the key. So far, I've come up with only brute forcing it as a way of cracking it. If its encrypted only once with this, then brute forcing is simple due to there only being 256 different possible keys, but say i encrypted it 4 times in a row, that indicates 2^32 different sets of keys, which a can take a brute forcing program hours, maybe even days?

Contributor

Posts: 686
Joined: Tue Mar 06, 2012 9:37 pm
Blog: View Blog (0)

Re: Encryption challenge

Hey, you make me look stupid I meant that, does the random number generator change the output? But I guess you answered that. My experience is that when using something multiple times in encryption, unless it's proven 'safe', will eventually weaken an algorithm. Inadvertently you will introduce a shortcut of some type. Otherwise all encryption would just use one thing over and over (yes, XOR and bit shifts are used a lot, but still). I'm sorry, I'm no expert on encryption. Quite the opposite actually, I did one course on it. I'll first have to translate your Java program into something more 'native' to me
Free your mind / Think clearly

cyberdrain
Expert

Posts: 2160
Joined: Sun Nov 27, 2011 1:58 pm
Blog: View Blog (0)

Re: Encryption challenge

The random number generator changes the encrypted output, but only in the unneeded bits of the byte. With the proper key, the random bits are masked out during decryption, and it makes it pointless whether they were 1s or 0s.

Btw, I'm no expert on encryption either. All I've had is basic 6 to practice off of.

Contributor

Posts: 686
Joined: Tue Mar 06, 2012 9:37 pm
Blog: View Blog (0)

Re: Encryption challenge

Interesting. I'll definitely look into it, when my other pet projects don't get in the way.

So, I'm not getting the plaintext. Is it "hheelloowwoorrllddhheelloowwoorrlldd..." or "hheelloo wwoorrllddhheelloo wwoorrlldd..." or "hheelloo wwoorrlldd hheelloo wwoorrlldd "? I can't fit any of those in ascii in the ciphertext... Or did you use a different encoding? I have to admit, I'm not getting far, this isn't something I did before. I think I can reverse AND and NOR without RNG and then use something like frequency analysis to get randomness out of it. But that's all just speculation for now.

Edit: Ok, so as you know the logic table dictates the following:
A=Text, M = Mask, B = NOR, C = AND
A M B C
0 0 1 0
0 1 0 0
1 0 0 0
1 1 0 1

Which means
iff A or iff B -> M = 0
if not B and ((A&&C) or (not A && not C)) which is equivalent to not B and (A XNOR C) -> M = 1
The other way around: C XNOR M and not B = A.
However, factor in the random number generator and it becomes harder. Am I making any sense here and/or does anyone have a better idea (do tell)?
Free your mind / Think clearly

cyberdrain
Expert

Posts: 2160
Joined: Sun Nov 27, 2011 1:58 pm
Blog: View Blog (0)

Re: Encryption challenge

Sorry I haven't answered this, just missed it by accident.

I'm not exactly understanding your statements with 'iff A or iff B -> M = 0' and 'not B and (A XNOR C) -> M = 1' . Your logic table is correct, and from it you should determine the following:

B = 1 iff A = 0 & M = 0
C = 1 iff A = 1 & M = 1

thus, during encryption, you can use the following assertions:

A = 1 if C = 1
A = 0 if B = 1
A = !M iff !(B & C)

If you really need it, here is the Java functions I use to decrypt this encryption (given the key of course):

desalting: (assuming byte [] aSalterMask = {mask ^ 0xFF, mask} )
Code: Select all
`   public byte[] reverseTransformBytes(byte[] vByteArray) {            byte [] nByteArray = new byte [vByteArray.length];               int tIndex = 0;            for(int i = 0; i < vByteArray.length; i++) {                  nByteArray[i] = (byte)((aSalterMask[tIndex] ^ 0xFF) & vByteArray[i]);                  tIndex++;                  if(tIndex == mNumMasks) {                        tIndex = 0;                     }               }            return nByteArray;         }`

Code: Select all
`   public byte [] reverseTransformBytes(byte [] vByteArray) {            byte [] nByteArray = new byte [vByteArray.length / 2];            for(int i = 0; i < nByteArray.length; i++) {                  nByteArray[i] = (byte)((0xFF ^ vByteArray[i * 2 + 1]) & (vByteArray[i * 2]  | (0xFF ^ mXORMask)));               }            return nByteArray;         }`

The randomness does come in quite painfully, I agree. But there must be some sort of a footprint from this encryption to give it away.

Contributor

Posts: 686
Joined: Tue Mar 06, 2012 9:37 pm
Blog: View Blog (0)

Re: Encryption challenge

I've had some time to kill, so I've been looking at this a bit.

The code snippets that you posted don't compile as-is, and I don't know/care enough about Java to write the rest.

Can you either post either -

1. the complete programs, or
2. some reference data (input, key, output)
Billibus_Maximus
New User

Posts: 8
Joined: Thu Jan 05, 2012 1:51 pm
Blog: View Blog (0)

Re: Encryption challenge

I can't post my whole program, it would take up too much space, plus it would include my entire cryptography project.

Instead I took the given code and plugged into it as simple main():

Code: Select all
`public class EncryptionTest {            public static void main(String [] args) {            String tData = "Hello World!!!";      byte tMask = 0x69;      byte [] tSalterMask = new byte [] {(byte) (tMask ^ 0xFF), tMask};                  //transform string data to bytes      byte [] tByteData = tData.getBytes();            //print the data      System.out.println(new String(tByteData, 0, tByteData.length));      //print every byte of the data seperately in 0x00 form      for(int i = 0; i < tByteData.length; i++) {                  System.out.print(toStringRawByte(tByteData[i]) + ", ");               }      System.out.println();      System.out.println();                  // encrypt      tByteData = transformBytes1(tByteData, tMask);      tByteData = transformBytes2(tByteData, tSalterMask, 2);                  //print the data      System.out.println(new String(tByteData, 0, tByteData.length));      //print every byte of the data seperately in 0x00 form      for(int i = 0; i < tByteData.length; i++) {                  System.out.print(toStringRawByte(tByteData[i]) + ", ");               }      System.out.println();      System.out.println();                  //decrypt      tByteData = reverseTransformBytes2(tByteData, tSalterMask, 2);      tByteData = reverseTransformBytes1(tByteData, tMask);                  //print the data      System.out.println(new String(tByteData, 0, tByteData.length));      //print every byte of the data seperately in 0x00 form      for(int i = 0; i < tByteData.length; i++) {                  System.out.print(toStringRawByte(tByteData[i]) + ", ");               }      System.out.println();      System.out.println();                     }            public static byte [] transformBytes1(byte [] vByteArray, byte mXORMask) {            byte [] nByteArray = new byte [vByteArray.length * 2];            nByteArray[0] = mXORMask;            for(int i = 0; i < vByteArray.length; i++) {                  nByteArray[i * 2] = (byte)(mXORMask & vByteArray[i]);         nByteArray[i * 2 + 1] = (byte)(0xFF ^ (mXORMask | vByteArray[i]));               }            return nByteArray;         }                  public static byte[] transformBytes2(byte[] vByteArray, byte [] aSalterMask, int mNumMasks) {            byte [] nByteArray = new byte [vByteArray.length];               int tIndex = 0;            for(int i = 0; i < vByteArray.length; i++) {                  nByteArray[i] = (byte)(((aSalterMask[tIndex] ^ 0xFF) & vByteArray[i]) | (aSalterMask[tIndex] & getRandomByte()));                  tIndex++;                  if(tIndex == mNumMasks) {                        tIndex = 0;                     }               }            return nByteArray;         }            public static byte [] reverseTransformBytes1(byte [] vByteArray, byte mXORMask) {            byte [] nByteArray = new byte [vByteArray.length / 2];            for(int i = 0; i < nByteArray.length; i++) {                  nByteArray[i] = (byte)((0xFF ^ vByteArray[i * 2 + 1]) & (vByteArray[i * 2]  | (0xFF ^ mXORMask)));               }            return nByteArray;         }            public static byte[] reverseTransformBytes2(byte[] vByteArray, byte [] aSalterMask, int mNumMasks) {            byte [] nByteArray = new byte [vByteArray.length];               int tIndex = 0;            for(int i = 0; i < vByteArray.length; i++) {                  nByteArray[i] = (byte)((aSalterMask[tIndex] ^ 0xFF) & vByteArray[i]);                  tIndex++;                  if(tIndex == mNumMasks) {                        tIndex = 0;                     }               }            return nByteArray;         }            public static byte getRandomByte() {            return (byte)(Math.random() * 256);         }            public static String toStringRawByte(byte vByte) {            String tString = "0x";            switch((vByte & 0xF0) >> 4) {            case 0x0:      {         tString += "0";         break;      }      case 0x1:      {         tString += "1";         break;      }      case 0x2:      {         tString += "2";         break;      }      case 0x3:      {         tString += "3";         break;      }      case 0x4:      {         tString += "4";         break;      }      case 0x5:      {         tString += "5";         break;      }      case 0x6:      {         tString += "6";         break;      }      case 0x7:      {         tString += "7";         break;      }      case 0x8:      {         tString += "8";         break;      }      case 0x9:      {         tString += "9";         break;      }      case 0xA:      {         tString += "A";         break;      }      case 0xB:      {         tString += "B";         break;      }      case 0xC:      {         tString += "C";         break;      }      case 0xD:      {         tString += "D";         break;      }      case 0xE:      {         tString += "E";         break;      }      case 0xF:      {         tString += "F";         break;      }      default:      {         tString += "R";         break;      }            }            switch(vByte & 0xF) {            case 0x0:      {         tString += "0";         break;      }      case 0x1:      {         tString += "1";         break;      }      case 0x2:      {         tString += "2";         break;      }      case 0x3:      {         tString += "3";         break;      }      case 0x4:      {         tString += "4";         break;      }      case 0x5:      {         tString += "5";         break;      }      case 0x6:      {         tString += "6";         break;      }      case 0x7:      {         tString += "7";         break;      }      case 0x8:      {         tString += "8";         break;      }      case 0x9:      {         tString += "9";         break;      }      case 0xA:      {         tString += "A";         break;      }      case 0xB:      {         tString += "B";         break;      }      case 0xC:      {         tString += "C";         break;      }      case 0xD:      {         tString += "D";         break;      }      case 0xE:      {         tString += "E";         break;      }      case 0xF:      {         tString += "F";         break;      }      default:      {         tString += "R";         break;      }            }            return tString;         }         }`

This compiles and runs right off the bat.

Sorry about the white space in some places. It got messed up somehow in copy-pasting from this site.

Contributor

Posts: 686
Joined: Tue Mar 06, 2012 9:37 pm
Blog: View Blog (0)

Re: Encryption challenge

Thanks, that helps.
Billibus_Maximus
New User

Posts: 8
Joined: Thu Jan 05, 2012 1:51 pm
Blog: View Blog (0)

Next