Last active
October 22, 2021 02:22
-
-
Save emmansun/276941d0bb41445db263c3b977dffe07 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"math/bits" | |
) | |
// https://en.wikipedia.org/wiki/Rijndael_S-box | |
// AES's irreducible polynomial is x^8+x^4+x^3+x+1 | |
func initAesSbox_1() []byte { | |
sbox := make([]byte, 256) | |
var p, q byte | |
p = 1 | |
q = 1 | |
/* 0 is a special case since it has no inverse */ | |
sbox[0] = 0x63 | |
for { | |
/* multiply p by 3 */ | |
if p&0x80 == 0x80 { | |
p = p ^ (p << 1) ^ 0x1b | |
} else { | |
p = p ^ (p << 1) | |
} | |
/* divide q by 3 (equals multiplication by 0xf6) */ | |
q ^= q << 1 | |
q ^= q << 2 | |
q ^= q << 4 | |
if q&0x80 == 0x80 { | |
q ^= 0x09 | |
} | |
/* compute the affine transformation */ | |
xformated := q ^ bits.RotateLeft8(q, 1) ^ bits.RotateLeft8(q, 2) ^ bits.RotateLeft8(q, 3) ^ bits.RotateLeft8(q, 4) | |
sbox[p] = xformated ^ 0x63 | |
if p == 1 { | |
break | |
} | |
} | |
return sbox | |
} | |
// https://merricx.github.io/aes-sbox/js/sbox.js | |
func initAesSbox_2() []byte { | |
tmp := make([]uint16, 256) | |
var x uint16 | |
//generate elements of GF(2^8) | |
x = 1 | |
for i := 0; i < 256; i++ { | |
tmp[i] = x | |
x ^= (x << 1) ^ ((x >> 7) * 0x11b) // {01}{1b} | |
} | |
sbox := make([]byte, 256) | |
sbox[0] = 0x63 | |
for i := 0; i < 255; i++ { | |
// Take the multiplicative inverse | |
x = tmp[255-i] | |
// compute the affine transformation | |
x |= x << 8 | |
x ^= (x >> 4) ^ (x >> 5) ^ (x >> 6) ^ (x >> 7) | |
sbox[tmp[i]] = byte(x ^ 0x63) | |
} | |
return sbox | |
} | |
// compute the SM4 affine transformation, matrix A= | |
// 1 1 0 1 0 0 1 1 b7 | |
// 1 1 1 0 1 0 0 1 b6 | |
// 1 1 1 1 0 1 0 0 b5 | |
// 0 1 1 1 1 0 1 0 x b4 | |
// 0 0 1 1 1 1 0 1 b3 | |
// 1 0 0 1 1 1 1 0 b2 | |
// 0 1 0 0 1 1 1 1 b1 | |
// 1 0 1 0 0 1 1 1 b0 | |
func sm4L(x byte) byte { | |
return x ^ bits.RotateLeft8(x, 1) ^ bits.RotateLeft8(x, 3) ^ bits.RotateLeft8(x, 6) ^ bits.RotateLeft8(x, 7) ^ 0xd3 | |
} | |
// compute the SM4 inversed affine transformation, matrix A'= | |
// 1 0 1 0 0 0 0 1 b7 | |
// 1 1 0 1 0 0 0 0 b6 | |
// 0 1 1 0 1 0 0 0 b5 | |
// 0 0 1 1 0 1 0 0 x b4 | |
// 0 0 0 1 1 0 1 0 b3 | |
// 0 0 0 0 1 1 0 1 b2 | |
// 1 0 0 0 0 1 1 0 b1 | |
// 0 1 0 0 0 0 1 1 b0 | |
func sm4LInv(x byte) byte { | |
y := x ^ 0xd3 | |
return y ^ bits.RotateLeft8(y, 2) ^ bits.RotateLeft8(y, 7) | |
} | |
// SM4's irreducible polynomial is x^8+x^7+x^6+x^5+x^4+x^2+1 | |
// Sbox(x) = L(Inv(L(x))) | |
func initSm4Sbox_1() []byte { | |
sbox := make([]byte, 256) | |
var i, p, q byte | |
p = 1 | |
q = 1 | |
for { | |
/* multiply p by 3 */ | |
if p&0x80 == 0x80 { | |
p = p ^ (p << 1) ^ 0xf5 | |
} else { | |
p = p ^ (p << 1) | |
} | |
/* divide q by 3 (equals multiplication by 0xac) */ | |
q ^= q << 1 | |
q ^= q << 2 | |
q ^= q << 4 | |
if q&0x80 == 0x80 { | |
q ^= 0x53 | |
} | |
i = sm4LInv(p) | |
/* compute the affine transformation */ | |
sbox[i] = sm4L(q) | |
if p == 1 { | |
break | |
} | |
} | |
/* 0 is a special case since it has no inverse */ | |
sbox[sm4LInv(0)] = sm4L(0) | |
return sbox | |
} | |
// SM4's irreducible polynomial is x^8+x^7+x^6+x^5+x^4+x^2+1 | |
func initSm4Sbox_2() []byte { | |
reverseTable := make(map[byte]byte) | |
tmp := make([]uint16, 256) | |
var x uint16 | |
//generate elements of GF(2^8) | |
x = 1 | |
for i := 0; i < 256; i++ { | |
tmp[i] = x | |
reverseTable[byte(x)] = byte(i) | |
x ^= (x << 1) ^ ((x >> 7) * 0x1f5) // {01}{f5} | |
} | |
sbox := make([]byte, 256) | |
for i := 0; i < 256; i++ { | |
li := sm4L(byte(i)) | |
if li == 0 { | |
sbox[i] = sm4L(0) | |
} else { | |
sbox[i] = sm4L(byte(tmp[255-reverseTable[li]])) | |
} | |
} | |
return sbox | |
} | |
// https://ppfocus.com/0/ed0cb869b.html | |
func initSm4SboxBasedAES() []byte { | |
Saes := initAesSbox_1() | |
sbox := make([]byte, 256) | |
var x byte | |
// Ssm4(x) = L(Saes(Mx+C1)) + C2 | |
// L=[0b11111010, 0b01100100, 0b10110100, 0b00001010, 0b01000001, 0b11011101, 0b00000001, 0b11000001] | |
// L=[0xfa, 0x64, 0xb4, 0x0a, 0x41, 0xdd, 0x01, 0xc1] | |
// M=[0b10010110, 0b01000111, 0b11101001, 0b00111101, 0b11011110, 0b01100101, 0b10101100, 0b10100111] | |
// M=[0x96, 0x47, 0xe9, 0x3d, 0xde, 0x65, 0xac, 0xa7] | |
// C1=0x69 | |
// C2=0x61 | |
for i := 0; i < 256; i++ { | |
x = ((byte(bits.OnesCount8(byte(i)&0x96)) & 1) << 7) ^ | |
((byte(bits.OnesCount8(byte(i)&0x47)) & 1) << 6) ^ | |
((byte(bits.OnesCount8(byte(i)&0xe9)) & 1) << 5) ^ | |
((byte(bits.OnesCount8(byte(i)&0x3d)) & 1) << 4) ^ | |
((byte(bits.OnesCount8(byte(i)&0xde)) & 1) << 3) ^ | |
((byte(bits.OnesCount8(byte(i)&0x65)) & 1) << 2) ^ | |
((byte(bits.OnesCount8(byte(i)&0xac)) & 1) << 1) ^ | |
((byte(bits.OnesCount8(byte(i)&0xa7)) & 1) << 0) ^ 0x69 | |
x = Saes[x] | |
x = ((byte(bits.OnesCount8(byte(x)&0xfa)) & 1) << 7) ^ | |
((byte(bits.OnesCount8(byte(x)&0x64)) & 1) << 6) ^ | |
((byte(bits.OnesCount8(byte(x)&0xb4)) & 1) << 5) ^ | |
((byte(bits.OnesCount8(byte(x)&0x0a)) & 1) << 4) ^ | |
((byte(bits.OnesCount8(byte(x)&0x41)) & 1) << 3) ^ | |
((byte(bits.OnesCount8(byte(x)&0xdd)) & 1) << 2) ^ | |
((byte(bits.OnesCount8(byte(x)&0x01)) & 1) << 1) ^ | |
((byte(bits.OnesCount8(byte(x)&0xc1)) & 1) << 0) ^ 0x61 | |
sbox[i] = x | |
} | |
return sbox | |
} | |
var m1l = [16]byte{0x01, 0x07, 0x72, 0x74, 0xe4, 0xe2, 0x97, 0x91, 0x57, 0x51, 0x24, 0x22, 0xb2, 0xb4, 0xc1, 0xc7} | |
var m1h = [16]byte{0x00, 0xa2, 0x49, 0xeb, 0x09, 0xab, 0x40, 0xe2, 0x12, 0xb0, 0x5b, 0xf9, 0x1b, 0xb9, 0x52, 0xf0} | |
var m2l = [16]byte{0x34, 0x08, 0x9d, 0xa1, 0xce, 0xf2, 0x67, 0x5b, 0x82, 0xbe, 0x2b, 0x17, 0x78, 0x44, 0xd1, 0xed} | |
var m2h = [16]byte{0x00, 0xdc, 0xaf, 0x73, 0xdd, 0x01, 0x72, 0xae, 0xbf, 0x63, 0x10, 0xcc, 0x62, 0xbe, 0xcd, 0x11} | |
// https://github.com/emmansun/sm4ni | |
func initSm4SboxBasedAES_2() []byte { | |
Saes := initAesSbox_1() | |
sbox := make([]byte, 256) | |
var x byte | |
for i := 0; i < 256; i++ { | |
x = m1l[i&0xf] ^ m1h[i>>4] | |
x = Saes[x] | |
x = m2l[x&0xf] ^ m2h[x>>4] | |
sbox[i] = x | |
} | |
return sbox | |
} | |
func initSm4SboxBasedAES_3() []byte { | |
Saes := initAesSbox_1() | |
sbox := make([]byte, 256) | |
var x byte | |
// Ssm4(x) = L(Saes(Mx+C1)) + C2 | |
// L=[0b11111110, 0b01010100, 0b10101111, 0b11011101, 0bffff0111, 0bffff1001, 0b10101100, 0b11100010] | |
// L=[0xfe, 0x54, 0xaf, 0xdd, 0xf7, 0xf9, 0xac, 0xe2] | |
// M=[0b00010100, 0b00101110, 0b00010110, 0b10001010, 0b01100000, 0b00001101, 0b10011011, 0b01100110] | |
// M=[0x14, 0x2e, 0x16, 0x8a, 0x60, 0x0d, 0x9b, 0x66] | |
// C1=0x01 | |
// C2=0x34 | |
for i := 0; i < 256; i++ { | |
x = ((byte(bits.OnesCount8(byte(i)&0x14)) & 1) << 7) ^ | |
((byte(bits.OnesCount8(byte(i)&0x2e)) & 1) << 6) ^ | |
((byte(bits.OnesCount8(byte(i)&0x16)) & 1) << 5) ^ | |
((byte(bits.OnesCount8(byte(i)&0x8a)) & 1) << 4) ^ | |
((byte(bits.OnesCount8(byte(i)&0x60)) & 1) << 3) ^ | |
((byte(bits.OnesCount8(byte(i)&0x0d)) & 1) << 2) ^ | |
((byte(bits.OnesCount8(byte(i)&0x9b)) & 1) << 1) ^ | |
((byte(bits.OnesCount8(byte(i)&0x66)) & 1) << 0) ^ 0x01 | |
x = Saes[x] | |
x = ((byte(bits.OnesCount8(byte(x)&0xfe)) & 1) << 7) ^ | |
((byte(bits.OnesCount8(byte(x)&0x54)) & 1) << 6) ^ | |
((byte(bits.OnesCount8(byte(x)&0xaf)) & 1) << 5) ^ | |
((byte(bits.OnesCount8(byte(x)&0xdd)) & 1) << 4) ^ | |
((byte(bits.OnesCount8(byte(x)&0xf7)) & 1) << 3) ^ | |
((byte(bits.OnesCount8(byte(x)&0xf9)) & 1) << 2) ^ | |
((byte(bits.OnesCount8(byte(x)&0xac)) & 1) << 1) ^ | |
((byte(bits.OnesCount8(byte(x)&0xe2)) & 1) << 0) ^ 0x34 | |
sbox[i] = x | |
} | |
return sbox | |
} | |
func printSbox(sbox []byte) { | |
for i := 0; i < len(sbox); i++ { | |
fmt.Printf("%02x ", sbox[i]) | |
if i > 0 && (i+1)%16 == 0 { | |
fmt.Println() | |
} | |
} | |
} | |
func main() { | |
printSbox(initAesSbox_1()) | |
fmt.Println() | |
printSbox(initAesSbox_2()) | |
fmt.Println() | |
printSbox(initSm4Sbox_1()) | |
fmt.Println() | |
printSbox(initSm4Sbox_2()) | |
fmt.Println() | |
printSbox(initSm4SboxBasedAES()) | |
fmt.Println() | |
printSbox(initSm4SboxBasedAES_2()) | |
fmt.Println() | |
printSbox(initSm4SboxBasedAES_3()) | |
fmt.Println() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment