Encryption challenge

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

Encryption challenge

Post by WallShadow on Wed Jul 18, 2012 11:15 am
([msg=68148]see Encryption challenge[/msg])

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 B

for 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


-WallShadow <3

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

Does no one have a solution for this?
User avatar
WallShadow
Contributor
Contributor
 
Posts: 594
Joined: Tue Mar 06, 2012 9:37 pm
Blog: View Blog (0)


Re: Encryption challenge

Post by cyberdrain on Sat Aug 04, 2012 9:20 am
([msg=68506]see Re: Encryption challenge[/msg])

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
User avatar
cyberdrain
Contributor
Contributor
 
Posts: 685
Joined: Sun Nov 27, 2011 1:58 pm
Blog: View Blog (0)


Re: Encryption challenge

Post by WallShadow on Sat Aug 04, 2012 12:57 pm
([msg=68511]see Re: Encryption challenge[/msg])

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?
User avatar
WallShadow
Contributor
Contributor
 
Posts: 594
Joined: Tue Mar 06, 2012 9:37 pm
Blog: View Blog (0)


Re: Encryption challenge

Post by cyberdrain on Sat Aug 04, 2012 3:56 pm
([msg=68516]see Re: Encryption challenge[/msg])

Hey, you make me look stupid :P 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
User avatar
cyberdrain
Contributor
Contributor
 
Posts: 685
Joined: Sun Nov 27, 2011 1:58 pm
Blog: View Blog (0)


Re: Encryption challenge

Post by WallShadow on Sat Aug 04, 2012 8:30 pm
([msg=68527]see Re: Encryption challenge[/msg])

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.
User avatar
WallShadow
Contributor
Contributor
 
Posts: 594
Joined: Tue Mar 06, 2012 9:37 pm
Blog: View Blog (0)


Re: Encryption challenge

Post by cyberdrain on Sun Aug 05, 2012 5:21 pm
([msg=68572]see Re: Encryption challenge[/msg])

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
User avatar
cyberdrain
Contributor
Contributor
 
Posts: 685
Joined: Sun Nov 27, 2011 1:58 pm
Blog: View Blog (0)


Re: Encryption challenge

Post by WallShadow on Fri Aug 17, 2012 6:48 am
([msg=68795]see Re: Encryption challenge[/msg])

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;
      
   }


decrypting: (assuming mXORMask = mask)
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.
User avatar
WallShadow
Contributor
Contributor
 
Posts: 594
Joined: Tue Mar 06, 2012 9:37 pm
Blog: View Blog (0)


Re: Encryption challenge

Post by Billibus_Maximus on Sun Aug 26, 2012 12:23 am
([msg=69030]see Re: Encryption challenge[/msg])

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
New User
 
Posts: 8
Joined: Thu Jan 05, 2012 1:51 pm
Blog: View Blog (0)


Re: Encryption challenge

Post by WallShadow on Sun Aug 26, 2012 10:50 am
([msg=69032]see Re: Encryption challenge[/msg])

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.

-WallShadow <3
User avatar
WallShadow
Contributor
Contributor
 
Posts: 594
Joined: Tue Mar 06, 2012 9:37 pm
Blog: View Blog (0)


Re: Encryption challenge

Post by Billibus_Maximus on Mon Aug 27, 2012 11:11 am
([msg=69043]see Re: Encryption challenge[/msg])

Thanks, that helps.
Billibus_Maximus
New User
New User
 
Posts: 8
Joined: Thu Jan 05, 2012 1:51 pm
Blog: View Blog (0)


Next

Return to Crypto

Who is online

Users browsing this forum: No registered users and 0 guests