mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-07 14:54:15 +00:00
Updated to latest version of BIP-0039.
This commit is contained in:
parent
5cd10a537a
commit
e86ce7f268
@ -17,8 +17,6 @@
|
||||
package com.google.bitcoin.crypto;
|
||||
|
||||
import com.google.bitcoin.core.Sha256Hash;
|
||||
import org.spongycastle.crypto.engines.RijndaelEngine;
|
||||
import org.spongycastle.crypto.params.KeyParameter;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@ -36,10 +34,6 @@ import java.util.List;
|
||||
* A MnemonicCode object may be used to convert between binary seed values and
|
||||
* lists of words per <a href="https://en.bitcoin.it/wiki/BIP_0039">the BIP 39
|
||||
* specification</a>
|
||||
*
|
||||
* NOTE - as of 15 Oct 2013 the spec at
|
||||
* https://en.bitcoin.it/wiki/BIP_0039 is out-of-date. The correct
|
||||
* spec can be found at https://github.com/trezor/python-mnemonic
|
||||
*/
|
||||
|
||||
public class MnemonicCode {
|
||||
@ -47,6 +41,8 @@ public class MnemonicCode {
|
||||
|
||||
public static String BIP39_ENGLISH_SHA256 = "ad90bf3beb7b0eb7e5acd74727dc0da96e0a280a258354e7293fb7e211ac03db";
|
||||
|
||||
private static final int HMAC_ROUNDS = 10000;
|
||||
|
||||
public MnemonicCode() throws IOException {
|
||||
this(MnemonicCode.class.getResourceAsStream("mnemonic/wordlist/english.txt"), BIP39_ENGLISH_SHA256);
|
||||
}
|
||||
@ -84,66 +80,89 @@ public class MnemonicCode {
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a 128, 192 or 256 bit seed into a list of words.
|
||||
* Convert mnemonic word list to seed.
|
||||
*/
|
||||
public List<String> encode(byte[] seed) throws MnemonicLengthException {
|
||||
public static byte[] toSeed(List<String> words, String passphrase) {
|
||||
|
||||
// To create binary seed from mnemonic, we use HMAC-SHA512
|
||||
// function with string "mnemonic" + passphrase (in UTF-8) as
|
||||
// key and mnemonic sentence (again in UTF-8) as the
|
||||
// message. We perform 10000 HMAC rounds and use the final
|
||||
// result as the binary seed.
|
||||
//
|
||||
// Pseudocode:
|
||||
//
|
||||
// K = "mnemonic" + passphrase
|
||||
// M = mnemonic_sentence
|
||||
// for i in 1 ... 10000 do
|
||||
// M = hmac_sha512(K, M)
|
||||
// done
|
||||
// seed = M
|
||||
|
||||
byte[] kk = new String("mnemonic" + passphrase).getBytes();
|
||||
byte[] mm = joinStringList(words).getBytes();
|
||||
|
||||
for (int ii = 0; ii < HMAC_ROUNDS; ++ii)
|
||||
mm = HDUtils.hmacSha512(kk, mm);
|
||||
|
||||
return mm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert arbitrary data to mnemonic word list.
|
||||
*/
|
||||
public List<String> toMnemonic(byte[] entropy) throws MnemonicLengthException {
|
||||
if (entropy.length % 4 > 0)
|
||||
throw new MnemonicLengthException("entropy length not multiple of 32 bits");
|
||||
|
||||
// We take initial entropy of ENT bits and compute its
|
||||
// checksum by taking first ENT / 32 bits of its SHA256 hash.
|
||||
|
||||
byte[] hash = Sha256Hash.create(entropy).getBytes();
|
||||
boolean[] hashBits = bytesToBits(hash);
|
||||
|
||||
// 2. Make sure its length (L) is 128, 192 or 256 bits.
|
||||
int len = seed.length * 8;
|
||||
if (len != 128 && len != 192 && len != 256)
|
||||
throw new MnemonicLengthException("seed not 128, 192 or 256 bits");
|
||||
boolean[] entropyBits = bytesToBits(entropy);
|
||||
int checksumLengthBits = entropyBits.length / 32;
|
||||
|
||||
// 3. Encrypt input data 10000x with Rijndael (ECB mode).
|
||||
// Set key to SHA256 hash of string ("mnemonic" + user_password).
|
||||
// Set block size to input size (that's why Rijndael is used, not AES).
|
||||
byte[] indata = stretch(len, seed);
|
||||
// We append these bits to the end of the initial entropy.
|
||||
boolean[] concatBits = new boolean[entropyBits.length + checksumLengthBits];
|
||||
for (int ii = 0; ii < entropyBits.length; ++ii)
|
||||
concatBits[ii] = entropyBits[ii];
|
||||
for (int ii = 0; ii < checksumLengthBits; ++ii)
|
||||
concatBits[entropyBits.length + ii] = hashBits[ii];
|
||||
|
||||
// Convert binary data to array of boolean for processing.
|
||||
boolean[] inarray = new boolean[indata.length * 8];
|
||||
for (int ii = 0; ii < indata.length; ++ii)
|
||||
for (int kk = 0; kk < 8; ++kk)
|
||||
inarray[(ii * 8) + kk] = (indata[ii] & (1 << (7 - kk))) != 0;
|
||||
// Next we take these concatenated bits and split them into
|
||||
// groups of 11 bits. Each group encodes number from 0-2047
|
||||
// which is a position in a wordlist. We convert numbers into
|
||||
// words and use joined words as mnemonic sentence.
|
||||
|
||||
// 4-6 Compute checksum.
|
||||
boolean[] chksum = checksum(inarray);
|
||||
|
||||
// 7. Concatenate I and C into encoded data (E). Length of E is divisable by 33 bits.
|
||||
boolean[] ee = new boolean[inarray.length + chksum.length];
|
||||
for (int ii = 0; ii < inarray.length; ++ii)
|
||||
ee[ii] = inarray[ii];
|
||||
for (int ii = 0; ii < chksum.length; ++ii)
|
||||
ee[inarray.length + ii] = chksum[ii];
|
||||
|
||||
// 8. Keep taking 11 bits from E until there are none left.
|
||||
// 9. Treat them as integer W, add word with index W to the output.
|
||||
ArrayList<String> words = new ArrayList<String>();
|
||||
int nwords = ee.length / 11;
|
||||
int nwords = concatBits.length / 11;
|
||||
for (int ii = 0; ii < nwords; ++ii) {
|
||||
int ndx = 0;
|
||||
for (int kk = 0; kk < 11; ++kk) {
|
||||
for (int jj = 0; jj < 11; ++jj) {
|
||||
ndx <<= 1;
|
||||
if (ee[(ii * 11) + kk])
|
||||
if (concatBits[(ii * 11) + jj])
|
||||
ndx |= 0x1;
|
||||
}
|
||||
words.add(this.wordList.get(ndx));
|
||||
}
|
||||
|
||||
return words;
|
||||
return words;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a list of words into a seed value.
|
||||
* Check to see if a mnemonic word list is valid.
|
||||
*/
|
||||
public byte[] decode(List<String> words) throws MnemonicLengthException, MnemonicWordException, MnemonicChecksumException {
|
||||
int nwords = words.size();
|
||||
public void check(List<String> words) throws MnemonicLengthException, MnemonicWordException, MnemonicChecksumException {
|
||||
if (words.size() % 3 > 0)
|
||||
throw new MnemonicLengthException("Word list size must be multiple of three words.");
|
||||
|
||||
// 2. Make sure the number of words is 12, 18 or 24.
|
||||
if (nwords != 12 && nwords != 18 && nwords != 24)
|
||||
throw new MnemonicLengthException("Mnemonic code not 12, 18 or 24 words");
|
||||
|
||||
// 3. Figure out word indexes in a dictionary and output them as binary stream E.
|
||||
int len = nwords * 11;
|
||||
boolean[] ee = new boolean[len];
|
||||
// Look up all the words in the list and construct the
|
||||
// concatenation of the original entropy and the checksum.
|
||||
//
|
||||
int concatLenBits = words.size() * 11;
|
||||
boolean[] concatBits = new boolean[concatLenBits];
|
||||
int wordindex = 0;
|
||||
for (String word : words) {
|
||||
// Find the words index in the wordlist.
|
||||
@ -153,80 +172,49 @@ public class MnemonicCode {
|
||||
|
||||
// Set the next 11 bits to the value of the index.
|
||||
for (int ii = 0; ii < 11; ++ii)
|
||||
ee[(wordindex * 11) + ii] = (ndx & (1 << (10 - ii))) != 0;
|
||||
concatBits[(wordindex * 11) + ii] = (ndx & (1 << (10 - ii))) != 0;
|
||||
++wordindex;
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Split E into two parts: B and C, where B are first L/33*32 bits, C are last L/33 bits.
|
||||
int bblen = (len / 33) * 32;
|
||||
int cclen = len - bblen;
|
||||
int checksumLengthBits = concatLenBits / 33;
|
||||
int entropyLengthBits = concatLenBits - checksumLengthBits;
|
||||
|
||||
boolean[] bb = new boolean[bblen];
|
||||
for (int ii = 0; ii < bblen; ++ii)
|
||||
bb[ii] = ee[ii];
|
||||
|
||||
boolean[] cc = new boolean[cclen];
|
||||
for (int ii = 0; ii < cclen; ++ii)
|
||||
cc[ii] = ee[bblen + ii];
|
||||
|
||||
// 6. Make sure C is the checksum of B (using the step 5 from the above paragraph).
|
||||
boolean[] chksum = checksum(bb);
|
||||
if (!Arrays.equals(chksum, cc))
|
||||
throw new MnemonicChecksumException("checksum error");
|
||||
|
||||
// 8. Treat B as binary data.
|
||||
byte[] outdata = new byte[bblen / 8];
|
||||
for (int ii = 0; ii < outdata.length; ++ii)
|
||||
// Extract original entropy as bytes.
|
||||
byte[] entropy = new byte[entropyLengthBits / 8];
|
||||
for (int ii = 0; ii < entropy.length; ++ii)
|
||||
for (int jj = 0; jj < 8; ++jj)
|
||||
if (bb[(ii * 8) + jj])
|
||||
outdata[ii] |= 1 << (7 - jj);
|
||||
if (concatBits[(ii * 8) + jj])
|
||||
entropy[ii] |= 1 << (7 - jj);
|
||||
|
||||
// 9. Decrypt this data 10000x with Rijndael (ECB mode),
|
||||
// use the same parameters as used in step 3 of encryption.
|
||||
byte[] seed = unstretch(bblen, outdata);
|
||||
// Take the digest of the entropy.
|
||||
byte[] hash = Sha256Hash.create(entropy).getBytes();
|
||||
boolean[] hashBits = bytesToBits(hash);
|
||||
|
||||
return seed;
|
||||
// Check all the checksum bits.
|
||||
for (int ii = 0; ii < checksumLengthBits; ++ii)
|
||||
if (concatBits[entropyLengthBits + ii] != hashBits[ii])
|
||||
throw new MnemonicChecksumException("checksum error");
|
||||
}
|
||||
|
||||
private byte[] stretch(int len, byte[] data) {
|
||||
// 3. Encrypt input data 10000x with Rijndael (ECB mode).
|
||||
// Set key to SHA256 hash of string ("mnemonic" + user_password).
|
||||
// Set block size to input size (that's why Rijndael is used, not AES).
|
||||
byte[] mnemonic = {'m', 'n', 'e', 'm', 'o', 'n', 'i', 'c'};
|
||||
byte[] key = Sha256Hash.create(mnemonic).getBytes();
|
||||
byte[] buffer = new byte[data.length];
|
||||
System.arraycopy(data, 0, buffer, 0, data.length);
|
||||
RijndaelEngine cipher = new RijndaelEngine(len);
|
||||
cipher.init(true, new KeyParameter(key));
|
||||
for (int ii = 0; ii < 10000; ++ii)
|
||||
cipher.processBlock(buffer, 0, buffer, 0);
|
||||
return buffer;
|
||||
private static boolean[] bytesToBits(byte[] data) {
|
||||
boolean[] bits = new boolean[data.length * 8];
|
||||
for (int ii = 0; ii < data.length; ++ii)
|
||||
for (int jj = 0; jj < 8; ++jj)
|
||||
bits[(ii * 8) + jj] = (data[ii] & (1 << (7 - jj))) != 0;
|
||||
return bits;
|
||||
}
|
||||
|
||||
private byte[] unstretch(int len, byte[] data) {
|
||||
// 9. Decrypt this data 10000x with Rijndael (ECB mode),
|
||||
// use the same parameters as used in step 3 of encryption.
|
||||
byte[] mnemonic = {'m', 'n', 'e', 'm', 'o', 'n', 'i', 'c'};
|
||||
byte[] key = Sha256Hash.create(mnemonic).getBytes();
|
||||
byte[] buffer = new byte[data.length];
|
||||
System.arraycopy(data, 0, buffer, 0, data.length);
|
||||
RijndaelEngine cipher = new RijndaelEngine(len);
|
||||
cipher.init(false, new KeyParameter(key));
|
||||
for (int ii = 0; ii < 10000; ++ii)
|
||||
cipher.processBlock(buffer, 0, buffer, 0);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private boolean[] checksum(boolean[] bits) {
|
||||
// 4. Compute the length of the checkum (LC). LC = L/32
|
||||
int lc = bits.length / 32;
|
||||
|
||||
// 5. Split I into chunks of LC bits (I1, I2, I3, ...).
|
||||
// 6. XOR them altogether and produce the checksum C. C = I1 xor I2 xor I3 ... xor In.
|
||||
boolean[] cc = new boolean[lc];
|
||||
for (int ii = 0; ii < 32; ++ii)
|
||||
for (int jj = 0; jj < lc; ++jj)
|
||||
cc[jj] ^= bits[(ii * lc) + jj];
|
||||
return cc;
|
||||
static private String joinStringList(List<String> list) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean first = true;
|
||||
for (String item : list)
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
sb.append(" ");
|
||||
sb.append(item);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -29,80 +29,103 @@ import java.util.List;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class MnemonicCodeTest {
|
||||
// These vectors are from https://raw.github.com/trezor/python-mnemonic/master/vectors.json
|
||||
// These vectors are from https://github.com/trezor/python-mnemonic/blob/master/vectors.json
|
||||
String vectors[] = {
|
||||
|
||||
"00000000000000000000000000000000",
|
||||
"risk tiger venture dinner age assume float denial penalty hello game wing",
|
||||
"00000000000000000000000000000000",
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
"cb5e7230ce8229de990674f6aa4288325fd4d8181f761734bd8b5cc944fedc2a4300e64422864b565352de7ffbc5ad0fafdf5344489f3a83e4a4bb5271cafaae",
|
||||
|
||||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
||||
"truth chase learn pretty right casual acoustic frozen betray main slogan method",
|
||||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
||||
"legal winner thank year wave sausage worth useful legal winner thank yellow",
|
||||
"de1277934939d6969519f44b7b3757a905d7f635be41e1e88022c346bc52ad26c0a3e9578e73e9b89066873266f285a5891d27d28cb27fccfe26d92bbd7ee364",
|
||||
|
||||
"80808080808080808080808080808080",
|
||||
"olive garment twenty drill people finish hat own usual level milk usage",
|
||||
"80808080808080808080808080808080",
|
||||
"letter advice cage absurd amount doctor acoustic avoid letter advice cage above",
|
||||
"8863bccef9cfffeacef1e4c6fc97bba8227ab0fc7e8e162be7467282689a13521ea364d7c4bc8cd241b59f53c5147a89c18a47248a96592ab9a2c1f1870b026c",
|
||||
|
||||
"ffffffffffffffffffffffffffffffff",
|
||||
"laundry faint system client frog vanish plug shell slot cable large embrace",
|
||||
"ffffffffffffffffffffffffffffffff",
|
||||
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong",
|
||||
"7a29e57c7a1532af1bddb7e02b892cfccc6a57b74fe9784324ea89fab8a66dc64fde79c31166b159685116f4e93c1795496f20ffdc2d3a69d3439931dabde86e",
|
||||
|
||||
"000000000000000000000000000000000000000000000000",
|
||||
"giant twelve seat embark ostrich jazz leader lunch budget hover much weapon vendor build truth garden year list",
|
||||
"000000000000000000000000000000000000000000000000",
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent",
|
||||
"c3e382025b6a22a901505cf393faea450eb6c4a5f2a8c8f0596285b2bd84688877a6cc7231420e2bbdd2428e62ed549a78fa215b3adafd8dea075dabfc704d5e",
|
||||
|
||||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
||||
"awful faint gun mean fuel side slogan marine glad donkey velvet oyster movie real type digital dress federal",
|
||||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
||||
"legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will",
|
||||
"c82666e40eb097bf6eb05fecd7dc2ddfb6bbdc6071900f4b3fd3c3e635db69aa2094f1f450c98e8dc6103aa72df635abdfcc3b6d6ec5261a9208a07a35a3f1c8",
|
||||
|
||||
"808080808080808080808080808080808080808080808080",
|
||||
"bless carpet daughter animal hospital pave faculty escape fortune song sign twin unknown bread mobile normal agent use",
|
||||
"808080808080808080808080808080808080808080808080",
|
||||
"letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always",
|
||||
"e90681c67c55504afadca009ce4042819341fa0e90300b6d32b4f2e8e8a6678ff7e7fc1da663ae194dc7a2ef7ec7b50112d1a5efce47bfd00c66eec82f2265b5",
|
||||
|
||||
"ffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"saddle curve flight drama client resemble venture arch will ordinary enrich clutch razor shallow trophy tumble dice outer",
|
||||
"ffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when",
|
||||
"2a372547df962742942674170a7cef495ea0b97f4864de16d0f3ee82eb577ca1eca345e601cc2df7c626c5bc51c52c28a3b4294224b685c958c7450bee6769e6",
|
||||
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"supreme army trim onion neglect coach squirrel spider device glass cabbage giant web digital floor able social magnet only fork fuel embrace salt fence",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
|
||||
"58cb9c5555d67ecc7b32305a78d1a2fcf0c9b22f1af761cfafc65eb1d3909f63ee2cab84996a7478cfd3e864cda5efb0caf580d56cf49739c6b3638d94e758c1",
|
||||
|
||||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
||||
"cloth video uncle switch year captain artist country adjust edit inherit ocean tennis soda baby express hospital forest panel actual profit boy spice elite",
|
||||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
|
||||
"legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title",
|
||||
"0093cb3ed6d1302d3cf498017f8cb1c7dc2fdbd62ec57fc49e4b2a4dd47a23e44e0b309517d5a3e7b0f4f0ef0ed132818cf120a098a92e572ad086f1a90ccb7f",
|
||||
|
||||
"8080808080808080808080808080808080808080808080808080808080808080",
|
||||
"fence twin prize extra choose mask twist deny cereal quarter can power term ostrich leg staff nature nut swift sausage amateur aim script wisdom",
|
||||
"8080808080808080808080808080808080808080808080808080808080808080",
|
||||
"letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless",
|
||||
"8a21e46b9d264328c63e707e3d38ed4eb21508deda309fa2ef57cc8eca8b351ca3018758844ba9fb5851bab15d026a61cabace53a9a39bc91dc2c51407542cf5",
|
||||
|
||||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"moon fiscal evidence exile rifle series neglect giant exclude banana glance frown kangaroo globe turtle hat fitness casual sudden select idle arctic best unlock",
|
||||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote",
|
||||
"5c8a1a284ab2844daf02cab322df3996574c9d53cbd36159c493441990f0d2a6bc9bc1502e3a067943d8ec67324663cbfb9667b57fed220e3f28335e26a90f93",
|
||||
|
||||
"449ea2d7249c6e0d8d295424fb8894cf",
|
||||
"choice barrel artefact cram increase sell veteran matrix mirror hollow walk pave",
|
||||
"1083fa24dbb0afa4e7b327d23f666567",
|
||||
"awesome cabin matrix resist april sponsor paddle gossip split will off soon",
|
||||
"467406b36a0176e40e013393e5ecef1f5b4019980b502eda9db1db06f7786e088b206f045f2bfcf93bd3b17a598335b078fcc5890115857ff741bd154b54f049",
|
||||
|
||||
"75fc3f44a7ff8e2b8af05aa18bded3827a3796df406763dd",
|
||||
"crack outside teach chat praise client manual scorpion predict chalk decrease casino lunch garbage enable ball when bamboo",
|
||||
"d8cbcd1ac2153ecd74048480c2732f637d642b21f0dd40df",
|
||||
"sugar fury effort loud fault grit source mountain liar bean slim shoulder stone better march brick dolphin zero",
|
||||
"f60180ea5047659cbb17ed6ef79c974de86c0170c7a1962b205329eb8fe9dcdd148615d35c515c4ec8da25f4cf54d5b7cd8cd5bf8dc4059df3a7900ca25f8306",
|
||||
|
||||
"1cce2f8c2c6a7f2d8473ebf1c32ce13b36737835d7a8768f44dcf96d64782c0e",
|
||||
"muffin evoke all fiber night guard black quote neck expire dial tenant leisure have dragon neck notable peace captain insane nice uphold shine angry",
|
||||
"2952f95cefe041616f6f379ab649cf8b702ecf8e4acceaebdda4cc50e2bf1d7b",
|
||||
"citizen oak fire thank advice radar sad tragic one rather initial black actual guitar decrease flower turtle galaxy hard obvious athlete garbage invest have",
|
||||
"eff4b6a15bb55fcf4bbfa2b3b9e24e7dc4bed8319ef7703f1786d472c73666922925778eaa5a06f8a26d2c7e7240be746fd69edfaf197e0dae12d7e0b550cfc8",
|
||||
|
||||
"3daa82dd08bd144ec9fb9f77c6ece3d2",
|
||||
"foil dawn net enroll turtle bird vault trumpet service fun immune unveil",
|
||||
"f5e82717078a6ddc538a03e825f91bed",
|
||||
"vote donkey shift audit plug until evolve document trial cool eight swarm",
|
||||
"83dad22293225780a914083fc1a69bfe1d910f5b5962b0364820132a42ae1bd567a1fb4d5a19ad3d64539e38a7ee3d6429fac2b74e72b020913131c5eadb7db4",
|
||||
|
||||
"9720239c0039f8446d44334daec325f3c24b3a490315d6d9",
|
||||
"damp all desert dash insane pear debate easily soup enough goddess make friend plug violin pact wealth insect",
|
||||
"16b59b6a426f2f302f73049a32ab8572394278982212357a",
|
||||
"birth proud surround luggage very object saddle gauge olive next throw tongue neither detail gauge drastic cube strategy",
|
||||
"38ceb07e0dad221f612631843be6ae44a650aaf789c8ebea9313e07498d7864385227d25c7a8268a5b850367eef31639632e9218acadead20980b864b1cd477e",
|
||||
|
||||
"fe58c6644bc3fad95832d4400cea0cce208c8b19bb4734a26995440b7fae7600",
|
||||
"wet sniff asthma once gap enrich pumpkin define trust rude gesture keen grass fine emerge census immense smooth ritual spirit rescue problem beef choice",
|
||||
"95b6cb48c7bc9c2a54496ae3eea790824b57e52b9637058f084555bc1b809b2f",
|
||||
"noble rent split month six benefit eye coil token inside tomorrow afraid rely verb purity shoulder airport joke bacon problem script scare hole trumpet",
|
||||
"e33e3d32e467877596a18ac60050488a0ec1557fda6bf95bad3d33d964c5e99dcd97d378403cc2723ed1c85c12b42bc59f15458d970d7a9d015f556109c146b0",
|
||||
|
||||
"99fe82c94edadffe75e1cc64cbd7ada7",
|
||||
"thing real emerge verify domain cloud lens teach travel radio effort glad",
|
||||
"7f93397f750f70a26513de2732ed95ee",
|
||||
"legend oil garlic tube warfare eye nephew knock cheese number grace tackle",
|
||||
"7f92ad63e4cdf4f15c23740556ad81e7f8cbd67cc672c93894c9c0d4fb171539eed5ab29f366570ed9940b816f45a539c3816f7ac19511794b752c5c1ec0e732",
|
||||
|
||||
"4fd6e8d06d55b4700130f8f462f7f9bfc6188da83e3faadb",
|
||||
"diary opinion lobster code orange odor insane permit spirit evolve upset final antique grant friend dutch say enroll",
|
||||
"14c29fe840dd1c9f05d392ba13e4e1466b32ed0726a15f89",
|
||||
"below belt wheel like spike exhibit blanket inch ring palace debate mimic rebel isolate broken stage garbage enhance",
|
||||
"7bae6e54f8bad645f18f574b310bd3e6fde126dabcaf63a889940380e4798810e48c8151fc56bb2389c07498deacef025f03cbf8fc57ea3ec68f6421b0fcb649",
|
||||
|
||||
"7a547fb59606e89ba88188013712946f6cb31c3e0ca606a7ee1ff23f57272c63",
|
||||
"layer owner legal stadium glance oyster element spell episode eager wagon stand pride old defense black print junior fade easy topic ready galaxy debris",
|
||||
"cb30610d175ffeab8357d5190d31923997752a7f9815087bfcad5eb0b43f6468",
|
||||
"sleep loan drive concert zoo fiction ask wide boil hat goose industry jar news wrist actor anchor that clip runway area cabbage museum abuse",
|
||||
"b922030609e7626696b9cf5ca4c06cd99290be30b1052770f6a60c5f26532d178f287a4285d7a2add2845dc89a816b26fdba1c830067d130740f64c0ab5cfbe1",
|
||||
|
||||
"e5fc62d20e0e5d9b2756e8d4d91cbb80",
|
||||
"flat make unit discover rifle armed unit acquire group panel nerve want",
|
||||
"a30b50a5439dcd1774f412ea5ec33403",
|
||||
"perfect fold citizen mango system merry stable liquid tumble voyage snack alter",
|
||||
"aae175f26848370c4d5d3d0640597e2bf1b28e95908dd877259b3eac5d71ffe3140739a3ed80180f88159571df84441985620e6b2fb0696e5cba1aa7b8d10b98",
|
||||
|
||||
"d29be791a9e4b6a48ff79003dbf31d6afabdc4290a273765",
|
||||
"absurd valve party disorder basket injury make blanket vintage ancient please random theory cart retire odor borrow belt",
|
||||
"70044da2175ad681d0ebbf2da83cf407eb9c8fd91fc0a8c9",
|
||||
"hybrid carbon hammer concert pulp domain dry jewel color draft dial average right elevator good way potato energy",
|
||||
"a3dffe3a31a2e949d1b04af7495a5b59db17e41d93b985feeaaae89260a9c86c6dcdf7cb32eaba61c2f4f0340f0f17d1ebb67af11657286b2ffd66ec4e05a8b7",
|
||||
|
||||
"c87c135433c16f1ecbf9919dc53dd9f30f85824dc7264d4e1bd644826c902be2",
|
||||
"upper will wisdom term once bean blur inquiry used bamboo frequent hamster amazing cake attack any author mimic leopard day token joy install company",
|
||||
"0e0bab4df9669b97ba3f75a50b2e92423bbe6e91a1b01dbbf3ba200a917c9106",
|
||||
"asthma front square version have slim trophy upgrade pink floor pig love room dance educate current buffalo test update divorce poverty salad dune scheme",
|
||||
"2eb4d85fbd8deaf9b06bf9cdb3e5f36e8da040d110312075eb32e776fc8e505b94be3e63c1525ad41f5e5968a263853001dc7c40ea3af8e8b0cfb7effd5f408c",
|
||||
};
|
||||
private MnemonicCode mc;
|
||||
|
||||
@ -112,43 +135,42 @@ public class MnemonicCodeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeVectors() throws Exception {
|
||||
for (int ii = 0; ii < vectors.length; ii += 2) {
|
||||
List<String> words = mc.encode(Hex.decode(vectors[ii]));
|
||||
assertEquals(vectors[ii + 1], Joiner.on(' ').join(words));
|
||||
}
|
||||
}
|
||||
public void testVectors() throws Exception {
|
||||
for (int ii = 0; ii < vectors.length; ii += 3) {
|
||||
String vecData = vectors[ii];
|
||||
String vecCode = vectors[ii+1];
|
||||
String vecSeed = vectors[ii+2];
|
||||
|
||||
@Test
|
||||
public void testDecodeVectors() throws Exception {
|
||||
for (int ii = 0; ii < vectors.length; ii += 2) {
|
||||
byte[] seed = mc.decode(split(vectors[ii+1]));
|
||||
assertEquals(vectors[ii], new String(Hex.encode(seed)));
|
||||
List<String> code = mc.toMnemonic(Hex.decode(vecData));
|
||||
byte[] seed = MnemonicCode.toSeed(code, "TREZOR");
|
||||
|
||||
assertEquals(vecCode, Joiner.on(' ').join(code));
|
||||
assertEquals(vecSeed, new String(Hex.encode(seed)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = MnemonicLengthException.class)
|
||||
public void testBadSeedLength() throws Exception {
|
||||
byte[] seed = Hex.decode("7f7f7f7f7f7f7f7f7f7f7f7f7f7f");
|
||||
mc.encode(seed);
|
||||
public void testBadEntropyLength() throws Exception {
|
||||
byte[] entropy = Hex.decode("7f7f7f7f7f7f7f7f7f7f7f7f7f7f");
|
||||
mc.toMnemonic(entropy);
|
||||
}
|
||||
|
||||
@Test(expected = MnemonicLengthException.class)
|
||||
public void testBadLength() throws Exception {
|
||||
List<String> words = split("risk tiger venture dinner age assume float denial penalty");
|
||||
mc.decode(words);
|
||||
List<String> words = split("risk tiger venture dinner age assume float denial penalty hello");
|
||||
mc.check(words);
|
||||
}
|
||||
|
||||
@Test(expected = MnemonicWordException.class)
|
||||
public void testBadWord() throws Exception {
|
||||
List<String> words = split("risk tiger venture dinner xyzzy assume float denial penalty hello game wing");
|
||||
mc.decode(words);
|
||||
mc.check(words);
|
||||
}
|
||||
|
||||
@Test(expected = MnemonicChecksumException.class)
|
||||
public void testBadChecksum() throws Exception {
|
||||
List<String> words = split("risk tiger venture dinner age assume float denial penalty hello game game");
|
||||
mc.decode(words);
|
||||
List<String> words = split("bless cloud wheel regular tiny venue bird web grief security dignity zoo");
|
||||
mc.check(words);
|
||||
}
|
||||
|
||||
static public List<String> split(String words) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user