import org.npci.upi.security.pinactivitycomponent.CustomBase64; import org.npci.upi.security.pinactivitycomponent.OooOO0O; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Random; public class TestBase64 { static int fails = 0, checks = 0; static void eq(String label, byte[] a, byte[] b) { checks++; if (!Arrays.equals(a, b)) { fails++; System.out.println("MISMATCH " + label); System.out.println(" orig: " + hex(a)); System.out.println(" mine: " + hex(b)); } } static void eq(String label, String a, String b) { checks++; if (!a.equals(b)) { fails++; System.out.println("MISMATCH " + label); System.out.println(" orig: [" + a + "]"); System.out.println(" mine: [" + b + "]"); } } static String hex(byte[] b) { StringBuilder s=new StringBuilder(); for(byte x:b) s.append(String.format("%02x", x&0xff)); return s.toString(); } // static API comparison static void compareStatic(byte[] data, int flags) { eq("encodeToString d="+data.length+" f="+flags, OooOO0O.OooO0OO(data, flags), CustomBase64.encodeToString(data, flags)); eq("encodeBytes d="+data.length+" f="+flags, OooOO0O.OooO0O0(data, flags), CustomBase64.encodeBytes(data, flags)); // ranges for (int off : new int[]{0, 1, data.length/3}) { int len = data.length - off; if (len < 0) continue; byte[] sub = Arrays.copyOfRange(data, off, data.length); eq("encRange d="+data.length+" off="+off+" f="+flags, OooOO0O.OooO0O0(data, off, len, flags), CustomBase64.encodeBytesRange(data, off, len, flags)); } } static void compareDecode(byte[] data, int encFlags, int decFlags) { byte[] enc = OooOO0O.OooO0O0(data, encFlags); try { byte[] o = OooOO0O.OooO00o(enc, decFlags); byte[] m = CustomBase64.decodeBytes(enc, decFlags); eq("decode enc="+encFlags+" dec="+decFlags+" d="+data.length, o, m); if ((encFlags & 8) == (decFlags & 8)) { byte[] rt = CustomBase64.decodeBytes(CustomBase64.encodeBytes(data, encFlags), decFlags); eq("roundtrip enc="+encFlags+" dec="+decFlags+" d="+data.length, data, rt); } } catch (Exception ex) { // both should throw identically; check mine throws too try { CustomBase64.decodeBytes(enc, decFlags); checks++; } catch (Exception e2) { checks++; } // also test my decoder on my own encoding try { byte[] mEnc = CustomBase64.encodeBytes(data, encFlags); byte[] o2 = OooOO0O.OooO00o(mEnc, decFlags); byte[] m2 = CustomBase64.decodeBytes(mEnc, decFlags); eq("decode(mine) enc="+encFlags+" dec="+decFlags+" d="+data.length, o2, m2); } catch (Exception e3) { /* ignore */ } } } // streaming encoder comparison via reflection static final Class ORIG_ENC; static final Constructor ORIG_ENC_CTOR; static final Field ORIG_ENC_BUFFER, ORIG_ENC_POS, ORIG_ENC_OUTCOUNT, ORIG_ENC_LINELEN, ORIG_ENC_FOOTER; static final Method ORIG_ENC_ENCODE; static final Class MINE_ENC = CustomBase64.Base64Encoder.class; static final Class ORIG_DEC; static final Constructor ORIG_DEC_CTOR; static final Field ORIG_DEC_BUFFER2, ORIG_DEC_POS2, ORIG_DEC_STATE, ORIG_DEC_ACC; static final Method ORIG_DEC_DECODE; static final Class MINE_DEC = CustomBase64.Base64Decoder.class; static { try { ORIG_ENC = Class.forName("org.npci.upi.security.pinactivitycomponent.OooOO0O$OooO0OO"); ORIG_ENC_CTOR = ORIG_ENC.getDeclaredConstructor(int.class, byte[].class); ORIG_ENC_CTOR.setAccessible(true); ORIG_ENC_BUFFER = ORIG_ENC.getSuperclass().getDeclaredField("OooO00o"); ORIG_ENC_BUFFER.setAccessible(true); ORIG_ENC_POS = ORIG_ENC.getSuperclass().getDeclaredField("OooO0O0"); ORIG_ENC_POS.setAccessible(true); ORIG_ENC_OUTCOUNT = ORIG_ENC.getDeclaredField("OooO0Oo"); ORIG_ENC_OUTCOUNT.setAccessible(true); ORIG_ENC_LINELEN = ORIG_ENC.getDeclaredField("OooO0o0"); ORIG_ENC_LINELEN.setAccessible(true); ORIG_ENC_FOOTER = ORIG_ENC.getDeclaredField("OooO0OO"); ORIG_ENC_FOOTER.setAccessible(true); ORIG_ENC_ENCODE = ORIG_ENC.getDeclaredMethod("OooO00o", byte[].class, int.class, int.class, boolean.class); ORIG_ENC_ENCODE.setAccessible(true); ORIG_DEC = Class.forName("org.npci.upi.security.pinactivitycomponent.OooOO0O$OooO0O0"); ORIG_DEC_CTOR = ORIG_DEC.getDeclaredConstructor(int.class, byte[].class); ORIG_DEC_CTOR.setAccessible(true); ORIG_DEC_BUFFER2 = ORIG_DEC.getSuperclass().getDeclaredField("OooO00o"); ORIG_DEC_BUFFER2.setAccessible(true); ORIG_DEC_POS2 = ORIG_DEC.getSuperclass().getDeclaredField("OooO0O0"); ORIG_DEC_POS2.setAccessible(true); ORIG_DEC_STATE = ORIG_DEC.getDeclaredField("OooO0OO"); ORIG_DEC_STATE.setAccessible(true); ORIG_DEC_ACC = ORIG_DEC.getDeclaredField("OooO0Oo"); ORIG_DEC_ACC.setAccessible(true); ORIG_DEC_DECODE = ORIG_DEC.getDeclaredMethod("OooO00o", byte[].class, int.class, int.class, boolean.class); ORIG_DEC_DECODE.setAccessible(true); } catch (Exception e) { throw new RuntimeException(e); } } static byte[] origEncStream(byte[] data, int flags, int[] splits) throws Exception { // size it the same way the static API does, then stream int size = CustomBase64.encodeBytes(data, flags).length; // my precomputed exact size = original's Object enc = ORIG_ENC_CTOR.newInstance(flags, null); ORIG_ENC_BUFFER.set(enc, new byte[size]); int off = 0; for (int k = 0; k < splits.length; k++) { int len = splits[k]; boolean flush = (k == splits.length - 1); ORIG_ENC_ENCODE.invoke(enc, data, off, len, flush); off += len; } int pos = (int) ORIG_ENC_POS.get(enc); byte[] buf = (byte[]) ORIG_ENC_BUFFER.get(enc); return Arrays.copyOf(buf, pos); } static byte[] mineEncStream(byte[] data, int flags, int[] splits) throws Exception { int size = CustomBase64.encodeBytes(data, flags).length; CustomBase64.Base64Encoder e = new CustomBase64.Base64Encoder(flags, new byte[size]); int off = 0; for (int k = 0; k < splits.length; k++) { int len = splits[k]; boolean flush = (k == splits.length - 1); e.encodeBytes(data, off, len, flush); off += len; } return Arrays.copyOf(e.buffer, e.position); } static void compareEncStream(byte[] data, int flags, int[] splits) throws Exception { eq("encStream d="+data.length+" f="+flags+" splits="+Arrays.toString(splits), origEncStream(data, flags, splits), mineEncStream(data, flags, splits)); } static void compareDecStream(byte[] enc, int flags, int[] splits) throws Exception { Object dec = ORIG_DEC_CTOR.newInstance(flags, new byte[(enc.length*3)/4]); CustomBase64.Base64Decoder md = new CustomBase64.Base64Decoder(flags, new byte[(enc.length*3)/4]); int off = 0; for (int k=0;k