Skip to content
Snippets Groups Projects
Commit eb6f18fa authored by inso's avatar inso
Browse files

Using pylibscrypt : easy to integrate in cxfreeze, fast and reliable !

parent d7cfc4bf
No related branches found
No related tags found
No related merge requests found
......@@ -6,7 +6,7 @@ Ucoin public and private keys
import base58
import base64
from .scrypt import hash
from pylibscrypt import scrypt
from libnacl.sign import Signer as NaclSigningKey
......@@ -17,15 +17,22 @@ SCRYPT_PARAMS = {'N': 4096,
'p': 1
}
def _ensure_bytes(data):
if isinstance(data, str):
return bytes(data, 'utf-8')
return data
class SigningKey(NaclSigningKey):
def __init__(self, salt, password):
seed = hash(password, salt,
salt = _ensure_bytes(salt)
password = _ensure_bytes(password)
seed = scrypt(password, salt,
SCRYPT_PARAMS['N'], SCRYPT_PARAMS['r'], SCRYPT_PARAMS['p'],
SEED_LENGTH)
super().__init__(seed)
self.pubkey = Base58Encoder.encoder(self.vk)
self.pubkey = Base58Encoder.encode(self.vk)
class Base58Encoder(object):
@staticmethod
......
# The MIT License (MIT)
#
# Copyright (c) 2014 Richard Moore
#
# 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.
import hashlib
import hmac
def salsa20_8(B):
'''Salsa 20/8 stream cypher; Used by BlockMix. See http://en.wikipedia.org/wiki/Salsa20'''
# Create a working copy
x = B[:]
# Expanded form of this code. The expansion is significantly faster but
# this is much easier to understand
# ROUNDS = (
# (4, 0, 12, 7), (8, 4, 0, 9), (12, 8, 4, 13), (0, 12, 8, 18),
# (9, 5, 1, 7), (13, 9, 5, 9), (1, 13, 9, 13), (5, 1, 13, 18),
# (14, 10, 6, 7), (2, 14, 10, 9), (6, 2, 14, 13), (10, 6, 2, 18),
# (3, 15, 11, 7), (7, 3, 15, 9), (11, 7, 3, 13), (15, 11, 7, 18),
# (1, 0, 3, 7), (2, 1, 0, 9), (3, 2, 1, 13), (0, 3, 2, 18),
# (6, 5, 4, 7), (7, 6, 5, 9), (4, 7, 6, 13), (5, 4, 7, 18),
# (11, 10, 9, 7), (8, 11, 10, 9), (9, 8, 11, 13), (10, 9, 8, 18),
# (12, 15, 14, 7), (13, 12, 15, 9), (14, 13, 12, 13), (15, 14, 13, 18),
# )
#
# for (destination, a1, a2, b) in ROUNDS:
# a = (x[a1] + x[a2]) & 0xffffffff
# x[destination] ^= ((a << b) | (a >> (32 - b))) & 0xffffffff
for i in (8, 6, 4, 2):
a = (x[0] + x[12]) & 0xffffffff
x[4] ^= ((a << 7) | (a >> 25))
a = (x[4] + x[0]) & 0xffffffff
x[8] ^= ((a << 9) | (a >> 23))
a = (x[8] + x[4]) & 0xffffffff
x[12] ^= ((a << 13) | (a >> 19))
a = (x[12] + x[8]) & 0xffffffff
x[0] ^= ((a << 18) | (a >> 14))
a = (x[5] + x[1]) & 0xffffffff
x[9] ^= ((a << 7) | (a >> 25))
a = (x[9] + x[5]) & 0xffffffff
x[13] ^= ((a << 9) | (a >> 23))
a = (x[13] + x[9]) & 0xffffffff
x[1] ^= ((a << 13) | (a >> 19))
a = (x[1] + x[13]) & 0xffffffff
x[5] ^= ((a << 18) | (a >> 14))
a = (x[10] + x[6]) & 0xffffffff
x[14] ^= ((a << 7) | (a >> 25))
a = (x[14] + x[10]) & 0xffffffff
x[2] ^= ((a << 9) | (a >> 23))
a = (x[2] + x[14]) & 0xffffffff
x[6] ^= ((a << 13) | (a >> 19))
a = (x[6] + x[2]) & 0xffffffff
x[10] ^= ((a << 18) | (a >> 14))
a = (x[15] + x[11]) & 0xffffffff
x[3] ^= ((a << 7) | (a >> 25))
a = (x[3] + x[15]) & 0xffffffff
x[7] ^= ((a << 9) | (a >> 23))
a = (x[7] + x[3]) & 0xffffffff
x[11] ^= ((a << 13) | (a >> 19))
a = (x[11] + x[7]) & 0xffffffff
x[15] ^= ((a << 18) | (a >> 14))
a = (x[0] + x[3]) & 0xffffffff
x[1] ^= ((a << 7) | (a >> 25))
a = (x[1] + x[0]) & 0xffffffff
x[2] ^= ((a << 9) | (a >> 23))
a = (x[2] + x[1]) & 0xffffffff
x[3] ^= ((a << 13) | (a >> 19))
a = (x[3] + x[2]) & 0xffffffff
x[0] ^= ((a << 18) | (a >> 14))
a = (x[5] + x[4]) & 0xffffffff
x[6] ^= ((a << 7) | (a >> 25))
a = (x[6] + x[5]) & 0xffffffff
x[7] ^= ((a << 9) | (a >> 23))
a = (x[7] + x[6]) & 0xffffffff
x[4] ^= ((a << 13) | (a >> 19))
a = (x[4] + x[7]) & 0xffffffff
x[5] ^= ((a << 18) | (a >> 14))
a = (x[10] + x[9]) & 0xffffffff
x[11] ^= ((a << 7) | (a >> 25))
a = (x[11] + x[10]) & 0xffffffff
x[8] ^= ((a << 9) | (a >> 23))
a = (x[8] + x[11]) & 0xffffffff
x[9] ^= ((a << 13) | (a >> 19))
a = (x[9] + x[8]) & 0xffffffff
x[10] ^= ((a << 18) | (a >> 14))
a = (x[15] + x[14]) & 0xffffffff
x[12] ^= ((a << 7) | (a >> 25))
a = (x[12] + x[15]) & 0xffffffff
x[13] ^= ((a << 9) | (a >> 23))
a = (x[13] + x[12]) & 0xffffffff
x[14] ^= ((a << 13) | (a >> 19))
a = (x[14] + x[13]) & 0xffffffff
x[15] ^= ((a << 18) | (a >> 14))
# Add the original values
for i in range(0, 16):
B[i] = (B[i] + x[i]) & 0xffffffff
def blockmix_salsa8(BY, Yi, r):
'''Blockmix; Used by SMix.'''
start = (2 * r - 1) * 16
X = BY[start:start + 16] # BlockMix - 1
for i in range(0, 2 * r): # BlockMix - 2
for xi in range(0, 16): # BlockMix - 3(inner)
X[xi] ^= BY[i * 16 + xi]
salsa20_8(X) # BlockMix - 3(outer)
aod = Yi + i * 16 # BlockMix - 4
BY[aod:aod + 16] = X[:16]
for i in range(0, r): # BlockMix - 6 (and below)
aos = Yi + i * 32
aod = i * 16
BY[aod:aod + 16] = BY[aos:aos + 16]
for i in range(0, r):
aos = Yi + (i * 2 + 1) * 16
aod = (i + r) * 16
BY[aod:aod + 16] = BY[aos:aos + 16]
def smix(B, Bi, r, N, V, X):
'''SMix; a specific case of ROMix. See scrypt.pdf in the links above.'''
X[:32 * r] = B[Bi:Bi + 32 * r] # ROMix - 1
for i in range(0, N): # ROMix - 2
aod = i * 32 * r # ROMix - 3
V[aod:aod + 32 * r] = X[:32 * r]
blockmix_salsa8(X, 32 * r, r) # ROMix - 4
for i in range(0, N): # ROMix - 6
j = X[(2 * r - 1) * 16] & (N - 1) # ROMix - 7
for xi in range(0, 32 * r): # ROMix - 8(inner)
X[xi] ^= V[j * 32 * r + xi]
blockmix_salsa8(X, 32 * r, r) # ROMix - 9(outer)
B[Bi:Bi + 32 * r] = X[:32 * r] # ROMix - 10
def hash(password, salt, N, r, p, dkLen):
"""Returns the result of the scrypt password-based key derivation function.
Constraints:
r * p < (2 ** 30)
dkLen <= (((2 ** 32) - 1) * 32
N must be a power of 2 greater than 1 (eg. 2, 4, 8, 16, 32...)
N, r, p must be positive
"""
# Scrypt implementation. Significant thanks to https://github.com/wg/scrypt
if N < 2 or (N & (N - 1)): raise ValueError('Scrypt N must be a power of 2 greater than 1')
# convert into integers
B = hashlib.pbkdf2_hmac("sha256", password, salt, 1, p * 128 * r)
B = [ ((B[i + 3] << 24) | (B[i + 2] << 16) | (B[i + 1] << 8) | B[i + 0]) for i in range(0, len(B), 4)]
XY = [ 0 ] * (64 * r)
V = [ 0 ] * (32 * r * N)
for i in range(0, p):
smix(B, i * 32 * r, r, N, V, XY)
# Convert back into bytes
Bc = [ ]
for i in B:
Bc.append((i >> 0) & 0xff)
Bc.append((i >> 8) & 0xff)
Bc.append((i >> 16) & 0xff)
Bc.append((i >> 24) & 0xff)
Bc = bytearray(Bc)
return hashlib.pbkdf2_hmac("sha256", password, Bc, 1, dkLen)
#return hashlib.pbkdf2(password, ''.join(chr(c) for c in Bc), 1, dkLen, prf)
......@@ -14,7 +14,7 @@ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), 'src')))
print(sys.path)
includes = ["sip", "re", "json", "logging", "hashlib", "os", "urllib", "ucoinpy", "requests", "cutecoin.core"]
excludes = []
packages = ["libnacl"]
packages = ["libnacl", "pylibscrypt"]
includefiles = []
options = {"path": sys.path,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment