diff --git a/core/src/main/java/com/google/bitcoin/crypto/MnemonicCode.java b/core/src/main/java/com/google/bitcoin/crypto/MnemonicCode.java
new file mode 100644
index 00000000..382b8915
--- /dev/null
+++ b/core/src/main/java/com/google/bitcoin/crypto/MnemonicCode.java
@@ -0,0 +1,230 @@
+/*
+ * 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;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.ByteBuffer;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.spongycastle.crypto.engines.RijndaelEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+
+import com.google.bitcoin.core.Sha256Hash;
+
+/**
+ * A MnemonicCode object may be used to convert between binary seed values and
+ * lists of words per the BIP 39
+ * specification
+ *
+ * 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 {
+
+ private ArrayList wordList;
+
+ public static String BIP0039_ENGLISH_SHA256 =
+ "ad90bf3beb7b0eb7e5acd74727dc0da96e0a280a258354e7293fb7e211ac03db";
+
+ /**
+ * Creates an MnemonicCode object, initializing with words read
+ * from the supplied input stream. If a wordListDigest is
+ * supplied the digest of the words will be checked.
+ */
+ public MnemonicCode(InputStream wordstream, String wordListDigest)
+ throws IOException, IllegalArgumentException {
+ BufferedReader br = new BufferedReader(new InputStreamReader(wordstream, "UTF-8"));
+ String word;
+ this.wordList = new ArrayList();
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("SHA-256");
+ } catch (NoSuchAlgorithmException ex) {
+ throw new RuntimeException(ex); // Can't happen.
+ }
+ while ((word = br.readLine()) != null) {
+ md.update(word.getBytes());
+ this.wordList.add(word);
+ }
+ br.close();
+
+ if (this.wordList.size() != 2048)
+ throw new IllegalArgumentException("input stream did not contain 2048 words");
+
+ // If a wordListDigest is supplied check to make sure it matches.
+ if (wordListDigest != null) {
+ byte[] digest = md.digest();
+ String hexdigest = new String(Hex.encode(digest));
+ if (!hexdigest.equals(wordListDigest))
+ throw new IllegalArgumentException("wordlist digest mismatch");
+ }
+ }
+
+ /**
+ * Encodes a 128, 192 or 256 bit seed into a list of words.
+ */
+ public List encode(byte[] seed) throws IllegalArgumentException {
+
+ // 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");
+
+ // 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);
+
+ // 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;
+
+ // 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 words = new ArrayList();
+ int nwords = ee.length / 11;
+ for (int ii = 0; ii < nwords; ++ii) {
+ int ndx = 0;
+ for (int kk = 0; kk < 11; ++kk) {
+ ndx <<= 1;
+ if (ee[(ii * 11) + kk])
+ ndx |= 0x1;
+ }
+ words.add(this.wordList.get(ndx));
+ }
+
+ return words;
+ }
+
+ /**
+ * Decodes a list of words into a seed value.
+ */
+ public byte[] decode(List words) throws IllegalArgumentException {
+ 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");
+
+ // 3. Figure out word indexes in a dictionary and output them as binary stream E.
+ int len = nwords * 11;
+ boolean[] ee = new boolean[len];
+ int wordindex = 0;
+ for (String word : words) {
+ // Find the words index in the wordlist.
+ int ndx = Collections.binarySearch(this.wordList, word);
+ if (ndx < 0)
+ throw new IllegalArgumentException("\"" + word + "\" invalid");
+
+ // 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;
+ ++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;
+
+ 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 IllegalArgumentException("checksum error");
+
+ // 8. Treat B as binary data.
+ byte[] outdata = new byte[bblen / 8];
+ for (int ii = 0; ii < outdata.length; ++ii)
+ for (int jj = 0; jj < 8; ++jj)
+ if (bb[(ii * 8) + jj])
+ outdata[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);
+
+ return seed;
+ }
+
+ 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();
+ RijndaelEngine cipher = new RijndaelEngine(len);
+ cipher.init(true, new KeyParameter(key));
+ for (int ii = 0; ii < 10000; ++ii)
+ cipher.processBlock(data, 0, data, 0);
+ return data;
+ }
+
+ 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();
+ RijndaelEngine cipher = new RijndaelEngine(len);
+ cipher.init(false, new KeyParameter(key));
+ for (int ii = 0; ii < 10000; ++ii)
+ cipher.processBlock(data, 0, data, 0);
+ return data;
+ }
+
+ 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;
+ }
+}
diff --git a/core/src/main/resources/com/google/bitcoin/crypto/mnemonic/wordlist/english.txt b/core/src/main/resources/com/google/bitcoin/crypto/mnemonic/wordlist/english.txt
new file mode 100644
index 00000000..942040ed
--- /dev/null
+++ b/core/src/main/resources/com/google/bitcoin/crypto/mnemonic/wordlist/english.txt
@@ -0,0 +1,2048 @@
+abandon
+ability
+able
+about
+above
+absent
+absorb
+abstract
+absurd
+abuse
+access
+accident
+account
+accuse
+achieve
+acid
+acoustic
+acquire
+across
+act
+action
+actor
+actress
+actual
+adapt
+add
+addict
+address
+adjust
+admit
+adult
+advance
+advice
+aerobic
+affair
+afford
+afraid
+again
+age
+agent
+agree
+ahead
+aim
+air
+airport
+aisle
+alarm
+album
+alcohol
+alert
+alien
+all
+alley
+allow
+almost
+alone
+alpha
+already
+also
+alter
+always
+amateur
+amazing
+among
+amount
+amused
+analyst
+anchor
+ancient
+anger
+angle
+angry
+animal
+ankle
+announce
+annual
+another
+answer
+antenna
+antique
+anxiety
+any
+apart
+apology
+appear
+apple
+approve
+april
+arch
+arctic
+area
+arena
+argue
+arm
+armed
+armor
+army
+around
+arrange
+arrest
+arrive
+arrow
+art
+artefact
+artist
+artwork
+ask
+aspect
+assault
+asset
+assist
+assume
+asthma
+athlete
+atom
+attack
+attend
+attitude
+attract
+auction
+audit
+august
+aunt
+author
+auto
+autumn
+average
+avocado
+avoid
+awake
+aware
+away
+awesome
+awful
+awkward
+axis
+baby
+bachelor
+bacon
+badge
+bag
+balance
+balcony
+ball
+bamboo
+banana
+banner
+bar
+barely
+bargain
+barrel
+base
+basic
+basket
+battle
+beach
+bean
+beauty
+because
+become
+beef
+before
+begin
+behave
+behind
+believe
+below
+belt
+bench
+benefit
+best
+betray
+better
+between
+beyond
+bicycle
+bid
+bike
+bind
+biology
+bird
+birth
+bitter
+black
+blade
+blame
+blanket
+blast
+bleak
+bless
+blind
+blood
+blossom
+blouse
+blue
+blur
+blush
+board
+boat
+body
+boil
+bomb
+bone
+bonus
+book
+boost
+border
+boring
+borrow
+boss
+bottom
+bounce
+box
+boy
+bracket
+brain
+brand
+brass
+brave
+bread
+breeze
+brick
+bridge
+brief
+bright
+bring
+brisk
+broccoli
+broken
+bronze
+broom
+brother
+brown
+brush
+bubble
+buddy
+budget
+buffalo
+build
+bulb
+bulk
+bullet
+bundle
+bunker
+burden
+burger
+burst
+bus
+business
+busy
+butter
+buyer
+buzz
+cabbage
+cabin
+cable
+cactus
+cage
+cake
+call
+calm
+camera
+camp
+can
+canal
+cancel
+candy
+cannon
+canoe
+canvas
+canyon
+capable
+capital
+captain
+car
+carbon
+card
+cargo
+carpet
+carry
+cart
+case
+cash
+casino
+castle
+casual
+cat
+catalog
+catch
+category
+cattle
+caught
+cause
+caution
+cave
+ceiling
+celery
+cement
+census
+century
+cereal
+certain
+chair
+chalk
+champion
+change
+chaos
+chapter
+charge
+chase
+chat
+cheap
+check
+cheese
+chef
+cherry
+chest
+chicken
+chief
+child
+chimney
+choice
+choose
+chronic
+chuckle
+chunk
+churn
+cigar
+cinnamon
+circle
+citizen
+city
+civil
+claim
+clap
+clarify
+claw
+clay
+clean
+clerk
+clever
+click
+client
+cliff
+climb
+clinic
+clip
+clock
+clog
+close
+cloth
+cloud
+clown
+club
+clump
+cluster
+clutch
+coach
+coast
+coconut
+code
+coffee
+coil
+coin
+collect
+color
+column
+combine
+come
+comfort
+comic
+common
+company
+concert
+conduct
+confirm
+congress
+connect
+consider
+control
+convince
+cook
+cool
+copper
+copy
+coral
+core
+corn
+correct
+cost
+cotton
+couch
+country
+couple
+course
+cousin
+cover
+coyote
+crack
+cradle
+craft
+cram
+crane
+crash
+crater
+crawl
+crazy
+cream
+credit
+creek
+crew
+cricket
+crime
+crisp
+critic
+crop
+cross
+crouch
+crowd
+crucial
+cruel
+cruise
+crumble
+crunch
+crush
+cry
+crystal
+cube
+culture
+cup
+cupboard
+curious
+current
+curtain
+curve
+cushion
+custom
+cute
+cycle
+dad
+damage
+damp
+dance
+danger
+daring
+dash
+daughter
+dawn
+day
+deal
+debate
+debris
+decade
+december
+decide
+decline
+decorate
+decrease
+deer
+defense
+define
+defy
+degree
+delay
+deliver
+demand
+demise
+denial
+dentist
+deny
+depart
+depend
+deposit
+depth
+deputy
+derive
+describe
+desert
+design
+desk
+despair
+destroy
+detail
+detect
+develop
+device
+devote
+diagram
+dial
+diamond
+diary
+dice
+diesel
+diet
+differ
+digital
+dignity
+dilemma
+dinner
+dinosaur
+direct
+dirt
+disagree
+discover
+disease
+dish
+dismiss
+disorder
+display
+distance
+divert
+divide
+divorce
+dizzy
+doctor
+document
+dog
+doll
+dolphin
+domain
+donate
+donkey
+donor
+door
+dose
+double
+dove
+draft
+dragon
+drama
+drastic
+draw
+dream
+dress
+drift
+drill
+drink
+drip
+drive
+drop
+drum
+dry
+duck
+dumb
+dune
+during
+dust
+dutch
+duty
+dwarf
+dynamic
+eager
+eagle
+early
+earn
+earth
+easily
+east
+easy
+echo
+ecology
+economy
+edge
+edit
+educate
+effort
+egg
+eight
+either
+elbow
+elder
+electric
+elegant
+element
+elephant
+elevator
+elite
+else
+embark
+embody
+embrace
+emerge
+emotion
+employ
+empower
+empty
+enable
+enact
+end
+endless
+endorse
+enemy
+energy
+enforce
+engage
+engine
+enhance
+enjoy
+enlist
+enough
+enrich
+enroll
+ensure
+enter
+entire
+entry
+envelope
+episode
+equal
+equip
+era
+erase
+erode
+erosion
+error
+erupt
+escape
+essay
+essence
+estate
+eternal
+ethics
+evidence
+evil
+evoke
+evolve
+exact
+example
+excess
+exchange
+excite
+exclude
+excuse
+execute
+exercise
+exhaust
+exhibit
+exile
+exist
+exit
+exotic
+expand
+expect
+expire
+explain
+expose
+express
+extend
+extra
+eye
+eyebrow
+fabric
+face
+faculty
+fade
+faint
+faith
+fall
+false
+fame
+family
+famous
+fan
+fancy
+fantasy
+farm
+fashion
+fat
+fatal
+father
+fatigue
+fault
+favorite
+feature
+february
+federal
+fee
+feed
+feel
+female
+fence
+festival
+fetch
+fever
+few
+fiber
+fiction
+field
+figure
+file
+film
+filter
+final
+find
+fine
+finger
+finish
+fire
+firm
+first
+fiscal
+fish
+fit
+fitness
+fix
+flag
+flame
+flash
+flat
+flavor
+flee
+flight
+flip
+float
+flock
+floor
+flower
+fluid
+flush
+fly
+foam
+focus
+fog
+foil
+fold
+follow
+food
+foot
+force
+forest
+forget
+fork
+fortune
+forum
+forward
+fossil
+foster
+found
+fox
+fragile
+frame
+frequent
+fresh
+friend
+fringe
+frog
+front
+frost
+frown
+frozen
+fruit
+fuel
+fun
+funny
+furnace
+fury
+future
+gadget
+gain
+galaxy
+gallery
+game
+gap
+garage
+garbage
+garden
+garlic
+garment
+gas
+gasp
+gate
+gather
+gauge
+gaze
+general
+genius
+genre
+gentle
+genuine
+gesture
+ghost
+giant
+gift
+giggle
+ginger
+giraffe
+girl
+give
+glad
+glance
+glare
+glass
+glide
+glimpse
+globe
+gloom
+glory
+glove
+glow
+glue
+goat
+goddess
+gold
+good
+goose
+gorilla
+gospel
+gossip
+govern
+gown
+grab
+grace
+grain
+grant
+grape
+grass
+gravity
+great
+green
+grid
+grief
+grit
+grocery
+group
+grow
+grunt
+guard
+guess
+guide
+guilt
+guitar
+gun
+gym
+habit
+hair
+half
+hammer
+hamster
+hand
+happy
+harbor
+hard
+harsh
+harvest
+hat
+have
+hawk
+hazard
+head
+health
+heart
+heavy
+hedgehog
+height
+hello
+helmet
+help
+hen
+hero
+hidden
+high
+hill
+hint
+hip
+hire
+history
+hobby
+hockey
+hold
+hole
+holiday
+hollow
+home
+honey
+hood
+hope
+horn
+horror
+horse
+hospital
+host
+hotel
+hour
+hover
+hub
+huge
+human
+humble
+humor
+hundred
+hungry
+hunt
+hurdle
+hurry
+hurt
+husband
+hybrid
+ice
+icon
+idea
+identify
+idle
+ignore
+ill
+illegal
+illness
+image
+imitate
+immense
+immune
+impact
+impose
+improve
+impulse
+inch
+include
+income
+increase
+index
+indicate
+indoor
+industry
+infant
+inflict
+inform
+inhale
+inherit
+initial
+inject
+injury
+inmate
+inner
+innocent
+input
+inquiry
+insane
+insect
+inside
+inspire
+install
+intact
+interest
+into
+invest
+invite
+involve
+iron
+island
+isolate
+issue
+item
+ivory
+jacket
+jaguar
+jar
+jazz
+jealous
+jeans
+jelly
+jewel
+job
+join
+joke
+journey
+joy
+judge
+juice
+jump
+jungle
+junior
+junk
+just
+kangaroo
+keen
+keep
+ketchup
+key
+kick
+kid
+kidney
+kind
+kingdom
+kiss
+kit
+kitchen
+kite
+kitten
+kiwi
+knee
+knife
+knock
+know
+lab
+label
+labor
+ladder
+lady
+lake
+lamp
+language
+laptop
+large
+later
+latin
+laugh
+laundry
+lava
+law
+lawn
+lawsuit
+layer
+lazy
+leader
+leaf
+learn
+leave
+lecture
+left
+leg
+legal
+legend
+leisure
+lemon
+lend
+length
+lens
+leopard
+lesson
+letter
+level
+liar
+liberty
+library
+license
+life
+lift
+light
+like
+limb
+limit
+link
+lion
+liquid
+list
+little
+live
+lizard
+load
+loan
+lobster
+local
+lock
+logic
+lonely
+long
+loop
+lottery
+loud
+lounge
+love
+loyal
+lucky
+luggage
+lumber
+lunar
+lunch
+luxury
+lyrics
+machine
+mad
+magic
+magnet
+maid
+mail
+main
+major
+make
+mammal
+man
+manage
+mandate
+mango
+mansion
+manual
+maple
+marble
+march
+margin
+marine
+market
+marriage
+mask
+mass
+master
+match
+material
+math
+matrix
+matter
+maximum
+maze
+meadow
+mean
+measure
+meat
+mechanic
+medal
+media
+melody
+melt
+member
+memory
+mention
+menu
+mercy
+merge
+merit
+merry
+mesh
+message
+metal
+method
+middle
+midnight
+milk
+million
+mimic
+mind
+minimum
+minor
+minute
+miracle
+mirror
+misery
+miss
+mistake
+mix
+mixed
+mixture
+mobile
+model
+modify
+mom
+moment
+monitor
+monkey
+monster
+month
+moon
+moral
+more
+morning
+mosquito
+mother
+motion
+motor
+mountain
+mouse
+move
+movie
+much
+muffin
+mule
+multiply
+muscle
+museum
+mushroom
+music
+must
+mutual
+myself
+mystery
+myth
+naive
+name
+napkin
+narrow
+nasty
+nation
+nature
+near
+neck
+need
+negative
+neglect
+neither
+nephew
+nerve
+nest
+net
+network
+neutral
+never
+news
+next
+nice
+night
+noble
+noise
+nominee
+noodle
+normal
+north
+nose
+notable
+note
+nothing
+notice
+novel
+now
+nuclear
+number
+nurse
+nut
+oak
+obey
+object
+oblige
+obscure
+observe
+obtain
+obvious
+occur
+ocean
+october
+odor
+off
+offer
+office
+often
+oil
+okay
+old
+olive
+olympic
+omit
+once
+one
+onion
+online
+only
+open
+opera
+opinion
+oppose
+option
+orange
+orbit
+orchard
+order
+ordinary
+organ
+orient
+original
+orphan
+ostrich
+other
+outdoor
+outer
+output
+outside
+oval
+oven
+over
+own
+owner
+oxygen
+oyster
+ozone
+pact
+paddle
+page
+pair
+palace
+palm
+panda
+panel
+panic
+panther
+paper
+parade
+parent
+park
+parrot
+party
+pass
+patch
+path
+patient
+patrol
+pattern
+pause
+pave
+payment
+peace
+peanut
+pear
+peasant
+pelican
+pen
+penalty
+pencil
+people
+pepper
+perfect
+permit
+person
+pet
+phone
+photo
+phrase
+physical
+piano
+picnic
+picture
+piece
+pig
+pigeon
+pill
+pilot
+pink
+pioneer
+pipe
+pistol
+pitch
+pizza
+place
+planet
+plastic
+plate
+play
+please
+pledge
+pluck
+plug
+plunge
+poem
+poet
+point
+polar
+pole
+police
+pond
+pony
+pool
+popular
+portion
+position
+possible
+post
+potato
+pottery
+poverty
+powder
+power
+practice
+praise
+predict
+prefer
+prepare
+present
+pretty
+prevent
+price
+pride
+primary
+print
+priority
+prison
+private
+prize
+problem
+process
+produce
+profit
+program
+project
+promote
+proof
+property
+prosper
+protect
+proud
+provide
+public
+pudding
+pull
+pulp
+pulse
+pumpkin
+punch
+pupil
+puppy
+purchase
+purity
+purpose
+purse
+push
+put
+puzzle
+pyramid
+quality
+quantum
+quarter
+question
+quick
+quit
+quiz
+quote
+rabbit
+raccoon
+race
+rack
+radar
+radio
+rail
+rain
+raise
+rally
+ramp
+ranch
+random
+range
+rapid
+rare
+rate
+rather
+raven
+raw
+razor
+ready
+real
+reason
+rebel
+rebuild
+recall
+receive
+recipe
+record
+recycle
+reduce
+reflect
+reform
+refuse
+region
+regret
+regular
+reject
+relax
+release
+relief
+rely
+remain
+remember
+remind
+remove
+render
+renew
+rent
+reopen
+repair
+repeat
+replace
+report
+require
+rescue
+resemble
+resist
+resource
+response
+result
+retire
+retreat
+return
+reunion
+reveal
+review
+reward
+rhythm
+rib
+ribbon
+rice
+rich
+ride
+ridge
+rifle
+right
+rigid
+ring
+riot
+ripple
+risk
+ritual
+rival
+river
+road
+roast
+robot
+robust
+rocket
+romance
+roof
+rookie
+room
+rose
+rotate
+rough
+round
+route
+royal
+rubber
+rude
+rug
+rule
+run
+runway
+rural
+sad
+saddle
+sadness
+safe
+sail
+salad
+salmon
+salon
+salt
+salute
+same
+sample
+sand
+satisfy
+satoshi
+sauce
+sausage
+save
+say
+scale
+scan
+scare
+scatter
+scene
+scheme
+school
+science
+scissors
+scorpion
+scout
+scrap
+screen
+script
+scrub
+sea
+search
+season
+seat
+second
+secret
+section
+security
+seed
+seek
+segment
+select
+sell
+seminar
+senior
+sense
+sentence
+series
+service
+session
+settle
+setup
+seven
+shadow
+shaft
+shallow
+share
+shed
+shell
+sheriff
+shield
+shift
+shine
+ship
+shiver
+shock
+shoe
+shoot
+shop
+short
+shoulder
+shove
+shrimp
+shrug
+shuffle
+shy
+sibling
+sick
+side
+siege
+sight
+sign
+silent
+silk
+silly
+silver
+similar
+simple
+since
+sing
+siren
+sister
+situate
+six
+size
+skate
+sketch
+ski
+skill
+skin
+skirt
+skull
+slab
+slam
+sleep
+slender
+slice
+slide
+slight
+slim
+slogan
+slot
+slow
+slush
+small
+smart
+smile
+smoke
+smooth
+snack
+snake
+snap
+sniff
+snow
+soap
+soccer
+social
+sock
+soda
+soft
+solar
+soldier
+solid
+solution
+solve
+someone
+song
+soon
+sorry
+sort
+soul
+sound
+soup
+source
+south
+space
+spare
+spatial
+spawn
+speak
+special
+speed
+spell
+spend
+sphere
+spice
+spider
+spike
+spin
+spirit
+split
+spoil
+sponsor
+spoon
+sport
+spot
+spray
+spread
+spring
+spy
+square
+squeeze
+squirrel
+stable
+stadium
+staff
+stage
+stairs
+stamp
+stand
+start
+state
+stay
+steak
+steel
+stem
+step
+stereo
+stick
+still
+sting
+stock
+stomach
+stone
+stool
+story
+stove
+strategy
+street
+strike
+strong
+struggle
+student
+stuff
+stumble
+style
+subject
+submit
+subway
+success
+such
+sudden
+suffer
+sugar
+suggest
+suit
+summer
+sun
+sunny
+sunset
+super
+supply
+supreme
+sure
+surface
+surge
+surprise
+surround
+survey
+suspect
+sustain
+swallow
+swamp
+swap
+swarm
+swear
+sweet
+swift
+swim
+swing
+switch
+sword
+symbol
+symptom
+syrup
+system
+table
+tackle
+tag
+tail
+talent
+talk
+tank
+tape
+target
+task
+taste
+tattoo
+taxi
+teach
+team
+tell
+ten
+tenant
+tennis
+tent
+term
+test
+text
+thank
+that
+theme
+then
+theory
+there
+they
+thing
+this
+thought
+three
+thrive
+throw
+thumb
+thunder
+ticket
+tide
+tiger
+tilt
+timber
+time
+tiny
+tip
+tired
+tissue
+title
+toast
+tobacco
+today
+toddler
+toe
+together
+toilet
+token
+tomato
+tomorrow
+tone
+tongue
+tonight
+tool
+tooth
+top
+topic
+topple
+torch
+tornado
+tortoise
+toss
+total
+tourist
+toward
+tower
+town
+toy
+track
+trade
+traffic
+tragic
+train
+transfer
+trap
+trash
+travel
+tray
+treat
+tree
+trend
+trial
+tribe
+trick
+trigger
+trim
+trip
+trophy
+trouble
+truck
+true
+truly
+trumpet
+trust
+truth
+try
+tube
+tuition
+tumble
+tuna
+tunnel
+turkey
+turn
+turtle
+twelve
+twenty
+twice
+twin
+twist
+two
+type
+typical
+ugly
+umbrella
+unable
+unaware
+uncle
+uncover
+under
+undo
+unfair
+unfold
+unhappy
+uniform
+unique
+unit
+universe
+unknown
+unlock
+until
+unusual
+unveil
+update
+upgrade
+uphold
+upon
+upper
+upset
+urban
+urge
+usage
+use
+used
+useful
+useless
+usual
+utility
+vacant
+vacuum
+vague
+valid
+valley
+valve
+van
+vanish
+vapor
+various
+vast
+vault
+vehicle
+velvet
+vendor
+venture
+venue
+verb
+verify
+version
+very
+vessel
+veteran
+viable
+vibrant
+vicious
+victory
+video
+view
+village
+vintage
+violin
+virtual
+virus
+visa
+visit
+visual
+vital
+vivid
+vocal
+voice
+void
+volcano
+volume
+vote
+voyage
+wage
+wagon
+wait
+walk
+wall
+walnut
+want
+warfare
+warm
+warrior
+wash
+wasp
+waste
+water
+wave
+way
+wealth
+weapon
+wear
+weasel
+weather
+web
+wedding
+weekend
+weird
+welcome
+west
+wet
+whale
+what
+wheat
+wheel
+when
+where
+whip
+whisper
+wide
+width
+wife
+wild
+will
+win
+window
+wine
+wing
+wink
+winner
+winter
+wire
+wisdom
+wise
+wish
+witness
+wolf
+woman
+wonder
+wood
+wool
+word
+work
+world
+worry
+worth
+wrap
+wreck
+wrestle
+wrist
+write
+wrong
+yard
+year
+yellow
+you
+young
+youth
+zebra
+zero
+zone
+zoo
diff --git a/core/src/test/java/com/google/bitcoin/crypto/MnemonicCodeTest.java b/core/src/test/java/com/google/bitcoin/crypto/MnemonicCodeTest.java
new file mode 100644
index 00000000..d20e0aa2
--- /dev/null
+++ b/core/src/test/java/com/google/bitcoin/crypto/MnemonicCodeTest.java
@@ -0,0 +1,177 @@
+/*
+ * 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;
+
+import org.junit.Test;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.spongycastle.util.encoders.Hex;
+
+import static org.junit.Assert.assertEquals;
+
+public class MnemonicCodeTest {
+
+ // These vectors are from https://raw.github.com/trezor/python-mnemonic/master/vectors.json
+ String vectors[] = {
+
+ "00000000000000000000000000000000",
+ "risk tiger venture dinner age assume float denial penalty hello game wing",
+
+ "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
+ "truth chase learn pretty right casual acoustic frozen betray main slogan method",
+
+ "80808080808080808080808080808080",
+ "olive garment twenty drill people finish hat own usual level milk usage",
+
+ "ffffffffffffffffffffffffffffffff",
+ "laundry faint system client frog vanish plug shell slot cable large embrace",
+
+ "000000000000000000000000000000000000000000000000",
+ "giant twelve seat embark ostrich jazz leader lunch budget hover much weapon vendor build truth garden year list",
+
+ "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
+ "awful faint gun mean fuel side slogan marine glad donkey velvet oyster movie real type digital dress federal",
+
+ "808080808080808080808080808080808080808080808080",
+ "bless carpet daughter animal hospital pave faculty escape fortune song sign twin unknown bread mobile normal agent use",
+
+ "ffffffffffffffffffffffffffffffffffffffffffffffff",
+ "saddle curve flight drama client resemble venture arch will ordinary enrich clutch razor shallow trophy tumble dice outer",
+
+ "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",
+
+ "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",
+
+ "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",
+
+ "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",
+
+ "449ea2d7249c6e0d8d295424fb8894cf",
+ "choice barrel artefact cram increase sell veteran matrix mirror hollow walk pave",
+
+ "75fc3f44a7ff8e2b8af05aa18bded3827a3796df406763dd",
+ "crack outside teach chat praise client manual scorpion predict chalk decrease casino lunch garbage enable ball when bamboo",
+
+ "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",
+
+ "3daa82dd08bd144ec9fb9f77c6ece3d2",
+ "foil dawn net enroll turtle bird vault trumpet service fun immune unveil",
+
+ "9720239c0039f8446d44334daec325f3c24b3a490315d6d9",
+ "damp all desert dash insane pear debate easily soup enough goddess make friend plug violin pact wealth insect",
+
+ "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",
+
+ "99fe82c94edadffe75e1cc64cbd7ada7",
+ "thing real emerge verify domain cloud lens teach travel radio effort glad",
+
+ "4fd6e8d06d55b4700130f8f462f7f9bfc6188da83e3faadb",
+ "diary opinion lobster code orange odor insane permit spirit evolve upset final antique grant friend dutch say enroll",
+
+ "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",
+
+ "e5fc62d20e0e5d9b2756e8d4d91cbb80",
+ "flat make unit discover rifle armed unit acquire group panel nerve want",
+
+ "d29be791a9e4b6a48ff79003dbf31d6afabdc4290a273765",
+ "absurd valve party disorder basket injury make blanket vintage ancient please random theory cart retire odor borrow belt",
+
+ "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",
+ };
+
+ @Test
+ public void testEncodeVectors() throws Exception {
+ InputStream wordstream = getClass().getResourceAsStream("mnemonic/wordlist/english.txt");
+ MnemonicCode mc = new MnemonicCode(wordstream, MnemonicCode.BIP0039_ENGLISH_SHA256);
+
+ for (int ii = 0; ii < vectors.length; ii += 2) {
+ List words = mc.encode(Hex.decode(vectors[ii]));
+ assertEquals(vectors[ii+1], join(words));
+ }
+ }
+
+ @Test
+ public void testDecodeVectors() throws Exception {
+ InputStream wordstream = getClass().getResourceAsStream("mnemonic/wordlist/english.txt");
+ MnemonicCode mc = new MnemonicCode(wordstream, MnemonicCode.BIP0039_ENGLISH_SHA256);
+
+ 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)));
+ }
+ }
+
+ @Test
+ public void testBadSeedLength() throws Exception {
+ InputStream wordstream = getClass().getResourceAsStream("mnemonic/wordlist/english.txt");
+ MnemonicCode mc = new MnemonicCode(wordstream, MnemonicCode.BIP0039_ENGLISH_SHA256);
+
+ boolean sawException = false;
+ try {
+ byte[] seed = Hex.decode("7f7f7f7f7f7f7f7f7f7f7f7f7f7f");
+ List words = mc.encode(seed);
+ } catch (IllegalArgumentException ex) {
+ sawException = true;
+ }
+ assertEquals(true, sawException);
+ }
+
+ @Test
+ public void testBadWordsLength() throws Exception {
+ InputStream wordstream = getClass().getResourceAsStream("mnemonic/wordlist/english.txt");
+ MnemonicCode mc = new MnemonicCode(wordstream, MnemonicCode.BIP0039_ENGLISH_SHA256);
+
+ boolean sawException = false;
+ try {
+ List words = split("risk tiger venture dinner age assume float denial penalty");
+ byte[] seed = mc.decode(words);
+ } catch (IllegalArgumentException ex) {
+ sawException = true;
+ }
+ assertEquals(true, sawException);
+ }
+
+ static public String join(List 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();
+ }
+
+ static public List split(String words) {
+ return new ArrayList(Arrays.asList(words.split("\\s+")));
+ }
+}