Thursday, April 25, 2013

I was looking for quick way to 'encrypt' an integer into another integer.  I tried a few things:

I tried using Java Ciphers with 32-bit block size ( ex. "DES/OFB32/NoPadding")

I couldn't make Ciphers work.  The encrypted integers that were returned were not sufficiently distributed in the integer domain....probably because I was doing something wrong... I didn't have time to figure it out.  See java code snippet at the bottom of the message.

I found this code snipped implementing a Fiestel Network

http://wiki.postgresql.org/wiki/Pseudo_encrypt

I made the changes recommended by J. Jancar to implement this:

-- Function: pseudo_encrypt(integer)

-- DROP FUNCTION pseudo_encrypt(integer);

CREATE OR REPLACE FUNCTION pseudo_encrypt(value integer)
  RETURNS integer AS
$BODY$
DECLARE
l1 int;
l2 int;
r1 int;
r2 int;
i int:=0;
BEGIN
 l1:= (VALUE >> 16) & 65535;
 r1:= VALUE & 65535;
 WHILE i < 3 LOOP
   l2 := r1;
   r2 := l1 # ((((1366.0 * r1 + 150889) % 714025) / 714025.0) * 32767)::int;
   l1 := l2;
   r1 := r2;
   i := i + 1;
 END LOOP;
 RETURN ((r1 << 16) + l1);
END;
$BODY$
  LANGUAGE plpgsql IMMUTABLE STRICT
  COST 100;
ALTER FUNCTION pseudo_encrypt(integer)
  OWNER TO thyroid;





Tested x = f(f(x)) on 4 million positive integers, works.

Translated to Java:

    public static int pseudoEncrypt(int data) {
        int l1 = (data >> 16) & 65535;
        int r1 = data & 65535;
        for (int i = 0; i<3 br="" i="">            int l2 = r1;
            //Don't change these constants until and unless we understand this better
            int r2 = l1 ^ (int)((((1366.0 * r1 + 150889) % 714025) / 714025.0) * 32767);
            l1 = l2;
            r1 = r2;
        }
        return (r1 << 16) + l1;
    }


Tested x = f(f(x))Java integers.  Works.




    @Test
    public void test3() throws Exception {
        for (int i=0; i<1000 br="" i="">       
            final String keyString = "YKQ22ROLDQYU6===";
            final String ivParametersString = "TOSHCB6GRJBLC===";
           
            byte[] data = ByteBuffer.allocate(4).putInt(i).array();
   
            SecretKey secretKey = new SecretKeySpec(base32.decode(keyString), "DES");
            final IvParameterSpec iv = new IvParameterSpec(base32.decode(ivParametersString));
            Cipher cipher = Cipher.getInstance("DES/OFB32/NoPadding");
       
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
            //IvParameterSpec iv = new IvParameterSpec(base32.decode(ivDataString));
            byte[] encryptedData = cipher.doFinal(data);
            int intEncrypted = ByteBuffer.wrap(encryptedData).getInt();
           
            cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
            byte[] decryptedData = cipher.doFinal(encryptedData);
   
            Assert.assertArrayEquals(data, decryptedData);
            int intDecrypted = ByteBuffer.wrap(decryptedData).getInt();
            System.out.printf("%s %s %s%n", i, intEncrypted, intDecrypted);
        }
    }


13 762798568 13
14 762798571 14
15 762798570 15
16 762798581 16
17 762798580 17
18 762798583 18
19 762798582 19
20 762798577 20
21 762798576 21
22 762798579 22
23 762798578 23
  <--i be="" br="" distributed="" encrypted="" expecting="" in="" integer="" space.="" the="" to="" values="" was="" widely="">


No comments:

Post a Comment