package experiment

import (
	"encoding/binary"
)

var aesA = [][]byte{
	{1, 0, 0, 0, 1, 1, 1, 1},
	{1, 1, 0, 0, 0, 1, 1, 1},
	{1, 1, 1, 0, 0, 0, 1, 1},
	{1, 1, 1, 1, 0, 0, 0, 1},
	{1, 1, 1, 1, 1, 0, 0, 0},
	{0, 1, 1, 1, 1, 1, 0, 0},
	{0, 0, 1, 1, 1, 1, 1, 0},
	{0, 0, 0, 1, 1, 1, 1, 1},
}

var aesC = &ffe{
	v: [8]byte{1, 1, 0, 0, 0, 1, 1, 0},
}

func aesSBox(in byte) byte {
	r := NewFFE(in)
	r = aesField.Invert(r)
	r = Transform(aesA, r)
	r = aesField.Add(r, aesC)
	return r.Byte()
}

func toBytes(x []uint32) []byte {
	data := make([]byte, 16)

	binary.LittleEndian.PutUint32(data[0:], x[0])
	binary.LittleEndian.PutUint32(data[4:], x[1])
	binary.LittleEndian.PutUint32(data[8:], x[2])
	binary.LittleEndian.PutUint32(data[12:], x[3])
	return data
}

func toUints(b []byte) []uint32 {
	r := make([]uint32, 4)
	r[0] = binary.LittleEndian.Uint32(b[0:])
	r[1] = binary.LittleEndian.Uint32(b[4:])
	r[2] = binary.LittleEndian.Uint32(b[8:])
	r[3] = binary.LittleEndian.Uint32(b[12:])
	return r
}

// 模拟aesni指令
// 注意aes是列优先的。
func aesni(a, key []uint32) []uint32 {

	aBuf := toBytes(a)
	kBuf := toBytes(key)

	AesLastRound(aBuf, kBuf)

	return toUints(aBuf)
}
