[Python-modules-commits] [python-mnemonic] 02/09: Import python-mnemonic_0.18.orig.tar.gz
Tristan Seligmann
mithrandi at moszumanska.debian.org
Mon Dec 11 10:44:06 UTC 2017
This is an automated email from the git hooks/post-receive script.
mithrandi pushed a commit to branch master
in repository python-mnemonic.
commit 2b411870744c9e5f524bb63a49f3fb8e17b2e891
Author: Tristan Seligmann <mithrandi at mithrandi.net>
Date: Mon Dec 11 11:04:43 2017 +0200
Import python-mnemonic_0.18.orig.tar.gz
---
LICENSE | 21 +++++++++++++
MANIFEST.in | 1 +
PKG-INFO | 4 +--
mnemonic.egg-info/PKG-INFO | 4 +--
mnemonic.egg-info/SOURCES.txt | 2 ++
mnemonic/mnemonic.py | 72 +++++++++++++++++++++++++++++++++----------
mnemonic/secretsharing.py | 18 +++++++----
mnemonic/shamir.py | 1 +
setup.py | 6 ++--
9 files changed, 99 insertions(+), 30 deletions(-)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..b135744
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-2016 Pavol Rusnak
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..1aba38f
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+include LICENSE
diff --git a/PKG-INFO b/PKG-INFO
index 8de08a0..bb35071 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,10 +1,10 @@
Metadata-Version: 1.1
Name: mnemonic
-Version: 0.15
+Version: 0.18
Summary: Implementation of Bitcoin BIP-0039
Home-page: https://github.com/trezor/python-mnemonic
Author: Bitcoin TREZOR
-Author-email: info at bitcointrezor.com
+Author-email: info at trezor.io
License: UNKNOWN
Description: UNKNOWN
Platform: UNKNOWN
diff --git a/mnemonic.egg-info/PKG-INFO b/mnemonic.egg-info/PKG-INFO
index 8de08a0..bb35071 100644
--- a/mnemonic.egg-info/PKG-INFO
+++ b/mnemonic.egg-info/PKG-INFO
@@ -1,10 +1,10 @@
Metadata-Version: 1.1
Name: mnemonic
-Version: 0.15
+Version: 0.18
Summary: Implementation of Bitcoin BIP-0039
Home-page: https://github.com/trezor/python-mnemonic
Author: Bitcoin TREZOR
-Author-email: info at bitcointrezor.com
+Author-email: info at trezor.io
License: UNKNOWN
Description: UNKNOWN
Platform: UNKNOWN
diff --git a/mnemonic.egg-info/SOURCES.txt b/mnemonic.egg-info/SOURCES.txt
index a7f201e..ff35210 100644
--- a/mnemonic.egg-info/SOURCES.txt
+++ b/mnemonic.egg-info/SOURCES.txt
@@ -1,3 +1,5 @@
+LICENSE
+MANIFEST.in
README.rst
setup.py
mnemonic/__init__.py
diff --git a/mnemonic/mnemonic.py b/mnemonic/mnemonic.py
index 374f11b..2ec6c3d 100644
--- a/mnemonic/mnemonic.py
+++ b/mnemonic/mnemonic.py
@@ -1,5 +1,6 @@
#
# Copyright (c) 2013 Pavol Rusnak
+# Copyright (c) 2017 mruddy
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
@@ -31,20 +32,23 @@ from pbkdf2 import PBKDF2
PBKDF2_ROUNDS = 2048
+
class ConfigurationError(Exception):
pass
+
# From <http://tinyurl.com/p54ocsk>
-def binary_search(a, x, lo=0, hi=None): # can't use a to specify default for hi
- hi = hi if hi is not None else len(a) # hi defaults to len(a)
- pos = bisect.bisect_left(a, x, lo, hi) # find insertion position
- return (pos if pos != hi and a[pos] == x else -1) # don't walk off the end
+def binary_search(a, x, lo=0, hi=None): # can't use a to specify default for hi
+ hi = hi if hi is not None else len(a) # hi defaults to len(a)
+ pos = bisect.bisect_left(a, x, lo, hi) # find insertion position
+ return (pos if pos != hi and a[pos] == x else -1) # don't walk off the end
+
class Mnemonic(object):
def __init__(self, language):
self.radix = 2048
with open('%s/%s.txt' % (self._get_directory(), language), 'r') as f:
- self.wordlist = [w.strip() for w in f.readlines()]
+ self.wordlist = [w.strip().decode('utf8') if sys.version < '3' else w.strip() for w in f.readlines()]
if len(self.wordlist) != self.radix:
raise ConfigurationError('Wordlist should contain %d words, but it contains %d words.' % (self.radix, len(self.wordlist)))
@@ -69,6 +73,7 @@ class Mnemonic(object):
@classmethod
def detect_language(cls, code):
+ code = cls.normalize_string(code)
first = code.split(' ')[0]
languages = cls.list_languages()
@@ -80,24 +85,28 @@ class Mnemonic(object):
raise ConfigurationError("Language not detected")
def generate(self, strength=128):
- if strength % 32 > 0:
- raise ValueError('Strength should be divisible by 32, but it is not (%d).' % strength)
+ if strength not in [128, 160, 192, 224, 256]:
+ raise ValueError('Strength should be one of the following [128, 160, 192, 224, 256], but it is not (%d).' % strength)
return self.to_mnemonic(os.urandom(strength // 8))
# Adapted from <http://tinyurl.com/oxmn476>
def to_entropy(self, words):
if not isinstance(words, list):
words = words.split(' ')
- if len(words) % 3 > 0:
- raise ValueError('Word list size must be multiple of three words.')
+ if len(words) not in [12, 15, 18, 21, 24]:
+ raise ValueError('Number of words must be one of the following: [12, 15, 18, 21, 24], but it is not (%d).' % len(words))
# Look up all the words in the list and construct the
# concatenation of the original entropy and the checksum.
concatLenBits = len(words) * 11
concatBits = [False] * concatLenBits
wordindex = 0
+ if self.detect_language(' '.join(words)) == 'english':
+ use_binary_search = True
+ else:
+ use_binary_search = False
for word in words:
# Find the words index in the wordlist
- ndx = binary_search(self.wordlist, word)
+ ndx = binary_search(self.wordlist, word) if use_binary_search else self.wordlist.index(word)
if ndx < 0:
raise LookupError('Unable to find "%s" in word list.' % word)
# Set the next 11 bits to the value of the index.
@@ -125,8 +134,8 @@ class Mnemonic(object):
return entropy
def to_mnemonic(self, data):
- if len(data) % 4 > 0:
- raise ValueError('Data length in bits should be divisible by 32, but it is not (%d bytes = %d bits).' % (len(data), len(data) * 8))
+ if len(data) not in [16, 20, 24, 28, 32]:
+ raise ValueError('Data length should be one of the following: [16, 20, 24, 28, 32], but it is not (%d).' % len(data))
h = hashlib.sha256(data).hexdigest()
b = bin(int(binascii.hexlify(data), 16))[2:].zfill(len(data) * 8) + \
bin(int(h, 16))[2:].zfill(256)[:len(data) * 8 // 32]
@@ -134,16 +143,14 @@ class Mnemonic(object):
for i in range(len(b) // 11):
idx = int(b[i * 11:(i + 1) * 11], 2)
result.append(self.wordlist[idx])
- if self.detect_language(' '.join(result)) == 'japanese': # Japanese must be joined by ideographic space.
- result_phrase = u'\xe3\x80\x80'.join(result)
+ if self.detect_language(' '.join(result)) == 'japanese': # Japanese must be joined by ideographic space.
+ result_phrase = u'\u3000'.join(result)
else:
result_phrase = ' '.join(result)
return result_phrase
def check(self, mnemonic):
- if self.detect_language(mnemonic.replace(u'\xe3\x80\x80', ' ')) == 'japanese':
- mnemonic = mnemonic.replace(u'\xe3\x80\x80', ' ') # Japanese will likely input with ideographic space.
- mnemonic = mnemonic.split(' ')
+ mnemonic = self.normalize_string(mnemonic).split(' ')
if len(mnemonic) % 3 > 0:
return False
try:
@@ -158,8 +165,39 @@ class Mnemonic(object):
nh = bin(int(hashlib.sha256(nd).hexdigest(), 16))[2:].zfill(256)[:l // 33]
return h == nh
+ def expand_word(self, prefix):
+ if prefix in self.wordlist:
+ return prefix
+ else:
+ matches = [word for word in self.wordlist if word.startswith(prefix)]
+ if len(matches) == 1: # matched exactly one word in the wordlist
+ return matches[0]
+ else:
+ # exact match not found.
+ # this is not a validation routine, just return the input
+ return prefix
+
+ def expand(self, mnemonic):
+ return ' '.join(map(self.expand_word, mnemonic.split(' ')))
+
@classmethod
def to_seed(cls, mnemonic, passphrase=''):
mnemonic = cls.normalize_string(mnemonic)
passphrase = cls.normalize_string(passphrase)
return PBKDF2(mnemonic, u'mnemonic' + passphrase, iterations=PBKDF2_ROUNDS, macmodule=hmac, digestmodule=hashlib.sha512).read(64)
+
+
+def main():
+ import binascii
+ import sys
+ if len(sys.argv) > 1:
+ data = sys.argv[1]
+ else:
+ data = sys.stdin.readline().strip()
+ data = binascii.unhexlify(data)
+ m = Mnemonic('english')
+ print(m.to_mnemonic(data))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/mnemonic/secretsharing.py b/mnemonic/secretsharing.py
index 1a71b33..0c77dce 100644
--- a/mnemonic/secretsharing.py
+++ b/mnemonic/secretsharing.py
@@ -9,6 +9,7 @@
from random import randint
+
def egcd(a, b):
if a == 0:
return (b, 0, 1)
@@ -16,6 +17,7 @@ def egcd(a, b):
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
+
def mod_inverse(k, prime):
k = k % prime
if k < 0:
@@ -24,6 +26,7 @@ def mod_inverse(k, prime):
r = egcd(prime, k)[2]
return (prime + r) % prime
+
def random_polynomial(degree, intercept, upper_bound):
""" Generates a random polynomial with positive coefficients.
"""
@@ -31,16 +34,17 @@ def random_polynomial(degree, intercept, upper_bound):
raise ValueError('Degree must be a non-negative number.')
coefficients = [intercept]
for i in range(degree):
- random_coeff = randint(0, upper_bound-1)
+ random_coeff = randint(0, upper_bound - 1)
coefficients.append(random_coeff)
return coefficients
+
def get_polynomial_points(coefficients, num_points, prime):
""" Calculates the first n polynomial points.
[ (1, f(1)), (2, f(2)), ... (n, f(n)) ]
"""
points = []
- for x in range(1, num_points+1):
+ for x in range(1, num_points + 1):
# start with x=1 and calculate the value of y
y = coefficients[0]
# calculate each term and add it to y, using modular math
@@ -52,6 +56,7 @@ def get_polynomial_points(coefficients, num_points, prime):
points.append((x, y))
return points
+
def modular_lagrange_interpolation(x, points, prime):
# break the points up into lists of x and y values
x_values, y_values = zip(*points)
@@ -73,6 +78,7 @@ def modular_lagrange_interpolation(x, points, prime):
f_x = (prime + f_x + (y_values[i] * lagrange_polynomial)) % prime
return f_x
+
def secret_int_to_points(secret_int, point_threshold, num_points, prime):
""" Split a secret (integer) into shares (pair of integers / x,y coords).
@@ -85,10 +91,11 @@ def secret_int_to_points(secret_int, point_threshold, num_points, prime):
raise ValueError("Threshold must be < the total number of points.")
if secret_int > prime:
raise ValueError("Error! Secret is too long for share calculation!")
- coefficients = random_polynomial(point_threshold-1, secret_int, prime)
+ coefficients = random_polynomial(point_threshold - 1, secret_int, prime)
points = get_polynomial_points(coefficients, num_points, prime)
return points
+
def points_to_secret_int(points, prime):
""" Join int points into a secret int.
@@ -99,10 +106,9 @@ def points_to_secret_int(points, prime):
for point in points:
if not isinstance(point, tuple) and len(point) == 2:
raise ValueError("Each point must be a tuple of two values.")
- if not isinstance(point[0], int) and \
- isinstance(point[1], int):
+ if not isinstance(point[0], int) and isinstance(point[1], int):
raise ValueError("Each value in the point must be an int.")
x_values, y_values = zip(*points)
free_coefficient = modular_lagrange_interpolation(0, points, prime)
- secret_int = free_coefficient # the secret int is the free coefficient
+ secret_int = free_coefficient # the secret int is the free coefficient
return secret_int
diff --git a/mnemonic/shamir.py b/mnemonic/shamir.py
index 18bf082..0ad6625 100644
--- a/mnemonic/shamir.py
+++ b/mnemonic/shamir.py
@@ -24,6 +24,7 @@ import binascii
from .secretsharing import secret_int_to_points, points_to_secret_int
from .mnemonic import Mnemonic
+
class Shamir(object):
def __init__(self, language):
diff --git a/setup.py b/setup.py
index ea7020d..dea9c76 100755
--- a/setup.py
+++ b/setup.py
@@ -3,12 +3,12 @@ from setuptools import setup
setup(
name='mnemonic',
- version='0.15',
+ version='0.18',
author='Bitcoin TREZOR',
- author_email='info at bitcointrezor.com',
+ author_email='info at trezor.io',
description='Implementation of Bitcoin BIP-0039',
url='https://github.com/trezor/python-mnemonic',
- packages=['mnemonic',],
+ packages=['mnemonic', ],
package_data={'mnemonic': ['wordlist/*.txt']},
zip_safe=False,
install_requires=['pbkdf2'],
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-mnemonic.git
More information about the Python-modules-commits
mailing list