package krypto; public class GalNumber { public static int RIJN_MOD = 0x11B; public static int BITWIDTH = 8; public static int BITMASK = 0xff; public static int DIV_POS = 0; public static int MOD_POS = 1; private static int[] BIT_LUT = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000 }; private int value; public GalNumber() { this.value = 0; } public GalNumber (int in) { value = in & BITMASK; } public GalNumber (GalNumber in) { value = in.value; } public GalNumber div(GalNumber rightOp) { int[] result = new int[2]; result=this.reduce(rightOp); return new GalNumber(result[DIV_POS]); } private int unstrippedMult(GalNumber rightOp) { int result = 0x0; int bitmask=0x0; int ro=rightOp.toInt(); int lo=this.value; int temp=0x0; int actBit; for (int i=0;i<16;i++) { bitmask=(0x1 << i); actBit=ro&bitmask; if (actBit != 0) { temp=lo << i; result ^= temp; } } return result; } public GalNumber mult(GalNumber rightOp) { int [] divmod = new int[2]; GalNumber gn_tmp = new GalNumber(); int tmp = this.unstrippedMult(rightOp); gn_tmp.setVal(tmp); divmod = gn_tmp.reduce(RIJN_MOD); return new GalNumber(divmod[MOD_POS]); } public GalNumber mod(GalNumber rightOp) { int[] result = new int[2]; result=this.reduce(rightOp); return new GalNumber(result[MOD_POS]); } public GalNumber euklid(int modul, GalNumber toInvert) throws Exception { GalNumber a= new GalNumber(modul); GalNumber b=new GalNumber(toInvert); GalNumber r1=new GalNumber(0); GalNumber r2=new GalNumber(1); GalNumber a_new=new GalNumber(0); GalNumber b_new=new GalNumber(0); GalNumber r1_new=new GalNumber(0); GalNumber r2_new=new GalNumber(0); //while (b.toInt() != 1) { while (b.toInt() > 1) { /*if (b.toInt() == 0) { throw new Exception("b became ZERO"); }*/ a_new = b; b_new= a.mod(b); r1_new=r2; r2_new=r1.add( ( a.div(b) ).mult(r2) ); a=a_new; b=b_new; r1=r1_new; r2=r2_new; } return r2; } public GalNumber inv() { GalNumber result = new GalNumber(); try { result = euklid(RIJN_MOD, this); } catch (Exception e) { //System.out.println(e.getMessage()); result.setVal(0); } return result; } public GalNumber add(GalNumber rightOp) { int sum=0; sum=this.value ^ rightOp.toInt(); return new GalNumber(sum); } private int[] reduce(GalNumber rightOp) { return reduce(rightOp.toInt() ); } private int[] reduce(int rightOp) { int [] divmod = new int[2]; divmod[DIV_POS]=0; divmod[MOD_POS]=this.toInt(); int shift = 0; int rightOpMSB=0; int leftOpMSB=0; // Search MSB in right Operand for (int i = BIT_LUT.length - 1; i >= 0; i--) { if ((rightOp & BIT_LUT[i]) != 0) { rightOpMSB = i; break; } } if (this.toInt() == 0) { divmod[DIV_POS]=0; divmod[MOD_POS]=0; return divmod; } if (rightOp == 0){ divmod[DIV_POS]=0; divmod[MOD_POS]=this.toInt(); return divmod; } do { // Search MSB in left Operand for (int i = BIT_LUT.length - 1; i >= 0; i--) { if ((divmod[MOD_POS] & BIT_LUT[i]) != 0) { leftOpMSB = i; break; } } if (leftOpMSB >= rightOpMSB) { // Align the ro to the MSB of the lp and add this shift = leftOpMSB - rightOpMSB; // Save result vor integral div divmod[DIV_POS] = divmod[DIV_POS] ^ (0x1 << shift); // Next polynom for division divmod[MOD_POS] = divmod[MOD_POS] ^ (rightOp << shift); if (divmod[MOD_POS] == 0) return divmod; } } while (leftOpMSB>=rightOpMSB); return divmod; } public GalNumber sub(GalNumber rightOp) { return new GalNumber(this.add(rightOp)); } public int toInt() { return this.value; } public String toHex() { return "'"+Integer.toHexString(this.toInt()).toUpperCase()+"'"; } public String toString() { return Integer.toString(this.value); } public char toChar() { return (char) this.toInt(); } public void setVal(int a) { value=a; } }