fixed signing

This commit is contained in:
pinpong
2017-11-04 17:21:43 +01:00
parent a1f407eeff
commit 1dee918ac7
6 changed files with 64 additions and 36 deletions
+1 -1
View File
@@ -313,7 +313,7 @@ public class IotaAPICore {
nodeConfig = new Properties();
if (null == fileReader) {
try {
fileReader = new FileReader("node_config.properties");
fileReader = new FileReader("../node_config.properties");
if (null == bufferedReader) {
bufferedReader = new BufferedReader(fileReader);
@@ -1,6 +1,7 @@
package jota.utils;
import jota.error.InvalidAddressException;
import jota.error.InvalidSecurityLevelException;
import jota.model.Bundle;
import jota.model.Input;
import jota.model.Transaction;
@@ -28,8 +29,9 @@ public class IotaAPIUtils {
* @param curl The curl instance.
* @return An String with address.
* @throws InvalidAddressException is thrown when the specified address is not an valid address.
* @throws InvalidSecurityLevelException is thrown when the specified security level is not valid.
*/
public static String newAddress(String seed, int security, int index, boolean checksum, ICurl curl) throws InvalidAddressException {
public static String newAddress(String seed, int security, int index, boolean checksum, ICurl curl) throws InvalidAddressException, InvalidSecurityLevelException {
Signing signing = new Signing(curl);
final int[] key = signing.key(Converter.trits(seed), index, security);
final int[] digests = signing.digests(key);
@@ -46,7 +48,7 @@ public class IotaAPIUtils {
public static List<String> signInputsAndReturn(final String seed,
final List<Input> inputs,
final Bundle bundle,
final List<String> signatureFragments, ICurl curl) {
final List<String> signatureFragments, ICurl curl) throws InvalidSecurityLevelException {
bundle.finalize(curl);
bundle.addTrytes(signatureFragments);
+3 -2
View File
@@ -1,5 +1,6 @@
package jota.utils;
import jota.error.InvalidSecurityLevelException;
import jota.model.Bundle;
import jota.pow.ICurl;
import jota.pow.SpongeFactory;
@@ -36,7 +37,7 @@ public class Multisig {
* @param index Key index to start search from. If the index is provided, the generation of the address is not deterministic.
* @return trytes
**/
public String getDigest(String seed, int security, int index) {
public String getDigest(String seed, int security, int index) throws InvalidSecurityLevelException {
int[] key = signingInstance.key(Converter.trits(seed, 243), index, security);
return Converter.trytes(signingInstance.digests(key));
}
@@ -75,7 +76,7 @@ public class Multisig {
* @return trytes.
**/
public String getKey(String seed, int index, int security) {
public String getKey(String seed, int index, int security) throws InvalidSecurityLevelException {
return Converter.trytes(signingInstance.key(Converter.trits(seed, 81 * security), index, security));
}
+40 -28
View File
@@ -1,5 +1,6 @@
package jota.utils;
import jota.error.InvalidSecurityLevelException;
import jota.model.Bundle;
import jota.model.Transaction;
import jota.pow.ICurl;
@@ -9,12 +10,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static jota.pow.JCurl.HASH_LENGTH;
public class Signing {
public final static int KEY_LENGTH = 6561;
/**
* Ask @come-from-beyond
*/
private ICurl curl;
/**
@@ -31,15 +32,21 @@ public class Signing {
}
/**
* @param seed
* @param inSeed
* @param index
* @param length
* @param security
* @return
*/
public int[] key(int[] seed, int index, int length) {
public int[] key(final int[] inSeed, final int index, int security) throws InvalidSecurityLevelException {
if (security < 1 || security > 3) {
throw new InvalidSecurityLevelException();
}
int[] seed = inSeed.clone();
// Derive subseed.
for (int i = 0; i < index; i++) {
for (int j = 0; j < 243; j++) {
for (int j = 0; j < HASH_LENGTH; j++) {
if (++seed[j] > 1) {
seed[j] = -1;
} else {
@@ -50,16 +57,18 @@ public class Signing {
curl.reset();
curl.absorb(seed, 0, seed.length);
curl.squeeze(seed, 0, seed.length);
// seed[0..HASH_LENGTH] contains subseed
curl.squeeze(seed, 0, HASH_LENGTH);
curl.reset();
curl.absorb(seed, 0, seed.length);
// absorb subseed
curl.absorb(seed, 0, HASH_LENGTH);
final int[] key = new int[length * seed.length * 27];
final int[] key = new int[security * HASH_LENGTH * 27];
int offset = 0;
while (length-- > 0) {
while (security-- > 0) {
for (int i = 0; i < 27; i++) {
curl.squeeze(key, offset, seed.length);
curl.squeeze(key, offset, HASH_LENGTH);
offset += seed.length;
}
}
@@ -67,20 +76,22 @@ public class Signing {
}
public int[] signatureFragment(int[] normalizedBundleFragment, int[] keyFragment) {
int[] signatureFragment = keyFragment.clone();
for (int i = 0; i < 27; i++) {
for (int j = 0; j < 13 - normalizedBundleFragment[i]; j++) {
curl.reset()
.absorb(keyFragment, i * 243, 243)
.squeeze(keyFragment, i * 243, 243);
.absorb(signatureFragment, i * HASH_LENGTH, HASH_LENGTH)
.squeeze(signatureFragment, i * HASH_LENGTH, HASH_LENGTH);
}
}
return keyFragment;
return signatureFragment;
}
public int[] address(int[] digests) {
int[] address = new int[243];
int[] address = new int[HASH_LENGTH];
curl.reset()
.absorb(digests)
.squeeze(address);
@@ -88,23 +99,25 @@ public class Signing {
}
public int[] digests(int[] key) {
int security = (int) Math.floor(key.length / KEY_LENGTH);
int[] digests = new int[(int) Math.floor(key.length / 6561) * 243];
int[] digests = new int[security * HASH_LENGTH];
int[] keyFragment = 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 i = 0; i < Math.floor(key.length / KEY_LENGTH); i++) {
System.arraycopy(key, i * KEY_LENGTH, keyFragment, 0, KEY_LENGTH);
for (int j = 0; j < 27; j++) {
for (int k = 0; k < 26; k++) {
curl.reset()
.absorb(keyFragment, j * 243, 243)
.squeeze(keyFragment, j * 243, 243);
.absorb(keyFragment, j * HASH_LENGTH, HASH_LENGTH)
.squeeze(keyFragment, j * HASH_LENGTH, HASH_LENGTH);
}
}
curl.reset();
curl.absorb(keyFragment, 0, keyFragment.length);
curl.squeeze(digests, i * 243, 243);
curl.squeeze(digests, i * HASH_LENGTH, HASH_LENGTH);
}
return digests;
}
@@ -112,10 +125,10 @@ public class Signing {
public int[] digest(int[] normalizedBundleFragment, int[] signatureFragment) {
curl.reset();
ICurl jCurl = SpongeFactory.create(SpongeFactory.Mode.KERL);
int[] buffer = new int[243];
int[] buffer = new int[HASH_LENGTH];
for (int i = 0; i < 27; i++) {
buffer = Arrays.copyOfRange(signatureFragment, i * 243, (i + 1) * 243);
buffer = Arrays.copyOfRange(signatureFragment, i * HASH_LENGTH, (i + 1) * HASH_LENGTH);
for (int j = normalizedBundleFragment[i] + 13; j-- > 0; ) {
jCurl.reset();
@@ -133,8 +146,8 @@ public class Signing {
String bundleHash = "";
Transaction trx;
List<String> signatureFragments = new ArrayList<>();
for (int i = 0; i < signedBundle.getTransactions().size(); i++) {
for (int i = 0; i < signedBundle.getTransactions().size(); i++) {
trx = signedBundle.getTransactions().get(i);
if (trx.getAddress().equals(inputAddress)) {
@@ -149,7 +162,6 @@ public class Signing {
}
}
return validateSignatures(inputAddress, signatureFragments.toArray(new String[signatureFragments.size()]), bundleHash);
}
@@ -167,13 +179,13 @@ public class Signing {
}
// Get digests
int[] digests = new int[signatureFragments.length * 243];
int[] digests = new int[signatureFragments.length * HASH_LENGTH];
for (int i = 0; i < signatureFragments.length; i++) {
int[] digestBuffer = digest(normalizedBundleFragments[i % 3], Converter.trits(signatureFragments[i]));
System.arraycopy(digestBuffer, 0, digests, i * 243, 243);
System.arraycopy(digestBuffer, 0, digests, i * HASH_LENGTH, HASH_LENGTH);
}
String address = Converter.trytes(address(digests));
@@ -4,6 +4,7 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import jota.error.InvalidAddressException;
import jota.error.InvalidBundleException;
import jota.error.InvalidSecurityLevelException;
import jota.error.InvalidTransferException;
import jota.model.Bundle;
import jota.model.Transaction;
@@ -39,7 +40,7 @@ public class IotaMultisigTest {
}
@Test
public void basicMultiSigTest() throws InvalidBundleException, InvalidTransferException, InvalidAddressException {
public void basicMultiSigTest() throws InvalidBundleException, InvalidTransferException, InvalidAddressException, InvalidSecurityLevelException {
Multisig ms = new Multisig();
+14 -2
View File
@@ -1,6 +1,7 @@
package jota;
import jota.error.InvalidAddressException;
import jota.error.InvalidSecurityLevelException;
import jota.model.Bundle;
import jota.utils.*;
import org.junit.Test;
@@ -22,13 +23,13 @@ public class SigningTest {
private static final String SIGNATURE2 = "URKFKLNXFEKDOGSQVMAOPEDIWSMTCKJZ9KEVWYALY9JAO9KHUGNDTMGQLKQJUIPWDIVMPEDSVPLFMDCIXDDT9WBBRTFQENL9AXLSBYHINXCDYBFGRNKJDYHAQVJKWCVOYXHTNBEZUNLVMJLUMZYJFAOW9PVVMJZNZZFJQEQFELVFZVFVWPJ9WQZJLPSGBYECHXSFVFQJGUCPFXC9GATTILVCAANNHOYMLOYX9QSUPCERYCOXPACZEEGLREBRZWXGUTTVTHB9GBRCIFEOBPIRXXPQKRSODEHDSZXLGIKXUQWNTQKIOPVDVSIK9WJUAEFOJBU9MBPBSVYSCLBMINTT9ZCTREZSMSVOPXSZOMCGFEZKMOCNLJ9QUTAPKBHRIAIYLCHUQHOINKSCMXWZVDGDXHNJQXJHPCCGBEWROVKEPAPBFFRCAVXZWIRKCRAWYHIHMDXFAGDJQNJJPYSQUHKFOOCEVQOGRQEIOQFKZWUQ9XVRNXKGMJOQEZHQZXQABWUQRBKXWHYUXEAEMDGXVY9WS9VJOCMGBQASSRNKAYJPTSPQEMYSJMTCLMDQJKDPBGQZZSFBDOKHBYY9UDRXNKTPWBCQTVKUGMEDUXL9TTKPATNIKVAGHACHPFSCRYNIRJBQC9OADPGWBFYYARSVNQCGMYQGCYLZH9KLMUIJPCLPQVS9BORXCJBXPDECJGKDNOUYWTKKFLXZARWKGUSMVMXKJTMRYZRERFCFGTZFZFCAOQSZGPQJUEZUJLJPU9QPMJUTZNLMSMPRGIFHUUZHMPMRBEBATEIIWPCOIMWOYOG9NYFBYOWFDKRXOTREBU99GNCPXKOWGI99LNVPRFFF9FCLFXI9HMUFU9NRLNJVTFNUSUJTAVOG9GKUYYEXIM9HTPIDTWIGLKRAQPKMQVZAPYMPSQIOJ9JZBWDMQHDSSRSHNCWSAJCSRORSEXLLQNZUKPXPGRLYMXOXWCCWWSBALFLXPHSGFLTOAFWPETBKJUMBLHMSKYLPJT9EJAZCPPNZWKPVCGKDJCRCLBBIAKVDSNWGONPLKFAYXZDI9FKPHDPKCB9UUPXLJVQTXOAZOQDRNSONXDVSLQGZYRIPGREYHRAUOSBFZDZPZHFNMWCZQGPXCZVLNCSASB9RQDFHOYMUVYLFKOEEWNREYCDMCTZIAFBFKLKRQWZCJHQZCZGWXIFTKRVMPHMVHAABHBDEV9WDEZBR9FLXLNBVNYKUOUFJQKNZVZVGZDDTFYNYFUVRLZKOLXXQYNV9MDVBLZSERXPGYKRIEZQZD9IBKFDT9AIYGWJJCXFWDUDURGJQLXVEJAVEOMZUVVTNCVBXEVQRDQIEHDUCSLCIJUTSCLFXEGMFYP9YLXELCZPMTBZWBIODZCFNJLVWTPQGLMQIHIABAYGJFFMOEDTCXGEDTNXMVXZYFGXRKVVRTIZ9ISXTDHAFPEKQZSM9XXQLOYBLTMD9MBERBIBEJDEXGMOLDZPZVVEPIRKJBDPAKFAWJPTCJSHZPDUKZEEHRFLMZCUGCOWFJBSTDGPHUIXSPPPHRQARMCFMTWKYPJNJQV9VSFZ9EWB9GVEAFUXHWRNUXQLCSBWROOITBATWUXUYGSMGAXKGEBP9ZJWXQWHBVPOSLDHTWXUOFQNO9EXSYPQF9LQLQAFNRU9MTIIRQLBBBYKUPANWRQKGESFARQIRUTGFMZVUKHZJYKTYOARTDOBIYBFRHJWEFHCYVHRHTLTWBRMUDVIVQVNELQMQRXYDNGVSICZINWIZCIWVFXLYOLYKWDNWCWFZUXHUWOPRDHMTSXOZX9CVHANU9ZXTJOGKEPYR9CHGOTIUQSWIALAOIKHQFXWY9ZWTSZADVXJNNZOLSCXVVFBRHLRBTGMSZOYNIXTAMABKGJTLGTZKRHOPPJMNYIQNVKRGXUQDWYEIEZYM9CSXO9YLSBJLDJUWOLUXDEKBGGEIDEXFLZMESDOITNYTNRLGOMHJH9HOLXJABUNLXCZYTXFPZMHRJPLXSVPDBJBBZX9TBIMZZFZOXUSFEJYHEXPFXGJCQTBBLPEEWAPHUETGXSXYYAF9PCCCOONRMQGAPJ9JO9BZQ9QSKTPFFYIFVHSLAZY9CWYSIMKDOSLRKWBHPGJGVEJEEMLCCWXKSOCMBMZZZJWYBBXE9FTAYJALGWITJRXAXWZEXMECTZEEIWZPHYX";
@Test
public void testAddressGeneration() throws InvalidAddressException {
public void testAddressGeneration() throws InvalidAddressException, InvalidSecurityLevelException {
assertEquals(FIRST_ADDR, IotaAPIUtils.newAddress(TEST_SEED, 2, 0, true, null));
assertEquals(SIXTH_ADDR, IotaAPIUtils.newAddress(TEST_SEED, 2, 5, true, null));
}
@Test
public void testSigning() throws InvalidAddressException {
public void testSigning() throws InvalidAddressException, InvalidSecurityLevelException {
// we can sign any hash, so for convenience we will sign the first
// address of our test seed
// (but remove the checksum) with the key of our fifth address
@@ -42,6 +43,17 @@ public class SigningTest {
assertEquals(SIGNATURE2, Converter.trytes(signature2));
}
@Test
public void testKeyLength() throws InvalidSecurityLevelException {
Signing signing = new Signing(null);
int[] key = signing.key(Converter.trits(TEST_SEED), 5, 1);
assertEquals(Signing.KEY_LENGTH, key.length);
key = signing.key(Converter.trits(TEST_SEED), 5, 2);
assertEquals(2 * Signing.KEY_LENGTH, key.length);
key = signing.key(Converter.trits(TEST_SEED), 5, 3);
assertEquals(3 * Signing.KEY_LENGTH, key.length);
}
@Test
public void testVerifying() throws InvalidAddressException {
assertTrue(new Signing(null).validateSignatures(removeChecksum(SIXTH_ADDR), new String[]{SIGNATURE1, SIGNATURE2}, removeChecksum(FIRST_ADDR)));