Merge branch 'feat_bin_backup_compatibility'
This commit is contained in:
commit
1cc56ef846
11 changed files with 616 additions and 34 deletions
|
@ -1,8 +1,6 @@
|
||||||
package de.bitsharesmunich.graphenej;
|
package de.bitsharesmunich.graphenej;
|
||||||
|
|
||||||
import de.bitsharesmunich.graphenej.crypto.AndroidRandomSource;
|
import de.bitsharesmunich.graphenej.crypto.SecureRandomGenerator;
|
||||||
import de.bitsharesmunich.graphenej.crypto.Random;
|
|
||||||
import de.bitsharesmunich.graphenej.crypto.SecureRandomStrengthener;
|
|
||||||
import org.bitcoinj.core.DumpedPrivateKey;
|
import org.bitcoinj.core.DumpedPrivateKey;
|
||||||
import org.bitcoinj.core.ECKey;
|
import org.bitcoinj.core.ECKey;
|
||||||
import org.bitcoinj.core.NetworkParameters;
|
import org.bitcoinj.core.NetworkParameters;
|
||||||
|
@ -44,7 +42,7 @@ public class BrainKey {
|
||||||
String[] wordArray = words.split(",");
|
String[] wordArray = words.split(",");
|
||||||
ArrayList<String> suggestedBrainKey = new ArrayList<String>();
|
ArrayList<String> suggestedBrainKey = new ArrayList<String>();
|
||||||
assert (wordArray.length == DICT_WORD_COUNT);
|
assert (wordArray.length == DICT_WORD_COUNT);
|
||||||
SecureRandom secureRandom = Random.getSecureRandom();
|
SecureRandom secureRandom = SecureRandomGenerator.getSecureRandom();
|
||||||
int index;
|
int index;
|
||||||
for (int i = 0; i < BRAINKEY_WORD_COUNT; i++) {
|
for (int i = 0; i < BRAINKEY_WORD_COUNT; i++) {
|
||||||
index = secureRandom.nextInt(DICT_WORD_COUNT - 1);
|
index = secureRandom.nextInt(DICT_WORD_COUNT - 1);
|
||||||
|
|
|
@ -1,24 +1,112 @@
|
||||||
package de.bitsharesmunich.graphenej;
|
package de.bitsharesmunich.graphenej;
|
||||||
|
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import de.bitsharesmunich.graphenej.crypto.SecureRandomStrengthener;
|
import de.bitsharesmunich.graphenej.crypto.SecureRandomStrengthener;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
import de.bitsharesmunich.graphenej.models.backup.WalletBackup;
|
||||||
import org.bitcoinj.core.ECKey;
|
import org.bitcoinj.core.ECKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to manage the Bin Files
|
* Class to manage the backup files
|
||||||
*
|
*
|
||||||
* @author Henry Varona
|
* @author Henry Varona
|
||||||
|
* @author Nelson R. Pérez
|
||||||
*/
|
*/
|
||||||
public abstract class FileBin {
|
public abstract class FileBin {
|
||||||
|
|
||||||
|
public static final int PUBLIC_KEY_LENGTH = 33;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method that receives as input both the bytes from the bin backup and the string used to encrypt the
|
||||||
|
* data contained in it.
|
||||||
|
*
|
||||||
|
* The procedure of deserializing the wallet backup involves first decrypting the data and then decompressing
|
||||||
|
* it using the LZMA algorithm. Once this two steps are performed, the resulting byte sequence represents
|
||||||
|
* a JSON-formatted object with one or more wallet and private keys information.
|
||||||
|
*
|
||||||
|
* @param input: Input bytes
|
||||||
|
* @param password: Password used to derive the encryption key
|
||||||
|
* @return: An instance of the WalletBackup class.
|
||||||
|
*/
|
||||||
|
public static WalletBackup deserializeWalletBackup(byte[] input, String password){
|
||||||
|
try{
|
||||||
|
byte[] publicKey = new byte[PUBLIC_KEY_LENGTH];
|
||||||
|
byte[] rawDataEncripted = new byte[input.length - PUBLIC_KEY_LENGTH];
|
||||||
|
|
||||||
|
System.arraycopy(input, 0, publicKey, 0, PUBLIC_KEY_LENGTH);
|
||||||
|
System.arraycopy(input, PUBLIC_KEY_LENGTH, rawDataEncripted, 0, rawDataEncripted.length);
|
||||||
|
|
||||||
|
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||||
|
|
||||||
|
ECKey randomECKey = ECKey.fromPublicOnly(publicKey);
|
||||||
|
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[] decryptedData = Util.decryptAES(rawDataEncripted, Util.bytesToHex(finalKey).getBytes());
|
||||||
|
|
||||||
|
byte[] checksum = new byte[4];
|
||||||
|
System.arraycopy(decryptedData, 0, checksum, 0, 4);
|
||||||
|
byte[] compressedData = new byte[decryptedData.length - 4];
|
||||||
|
System.arraycopy(decryptedData, 4, compressedData, 0, compressedData.length);
|
||||||
|
|
||||||
|
byte[] decompressedData = Util.decompress(compressedData, Util.LZMA);
|
||||||
|
String walletString = new String(decompressedData, "UTF-8");
|
||||||
|
System.out.println("Wallet str: "+walletString);
|
||||||
|
return new GsonBuilder().create().fromJson(walletString, WalletBackup.class);
|
||||||
|
}catch(NoSuchAlgorithmException e){
|
||||||
|
System.out.println("NoSuchAlgorithmException. Msg: "+e.getMessage());
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
System.out.println("UnsupportedEncodingException. Msg: "+e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] serializeWalletBackup(WalletBackup walletBackup, String password){
|
||||||
|
SecureRandomStrengthener randomStrengthener = SecureRandomStrengthener.getInstance();
|
||||||
|
//randomStrengthener.addEntropySource(new AndroidRandomSource());
|
||||||
|
SecureRandom secureRandom = randomStrengthener.generateAndSeedRandomNumberGenerator();
|
||||||
|
|
||||||
|
try{
|
||||||
|
String json = new GsonBuilder().create().toJson(walletBackup, WalletBackup.class);
|
||||||
|
byte[] compressed = Util.compress(json.getBytes(), Util.LZMA);
|
||||||
|
System.out.println("json: "+json);
|
||||||
|
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||||
|
byte[] checksum = md.digest(compressed);
|
||||||
|
byte[] checksummed = new byte[compressed.length + 4];
|
||||||
|
|
||||||
|
System.arraycopy(checksum, 0, checksummed, 0, 4);
|
||||||
|
System.arraycopy(compressed, 0, checksummed, 4, compressed.length);
|
||||||
|
byte[] randomKey = new byte[32];
|
||||||
|
secureRandom.nextBytes(randomKey);
|
||||||
|
ECKey randomECKey = ECKey.fromPrivate(md.digest(randomKey));
|
||||||
|
byte[] randPubKey = randomECKey.getPubKey();
|
||||||
|
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);
|
||||||
|
checksummed = Util.encryptAES(checksummed, Util.byteToString(finalKey).getBytes());
|
||||||
|
|
||||||
|
byte[] finalPayload = new byte[checksummed.length + randPubKey.length];
|
||||||
|
System.arraycopy(randPubKey, 0, finalPayload, 0, randPubKey.length);
|
||||||
|
System.arraycopy(checksummed, 0, finalPayload, randPubKey.length, checksummed.length);
|
||||||
|
|
||||||
|
return finalPayload;
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
System.out.println("NoSuchAlgorithmException. Msg: "+e.getMessage());
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
System.out.println("UnsupportedEncodingException. Msg: "+e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to get the brainkey fron an input of bytes
|
* Method to get the brainkey fron an input of bytes
|
||||||
*
|
*
|
||||||
|
@ -26,7 +114,11 @@ public abstract class FileBin {
|
||||||
* @param password the pin code
|
* @param password the pin code
|
||||||
* @return the brainkey file, or null if the file or the password are
|
* @return the brainkey file, or null if the file or the password are
|
||||||
* incorrect
|
* incorrect
|
||||||
|
*
|
||||||
|
* @deprecated use {@link #deserializeWalletBackup(byte[], String)} instead, as it is a more complete method
|
||||||
|
* that will return a WalletBackup class instance.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static String getBrainkeyFromByte(byte[] input, String password) {
|
public static String getBrainkeyFromByte(byte[] input, String password) {
|
||||||
try {
|
try {
|
||||||
byte[] publicKey = new byte[33];
|
byte[] publicKey = new byte[33];
|
||||||
|
@ -42,12 +134,12 @@ public abstract class FileBin {
|
||||||
MessageDigest md1 = MessageDigest.getInstance("SHA-512");
|
MessageDigest md1 = MessageDigest.getInstance("SHA-512");
|
||||||
finalKey = md1.digest(finalKey);
|
finalKey = md1.digest(finalKey);
|
||||||
byte[] rawData = Util.decryptAES(rawDataEncripted, Util.byteToString(finalKey).getBytes());
|
byte[] rawData = Util.decryptAES(rawDataEncripted, Util.byteToString(finalKey).getBytes());
|
||||||
|
|
||||||
byte[] checksum = new byte[4];
|
byte[] checksum = new byte[4];
|
||||||
System.arraycopy(rawData, 0, checksum, 0, 4);
|
System.arraycopy(rawData, 0, checksum, 0, 4);
|
||||||
byte[] compressedData = new byte[rawData.length - 4];
|
byte[] compressedData = new byte[rawData.length - 4];
|
||||||
System.arraycopy(rawData, 4, compressedData, 0, compressedData.length);
|
System.arraycopy(rawData, 4, compressedData, 0, compressedData.length);
|
||||||
|
|
||||||
byte[] wallet_object_bytes = Util.decompress(compressedData, Util.XZ);
|
byte[] wallet_object_bytes = Util.decompress(compressedData, Util.XZ);
|
||||||
String wallet_string = new String(wallet_object_bytes, "UTF-8");
|
String wallet_string = new String(wallet_object_bytes, "UTF-8");
|
||||||
JsonObject wallet = new JsonParser().parse(wallet_string).getAsJsonObject();
|
JsonObject wallet = new JsonParser().parse(wallet_string).getAsJsonObject();
|
||||||
|
@ -87,7 +179,10 @@ public abstract class FileBin {
|
||||||
* @param password The pin code
|
* @param password The pin code
|
||||||
* @param accountName The Account Name
|
* @param accountName The Account Name
|
||||||
* @return The array byte of the file, or null if an error happens
|
* @return The array byte of the file, or null if an error happens
|
||||||
|
*
|
||||||
|
* @deprecated use {@link #serializeWalletBackup(WalletBackup, String)} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static byte[] getBytesFromBrainKey(String BrainKey, String password, String accountName) {
|
public static byte[] getBytesFromBrainKey(String BrainKey, String password, String accountName) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -138,6 +233,4 @@ public abstract class FileBin {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,12 @@ public class Main {
|
||||||
|
|
||||||
public static final String WIF = "5KMzB2GqGhnh7ufhgddmz1eKPHS72uTLeL9hHjSvPb1UywWknF5";
|
public static final String WIF = "5KMzB2GqGhnh7ufhgddmz1eKPHS72uTLeL9hHjSvPb1UywWknF5";
|
||||||
|
|
||||||
|
public static final String BILTHON_83_PASSWORD = System.getenv("BILTHON_83_PASSWORD");
|
||||||
|
|
||||||
|
public static final String BILTHON_25_PASSWORD = System.getenv("BILTHON_25_PASSWORD");
|
||||||
|
|
||||||
|
public static final String BILTHON_11_BRAIN_KEY = System.getenv("BILTHON_11_BRAIN_KEY");
|
||||||
|
|
||||||
// Static block information used for transaction serialization tests
|
// Static block information used for transaction serialization tests
|
||||||
public static int REF_BLOCK_NUM = 56204;
|
public static int REF_BLOCK_NUM = 56204;
|
||||||
public static int REF_BLOCK_PREFIX = 1614747814;
|
public static int REF_BLOCK_PREFIX = 1614747814;
|
||||||
|
@ -60,7 +66,11 @@ public class Main {
|
||||||
// test.testAccountUpdateOperationBroadcast();
|
// test.testAccountUpdateOperationBroadcast();
|
||||||
// test.testCreateBinFile();
|
// test.testCreateBinFile();
|
||||||
// test.testImportBinFile();
|
// test.testImportBinFile();
|
||||||
// test.testLookupAccounts();
|
test.testExportBinFile();
|
||||||
|
// test.testLzmaCompression();
|
||||||
|
// test.testLzmaDecompression();
|
||||||
|
// test.testSimpleDecompression();
|
||||||
|
// test.testLookupAccounts();
|
||||||
// test.testLookupAccounts();
|
// test.testLookupAccounts();
|
||||||
// test.testDecodeMemo();
|
// test.testDecodeMemo();
|
||||||
// test.testGetRelativeAccountHistory();
|
// test.testGetRelativeAccountHistory();
|
||||||
|
@ -74,6 +84,6 @@ public class Main {
|
||||||
// test.testGetMarketHistory();
|
// test.testGetMarketHistory();
|
||||||
// test.testGetAccountBalances();
|
// test.testGetAccountBalances();
|
||||||
// test.testGetAssetHoldersCount();
|
// test.testGetAssetHoldersCount();
|
||||||
test.testSubscription(null);
|
// test.testSubscription(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
package de.bitsharesmunich.graphenej;
|
package de.bitsharesmunich.graphenej;
|
||||||
|
|
||||||
|
import com.google.common.primitives.Bytes;
|
||||||
import de.bitsharesmunich.graphenej.interfaces.SubscriptionListener;
|
import de.bitsharesmunich.graphenej.interfaces.SubscriptionListener;
|
||||||
import de.bitsharesmunich.graphenej.models.*;
|
import de.bitsharesmunich.graphenej.models.*;
|
||||||
|
import de.bitsharesmunich.graphenej.models.backup.LinkedAccount;
|
||||||
|
import de.bitsharesmunich.graphenej.models.backup.PrivateKeyBackup;
|
||||||
|
import de.bitsharesmunich.graphenej.models.backup.Wallet;
|
||||||
|
import de.bitsharesmunich.graphenej.models.backup.WalletBackup;
|
||||||
import de.bitsharesmunich.graphenej.objects.Memo;
|
import de.bitsharesmunich.graphenej.objects.Memo;
|
||||||
import com.google.common.primitives.UnsignedLong;
|
import com.google.common.primitives.UnsignedLong;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
@ -16,6 +21,7 @@ import com.neovisionaries.ws.client.*;
|
||||||
import de.bitsharesmunich.graphenej.api.*;
|
import de.bitsharesmunich.graphenej.api.*;
|
||||||
import org.bitcoinj.core.*;
|
import org.bitcoinj.core.*;
|
||||||
import org.spongycastle.crypto.digests.RIPEMD160Digest;
|
import org.spongycastle.crypto.digests.RIPEMD160Digest;
|
||||||
|
import org.tukaani.xz.*;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
@ -23,6 +29,7 @@ import java.lang.reflect.Type;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -632,13 +639,142 @@ public class Test {
|
||||||
public void testImportBinFile() {
|
public void testImportBinFile() {
|
||||||
try {
|
try {
|
||||||
String current = new File(".").getCanonicalPath();
|
String current = new File(".").getCanonicalPath();
|
||||||
File file = new File(current + "/src/main/java/de/bitsharesmunich/graphenej/bts_bilthon_20161218.bin");
|
File file = new File(current + "/src/main/java/de/bitsharesmunich/graphenej/bts_bilthon-25_20170214.bin");
|
||||||
Path path = Paths.get(file.getAbsolutePath());
|
Path path = Paths.get(file.getAbsolutePath());
|
||||||
byte[] data = Files.readAllBytes(path);
|
byte[] data = Files.readAllBytes(path);
|
||||||
|
byte[] publicKey = new byte[FileBin.PUBLIC_KEY_LENGTH];
|
||||||
|
System.arraycopy(data, 0, publicKey, 0, FileBin.PUBLIC_KEY_LENGTH);
|
||||||
|
|
||||||
System.out.println(FileBin.getBrainkeyFromByte(data, "123456"));
|
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||||
|
ECKey randomECKey = ECKey.fromPublicOnly(publicKey);
|
||||||
|
byte[] finalKey = randomECKey.getPubKeyPoint().multiply(ECKey.fromPrivate(md.digest(Main.BILTHON_25_PASSWORD.getBytes("UTF-8"))).getPrivKey()).normalize().getXCoord().getEncoded();
|
||||||
|
|
||||||
|
WalletBackup walletBackup = FileBin.deserializeWalletBackup(data, Main.BILTHON_25_PASSWORD);
|
||||||
|
System.out.println("Number of wallets: "+walletBackup.getWalletCount());
|
||||||
|
String brainKeyString = walletBackup.getWallet(0).decryptBrainKey(Main.BILTHON_25_PASSWORD);
|
||||||
|
System.out.println("Brain key: "+brainKeyString);
|
||||||
|
BrainKey brainKey = new BrainKey(brainKeyString, 1);
|
||||||
|
byte[] privateKey = brainKey.getPrivateKey().getPrivKeyBytes();
|
||||||
|
System.out.println("Brainkey derived private....: " + Util.bytesToHex(privateKey));
|
||||||
|
|
||||||
|
byte[] privateKey2 = walletBackup.getPrivateKeyBackup(0).decryptPrivateKey(walletBackup.getWallet(0).getEncryptionKey(Main.BILTHON_25_PASSWORD));
|
||||||
|
System.out.println("Encrypted private key.......: "+Util.bytesToHex(privateKey2));
|
||||||
|
|
||||||
|
Address addr1 = new Address(ECKey.fromPublicOnly(ECKey.fromPrivate(privateKey).getPubKey()));
|
||||||
|
Address addr2 = new Address(ECKey.fromPublicOnly(ECKey.fromPrivate(privateKey2).getPubKey()));
|
||||||
|
Address addr3 = new Address(ECKey.fromPublicOnly(publicKey));
|
||||||
|
System.out.println("Addr1: "+addr1.toString());
|
||||||
|
System.out.println("Addr2: "+addr2.toString());
|
||||||
|
System.out.println("Addr3: "+addr3.toString());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("IOException while trying to open bin file. Msg: "+e.getMessage());
|
System.out.println("IOException while trying to open bin file. Msg: "+e.getMessage());
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
System.out.println("NoSuchAlgorithmException while trying to open bin file. Msg: "+e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testExportBinFile(){
|
||||||
|
String password = "123456";
|
||||||
|
BrainKey brainKey = new BrainKey(Main.BILTHON_11_BRAIN_KEY, 0);
|
||||||
|
Wallet wallet = new Wallet("bilthon-11", brainKey.getBrainKey(), brainKey.getSequenceNumber(), Chains.BITSHARES.CHAIN_ID, password);
|
||||||
|
byte[] privateKey = brainKey.getPrivateKey().getPrivKeyBytes();
|
||||||
|
PrivateKeyBackup privateKeyBackup = new PrivateKeyBackup(privateKey, brainKey.getSequenceNumber(), 1, wallet.getEncryptionKey(password));
|
||||||
|
LinkedAccount linkedAccount = new LinkedAccount("bilthon-11", Chains.BITSHARES.CHAIN_ID);
|
||||||
|
|
||||||
|
ArrayList<Wallet> walletList = new ArrayList<>();
|
||||||
|
walletList.add(wallet);
|
||||||
|
ArrayList<PrivateKeyBackup> keyList = new ArrayList<>();
|
||||||
|
keyList.add(privateKeyBackup);
|
||||||
|
ArrayList<LinkedAccount> linkedAccounts = new ArrayList<>();
|
||||||
|
linkedAccounts.add(linkedAccount);
|
||||||
|
WalletBackup backup = new WalletBackup(walletList, keyList, linkedAccounts);
|
||||||
|
byte[] serialized = FileBin.serializeWalletBackup(backup, password);
|
||||||
|
System.out.println("Serialized: "+Util.bytesToHex(serialized));
|
||||||
|
try {
|
||||||
|
String current = new File(".").getCanonicalPath();
|
||||||
|
String fullPath = current + "/scwall_bithon_11.bin";
|
||||||
|
System.out.println("Full path: "+fullPath);
|
||||||
|
File file = new File(fullPath);
|
||||||
|
FileOutputStream out = new FileOutputStream(file);
|
||||||
|
out.write(serialized);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLzmaCompression(){
|
||||||
|
String data = "A long time ago in a galaxy far, far away...";
|
||||||
|
byte[] compressed = Util.compress(data.getBytes(), Util.LZMA);
|
||||||
|
|
||||||
|
try {
|
||||||
|
String current = new File(".").getCanonicalPath();
|
||||||
|
File file = new File(current + "/src/main/java/de/bitsharesmunich/graphenej/java_compressed_1.4.lzma");
|
||||||
|
FileOutputStream out = new FileOutputStream(file);
|
||||||
|
System.out.println("Writing "+compressed.length+" bytes");
|
||||||
|
out.write(compressed);
|
||||||
|
out.close();
|
||||||
|
}catch(IOException e){
|
||||||
|
System.out.println("IOException. Msg: "+e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSimpleDecompression(){
|
||||||
|
try{
|
||||||
|
String current = new File(".").getCanonicalPath();
|
||||||
|
// File file = new File(current + "/src/main/java/de/bitsharesmunich/graphenej/node_compressed_1.2.lzma");
|
||||||
|
File file = new File(current + "/src/main/java/de/bitsharesmunich/graphenej/decrypted.bin");
|
||||||
|
Path path = Paths.get(file.getAbsolutePath());
|
||||||
|
byte[] data = Files.readAllBytes(path);
|
||||||
|
byte[] decompressed = Util.decompress(data, Util.LZMA);
|
||||||
|
System.out.println("Decompressed.......: "+Util.bytesToHex(decompressed));
|
||||||
|
String message = new String(decompressed);
|
||||||
|
System.out.println("Decompressed msg...: "+message);
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("IOException. Msg: "+e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLzmaDecompression(){
|
||||||
|
try {
|
||||||
|
String current = new File(".").getCanonicalPath();
|
||||||
|
File file = new File(current + "/src/main/java/de/bitsharesmunich/graphenej/java_compressed_1.4.lzma");
|
||||||
|
Path path = Paths.get(file.getAbsolutePath());
|
||||||
|
byte[] data = Files.readAllBytes(path);
|
||||||
|
System.out.println("Compressed bytes...: " + Util.bytesToHex(data));
|
||||||
|
|
||||||
|
InputStream in = null;
|
||||||
|
byte[] decompressed;
|
||||||
|
byte[] properties = Arrays.copyOfRange(data, 0, 1);
|
||||||
|
byte[] dictSize = Arrays.copyOfRange(data, 1, 5);
|
||||||
|
byte[] uncompressedSize = Arrays.copyOfRange(data, 5, 13);
|
||||||
|
byte[] header = Bytes.concat(properties, Util.revertBytes(dictSize), Util.revertBytes(uncompressedSize));
|
||||||
|
byte[] payload = Arrays.copyOfRange(data, 13, data.length);
|
||||||
|
System.out.println("Header.............: "+Util.bytesToHex(header));
|
||||||
|
System.out.println("Payload............: "+Util.bytesToHex(payload));
|
||||||
|
ByteArrayInputStream input = new ByteArrayInputStream(Bytes.concat(header, payload));
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream(2 * 2048);
|
||||||
|
// in = new LZMAInputStream(input, 44, (byte) 0x5d, 65536);
|
||||||
|
in = new LZMAInputStream(input);
|
||||||
|
int size;
|
||||||
|
try{
|
||||||
|
while ((size = in.read()) != -1) {
|
||||||
|
output.write(size);
|
||||||
|
}
|
||||||
|
}catch(IOException e){
|
||||||
|
System.out.println("IOException detected. End of stream reached. Msg: "+e.getMessage());
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
decompressed = output.toByteArray();
|
||||||
|
|
||||||
|
System.out.println("Decompressed bytes.: " + Util.bytesToHex(decompressed));
|
||||||
|
String decompressedString = new String(decompressed);
|
||||||
|
System.out.println("Decompressed: " + decompressedString);
|
||||||
|
} catch (CorruptedInputException e) {
|
||||||
|
System.out.println("CorruptedInputException. Msg: " + e.getMessage());
|
||||||
|
} catch (UnsupportedOptionsException e){
|
||||||
|
System.out.println("UnsupportedOptionsException. Msg: "+e.getMessage());
|
||||||
|
} catch(IOException e){
|
||||||
|
System.out.println("IOException. Msg: "+e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
public static final String KEY_EXTENSIONS = "extensions";
|
public static final String KEY_EXTENSIONS = "extensions";
|
||||||
public static final String KEY_REF_BLOCK_NUM = "ref_block_num";
|
public static final String KEY_REF_BLOCK_NUM = "ref_block_num";
|
||||||
public static final String KEY_REF_BLOCK_PREFIX = "ref_block_prefix";
|
public static final String KEY_REF_BLOCK_PREFIX = "ref_block_prefix";
|
||||||
public static final String TIME_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
|
|
||||||
|
|
||||||
private ECKey privateKey;
|
private ECKey privateKey;
|
||||||
private BlockData blockData;
|
private BlockData blockData;
|
||||||
|
@ -205,7 +204,7 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
|
|
||||||
// Formatting expiration time
|
// Formatting expiration time
|
||||||
Date expirationTime = new Date(blockData.getExpiration() * 1000);
|
Date expirationTime = new Date(blockData.getExpiration() * 1000);
|
||||||
SimpleDateFormat dateFormat = new SimpleDateFormat(TIME_DATE_FORMAT);
|
SimpleDateFormat dateFormat = new SimpleDateFormat(Util.TIME_DATE_FORMAT);
|
||||||
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
|
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
|
|
||||||
// Adding expiration
|
// Adding expiration
|
||||||
|
@ -260,7 +259,7 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
int refBlockNum = jsonObject.get(KEY_REF_BLOCK_NUM).getAsInt();
|
int refBlockNum = jsonObject.get(KEY_REF_BLOCK_NUM).getAsInt();
|
||||||
long refBlockPrefix = jsonObject.get(KEY_REF_BLOCK_PREFIX).getAsLong();
|
long refBlockPrefix = jsonObject.get(KEY_REF_BLOCK_PREFIX).getAsLong();
|
||||||
String expiration = jsonObject.get(KEY_EXPIRATION).getAsString();
|
String expiration = jsonObject.get(KEY_EXPIRATION).getAsString();
|
||||||
SimpleDateFormat dateFormat = new SimpleDateFormat(TIME_DATE_FORMAT);
|
SimpleDateFormat dateFormat = new SimpleDateFormat(Util.TIME_DATE_FORMAT);
|
||||||
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
|
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
Date expirationDate = dateFormat.parse(expiration, new ParsePosition(0));
|
Date expirationDate = dateFormat.parse(expiration, new ParsePosition(0));
|
||||||
BlockData blockData = new BlockData(refBlockNum, refBlockPrefix, expirationDate.getTime());
|
BlockData blockData = new BlockData(refBlockNum, refBlockPrefix, expirationDate.getTime());
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
package de.bitsharesmunich.graphenej;
|
package de.bitsharesmunich.graphenej;
|
||||||
|
|
||||||
import org.tukaani.xz.FinishableOutputStream;
|
import com.google.common.primitives.Bytes;
|
||||||
import org.tukaani.xz.LZMA2Options;
|
import org.tukaani.xz.*;
|
||||||
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.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -33,6 +30,17 @@ public class Util {
|
||||||
public static final int LZMA = 0;
|
public static final int LZMA = 0;
|
||||||
public static final int XZ = 1;
|
public static final int XZ = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES encryption key length in bytes
|
||||||
|
*/
|
||||||
|
public static final int KEY_LENGTH = 32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time format used across the platform
|
||||||
|
*/
|
||||||
|
public static final String TIME_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an hexadecimal string to its corresponding byte[] value.
|
* Converts an hexadecimal string to its corresponding byte[] value.
|
||||||
* @param s: String with hexadecimal numbers representing a byte array.
|
* @param s: String with hexadecimal numbers representing a byte array.
|
||||||
|
@ -94,10 +102,10 @@ public class Util {
|
||||||
}else if(which == Util.XZ){
|
}else if(which == Util.XZ){
|
||||||
out = new XZOutputStream(output, options);
|
out = new XZOutputStream(output, options);
|
||||||
}
|
}
|
||||||
byte[] buf = new byte[inputBytes.length];
|
byte[] inputBuffer = new byte[inputBytes.length];
|
||||||
int size;
|
int size;
|
||||||
while ((size = input.read(buf)) != -1) {
|
while ((size = input.read(inputBuffer)) != -1) {
|
||||||
out.write(buf, 0, size);
|
out.write(inputBuffer, 0, size);
|
||||||
}
|
}
|
||||||
out.finish();
|
out.finish();
|
||||||
return output.toByteArray();
|
return output.toByteArray();
|
||||||
|
@ -124,26 +132,51 @@ public class Util {
|
||||||
public static byte[] decompress(byte[] inputBytes, int which) {
|
public static byte[] decompress(byte[] inputBytes, int which) {
|
||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
try {
|
try {
|
||||||
|
System.out.println("Bytes: "+Util.bytesToHex(inputBytes));
|
||||||
ByteArrayInputStream input = new ByteArrayInputStream(inputBytes);
|
ByteArrayInputStream input = new ByteArrayInputStream(inputBytes);
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream(2048);
|
ByteArrayOutputStream output = new ByteArrayOutputStream(16*2048);
|
||||||
if(which == XZ) {
|
if(which == XZ) {
|
||||||
in = new XZInputStream(input);
|
in = new XZInputStream(input);
|
||||||
}else if(which == LZMA){
|
}else if(which == LZMA){
|
||||||
in = new LZMAInputStream(input);
|
in = new LZMAInputStream(input);
|
||||||
}
|
}
|
||||||
int size;
|
int size;
|
||||||
while ((size = in.read()) != -1) {
|
try{
|
||||||
output.write(size);
|
while ((size = in.read()) != -1) {
|
||||||
|
output.write(size);
|
||||||
|
}
|
||||||
|
}catch(CorruptedInputException e){
|
||||||
|
// Taking property byte
|
||||||
|
byte[] properties = Arrays.copyOfRange(inputBytes, 0, 1);
|
||||||
|
// Taking dict size bytes
|
||||||
|
byte[] dictSize = Arrays.copyOfRange(inputBytes, 1, 5);
|
||||||
|
// Taking uncompressed size bytes
|
||||||
|
byte[] uncompressedSize = Arrays.copyOfRange(inputBytes, 5, 13);
|
||||||
|
|
||||||
|
// Reversing bytes in header
|
||||||
|
byte[] header = Bytes.concat(properties, Util.revertBytes(dictSize), Util.revertBytes(uncompressedSize));
|
||||||
|
byte[] payload = Arrays.copyOfRange(inputBytes, 13, inputBytes.length);
|
||||||
|
|
||||||
|
// Trying again
|
||||||
|
input = new ByteArrayInputStream(Bytes.concat(header, payload));
|
||||||
|
output = new ByteArrayOutputStream(2048);
|
||||||
|
if(which == XZ) {
|
||||||
|
in = new XZInputStream(input);
|
||||||
|
}else if(which == LZMA){
|
||||||
|
in = new LZMAInputStream(input);
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
while ((size = in.read()) != -1) {
|
||||||
|
output.write(size);
|
||||||
|
}
|
||||||
|
}catch(CorruptedInputException ex){
|
||||||
|
System.out.println("CorruptedInputException. Msg: "+ex.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
in.close();
|
in.close();
|
||||||
return output.toByteArray();
|
return output.toByteArray();
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
in.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex); }
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -177,6 +210,14 @@ public class Util {
|
||||||
return ByteBuffer.allocate(Long.SIZE / 8).putLong(Long.reverseBytes(input)).array();
|
return ByteBuffer.allocate(Long.SIZE / 8).putLong(Long.reverseBytes(input)).array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] revertBytes(byte[] array){
|
||||||
|
byte[] reverted = new byte[array.length];
|
||||||
|
for(int i = 0; i < reverted.length; i++){
|
||||||
|
reverted[i] = array[array.length - i - 1];
|
||||||
|
}
|
||||||
|
return reverted;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to encrypt a message with AES
|
* Function to encrypt a message with AES
|
||||||
* @param input data to encrypt
|
* @param input data to encrypt
|
||||||
|
|
|
@ -5,7 +5,7 @@ import java.security.SecureRandom;
|
||||||
/**
|
/**
|
||||||
* Created by nelson on 12/20/16.
|
* Created by nelson on 12/20/16.
|
||||||
*/
|
*/
|
||||||
public class Random {
|
public class SecureRandomGenerator {
|
||||||
|
|
||||||
public static SecureRandom getSecureRandom(){
|
public static SecureRandom getSecureRandom(){
|
||||||
SecureRandomStrengthener randomStrengthener = SecureRandomStrengthener.getInstance();
|
SecureRandomStrengthener randomStrengthener = SecureRandomStrengthener.getInstance();
|
|
@ -0,0 +1,31 @@
|
||||||
|
package de.bitsharesmunich.graphenej.models.backup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used to represent an entry in the "linked_accounts" field of the JSON-formatted backup file.
|
||||||
|
* Created by nelson on 2/15/17.
|
||||||
|
*/
|
||||||
|
public class LinkedAccount {
|
||||||
|
private String name;
|
||||||
|
private String chainId;
|
||||||
|
|
||||||
|
public LinkedAccount(String name, String chainId){
|
||||||
|
this.name = name;
|
||||||
|
this.chainId = chainId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChainId() {
|
||||||
|
return chainId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChainId(String chainId) {
|
||||||
|
this.chainId = chainId;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package de.bitsharesmunich.graphenej.models.backup;
|
||||||
|
|
||||||
|
import de.bitsharesmunich.graphenej.Address;
|
||||||
|
import de.bitsharesmunich.graphenej.Util;
|
||||||
|
import org.bitcoinj.core.ECKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used to represent an entry in the "private_keys" array field in the JSON-formatted
|
||||||
|
* backup file.
|
||||||
|
*
|
||||||
|
* Created by nelson on 2/14/17.
|
||||||
|
*/
|
||||||
|
public class PrivateKeyBackup {
|
||||||
|
public String encrypted_key;
|
||||||
|
public String pubkey;
|
||||||
|
public int brainkey_sequence;
|
||||||
|
public int id;
|
||||||
|
|
||||||
|
public PrivateKeyBackup(byte[] privateKey, int brainkeySequence, int id, byte[] encryptionKey){
|
||||||
|
this.encrypted_key = encryptPrivateKey(privateKey, encryptionKey);
|
||||||
|
this.brainkey_sequence = brainkeySequence;
|
||||||
|
this.id = id;
|
||||||
|
deriveAddress(privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] decryptPrivateKey(byte[] encryptionKey){
|
||||||
|
return Util.decryptAES(Util.hexToBytes(encrypted_key), encryptionKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String encryptPrivateKey(byte[] data, byte[] encryptionKey){
|
||||||
|
return Util.bytesToHex(Util.encryptAES(data, encryptionKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deriveAddress(byte[] privateKey){
|
||||||
|
Address address = new Address(ECKey.fromPublicOnly(ECKey.fromPrivate(privateKey).getPubKey()));
|
||||||
|
this.pubkey = address.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,187 @@
|
||||||
|
package de.bitsharesmunich.graphenej.models.backup;
|
||||||
|
|
||||||
|
import de.bitsharesmunich.graphenej.Chains;
|
||||||
|
import de.bitsharesmunich.graphenej.Util;
|
||||||
|
import de.bitsharesmunich.graphenej.crypto.SecureRandomGenerator;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class holds data deserialized from a wallet in the backup file.
|
||||||
|
*
|
||||||
|
* Created by nelson on 2/14/17.
|
||||||
|
*/
|
||||||
|
public class Wallet {
|
||||||
|
private String public_name;
|
||||||
|
private String password_pubkey;
|
||||||
|
private String encryption_key;
|
||||||
|
private String encrypted_brainkey;
|
||||||
|
private String brainkey_pubkey;
|
||||||
|
private int brainkey_sequence;
|
||||||
|
private String brainkey_backup_date;
|
||||||
|
private String created;
|
||||||
|
private String last_modified;
|
||||||
|
private String chain_id;
|
||||||
|
private String id;
|
||||||
|
private String backup_date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No args constructor
|
||||||
|
*/
|
||||||
|
public Wallet(){}
|
||||||
|
|
||||||
|
public Wallet(String name){
|
||||||
|
this.public_name = name;
|
||||||
|
this.id = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wallet constructor that takes a few arguments.
|
||||||
|
* @param name: The name of this wallet.
|
||||||
|
* @param brainKey: The brain key to be used.
|
||||||
|
* @param brainkeySequence: The brain key sequence.
|
||||||
|
* @param chainId: The chain id
|
||||||
|
* @param password: Password used to encrypt all sensitive data.
|
||||||
|
*/
|
||||||
|
public Wallet(String name, String brainKey, int brainkeySequence, String chainId, String password){
|
||||||
|
this(name);
|
||||||
|
SecureRandom secureRandom = SecureRandomGenerator.getSecureRandom();
|
||||||
|
byte[] decryptedKey = new byte[Util.KEY_LENGTH];
|
||||||
|
secureRandom.nextBytes(decryptedKey);
|
||||||
|
this.encryption_key = Util.bytesToHex(Util.encryptAES(decryptedKey, password.getBytes()));
|
||||||
|
this.encrypted_brainkey = Util.bytesToHex(Util.encryptAES(decryptedKey, brainKey.getBytes()));
|
||||||
|
this.brainkey_sequence = brainkeySequence;
|
||||||
|
this.chain_id = chainId;
|
||||||
|
|
||||||
|
//TODO: Find out how to fill "password_pubkey" and "brainkey_pubkey" fields.
|
||||||
|
|
||||||
|
Date now = new Date();
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat(Util.TIME_DATE_FORMAT);
|
||||||
|
this.created = dateFormat.format(now);
|
||||||
|
this.last_modified = created;
|
||||||
|
this.backup_date = created;
|
||||||
|
this.brainkey_backup_date = created;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method that will return the decrypted version of the "encrypted_brainkey" field.
|
||||||
|
* @param password: Password used to encrypt the encryption key.
|
||||||
|
* @return: The brainkey in its plaintext version.
|
||||||
|
*/
|
||||||
|
public String decryptBrainKey(String password){
|
||||||
|
byte[] decryptedKey = getEncryptionKey(password);
|
||||||
|
byte[] encryptedBrainKey = Util.hexToBytes(encrypted_brainkey);
|
||||||
|
return new String(Util.decryptAES(encryptedBrainKey, decryptedKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts the encryption key, which is also provided in an encrypted form.
|
||||||
|
* @param password: The password used to encrypt the encryption key.
|
||||||
|
* @return: The encryption key.
|
||||||
|
*/
|
||||||
|
public byte[] getEncryptionKey(String password){
|
||||||
|
return Util.decryptAES(Util.hexToBytes(encryption_key), password.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrivateName() {
|
||||||
|
return public_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrivateName(String privateName) {
|
||||||
|
this.public_name = privateName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPasswordPubkey() {
|
||||||
|
return password_pubkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPasswordPubkey(String password_pubkey) {
|
||||||
|
this.password_pubkey = password_pubkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cyphertext version of the encryption key.
|
||||||
|
* @return: Encryption key in its cyphertext version.
|
||||||
|
*/
|
||||||
|
public String getEncryptionKey() {
|
||||||
|
return encryption_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEncryptionKey(String encryption_key) {
|
||||||
|
this.encryption_key = encryption_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEncryptedBrainkey() {
|
||||||
|
return encrypted_brainkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEncryptedBrainkey(String encrypted_brainkey) {
|
||||||
|
this.encrypted_brainkey = encrypted_brainkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBrainkeyPubkey() {
|
||||||
|
return brainkey_pubkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBrainkeyPubkey(String brainkey_pubkey) {
|
||||||
|
this.brainkey_pubkey = brainkey_pubkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBrainkeySequence() {
|
||||||
|
return brainkey_sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBrainkeySequence(int brainkey_sequence) {
|
||||||
|
this.brainkey_sequence = brainkey_sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBrainkeyBackup_date() {
|
||||||
|
return brainkey_backup_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBrainkeyBackupDate(String brainkey_backup_date) {
|
||||||
|
this.brainkey_backup_date = brainkey_backup_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreated() {
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreated(String created) {
|
||||||
|
this.created = created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastModified() {
|
||||||
|
return last_modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastModified(String last_modified) {
|
||||||
|
this.last_modified = last_modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChainId() {
|
||||||
|
return chain_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChainId(String chain_id) {
|
||||||
|
this.chain_id = chain_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBackupDate() {
|
||||||
|
return backup_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBackupDate(String backup_date) {
|
||||||
|
this.backup_date = backup_date;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package de.bitsharesmunich.graphenej.models.backup;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to represent the JSON-formatted version of the file backup containing one or more
|
||||||
|
* wallets and keys.
|
||||||
|
*
|
||||||
|
* Created by nelson on 2/14/17.
|
||||||
|
*/
|
||||||
|
public class WalletBackup {
|
||||||
|
private Wallet[] wallet;
|
||||||
|
private PrivateKeyBackup[] private_keys;
|
||||||
|
private LinkedAccount[] linked_accounts;
|
||||||
|
|
||||||
|
public WalletBackup(List<Wallet> wallets, List<PrivateKeyBackup> privateKeys, List<LinkedAccount> linkedAccounts){
|
||||||
|
this.wallet = wallets.toArray(new Wallet[wallets.size()]);
|
||||||
|
this.private_keys = privateKeys.toArray(new PrivateKeyBackup[privateKeys.size()]);
|
||||||
|
this.linked_accounts = linkedAccounts.toArray(new LinkedAccount[linkedAccounts.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Wallet[] getWallets(){
|
||||||
|
return wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrivateKeyBackup[] getPrivateKeys(){
|
||||||
|
return private_keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkedAccount[] getLinkedAccounts(){
|
||||||
|
return linked_accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Wallet getWallet(int index){
|
||||||
|
return wallet[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrivateKeyBackup getPrivateKeyBackup(int index){
|
||||||
|
return private_keys[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWalletCount(){
|
||||||
|
return wallet.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getKeyCount(){
|
||||||
|
return private_keys.length;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue