Пример #1
0
// generateAffineMasks creates the random external masks for the construction.
func generateAffineMasks(rs *random.Source) (inputMask, outputMask *blockAffine) {
	var inputLinear, outputLinear matrix.Matrix
	common.GenerateMasks(rs, common.IndependentMasks{common.RandomMask, common.RandomMask}, &inputLinear, &outputLinear)

	reader := rs.Stream(make([]byte, 16))

	inputConstant, outputConstant := matrix.NewRow(128), matrix.NewRow(128)
	reader.Read(inputConstant[:])
	reader.Read(outputConstant[:])

	inputMask = &blockAffine{linear: inputLinear, constant: inputConstant}
	outputMask = &blockAffine{linear: outputLinear, constant: outputConstant}

	return
}
Пример #2
0
// isBlockOfInverse takes a candidate solution for the given block of the matrix and returns true if it is valid and
// false if it isn't.
func (al *affineLayer) isBlockOfInverse(block int, cand matrix.Matrix) bool {
	// Pad matrix.
	inv := matrix.GenerateEmpty(32*block, 32)
	for _, row := range cand {
		inv = append(inv, row)
	}
	for row := 0; row < 96-32*block; row++ {
		inv = append(inv, matrix.NewRow(32))
	}

	// Test if this is consistent with inverse.
	res := (*al).BlockLinear.Forwards.Compose(inv).Transpose()

	for i := 0; i < 4; i++ {
		row, pos := res[8*i], blockPos[4*block+i]

		if h := row.Height(); !(16*pos <= h && h < 16*(pos+1)) {
			return false
		}

		if !row[2*(pos+1):].IsZero() {
			return false
		}
	}

	return true
}
Пример #3
0
// generateSelfEquivalence returns a random self-equivalence of the S-box layer, defined by stateSize and compressSize.
func generateSelfEquivalence(r io.Reader, stateSize, compressSize int) (a, bInv *blockAffine) {
	inSize, outSize := 8*(stateSize+compressSize), 8*stateSize
	in := &blockAffine{
		linear:   matrix.GenerateEmpty(inSize, inSize),
		constant: matrix.NewRow(inSize),
	}
	out := &blockAffine{
		linear:   matrix.GenerateEmpty(outSize, outSize),
		constant: matrix.NewRow(outSize),
	}

	// The S-box portion of the self-equivalence.
	forwards, backwards := generatePermutation(r, 8*compressSize)

	for i := 0; i < 8*compressSize; i++ {
		selfEq := generateSboxSelfEq(r)

		in.linear[2*forwards[i]+0].SetBit(2*i+0, selfEq[0])
		in.linear[2*forwards[i]+0].SetBit(2*i+1, selfEq[1])
		in.linear[2*forwards[i]+1].SetBit(2*i+0, selfEq[2])
		in.linear[2*forwards[i]+1].SetBit(2*i+1, selfEq[3])

		in.constant.SetBit(2*forwards[i]+0, selfEq[4])
		in.constant.SetBit(2*forwards[i]+1, selfEq[5])

		out.linear[backwards[i]].SetBit(i, true)
	}

	// The open portion of the self-equivalence. Fill it with a random, invertible matrix.
	ignoreAll := func(_ int) bool { return true }
	dense, denseInv := matrix.GenerateRandomPartial(r, 8*(stateSize-compressSize), matrix.IgnoreNoBytes, ignoreAll)
	for i := 0; i < 8*(stateSize-compressSize); i++ {
		copy(in.linear[8*2*compressSize+i][2*compressSize:], dense[i])
		copy(out.linear[8*compressSize+i][compressSize:], denseInv[i])
	}

	return in, out
}