public HashReturn SpongentHash(BitSequence[] data, DataLength databitlen, BitSequence[] hashval) { hashState state = new hashState(); HashReturn res; /* initialize */ res = Init(ref state, hashval); if (res != HashReturn.SUCCESS) return res; int j = 0; /* Absorb available message blocks */ while (databitlen >= rate) { Array.Copy(data, j * R_SizeInBytes, state.messageblock, 0, R_SizeInBytes); #if _PrintState_ Debug.Write("\n"); Debug.Write("m_i\t"); for(int i = 0; i < R_SizeInBytes; i++) Debug.Write(state.messageblock[i].ToString("X")); Debug.Write("\n"); #endif Absorb(ref state); j++; databitlen -= rate; // data += R_SizeInBytes; } /* Pad the remaining bits before absorbing */ if (databitlen > 0) { Array.Copy(data, j * R_SizeInBytes, state.messageblock, 0, ((int)databitlen / 8) + ((int)databitlen % 8 > 0 ? 1 : 0)); state.remainingbitlen = databitlen; } else if (databitlen == 0) { Array.Clear(state.messageblock, 0, R_SizeInBytes); state.remainingbitlen = databitlen; } Pad(ref state); #if _PrintState_ Debug.Write("\n"); Debug.Write("m_i\t"); for(int i = 0; i < R_SizeInBytes; i++) Debug.Write("%02X", state.messageblock[i]); Debug.Write("\n"); #endif Absorb(ref state); state.hashbitlen += rate; /* Squeeze data blocks */ while (state.hashbitlen < hashsize) { Squeeze(ref state); Array.Copy(state.messageblock, 0, hashval, i * R_SizeInBytes, R_SizeInBytes); state.hashbitlen += rate; i++; //hashval += R_SizeInBytes; } Array.Copy(state.value, 0, hashval, i * R_SizeInBytes, R_SizeInBytes); i++; //hashval += R_SizeInBytes; #if _PrintState_ Debug.Write("h_i\t"); for(int i = 0; i < R_SizeInBytes; i++) Debug.Write(state.value[i].ToString("X")); Debug.Write("\n\n"); #endif return HashReturn.SUCCESS; }
//-------------------------------------------------------------------------------------------- void PrintState(ref hashState state) { int i; for (i = nSBox - 1; i >= 0; i--) Debug.Write(state.value[i].ToString("X")); Debug.WriteLine(""); }
//-------------------------------------------------------------------------------------------- HashReturn Squeeze(ref hashState state) { Array.Copy(state.value, state.messageblock, R_SizeInBytes); #if _PrintState_ Debug.Write("h_i\t"); for(int i = 0; i < R_SizeInBytes; i++) Debug.Write("%02X", state.messageblock[i]); Debug.Write("\n\n"); #endif Permute(ref state); return HashReturn.SUCCESS; }
//-------------------------------------------------------------------------------------------- void pLayer(ref hashState state) { int i, j, PermutedBitNo; bit8[] tmp = new bit8[nSBox]; bit8 x, y; for (i = 0; i < nSBox; i++) tmp[i] = 0; for (i = 0; i < nSBox; i++) { for (j = 0; j < 8; j++) { x = (bit8)((state.value[i] >> j) & 0x1); PermutedBitNo = Pi(8 * i + j); y = (bit8)(PermutedBitNo / 8); tmp[y] ^= (bit8)(x << (PermutedBitNo - 8 * y)); } } Array.Copy(tmp, state.value, nSBox); }
//-------------------------------------------------------------------------------------------- void Permute(ref hashState state) { bit16 i, j, IV, INV_IV; switch (version) { case 88808: IV = 0x05; break; case 8817688: IV = 0xC6; break; case 1281288: IV = 0x7A; break; case 128256128: IV = 0xFB; break; case 16016016: IV = 0x45; break; case 16016080: IV = 0x01; break; case 160320160: IV = 0xA7; break; case 22422416: IV = 0x01; break; case 224224112: IV = 0x52; break; case 224448224: IV = 0x105; break; case 25625616: IV = 0x9e; break; case 256256128: IV = 0xfb; break; case 256512256: IV = 0x015; break; } for (i = 0; i < nRounds; i++) { #if _PrintState_ Debug.Write("%3d\t", i); PrintState(state); #endif /* Add counter values */ state.value[0] ^= (bit8)(IV & 0xFF); state.value[1] ^= (bit8)((IV >> 8) & 0xFF); INV_IV = retnuoCl(IV); state.value[nSBox - 1] ^= (bit8)((INV_IV >> 8) & 0xFF); state.value[nSBox - 2] ^= (bit8)(INV_IV & 0xFF); IV = lCounter(IV); /* sBoxLayer layer */ for (j = 0; j < nSBox; j++) state.value[j] = (bit8)sBoxLayer[state.value[j]]; /* pLayer */ pLayer(ref state); } #if _PrintState_ Debug.Write("%3d\t", i); PrintState(state); #endif }
//-------------------------------------------------------------------------------------------- HashReturn Pad(ref hashState state) { int byteind = (int)state.remainingbitlen / 8; /* byte index of remaining byte */ int bitpos = (int)state.remainingbitlen % 8; /* bit position in last byte */ /* make unoccupied bits 0 */ if (bitpos > 0) state.messageblock[byteind] &= (BitSequence)(0xFF << (8 - bitpos)); /* add single 1-bit */ if (bitpos > 0) { state.messageblock[byteind] |= (BitSequence)(0x80 >> (bitpos)); } else { state.messageblock[byteind] = 0x80; } /* add 0-bits until we have rate bits */ byteind++; while (byteind < R_SizeInBytes) { state.messageblock[byteind] = 0; byteind++; } return HashReturn.SUCCESS; }
//-------------------------------------------------------------------------------------------- HashReturn Init(ref hashState state, BitSequence[] hashval) { /* check hashsize and initialize accordingly */ switch (hashsize) { case 88: break; case 128: break; case 160: break; case 224: break; case 256: break; default: return HashReturn.BAD_HASHBITLEN; } Array.Clear(state.value, 0, nSBox); state.hashbitlen = 0; state.remainingbitlen = 0; Array.Clear(hashval, 0, hashsize / 8); return HashReturn.SUCCESS; }
//-------------------------------------------------------------------------------------------- HashReturn Absorb(ref hashState state) { int i; for (i = 0; i < R_SizeInBytes; i++) state.value[i] ^= state.messageblock[i]; Permute(ref state); return HashReturn.SUCCESS; }