# Okay to post homework # Ryan Badi, March 31, 2024, Homework 18 #RW(k): a random binary word of length k RW:=proc(k) local ra,i: ra:=rand(0..1): [seq(ra(),i=1..k)]: end: #BinToIn(L): inputs a binary word L and outputs the integer n whose binary representation #it is BinToIn:=proc(L) local k,i: k:=nops(L): #[1,0,1]: 1*2^2+0*2^1+1*2^0 add(L[i]*2^(k-i) , i=1..k): end: #InToBin(n,k): inputs a non-neg. integer n<2^k into its binary representation with #0's in front if neccessary so that it is of length k InToBin:=proc(n,k) local i: #option remember: if ( n>=2^k or n<0) or not (type(n,integer)) then RETURN(FAIL): fi: if k=1 then if n=0 then RETURN([0]): else RETURN([1]): fi: fi: if n<2^(k-1) then RETURN([0,op(InToBin(n,k-1))]): else RETURN([1,op(InToBin(n-2^(k-1),k-1))]): fi: end: #BinFun(F,L): conmverts a function on the integers (mod 2^k) to a function #on binary words BinFun:=proc(F,L) local k: k:=nops(L): InToBin(eval(F,n=BinToIn(L)) mod 2^k,k): end: #Feistel(LR,F): The Feistel transform that takes [L,R]->[R+F(L) mod 2, L] #For example Feistel([1,1,0,1],n->n^5+n); Feistel:=proc(LR,F) local k,L,R: k:=nops(LR): if k mod 2<>0 then RETURN(FAIL): fi: L:=[op(1..k/2,LR)]: R:=[op(k/2+1..k,LR)]: [op(R+ BinFun(F,L) mod 2) , op(L) ]: end: #revFeistel(LR,F): The reverse Feistel transform that takes [L,R]->[R,L+F(R)] #For example Feistel([1,1,0,1],n->n^5+n); revFeistel:=proc(LR,F) local k,L,R: k:=nops(LR): if k mod 2<>0 then RETURN(FAIL): fi: L:=[op(1..k/2,LR)]: R:=[op(k/2+1..k,LR)]: [op(R), op(L + BinFun(F, R) mod 2)]: end: MakeCubic := proc(L, n): if nops(L) <> 20 then return FAIL: fi: return BinToIn([op(1..5,L)]) + BinToIn([op(6..10,L)])*n + BinToIn([op(11..15,L)])*n^2 + BinToIn([op(16..20,L)])*n^3: end: EncodeDES := proc(M, K, r) local keys, cubics, result, i: if nops(M) mod 2 <> 0 or nops(K) <> (20 * r) then return FAIL: fi: keys := [seq(K[20*i-19..20*i],i=1..r)]: cubics := [seq(MakeCubic(keys[i], n), i=1..r)]: result := M: for i from 1 to r do: result := Feistel(result, cubics[i]): od: return result: end: DecodeDES := proc(M, K, r) local keys, cubics, result, i: if nops(M) mod 2 <> 0 or nops(K) <> (20 * r) then return FAIL: fi: keys := [seq(K[20*i-19..20*i], i=1..r)]: cubics := [seq(MakeCubic(keys[i], n), i=1..r)]: result := M: for i from 1 to r do: result := revFeistel(result, cubics[r+1-i]): od: return result: end: