-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
307 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package jota.utils; | ||
|
||
import java.util.Arrays; | ||
|
||
public class Converter { | ||
|
||
public static final int RADIX = 3; | ||
public static final int MAX_TRIT_VALUE = (RADIX - 1) / 2, MIN_TRIT_VALUE = -MAX_TRIT_VALUE; | ||
|
||
public static final int NUMBER_OF_TRITS_IN_A_BYTE = 5; | ||
public static final int NUMBER_OF_TRITS_IN_A_TRYTE = 3; | ||
|
||
static final int[][] BYTE_TO_TRITS_MAPPINGS = new int[243][]; | ||
static final int[][] TRYTE_TO_TRITS_MAPPINGS = new int[27][]; | ||
|
||
public static final String TRYTE_ALPHABET = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | ||
|
||
static { | ||
|
||
final int[] trits = new int[NUMBER_OF_TRITS_IN_A_BYTE]; | ||
|
||
for (int i = 0; i < 243; i++) { | ||
BYTE_TO_TRITS_MAPPINGS[i] = Arrays.copyOf(trits, NUMBER_OF_TRITS_IN_A_BYTE); | ||
increment(trits, NUMBER_OF_TRITS_IN_A_BYTE); | ||
} | ||
|
||
for (int i = 0; i < 27; i++) { | ||
TRYTE_TO_TRITS_MAPPINGS[i] = Arrays.copyOf(trits, NUMBER_OF_TRITS_IN_A_TRYTE); | ||
increment(trits, NUMBER_OF_TRITS_IN_A_TRYTE); | ||
} | ||
} | ||
|
||
public static byte[] bytes(final int[] trits, final int offset, final int size) { | ||
|
||
final byte[] bytes = new byte[(size + NUMBER_OF_TRITS_IN_A_BYTE - 1) / NUMBER_OF_TRITS_IN_A_BYTE]; | ||
for (int i = 0; i < bytes.length; i++) { | ||
|
||
int value = 0; | ||
for (int j = (size - i * NUMBER_OF_TRITS_IN_A_BYTE) < 5 ? (size - i * NUMBER_OF_TRITS_IN_A_BYTE) : NUMBER_OF_TRITS_IN_A_BYTE; j-- > 0; ) { | ||
value = value * RADIX + trits[offset + i * NUMBER_OF_TRITS_IN_A_BYTE + j]; | ||
} | ||
bytes[i] = (byte)value; | ||
} | ||
|
||
return bytes; | ||
} | ||
|
||
public static byte[] bytes(final int[] trits) { | ||
return bytes(trits, 0, trits.length); | ||
} | ||
|
||
public static void getTrits(final byte[] bytes, final int[] trits) { | ||
|
||
int offset = 0; | ||
for (int i = 0; i < bytes.length && offset < trits.length; i++) { | ||
System.arraycopy(BYTE_TO_TRITS_MAPPINGS[bytes[i] < 0 ? (bytes[i] + BYTE_TO_TRITS_MAPPINGS.length) : bytes[i]], 0, trits, offset, trits.length - offset < NUMBER_OF_TRITS_IN_A_BYTE ? (trits.length - offset) : NUMBER_OF_TRITS_IN_A_BYTE); | ||
offset += NUMBER_OF_TRITS_IN_A_BYTE; | ||
} | ||
while (offset < trits.length) { | ||
trits[offset++] = 0; | ||
} | ||
} | ||
|
||
public static int[] trits(final String trytes) { | ||
|
||
final int[] trits = new int[trytes.length() * NUMBER_OF_TRITS_IN_A_TRYTE]; | ||
for (int i = 0; i < trytes.length(); i++) { | ||
System.arraycopy(TRYTE_TO_TRITS_MAPPINGS[TRYTE_ALPHABET.indexOf(trytes.charAt(i))], 0, trits, i * NUMBER_OF_TRITS_IN_A_TRYTE, NUMBER_OF_TRITS_IN_A_TRYTE); | ||
} | ||
|
||
return trits; | ||
} | ||
|
||
public static void copyTrits(final long value, final int[] destination, final int offset, final int size) { | ||
|
||
long absoluteValue = value < 0 ? -value : value; | ||
for (int i = 0; i < size; i++) { | ||
|
||
int remainder = (int)(absoluteValue % RADIX); | ||
absoluteValue /= RADIX; | ||
if (remainder > MAX_TRIT_VALUE) { | ||
|
||
remainder = MIN_TRIT_VALUE; | ||
absoluteValue++; | ||
} | ||
destination[offset + i] = remainder; | ||
} | ||
|
||
if (value < 0) { | ||
|
||
for (int i = 0; i < size; i++) { | ||
destination[offset + i] = -destination[offset + i]; | ||
} | ||
} | ||
} | ||
|
||
public static String trytes(final int[] trits, final int offset, final int size) { | ||
|
||
StringBuilder trytes = new StringBuilder(); | ||
for (int i = 0; i < (size + NUMBER_OF_TRITS_IN_A_TRYTE - 1) / NUMBER_OF_TRITS_IN_A_TRYTE; i++) { | ||
|
||
int j = trits[offset + i * 3] + trits[offset + i * 3 + 1] * 3 + trits[offset + i * 3 + 2] * 9; | ||
if (j < 0) { | ||
|
||
j += TRYTE_ALPHABET.length(); | ||
} | ||
trytes.append(TRYTE_ALPHABET.charAt(j)); | ||
} | ||
return trytes.toString(); | ||
} | ||
|
||
public static String trytes(final int[] trits) { | ||
return trytes(trits, 0, trits.length); | ||
} | ||
|
||
public static int tryteValue(final int[] trits, final int offset) { | ||
return trits[offset] + trits[offset + 1] * 3 + trits[offset + 2] * 9; | ||
} | ||
|
||
public static void increment(final int[] trits, final int size) { | ||
|
||
for (int i = 0; i < size; i++) { | ||
if (++trits[i] > Converter.MAX_TRIT_VALUE) { | ||
trits[i] = Converter.MIN_TRIT_VALUE; | ||
} else { | ||
break; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package jota.utils; | ||
|
||
/** | ||
* (c) 2016 Come-from-Beyond | ||
* | ||
* Curl belongs to the sponge function family. | ||
* | ||
*/ | ||
public class Curl { | ||
|
||
public static final int HASH_LENGTH = 243; | ||
private static final int STATE_LENGTH = 3 * HASH_LENGTH; | ||
|
||
private static final int NUMBER_OF_ROUNDS = 27; | ||
private static final int[] TRUTH_TABLE = {1, 0, -1, 1, -1, 0, -1, 1, 0}; | ||
|
||
private final int[] state = new int[STATE_LENGTH]; | ||
|
||
public void absorb(final int[] trits, int offset, int length) { | ||
|
||
do { | ||
System.arraycopy(trits, offset, state, 0, length < HASH_LENGTH ? length : HASH_LENGTH); | ||
transform(); | ||
offset += HASH_LENGTH; | ||
} while ((length -= HASH_LENGTH) > 0); | ||
} | ||
|
||
public int [] squeeze(final int[] trits, int offset, int length) { | ||
|
||
do { | ||
System.arraycopy(state, 0, trits, offset, length < HASH_LENGTH ? length : HASH_LENGTH); | ||
transform(); | ||
offset += HASH_LENGTH; | ||
} while ((length -= HASH_LENGTH) > 0); | ||
|
||
return state; | ||
} | ||
|
||
private void transform() { | ||
|
||
final int[] scratchpad = new int[STATE_LENGTH]; | ||
int scratchpadIndex = 0; | ||
for (int round = 0; round < NUMBER_OF_ROUNDS; round++) { | ||
System.arraycopy(state, 0, scratchpad, 0, STATE_LENGTH); | ||
for (int stateIndex = 0; stateIndex < STATE_LENGTH; stateIndex++) { | ||
state[stateIndex] = TRUTH_TABLE[scratchpad[scratchpadIndex] + scratchpad[scratchpadIndex += (scratchpadIndex < 365 ? 364 : -365)] * 3 + 4]; | ||
} | ||
} | ||
} | ||
|
||
public void reset() { | ||
for (int stateIndex = 0; stateIndex < STATE_LENGTH; stateIndex++) { | ||
state[stateIndex] = 0; | ||
} | ||
} | ||
|
||
public int[] getState() { | ||
return state; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package jota.utils; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
public class Signing { | ||
|
||
static int[] key(int [] seed, int index, int length) { | ||
|
||
final int[] subseed = seed; | ||
|
||
for (int i = 0; i < index; i++) { | ||
for (int j = 0; j < 243; j++) { | ||
if (++subseed[j] > 1) { | ||
subseed[j] = -1; | ||
} else { | ||
break; | ||
} | ||
} | ||
} | ||
|
||
Curl curl = new Curl(); | ||
//curl.absorb(subseed, state); | ||
//curl.squeeze(subseed, state); | ||
curl.absorb(subseed, 0, subseed.length); | ||
|
||
List<Integer> key = new ArrayList<>(); | ||
int [] buffer = new int[subseed.length]; | ||
int offset = 0; | ||
|
||
while (length-- > 0) { | ||
|
||
for (int i = 0; i < 27; i++) { | ||
|
||
curl.squeeze(buffer, 0, buffer.length); | ||
for (int j = 0; j < 243; j++) { | ||
key.add(buffer[j]); | ||
} | ||
} | ||
} | ||
return to(key); | ||
} | ||
|
||
private static int[] to(List<Integer> key) { | ||
int a [] = new int[key.size()]; int i = 0; | ||
for (Integer v : key) { | ||
a[i++] = v; | ||
} | ||
return a; | ||
} | ||
|
||
public static int [] digests(int [] key) { | ||
final Curl curl = new Curl(); | ||
|
||
int[] digests = new int[key.length]; | ||
int[] buffer = new int[key.length]; | ||
|
||
for (int i = 0; i < Math.floor(key.length / 6561); i++) { | ||
int [] keyFragment = Arrays.copyOfRange(key, i * 6561, (i + 1) * 6561); | ||
|
||
for (int j = 0; j < 27; j++) { | ||
|
||
buffer = Arrays.copyOfRange(keyFragment, j * 243, (j + 1) * 243); | ||
for (int k = 0; k < 26; k++) { | ||
|
||
curl.absorb(buffer, 0, buffer.length); | ||
curl.squeeze(buffer, 0, buffer.length); | ||
} | ||
for (int k = 0; k < 243; k++) { | ||
|
||
keyFragment[j * 243 + k] = buffer[k]; | ||
} | ||
} | ||
|
||
curl.absorb(keyFragment, 0, keyFragment.length); | ||
curl.squeeze(buffer, 0, buffer.length); | ||
|
||
for (int j = 0; j < 243; j++) { | ||
digests[i * 243 + j] = buffer[j]; | ||
} | ||
} | ||
return digests; | ||
} | ||
|
||
public static int [] address(int [] digests) { | ||
final Curl curl = new Curl(); | ||
int [] address = new int[digests.length]; | ||
curl.absorb(digests, 0, digests.length); | ||
curl.squeeze(address, 0, address.length); | ||
return address; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters