From 53fd00312abadd399180599b9cd04865343d8275 Mon Sep 17 00:00:00 2001
From: Indrakanti Aishwarya <cb.en.p2cys21014@cb.students.amrita.edu>
Date: Thu, 10 Aug 2023 14:55:27 +0530
Subject: [PATCH] Upload New File

---
 Difference/SecureLCB.py | 159 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 159 insertions(+)
 create mode 100644 Difference/SecureLCB.py

diff --git a/Difference/SecureLCB.py b/Difference/SecureLCB.py
new file mode 100644
index 0000000..02baf97
--- /dev/null
+++ b/Difference/SecureLCB.py
@@ -0,0 +1,159 @@
+# This is a vectorized implementation of the LCB cipher, compatible with our optimizer and neural distinguisher.
+ 
+#### ADDING A CIPHER
+# In order to be compatible with this repo, a cipher implementation must:
+# - Provide plain_bits and key_bits variables, giving respectively the number of bits in the plaintext and in the key.
+# - Provide a vectorized “encrypt(p, k, r)” function, that takes as input, for n samples:
+#       - An n by plain_bits binary matrix p of numpy.uint8 for the plaintexts;
+#       - An n by key_bits binary matrix of numpy.uint8 for the keys;
+#       - A number of rounds r.
+# The encrypt function must return an n by plain_bits matrix of numpy.uint8 containing the ciphertexts. The encrypt function in the provided in this file exemplifies the use of the functions “convert_to_binary” and “convert_from_binary” to translate between binary matrices and the native format of the cipher implementation.
+ 
+import numpy as np
+ 
+plain_bits = 32
+key_bits = 64
+word_size = 16
+ 
+def WORD_SIZE():
+    return(16);
+ 
+S =  [12,5,6,11,9,0,10,13,3,14,15,8,4,7,1,2];
+P = [12,3,7,13,9,8,14,1,4,15,10,5,16,2,6,11];
+L = [1,5,9,13,15,11,7,3,2,6,10,14,16,12,8,4];
+k1 = None
+k2 = None
+k3 = None
+k4 = None
+ 
+ 
+def substitute(x, s):
+    #print("X:",x)
+    y = np.zeros_like(x)
+    for i in range(x.size):
+        temp = x[i]
+        y[i] += s[(temp % 16)]
+        temp = temp >> 4
+        y[i] += (s[temp % 16] << 4)
+        temp = temp >> 4
+        y[i] += (s[temp % 16] << 8)
+        temp = temp >> 4
+        y[i] += (s[temp % 16] << 12)
+    #print("HIIIIIIIIIIIIIIII")
+    #print("y", y)
+    return y
+ 
+def permute(x,p):
+    y = x*0;
+    for i in range(0,16):
+      y+=(x%2)*(2**(16-p[15-i]));
+      x=x>>1;
+    #print("permute:", y)
+    return y;
+ 
+def enc_one_round(p,k):
+    l,r =  p[0], p[1];
+    k1, k2 = k[0], k[1];
+    #p2 = S(p2)
+    r1 = substitute(r, S);
+ 
+    #p2 = P(p2)
+    r2 = permute(r1, P);
+ 
+    #p2 = L(p2)
+    r3 = permute(r2,L);
+ 
+    #p2 = p2^k
+    r4 = r3 ^ k2
+ 
+    #p1 = S(p1)
+    l1 = substitute(l, S);
+ 
+    #p1 = P(p1)
+    l2 = permute(l1, P);
+ 
+    #p1 = L(p1)
+    l3 = permute(l2,L);
+ 
+    #p1 = p1^k
+    l4 = l3 ^ k1
+ 
+    return r4, l4;
+ 
+# The encrypt function must adhere to this format, with p and k being binary matrices representing the plaintexts and the key, and the return value being a binary matrix as well.
+def encrypt(p, ks, nr):
+    p = convert_from_binary(p)
+    global k1, k2, k3, k4
+    x, y = p[:, 0], p[:, 1];
+    #print("BRO!",x,y)
+    ks = convert_from_binary(ks).transpose()
+    #print(ks)
+    #ks = ks.reshape(4,-1);
+    k1, k2, k3, k4 = ks[0], ks[1], ks[2], ks[3]
+    #print("k1,k2,k3,k4:", k1, k2, k3, k4)
+    if(nr == 1):
+    	x, y = enc_one_round((x,y), (k1,k2));
+    elif(nr%2 == 0): 
+        for k in range(int(nr/2)):
+                x, y = enc_one_round((x,y), (k1,k2));
+                k1 = substitute(k1, S)
+                k1 = permute(k1, P)
+                k1 = permute(k1, L)
+                k2 = substitute(k2, S)
+                k2 = permute(k2, P)
+                k2 = permute(k2, L)
+                x, y = enc_one_round((x,y), (k3,k4));
+                k3 = substitute(k3, S)
+                k3 = permute(k3, P)
+                k3 = permute(k3, L)
+                k4 = substitute(k4, S)
+                k4 = permute(k4, P)
+                k4 = permute(k4, L)
+    
+    else:
+        for k in range(int(nr/2)):
+                x, y = enc_one_round((x,y), (k1,k2));
+                k1 = substitute(k1, S)
+                k1 = permute(k1, P)
+                k1 = permute(k1, L)
+                k2 = substitute(k2, S)
+                k2 = permute(k2, P)
+                k2 = permute(k2, L)
+                x, y = enc_one_round((x,y), (k3,k4));
+                k3 = substitute(k3, S)
+                k3 = permute(k3, P)
+                k3 = permute(k3, L)
+                k4 = substitute(k4, S)
+                k4 = permute(k4, P)
+                k4 = permute(k4, L)
+        x, y = enc_one_round((x,y), (k1,k2));
+    	
+    #print("X and y:", x, y)
+    
+    return convert_to_binary([x, y]);
+ 
+#convert_to_binary takes as input an array of ciphertext pairs
+#where the first row of the array contains the lefthand side of the ciphertexts,
+#the second row contains the righthand side of the ciphertexts,
+#the third row contains the lefthand side of the second ciphertexts,
+#and so on
+#it returns an array of bit vectors containing the same data
+def convert_to_binary(arr):
+  X = np.zeros((len(arr) * WORD_SIZE(),len(arr[0])),dtype=np.uint8);
+  for i in range(len(arr) * WORD_SIZE()):
+    index = i // WORD_SIZE();
+    offset = WORD_SIZE() - (i % WORD_SIZE()) - 1;
+    X[i] = (arr[index] >> offset) & 1;
+  X = X.transpose();
+  return(X);
+ 
+# Convert_from_binary takes as input an n by num_bits binary matrix of type np.uint8, for n samples, 
+# and converts it to an n by num_words array of type dtype.
+def convert_from_binary(arr, _dtype=np.uint16):
+  num_words = arr.shape[1]//WORD_SIZE()
+  X = np.zeros((len(arr), num_words),dtype=_dtype);
+  for i in range(num_words):
+    for j in range(WORD_SIZE()):
+        pos = WORD_SIZE()*i+j
+        X[:, i] += 2**(WORD_SIZE()-1-j)*arr[:, pos]
+  return(X);
-- 
GitLab