Example #1
0
func (tyi TyiTable) Get(i byte) (out [4]byte) {
	// Calculate dot product of i and [0x02 0x01 0x01 0x03]
	j := number.ByteFieldElem(i)

	a := byte(number.ByteFieldElem(0x02).Mul(j))
	b := byte(number.ByteFieldElem(0x01).Mul(j))
	c := byte(number.ByteFieldElem(0x03).Mul(j))

	// Merge into one output and rotate according to column.
	res := [4]byte{a, b, b, c}
	copy(out[:], append(res[(4-tyi):], res[0:(4-tyi)]...))

	return
}
Example #2
0
// generateSelfEquivalence returns a random self-equivalence of the S-box layer, so that \zeta(x) = bInv(\zeta(a(x))).
func generateSelfEquivalence(r io.Reader) (a, bInv encoding.Block) {
	// Sample a byte-wise permutation to apply to the input.
	p := &permutation{encoding.GenerateShuffle(r)}

	// Sample one non-zero scalar for each byte. Each byte of the input is multiplied by this scalar.
	buff := make([]byte, 1)
	scalars := encoding.ConcatenatedBlock{}

	for pos := 0; pos < 16; {
		r.Read(buff)
		if buff[0] != 0x00 {
			scalars[pos] = encoding.NewByteMultiplication(number.ByteFieldElem(buff[0]))
			pos++
		}
	}

	// Sample a random value in [0, 8) for each byte. This is the number of times to apply the Frobenius.
	frobs := encoding.ConcatenatedBlock{}
	for pos := 0; pos < 16; pos++ {
		r.Read(buff)
		frobs[pos] = frobenius(buff[0] & 0x7)
	}

	return encoding.ComposedBlocks{
			frobs, scalars, p,
		}, encoding.ComposedBlocks{
			encoding.InverseBlock{p}, scalars, encoding.InverseBlock{frobs},
		}
}
Example #3
0
func unMixColumns(i, j byte) [4]byte {
	k, l := number.ByteFieldElem(i), number.ByteFieldElem(j)

	var a, b, c, d number.ByteFieldElem

	a = number.ByteFieldElem(0x0e).Mul(k)
	b = number.ByteFieldElem(0x09).Mul(k)
	c = number.ByteFieldElem(0x0d).Mul(k)
	d = number.ByteFieldElem(0x0b).Mul(k)

	a = number.ByteFieldElem(0x0b).Mul(l).Add(a)
	b = number.ByteFieldElem(0x0e).Mul(l).Add(b)
	c = number.ByteFieldElem(0x09).Mul(l).Add(c)
	d = number.ByteFieldElem(0x0d).Mul(l).Add(d)

	return [4]byte{byte(a), byte(b), byte(c), byte(d)}
}
Example #4
0
func (f frobenius) Encode(in byte) (out byte) {
	temp := number.ByteFieldElem(in)
	for i := 0; i < int(f); i++ {
		temp = temp.Mul(temp)
	}

	return byte(temp)
}
Example #5
0
func (f frobenius) Decode(in byte) (out byte) {
	temp := number.ByteFieldElem(in)
	g := (8 - int(f)) % 8
	for i := 0; i < g; i++ {
		temp = temp.Mul(temp)
	}

	return byte(temp)
}
Example #6
0
// Decrypt decrypts the first block in src into dst. Dst and src may point at the same memory.
func (constr Construction) Decrypt(dst, src []byte) {
	state := gfmatrix.NewRow(128)
	for pos := 0; pos < 128; pos++ {
		state[pos] = number.ByteFieldElem(src[pos])
	}

	state = constr.decrypt(state)

	for pos := 0; pos < 128; pos++ {
		dst[pos] = byte(state[pos])
	}
}
Example #7
0
// stripScalars gets rid of unknown scalars in each block of the affine layer. It leaves it exactly equal to MixColumns,
// but there is an unknown scalar in each block that will move into the S-box layers.
func (al *affineLayer) stripScalars() (encoding.ConcatenatedBlock, encoding.ConcatenatedBlock) {
	input, output := [16]encoding.ByteLinear{}, [16]encoding.ByteLinear{}

	for pos := 0; pos < 16; pos += 4 {
		found := false

		for guess := 1; guess < 256 && !found; guess++ { // Take a guess for the input scalar on the first column.
			input[pos], _ = encoding.DecomposeByteLinear(encoding.NewByteMultiplication(number.ByteFieldElem(guess)))

			// Given input scalar on first column, calculate output scalars on all rows.
			for i := pos; i < pos+4; i++ {
				mc, _ := mixColumns[i%4][0].Invert()
				output[i] = encoding.NewByteLinear(
					al.getBlock(i, pos).Compose(input[pos].Backwards).Compose(mc),
				)
			}

			// Given output scalar on each row, calculate input scalars on all columns.
			for i := pos + 1; i < pos+4; i++ {
				mc, _ := mixColumns[0][i%4].Invert()
				input[i] = encoding.NewByteLinear(
					al.getBlock(pos, i).Compose(output[pos].Backwards).Compose(mc),
				)
			}

			// Verify that guess is consistent.
			found = true

			for i := pos; i < pos+4 && found; i++ {
				for j := pos; j < pos+4 && found; j++ {
					cand := al.getBlock(i, j).Compose(output[i].Backwards).Compose(input[j].Backwards)
					real := mixColumns[i%4][j%4]

					if !cand.Equals(real) {
						found = false
					}
				}
			}
		}

		if !found {
			panic("Failed to disambiguate block affine layer!")
		}
	}

	in, out := encoding.ConcatenatedBlock{}, encoding.ConcatenatedBlock{}
	for pos := 0; pos < 16; pos++ {
		in[pos], out[pos] = input[pos], output[pos]
	}

	return in, out
}
Example #8
0
// Expand takes a value from AES's space and embeds it in BES's space.
func Expand(in []byte) gfmatrix.Row {
	out := gfmatrix.NewRow(8 * len(in))

	for k, v := range in {
		num := number.ByteFieldElem(v)

		for pos := 0; pos < 8; pos++ {
			out[8*k+pos] = num
			num = num.Mul(num)
		}
	}

	return out
}
Example #9
0
func mixColumns(i, j byte) [4]byte {
	k, l := number.ByteFieldElem(i), number.ByteFieldElem(j)

	var a, b, c, d number.ByteFieldElem

	a = number.ByteFieldElem(0x02).Mul(k)
	b = number.ByteFieldElem(0x01).Mul(k)
	d = number.ByteFieldElem(0x03).Mul(k)

	a = number.ByteFieldElem(0x03).Mul(l).Add(a)
	c = number.ByteFieldElem(0x01).Mul(l)
	d = c.Add(d)
	c = c.Add(b)
	b = number.ByteFieldElem(0x02).Mul(l).Add(b)

	return [4]byte{byte(a), byte(b), byte(c), byte(d)}
}
Example #10
0
// UnMixColumn is the inverse of MixColumn.
func (constr *Construction) UnMixColumn(slice []byte) {
	column := number.ArrayRingElem{
		number.ByteFieldElem(slice[0]), number.ByteFieldElem(slice[1]),
		number.ByteFieldElem(slice[2]), number.ByteFieldElem(slice[3]),
	}.Mul(number.ArrayRingElem{
		number.ByteFieldElem(0x0e), number.ByteFieldElem(0x09),
		number.ByteFieldElem(0x0d), number.ByteFieldElem(0x0b),
	})

	for i := 0; i < 4; i++ {
		if len(column) > i {
			slice[i] = byte(column[i])
		} else {
			slice[i] = 0x00
		}
	}
}
Example #11
0
// SubByte is AES' S-box. It is a bijection.
func (constr *Construction) SubByte(e byte) byte {
	// AES S-Box
	m := matrix.Matrix{ // Linear component.
		matrix.Row{0xF1}, // 0b11110001
		matrix.Row{0xE3}, // 0b11100011
		matrix.Row{0xC7}, // 0b11000111
		matrix.Row{0x8F}, // 0b10001111
		matrix.Row{0x1F}, // 0b00011111
		matrix.Row{0x3E}, // 0b00111110
		matrix.Row{0x7C}, // 0b01111100
		matrix.Row{0xF8}, // 0b11111000
	}
	a := byte(0x63) // 0b01100011 - Affine component.

	return m.Mul(matrix.Row{byte(number.ByteFieldElem(e).Invert())})[0] ^ a
}
Example #12
0
// UnSubByte is the inverse of SubByte. It is a bijection.
func (constr *Construction) UnSubByte(e byte) byte {
	// AES Inverse S-Box
	m := 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},
	}
	a := byte(0x63)

	invVal := m.Mul(matrix.Row{e ^ a})[0]
	return byte(number.ByteFieldElem(invVal).Invert())
}