electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit cef75e9e7ba3bf96415c2dac9e2e53a3c198f096
parent 1df007483e4c402cfcd8da098fd425142d9d3bcc
Author: ThomasV <thomasv@gitorious>
Date:   Sat, 13 Sep 2014 19:31:05 +0200

new seed_version: remove whitespaces only between CJK characters

Diffstat:
Mgui/qt/installwizard.py | 5++---
Mlib/bitcoin.py | 2+-
Mlib/mnemonic.py | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Mlib/version.py | 2+-
4 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py @@ -16,7 +16,7 @@ from amountedit import AmountEdit import sys import threading from electrum.plugins import run_hook - +from electrum.mnemonic import prepare_seed MSG_ENTER_ANYTHING = _("Please enter a wallet seed, a master public key, a list of Bitcoin addresses, or a list of private keys") MSG_SHOW_MPK = _("This is your master public key") @@ -114,8 +114,7 @@ class InstallWizard(QDialog): r = self.enter_seed_dialog(MSG_VERIFY_SEED, sid, func) if not r: return - - if r != seed: + if prepare_seed(r) != prepare_seed(seed): QMessageBox.warning(None, _('Error'), _('Incorrect seed'), _('OK')) return False else: diff --git a/lib/bitcoin.py b/lib/bitcoin.py @@ -150,7 +150,7 @@ hmac_sha_512 = lambda x,y: hmac.new(x, y, hashlib.sha512).digest() def is_new_seed(x, prefix=version.SEED_BIP44): import mnemonic - x = mnemonic.Mnemonic.prepare_seed(x) + x = mnemonic.prepare_seed(x) s = hmac_sha_512("Seed version", x.encode('utf8')).encode('hex') return s.startswith(prefix) diff --git a/lib/mnemonic.py b/lib/mnemonic.py @@ -32,6 +32,60 @@ from bitcoin import is_old_seed, is_new_seed import version +# http://www.asahi-net.or.jp/~ax2s-kmtn/ref/unicode/e_asia.html +CJK_INTERVALS = [ + (0x4E00, 0x9FFF, 'CJK Unified Ideographs'), + (0x3400, 0x4DBF, 'CJK Unified Ideographs Extension A'), + (0x20000, 0x2A6DF, 'CJK Unified Ideographs Extension B'), + (0x2A700, 0x2B73F, 'CJK Unified Ideographs Extension C'), + (0x2B740, 0x2B81F, 'CJK Unified Ideographs Extension D'), + (0xF900, 0xFAFF, 'CJK Compatibility Ideographs'), + (0x2F800, 0x2FA1D, 'CJK Compatibility Ideographs Supplement'), + (0x3190, 0x319F , 'Kanbun'), + (0x2E80, 0x2EFF, 'CJK Radicals Supplement'), + (0x2F00, 0x2FDF, 'CJK Radicals'), + (0x31C0, 0x31EF, 'CJK Strokes'), + (0x2FF0, 0x2FFF, 'Ideographic Description Characters'), + (0xE0100, 0xE01EF, 'Variation Selectors Supplement'), + (0x3100, 0x312F, 'Bopomofo'), + (0x31A0, 0x31BF, 'Bopomofo Extended'), + (0xFF00, 0xFFEF, 'Halfwidth and Fullwidth Forms'), + (0x3040, 0x309F, 'Hiragana'), + (0x30A0, 0x30FF, 'Katakana'), + (0x31F0, 0x31FF, 'Katakana Phonetic Extensions'), + (0x1B000, 0x1B0FF, 'Kana Supplement'), + (0xAC00, 0xD7AF, 'Hangul Syllables'), + (0x1100, 0x11FF, 'Hangul Jamo'), + (0xA960, 0xA97F, 'Hangul Jamo Extended A'), + (0xD7B0, 0xD7FF, 'Hangul Jamo Extended B'), + (0x3130, 0x318F, 'Hangul Compatibility Jamo'), + (0xA4D0, 0xA4FF, 'Lisu'), + (0x16F00, 0x16F9F, 'Miao'), + (0xA000, 0xA48F, 'Yi Syllables'), + (0xA490, 0xA4CF, 'Yi Radicals'), +] + +def is_CJK(c): + n = ord(c) + for imin,imax,name in CJK_INTERVALS: + if n>=imin and n<=imax: return True + return False + + +def prepare_seed(seed): + # normalize + seed = unicodedata.normalize('NFKD', unicode(seed)) + # lower + seed = seed.lower() + # remove accents + seed = u''.join([c for c in seed if not unicodedata.combining(c)]) + # normalize whitespaces + seed = u' '.join(seed.split()) + # remove whitespaces between CJK + seed = u''.join([seed[i] for i in range(len(seed)) if not (seed[i] in string.whitespace and is_CJK(seed[i-1]) and is_CJK(seed[i+1]))]) + return seed + + filenames = { 'en':'english.txt', 'es':'spanish.txt', @@ -63,19 +117,9 @@ class Mnemonic(object): @classmethod def mnemonic_to_seed(self, mnemonic, passphrase): PBKDF2_ROUNDS = 2048 - mnemonic = self.prepare_seed(mnemonic) + mnemonic = prepare_seed(mnemonic) return pbkdf2.PBKDF2(mnemonic, 'mnemonic' + passphrase, iterations = PBKDF2_ROUNDS, macmodule = hmac, digestmodule = hashlib.sha512).read(64) - @classmethod - def prepare_seed(self, seed): - # normalize - seed = unicodedata.normalize('NFKD', unicode(seed)) - # lower - seed = seed.lower() - # remove accents and whitespaces - seed = u''.join([c for c in seed if not unicodedata.combining(c) and not c in string.whitespace]) - return seed - def mnemonic_encode(self, i): n = len(self.wordlist) words = [] @@ -120,4 +164,3 @@ class Mnemonic(object): break print_error('%d words'%len(seed.split())) return seed - diff --git a/lib/version.py b/lib/version.py @@ -1,6 +1,6 @@ ELECTRUM_VERSION = "2.0" # version of the client package PROTOCOL_VERSION = '0.9' # protocol version requested -NEW_SEED_VERSION = 9 # electrum versions >= 2.0 +NEW_SEED_VERSION = 10 # electrum versions >= 2.0 OLD_SEED_VERSION = 4 # electrum versions < 2.0