/** * Determines if the address is valid. * * @return true if the address is valid. */ public static boolean isValid(@Nullable final String value) { if (value == null) { return false; } // this check should prevent leading and trailing whitespace if (NUM_DECODED_BYTES_LENGTH != value.length()) { return false; } final byte[] encodedBytes; try { encodedBytes = Base32Encoder.getBytes(value); } catch (final IllegalArgumentException e) { return false; } if (NUM_ENCODED_BYTES_LENGTH != encodedBytes.length) { return false; } if (AppConstants.NETWORK_VERSION.get() != encodedBytes[0]) { return false; } final int checksumStartIndex = NUM_ENCODED_BYTES_LENGTH - NUM_CHECKSUM_BYTES; final byte[] versionPrefixedHash = Arrays.copyOfRange(encodedBytes, 0, checksumStartIndex); final byte[] addressChecksum = Arrays.copyOfRange( encodedBytes, checksumStartIndex, checksumStartIndex + NUM_CHECKSUM_BYTES); final byte[] calculatedChecksum = generateChecksum(versionPrefixedHash); return Arrays.equals(addressChecksum, calculatedChecksum); }
private static String generateEncoded(final byte version, final byte[] publicKey) { // step 1: sha3 hash of the public key final byte[] sha3PublicKeyHash = Hashes.sha3_256(publicKey); // step 2: ripemd160 hash of (1) final byte[] ripemd160StepOneHash = Hashes.ripemd160(sha3PublicKeyHash); // step 3: store version byte in front of (2) final byte[] versionPrefixedRipemd160Hash = ArrayUtils.concat(new byte[] {version}, ripemd160StepOneHash); // step 4: get the checksum of (3) final byte[] stepThreeChecksum = generateChecksum(versionPrefixedRipemd160Hash); // step 5: concatenate (3) and (4) final byte[] concatStepThreeAndStepSix = ArrayUtils.concat(versionPrefixedRipemd160Hash, stepThreeChecksum); // step 6: base32 encode (5) return Base32Encoder.getString(concatStepThreeAndStepSix); }