3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-31 15:22:16 +00:00

Added Mnemonic{Length,Word,Checksum}Exception and tests for each case.

This commit is contained in:
Ken Sedgwick 2013-11-29 19:29:55 -08:00 committed by Mike Hearn
parent 69f52c1b8a
commit 5cd10a537a
5 changed files with 136 additions and 9 deletions

View File

@ -0,0 +1,35 @@
/*
* Copyright 2013 Ken Sedgwick
*
* 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.google.bitcoin.crypto;
/**
* Thrown when a list of MnemonicCode words fails the checksum check.
*/
@SuppressWarnings("serial")
public class MnemonicChecksumException extends Exception {
public MnemonicChecksumException(String msg) {
super(msg);
}
public MnemonicChecksumException(Exception e) {
super(e);
}
public MnemonicChecksumException(String msg, Exception e) {
super(msg, e);
}
}

View File

@ -86,12 +86,12 @@ public class MnemonicCode {
/**
* Encodes a 128, 192 or 256 bit seed into a list of words.
*/
public List<String> encode(byte[] seed) throws IllegalArgumentException {
public List<String> encode(byte[] seed) throws MnemonicLengthException {
// 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 IllegalArgumentException("seed not 128, 192 or 256 bits");
throw new MnemonicLengthException("seed not 128, 192 or 256 bits");
// 3. Encrypt input data 10000x with Rijndael (ECB mode).
// Set key to SHA256 hash of string ("mnemonic" + user_password).
@ -134,12 +134,12 @@ public class MnemonicCode {
/**
* Decodes a list of words into a seed value.
*/
public byte[] decode(List<String> words) throws IllegalArgumentException {
public byte[] decode(List<String> words) throws MnemonicLengthException, MnemonicWordException, MnemonicChecksumException {
int nwords = words.size();
// 2. Make sure the number of words is 12, 18 or 24.
if (nwords != 12 && nwords != 18 && nwords != 24)
throw new IllegalArgumentException("Mnemonic code not 12, 18 or 24 words");
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;
@ -149,7 +149,7 @@ public class MnemonicCode {
// Find the words index in the wordlist.
int ndx = Collections.binarySearch(this.wordList, word);
if (ndx < 0)
throw new IllegalArgumentException("\"" + word + "\" invalid");
throw new MnemonicWordException("\"" + word + "\" invalid", word);
// Set the next 11 bits to the value of the index.
for (int ii = 0; ii < 11; ++ii)
@ -172,7 +172,7 @@ public class MnemonicCode {
// 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 IllegalArgumentException("checksum error");
throw new MnemonicChecksumException("checksum error");
// 8. Treat B as binary data.
byte[] outdata = new byte[bblen / 8];

View File

@ -0,0 +1,35 @@
/*
* Copyright 2013 Ken Sedgwick
*
* 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.google.bitcoin.crypto;
/**
* Thrown when an argument to MnemonicCode is the wrong length.
*/
@SuppressWarnings("serial")
public class MnemonicLengthException extends Exception {
public MnemonicLengthException(String msg) {
super(msg);
}
public MnemonicLengthException(Exception e) {
super(e);
}
public MnemonicLengthException(String msg, Exception e) {
super(msg, e);
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright 2013 Ken Sedgwick
*
* 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.google.bitcoin.crypto;
/**
* Thrown when a word is encountered which is not in the MnemonicCode's word list.
*/
@SuppressWarnings("serial")
public class MnemonicWordException extends Exception {
/** Contains the word that was not found in the word list. */
public String badWord;
public MnemonicWordException(String msg, String badWord) {
super(msg);
this.badWord = badWord;
}
public MnemonicWordException(String badWord, Exception e) {
super(e);
this.badWord = badWord;
}
public MnemonicWordException(String msg, String badWord, Exception e) {
super(msg, e);
this.badWord = badWord;
}
public String getBadWord() {
return badWord;
}
}

View File

@ -127,18 +127,30 @@ public class MnemonicCodeTest {
}
}
@Test(expected = IllegalArgumentException.class)
@Test(expected = MnemonicLengthException.class)
public void testBadSeedLength() throws Exception {
byte[] seed = Hex.decode("7f7f7f7f7f7f7f7f7f7f7f7f7f7f");
mc.encode(seed);
}
@Test(expected = IllegalArgumentException.class)
public void testBadWordsLength() throws Exception {
@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);
}
@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);
}
@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);
}
static public List<String> split(String words) {
return new ArrayList<String>(Arrays.asList(words.split("\\s+")));
}