1 package net.sumaris.core.util.crypto;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 import java.io.UnsupportedEncodingException;
27 import java.security.MessageDigest;
28 import java.security.NoSuchAlgorithmException;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public class Base58 {
48 public static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray();
49 private static final MessageDigest digest;
50 static {
51 try {
52 digest = MessageDigest.getInstance("SHA-256");
53 } catch (NoSuchAlgorithmException e) {
54 throw new RuntimeException(e);
55 }
56 }
57 private static final int[] INDEXES = new int[128];
58 static {
59 for (int i = 0; i < INDEXES.length; i++) {
60 INDEXES[i] = -1;
61 }
62 for (int i = 0; i < ALPHABET.length; i++) {
63 INDEXES[ALPHABET[i]] = i;
64 }
65 }
66
67
68 public static String encode(byte[] input) {
69 if (input.length == 0) {
70 return "";
71 }
72 input = copyOfRange(input, 0, input.length);
73
74 int zeroCount = 0;
75 while (zeroCount < input.length && input[zeroCount] == 0) {
76 ++zeroCount;
77 }
78
79 byte[] temp = new byte[input.length * 2];
80 int j = temp.length;
81
82 int startAt = zeroCount;
83 while (startAt < input.length) {
84 byte mod = divmod58(input, startAt);
85 if (input[startAt] == 0) {
86 ++startAt;
87 }
88 temp[--j] = (byte) ALPHABET[mod];
89 }
90
91
92 while (j < temp.length && temp[j] == ALPHABET[0]) {
93 ++j;
94 }
95
96 while (--zeroCount >= 0) {
97 temp[--j] = (byte) ALPHABET[0];
98 }
99
100 byte[] output = copyOfRange(temp, j, temp.length);
101 try {
102 return new String(output, "US-ASCII");
103 } catch (UnsupportedEncodingException e) {
104 throw new RuntimeException(e);
105 }
106 }
107
108 public static byte[] decode(String input) throws AddressFormatException {
109 if (input.length() == 0) {
110 return new byte[0];
111 }
112 byte[] input58 = new byte[input.length()];
113
114 for (int i = 0; i < input.length(); ++i) {
115 char c = input.charAt(i);
116
117 int digit58 = -1;
118 if (c >= 0 && c < 128) {
119 digit58 = INDEXES[c];
120 }
121 if (digit58 < 0) {
122 throw new AddressFormatException("Illegal character " + c + " at " + i);
123 }
124
125 input58[i] = (byte) digit58;
126 }
127
128 int zeroCount = 0;
129 while (zeroCount < input58.length && input58[zeroCount] == 0) {
130 ++zeroCount;
131 }
132
133 byte[] temp = new byte[input.length()];
134 int j = temp.length;
135
136 int startAt = zeroCount;
137 while (startAt < input58.length) {
138 byte mod = divmod256(input58, startAt);
139 if (input58[startAt] == 0) {
140 ++startAt;
141 }
142
143 temp[--j] = mod;
144 }
145
146 while (j < temp.length && temp[j] == 0) {
147 ++j;
148 }
149
150 return copyOfRange(temp, j - zeroCount, temp.length);
151 }
152
153
154
155
156 private static byte divmod58(byte[] number, int startAt) {
157 int remainder = 0;
158 for (int i = startAt; i < number.length; i++) {
159 int digit256 = (int) number[i] & 0xFF;
160 int temp = remainder * 256 + digit256;
161
162 number[i] = (byte) (temp / 58);
163
164 remainder = temp % 58;
165 }
166
167 return (byte) remainder;
168 }
169
170
171
172
173 private static byte divmod256(byte[] number58, int startAt) {
174 int remainder = 0;
175 for (int i = startAt; i < number58.length; i++) {
176 int digit58 = (int) number58[i] & 0xFF;
177 int temp = remainder * 58 + digit58;
178
179 number58[i] = (byte) (temp / 256);
180
181 remainder = temp % 256;
182 }
183
184 return (byte) remainder;
185 }
186
187 private static byte[] copyOfRange(byte[] source, int from, int to) {
188 byte[] range = new byte[to - from];
189 System.arraycopy(source, from, range, 0, range.length);
190
191 return range;
192 }
193 }