package experiment // ffe stands for finite field elements type ffe struct { v [8]byte } func NewFFE(in byte) *ffe { r := new(ffe) for i := 0; i < 8; i++ { r.v[i] = (in >> i) & 1 } return r } type gf256 struct { f [9]byte invertTable [256]byte } var sm4Field = &gf256{ f: [9]byte{1, 0, 1, 0, 1, 1, 1, 1, 1}, } var aesField = &gf256{ f: [9]byte{1, 1, 0, 1, 1, 0, 0, 0, 1}, } func (g *gf256) _add(u, v []byte) []byte { l := len(u) if l < len(v) { l = len(v) } r := make([]byte, l) copy(r, u) for i := 0; i < len(v); i++ { r[i] = r[i] ^ v[i] } return r } func (g *gf256) Add(u, v *ffe) *ffe { r := new(ffe) for i := 0; i < 8; i++ { r.v[i] = u.v[i] ^ v.v[i] } return r } // return v*x^n func (g *gf256) _mulxn(v []byte, n int) []byte { buf := make([]byte, n, len(v)+n) buf = append(buf, v[:]...) return buf } func (g *gf256) reduce(v []byte) *ffe { buf := append([]byte{}, v...) for i := len(buf) - 1; i >= 8; i-- { if buf[i] == 1 { buf = g._add(buf, g._mulxn(g.f[:], i-8)) } } r := new(ffe) copy(r.v[:], buf) return r } // vmul return v1*v2 mod m func (g *gf256) Mul(u, v *ffe) *ffe { r := make([]byte, 16) // copy(r, u.v[:]) for i := 0; i < 8; i++ { if v.v[i] == 1 { r = g._add(r, g._mulxn(u.v[:], i)) } } return g.reduce(r) } func (g *gf256) IsOne(v *ffe) bool { if v.v[0] == 0 { return false } for i := 1; i < len(v.v); i++ { if v.v[i] != 0 { return false } } return true } func (g *gf256) makeInverseTable() { g.invertTable[0] = 0 for i := 1; i < 256; i++ { u := NewFFE(byte(i)) for j := 1; j < 256; j++ { if g.IsOne(g.Mul(u, NewFFE(byte(j)))) { g.invertTable[i] = byte(j) break } } } } func init() { aesField.makeInverseTable() sm4Field.makeInverseTable() } func (g *gf256) Invert(v *ffe) *ffe { return NewFFE(g.invertTable[v.Byte()]) } func (e *ffe) Byte() byte { r := byte(0) for i := 0; i < len(e.v); i++ { r = r << 1 r = r | e.v[len(e.v)-1-i] } return r }