Esempio n. 1
0
// 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!")
}
Esempio n. 2
0
// RecoverEncodings returns the full affine output encoding of affine-encoded f at the given position, as well as the
// input affine encodings for all neighboring bytes up to a key byte.  Returns (out, []in)
func RecoverEncodings(constr *chow.Construction, round, pos int) (encoding.ByteAffine, []encoding.ByteAffine) {
	Ps := make([]encoding.ByteAffine, 4)  // Approximate input encodings.
	Ds := make([]number.ByteFieldElem, 4) // Array of gamma * MC coefficient
	q := byte(0x00)                       // The constant part of the output encoding.

	L := RecoverL(constr, round, pos)
	Atilde := FindAtilde(constr, L)
	AtildeInv, _ := Atilde.Invert()

	for i := 0; i < 4; i++ {
		j := pos/4*4 + i

		inEnc, _ := RecoverAffineEncoded(constr, encoding.IdentityByte{}, round-1, unshiftRows(j), unshiftRows(j))
		_, f := RecoverAffineEncoded(constr, inEnc, round, j, pos)

		var c byte
		Ds[i], c, Ps[i] = FindPartialEncoding(constr, f, L, AtildeInv)
		q ^= c

		if i == 0 {
			q ^= f.Get(0x00)
		}
	}

	DInv, _ := DecomposeAffineEncoding(encoding.ByteMultiplication(FindDuplicate(Ds).Invert()))
	A := Atilde.Compose(DInv)

	return encoding.ByteAffine{encoding.ByteLinear(A), q}, Ps
}
Esempio n. 3
0
func TestFindCharacteristic(t *testing.T) {
	M := matrix.GenerateRandom(rand.Reader, 8)

	A := matrix.GenerateRandom(rand.Reader, 8)
	AInv, _ := A.Invert()

	N, _ := DecomposeAffineEncoding(encoding.ComposedBytes{
		encoding.ByteLinear(A),
		encoding.ByteLinear(M),
		encoding.ByteLinear(AInv),
	})

	if FindCharacteristic(M) != FindCharacteristic(N) {
		t.Fatalf("FindCharacteristic was not invariant!\nM = %2.2x\nA = %2.2x\nN = %2.2x, ", M, A, N)
	}
}
Esempio n. 4
0
func TestDecomposeAffineEncoding(t *testing.T) {
	ae := encoding.ByteAffine{
		encoding.ByteLinear(matrix.Matrix{
			matrix.Row{0xA4},
			matrix.Row{0x49},
			matrix.Row{0x92},
			matrix.Row{0x25},
			matrix.Row{0x4a},
			matrix.Row{0x94},
			matrix.Row{0x29},
			matrix.Row{0x52},
		}),
		0x63,
	}

	m, c := DecomposeAffineEncoding(ae)

	for i := 0; i < 8; i++ {
		if ae.Linear[i][0] != m[i][0] {
			t.Fatalf("Row %v in the linear part is wrong! %v != %v", i, ae.Linear[i][0], m[i][0])
		}
	}

	if ae.Constant != c {
		t.Fatalf("The affine part is wrong! %v != %v", ae.Constant, c)
	}
}
Esempio n. 5
0
func getOutputAffineEncoding(constr, fastConstr *chow.Construction, round, pos int) encoding.ByteAffine {
	_, out, _ := exposeRound(constr, round, pos, pos)
	outEncTilde, _ := RecoverAffineEncoded(fastConstr, encoding.IdentityByte{}, round, pos, pos)
	outAff := encoding.ComposedBytes{out, encoding.InverseByte{outEncTilde}}
	A, b := DecomposeAffineEncoding(outAff)

	return encoding.ByteAffine{encoding.ByteLinear(A), b}
}
Esempio n. 6
0
// FindCharacteristic finds the characteristic number of a matrix.  This number is invariant to matrix similarity.
func FindCharacteristic(A matrix.Matrix) (a byte) {
	AkEnc := encoding.ComposedBytes{}

	for k := uint(0); k < 8; k++ {
		AkEnc = append(AkEnc, encoding.ByteLinear(A))
		Ak, _ := DecomposeAffineEncoding(AkEnc)
		a ^= Ak.Trace() << k
	}

	return
}
Esempio n. 7
0
func verifyIsAffine(t *testing.T, aff encoding.Byte, err string) {
	m, c := DecomposeAffineEncoding(aff)
	test := encoding.ByteAffine{encoding.ByteLinear(m), c}

	for i := 0; i < 256; i++ {
		a, b := aff.Encode(byte(i)), test.Encode(byte(i))
		if a != b {
			t.Fatalf(err, i, a, b)
		}
	}
}
Esempio n. 8
0
func BenchmarkDecomposeAffineEncoding(b *testing.B) {
	aff := encoding.ByteAffine{
		encoding.ByteLinear(matrix.GenerateRandom(rand.Reader, 8)),
		0x60,
	}
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		DecomposeAffineEncoding(aff)
	}
}
Esempio n. 9
0
// RecoverAffineRel returns the affine relationship that maps y_i to y_j (instances of F with affine output encodings),
// both taking input in the (inPos)th position and outputting in the (outPos1)th and (outPos2)th position, respectively.
func RecoverAffineRel(constr *chow.Construction, round, inPos, outPos1, outPos2 int) encoding.ByteAffine {
	_, y_i := RecoverAffineEncoded(constr, encoding.IdentityByte{}, round, inPos, outPos1)
	_, y_j := RecoverAffineEncoded(constr, encoding.IdentityByte{}, round, inPos, outPos2)

	RelEnc := encoding.ComposedBytes{
		TableAsEncoding{table.Invert(y_i), nil},
		TableAsEncoding{y_j, nil},
	}

	L, c := DecomposeAffineEncoding(RelEnc)
	return encoding.ByteAffine{encoding.ByteLinear(L), c}
}
Esempio n. 10
0
// isAffine returns true if the given encoding is affine and false if not.
func isAffine(aff encoding.Byte) bool {
	m, c := DecomposeAffineEncoding(aff)
	test := encoding.ByteAffine{encoding.ByteLinear(m), c}

	for i := 0; i < 256; i++ {
		a, b := aff.Encode(byte(i)), test.Encode(byte(i))
		if a != b {
			return false
		}
	}

	return true
}
Esempio n. 11
0
func TestRecoverL(t *testing.T) {
	MC := [][]number.ByteFieldElem{
		[]number.ByteFieldElem{0x02, 0x01, 0x01, 0x03},
		[]number.ByteFieldElem{0x03, 0x02, 0x01, 0x01},
	}

	constr, _ := testConstruction()
	fastConstr := fastTestConstruction()

	for i := 0; i < 16; i++ {
		L := RecoverL(fastConstr, 1, i)

		outAff := getOutputAffineEncoding(constr, fastConstr, 1, i)

		// L is supposed to equal A_i <- D(beta) <- A_i^(-1)
		// We strip the conjugation by A_i and check that D(beta) is multiplication by an element of GF(2^8).
		DEnc := encoding.ComposedBytes{
			outAff,
			encoding.ByteLinear(L),
			encoding.InverseByte{outAff},
		}
		D, _ := DecomposeAffineEncoding(DEnc)
		Dstr := fmt.Sprintf("%x", D)

		// Calculate what beta should be.
		pos0, pos1 := i%4, (i+1)%4
		beta := MC[0][pos0].Mul(MC[1][pos1]).Mul(MC[0][pos1].Mul(MC[1][pos0]).Invert())

		// Calculate the matrix of multiplication by beta and check that it equals what we derived in D.
		E, _ := DecomposeAffineEncoding(encoding.ByteMultiplication(beta))
		Estr := fmt.Sprintf("%x", E)

		if Dstr != Estr {
			t.Fatalf("A_i^(-1) * L * A_i doesn't equal D(beta)! i = %v\nL = %2.2x\nD = %2.2x\nE = %2.2x\n", i, L, D, E)
		}
	}
}
Esempio n. 12
0
func generateKeys(seed []byte, opts KeyGenerationOpts, out *Construction, inputMask, outputMask *matrix.Matrix, shift func(int) int, skinny func(int) table.Byte, wide func(int, int) table.Word) {
	// Generate input and output encodings.
	switch opts.(type) {
	case IndependentMasks:
		*inputMask = GenerateMask(opts.(IndependentMasks).Input, seed, Inside)
		*outputMask = GenerateMask(opts.(IndependentMasks).Output, seed, Outside)
	case SameMasks:
		mask := GenerateMask(MaskType(opts.(SameMasks)), seed, Inside)
		*inputMask, *outputMask = mask, mask
	case MatchingMasks:
		mask := GenerateMask(RandomMask, seed, Inside)

		*inputMask = mask
		*outputMask, _ = mask.Invert()
	default:
		panic("Unrecognized key generation options!")
	}

	// Generate the Input Mask table and the 10th T-Box/Output Mask table
	for pos := 0; pos < 16; pos++ {
		out.InputMask[pos] = encoding.BlockTable{
			encoding.IdentityByte{},
			BlockMaskEncoding(seed, pos, Inside, shift),
			MaskTable{*inputMask, pos},
		}

		out.TBoxOutputMask[pos] = encoding.BlockTable{
			encoding.ComposedBytes{
				encoding.ByteLinear(MixingBijection(seed, 8, 8, pos)),
				ByteRoundEncoding(seed, 8, pos, Outside),
			},
			BlockMaskEncoding(seed, pos, Outside, shift),
			table.ComposedToBlock{
				skinny(pos),
				MaskTable{*outputMask, pos},
			},
		}
	}

	// Generate the XOR Tables for the Input and Output Masks.
	out.InputXORTable = blockXORTables(seed, Inside, shift)
	out.OutputXORTable = blockXORTables(seed, Outside, shift)

	// Generate round material.
	for round := 0; round < 9; round++ {
		for pos := 0; pos < 16; pos++ {
			// Generate a word-sized mixing bijection and stick it on the end of the T-Box/Tyi Table.
			mb := MixingBijection(seed, 32, round, pos/4)

			// Build the T-Box and Tyi Table for this round and position in the state matrix.
			out.TBoxTyiTable[round][pos] = encoding.WordTable{
				encoding.ComposedBytes{
					encoding.ByteLinear(MixingBijection(seed, 8, round-1, pos)),
					encoding.ConcatenatedByte{
						RoundEncoding(seed, round-1, 2*pos+0, Outside),
						RoundEncoding(seed, round-1, 2*pos+1, Outside),
					},
				},
				encoding.ComposedWords{
					encoding.ConcatenatedWord{
						encoding.ByteLinear(MixingBijection(seed, 8, round, shift(pos/4*4+0))),
						encoding.ByteLinear(MixingBijection(seed, 8, round, shift(pos/4*4+1))),
						encoding.ByteLinear(MixingBijection(seed, 8, round, shift(pos/4*4+2))),
						encoding.ByteLinear(MixingBijection(seed, 8, round, shift(pos/4*4+3))),
					},
					encoding.WordLinear(mb),
					WordStepEncoding(seed, round, pos, Inside),
				},
				wide(round, pos),
			}

			// Encode the inverse of the mixing bijection from above in the MB^(-1) table for this round and position.
			mbInv, _ := mb.Invert()

			out.MBInverseTable[round][pos] = encoding.WordTable{
				encoding.ConcatenatedByte{
					RoundEncoding(seed, round, 2*pos+0, Inside),
					RoundEncoding(seed, round, 2*pos+1, Inside),
				},
				WordStepEncoding(seed, round, pos, Outside),
				MBInverseTable{mbInv, uint(pos) % 4},
			}
		}
	}

	// Generate the High and Low XOR Tables for reach round.
	out.HighXORTable = xorTables(seed, Inside, shift)
	out.LowXORTable = xorTables(seed, Outside, shift)
}