user7: I'm trying to implement the asset fingerprint in java.
So i'm importing these dependencies
<dependency>
    <groupId>org.bitcoinj</groupId>
    <artifactId>bitcoinj-core</artifactId>
    <version>0.15.10</version>
</dependency>
<dependency>
    <groupId>com.github.alphazero</groupId>
    <artifactId>Blake2b</artifactId>
    <version>bbf094983c</version>
</dependency>

And coded this as specified here: https://github.com/cardano-foundation/CIPs/pull/64
public static void main(String[] args) throws DecoderException {
    final String policyId = "2697bec9e609932eaaaafb34c8e1ea706549d268166ef60285026b85";
    final String assetName = "redomgrun";

    byte[] policyIdBytes = Hex.decodeHex(policyId);
    byte[] assetNameBytes = assetName.getBytes();

    Digest blakeDigest = Blake2b.Digest.newInstance(20);
    byte[] blakeHash = blakeDigest.digest(ArrayUtils.addAll(policyIdBytes, assetNameBytes));
    String bechString = Bech32.encode("asset", blakeHash);
    System.out.println(bechString);
}

But blake produces bytes like this
[127, -84, -10, 11, 1, -8, 78 ...

Which lead to String index out of range: 127 at bech encoding.
What am i doing wrong?

user1900: You have to first convert blakeHash bytes from 8 bits to 5 bits unsigned integer and then call Bech32.encode().
Sample code:
public static void main(String[] args) throws DecoderException {
    ...
    byte[] blakeHash = blakeDigest.digest(ArrayUtils.addAll(policyIdBytes, assetNameBytes));

    List<Integer> words = convertBits(blakeHash, 8, 5, false);
    byte[] bytes = new byte[words.size()];
    for(int i=0; i < words.size(); i++) {
        bytes[i] = words.get(i).byteValue();
    }

    String bechString = Bech32.encode("asset", bytes);
    System.out.println(bechString);
}

private static List<Integer> convertBits(byte[] data, int fromWidth, int toWidth, boolean pad) {
    int acc = 0;
    int bits = 0;
    int maxv = (1 << toWidth) - 1;
    List<Integer> ret = new ArrayList<>();

    for (int i = 0; i < data.length; i++) {
        int value = data[i] & 0xff;
        if (value < 0 || value >> fromWidth != 0) {
            return null;
        }
        acc = (acc << fromWidth) | value;
        bits += fromWidth;
        while (bits >= toWidth) {
            bits -= toWidth;
            ret.add((acc >> bits) & maxv);
        }
    }

    if (pad) {
        if (bits > 0) {
            ret.add((acc << (toWidth - bits)) & maxv);
        } else if (bits >= fromWidth || ((acc << (toWidth - bits)) & maxv) != 0) {
            return null;
        }
    }
    return ret;
}


7: <p>I'm trying to implement the asset fingerprint in java.</p>
<p>So i'm importing these dependencies</p>
<pre><code>&lt;dependency&gt;
    &lt;groupId&gt;org.bitcoinj&lt;/groupId&gt;
    &lt;artifactId&gt;bitcoinj-core&lt;/artifactId&gt;
    &lt;version&gt;0.15.10&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;com.github.alphazero&lt;/groupId&gt;
    &lt;artifactId&gt;Blake2b&lt;/artifactId&gt;
    &lt;version&gt;bbf094983c&lt;/version&gt;
&lt;/dependency&gt;
</code></pre>
<p>And coded this as specified here: <a href="https://github.com/cardano-foundation/CIPs/pull/64" rel="nofollow noreferrer">https://github.com/cardano-foundation/CIPs/pull/64</a></p>
<pre><code>public static void main(String[] args) throws DecoderException {
    final String policyId = &quot;2697bec9e609932eaaaafb34c8e1ea706549d268166ef60285026b85&quot;;
    final String assetName = &quot;redomgrun&quot;;

    byte[] policyIdBytes = Hex.decodeHex(policyId);
    byte[] assetNameBytes = assetName.getBytes();

    Digest blakeDigest = Blake2b.Digest.newInstance(20);
    byte[] blakeHash = blakeDigest.digest(ArrayUtils.addAll(policyIdBytes, assetNameBytes));
    String bechString = Bech32.encode(&quot;asset&quot;, blakeHash);
    System.out.println(bechString);
}
</code></pre>
<p>But blake produces bytes like this</p>
<pre><code>[127, -84, -10, 11, 1, -8, 78 ...
</code></pre>
<p>Which lead to <code>String index out of range: 127</code> at bech encoding.</p>
<p>What am i doing wrong?</p>
 1900: <p>You have to first convert blakeHash bytes from 8 bits to 5 bits unsigned integer and then call Bech32.encode().</p>
<p>Sample code:</p>
<pre><code>public static void main(String[] args) throws DecoderException {
    ...
    byte[] blakeHash = blakeDigest.digest(ArrayUtils.addAll(policyIdBytes, assetNameBytes));

    List&lt;Integer&gt; words = convertBits(blakeHash, 8, 5, false);
    byte[] bytes = new byte[words.size()];
    for(int i=0; i &lt; words.size(); i++) {
        bytes[i] = words.get(i).byteValue();
    }

    String bechString = Bech32.encode(&quot;asset&quot;, bytes);
    System.out.println(bechString);
}

private static List&lt;Integer&gt; convertBits(byte[] data, int fromWidth, int toWidth, boolean pad) {
    int acc = 0;
    int bits = 0;
    int maxv = (1 &lt;&lt; toWidth) - 1;
    List&lt;Integer&gt; ret = new ArrayList&lt;&gt;();

    for (int i = 0; i &lt; data.length; i++) {
        int value = data[i] &amp; 0xff;
        if (value &lt; 0 || value &gt;&gt; fromWidth != 0) {
            return null;
        }
        acc = (acc &lt;&lt; fromWidth) | value;
        bits += fromWidth;
        while (bits &gt;= toWidth) {
            bits -= toWidth;
            ret.add((acc &gt;&gt; bits) &amp; maxv);
        }
    }

    if (pad) {
        if (bits &gt; 0) {
            ret.add((acc &lt;&lt; (toWidth - bits)) &amp; maxv);
        } else if (bits &gt;= fromWidth || ((acc &lt;&lt; (toWidth - bits)) &amp; maxv) != 0) {
            return null;
        }
    }
    return ret;
}
</code></pre>
