diff --git a/src/main/java/jota/utils/IotaAPIUtils.java b/src/main/java/jota/utils/IotaAPIUtils.java index 593b170..6f24a9d 100644 --- a/src/main/java/jota/utils/IotaAPIUtils.java +++ b/src/main/java/jota/utils/IotaAPIUtils.java @@ -47,7 +47,7 @@ public class IotaAPIUtils { public static GetBundleResponse getBundle(final String transaction) { throw new NotImplementedException("Not yet implemented"); } -/* + public static String transactionTrytes(Transaction trx) { int[] valueTrits = Converter.trits(trx.getValue()); while (valueTrits.length < 81) { @@ -59,12 +59,12 @@ public class IotaAPIUtils { timestampTrits[timestampTrits.length] = 0; } - int[] currentIndexTrits = Converter.trits(trx.getC); + int[] currentIndexTrits = Converter.trits(trx.getTimestamp()); while (currentIndexTrits.length < 27) { currentIndexTrits[currentIndexTrits.length] = 0; } - int[] lastIndexTrits = Converter.trits(trx.get); + int[] lastIndexTrits = Converter.trits(trx.getCurrentIndex()); while (lastIndexTrits.length < 27) { lastIndexTrits[lastIndexTrits.length] = 0; } @@ -72,14 +72,14 @@ public class IotaAPIUtils { return trx.getSignatureMessageChunk() + trx.getAddress() + Converter.trytes(valueTrits) - + trx.getT + + trx.getTag() + Converter.trytes(timestampTrits) + Converter.trytes(currentIndexTrits) + Converter.trytes(lastIndexTrits) - + trx.bundle - + trx.trunkTransaction - + trx.branchTransaction - + trx.nonce; + + trx.getBundle() + + trx.getTrunkTransaction() + + trx.getBranchTransaction() + + trx.getNonce(); } public static List signInputsAndReturn(String seed, List inputs, Bundle bundle, @@ -111,33 +111,33 @@ public class IotaAPIUtils { int[] key = Signing.key(Converter.trits(seed), keyIndex, 2); // First 6561 trits for the firstFragment - int[] firstFragment = Arrays.copyOfRange((6561); + int[] firstFragment = Arrays.copyOfRange(key, 0, 6561); // Get the normalized bundle hash - String normalizedBundleHash = bundle.normalizedBundle(bundleHash); + int[] normalizedBundleHash = bundle.normalizedBundle(bundleHash); // First bundle fragment uses 27 trytes - var firstBundleFragment = normalizedBundleHash(27); + int[] firstBundleFragment = Arrays.copyOfRange(normalizedBundleHash, 0, 27); // Calculate the new signatureFragment with the first bundle fragment - var firstSignedFragment = Signing.signatureFragment(firstBundleFragment, firstFragment); + int[] firstSignedFragment = Signing.signatureFragment(firstBundleFragment, firstFragment); // Convert signature to trytes and assign the new signatureFragment - bundle.Transactions[i].signatureMessageFragment = Converter.trytes(firstSignedFragment); + bundle.getTransactions().get(i).setSignatureMessageChunk(Converter.trytes(firstSignedFragment)); // Because the signature is > 2187 trytes, we need to // find the second transaction to add the remainder of the signature - for (var j = 0; j < bundle.Transactions.Count; j++) { + for (int j = 0; j < bundle.getTransactions().size(); j++) { // Same address as well as value = 0 (as we already spent the input) - if (bundle.Transactions[j].Address == thisAddress && bundle.Transactions[j].Value == 0) { + if (bundle.getTransactions().get(j).getAddress() == thisAddress && Long.parseLong(bundle.getTransactions().get(j).getValue()) == 0) { // Use the second 6562 trits - var secondFragment = key.Skip(6561).Take(6561); + int[] secondFragment = Arrays.copyOfRange(key, 6561, 6561 * 2); // The second 27 to 54 trytes of the bundle hash - var secondBundleFragment = normalizedBundleHash.slice(27, 27 * 2); + int[] secondBundleFragment = Arrays.copyOfRange(normalizedBundleHash, 27, 27 * 2); // Calculate the new signature - var secondSignedFragment = Signing.signatureFragment(secondBundleFragment, secondFragment); + int[] secondSignedFragment = Signing.signatureFragment(secondBundleFragment, secondFragment); // Convert signature to trytes and assign it again to this bundle entry bundle.getTransactions().get(j).setSignatureMessageChunk(Converter.trytes(secondSignedFragment)); @@ -154,5 +154,5 @@ public class IotaAPIUtils { } Collections.reverse(bundleTrytes); return bundleTrytes; - }*/ + } } diff --git a/src/main/java/jota/utils/Signing.java b/src/main/java/jota/utils/Signing.java index a5e2553..a3b2148 100644 --- a/src/main/java/jota/utils/Signing.java +++ b/src/main/java/jota/utils/Signing.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import com.sun.org.apache.xpath.internal.operations.Bool; +import jota.model.Bundle; import jota.pow.Curl; public class Signing { @@ -90,4 +92,101 @@ public class Signing { curl.squeeze(address, 0, address.length); return address; } + + /** + * + * + **/ + public static int[] signatureFragment(int[] normalizedBundleFragment, int[] keyFragment) { + + int[] signatureFragment = keyFragment; + int[] hash; + + Curl curl = new Curl(); + + for (int i = 0; i < 27; i++) { + + hash = Arrays.copyOfRange(signatureFragment, i * 243, (i + 1) * 243); + + for (int j = 0; j < 13 - normalizedBundleFragment[i]; j++) { + + curl.reset(); + curl.absorb(hash, 0, hash.length); + curl.squeeze(hash, 0, hash.length); + } + + for (int j = 0; j < 243; j++) { + + signatureFragment[i * 243 + j] = hash[j]; + } + } + + return signatureFragment; + } + + /** + * + * + **/ + public static int[] digest(int[] normalizedBundleFragment, int[] signatureFragment) { + + int[] buffer = new int[243]; + + Curl curl = new Curl(); + + curl.reset(); + + for (int i = 0; i < 27; i++) { + buffer = Arrays.copyOfRange(signatureFragment, i * 243, (i + 1) * 243); + + for (int j = normalizedBundleFragment[i] + 13; j-- > 0; ) { + + Curl jCurl = new Curl(); + + jCurl.reset(); + jCurl.absorb(buffer, 0, buffer.length); + jCurl.squeeze(buffer, 0, buffer.length); + } + + curl.absorb(buffer, 0, buffer.length); + } + + curl.squeeze(buffer, 0, buffer.length); + + return buffer; + } + + /** + * + * + **/ + public static 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 + 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++) { + + digests[i * 243 + j] = digestBuffer[j]; + } + } + + String address = Converter.trytes(address(digests)); + + return (expectedAddress.equals(address)); + } }