Created
November 6, 2018 21:19
-
-
Save nodech/5c47d5b3fe042df7af1ea3cf153f0340 to your computer and use it in GitHub Desktop.
GF2 tests.
This file contains hidden or 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
'use strict'; | |
const assert = require('assert'); | |
// Code .. | |
console.log(`remainder => ${ffmul25(26, 5)}`); | |
{ | |
const mul = ffmul25(0x1d, 0x02); | |
console.log(`0x1d(29) * 0x02(2) mod 0x29(41) = ${byte2hex(mul)}(${mul})`) | |
console.log(`-- | |
(${bit2pol6(0x1d)})\t(0x1d -- 29) | |
* | |
(${bit2pol6(0x02)})\t(0x02 -- 2) | |
mod | |
(${bit2pol6(0x29)})\t(0x29 -- 41) | |
= | |
(${bit2pol6(mul)})\t(0x13 -- 19) | |
--`); | |
} | |
/** | |
* Multiplication with generator | |
* and log/exp tables. | |
* We use simplest generator x + 1 over GF(2^8). | |
*/ | |
const GENERATOR = 0x03; // x + 1 | |
// generate tables | |
//const GF256_EXP = generateExps(GENERATOR); | |
//const GF256_LOG = generateLogs(GF256_EXP); | |
//console.log(print256(GF256_EXP)); | |
//console.log(print256(GF256_LOG)); | |
const GF256_EXP = [ | |
0x01, 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff, | |
0x1a, 0x2e, 0x72, 0x96, 0xa1, 0xf8, 0x13, 0x35, | |
0x5f, 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4, | |
0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa, | |
0xe5, 0x34, 0x5c, 0xe4, 0x37, 0x59, 0xeb, 0x26, | |
0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31, | |
0x53, 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc, | |
0x4f, 0xd1, 0x68, 0xb8, 0xd3, 0x6e, 0xb2, 0xcd, | |
0x4c, 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7, | |
0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88, | |
0x83, 0x9e, 0xb9, 0xd0, 0x6b, 0xbd, 0xdc, 0x7f, | |
0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a, | |
0xb5, 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0, | |
0x0b, 0x1d, 0x27, 0x69, 0xbb, 0xd6, 0x61, 0xa3, | |
0xfe, 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec, | |
0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0, | |
0xfb, 0x16, 0x3a, 0x4e, 0xd2, 0x6d, 0xb7, 0xc2, | |
0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41, | |
0xc3, 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0, | |
0x5b, 0xed, 0x2c, 0x74, 0x9c, 0xbf, 0xda, 0x75, | |
0x9f, 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e, | |
0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80, | |
0x9b, 0xb6, 0xc1, 0x58, 0xe8, 0x23, 0x65, 0xaf, | |
0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54, | |
0xfc, 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09, | |
0x1b, 0x2d, 0x77, 0x99, 0xb0, 0xcb, 0x46, 0xca, | |
0x45, 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91, | |
0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e, | |
0x12, 0x36, 0x5a, 0xee, 0x29, 0x7b, 0x8d, 0x8c, | |
0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17, | |
0x39, 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd, | |
0x1c, 0x24, 0x6c, 0xb4, 0xc7, 0x52, 0xf6, 0x01 | |
]; | |
const GF256_LOG = [ | |
-0x1, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, | |
0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03, | |
0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, | |
0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1, | |
0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, | |
0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78, | |
0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, | |
0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e, | |
0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, | |
0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38, | |
0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, | |
0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10, | |
0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, | |
0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba, | |
0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, | |
0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57, | |
0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, | |
0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8, | |
0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, | |
0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0, | |
0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, | |
0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7, | |
0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, | |
0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d, | |
0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, | |
0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1, | |
0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, | |
0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab, | |
0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, | |
0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5, | |
0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, | |
0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07 | |
]; | |
console.log(`0xb6 * 0x53 mod 0x1b = ${byte2hex(ffmul28(0xb6, 0x53, 0x1b))}`) | |
console.log(`0xb6 * 0x53 mod 0x1b = ${byte2hex(ffmulFast(0xb6, 0x53))}`); | |
// functions .. | |
/** | |
* GF(32) Addition and Multiplication | |
*/ | |
/** | |
* Addition for coeffients | |
* @param {Number} a - 5 bits | |
* @param {Number} b - 5 bits | |
*/ | |
function add2(a, b) { | |
assert(typeof a === 'number', 'a must be a number.'); | |
assert(typeof b === 'number', 'b must be a number.'); | |
// take only five bits | |
a = a & 0x1f; | |
b = b & 0x1f; | |
return a ^ b; | |
} | |
/** | |
* This function will compute multiplication of two | |
* polynomials withing GF(2^5) | |
* @param {Number} a - 5 bits will be used | |
* @param {Number} b - only 5 bits will be used and | |
*/ | |
function mul2(a, b) { | |
// take only five bits | |
a = a & 0x1f; | |
b = b & 0x1f; | |
let r = 0; | |
// if we have a(x) * x^0 | |
if (a & 0x01) r ^= b << 0; // r' = r(x) + b(x) * x^0 | |
// if we have a(x) * x^1 | |
if (a & 0x02) r ^= b << 1; // r' = r(x) + b(x) * x^1 | |
// ... | |
if (a & 0x04) r ^= b << 2; | |
if (a & 0x08) r ^= b << 3; | |
if (a & 0x10) r ^= b << 4; | |
return r; | |
} | |
function ffmul2(a, b, m, d) { | |
a = a & 0xff; | |
b = b & 0xff; | |
m = m & 0xff; | |
d = d & 0xff; | |
let r = 0; | |
let t; | |
while (a != 0) { | |
// do we have coeffient? | |
if ((a & 1) != 0) | |
r ^= b; // then add those coeffient. | |
t = b & d; // highest degree? | |
b <<= 1; | |
// if we have higher degree then subtract m | |
if (t != 0) | |
b ^= m; | |
a >>>= 1; | |
} | |
return r; | |
} | |
/** | |
* This function will multiply two polynomials | |
* over GF(2) with maximum degree of 5 | |
* @param {Number} a | |
* @param {Number} b | |
* @param {Number} [m=x^5 + x^3 + 1] - modulo | |
* @returns {Number} | |
*/ | |
function ffmul25(a, b, m = 0x29) { | |
return ffmul2(a & 0x1f, b & 0x1f, m, 0x10); | |
} | |
/** | |
* Same as ffmul25, but with max degree of 8 | |
* @param {Number} a | |
* @param {Number} b | |
* @param {Number} m | |
* @returns {Number} | |
*/ | |
function ffmul28(a, b, m) { | |
return ffmul2(a, b, m, 0x80); | |
} | |
/** | |
* ffmul210, max degree ?? | |
* @param {Number} a | |
* @param {Number} b | |
* @param {Number} [m=???] - modulo | |
* @returns {Number} | |
*/ | |
function ffmul210(a, b, m) { | |
return ffmul2(a & 0x3ff, b & 0x3ff, m, 0x400); | |
} | |
/** | |
* Polynomial multiplication over GF(2^8) | |
* using precomputed tables | |
* @param {Number} a | |
* @param {Number} b | |
* @returns {Number} | |
*/ | |
function ffmulFast(a, b) { | |
if (a === 0 || b === 0) | |
return 0; | |
let t = GF256_LOG[a] + GF256_LOG[b]; | |
if (t > 0xff) | |
t -= 255; | |
return GF256_EXP[t]; | |
} | |
function generateExps(generator) { | |
const exps = new Array(256); | |
let x = 0x01; | |
exps[0] = x; | |
for (let i = 1; i < 256; i++) { | |
const y = ffmul28(x, GENERATOR, 0x1b); | |
exps[i] = y; | |
x = y; | |
} | |
return exps; | |
} | |
function generateLogs(exps) { | |
const logs = new Array(256); | |
logs[1] = 0; | |
for (let i = 1; i < 255; i++) { | |
logs[exps[i] & 0xff] = i; | |
} | |
return logs; | |
} | |
/** | |
* Helpers | |
*/ | |
// format binary | |
function fb(a, bits = 5) { | |
return ('0'.repeat(bits) + a.toString(2)).slice(-bits); | |
} | |
// for print256 | |
function byte2hex(a) { | |
if (!Number.isInteger(a)) return '-0x1'; | |
return '0x' + ('00' + a.toString(16)).slice(-2); | |
} | |
// print 6 bit representation as polynomial | |
function bit2pol6(n) { | |
let pol = ''; | |
if (n & 0x20) pol += '+ x^5 '; | |
if (n & 0x10) pol += '+ x^4 '; | |
if (n & 0x08) pol += '+ x^3 '; | |
if (n & 0x04) pol += '+ x^2 '; | |
if (n & 0x02) pol += '+ x^1 '; | |
if (n & 0x01) pol += '+ 1 '; | |
return pol.substring(2, pol.length - 1); | |
} | |
// hex print tables for GF(256) | |
function print256(table) { | |
const str = []; | |
str.push('[\n'); | |
while (table.length > 0) { | |
str.push(' '); | |
for (let i = 0; i < 8; i++) | |
str.push(byte2hex(table.shift()), ', '); | |
str.push('\n'); | |
} | |
str.splice(-2, 1); | |
str.push(']'); | |
return str.join(''); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment