func generateMask(rs *random.Source, maskType MaskType, surface Surface) matrix.Matrix { if maskType == RandomMask { label := make([]byte, 16) if surface == Inside { copy(label[:], []byte("MASK Inside")) return rs.Matrix(label, 128) } else { copy(label[:], []byte("MASK Outside")) return rs.Matrix(label, 128) } } else { // Identity mask. return matrix.GenerateIdentity(128) } }
// GenerateKeys creates a white-boxed version of the AES key `key`, with any non-determinism generated by `seed`. func GenerateKeys(key, seed []byte) (out Construction, inputMask, outputMask encoding.BlockAffine) { rs := random.NewSource("Ful Construction", seed) // Generate two completely random affine transformations, to be put on input and output of SPN. input, output := generateAffineMasks(&rs) // Steal key schedule logic from the standard AES construction. contr := saes.Construction{key} roundKeys := contr.StretchedKey() // Generate an SPN which has the input and output masks, but is otherwise un-obfuscated. out[0] = decomposition[0].compose(&blockAffine{ linear: matrix.GenerateIdentity(128), constant: matrix.Row(roundKeys[0]), }).compose(input) copy(out[1:5], decomposition[1:5]) for i := 1; i < 10; i++ { out[4*i+0] = decomposition[0].compose(&blockAffine{ linear: round, constant: matrix.Row(roundKeys[i]).Add(subBytesConst), }).compose(out[4*i+0]) copy(out[4*i+1:4*i+5], decomposition[1:5]) } out[40] = output.compose(&blockAffine{ linear: lastRound, constant: matrix.Row(roundKeys[10]).Add(subBytesConst), }).compose(out[40]) // Sample self-equivalences of the S-box layer and mix them into adjacent affine layers. label := make([]byte, 16) copy(label, []byte("Self-Eq")) r := rs.Stream(label) for i := 0; i < 40; i++ { a, bInv := generateSelfEquivalence(r, stateSize[i%4], compressSize[i%4]) out[i] = a.compose(out[i]) out[i+1] = out[i+1].compose(bInv) } return out, input.BlockAffine(), output.BlockAffine() }