// FindPartialEncoding takes an affine encoded F and finds the values that strip its output encoding. It returns the // parameters it finds and the input encoding of f up to a key byte. func FindPartialEncoding(constr *chow.Construction, f table.Byte, L, AtildeInv matrix.Matrix) (number.ByteFieldElem, byte, encoding.ByteAffine) { fInv := table.Invert(f) id := encoding.ByteLinear(matrix.GenerateIdentity(8)) SInv := table.InvertibleTable(chow.InvTBox{saes.Construction{}, 0x00, 0x00}) S := table.Invert(SInv) // Brute force the constant part of the output encoding and the beta in Atilde = A_i <- D(beta) for c := 0; c < 256; c++ { for d := 1; d < 256; d++ { cand := encoding.ComposedBytes{ TableAsEncoding{f, fInv}, encoding.ByteAffine{id, byte(c)}, encoding.ByteLinear(AtildeInv), encoding.ByteMultiplication(byte(d)), // D below TableAsEncoding{SInv, S}, } if isAffine(cand) { a, b := DecomposeAffineEncoding(cand) return number.ByteFieldElem(d), byte(c), encoding.ByteAffine{encoding.ByteLinear(a), byte(b)} } } } panic("Failed to strip output encodings!") }
// 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 }
// RecoverAffineEncoded reduces the output encodings of a function to affine transformations. func RecoverAffineEncoded(constr *chow.Construction, inputEnc encoding.Byte, round, inPos, outPos int) (encoding.Byte, table.InvertibleTable) { S := GenerateS(constr, round, inPos/4*4, outPos) _ = FindBasisAndSort(S) qtilde := Qtilde{S} outEnc := qtilde outTable := encoding.ByteTable{ encoding.InverseByte{inputEnc}, encoding.InverseByte{qtilde}, F{constr, round, inPos, outPos, 0x00}, } return outEnc, table.InvertibleTable(outTable) }
func exposeRound(constr *chow.Construction, round, inPos, outPos int) (encoding.Byte, encoding.Byte, table.InvertibleTable) { // Actual input and output encoding for round 1 in position i. in := constr.TBoxTyiTable[round][inPos].(encoding.WordTable).In out := constr.TBoxTyiTable[round+1][shiftRows(outPos)].(encoding.WordTable).In f := F{constr, round, inPos, outPos, 0x00} // R corresponds to an exposed round. // Marginally more intuitive way to write it: V(x) := out.Decode(f.Get(in.Encode(x))) R := table.InvertibleTable(encoding.ByteTable{ encoding.InverseByte{in}, encoding.InverseByte{out}, f, }) return in, out, R }