/* Global assumption:
E<e> := GF(2,6);
V6 := VectorSpace(GF(2), 6);
V24 := VectorSpace(GF(2), 24); */

RoundInv := function(a, unlambda, k)

  a := a + k;
  a := Divide(a,4);
  a := Matrix(E, 1, 4, [Vector2Element(a[1]),
Vector2Element(a[2]), Vector2Element(a[3]),
Vector2Element(a[4])]);
  a := a * unlambda;
  
  
  a := SBinv(a);
  a := Matrix(GF(2), 4, 6, [Element2Vector(a[1][1]),
Element2Vector(a[1][2]), Element2Vector(a[1][3]),
Element2Vector(a[1][4])]);
  a := V24!Join(a); a;
  
  return a;
end function;

Decode := function(a, W)
  local unlambda, k;

  unlambda := MatrixLambdaRSC(64, 4, 12);
  unlambda := unlambda^(-1);
  a := V24!a; a;
  for nround in [1..15] do
    k := KeyScheduleStep3(W, 17-nround);
    a := RoundInv(a, unlambda, k);
  end for;
  k := KeyScheduleStep3(W, 1);
  a := a + k;

  return V24!a;
end function;

BunnyTNInv := function(m, k)
  local W;

  W := KeyScheduleStep1(k);
  W := KeyScheduleStep2(W, 15);

  return Decode(m, W);
end function;