Files
xgcl/sm/sm4/experiment/affine.go
T
2026-05-27 23:03:00 +08:00

136 lines
3.5 KiB
Go

package experiment
// return x·y
func DotProd(x, y []byte) byte {
var z byte
for i := 0; i < len(x); i++ {
z ^= x[i] & y[i]
}
return z
}
var M1 = [][]byte{
{0, 0, 1, 1, 0, 0, 1, 0},
{0, 0, 0, 1, 0, 1, 0, 0},
{1, 0, 1, 1, 1, 1, 1, 0},
{1, 0, 0, 1, 1, 1, 0, 1},
{0, 1, 0, 1, 1, 0, 0, 0},
{0, 1, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 1, 0, 1, 0},
{1, 0, 1, 1, 1, 0, 1, 0},
}
var M2 = [][]byte{
{0, 0, 0, 1, 0, 0, 1, 0},
{0, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 1, 1, 0, 0, 1, 0},
{1, 1, 1, 0, 0, 0, 1, 0},
{1, 0, 1, 0, 0, 1, 1, 0},
{1, 0, 1, 1, 1, 0, 0, 0},
{0, 1, 0, 1, 1, 1, 0, 1},
{1, 1, 0, 0, 1, 0, 1, 1},
}
var A = [][]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 M2A = [][]byte{
{1, 1, 0, 0, 1, 1, 1, 1},
{1, 1, 0, 1, 0, 1, 0, 1},
{0, 0, 1, 0, 1, 1, 0, 0},
{1, 0, 0, 1, 0, 1, 0, 1},
{0, 0, 1, 0, 1, 1, 1, 0},
{0, 1, 1, 0, 0, 1, 0, 1},
{1, 0, 1, 0, 1, 1, 0, 1},
{1, 0, 0, 1, 0, 0, 0, 1},
}
var c = []byte{1, 1, 0, 0, 0, 1, 1, 0}
var c2 = []byte{0, 0, 1, 1, 0, 1, 1, 0}
var c3 = []byte{1, 1, 0, 0, 1, 0, 1, 1}
func MatrixMulVector(M [][]byte, N []byte) []byte {
r := make([]byte, 8)
for i := 0; i < 8; i++ {
r[i] = DotProd(M[i], N)
}
return r
}
func MatrixMul(M, N [][]byte) [][]byte {
R := make([][]byte, 8)
for i := 0; i < 8; i++ {
R[i] = make([]byte, 8)
}
for i := 0; i < 8; i++ {
for j := 0; j < 8; j++ {
s := byte(0)
for k := 0; k < 8; k++ {
s += M[i][k] * N[k][j]
}
R[i][j] = s % 2
}
}
return R
}
// 8*4
func CreatTable(M [][]byte, D byte) ([]byte, []byte) {
var ml, mh [16]byte
for i := byte(0); i < 16; i++ {
var buf = []byte{i & 1, (i >> 1) & 1, (i >> 2) & 1, (i >> 3) & 1}
// ml[i] = ((DotProd(M[0][:4], buf) << 0) | (DotProd(M[1][:4], buf) << 1) |
// (DotProd(M[2][:4], buf) << 2) | (DotProd(M[3][:4], buf) << 3) |
// (DotProd(M[4][:4], buf) << 4) | (DotProd(M[5][:4], buf) << 5) |
// (DotProd(M[6][:4], buf) << 6) | (DotProd(M[7][:4], buf) << 7)) ^ 0x0e // C1=[0, 1, 1, 1, 1, 1, 0, 0]
// mh[i] = ((DotProd(M[0][4:], buf) << 0) | (DotProd(M[1][4:], buf) << 1) |
// (DotProd(M[2][4:], buf) << 2) | (DotProd(M[3][4:], buf) << 3) |
// (DotProd(M[4][4:], buf) << 4) | (DotProd(M[5][4:], buf) << 5) |
// (DotProd(M[6][4:], buf) << 6) | (DotProd(M[7][4:], buf) << 7)) ^ 0x30 // C1=[0, 1, 1, 1, 1, 1, 0, 0]
ml[i] = ((DotProd(M[0][:4], buf) << 0) | (DotProd(M[1][:4], buf) << 1) |
(DotProd(M[2][:4], buf) << 2) | (DotProd(M[3][:4], buf) << 3) |
(DotProd(M[4][:4], buf) << 4) | (DotProd(M[5][:4], buf) << 5) |
(DotProd(M[6][:4], buf) << 6) | (DotProd(M[7][:4], buf) << 7)) ^ (D & 0xf)
mh[i] = ((DotProd(M[0][4:], buf) << 0) | (DotProd(M[1][4:], buf) << 1) |
(DotProd(M[2][4:], buf) << 2) | (DotProd(M[3][4:], buf) << 3) |
(DotProd(M[4][4:], buf) << 4) | (DotProd(M[5][4:], buf) << 5) |
(DotProd(M[6][4:], buf) << 6) | (DotProd(M[7][4:], buf) << 7)) ^ (D & 0xf0)
}
return ml[:], mh[:]
}
// return A*v in GF(2)^8
func Transform(A [][]byte, in *ffe) *ffe {
r := new(ffe)
for i := 0; i < 8; i++ {
for j := 0; j < 8; j++ {
r.v[i] += A[i][j] * in.v[j]
}
r.v[i] = r.v[i] % 2
}
return r
}
func M1Transform(a byte) byte {
var M1 = [][]byte{
{0, 0, 1, 1, 0, 0, 1, 0},
{0, 0, 0, 1, 0, 1, 0, 0},
{1, 0, 1, 1, 1, 1, 1, 0},
{1, 0, 0, 1, 1, 1, 0, 1},
{0, 1, 0, 1, 1, 0, 0, 0},
{0, 1, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 1, 0, 1, 0},
{1, 0, 1, 1, 1, 0, 1, 0},
}
ml, mh := CreatTable(M1, 0x3e)
return ml[a&0xf] ^ mh[a>>4]
}