iota.lib.java/src/main/java/jota/utils/Signing.java
2017-01-23 20:20:20 +01:00

173 lines
4.8 KiB
Java

package jota.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import jota.model.Bundle;
import jota.pow.ICurl;
import jota.pow.JCurl;
public class Signing {
private ICurl curl;
public Signing() {
this(null);
}
public Signing(ICurl curl) {
this.curl = curl == null ? new JCurl() : curl;
}
public int[] key(int[] seed, int index, int length) {
for (int i = 0; i < index; i++) {
for (int j = 0; j < 243; j++) {
if (++seed[j] > 1) {
seed[j] = -1;
} else {
break;
}
}
}
curl.reset();
curl.absorb(seed, 0, seed.length);
curl.squeeze(seed, 0, seed.length);
curl.reset();
curl.absorb(seed, 0, seed.length);
final List<Integer> key = new ArrayList<>();
int[] buffer = new int[seed.length];
int offset = 0;
while (length-- > 0) {
for (int i = 0; i < 27; i++) {
curl.squeeze(buffer, offset, buffer.length);
for (int j = 0; j < 243; j++) {
key.add(buffer[j]);
}
}
}
return to(key);
}
private int[] to(List<Integer> key) {
int a[] = new int[key.size()];
int i = 0;
for (Integer v : key) {
a[i++] = v;
}
return a;
}
public int[] signatureFragment(int[] normalizedBundleFragment, int[] keyFragment) {
int[] hash;
for (int i = 0; i < 27; i++) {
hash = Arrays.copyOfRange(keyFragment, i * 243, (i + 1) * 243);
for (int j = 0; j < 13 - normalizedBundleFragment[i]; j++) {
curl.reset()
.absorb(hash, 0, hash.length)
.squeeze(hash, 0, hash.length);
}
for (int j = 0; j < 243; j++) {
System.arraycopy(hash, j, keyFragment, i * 243 + j, 1);
}
}
return keyFragment;
}
public int[] address(int[] digests) {
int[] address = new int[243];
curl.reset()
.absorb(digests)
.squeeze(address);
return address;
}
public int[] digests(int[] key) {
int[] digests = new int[(int) Math.floor(key.length / 6561) * 243];
int[] buffer = new int[243];
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.reset()
.absorb(buffer)
.squeeze(buffer);
}
System.arraycopy(buffer, 0, keyFragment, j * 243, 243);
}
curl.reset();
curl.absorb(keyFragment, 0, keyFragment.length);
curl.squeeze(buffer, 0, buffer.length);
System.arraycopy(buffer, 0, digests, i * 243, 243);
}
return digests;
}
public int[] digest(int[] normalizedBundleFragment, int[] signatureFragment) {
curl.reset();
int[] buffer = new int[243];
for (int i = 0; i < 27; i++) {
buffer = Arrays.copyOfRange(signatureFragment, i * 243, (i + 1) * 243);
for (int j = normalizedBundleFragment[i] + 13; j-- > 0; ) {
ICurl jCurl = new JCurl();
jCurl.reset();
jCurl.absorb(buffer);
jCurl.squeeze(buffer);
}
curl.absorb(buffer);
}
curl.squeeze(buffer);
return buffer;
}
public Boolean validateSignatures(String expectedAddress, String[] signatureFragments, String bundleHash) {
Bundle bundle = new Bundle();
int[][] normalizedBundleFragments = new int[3][27];
int[] normalizedBundleHash = bundle.normalizedBundle(bundleHash);
// Split hash into 3 fragments
for (int i = 0; i < 3; i++) {
normalizedBundleFragments[i] = Arrays.copyOfRange(normalizedBundleHash, i * 27, (i + 1) * 27);
}
// Get digests
int[] digests = new int[signatureFragments.length * 243];
for (int i = 0; i < signatureFragments.length; i++) {
int[] digestBuffer = digest(normalizedBundleFragments[i % 3], Converter.trits(signatureFragments[i]));
for (int j = 0; j < 243; j++) {
System.arraycopy(digestBuffer, j, digests, i * 243 + j, 1);
}
}
String address = Converter.trytes(address(digests));
return (expectedAddress.equals(address));
}
}