package ro.pub.cs.pp.a51hadoop.algorithm.testing; import ro.pub.cs.pp.a51hadoop.algorithm.HashReducer; /* A reduction function R that maps hash values back into secret values. * * There are many possible implementations for this function, and it's only * important that it behaves pseudorandomly. * * By alternating the hash function with the reduction function, * chains of alternating passwords and hash values are formed. * * * This reducer only changes one digit of the given string * (represented as a number). */ public class DigitReducer implements HashReducer { private int i; private int k; public DigitReducer(int i, int k) { this.i = i; this.k = k; } /* * Apply the current Reducer on the given hash. * * @return a new secret value */ public String apply(String strX) { try { int last_digit = 0; int x = Integer.parseInt(strX); /* * This is a limmited implementation. * * It will not give us pseudorandom strings, * but this will do for testing pourposes. */ switch (i) { case 0: last_digit = i % 3; break; case 1: last_digit = i % 3 + 3; break; case 2: last_digit = i % 3 + 6; break; default: last_digit = 9; break; } /* * Change the last digit */ x = x / 10 * 10 + last_digit; /* * This is done to look like we have many * distinct reducer functions. * * This is required to solve the problem of * collisions with ordinary hash chains by * replacing the single reduction function R * with a sequence of related reduction * functions R1 through Rk. * * This way, in order for two chains to * collide and merge, they must hit the same * value on the same iteration. Consequently, * the final values in each chain will be * identical. A final postprocessing pass can * sort the chains in the table and remove any * "duplicate" chains that have the same final * value as other chains. New chains are then * generated to fill out the table. These * chains are not collision-free (they may * overlap briefly) but they will not merge, * drastically reducing the overall number of * collisions */ x = x ^ k; String ret = "" + x; while(ret.length() < strX.length()) ret = "0" + ret; if (ret.length() > strX.length()) ret = ret.substring(0, strX.length()); return ret; } catch (Exception e) { /* * On error return the original unmodified * string. */ return strX; } } }