func TestFindBasisAndSort(t *testing.T) { constr := fastTestConstruction() S := GenerateS(constr, 0, 0, 0) basis := FindBasisAndSort(S) // Test that each vector is correct in place. for i, perm := range S { vect := [256]byte{} copy(vect[:], table.SerializeByte(FunctionFromBasis(i, basis))) if vect != perm { t.Fatalf("FindBasisAndSort, position #%v is wrong!\n%v\n%v", i, vect, perm) } } // Test composition of two functions. x := table.SerializeByte(table.ComposedBytes{ table.ParsedByte(S[39][:]), table.ParsedByte(S[120][:]), }) y := [256]byte{} copy(y[:], x) if y != S[39^120] { t.Fatalf("Function composition was wrong!\n%v\n%v", x, S[39^120]) } }
// GenerateS creates the set of elements S, of the form fXX(f00^(-1)(x)) = Q(Q^(-1)(x) + b) for indeterminate x is // isomorphic to the additive group (GF(2)^8, xor) under composition. func GenerateS(constr *chow.Construction, round, inPos, outPos int) [][256]byte { f00 := table.InvertibleTable(F{constr, round, inPos, outPos, 0x00}) f00Inv := table.Invert(f00) S := make([][256]byte, 256) for x := 0; x < 256; x++ { copy(S[x][:], table.SerializeByte(table.ComposedBytes{ f00Inv, F{constr, round, inPos, outPos, byte(x)}, })) } return S }
// FindBasisAndSort finds 8 elements of S that act as a basis for S and build isomorphism psi. func FindBasisAndSort(S [][256]byte) (basis []table.Byte) { for len(basis) < 8 { // Until we have a full basis. basis = append(basis, table.ParsedByte(S[1<<uint(len(basis))][:])) // Add the first independent vector to the basis. // Move all (now) dependent vectors from S into their correct position. for i := 1 << uint(len(basis)-1); i < 1<<uint(len(basis)); i++ { vect := [256]byte{} copy(vect[:], table.SerializeByte(FunctionFromBasis(i, basis))) // Move it to the correct position in S. for j := i; j < len(S); j++ { if vect == S[j] { S[i], S[j] = S[j], S[i] break } } } } return }