1 package com.jsql.util.bruter;
2
3 import org.apache.commons.lang3.StringUtils;
4
5 import java.nio.charset.StandardCharsets;
6 import java.util.Arrays;
7
8 public class Base58 {
9
10 private static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray();
11 private static final int BASE_58 = Base58.ALPHABET.length;
12 private static final int BASE_256 = 256;
13
14 private static final int[] INDEXES = new int[128];
15
16 static {
17 Arrays.fill(Base58.INDEXES, -1);
18 for (int i = 0; i < Base58.ALPHABET.length; i++) {
19 Base58.INDEXES[Base58.ALPHABET[i]] = i;
20 }
21 }
22
23 private Base58() {
24
25 }
26
27 public static String encode(byte[] input) {
28 if (input.length == 0) {
29
30 return StringUtils.EMPTY;
31 }
32
33 byte[] copyInput = Base58.copyOfRange(input, 0, input.length);
34
35 var zeroCount = 0;
36 while (zeroCount < copyInput.length && copyInput[zeroCount] == 0) {
37 ++zeroCount;
38 }
39
40 var temp = new byte[copyInput.length * 2];
41 int j = temp.length;
42 int startAt = zeroCount;
43 while (startAt < copyInput.length) {
44 byte mod = Base58.divmod58(copyInput, startAt);
45 if (copyInput[startAt] == 0) {
46 ++startAt;
47 }
48 temp[--j] = (byte) Base58.ALPHABET[mod];
49 }
50
51 while (j < temp.length && temp[j] == Base58.ALPHABET[0]) {
52 ++j;
53 }
54
55 while (--zeroCount >= 0) {
56 temp[--j] = (byte) Base58.ALPHABET[0];
57 }
58 byte[] output = Base58.copyOfRange(temp, j, temp.length);
59 return new String(output, StandardCharsets.UTF_8);
60 }
61
62 public static byte[] decode(String input) {
63 if (input.isEmpty()) {
64
65 return new byte[0];
66 }
67 var input58 = new byte[input.length()];
68
69 for (var i = 0; i < input.length(); ++i) {
70 var c = input.charAt(i);
71 int digit58 = -1;
72 if (c >= 0 && c < 128) {
73 digit58 = Base58.INDEXES[c];
74 }
75 if (digit58 < 0) {
76 throw new IllegalArgumentException("Not a Base58 input: " + input);
77 }
78 input58[i] = (byte) digit58;
79 }
80
81
82 var zeroCount = 0;
83 while (zeroCount < input58.length && input58[zeroCount] == 0) {
84 ++zeroCount;
85 }
86
87
88 var temp = new byte[input.length()];
89 int j = temp.length;
90
91 int startAt = zeroCount;
92 while (startAt < input58.length) {
93 byte mod = Base58.divmod256(input58, startAt);
94 if (input58[startAt] == 0) {
95 ++startAt;
96 }
97 temp[--j] = mod;
98 }
99
100 while (j < temp.length && temp[j] == 0) {
101 ++j;
102 }
103 return Base58.copyOfRange(temp, j - zeroCount, temp.length);
104 }
105
106 private static byte divmod58(byte[] number, int startAt) {
107 var remainder = 0;
108 for (int i = startAt; i < number.length; i++) {
109 int digit256 = number[i] & 0xFF;
110 int temp = remainder * Base58.BASE_256 + digit256;
111 number[i] = (byte) (temp / Base58.BASE_58);
112 remainder = temp % Base58.BASE_58;
113 }
114 return (byte) remainder;
115 }
116
117 private static byte divmod256(byte[] number58, int startAt) {
118 var remainder = 0;
119 for (int i = startAt; i < number58.length; i++) {
120 int digit58 = number58[i] & 0xFF;
121 int temp = remainder * Base58.BASE_58 + digit58;
122 number58[i] = (byte) (temp / Base58.BASE_256);
123 remainder = temp % Base58.BASE_256;
124 }
125 return (byte) remainder;
126 }
127
128 private static byte[] copyOfRange(byte[] source, int from, int to) {
129 var range = new byte[to - from];
130 System.arraycopy(source, from, range, 0, range.length);
131 return range;
132 }
133 }