%------------------------------------------------------------------------------% % % Chosen Key Differential Cryptanalysis % % Authors: % David Gerault, Marine Minier, Christine Solnon % Published at CP 2016: % Constraint Programming Models for Chosen Key Differential Cryptanalysis % %------------------------------------------------------------------------------% int: n; % Number of rounds int: objective; % Max objective value int: KEY_BITS; % Number of bits in the key int: BLOCK_BITS=128; % Number of bits in the blocks int: KC=KEY_BITS div 32; % Number of columns per round of key schedule int: BC=BLOCK_BITS div 32; % Number of columns per round int: NBK=KC + n * BC div KC; % Number of variables to represent the components of the key (cf. paper) array[0..n-2, 0..BC-1, 0..3] of var 0..1: deltaY; % State before ARK array[0..n-1, 0..BC-1,0..3] of var 0..1: deltaX; % State after ARK array[0..n-1, 0..BC-1,0..3] of var 0..1: deltaSR; % State after ShiftRows array[0..n-1, 0..BC-1,0..3] of var 0..1: deltaK; % Key array[0..n-1, 0..BC-1,0..3,0..NBK-1] of var 0..1: Kcomp; % The components of the key array[0..3,0..n-1,0..BC-1,0..n-1,0..BC-1] of var 0..1: eqK; % eqK[i][r1][j1][r2][j2] => The byte values of DeltaK[r1,i,j1] and [r2,i,j2] are equal. array[0..n-1,0..BC-1] of var 0..4: colX; % colX[r][j] = The sum for i in 0..3 of DeltaY[r][i][j] array[0..n-1,0..BC-1] of var 0..4: colSRX; % colSRX[r][j] = The sum for i in 0..3 of SR(DeltaY)[r][i][j] array[0..n-1,0..BC-1] of var 0..4: colK; % colK[r][j] = The sum for i in 0..3 of DeltaK[r][i][j] %The sum to minimize constraint sum(r in 0..n-1, j in 0..BC-1) (colSRX[r,j]) + sum(J in 0..BC*n -1 where J mod KC == KC-1 )(colK[J div BC, J mod BC])=objective; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Initialisation of the redundant variables. constraint forall (r in 0..n-1, j in 0..BC-1) ( colX[r,j]=sum(i in 0..3)(deltaX[r,j,i]) /\ colK[r,j]=sum(i in 0..3)(deltaK[r,j,i]) /\ colSRX[r,j]=sum(i in 0..3)(deltaSR[r,j,i]) ); constraint initKS(deltaK, Kcomp); constraint ARK(deltaY, deltaK, deltaX); %Add Round Key constraint SR(deltaX,deltaSR); % MDS property constraint MC(colSRX,deltaY); % MDS property constraint KS(deltaK,Kcomp,eqK); % Key schedule constraint EQrelations(deltaK,Kcomp,eqK); % If (in byte values) DK[r][i][j] == DK[r2][i][j2] and DK[r2][i][j2] == DK[r3][i][j3] then DK[r][i][j] == DK[r3][i][j3] constraint linearMC(deltaY, deltaK, deltaX,deltaSR,eqK,colSRX); % Cardinalities before and after MC % The search heuristic. solve :: seq_search([ int_search( [colK[J div BC, J mod BC] | J in 0..BC*n -1 where J mod KC == KC-1] ++ [colSRX[r,j] | r in 0..n-1, j in 0..BC-1] , input_order, indomain_min, complete) , int_search( array1d(deltaSR)++ [deltaK[J div BC ,J mod BC,i] | J in 0..BC*n -1, i in 0..3 where J mod KC == KC-1] ++ [colX[J div BC, J mod BC] | J in 0..BC*n -1 where J mod KC==KC-1] ++ [deltaY[J div BC ,J mod BC,i] | J in 0..BC*(n-1) -1, i in 0..3 where J mod KC == KC-1] ++ [deltaK[J div BC,J mod BC,i] | J in 0..BC*n -1, i in 0..3 where J mod KC != KC-1] ++ [colK[J div BC,J mod BC] | J in 0..BC*n -1 where J mod KC != KC-1 ] ++ [colX[J div BC, J mod BC] | J in 0..BC*n -1 where J mod KC!=KC-1] ++ [deltaX[r,j,i] | r in 0..n-1, j in 0..3, i in 0..3] ++ [deltaY[J div BC ,J mod BC,i ] | J in 0..BC*(n-1) -1, i in 0..3 where J mod KC != KC-1] , input_order , indomain_min, complete)]) satisfy; output [ "deltaX = array3d(0..\(n-1), 0..\(BC-1),0..3,\(deltaX));\n" ++"deltaY = array3d(0..\(n-2), 0..\(BC-1),0..3,\(deltaY));\n" ++"deltaK = array3d(0..\(n-1), 0..\(BC-1),0..3,\(deltaK));\n" ++"deltaSR = array3d(0..\(n-1), 0..\(BC-1),0..3,\(deltaSR));\n" ++"%% objective = \(objective);\n" ]; % output [ show([if r>0 then deltaY[r-1,j,i] else 0 endif | j in 0..BC-1] ) ++ " "++show([deltaK[r,j,i] | j in 0..BC-1]) ++ " "++ show([deltaX[r,j,i]| j in 0..BC-1]) ++ " " ++ show([deltaSR[r,j,i] | j in 0..BC-1] ) ++ " "++ if i mod 3==0 /\ i>0 then "\n\n" else "\n" endif ++ if i == 3 /\ r==n-1 then show(objective) else "" endif | r in 0..n-1, i in 0..3]; % regular xor, except 1 xor 1 can be either 0 or 1. predicate XOR(var 0..1: a,var 0..1: b,var 0..1: c) = a+b+c!=1 ; %xor with equivalence propagation predicate XOR2(var 0..1: a,var 0..1: b,var 0..1: c, var 0..1: eqab,var 0..1: eqac, var 0..1: eqbc ) = a+b+c!=1 /\ eqab = 1-c /\ eqac = 1-b /\ eqbc = 1-a ; %Add round key predicate ARK(array[0..n-2,0..3,0..BC-1] of var 0..1: DY, array[0..n-1,0..3,0..BC-1] of var 0..1: DK, array[0..n-1,0..3,0..BC-1] of var 0..1: DX ) = forall(r in 1..n-1,j in 0..BC-1, i in 0..3) ( XOR(DY[r-1,j,i], DK[r,j,i], DX[r,j,i]) ) ; %Shiftrows predicate SR(array[0..n-1,0..3,0..BC-1] of var 0..1: DX,array[0..n-2,0..3,0..BC-1] of var 0..1: DSR) = forall(r in 0..n-1,j in 0..BC-1, i in 0..3) ( DSR[r,j,i]=DX[r,((j+i) mod BC),i] ); % Mixcolumns predicate MC(array[0..n-1,0..BC-1] of var 0..4: CSRX,array[0..n-2,0..3,0..BC-1] of var 0..1: DY) = forall(r in 0..n-2, j in 0..BC-1) ( (CSRX[r,j] + sum(i in 0..3)(DY[r,j,i])) in {0,5,6,7,8} ) ; %Initialization of the components predicate initKS(array[0..n-1,0..BC-1,0..3] of var 0..1: DK, array[0..n-1,0..BC-1,0..3, 0..NBK-1] of var 0..1: Kcomp ) = forall (J in 0..n*BC-1, i in 0..3) ( let {int: r = J div BC, int: j = J mod BC} in forall (k in 0..NBK-1) ( if J (DK[r,j,i]==DK[r2,j2,i])) /\ % EQ(a,b) => A=B EQ[i,r,j,r2,j2] = EQ[i,r2,j2,r,j] /\ % symmetry ((forall(k in 0..NBK-1) (Kcomp[r,j,i,k]==Kcomp[r2,j2,i,k])) -> (EQ[i,r,j,r2,j2]=1)) /\% Va=Vb => EQ(a,b) (DK[r,j,i]+DK[r2,j2,i] + EQ[i,r,j,r2,j2]) != 0 /\ % a+b+EQ(a,b) !=0 forall (J3 in 0..n*BC-1) ( let {int: r3 = J3 div BC, int: j3 = J3 mod BC} in EQ[i,r,j,r3,j3] + EQ[i,r,j,r2,j2] + EQ[i,r2,j2,r3,j3] != 2 %transitivity ) ) ); predicate linearMC(array[0..n-2,0..3,0..BC-1] of var 0..1: DY, array[0..n-1,0..3,0..BC-1] of var 0..1: DK, array[0..n-1,0..3,0..BC-1] of var 0..1: DX, array[0..n-1,0..3,0..BC-1] of var 0..1: DSR, array[0..3,0..n-1,0..BC-1,0..n-1,0..BC-1] of var 0..1: EQ, array[0..n-1,0..BC-1] of var 0..4: CSRX) = forall(J in BC..n*BC-1, J2 in J+1..n*BC-1) ( let {int: r = J div BC, int: j = J mod BC, int: r2 = J2 div BC, int: j2 = J2 mod BC} in let { var bool: DIFF_SX= % SB(A) != SB(B) (bytes). ( exists(i in 0..3) % There is a difference if any of the following is true ( DSR[r-1,j,i] != DSR[r2-1,j2,i] % different bit values \/ DY[r-1,j,i] != DY[r2-1,j2,i] % different after MC (since A==b => MC(A) == MC(B)) \/ EQ[i,r,j,r2,j2] + DX[r,j,i] + DX [r2,j2,i] == 0 % MC(SB(A)) xor K1 + MC(SB(B)) xor K2 = 0 and not(EQ(K1, K2)) \/ ( (EQ[i,r,j,r2,j2] + DK[r,j,i] == 2) /\ (DX[r,j,i] != DX[r2,j2,i]) ) % MC(SB(A)) xor K != MC(SB(B)) xor K ) ), var 0..4: EQ_SRX= sum (i in 0..3) ( % Lower bound on the equalities between SR(SB(A)) and SR(SB(B)) bool2int((DSR[r-1,j,i] + DSR[r2-1,j2,i]) == 0)), var 0..4: EQ_Y= sum (i in 0..3) ( % Lower bound on the equalities between MC(SB(A)) and MC(SB(B)) bool2int((EQ[i,r,j,r2,j2] ==1 /\ DX[r,j,i] + DX [r2,j2,i] == 0) \/ (DY[r-1,j,i] + DY[r2-1,j2,i])==0 ) ) } in % If S(A) != S(B) (in bytes) then MDS property DIFF_SX -> EQ_SRX+EQ_Y <= 3 ) ;