gf256 operator*(gf256 a, gf256 b) { unsigned raw_a = a.to_byte(); unsigned raw_b = b.to_byte(); if (raw_a == 0 || raw_b == 0) { return gf256::zero(); } else { auto& t = get_tables(); return gf256(t.exp[(t.log[raw_a] + t.log[raw_b]) % 255]); } }
gf256 operator/(gf256 a, gf256 b) { unsigned raw_a = a.to_byte(); unsigned raw_b = b.to_byte(); if (raw_a == 0) { return gf256::zero(); } else if (raw_b == 0) { throw std::domain_error("division by zero"); } else { auto& t = get_tables(); return gf256(t.exp[(t.log[raw_a] + 255 - t.log[raw_b]) % 255]); } }
static word64 SHARKTransform(word64 a) { static const byte iG[8][8] = { 0xe7, 0x30, 0x90, 0x85, 0xd0, 0x4b, 0x91, 0x41, 0x53, 0x95, 0x9b, 0xa5, 0x96, 0xbc, 0xa1, 0x68, 0x02, 0x45, 0xf7, 0x65, 0x5c, 0x1f, 0xb6, 0x52, 0xa2, 0xca, 0x22, 0x94, 0x44, 0x63, 0x2a, 0xa2, 0xfc, 0x67, 0x8e, 0x10, 0x29, 0x75, 0x85, 0x71, 0x24, 0x45, 0xa2, 0xcf, 0x2f, 0x22, 0xc1, 0x0e, 0xa1, 0xf1, 0x71, 0x40, 0x91, 0x27, 0x18, 0xa5, 0x56, 0xf4, 0xaf, 0x32, 0xd2, 0xa4, 0xdc, 0x71, }; word64 result=0; GF256 gf256(0xf5); for (unsigned int i=0; i<8; i++) for(unsigned int j=0; j<8; j++) result ^= word64(gf256.Multiply(iG[i][j], a>>(56-8*j))) << (56-8*i); return result; }
// apply theta to a roundkey static void SquareTransform (word32 in[4], word32 out[4]) { static const byte G[4][4] = { 0x02U, 0x01U, 0x01U, 0x03U, 0x03U, 0x02U, 0x01U, 0x01U, 0x01U, 0x03U, 0x02U, 0x01U, 0x01U, 0x01U, 0x03U, 0x02U }; GF256 gf256(0xf5); for (int i = 0; i < 4; i++) { word32 temp = 0; for (int j = 0; j < 4; j++) for (int k = 0; k < 4; k++) temp ^= (word32)gf256.Multiply(GETBYTE(in[i], 3-k), G[k][j]) << ((3-j)*8); out[i] = temp; } }
gf256 gf256::exp(unsigned p) { return gf256(get_tables().exp[p % 255]); }