Computes hashcash proof-of-work stamp for the given input and bitstrength. Servers can choose which bitstrength they accept, but we recommend at least 20. The colon ":" is a delimiter in hashcash so we replace all occurances in a token with ".". This machine is calculating stamps at a mean rate of
(int bitstrength, long timestamp,
String token)
| 181 | * @return |
| 182 | */ |
| 183 | public static final String computeStamp(int bitstrength, long timestamp, |
| 184 | String token) { |
| 185 | try { |
| 186 | if (token.indexOf(':') != -1) { |
| 187 | token = token.replace(":", "."); |
| 188 | } |
| 189 | String formattedDate = new SimpleDateFormat("YYMMdd") |
| 190 | .format(new Date(timestamp)); |
| 191 | String prefix = "1:" + Integer.toString(bitstrength) + ":" |
| 192 | + formattedDate + ":" + token + "::" |
| 193 | + Long.toHexString(timestamp) + ":"; |
| 194 | int masklength = bitstrength / 8; |
| 195 | byte[] prefixBytes = prefix.getBytes("UTF-8"); |
| 196 | MessageDigest sha1 = MessageDigest.getInstance("SHA-1"); |
| 197 | |
| 198 | int i; |
| 199 | int b; |
| 200 | byte[] hash; |
| 201 | long counter = 0; |
| 202 | while (true) { |
| 203 | sha1.update(prefixBytes); |
| 204 | sha1.update(Long.toHexString(counter).getBytes()); |
| 205 | hash = sha1.digest(); // 20 bytes long |
| 206 | for (i = 0; i < 20; i++) { |
| 207 | b = (i < masklength) ? 0 : 255 >> (bitstrength % 8); |
| 208 | if (b != (b | hash[i])) { |
| 209 | // no match; keep trying |
| 210 | break; |
| 211 | } |
| 212 | if (i == masklength) { |
| 213 | // we're a match: return the stamp |
| 214 | // System.out.println(Common.toHex(hash)); |
| 215 | return prefix + Long.toHexString(counter); |
| 216 | } |
| 217 | } |
| 218 | counter++; |
| 219 | // keep going forever until we find it |
| 220 | } |
| 221 | } catch (UnsupportedEncodingException e) { |
| 222 | log.error("No string encoding found: ", e); |
| 223 | } catch (NoSuchAlgorithmException e) { |
| 224 | log.error("No hash algorithm found: ", e); |
| 225 | } |
| 226 | log.error("Exiting without stamp: should never happen"); |
| 227 | return null; |
| 228 | } |
| 229 | |
| 230 | /** |
| 231 | * Verifies the specified hashcash proof-of-work stamp for the given |