Implementing the method suggest that will provide us with a fresh new brainkey
This commit is contained in:
parent
f5065b215b
commit
27c864ebd9
4 changed files with 93 additions and 26 deletions
|
@ -1,27 +1,64 @@
|
||||||
package com.luminiasoft.bitshares;
|
package com.luminiasoft.bitshares;
|
||||||
|
|
||||||
import org.bitcoinj.core.Base58;
|
import com.luminiasoft.bitshares.crypto.AndroidRandomSource;
|
||||||
import org.bitcoinj.core.DumpedPrivateKey;
|
import com.luminiasoft.bitshares.crypto.SecureRandomStrengthener;
|
||||||
import org.bitcoinj.core.ECKey;
|
import org.bitcoinj.core.ECKey;
|
||||||
import org.bitcoinj.core.NetworkParameters;
|
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by nelson on 11/19/16.
|
* Class used to encapsulate all BrainKey-related operations.
|
||||||
*/
|
*/
|
||||||
public class BrainKey {
|
public class BrainKey {
|
||||||
|
// The size of the word dictionary
|
||||||
|
public static final int DICT_WORD_COUNT = 49744;
|
||||||
|
|
||||||
|
// The required number of words
|
||||||
|
public static final int BRAINKEY_WORD_COUNT = 12;
|
||||||
|
|
||||||
private ECKey mPrivateKey;
|
private ECKey mPrivateKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method that will generate a random brain key
|
||||||
|
* @param words The list of words from the graphene specification dictionary.
|
||||||
|
* @return A random sequence of words
|
||||||
|
*/
|
||||||
|
public static String suggest(String words){
|
||||||
|
String[] wordArray = words.split(",");
|
||||||
|
ArrayList<String> suggestedBrainKey = new ArrayList<String>();
|
||||||
|
assert(wordArray.length == DICT_WORD_COUNT);
|
||||||
|
SecureRandomStrengthener randomStrengthener = SecureRandomStrengthener.getInstance();
|
||||||
|
randomStrengthener.addEntropySource(new AndroidRandomSource());
|
||||||
|
SecureRandom secureRandom = randomStrengthener.generateAndSeedRandomNumberGenerator();
|
||||||
|
int index;
|
||||||
|
for(int i = 0; i < BRAINKEY_WORD_COUNT; i++){
|
||||||
|
index = secureRandom.nextInt(DICT_WORD_COUNT - 1);
|
||||||
|
suggestedBrainKey.add(wordArray[index].toUpperCase());
|
||||||
|
}
|
||||||
|
String result = String.join(" ", suggestedBrainKey.toArray(new String[suggestedBrainKey.size()]));
|
||||||
|
System.out.println("result: '"+result+"'");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BrainKey constructor that takes as argument a specific brain key word sequence and generates the
|
||||||
|
* private key and address from that.
|
||||||
|
* @param words The brain key specifying the private key
|
||||||
|
* @param sequence Sequence number
|
||||||
|
*/
|
||||||
public BrainKey(String words, int sequence) {
|
public BrainKey(String words, int sequence) {
|
||||||
String encoded = String.format("%s %d", words, sequence);
|
String encoded = String.format("%s %d", words, sequence);
|
||||||
try {
|
try {
|
||||||
MessageDigest sha512 = MessageDigest.getInstance("SHA-512");
|
MessageDigest md = MessageDigest.getInstance("SHA-512");
|
||||||
|
byte[] bytes = md.digest(encoded.getBytes("UTF-8"));
|
||||||
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
|
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
|
||||||
mPrivateKey = ECKey.fromPrivate(sha256.digest(sha512.digest(encoded.getBytes("UTF-8"))));
|
byte[] result = sha256.digest(bytes);
|
||||||
|
mPrivateKey = ECKey.fromPrivate(result);
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
System.out.println("NoSuchAlgotithmException. Msg: " + e.getMessage());
|
System.out.println("NoSuchAlgotithmException. Msg: " + e.getMessage());
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
@ -29,7 +66,11 @@ public class BrainKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ECKey getPrivateKey(){
|
public String getPublicKey() {
|
||||||
return this.mPrivateKey;
|
return Base64.getEncoder().encodeToString(mPrivateKey.getPubKey());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public ECKey getPrivateKey(){
|
||||||
|
return mPrivateKey;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,9 +16,10 @@ import org.spongycastle.crypto.Digest;
|
||||||
import org.spongycastle.crypto.digests.SHA512Digest;
|
import org.spongycastle.crypto.digests.SHA512Digest;
|
||||||
import org.spongycastle.crypto.prng.DigestRandomGenerator;
|
import org.spongycastle.crypto.prng.DigestRandomGenerator;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.io.Serializable;
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -503,23 +504,37 @@ public class Test {
|
||||||
* into the WIF at Main.WIF
|
* into the WIF at Main.WIF
|
||||||
*/
|
*/
|
||||||
public void testBrainKeyOperations(){
|
public void testBrainKeyOperations(){
|
||||||
BrainKey brainKey = new BrainKey(Main.BRAIN_KEY, 0);
|
try {
|
||||||
ECKey key = brainKey.getPrivateKey();
|
String current = new java.io.File( "." ).getCanonicalPath();
|
||||||
String wif = key.getPrivateKeyAsWiF(NetworkParameters.fromID(NetworkParameters.ID_MAINNET));
|
File file = new File(current + "/src/main/java/com/luminiasoft/bitshares/brainkeydict.txt");
|
||||||
System.out.println("wif compressed: "+wif);
|
|
||||||
String wif2 = key.decompress().getPrivateKeyAsWiF(NetworkParameters.fromID(NetworkParameters.ID_MAINNET));
|
|
||||||
System.out.println("wif decompressed: "+wif2);
|
|
||||||
|
|
||||||
byte[] pubKey1 = key.decompress().getPubKey();
|
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
|
||||||
System.out.println("decompressed public key: "+Base58.encode(pubKey1));
|
StringBuffer buffer = new StringBuffer();
|
||||||
byte[] pubKey2 = key.getPubKey();
|
String words = bufferedReader.readLine();
|
||||||
System.out.println("compressed public key: "+Base58.encode(pubKey2));
|
String suggestion = BrainKey.suggest(words);
|
||||||
|
BrainKey brainKey = new BrainKey(Main.BRAIN_KEY, 0);
|
||||||
|
ECKey key = brainKey.getPrivateKey();
|
||||||
|
String wif = key.getPrivateKeyAsWiF(NetworkParameters.fromID(NetworkParameters.ID_MAINNET));
|
||||||
|
System.out.println("wif compressed: "+wif);
|
||||||
|
String wif2 = key.decompress().getPrivateKeyAsWiF(NetworkParameters.fromID(NetworkParameters.ID_MAINNET));
|
||||||
|
System.out.println("wif decompressed: "+wif2);
|
||||||
|
|
||||||
System.out.println("pub key compressed : "+Util.bytesToHex(pubKey1));
|
byte[] pubKey1 = key.decompress().getPubKey();
|
||||||
System.out.println("pub key uncompressed : "+Util.bytesToHex(pubKey2));
|
System.out.println("decompressed public key: "+Base58.encode(pubKey1));
|
||||||
|
byte[] pubKey2 = key.getPubKey();
|
||||||
|
System.out.println("compressed public key: "+Base58.encode(pubKey2));
|
||||||
|
|
||||||
byte[] pubKey3 = key.getPubKeyPoint().getEncoded(true);
|
System.out.println("pub key compressed : "+Util.bytesToHex(pubKey1));
|
||||||
System.out.println("pub key compressed : "+Base58.encode(pubKey3));
|
System.out.println("pub key uncompressed : "+Util.bytesToHex(pubKey2));
|
||||||
|
|
||||||
|
byte[] pubKey3 = key.getPubKeyPoint().getEncoded(true);
|
||||||
|
System.out.println("pub key compressed : "+Base58.encode(pubKey3));
|
||||||
|
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
System.out.println("FileNotFoundException. Msg: "+e.getMessage());
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("IOException. Msg: "+e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
1
src/main/java/com/luminiasoft/bitshares/brainkeydict.txt
Normal file
1
src/main/java/com/luminiasoft/bitshares/brainkeydict.txt
Normal file
File diff suppressed because one or more lines are too long
|
@ -38,9 +38,10 @@ import java.io.DataInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
|
||||||
public class AndroidRandomSource implements RandomSource {
|
public class AndroidRandomSource implements RandomSource, EntropySource {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void nextBytes(byte[] bytes) {
|
public synchronized void nextBytes(byte[] bytes) {
|
||||||
|
@ -58,4 +59,13 @@ public class AndroidRandomSource implements RandomSource {
|
||||||
throw new RuntimeException("Unable to generate random bytes on this Android device", e);
|
throw new RuntimeException("Unable to generate random bytes on this Android device", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer provideEntropy() {
|
||||||
|
byte[] buffer = new byte[ 256 / 8];
|
||||||
|
nextBytes(buffer);
|
||||||
|
ByteBuffer byteBuffer = ByteBuffer.allocate(buffer.length);
|
||||||
|
byteBuffer.put(buffer, 0, buffer.length);
|
||||||
|
return byteBuffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue