Merge branch 'MemoImplementation'
This commit is contained in:
commit
45476baa7e
59 changed files with 617 additions and 327 deletions
|
@ -1,3 +1,3 @@
|
|||
rootProject.name = 'fullerene'
|
||||
rootProject.name = 'graphenej'
|
||||
include 'application'
|
||||
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
|
||||
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
||||
|
||||
/**
|
||||
* Created by nelson on 11/9/16.
|
||||
*/
|
||||
public class Memo implements ByteSerializable {
|
||||
//TODO: Give this class a proper implementation
|
||||
|
||||
@Override
|
||||
public byte[] toBytes() {
|
||||
return new byte[1];
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.luminiasoft.bitshares.interfaces.GrapheneSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.GrapheneSerializable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.common.primitives.UnsignedLong;
|
||||
|
@ -6,8 +6,6 @@ import com.google.gson.Gson;
|
|||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
|
||||
/**
|
||||
* Class used to encapsulate operations related to the account_update_operation.
|
|
@ -1,6 +1,6 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.luminiasoft.bitshares.errors.MalformedTransactionException;
|
||||
import de.bitsharesmunich.graphenej.errors.MalformedTransactionException;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
|
||||
import java.util.ArrayList;
|
|
@ -1,14 +1,12 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.luminiasoft.bitshares.errors.MalformedAddressException;
|
||||
import de.bitsharesmunich.graphenej.errors.MalformedAddressException;
|
||||
import org.bitcoinj.core.Base58;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.spongycastle.crypto.digests.RIPEMD160Digest;
|
||||
import org.spongycastle.math.ec.ECPoint;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.IllegalFormatException;
|
||||
|
||||
/**
|
||||
* Class used to encapsulate address-related operations.
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
/**
|
||||
* Created by nelson on 11/9/16.
|
|
@ -1,16 +1,16 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.google.common.primitives.UnsignedLong;
|
||||
import com.google.gson.*;
|
||||
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
||||
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.ByteSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.JsonSerializable;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Created by nelson on 11/7/16.
|
||||
*/
|
||||
public class AssetAmount implements ByteSerializable, JsonSerializable{
|
||||
public class AssetAmount implements ByteSerializable, JsonSerializable {
|
||||
/**
|
||||
* Constants used in the JSON serialization procedure.
|
||||
*/
|
|
@ -1,11 +1,11 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.luminiasoft.bitshares.errors.MalformedAddressException;
|
||||
import com.luminiasoft.bitshares.interfaces.GrapheneSerializable;
|
||||
import de.bitsharesmunich.graphenej.errors.MalformedAddressException;
|
||||
import de.bitsharesmunich.graphenej.interfaces.GrapheneSerializable;
|
||||
|
||||
import java.util.*;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.bitcoinj.core.Base58;
|
|
@ -1,12 +1,12 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
||||
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.ByteSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.JsonSerializable;
|
||||
|
||||
/**
|
||||
* Created by nelson on 11/5/16.
|
||||
*/
|
||||
public abstract class BaseOperation implements ByteSerializable, JsonSerializable{
|
||||
public abstract class BaseOperation implements ByteSerializable, JsonSerializable {
|
||||
|
||||
protected OperationType type;
|
||||
|
|
@ -1,10 +1,6 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
import de.bitsharesmunich.graphenej.interfaces.ByteSerializable;
|
||||
|
||||
/**
|
||||
* This class encapsulates all block-related information needed in order to build a valid transaction.
|
|
@ -1,8 +1,7 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.luminiasoft.bitshares.crypto.AndroidRandomSource;
|
||||
import com.luminiasoft.bitshares.crypto.SecureRandomStrengthener;
|
||||
import org.bitcoinj.core.Base58;
|
||||
import de.bitsharesmunich.graphenej.crypto.AndroidRandomSource;
|
||||
import de.bitsharesmunich.graphenej.crypto.SecureRandomStrengthener;
|
||||
import org.bitcoinj.core.DumpedPrivateKey;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
|
@ -11,7 +10,6 @@ import java.io.UnsupportedEncodingException;
|
|||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.ECPoint;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
/**
|
||||
* Created by nelson on 11/8/16.
|
|
@ -1,9 +1,9 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
||||
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.ByteSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.JsonSerializable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -1,24 +1,16 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.luminiasoft.bitshares.crypto.AndroidRandomSource;
|
||||
import com.luminiasoft.bitshares.crypto.SecureRandomStrengthener;
|
||||
import de.bitsharesmunich.graphenej.crypto.SecureRandomStrengthener;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.spongycastle.crypto.DataLengthException;
|
||||
import org.spongycastle.crypto.InvalidCipherTextException;
|
||||
import org.spongycastle.crypto.engines.AESFastEngine;
|
||||
import org.spongycastle.crypto.modes.CBCBlockCipher;
|
||||
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
|
||||
import org.spongycastle.crypto.params.KeyParameter;
|
||||
import org.spongycastle.crypto.params.ParametersWithIV;
|
||||
|
||||
/**
|
||||
* Class to manage the Bin Files
|
||||
|
@ -38,7 +30,7 @@ public abstract class FileBin {
|
|||
public static String getBrainkeyFromByte(byte[] input, String password) {
|
||||
try {
|
||||
byte[] publicKey = new byte[33];
|
||||
byte[] rawDataEncripted = new byte[input.length-33];
|
||||
byte[] rawDataEncripted = new byte[input.length - 33];
|
||||
|
||||
System.arraycopy(input, 0, publicKey, 0, publicKey.length);
|
||||
System.arraycopy(input, 33, rawDataEncripted, 0, rawDataEncripted.length);
|
||||
|
@ -49,14 +41,13 @@ public abstract class FileBin {
|
|||
byte[] finalKey = randomECKey.getPubKeyPoint().multiply(ECKey.fromPrivate(md.digest(password.getBytes("UTF-8"))).getPrivKey()).normalize().getXCoord().getEncoded();
|
||||
MessageDigest md1 = MessageDigest.getInstance("SHA-512");
|
||||
finalKey = md1.digest(finalKey);
|
||||
byte[] rawData = decryptAES(rawDataEncripted, byteToString(finalKey).getBytes());
|
||||
byte[] rawData = Util.decryptAES(rawDataEncripted, Util.byteToString(finalKey).getBytes());
|
||||
|
||||
byte[] checksum = new byte[4];
|
||||
System.arraycopy(rawData, 0, checksum, 0, 4);
|
||||
byte[] compressedData = new byte[rawData.length - 4];
|
||||
System.arraycopy(rawData, 4, compressedData, 0, compressedData.length);
|
||||
|
||||
System.out.println("Despues:"+byteToString(compressedData));
|
||||
byte[] wallet_object_bytes = Util.decompress(compressedData, Util.XZ);
|
||||
String wallet_string = new String(wallet_object_bytes, "UTF-8");
|
||||
JsonObject wallet = new JsonParser().parse(wallet_string).getAsJsonObject();
|
||||
|
@ -69,17 +60,17 @@ public abstract class FileBin {
|
|||
byte[] encKey_enc = new BigInteger(wallet.get("encryption_key").getAsString(), 16).toByteArray();
|
||||
byte[] temp = new byte[encKey_enc.length - (encKey_enc[0] == 0 ? 1 : 0)];
|
||||
System.arraycopy(encKey_enc, (encKey_enc[0] == 0 ? 1 : 0), temp, 0, temp.length);
|
||||
byte[] encKey = decryptAES(temp, password.getBytes("UTF-8"));
|
||||
byte[] encKey = Util.decryptAES(temp, password.getBytes("UTF-8"));
|
||||
temp = new byte[encKey.length];
|
||||
System.arraycopy(encKey, 0, temp, 0, temp.length);
|
||||
|
||||
byte[] encBrain = new BigInteger(wallet.get("encrypted_brainkey").getAsString(), 16).toByteArray();
|
||||
while(encBrain[0] == 0){
|
||||
byte[]temp2 = new byte[encBrain.length-1];
|
||||
while (encBrain[0] == 0) {
|
||||
byte[] temp2 = new byte[encBrain.length - 1];
|
||||
System.arraycopy(encBrain, 1, temp2, 0, temp2.length);
|
||||
encBrain = temp2;
|
||||
}
|
||||
String BrainKey = new String((decryptAES(encBrain, temp)), "UTF-8");
|
||||
String BrainKey = new String((Util.decryptAES(encBrain, temp)), "UTF-8");
|
||||
|
||||
return BrainKey;
|
||||
|
||||
|
@ -105,15 +96,15 @@ public abstract class FileBin {
|
|||
//randomStrengthener.addEntropySource(new AndroidRandomSource());
|
||||
SecureRandom secureRandom = randomStrengthener.generateAndSeedRandomNumberGenerator();
|
||||
secureRandom.nextBytes(encKey);
|
||||
byte[] encKey_enc = encryptAES(encKey, password.getBytes("UTF-8"));
|
||||
byte[] encBrain = encryptAES(BrainKey.getBytes("ASCII"), encKey);
|
||||
byte[] encKey_enc = Util.encryptAES(encKey, password.getBytes("UTF-8"));
|
||||
byte[] encBrain = Util.encryptAES(BrainKey.getBytes("ASCII"), encKey);
|
||||
|
||||
/**
|
||||
* Data to Store
|
||||
*/
|
||||
JsonObject wallet = new JsonObject();
|
||||
wallet.add("encryption_key", new JsonParser().parse(byteToString(encKey_enc)));
|
||||
wallet.add("encrypted_brainkey", new JsonParser().parse(byteToString(encBrain)));
|
||||
wallet.add("encryption_key", new JsonParser().parse(Util.byteToString(encKey_enc)));
|
||||
wallet.add("encrypted_brainkey", new JsonParser().parse(Util.byteToString(encBrain)));
|
||||
JsonObject wallet_object = new JsonObject();
|
||||
wallet_object.add("wallet", wallet);
|
||||
JsonArray accountNames = new JsonArray();
|
||||
|
@ -122,7 +113,6 @@ public abstract class FileBin {
|
|||
accountNames.add(jsonAccountName);
|
||||
wallet_object.add("linked_accounts", accountNames);
|
||||
byte[] compressedData = Util.compress(wallet_object.toString().getBytes("UTF-8"), Util.XZ);
|
||||
System.out.println("Antes:"+byteToString(compressedData));
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
byte[] checksum = md.digest(compressedData);
|
||||
byte[] rawData = new byte[compressedData.length + 4];
|
||||
|
@ -135,7 +125,7 @@ public abstract class FileBin {
|
|||
byte[] finalKey = randomECKey.getPubKeyPoint().multiply(ECKey.fromPrivate(md.digest(password.getBytes("UTF-8"))).getPrivKey()).normalize().getXCoord().getEncoded();
|
||||
MessageDigest md1 = MessageDigest.getInstance("SHA-512");
|
||||
finalKey = md1.digest(finalKey);
|
||||
rawData = encryptAES(rawData, byteToString(finalKey).getBytes());
|
||||
rawData = Util.encryptAES(rawData, Util.byteToString(finalKey).getBytes());
|
||||
|
||||
byte[] result = new byte[rawData.length + randPubKey.length];
|
||||
System.arraycopy(randPubKey, 0, result, 0, randPubKey.length);
|
||||
|
@ -149,80 +139,5 @@ public abstract class FileBin {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static byte[] encryptAES(byte[] input, byte[] key) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-512");
|
||||
byte[] result = md.digest(key);
|
||||
byte[] ivBytes = new byte[16];
|
||||
System.arraycopy(result, 32, ivBytes, 0, 16);
|
||||
byte[] sksBytes = new byte[32];
|
||||
System.arraycopy(result, 0, sksBytes, 0, 32);
|
||||
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESFastEngine()));
|
||||
cipher.init(true, new ParametersWithIV(new KeyParameter(sksBytes), ivBytes));
|
||||
byte[] temp = new byte[input.length + (16 - (input.length % 16))];
|
||||
System.arraycopy(input, 0, temp, 0, input.length);
|
||||
Arrays.fill(temp, input.length, temp.length, (byte) (16 - (input.length % 16)));
|
||||
byte[] out = new byte[cipher.getOutputSize(temp.length)];
|
||||
int proc = cipher.processBytes(temp, 0, temp.length, out, 0);
|
||||
cipher.doFinal(out, proc);
|
||||
temp = new byte[out.length - 16];
|
||||
System.arraycopy(out, 0, temp, 0, temp.length);
|
||||
return temp;
|
||||
} catch (NoSuchAlgorithmException | DataLengthException | IllegalStateException | InvalidCipherTextException ex) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static byte[] decryptAES(byte[] input, byte[] key) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-512");
|
||||
byte[] result = md.digest(key);
|
||||
byte[] ivBytes = new byte[16];
|
||||
System.arraycopy(result, 32, ivBytes, 0, 16);
|
||||
byte[] sksBytes = new byte[32];
|
||||
System.arraycopy(result, 0, sksBytes, 0, 32);
|
||||
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESFastEngine()));
|
||||
cipher.init(false, new ParametersWithIV(new KeyParameter(sksBytes), ivBytes));
|
||||
|
||||
byte[] pre_out = new byte[cipher.getOutputSize(input.length)];
|
||||
int proc = cipher.processBytes(input, 0, input.length, pre_out, 0);
|
||||
int proc2 = cipher.doFinal(pre_out, proc);
|
||||
byte[] out = new byte[proc+proc2];
|
||||
System.arraycopy(pre_out, 0, out, 0, proc+proc2);
|
||||
|
||||
//Unpadding
|
||||
byte countByte = (byte)((byte)out[out.length-1] % 16);
|
||||
int count = countByte & 0xFF;
|
||||
|
||||
if ((count > 15) || (count <= 0)){
|
||||
return out;
|
||||
}
|
||||
|
||||
byte[] temp = new byte[count];
|
||||
System.arraycopy(out, out.length - count, temp, 0, temp.length);
|
||||
byte[] temp2 = new byte[count];
|
||||
Arrays.fill(temp2, (byte) count);
|
||||
if (Arrays.equals(temp, temp2)) {
|
||||
temp = new byte[out.length - count];
|
||||
System.arraycopy(out, 0, temp, 0, out.length - count);
|
||||
return temp;
|
||||
} else {
|
||||
return out;
|
||||
}
|
||||
} catch (NoSuchAlgorithmException | DataLengthException | IllegalStateException | InvalidCipherTextException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String byteToString(byte[] input) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (byte in : input) {
|
||||
if ((in & 0xff) < 0x10) {
|
||||
result.append("0");
|
||||
}
|
||||
result.append(Integer.toHexString(in & 0xff));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.JsonSerializable;
|
||||
import org.bitcoinj.core.Base58;
|
||||
|
||||
/**
|
|
@ -1,31 +1,18 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
|
||||
import org.bitcoinj.core.ECKey;
|
||||
|
||||
import java.io.IOException;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
public class Main {
|
||||
|
||||
// Brain key from Nelson's app referencing the bilthon-83 account
|
||||
public static final String BILTHON_83_BRAIN_KEY = "PUMPER ISOTOME SERE STAINER CLINGER MOONLIT CHAETA UPBRIM AEDILIC BERTHER NIT SHAP SAID SHADING JUNCOUS CHOUGH";
|
||||
public static final String BILTHON_83_BRAIN_KEY = System.getenv("BILTHON_83_BRAIN_KEY");
|
||||
|
||||
public static final String BILTHON_5_BRAIN_KEY = "UNMATE AURIGAL NAVET WAVICLE REWOVE ABBOTCY COWHERB OUTKICK STOPPER JUSSORY BEAMLET WIRY";
|
||||
public static final String BILTHON_5_BRAIN_KEY = System.getenv("BILTHON_5_BRAIN_KEY");
|
||||
|
||||
public static final String BILTHON_7_BRAIN_KEY = "VENIN QUOTHA OBESELY TORIC OSMATIC SPOKEN DIACOPE CUBICA TABULA REDDING APONIA TARTAR";
|
||||
public static final String BILTHON_7_BRAIN_KEY = System.getenv("BILTHON_7_BRAIN_KEY");
|
||||
|
||||
//public static final String BILTHON_83_BRAIN_KEY = "TWIXT SERMO TRILLI AUDIO PARDED PLUMET BIWA REHUNG MAUDLE VALVULA OUTBURN FEWNESS ALIENER UNTRACE PRICH TROKER";
|
||||
//public static final String BILTHON_83_BRAIN_KEY = "SIVER TIKKER FOGO HOMINAL PRAYER LUTEIN SMALLY ACARID MEROPIA TRANCE BOGONG IDDAT HICKORY SOUTANE MOOD DOWSER";
|
||||
public static final String BIP39_KEY = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
|
||||
|
||||
// WIF from Nelson's app referencing the bilthon-83 account
|
||||
// public static final String WIF = "5J96pne45qWM1WpektoeazN6k9Mt93jQ7LyueRxFfEMTiy6yxjM";
|
||||
// Brain key from an empty account created by the cli_wallet
|
||||
// public static final String BILTHON_83_BRAIN_KEY = "TWIXT SERMO TRILLI AUDIO PARDED PLUMET BIWA REHUNG MAUDLE VALVULA OUTBURN FEWNESS ALIENER UNTRACE PRICH TROKER";
|
||||
// WIF from an empty account created by the cli_wallet
|
||||
public static final String WIF = "5KMzB2GqGhnh7ufhgddmz1eKPHS72uTLeL9hHjSvPb1UywWknF5";
|
||||
|
||||
public static final String EXTERNAL_SIGNATURE = "1f36c41acb774fcbc9c231b5895ec9701d6872729098d8ea56d78dda72a6b54252694db85d7591de5751b7aea06871da15d63a1028758421607ffc143e53ef3306";
|
||||
|
||||
// Static block information used for transaction serialization tests
|
||||
public static int REF_BLOCK_NUM = 56204;
|
||||
public static int REF_BLOCK_PREFIX = 1614747814;
|
||||
|
@ -33,6 +20,7 @@ public class Main {
|
|||
|
||||
public static void main(String[] args) {
|
||||
Test test = new Test();
|
||||
|
||||
// test.testTransactionSerialization();
|
||||
// ECKey.ECDSASignature signature = test.testSigning();
|
||||
|
||||
|
@ -68,6 +56,8 @@ public class Main {
|
|||
// test.testAccountUpdateOperationBroadcast();
|
||||
// test.testCreateBinFile();
|
||||
// test.testImportBinFile();
|
||||
test.testLookupAccounts();
|
||||
test.testLookupAccounts();
|
||||
// test.testLookupAccounts();
|
||||
// test.testDecodeMemo();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
/**
|
||||
* Created by nelson on 11/6/16.
|
|
@ -1,7 +1,7 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.luminiasoft.bitshares.interfaces.GrapheneSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.GrapheneSerializable;
|
||||
|
||||
/**
|
||||
* Used whenever we have an optional field.
|
|
@ -1,6 +1,6 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.ByteSerializable;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
|
||||
/**
|
||||
|
@ -21,4 +21,8 @@ public class PublicKey implements ByteSerializable {
|
|||
public byte[] toBytes() {
|
||||
return publicKey.getPubKey();
|
||||
}
|
||||
|
||||
public String getAddress(){
|
||||
return new Address(publicKey).toString();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
/**
|
||||
* Created by nelson on 11/16/16.
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
@ -7,9 +7,8 @@ import com.google.gson.JsonElement;
|
|||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.luminiasoft.bitshares.errors.MalformedTransactionException;
|
||||
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
||||
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.ByteSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.JsonSerializable;
|
||||
|
||||
import org.bitcoinj.core.DumpedPrivateKey;
|
||||
import org.bitcoinj.core.ECKey;
|
|
@ -1,6 +1,6 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.luminiasoft.bitshares.errors.MalformedTransactionException;
|
||||
import de.bitsharesmunich.graphenej.errors.MalformedTransactionException;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import de.bitsharesmunich.graphenej.objects.Memo;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.gson.*;
|
||||
|
||||
|
@ -15,6 +16,7 @@ public class TransferOperation extends BaseOperation {
|
|||
public static final String KEY_EXTENSIONS = "extensions";
|
||||
public static final String KEY_FROM = "from";
|
||||
public static final String KEY_TO = "to";
|
||||
public static final String KEY_MEMO = "memo";
|
||||
|
||||
private AssetAmount fee;
|
||||
private AssetAmount amount;
|
||||
|
@ -85,14 +87,19 @@ public class TransferOperation extends BaseOperation {
|
|||
array.add(this.getId());
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.add(KEY_FEE, fee.toJsonObject());
|
||||
jsonObject.add(KEY_AMOUNT, amount.toJsonObject());
|
||||
jsonObject.add(KEY_EXTENSIONS, new JsonArray());
|
||||
jsonObject.addProperty(KEY_FROM, from.toJsonString());
|
||||
jsonObject.addProperty(KEY_TO, to.toJsonString());
|
||||
jsonObject.add(KEY_AMOUNT, amount.toJsonObject());
|
||||
jsonObject.add(KEY_MEMO, memo.toJsonObject());
|
||||
jsonObject.add(KEY_EXTENSIONS, new JsonArray());
|
||||
array.add(jsonObject);
|
||||
return array;
|
||||
}
|
||||
|
||||
public void setMemo(Memo memo) {
|
||||
this.memo = memo;
|
||||
}
|
||||
|
||||
public static class TransferSerializer implements JsonSerializer<TransferOperation> {
|
||||
|
||||
@Override
|
|
@ -1,6 +1,7 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.luminiasoft.bitshares.errors.MalformedTransactionException;
|
||||
import de.bitsharesmunich.graphenej.objects.Memo;
|
||||
import de.bitsharesmunich.graphenej.errors.MalformedTransactionException;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -15,6 +16,7 @@ public class TransferTransactionBuilder extends TransactionBuilder {
|
|||
private UserAccount destinationAccount;
|
||||
private AssetAmount transferAmount;
|
||||
private AssetAmount feeAmount;
|
||||
private Memo memo;
|
||||
|
||||
public TransferTransactionBuilder(){}
|
||||
|
||||
|
@ -52,6 +54,11 @@ public class TransferTransactionBuilder extends TransactionBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public TransferTransactionBuilder setMemo(Memo memo){
|
||||
this.memo = memo;
|
||||
return this;
|
||||
}
|
||||
|
||||
//TODO: Add support for multiple transfer operations in a single transaction
|
||||
public TransferTransactionBuilder addOperation(TransferOperation transferOperation){
|
||||
if(operations == null){
|
||||
|
@ -84,6 +91,9 @@ public class TransferTransactionBuilder extends TransactionBuilder {
|
|||
}else{
|
||||
transferOperation = new TransferOperation(sourceAccount, destinationAccount, transferAmount, feeAmount);
|
||||
}
|
||||
if(memo != null){
|
||||
transferOperation.setMemo(this.memo);
|
||||
}
|
||||
operations.add(transferOperation);
|
||||
}
|
||||
return new Transaction(privateKey, blockData, operations);
|
|
@ -1,8 +1,8 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
||||
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.ByteSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.JsonSerializable;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutput;
|
|
@ -1,20 +1,28 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import org.tukaani.xz.FinishableOutputStream;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import org.tukaani.xz.LZMA2Options;
|
||||
import org.tukaani.xz.LZMAInputStream;
|
||||
import org.tukaani.xz.LZMAOutputStream;
|
||||
import org.tukaani.xz.XZInputStream;
|
||||
import org.tukaani.xz.XZOutputStream;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.spongycastle.crypto.DataLengthException;
|
||||
import org.spongycastle.crypto.InvalidCipherTextException;
|
||||
import org.spongycastle.crypto.engines.AESFastEngine;
|
||||
import org.spongycastle.crypto.modes.CBCBlockCipher;
|
||||
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
|
||||
import org.spongycastle.crypto.params.KeyParameter;
|
||||
import org.spongycastle.crypto.params.ParametersWithIV;
|
||||
|
||||
/**
|
||||
* Class used to encapsulate common utility methods
|
||||
|
@ -142,7 +150,101 @@ public class Util {
|
|||
* @param input A Long value
|
||||
* @return The array of bytes that represent this value in the reverse format.
|
||||
*/
|
||||
public static byte[] revertLong(Long input){
|
||||
public static byte[] revertLong(Long input) {
|
||||
return ByteBuffer.allocate(Long.SIZE / 8).putLong(Long.reverseBytes(input)).array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to encrypt a message with AES
|
||||
* @param input data to encrypt
|
||||
* @param key key for encryption
|
||||
* @return AES Encription of input
|
||||
*/
|
||||
public static byte[] encryptAES(byte[] input, byte[] key) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-512");
|
||||
byte[] result = md.digest(key);
|
||||
byte[] ivBytes = new byte[16];
|
||||
System.arraycopy(result, 32, ivBytes, 0, 16);
|
||||
byte[] sksBytes = new byte[32];
|
||||
System.arraycopy(result, 0, sksBytes, 0, 32);
|
||||
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESFastEngine()));
|
||||
cipher.init(true, new ParametersWithIV(new KeyParameter(sksBytes), ivBytes));
|
||||
byte[] temp = new byte[input.length + (16 - (input.length % 16))];
|
||||
System.arraycopy(input, 0, temp, 0, input.length);
|
||||
Arrays.fill(temp, input.length, temp.length, (byte) (16 - (input.length % 16)));
|
||||
byte[] out = new byte[cipher.getOutputSize(temp.length)];
|
||||
int proc = cipher.processBytes(temp, 0, temp.length, out, 0);
|
||||
cipher.doFinal(out, proc);
|
||||
temp = new byte[out.length - 16];
|
||||
System.arraycopy(out, 0, temp, 0, temp.length);
|
||||
return temp;
|
||||
} catch (NoSuchAlgorithmException | DataLengthException | IllegalStateException | InvalidCipherTextException ex) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to decrypt a message with AES encryption
|
||||
* @param input data to decrypt
|
||||
* @param key key for decryption
|
||||
* @return input decrypted with AES. Null if the decrypt failed (Bad Key)
|
||||
*/
|
||||
public static byte[] decryptAES(byte[] input, byte[] key) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-512");
|
||||
byte[] result = md.digest(key);
|
||||
byte[] ivBytes = new byte[16];
|
||||
System.arraycopy(result, 32, ivBytes, 0, 16);
|
||||
byte[] sksBytes = new byte[32];
|
||||
System.arraycopy(result, 0, sksBytes, 0, 32);
|
||||
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESFastEngine()));
|
||||
cipher.init(false, new ParametersWithIV(new KeyParameter(sksBytes), ivBytes));
|
||||
|
||||
byte[] pre_out = new byte[cipher.getOutputSize(input.length)];
|
||||
int proc = cipher.processBytes(input, 0, input.length, pre_out, 0);
|
||||
int proc2 = cipher.doFinal(pre_out, proc);
|
||||
byte[] out = new byte[proc+proc2];
|
||||
System.arraycopy(pre_out, 0, out, 0, proc+proc2);
|
||||
|
||||
//Unpadding
|
||||
byte countByte = (byte)((byte)out[out.length-1] % 16);
|
||||
int count = countByte & 0xFF;
|
||||
|
||||
if ((count > 15) || (count <= 0)){
|
||||
return out;
|
||||
}
|
||||
|
||||
byte[] temp = new byte[count];
|
||||
System.arraycopy(out, out.length - count, temp, 0, temp.length);
|
||||
byte[] temp2 = new byte[count];
|
||||
Arrays.fill(temp2, (byte) count);
|
||||
if (Arrays.equals(temp, temp2)) {
|
||||
temp = new byte[out.length - count];
|
||||
System.arraycopy(out, 0, temp, 0, out.length - count);
|
||||
return temp;
|
||||
} else {
|
||||
return out;
|
||||
}
|
||||
} catch (NoSuchAlgorithmException | DataLengthException | IllegalStateException | InvalidCipherTextException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform an array of bytes to an hex String representation
|
||||
* @param input array of bytes to transform as a string
|
||||
* @return Input as a String
|
||||
*/
|
||||
public static String byteToString(byte[] input) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (byte in : input) {
|
||||
if ((in & 0xff) < 0x10) {
|
||||
result.append("0");
|
||||
}
|
||||
result.append(Integer.toHexString(in & 0xff));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
|
||||
import java.io.DataInput;
|
|
@ -1,6 +1,6 @@
|
|||
package com.luminiasoft.bitshares;
|
||||
package de.bitsharesmunich.graphenej;
|
||||
|
||||
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.ByteSerializable;
|
||||
|
||||
/**
|
||||
* Created by nelson on 12/5/16.
|
|
@ -1,13 +1,13 @@
|
|||
package com.luminiasoft.bitshares.ws;
|
||||
package de.bitsharesmunich.graphenej.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.luminiasoft.bitshares.RPC;
|
||||
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
||||
import com.luminiasoft.bitshares.models.AccountProperties;
|
||||
import com.luminiasoft.bitshares.models.ApiCall;
|
||||
import com.luminiasoft.bitshares.models.BaseResponse;
|
||||
import com.luminiasoft.bitshares.models.WitnessResponse;
|
||||
import de.bitsharesmunich.graphenej.RPC;
|
||||
import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener;
|
||||
import de.bitsharesmunich.graphenej.models.AccountProperties;
|
||||
import de.bitsharesmunich.graphenej.models.ApiCall;
|
||||
import de.bitsharesmunich.graphenej.models.BaseResponse;
|
||||
import de.bitsharesmunich.graphenej.models.WitnessResponse;
|
||||
import com.neovisionaries.ws.client.WebSocket;
|
||||
import com.neovisionaries.ws.client.WebSocketAdapter;
|
||||
import com.neovisionaries.ws.client.WebSocketException;
|
|
@ -1,20 +1,21 @@
|
|||
package com.luminiasoft.bitshares.ws;
|
||||
package de.bitsharesmunich.graphenej.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.luminiasoft.bitshares.RPC;
|
||||
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
||||
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
||||
import com.luminiasoft.bitshares.models.AccountProperties;
|
||||
import com.luminiasoft.bitshares.models.ApiCall;
|
||||
import com.luminiasoft.bitshares.models.BaseResponse;
|
||||
import com.luminiasoft.bitshares.models.WitnessResponse;
|
||||
import de.bitsharesmunich.graphenej.RPC;
|
||||
import de.bitsharesmunich.graphenej.interfaces.JsonSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener;
|
||||
import de.bitsharesmunich.graphenej.models.AccountProperties;
|
||||
import de.bitsharesmunich.graphenej.models.BaseResponse;
|
||||
import com.neovisionaries.ws.client.WebSocket;
|
||||
import com.neovisionaries.ws.client.WebSocketAdapter;
|
||||
import com.neovisionaries.ws.client.WebSocketException;
|
||||
import com.neovisionaries.ws.client.WebSocketFrame;
|
||||
import de.bitsharesmunich.graphenej.models.ApiCall;
|
||||
import de.bitsharesmunich.graphenej.models.WitnessResponse;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
|
@ -1,17 +1,16 @@
|
|||
package com.luminiasoft.bitshares.ws;
|
||||
package de.bitsharesmunich.graphenej.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.luminiasoft.bitshares.Address;
|
||||
import com.luminiasoft.bitshares.RPC;
|
||||
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
||||
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
||||
import com.luminiasoft.bitshares.models.AccountProperties;
|
||||
import com.luminiasoft.bitshares.models.ApiCall;
|
||||
import com.luminiasoft.bitshares.models.BaseResponse;
|
||||
import com.luminiasoft.bitshares.models.WitnessResponse;
|
||||
import de.bitsharesmunich.graphenej.Address;
|
||||
import de.bitsharesmunich.graphenej.RPC;
|
||||
import de.bitsharesmunich.graphenej.interfaces.JsonSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener;
|
||||
import de.bitsharesmunich.graphenej.models.ApiCall;
|
||||
import de.bitsharesmunich.graphenej.models.BaseResponse;
|
||||
import de.bitsharesmunich.graphenej.models.WitnessResponse;
|
||||
import com.neovisionaries.ws.client.WebSocket;
|
||||
import com.neovisionaries.ws.client.WebSocketAdapter;
|
||||
import com.neovisionaries.ws.client.WebSocketException;
|
|
@ -1,17 +1,17 @@
|
|||
package com.luminiasoft.bitshares.ws;
|
||||
package de.bitsharesmunich.graphenej.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.luminiasoft.bitshares.AssetAmount;
|
||||
import com.luminiasoft.bitshares.RPC;
|
||||
import com.luminiasoft.bitshares.TransferOperation;
|
||||
import com.luminiasoft.bitshares.UserAccount;
|
||||
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
||||
import com.luminiasoft.bitshares.models.ApiCall;
|
||||
import com.luminiasoft.bitshares.models.BaseResponse;
|
||||
import com.luminiasoft.bitshares.models.HistoricalTransfer;
|
||||
import com.luminiasoft.bitshares.models.WitnessResponse;
|
||||
import de.bitsharesmunich.graphenej.AssetAmount;
|
||||
import de.bitsharesmunich.graphenej.RPC;
|
||||
import de.bitsharesmunich.graphenej.TransferOperation;
|
||||
import de.bitsharesmunich.graphenej.UserAccount;
|
||||
import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener;
|
||||
import de.bitsharesmunich.graphenej.models.ApiCall;
|
||||
import de.bitsharesmunich.graphenej.models.BaseResponse;
|
||||
import de.bitsharesmunich.graphenej.models.HistoricalTransfer;
|
||||
import de.bitsharesmunich.graphenej.models.WitnessResponse;
|
||||
import com.neovisionaries.ws.client.WebSocket;
|
||||
import com.neovisionaries.ws.client.WebSocketAdapter;
|
||||
import com.neovisionaries.ws.client.WebSocketException;
|
|
@ -1,20 +1,20 @@
|
|||
package com.luminiasoft.bitshares.ws;
|
||||
package de.bitsharesmunich.graphenej.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.luminiasoft.bitshares.Asset;
|
||||
import com.luminiasoft.bitshares.AssetAmount;
|
||||
import com.luminiasoft.bitshares.BaseOperation;
|
||||
import com.luminiasoft.bitshares.RPC;
|
||||
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
||||
import com.luminiasoft.bitshares.models.ApiCall;
|
||||
import com.luminiasoft.bitshares.models.BaseResponse;
|
||||
import com.luminiasoft.bitshares.models.WitnessResponse;
|
||||
import de.bitsharesmunich.graphenej.AssetAmount;
|
||||
import de.bitsharesmunich.graphenej.RPC;
|
||||
import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener;
|
||||
import de.bitsharesmunich.graphenej.models.ApiCall;
|
||||
import de.bitsharesmunich.graphenej.models.BaseResponse;
|
||||
import de.bitsharesmunich.graphenej.models.WitnessResponse;
|
||||
import com.neovisionaries.ws.client.WebSocket;
|
||||
import com.neovisionaries.ws.client.WebSocketAdapter;
|
||||
import com.neovisionaries.ws.client.WebSocketException;
|
||||
import com.neovisionaries.ws.client.WebSocketFrame;
|
||||
import de.bitsharesmunich.graphenej.Asset;
|
||||
import de.bitsharesmunich.graphenej.BaseOperation;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
|
@ -1,13 +1,13 @@
|
|||
package com.luminiasoft.bitshares.ws;
|
||||
package de.bitsharesmunich.graphenej.api;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.luminiasoft.bitshares.RPC;
|
||||
import com.luminiasoft.bitshares.UserAccount;
|
||||
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
||||
import com.luminiasoft.bitshares.models.ApiCall;
|
||||
import com.luminiasoft.bitshares.models.BaseResponse;
|
||||
import com.luminiasoft.bitshares.models.WitnessResponse;
|
||||
import de.bitsharesmunich.graphenej.RPC;
|
||||
import de.bitsharesmunich.graphenej.UserAccount;
|
||||
import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener;
|
||||
import de.bitsharesmunich.graphenej.models.ApiCall;
|
||||
import de.bitsharesmunich.graphenej.models.BaseResponse;
|
||||
import de.bitsharesmunich.graphenej.models.WitnessResponse;
|
||||
import com.neovisionaries.ws.client.WebSocket;
|
||||
import com.neovisionaries.ws.client.WebSocketAdapter;
|
||||
import com.neovisionaries.ws.client.WebSocketException;
|
|
@ -1,23 +1,22 @@
|
|||
package com.luminiasoft.bitshares.ws;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.luminiasoft.bitshares.*;
|
||||
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
||||
import com.luminiasoft.bitshares.models.ApiCall;
|
||||
import com.luminiasoft.bitshares.models.BaseResponse;
|
||||
import com.luminiasoft.bitshares.models.DynamicGlobalProperties;
|
||||
import com.luminiasoft.bitshares.models.WitnessResponse;
|
||||
import com.neovisionaries.ws.client.WebSocket;
|
||||
import com.neovisionaries.ws.client.WebSocketAdapter;
|
||||
import com.neovisionaries.ws.client.WebSocketException;
|
||||
import com.neovisionaries.ws.client.WebSocketFrame;
|
||||
package de.bitsharesmunich.graphenej.api;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import de.bitsharesmunich.graphenej.*;
|
||||
import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener;
|
||||
import de.bitsharesmunich.graphenej.models.ApiCall;
|
||||
import de.bitsharesmunich.graphenej.models.BaseResponse;
|
||||
import de.bitsharesmunich.graphenej.models.DynamicGlobalProperties;
|
||||
import de.bitsharesmunich.graphenej.models.WitnessResponse;
|
||||
import com.neovisionaries.ws.client.WebSocket;
|
||||
import com.neovisionaries.ws.client.WebSocketAdapter;
|
||||
import com.neovisionaries.ws.client.WebSocketException;
|
||||
import com.neovisionaries.ws.client.WebSocketFrame;
|
||||
|
||||
/**
|
||||
* Class that will handle the transaction publication procedure.
|
|
@ -32,7 +32,7 @@
|
|||
* fitness for a particular purpose and non-infringement.
|
||||
*/
|
||||
|
||||
package com.luminiasoft.bitshares.crypto;
|
||||
package de.bitsharesmunich.graphenej.crypto;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares.crypto;
|
||||
package de.bitsharesmunich.graphenej.crypto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.luminiasoft.bitshares.crypto;
|
||||
package de.bitsharesmunich.graphenej.crypto;
|
||||
|
||||
public interface RandomSource {
|
||||
/**
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares.crypto;
|
||||
package de.bitsharesmunich.graphenej.crypto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.DigestException;
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares.errors;
|
||||
package de.bitsharesmunich.graphenej.errors;
|
||||
|
||||
/**
|
||||
* Created by nelson on 12/1/16.
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares.errors;
|
||||
package de.bitsharesmunich.graphenej.errors;
|
||||
|
||||
/**
|
||||
* Created by nelson on 11/14/16.
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares.interfaces;
|
||||
package de.bitsharesmunich.graphenej.interfaces;
|
||||
|
||||
/**
|
||||
* Interface implemented by all entities for which makes sense to have a byte-array representation.
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares.interfaces;
|
||||
package de.bitsharesmunich.graphenej.interfaces;
|
||||
|
||||
/**
|
||||
* Interface used to group both ByteSerializable and JsonSerializable interfaces.
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares.interfaces;
|
||||
package de.bitsharesmunich.graphenej.interfaces;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package com.luminiasoft.bitshares.interfaces;
|
||||
package de.bitsharesmunich.graphenej.interfaces;
|
||||
|
||||
import com.luminiasoft.bitshares.models.BaseResponse;
|
||||
import com.luminiasoft.bitshares.models.WitnessResponse;
|
||||
import de.bitsharesmunich.graphenej.models.BaseResponse;
|
||||
import de.bitsharesmunich.graphenej.models.WitnessResponse;
|
||||
|
||||
/**
|
||||
* Class used to represent any listener to network requests.
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares.models;
|
||||
package de.bitsharesmunich.graphenej.models;
|
||||
|
||||
/**
|
||||
* Created by nelson on 11/15/16.
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares.models;
|
||||
package de.bitsharesmunich.graphenej.models;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
|
@ -6,7 +6,7 @@ import com.google.gson.JsonElement;
|
|||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.JsonSerializable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares.models;
|
||||
package de.bitsharesmunich.graphenej.models;
|
||||
|
||||
/**
|
||||
* Created by nelson on 11/12/16.
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares.models;
|
||||
package de.bitsharesmunich.graphenej.models;
|
||||
|
||||
/**
|
||||
* Class used to deserialize the 'result' field returned by the full node after making a call
|
|
@ -1,6 +1,6 @@
|
|||
package com.luminiasoft.bitshares.models;
|
||||
package de.bitsharesmunich.graphenej.models;
|
||||
|
||||
import com.luminiasoft.bitshares.TransferOperation;
|
||||
import de.bitsharesmunich.graphenej.TransferOperation;
|
||||
|
||||
/**
|
||||
* This class offers support to deserialization of transfer operations received by the API
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares.models;
|
||||
package de.bitsharesmunich.graphenej.models;
|
||||
|
||||
/**
|
||||
* Generic witness response
|
184
src/main/java/de/bitsharesmunich/graphenej/objects/Memo.java
Normal file
184
src/main/java/de/bitsharesmunich/graphenej/objects/Memo.java
Normal file
|
@ -0,0 +1,184 @@
|
|||
package de.bitsharesmunich.graphenej.objects;
|
||||
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import de.bitsharesmunich.graphenej.PublicKey;
|
||||
import de.bitsharesmunich.graphenej.Util;
|
||||
import de.bitsharesmunich.graphenej.crypto.SecureRandomStrengthener;
|
||||
import de.bitsharesmunich.graphenej.interfaces.ByteSerializable;
|
||||
import de.bitsharesmunich.graphenej.interfaces.JsonSerializable;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* Created by nelson on 11/9/16.
|
||||
*/
|
||||
public class Memo implements ByteSerializable, JsonSerializable {
|
||||
|
||||
public static final String KEY_FROM = "from";
|
||||
public static final String KEY_TO = "to";
|
||||
public static final String KEY_NONCE = "nonce";
|
||||
public static final String KEY_MESSAGE = "message";
|
||||
|
||||
private PublicKey from;
|
||||
private PublicKey to;
|
||||
private final byte[] nonce = new byte[8];
|
||||
private byte[] message;
|
||||
|
||||
/**
|
||||
* Empty Constructor
|
||||
*/
|
||||
public Memo() {
|
||||
this.from = null;
|
||||
this.to = null;
|
||||
this.message = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement metod, serialized this Object
|
||||
* @return the byte array of this object serialized
|
||||
*/
|
||||
@Override
|
||||
public byte[] toBytes() {
|
||||
if ((this.from == null) || (this.to == null) || (this.message == null)) {
|
||||
return new byte[]{(byte) 0};
|
||||
} else {
|
||||
byte[] nonceformat = new byte[nonce.length];
|
||||
for (int i = 0; i < nonceformat.length; i++) {
|
||||
nonceformat[i] = nonce[nonce.length - i - 1];
|
||||
}
|
||||
return Bytes.concat(new byte[]{1}, this.from.toBytes(), this.to.toBytes(), nonceformat, new byte[]{(byte) this.message.length}, this.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a memo message using the input source key and destination key
|
||||
* @param fromKey The source destination, need to have a private key accesss
|
||||
* @param toKey The destination, needs only the public key access
|
||||
* @param msg The message in bytes
|
||||
* @return a Memo corresponding with the message encoding
|
||||
*/
|
||||
public static Memo encodeMessage(PublicKey fromKey, PublicKey toKey, byte[] msg) {
|
||||
return encodeMessage(fromKey, toKey, msg, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a message a return a memo with that message encoded
|
||||
*
|
||||
* @param fromKey The source destination, need to have a private key accesss
|
||||
* @param toKey The destination, needs only the public key access
|
||||
* @param msg The message in bytes
|
||||
* @param custom_nonce the custom nonce to be use or 0 to create a new one
|
||||
* @return a Memo corresponding with the message encoding
|
||||
*/
|
||||
public static Memo encodeMessage(PublicKey fromKey, PublicKey toKey, byte[] msg, long custom_nonce) {
|
||||
Memo memo = new Memo();
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
|
||||
memo.from = fromKey;
|
||||
memo.to = toKey;
|
||||
|
||||
if (custom_nonce == 0) {
|
||||
SecureRandomStrengthener randomStrengthener = SecureRandomStrengthener.getInstance();
|
||||
//randomStrengthener.addEntropySource(new AndroidRandomSource());
|
||||
SecureRandom secureRandom = randomStrengthener.generateAndSeedRandomNumberGenerator();
|
||||
secureRandom.nextBytes(memo.nonce);
|
||||
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
for (int i = 7; i >= 1; i--) {
|
||||
memo.nonce[i] = (byte) (time & 0xff);
|
||||
time = time / 0x100;
|
||||
}
|
||||
} else {
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
memo.nonce[i] = (byte) (custom_nonce & 0xff);
|
||||
custom_nonce = custom_nonce / 0x100;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] secret = toKey.getKey().getPubKeyPoint().multiply(fromKey.getKey().getPrivKey()).normalize().getXCoord().getEncoded();
|
||||
byte[] finalKey = new byte[secret.length + memo.nonce.length];
|
||||
System.arraycopy(secret, 0, finalKey, 0, secret.length);
|
||||
System.arraycopy(memo.nonce, 0, finalKey, secret.length, memo.nonce.length);
|
||||
|
||||
byte[] sha256Msg = md.digest(msg);
|
||||
byte[] serialChecksum = new byte[4];
|
||||
System.arraycopy(sha256Msg, 0, serialChecksum, 0, 4);
|
||||
byte[] msgFinal = new byte[serialChecksum.length + msg.length];
|
||||
System.arraycopy(serialChecksum, 0, msgFinal, 0, serialChecksum.length);
|
||||
System.arraycopy(msg, 0, msgFinal, serialChecksum.length, msg.length);
|
||||
memo.message = Util.encryptAES(msgFinal, finalKey);
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
}
|
||||
return memo;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the string coreesponding a encode memo
|
||||
*
|
||||
* @param fromKey The soruce key, need to have public key only
|
||||
* @param toKey The destination key, need to have private key access
|
||||
* @param msg The message to be decoded
|
||||
* @param nonce The nonce used in the decoded message
|
||||
* @return The message
|
||||
*/
|
||||
public static String decodeMessage(PublicKey fromKey, PublicKey toKey, byte[] msg, byte[] nonce) {
|
||||
|
||||
byte[] secret = fromKey.getKey().getPubKeyPoint().multiply(toKey.getKey().getPrivKey()).normalize().getXCoord().getEncoded();
|
||||
byte[] finalKey = new byte[secret.length + nonce.length];
|
||||
System.arraycopy(secret, 0, finalKey, 0, secret.length);
|
||||
System.arraycopy(nonce, 0, finalKey, secret.length, nonce.length);
|
||||
|
||||
byte[] msgFinal = Util.decryptAES(msg, finalKey);
|
||||
byte[] decodedMsg = new byte[msgFinal.length - 4];
|
||||
//TODO verify checksum for integrity
|
||||
System.arraycopy(msgFinal, 4, decodedMsg, 0, decodedMsg.length);
|
||||
return new String(decodedMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the string coreesponding a encode memo
|
||||
*
|
||||
* @param fromKey The soruce key, need to have public key only
|
||||
* @param toKey The destination key, need to have private key access
|
||||
* @param message The message to be decoded
|
||||
* @param nonce The nonce used in the decoded message
|
||||
* @return The message
|
||||
*/
|
||||
public static String decodeMessage(PublicKey fromKey, PublicKey toKey, String message, String nonce) {
|
||||
byte[] msg = new BigInteger(message, 16).toByteArray();
|
||||
if (msg[0] == 0) {
|
||||
byte[] temp = new byte[msg.length - 1];
|
||||
System.arraycopy(msg, 1, temp, 0, temp.length);
|
||||
msg = temp;
|
||||
}
|
||||
byte[] firstNonce = new BigInteger(nonce, 10).toByteArray();
|
||||
byte[] nonceByte = new byte[8];
|
||||
System.arraycopy(firstNonce, firstNonce.length - 8, nonceByte, 0, nonceByte.length);
|
||||
return decodeMessage(fromKey, toKey, msg, nonceByte);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toJsonString() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement toJsonObject() {
|
||||
if ((this.from == null) || (this.to == null) || (this.nonce == null) || (this.message == null)) {
|
||||
return null;
|
||||
}
|
||||
JsonObject memoObject = new JsonObject();
|
||||
memoObject.addProperty(KEY_FROM, this.from.getAddress());
|
||||
memoObject.addProperty(KEY_TO, this.to.getAddress());
|
||||
memoObject.addProperty(KEY_NONCE, new BigInteger(1, this.nonce).toString(10));
|
||||
memoObject.addProperty(KEY_MESSAGE, new BigInteger(1, this.message).toString(16));
|
||||
return memoObject;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package de.bitsharesmunich.graphenej.objects;
|
||||
|
||||
import de.bitsharesmunich.graphenej.PublicKey;
|
||||
|
||||
/**
|
||||
* Class to build a Memo Object
|
||||
* @author henry 10/12/2016
|
||||
*/
|
||||
public class MemoBuilder {
|
||||
|
||||
private PublicKey fromKey;
|
||||
private PublicKey toKey;
|
||||
private String message;
|
||||
private long nonce = 0;
|
||||
|
||||
/**
|
||||
* Empty Constructor
|
||||
*/
|
||||
public MemoBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the key of the Source, needs to have a private Key access
|
||||
* @param fromKey The Public Key of the sender
|
||||
* @return The MemoBuilder
|
||||
*/
|
||||
public MemoBuilder setFromKey(PublicKey fromKey) {
|
||||
this.fromKey = fromKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the key of the destination, only need the public key.
|
||||
* @param toKey The Public Key of the receiver
|
||||
* @return The MemoBuilder
|
||||
*/
|
||||
public MemoBuilder setToKey(PublicKey toKey) {
|
||||
this.toKey = toKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the message to be send
|
||||
* @param message The message as a String
|
||||
* @return The MemoBuilder
|
||||
*/
|
||||
public MemoBuilder setMessage(String message) {
|
||||
this.message = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* (Optional) Sets a custom nonce
|
||||
* @param nonce The custom nonce
|
||||
* @return The MemoBuilder
|
||||
*/
|
||||
public MemoBuilder setNone(Long nonce) {
|
||||
this.nonce = nonce;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Biulds the memo object
|
||||
* @return The Memo object
|
||||
*/
|
||||
public Memo build() {
|
||||
//Todo unencode key
|
||||
if (nonce == 0) {
|
||||
return Memo.encodeMessage(fromKey, toKey, message.getBytes());
|
||||
}
|
||||
return Memo.encodeMessage(fromKey, toKey, message.getBytes(), nonce);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.luminiasoft.bitshares.test;
|
||||
package de.bitsharesmunich.graphenej.test;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Neo Visionaries Inc.
|
Loading…
Reference in a new issue