A lightweight generator for short, unique, non-sequential and decodable Hashids from positive unsigned (long) integer numbers.
Java
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.idea
src
.gitignore
.travis.yml
CHANGELOG.md
LICENSE.md
README.md
circle.yml
icecore-hashids.iml
pom.xml

README.md

A lightweight generator for short, unique, non-sequential and decodable Hashids from positive unsigned (long) integer numbers.
Implementation of the Hashids project.


Designed for websites to use in URL shortening, tracking stuff, or making pages private or at least unguessable.
Can be used to create e.g obfuscated database ids, invitation codes, store shard numbers and much more.

It converts numbers like 347 into strings like yr8, or array of numbers like [27, 986] into 3kTMd.
You can also decode those ids back.
This is useful in bundling several parameters into one or simply using them as short UIDs.

This algorithm tries to satisfy the following requirements:

  1. Hashids must be unique and decodable
  2. Hashids should be able to contain more than one integer to use them in complex or clustered systems
  3. Ability to specify minimum hash length
  4. Hashids should not contain basic English curse words since they are meant to appear in public places like a URL

NOTE: All (long) integers must be greater than or equal to zero.

Getting started

Setup

To use icecore-hashids it must be available on your classpath.
You can use it as a dependency for your favorite build tool or download the latest version.

Apache Maven

<dependency>
  <groupId>com.arcticicestudio</groupId>
  <artifactId>icecore-hashids</artifactId>
  <version>0.2.0</version>
</dependency>

Gradle

compile(group: 'com.arcticicestudio', name: 'icecore-hashids', version: '0.2.0')

Apache Ivy

<dependency org="com.arcticicestudio" name="icecore-hashids" rev="0.2.0" />

Development snapshots are available via OSS Sonatype.

Build

Build and install icecore-hashids into your local repository without GPG signing:

mvn clean install

Signed artifacts may be build by using the sign-gpg profile with a provided gpg.keyname property:

mvn clean install -Dgpg.keyname=YourGPGKeyId

Continuous integration builds are running at Travis CI and Circle CI.

Usage Guide

This is a basic guide to show the common usage of the icecore-hashids API.
The API documentation can be found in the JavaDoc.

The class Hashids is the entrypoint to the icecore-hashids API.

  1. Encoding a number
  2. Decoding
  3. Encoding several numbers
  4. Decoding a hash of several numbers
  5. Encoding with a specified minimum hash length
  6. Specify a custom hash alphabet
  7. Specify custom separators
  8. Randomness
  9. Bad or offensive hashes

Encoding a number

You can pass a unique salt value to create a individual hash:

Hashids hashids = new Hashids("salt");
String hash = hashids.encodeToString(12345L);

hash will be X4j1.

Via the Builder:

Hashids hashids = new Hashids.Builder()
  .salt("salt")
  .build();
String hash = hashids.encodeToString(12345L);

Supported number types are long and int.

Decoding

NOTE: Make sure to use the same salt during decoding!**

Hashids hashids = new Hashids("salt");
long[] numbers = hashids.decodeLongNumbers("X4j1");

numbers will be [ 12345 ].

Via the Builder:

Hashids hashids = new Hashids.Builder()
  .salt("salt")
  .build();
long[] numbers = hashids.decodeLongNumbers("X4j1");

Decoding will not work if salt is changed:

Hashids hashids = new Hashids("salt and pepper");
long[] numbers = hashids.decodeLongNumbers("X4j1");

This will throw a IllegalArgumentException.class exception!

Encoding several numbers

Hashids hashids = new Hashids("salt");
String hash = hashids.encodeToString(683L, 94108L, 123L, 5L);

hash will be 1eMToyKzsRAfO.

Decoding a hash of several numbers

Hashids hashids = new Hashids("salt");
long[] numbers = hashids.decodeLongNumbers("1eMToyKzsRAfO");

numbers will be [ 683, 94108, 123, 5 ].

Encoding with a specified minimum hash length

You can set the minimum hash length by passing it to the constructor or the Builder method minHashLength(int).
The default value is 0 to generate hashes with the shortest possible length.

Hashids hashids = new Hashids("salt", 8);
String hash = hashids.encodeToString(1L);

hash will be zxkXG8ZW.

Via the Builder:

Hashids hashids = new Hashids.Builder()
  .salt("salt")
  .minHashLength(8)
  .build();
String hash = hashids.encodeToString(1L);

Specify a custom hash alphabet

You can also set a custom alphabet by passing it to the constructor or the Builder method alphabet(String).

Hashids hashids = new Hashids("salt", "0123456789abcdef");
String hash = hashids.encodeToString(1234567L);

hash will be e884ade.

Via the Builder:

Hashids hashids = new Hashids.Builder()
  .salt("salt")
  .alphabet("0123456789abcdef")
  .build();
String hash = hashids.encodeToString(1234567L);

Specify custom separators

You can set custom separators by passing it to the constructor or the Builder method separators(String).

Hashids hashids = new Hashids("salt", 0, Hashids.DEFAULT_ALPHABET, "aeiosuyzAEIOSUYZ0179");
String hash = hashids.encodeToString(12345L);

hash will be VFKk.

Via the Builder:

Hashids hashids = new Hashids.Builder()
  .salt("salt")
  .separators("aeiosuyzAEIOSUYZ0179")
  .build();
String hash = hashids.encodeToString(12345L);

Separators try to prevent accidentally generated bad or offensive hashes.
Read the section 9. Bad or offensive hashes for more information.

Randomness

The primary purpose of hashids is to obfuscate ids.
This algorithm does try to make these hashes unguessable and unpredictable.
Note that it is not meant to be used for security purposes or compression!

Repeating numbers

Hashids hashids = new Hashids("salt");
String hash = hashids.encodeToString(5L, 5L, 5L, 5L);

hash is going to be YBF7FKFz.

You don't see any repeating patterns that might show there's 4 identical numbers in the hash.
Same with incremented numbers:

Hashids hashids = new Hashids("salt");
String hash = hashids.encodeToString(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L);

hash will be rjiJulUECaFAS1TBhzcX.

You can compare this result by encoding every number on its own:

Hashids hashids = new Hashids("this is my salt");
String hash1 = hashids.encodeToString(1L); /* XG */
String hash2 = hashids.encodeToString(2L); /* dv */
String hash3 = hashids.encodeToString(3L); /* w2 */
String hash4 = hashids.encodeToString(4L); /* nO */
String hash5 = hashids.encodeToString(5L); /* q2 */
//...

Bad or offensive hashes

This module was written with the intent of placing these hashes in visible places like the URL.
It is possible that the created hash ends up accidentally being a bad or offensice word.

Therefore, this algorithm tries to avoid generating most common english curse words with the default alphabet.
This is done by never placing the following letters next to each other:
c, C, s, S, f, F, h, H, u, U, i, I, t, T


Development

Contribution

Please report issues/bugs, feature requests and suggestions for improvements to the issue tracker.


Copyright © 2016 Arctic Ice Studio