Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
npci-cl-custom-base64 TestBase64.java
11 kB · 211 lines
Java
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212import 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<splits.length;k++){ int len=splits[k]; boolean flush=(k==splits.length-1); ORIG_DEC_DECODE.invoke(dec, enc, off, len, flush); md.decodeBytes(enc, off, len, flush); off+=len; } int op=(int)ORIG_DEC_POS2.get(dec); byte[] ob=(byte[])ORIG_DEC_BUFFER2.get(dec); byte[] o=Arrays.copyOf(ob,op), m=Arrays.copyOf(md.buffer, md.position); eq("decStream enc.len="+enc.length+" f="+flags+" splits="+Arrays.toString(splits), o, m); }
public static void main(String[] a) throws Exception { // toUrlSafe for (String s : new String[]{"", "a", "a+b", "/c", "a+b/c", "++//", "x"}) eq("toUrlSafe "+s, OooOO0O.OooO00o(s), CustomBase64.toUrlSafe(s));
int[] allFlags = new int[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
// Deterministic sizes 0..300 for (int n=0;n<=300;n++){ byte[] d=new byte[n]; for(int i=0;i<n;i++) d[i]=(byte)(i*31+7); for(int f: allFlags){ compareStatic(d,f); } }
// Decoding matrix: encode under several flags, decode under all flags for (int n : new int[]{0,1,2,3,4,5,56,57,58,114,200,301}) { byte[] d=new byte[n]; for(int i=0;i<n;i++) d[i]=(byte)(i*131+1); for (int ef : new int[]{0,1,2,4,8,10,12}) for (int df : allFlags) compareDecode(d, ef, df); }
// Random fuzz Random r = new Random(1234); for (int t=0;t<2000;t++){ int n=r.nextInt(400); byte[] d=new byte[n]; r.nextBytes(d); int f=r.nextInt(16); compareStatic(d,f); int ef=r.nextInt(16), df=r.nextInt(16); compareDecode(d, ef, df); }
// Streaming encoder fuzz: various split patterns for (int n : new int[]{0,1,2,3,4,5,56,57,58,59,114,200,300,500}) { byte[] d=new byte[n]; for(int i=0;i<n;i++) d[i]=(byte)(i*97+3); for (int f : new int[]{0,1,2,4,5,8,10,12,13,15}) { // all splits from set of break points for (int[] splits : allSplits(n)) compareEncStream(d, f, splits); } } // streaming decoder fuzz over encoded data for (int n : new int[]{0,1,2,3,4,57,58,200}) { byte[] d=new byte[n]; for(int i=0;i<n;i++) d[i]=(byte)(i*73+9); for (int ef : new int[]{0,2,8,10}) { byte[] enc = OooOO0O.OooO0O0(d, ef); for (int df : new int[]{0,8}) { for (int[] splits : allSplits(enc.length)) compareDecStream(enc, df, splits); } } }
System.out.println("== checks=" + checks + " fails=" + fails + " =="); if (fails>0) System.exit(1); }
static java.util.List<int[]> allSplits(int n) { java.util.List<int[]> out = new java.util.ArrayList<>(); out.add(new int[]{n}); // whole if (n > 0) { if (n <= 20) { int[] s = new int[n]; Arrays.fill(s, 1); out.add(s); } // every byte out.add(new int[]{n / 2, n - n / 2}); // halves out.add(new int[]{1, n - 1}); // 1 then rest out.add(new int[]{n - 1, 1}); // rest then 1 out.add(new int[]{n / 3, n / 3, n - 2 * (n / 3)}); // thirds } return out; }}