Fixed merge issues

This commit is contained in:
Nelson R. Perez 2016-11-23 12:23:35 -05:00
commit 66197aa0d2
9 changed files with 367 additions and 9 deletions

2
.gitignore vendored
View file

@ -75,3 +75,5 @@ atlassian-ide-plugin.xml
# Logs
# ----
/*.log
src/main/java/com/luminiasoft/bitshares/mycelium/*

View file

@ -1,19 +1,56 @@
package com.luminiasoft.bitshares;
import com.luminiasoft.bitshares.crypto.AndroidRandomSource;
import com.luminiasoft.bitshares.crypto.SecureRandomStrengthener;
import org.bitcoinj.core.ECKey;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
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 {
// 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;
/**
* 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) {
String encoded = String.format("%s %d", words, sequence);
try {
@ -32,4 +69,8 @@ public class BrainKey {
public String getPublicKey() {
return Base64.getEncoder().encodeToString(mPrivateKey.getPubKey());
}
public ECKey getPrivateKey(){
return mPrivateKey;
}
}

View file

@ -7,13 +7,18 @@ import java.io.IOException;
public class Main {
// Brain key from Nelson's app referencing the bilthon-83 account
public static final String BRAIN_KEY = "PUMPER ISOTOME SERE STAINER CLINGER MOONLIT CHAETA UPBRIM AEDILIC BERTHER NIT SHAP SAID SHADING JUNCOUS CHOUGH";
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";
// public static final String WIF = "5J96pne45qWM1WpektoeazN6k9Mt93jQ7LyueRxFfEMTiy6yxjM";
// Brain key from an empty account created by the cli_wallet
// public static final String BRAIN_KEY = "TWIXT SERMO TRILLI AUDIO PARDED PLUMET BIWA REHUNG MAUDLE VALVULA OUTBURN FEWNESS ALIENER UNTRACE PRICH TROKER";
// WIF from an emty account created by the cli_wallet
public static final String WIF = "5KMzB2GqGhnh7ufhgddmz1eKPHS72uTLeL9hHjSvPb1UywWknF5";
// WIF from the cli_wallet instance
// public static final String WIF = "5KMzB2GqGhnh7ufhgddmz1eKPHS72uTLeL9hHjSvPb1UywWknF5";
public static final String EXTERNAL_SIGNATURE = "1f36c41acb774fcbc9c231b5895ec9701d6872729098d8ea56d78dda72a6b54252694db85d7591de5751b7aea06871da15d63a1028758421607ffc143e53ef3306";
// Static block information used for transaction serialization tests
@ -61,6 +66,7 @@ public class Main {
// test.testRandomNumberGeneration();
test.testBrainKeyOperations();
test.testBip39Opertion();
}
}

View file

@ -16,9 +16,10 @@ import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.digests.SHA512Digest;
import org.spongycastle.crypto.prng.DigestRandomGenerator;
import java.io.IOException;
import java.io.Serializable;
import java.io.*;
import java.lang.reflect.Type;
import java.net.URL;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;
@ -505,12 +506,41 @@ public class Test {
* The final purpose of this test is to convert the plain brainkey at
* Main.BRAIN_KEY into the WIF at Main.WIF
*/
public void testBrainKeyOperations() {
BrainKey brainKey = new BrainKey(Main.BRAIN_KEY, 0);
public void testBrainKeyOperations(){
try {
String current = new java.io.File( "." ).getCanonicalPath();
File file = new File(current + "/src/main/java/com/luminiasoft/bitshares/brainkeydict.txt");
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
StringBuffer buffer = new StringBuffer();
String words = bufferedReader.readLine();
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);
byte[] pubKey1 = key.decompress().getPubKey();
System.out.println("decompressed public key: "+Base58.encode(pubKey1));
byte[] pubKey2 = key.getPubKey();
System.out.println("compressed public key: "+Base58.encode(pubKey2));
System.out.println("pub key compressed : "+Util.bytesToHex(pubKey1));
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());
}
}
public void testBip39Opertion() {
BIP39 bip39 = new BIP39(Main.BIP39_KEY, "");
}
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,71 @@
/*
* Copyright 2013, 2014 Megion Research and Development GmbH
*
* Licensed under the Microsoft Reference Source License (MS-RSL)
*
* This license governs use of the accompanying software. If you use the software, you accept this license.
* If you do not accept the license, do not use the software.
*
* 1. Definitions
* The terms "reproduce," "reproduction," and "distribution" have the same meaning here as under U.S. copyright law.
* "You" means the licensee of the software.
* "Your company" means the company you worked for when you downloaded the software.
* "Reference use" means use of the software within your company as a reference, in read only form, for the sole purposes
* of debugging your products, maintaining your products, or enhancing the interoperability of your products with the
* software, and specifically excludes the right to distribute the software outside of your company.
* "Licensed patents" means any Licensor patent claims which read directly on the software as distributed by the Licensor
* under this license.
*
* 2. Grant of Rights
* (A) Copyright Grant- Subject to the terms of this license, the Licensor grants you a non-transferable, non-exclusive,
* worldwide, royalty-free copyright license to reproduce the software for reference use.
* (B) Patent Grant- Subject to the terms of this license, the Licensor grants you a non-transferable, non-exclusive,
* worldwide, royalty-free patent license under licensed patents for reference use.
*
* 3. Limitations
* (A) No Trademark License- This license does not grant you any rights to use the Licensors name, logo, or trademarks.
* (B) If you begin patent litigation against the Licensor over patents that you think may apply to the software
* (including a cross-claim or counterclaim in a lawsuit), your license to the software ends automatically.
* (C) The software is licensed "as-is." You bear the risk of using it. The Licensor gives no express warranties,
* guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot
* change. To the extent permitted under your local laws, the Licensor excludes the implied warranties of merchantability,
* fitness for a particular purpose and non-infringement.
*/
package com.luminiasoft.bitshares.crypto;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
public class AndroidRandomSource implements RandomSource, EntropySource {
@Override
public synchronized void nextBytes(byte[] bytes) {
// On Android we use /dev/urandom for providing random data
File file = new File("/dev/urandom");
if (!file.exists()) {
throw new RuntimeException("Unable to generate random bytes on this Android device");
}
try {
FileInputStream stream = new FileInputStream(file);
DataInputStream dis = new DataInputStream(stream);
dis.readFully(bytes);
dis.close();
} catch (IOException 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;
}
}

View file

@ -0,0 +1,19 @@
package com.luminiasoft.bitshares.crypto;
import java.nio.ByteBuffer;
/**
* A simple interface that can be used to retrieve entropy from any source.
*
* @author owlstead
*/
public interface EntropySource {
/**
* Retrieves the entropy.
* The position of the ByteBuffer must be advanced to the limit by any users calling this method.
* The values of the bytes between the position and limit should be set to zero by any users calling this method.
*
* @return entropy within the position and limit of the given buffer
*/
ByteBuffer provideEntropy();
}

View file

@ -0,0 +1,26 @@
/*
* Copyright 2013, 2014 Megion Research & Development GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.luminiasoft.bitshares.crypto;
public interface RandomSource {
/**
* Generates a user specified number of random bytes
*
* @param bytes
* The array to fill with random bytes
*/
void nextBytes(byte[] bytes);
}

View file

@ -0,0 +1,162 @@
package com.luminiasoft.bitshares.crypto;
import java.nio.ByteBuffer;
import java.security.DigestException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.LinkedList;
import java.util.List;
/**
* A strengthener that can be used to generate and re-seed random number
* generators that do not seed themselves appropriately.
*
* @author owlstead
*/
public class SecureRandomStrengthener {
private static final String DEFAULT_PSEUDO_RANDOM_NUMBER_GENERATOR = "SHA1PRNG";
private static final EntropySource mTimeEntropySource = new EntropySource() {
final ByteBuffer timeBuffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE
* 2);
@Override
public ByteBuffer provideEntropy() {
this.timeBuffer.clear();
this.timeBuffer.putLong(System.currentTimeMillis());
this.timeBuffer.putLong(System.nanoTime());
this.timeBuffer.flip();
return this.timeBuffer;
}
};
private final String algorithm;
private final List<EntropySource> entropySources = new LinkedList<EntropySource>();
private final MessageDigest digest;
private final ByteBuffer seedBuffer;
/**
* Generates an instance of a {@link SecureRandomStrengthener} that
* generates and re-seeds instances of {@code "SHA1PRNG"}.
*
* @return the strengthener, never null
*/
public static SecureRandomStrengthener getInstance() {
return new SecureRandomStrengthener(
DEFAULT_PSEUDO_RANDOM_NUMBER_GENERATOR);
}
/**
* Generates an instance of a {@link SecureRandomStrengthener} that
* generates instances of the given argument. Note that the availability of
* the given algorithm arguments in not tested until generation.
*
* @param algorithm
* the algorithm indicating the {@link SecureRandom} instance to
* use
* @return the strengthener, never null
*/
public static SecureRandomStrengthener getInstance(final String algorithm) {
return new SecureRandomStrengthener(algorithm);
}
private SecureRandomStrengthener(final String algorithm) {
if (algorithm == null || algorithm.length() == 0) {
throw new IllegalArgumentException(
"Please provide a PRNG algorithm string such as SHA1PRNG");
}
this.algorithm = algorithm;
try {
this.digest = MessageDigest.getInstance("SHA1");
} catch (final NoSuchAlgorithmException e) {
throw new IllegalStateException(
"MessageDigest to create seed not available", e);
}
this.seedBuffer = ByteBuffer.allocate(this.digest.getDigestLength());
}
/**
* Add an entropy source, which will be called for each generation and
* re-seeding of the given random number generator.
*
* @param source
* the source of entropy
*/
public void addEntropySource(final EntropySource source) {
if (source == null) {
throw new IllegalArgumentException(
"EntropySource should not be null");
}
this.entropySources.add(source);
}
/**
* Generates and seeds a random number generator of the configured
* algorithm. Calls the {@link EntropySource#provideEntropy()} method of all
* added sources of entropy.
*
* @return the random number generator
*/
public SecureRandom generateAndSeedRandomNumberGenerator() {
final SecureRandom secureRandom;
try {
secureRandom = SecureRandom.getInstance(this.algorithm);
} catch (final NoSuchAlgorithmException e) {
throw new IllegalStateException("PRNG is not available", e);
}
reseed(secureRandom);
return secureRandom;
}
/**
* Re-seeds the random number generator. Calls the
* {@link EntropySource#provideEntropy()} method of all added sources of
* entropy.
*
* @param secureRandom
* the random number generator to re-seed
*/
public void reseed(final SecureRandom secureRandom) {
this.seedBuffer.clear();
secureRandom.nextBytes(this.seedBuffer.array());
for (final EntropySource source : this.entropySources) {
final ByteBuffer entropy = source.provideEntropy();
if (entropy == null) {
continue;
}
final ByteBuffer wipeBuffer = entropy.duplicate();
this.digest.update(entropy);
wipe(wipeBuffer);
}
this.digest.update(mTimeEntropySource.provideEntropy());
this.digest.update(this.seedBuffer);
this.seedBuffer.clear();
// remove data from seedBuffer so it won't be retrievable
// reuse
try {
this.digest.digest(this.seedBuffer.array(), 0,
this.seedBuffer.capacity());
} catch (final DigestException e) {
throw new IllegalStateException(
"DigestException should not be thrown", e);
}
secureRandom.setSeed(this.seedBuffer.array());
wipe(this.seedBuffer);
}
private void wipe(final ByteBuffer buf) {
while (buf.hasRemaining()) {
buf.put((byte) 0);
}
}
}