def encrypt(privkey, passphrase): """ BIP0038 non-ec-multiply encryption. Returns BIP0038 encrypted privkey. :param privkey: Private key :type privkey: Base58 :param str passphrase: UTF-8 encoded passphrase for encryption :return: BIP0038 non-ec-multiply encrypted wif key :rtype: Base58 """ privkeyhex = repr(privkey) # hex addr = format(privkey.uncompressed.address, "BTC") a = bytes(addr, 'ascii') salt = hashlib.sha256(hashlib.sha256(a).digest()).digest()[0:4] if "scrypt" in sys.modules: key = scrypt.hash(passphrase, salt, 16384, 8, 8) else: key = pylibscrypt.scrypt(bytes(passphrase, "utf-8"), salt, 16384, 8, 8) (derived_half1, derived_half2) = (key[:32], key[32:]) aes = AES.new(derived_half2) encrypted_half1 = _encrypt_xor(privkeyhex[:32], derived_half1[:16], aes) encrypted_half2 = _encrypt_xor(privkeyhex[32:], derived_half1[16:], aes) " flag byte is forced 0xc0 because Graphene only uses compressed keys " payload = (b'\x01' + b'\x42' + b'\xc0' + salt + encrypted_half1 + encrypted_half2) " Checksum " checksum = hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4] privatkey = hexlify(payload + checksum).decode('ascii') return Base58(privatkey)
def __init__(self, salt, password): 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.encode(self.vk)
def __init__(self, salt, password, scrypt_params=ScryptParams(4096,16,1)): 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.encode(self.vk)
def build_scrypt_key(passphrase, salt): coded_passphrase = struct.pack(">" + "H" * len(passphrase), *[ord(x) for x in passphrase]) return scrypt(coded_passphrase, salt, N=DEFAULT_N, r=DEFAULT_R, p=DEFAULT_P, olen=DEFAULT_DERIVED_KEY_LENGTH)
def __init__(self, email, password): salt = ('KeySwarm Profile Signature Key:'.join(email)).encode('utf-8') pw = password.encode('utf-8') hashed_pw = pyblake2.blake2s(pw).digest() seed = pylibscrypt.scrypt(hashed_pw, salt, 2**17, 8, 1, 32) self.private_key = ed25519.SigningKey(seed) #print("test: " + str(self.private_key.sign(b"hello world", encoding="base64"))) self.public_key = self.private_key.get_verifying_key() self.address = base58.b58encode( self.public_key.to_bytes() + pyblake2.blake2s(self.public_key.to_bytes(), 1).digest() ) print("Adress: ", (self.address).decode('utf-8'))
def from_ewif_hex(cls: Type[SigningKeyType], ewif_hex: str, password: str) -> SigningKeyType: """ Return SigningKey instance from Duniter EWIF in hexadecimal format :param ewif_hex: EWIF string in hexadecimal format :param password: Password of the encrypted seed """ ewif_bytes = Base58Encoder.decode(ewif_hex) if len(ewif_bytes) != 39: raise Exception("Error: the size of EWIF is invalid") # extract data fi = ewif_bytes[0:1] checksum_from_ewif = ewif_bytes[-2:] ewif_no_checksum = ewif_bytes[0:-2] salt = ewif_bytes[1:5] encryptedhalf1 = ewif_bytes[5:21] encryptedhalf2 = ewif_bytes[21:37] # check format flag if fi != b"\x02": raise Exception("Error: bad format version, not EWIF") # checksum control checksum = libnacl.crypto_hash_sha256(libnacl.crypto_hash_sha256(ewif_no_checksum))[0:2] if checksum_from_ewif != checksum: raise Exception("Error: bad checksum of the EWIF") # SCRYPT password_bytes = password.encode("utf-8") scrypt_seed = scrypt(password_bytes, salt, 16384, 8, 8, 64) derivedhalf1 = scrypt_seed[0:32] derivedhalf2 = scrypt_seed[32:64] # AES aes = pyaes.AESModeOfOperationECB(derivedhalf2) decryptedhalf1 = aes.decrypt(encryptedhalf1) decryptedhalf2 = aes.decrypt(encryptedhalf2) # XOR seed1 = xor_bytes(decryptedhalf1, derivedhalf1[0:16]) seed2 = xor_bytes(decryptedhalf2, derivedhalf1[16:32]) seed = bytes(seed1 + seed2) # Password Control signer = SigningKey(seed) salt_from_seed = libnacl.crypto_hash_sha256( libnacl.crypto_hash_sha256( Base58Encoder.decode(signer.pubkey)))[0:4] if salt_from_seed != salt: raise Exception("Error: bad Password of EWIF address") return cls(seed)
def encrypt(privkeyhex, addr, passphrase): a = bytes(addr, 'ascii') salt = hashlib.sha256(hashlib.sha256(a).digest()).digest()[0:4] key = scrypt.scrypt(bytes(passphrase, "utf-8"), salt, 16384, 8, 8) derived_half1, derived_half2 = key[:32], key[32:] aes = AES.new(derived_half2) encrypted_half1 = _encrypt_xor(privkeyhex[:32], derived_half1[:16], aes) encrypted_half2 = _encrypt_xor(privkeyhex[32:], derived_half1[16:], aes) payload = (b'\x01' + b'\x42' + b'\xc0' + salt + encrypted_half1 + encrypted_half2) checksum = hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4] privatkey = hexlify(payload + checksum).decode('ascii') return Base58(privatkey)
def generate(master_password, keyword, N=2 ** 15): # password: Your life depends on this one. I chose to comine 2 of my passwords -> 16 characters # salt: This should be unique per application. E.g. "gmail". # When you need a new just add a 1, then increment # N: Value above 2**14 is considered safe for interactive use # 2 ** 20 is used for non-interactive use # r: Memory factor, I chose 8 since it still works on relatively old phone (1G ram) # p: Factor for parallelism, everyone agrees p=1 is the best # dkLen: Argument in pyscrypt, olen: argument in pylibscrypt hashed = scrypt(ensure_input(master_password), ensure_input(keyword), N, 8, 1, 32) res = codecs.encode(hashed, 'hex').decode('utf-8')[:32] res = "!A" + res[:-2] return res
def to_json(self, pwd): salt = base64.b16encode(os.urandom(16)) pad = bytearray(pylibscrypt.scrypt(pwd, salt, olen=len(self.key))) key = bytearray(self.key) for i, p in enumerate(pad): key[i] = key[i] ^ p return json.dumps({ 'key': base64.b16encode(key), 'salt': salt, 'h_length': self.h_length, 'h_hash': self.h_hash, 't_timeout': self.t_timeout, 't_zero': self.t_zero, })
def save_ewif_file(self, path: str, password: str) -> None: """ Save an Encrypted Wallet Import Format file (WIF v2) :param path: Path to file :param password: """ # version version = 1 # add version to seed salt = libnacl.crypto_hash_sha256( libnacl.crypto_hash_sha256( Base58Encoder.decode(self.pubkey)))[0:4] # SCRYPT password_bytes = password.encode("utf-8") scrypt_seed = scrypt(password_bytes, salt, 16384, 8, 8, 64) derivedhalf1 = scrypt_seed[0:32] derivedhalf2 = scrypt_seed[32:64] # XOR seed1_xor_derivedhalf1_1 = bytes(xor_bytes(self.seed[0:16], derivedhalf1[0:16])) seed2_xor_derivedhalf1_2 = bytes(xor_bytes(self.seed[16:32], derivedhalf1[16:32])) # AES aes = pyaes.AESModeOfOperationECB(derivedhalf2) encryptedhalf1 = aes.encrypt(seed1_xor_derivedhalf1_1) encryptedhalf2 = aes.encrypt(seed2_xor_derivedhalf1_2) # add format to final seed (1=WIF,2=EWIF) seed_bytes = b'\x02' + salt + encryptedhalf1 + encryptedhalf2 # calculate checksum sha256_v1 = libnacl.crypto_hash_sha256(seed_bytes) sha256_v2 = libnacl.crypto_hash_sha256(sha256_v1) checksum = sha256_v2[0:2] # B58 encode final key string ewif_key = Base58Encoder.encode(seed_bytes + checksum) # save file with open(path, 'w') as fh: fh.write( """Type: EWIF Version: {version} Data: {data}""".format(version=version, data=ewif_key) )
def from_credentials(cls: Type[SigningKeyType], salt: Union[str, bytes], password: Union[str, bytes], scrypt_params: Optional[ScryptParams] = None) -> SigningKeyType: """ Create a SigningKey object from credentials :param salt: Secret salt passphrase credential :param password: Secret password credential :param scrypt_params: ScryptParams instance """ if scrypt_params is None: scrypt_params = ScryptParams() salt = ensure_bytes(salt) password = ensure_bytes(password) seed = scrypt(password, salt, scrypt_params.N, scrypt_params.r, scrypt_params.p, scrypt_params.seed_length) return cls(seed)
def from_passphrase(cls, email, passphrase): """ This performs key derivation from an email address and passphrase according to the miniLock specification. Specifically, the passphrase is digested with a standard blake2s 32-bit digest, then it is passed through scrypt with the email address as salt value using N = 217, r = 8, p = 1, L = 32. The 32-byte digest from scrypt is then used as the Private Key from which the public key is derived. """ pp_blake = pyblake2.blake2s(cls.ensure_bytes(passphrase)).digest() #pp_scrypt = scrypt.hash(pp_blake, cls.ensure_bytes(email), 2**17, 8, 1, 32) pp_scrypt = pylibscrypt.scrypt(pp_blake, cls.ensure_bytes(email), 2**17, 8, 1, 32) key = nacl.public.PrivateKey(pp_scrypt) return cls(key.public_key, key)
def __init__(self, salt, password, scrypt_params=None): """ Init a SigningKey object from credentials :param str salt: Secret salt passphrase credential :param str password: Secret password credential :param ScryptParams scrypt_params: ScryptParams instance """ if scrypt_params is None: scrypt_params = ScryptParams(4096, 16, 1) 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.encode(self.vk)
def __init__(self, salt: Union[str, bytes], password: Union[str, bytes], scrypt_params: Optional[ScryptParams] = None) -> None: """ Create SecretKey key pair instance from salt and password credentials :param salt: Salt credential :param password: Password credential :param scrypt_params: Optional ScriptParams instance """ if scrypt_params is None: scrypt_params = ScryptParams() salt = ensure_bytes(salt) password = ensure_bytes(password) seed = scrypt(password, salt, scrypt_params.N, scrypt_params.r, scrypt_params.p, scrypt_params.seed_length) super().__init__(seed) self.public_key = PublicKey(Base58Encoder.encode(self.pk))
def decrypt(encrypted_privkey, passphrase): """BIP0038 non-ec-multiply decryption. Returns WIF privkey. :param Base58 encrypted_privkey: Private key :param str passphrase: UTF-8 encoded passphrase for decryption :return: BIP0038 non-ec-multiply decrypted key :rtype: Base58 :raises SaltException: if checksum verification failed (e.g. wrong password) """ d = unhexlify(base58decode(encrypted_privkey)) d = d[2:] # remove trailing 0x01 and 0x42 flagbyte = d[0:1] # get flag byte d = d[1:] # get payload assert flagbyte == b'\xc0', "Flagbyte has to be 0xc0" salt = d[0:4] d = d[4:-4] if "scrypt" in sys.modules: key = scrypt.hash(passphrase, salt, 16384, 8, 8) else: key = pylibscrypt.scrypt(bytes(passphrase, "utf-8"), salt, 16384, 8, 8) derivedhalf1 = key[0:32] derivedhalf2 = key[32:64] encryptedhalf1 = d[0:16] encryptedhalf2 = d[16:32] aes = AES.new(derivedhalf2) decryptedhalf2 = aes.decrypt(encryptedhalf2) decryptedhalf1 = aes.decrypt(encryptedhalf1) privraw = decryptedhalf1 + decryptedhalf2 privraw = ('%064x' % (int(hexlify(privraw), 16) ^ int(hexlify(derivedhalf1), 16))) wif = Base58(privraw) """ Verify Salt """ privkey = PrivateKey(format(wif, "wif")) addr = format(privkey.uncompressed.address, "BTC") a = bytes(addr, 'ascii') saltverify = hashlib.sha256(hashlib.sha256(a).digest()).digest()[0:4] if saltverify != salt: raise SaltException( 'checksum verification failed! Password may be incorrect.') return wif
def decrypt(encrypted_privkey, passphrase): d = unhexlify(base58decode(encrypted_privkey)) d = d[2:] # remove trailing 0x01 and 0x42 flagbyte = d[0:1] # get flag byte d = d[1:] # get payload salt = d[0:4] d = d[4:-4] key = scrypt.scrypt(bytes(passphrase, "utf-8"), salt, 16384, 8, 8) derivedhalf1 = key[0:32] derivedhalf2 = key[32:64] encryptedhalf1 = d[0:16] encryptedhalf2 = d[16:32] aes = AES.new(derivedhalf2) decryptedhalf2 = aes.decrypt(encryptedhalf2) decryptedhalf1 = aes.decrypt(encryptedhalf1) privraw = decryptedhalf1 + decryptedhalf2 privraw = ('%064x' % (int(hexlify(privraw), 16) ^ int(hexlify(derivedhalf1), 16))) return privraw
def encrypt_secret_key(secret, coldkey, public_address, scrypt_N=2**14, scrypt_p=1): '''Encrypt a secret exponent using an individual symmetric key. The symmetric key is generated from the shared coldwallet key (given as byte string) and the public bitcoin address (given in human readable format) using the memory-hard scrypt hash. The result is returned in base64 encoding. ''' # Generate a 256 bit symmetric key from the coldwallet key and the public bitcoin address symmetric_key = pylibscrypt.scrypt(coldkey, public_address.encode('ascii'), olen=32, N=scrypt_N, p=scrypt_p) # Encrypt the secret exponent with the symmetric key encrypted_secret = coldwallet.aes.encrypt_block(secret, symmetric_key) # Base64 encode the result return base64.b64encode(encrypted_secret).decode('ascii')
def decrypt_secret_key(code, coldkey, public_address, scrypt_N=2**14, scrypt_p=1): '''Decrypt a secret exponent, given in base64 encoding, using an individual symmetric key. The symmetric key is generated as above. The result is returned as a byte string. ''' # Base64 decode the input code = base64.b64decode(code.encode('ascii')) # Generate a 256 bit symmetric key from the coldwallet key and the public bitcoin address symmetric_key = pylibscrypt.scrypt(coldkey, public_address.encode('ascii'), olen=32, N=scrypt_N, p=scrypt_p) # Decrypt the secret exponent with the symmetric key secret = coldwallet.aes.decrypt_block(code, symmetric_key) return secret
import pylibscrypt import sys SEED_LENGTH = 32 # Length of the key crypto_sign_BYTES = 64 SCRYPT_PARAMS = {'N': 4096, 'r': 16, 'p': 1 } def _ensure_bytes(data): if isinstance(data, str): return bytes(data, 'utf-8') return data if __name__ == '__main__': seed = pylibscrypt.scrypt(_ensure_bytes("pass"), _ensure_bytes("salt"), SCRYPT_PARAMS['N'], SCRYPT_PARAMS['r'], SCRYPT_PARAMS['p'], SEED_LENGTH) print(seed) sys.exit()
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import os import threading from typing import Optional, Dict from . import util from .bitcoin import hash_encode, int_to_hex, rev_hex from .crypto import sha256d from . import constants from .util import bfh, bh2u from .simple_config import SimpleConfig try: import pylibscrypt getPoWHash = lambda x: pylibscrypt.scrypt(password=x, salt=x, N=1024, r=1, p=1, olen=32) except ImportError: util.print_msg("Warning: package pylibscrypt not available") HEADER_SIZE = 80 # bytes MAX_TARGET = 0x00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff class MissingHeader(Exception): pass class InvalidHeader(Exception): pass def serialize_header(header_dict: dict) -> str:
def load_wallet(wallet_file, get_password_fn): """load and if necessary decrypt a bitcoinj wallet file :param wallet_file: an open bitcoinj wallet file :type wallet_file: file :param get_password_fn: a callback returning a password that's called iff one is required :type get_password_fn: function :return: the Wallet protobuf message or None if no password was entered when required :rtype: wallet_pb2.Wallet """ #// The format of the encrypted ".cipher" file is: #// 7 magic bytes 'mendoza' in ASCII. #// 1 byte version number of format - initially set to 0 (actually 0x00!) #// 8 bytes salt #// 16 bytes iv #// rest of file is the encrypted byte data wallet_file.seek(0) magic_bytes = wallet_file.read(7) version = wallet_file.read(1) wallet_file.seek(0, os.SEEK_END) wallet_size = wallet_file.tell() wallet_file.seek(0) if magic_bytes[0:7] == b"mendoza" and version == "\x00" and wallet_size % 16 == 0: print("") print("MultiBit Classic Cipher file found") print("") takes_long = not pylibscrypt._done # if a binary library wasn't found, this'll take a while ciphertext = wallet_file.read() assert len(ciphertext) % 16 == 0 password = get_password_fn(takes_long) if not password: return None # Derive the encryption key salt = ciphertext[8:16] key = pylibscrypt.scrypt(password.encode('utf_16_be'), salt, olen=32) iv = ciphertext[16:32] # Decrypt the wallet ( v0.5.0+ ) plaintext = aes256_cbc_decrypt(ciphertext[32:], key, iv) if plaintext[2:6] != b"org.": raise ValueError('incorrect password') # Else it's not a cipher file encrypted else: print("File is NOT a Multibit Classic Cipher File") return # Parse the wallet protobuf pb_wallet = wallet_pb2.Wallet() try: pb_wallet.ParseFromString(plaintext) except Exception as e: msg = 'not a wallet file: ' + str(e) if password: msg = "incorrect password (or " + msg + ")" raise ValueError(msg) f = open('parsed_cipher_wallet.txt','w') f.write(pb_wallet.__str__()) f.close() print("--------------------------------------------------------------------------------") if pb_wallet.encryption_type == 2: print("Keys are encrypted") takes_long = not pylibscrypt._done # if a binary library wasn't found, this'll take a while password = get_password_fn(takes_long) if not password: return None salt = pb_wallet.encryption_parameters.salt dkey = pylibscrypt.scrypt(password.encode('utf_16_be'), salt, olen=32) for enckeys in pb_wallet.key: ciphertext = enckeys.encrypted_data.encrypted_private_key iv = enckeys.encrypted_data.initialisation_vector privkey = aes256_cbc_decrypt(ciphertext, dkey, iv) print("") print("Pubkey: " + bitcoin.pubtoaddr(enckeys.public_key)) print("Privkey: " + bitcoin.encode_privkey(privkey, 'wif_compressed')) elif pb_wallet.encryption_type == 1: print("Keys NOT encrypted") for enckeys in pb_wallet.key: print("") print("Pubkey: " + bitcoin.pubtoaddr(enckeys.public_key)) print("Privkey: " + bitcoin.encode_privkey(enckeys.secret_bytes, 'wif_compressed')) print("") print("--------------------------------------------------------------------------------") return pb_wallet
def load_wallet(wallet_file, get_password_fn): """load and if necessary decrypt a bitcoinj wallet file :param wallet_file: an open bitcoinj wallet file :type wallet_file: file :param get_password_fn: a callback returning a password that's called iff one is required :type get_password_fn: function :return: the Wallet protobuf message or None if no password was entered when required :rtype: wallet_pb2.Wallet """ wallet_file.seek(0) magic_bytes = wallet_file.read(12) wallet_file.seek(0, os.SEEK_END) wallet_size = wallet_file.tell() wallet_file.seek(0) if magic_bytes[2:6] != b"org." and wallet_size % 16 == 0: takes_long = not pylibscrypt._done # if a binary library wasn't found, this'll take a while ciphertext = wallet_file.read() assert len(ciphertext) % 16 == 0 password = get_password_fn(takes_long) if not password: return None # Derive the encryption key salt = '\x35\x51\x03\x80\x75\xa3\xb0\xc5' key = pylibscrypt.scrypt(password.encode('utf_16_be'), salt, olen=32) # Decrypt the wallet ( v0.5.0+ ) try: plaintext = aes256_cbc_decrypt(ciphertext[16:], key, ciphertext[:16]) if plaintext[2:6] != b"org.": raise ValueError('incorrect password') except ValueError as e: if e.args[0] == 'incorrect password': # Decrypt the wallet ( < v0.5.0 ) iv = '\xa3\x44\x39\x1f\x53\x83\x11\xb3\x29\x54\x86\x16\xc4\x89\x72\x3e' plaintext = aes256_cbc_decrypt(ciphertext, key, iv) global multibit_hd_password multibit_hd_password = password # Else it's not whole-file encrypted else: print("File NOT Encrypted") password = None plaintext = wallet_file.read() # Parse the wallet protobuf pb_wallet = wallet_pb2.Wallet() try: pb_wallet.ParseFromString(plaintext) except Exception as e: msg = 'not a wallet file: ' + str(e) if password: msg = "incorrect password (or " + msg + ")" raise ValueError(msg) f = open('parsed_wallet.txt','w') f.write(pb_wallet.__str__()) f.close() print("--------------------------------------------------------------------------------") if pb_wallet.encryption_type == 2: print("Keys are encrypted") takes_long = not pylibscrypt._done # if a binary library wasn't found, this'll take a while password = get_password_fn(takes_long) if not password: return None salt = pb_wallet.encryption_parameters.salt dkey = pylibscrypt.scrypt(password.encode('utf_16_be'), salt, olen=32) for enckeys in pb_wallet.key: ciphertext = enckeys.encrypted_data.encrypted_private_key iv = enckeys.encrypted_data.initialisation_vector privkey = aes256_cbc_decrypt(ciphertext, dkey, iv) print("") print("Pubkey: " + bitcoin.pubtoaddr(enckeys.public_key)) print("Privkey: " + bitcoin.encode_privkey(privkey, 'wif_compressed')) elif pb_wallet.encryption_type == 1: print("Keys NOT encrypted") for enckeys in pb_wallet.key: print("") print("Pubkey: " + bitcoin.pubtoaddr(enckeys.public_key)) print("Privkey: " + bitcoin.encode_privkey(enckeys.secret_bytes, 'wif_compressed')) print("") print("--------------------------------------------------------------------------------") return pb_wallet
def dec_key(self, pwd): self.key = bytearray(self.key) pad = bytearray(pylibscrypt.scrypt(pwd, self.salt, olen=len(self.key))) for i, p in enumerate(pad): self.key[i] = self.key[i] ^ p
#!/usr/bin/env python3 # Copyright (c) 2014-2021, Jan Varho # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. from base64 import b16encode from pylibscrypt import scrypt, scrypt_mcf, scrypt_mcf_check # Print a raw scrypt hash in hex print(b16encode(scrypt(b'Hello World', b'salt'))) # Generate an MCF hash with random salt mcf = scrypt_mcf('Hello World') # Test it print(scrypt_mcf_check(mcf, 'Hello World')) print(scrypt_mcf_check(mcf, 'HelloPyWorld'))
def main(token): # Name of the challenge challenge_name = 'password_hashing' # Data of the challenge to a dict challenge_dict = data_request(challenge_name, token) print(challenge_dict) print() # Unpack the elements password = challenge_dict['password'].encode(encoding='UTF-8') print(f'password: {password}') salt = base64.b64decode(challenge_dict['salt']) #decode from base64 print(f'salt: {salt}') print(f"salt: {salt.decode(encoding = 'ISO-8859-1')}") # PBKDF parameters hash_pbkdf2 = challenge_dict['pbkdf2']['hash'] iterations_pbkdf2 = challenge_dict['pbkdf2']['rounds'] # scrypt parameters scrypt_N = challenge_dict['scrypt']['N'] scrypt_p = challenge_dict['scrypt']['p'] scrypt_r = challenge_dict['scrypt']['r'] scrypt_buflen = challenge_dict['scrypt']['buflen'] _control = challenge_dict['scrypt']['_control'] # SHA256 pass_sha256 = sha256() pass_sha256.update(password) pass_sha256 = pass_sha256.hexdigest() print(f'SHA256: {pass_sha256}') # HMAC-SHA256 pass_hmac = hmac.new(salt, msg=password, digestmod=sha256).hexdigest() print(f'HMAC-SHA256: {pass_hmac}') # PBKDF-SHA256 pass_pbkdf2 = pbkdf2_hmac(hash_pbkdf2, password, salt, iterations_pbkdf2) pass_pbkdf2 = str(hexlify(pass_pbkdf2), encoding='UTF-8') print(f'PBKDF-SHA256: {pass_hmac}') # scrypt pass_scrypt = pylibscrypt.scrypt(password, salt, N=scrypt_N, r=scrypt_r, p=scrypt_p, olen=32) pass_scrypt = str(hexlify(pass_scrypt), encoding='UTF-8') print(f'scrypt: {pass_scrypt}') # Dict for the solution challenge_solution = { 'sha256': pass_sha256, 'hmac': pass_hmac, 'pbkdf2': pass_pbkdf2, 'scrypt': pass_scrypt } # Solution POST return solution_post(challenge_name, token, challenge_solution)
def load_wallet(wallet_file, get_password_fn): """load and if necessary decrypt a bitcoinj wallet file :param wallet_file: an open bitcoinj wallet file :type wallet_file: file :param get_password_fn: a callback returning a password that's called iff one is required :type get_password_fn: function :return: the Wallet protobuf message or None if no password was entered when required :rtype: wallet_pb2.Wallet """ wallet_file.seek(0) magic_bytes = wallet_file.read(12) wallet_file.seek(0, os.SEEK_END) wallet_size = wallet_file.tell() wallet_file.seek(0) if magic_bytes[2:6] != b"org." and wallet_size % 16 == 0: import pylibscrypt takes_long = not pylibscrypt._done # if a binary library wasn't found, this'll take a while ciphertext = wallet_file.read() assert len(ciphertext) % 16 == 0 password = get_password_fn(takes_long) if not password: return None # Derive the encryption key salt = '\x35\x51\x03\x80\x75\xa3\xb0\xc5' key = pylibscrypt.scrypt(password.encode('utf_16_be'), salt, olen=32) # Decrypt the wallet ( v0.5.0+ ) try: plaintext = aes256_cbc_decrypt(ciphertext[16:], key, ciphertext[:16]) if plaintext[2:6] != b"org.": raise ValueError('incorrect password') except ValueError as e: if e.args[0] == 'incorrect password': # Decrypt the wallet ( < v0.5.0 ) iv = '\xa3\x44\x39\x1f\x53\x83\x11\xb3\x29\x54\x86\x16\xc4\x89\x72\x3e' plaintext = aes256_cbc_decrypt(ciphertext, key, iv) global multibit_hd_password multibit_hd_password = password # Else it's not whole-file encrypted else: password = None plaintext = wallet_file.read() # Parse the wallet protobuf pb_wallet = wallet_pb2.Wallet() try: pb_wallet.ParseFromString(plaintext) except Exception as e: msg = 'not a wallet file: ' + str(e) if password: msg = "incorrect password (or " + msg + ")" raise ValueError(msg) f = open('parsed_wallet.txt','w') f.write(pb_wallet.__str__()) f.close() foundAddr = [] for trans in pb_wallet.transaction: if trans.pool == 4: print("--------------------------------------------------------------------------------") print("TXID: " + binascii.hexlify(trans.hash)) for out in trans.transaction_output: print("") faddr = bitcoin.bin_to_b58check(bitcoin.deserialize_script(out.script_bytes)[2]) print("Addr: " + faddr) foundAddr.append(faddr) print("Amt: " + str(out.value * 0.00000001) + " BTC") print("") print("--------------------------------------------------------------------------------") seed = None sys.stdout.write('Finding Seed....') salt = pb_wallet.encryption_parameters.salt dkey = pylibscrypt.scrypt(password.encode('utf_16_be'), salt, olen=32) for wkey in pb_wallet.key: if wkey.type == 3: seed = aes256_cbc_decrypt(wkey.encrypted_deterministic_seed.encrypted_private_key, dkey, wkey.encrypted_deterministic_seed.initialisation_vector) break if not seed: print("No DETERMINISTIC_MNEMONIC seed found!") return None else: print("Done!") xprv = bitcoin.bip32_master_key(seed) xprvReceive = bitcoin.bip32_ckd(bitcoin.bip32_ckd(xprv, 2**31),0) #m/0'/0 xprvChange = bitcoin.bip32_ckd(bitcoin.bip32_ckd(xprv, 2**31),1) #m/0'/1 rcvAddr = [] chgAddr = [] rcvPrivKey = [] chgPrivKey = [] sys.stdout.write("Generating Addresses/Keys.") for x in range(0,1000): if x % 10 == 0: sys.stdout.write(".") childprivReceive = bitcoin.bip32_ckd(xprvReceive, x) childprivChange = bitcoin.bip32_ckd(xprvChange, x) pkeyReceive = bitcoin.bip32_extract_key(childprivReceive) pkeyChange = bitcoin.bip32_extract_key(childprivChange) #addressReceive = privtoaddr(pkeyReceive) #addressChange = privtoaddr(pkeyChange) rcvAddr.append(bitcoin.privtoaddr(pkeyReceive)) chgAddr.append(bitcoin.privtoaddr(pkeyChange)) rcvPrivKey.append(bitcoin.encode_privkey(pkeyReceive, 'wif_compressed')) chgPrivKey.append(bitcoin.encode_privkey(pkeyChange, 'wif_compressed')) print("Done!") print("--------------------------------------------------------------------------------") for addy in foundAddr: if addy in rcvAddr: print("") print("Found Address: " + addy) print("PrivateKey: " + rcvPrivKey[rcvAddr.index(addy)]) elif addy in chgAddr: print("") print("Found Change Address: " + addy) print("PrivateKey: " + chgPrivKey[chgAddr.index(addy)]) else: print("") print("Address not found: " + addy) print("") print("--------------------------------------------------------------------------------") return pb_wallet
#!/usr/bin/env python # Copyright (c) 2014-2015, Jan Varho # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. from base64 import b16encode from pylibscrypt import scrypt, scrypt_mcf, scrypt_mcf_check # Print a raw scrypt hash in hex print(b16encode(scrypt(b'Hello World', b'salt'))) # Generate an MCF hash with random salt mcf = scrypt_mcf(b'Hello World') # Test it print(scrypt_mcf_check(mcf, b'Hello World')) print(scrypt_mcf_check(mcf, b'HelloPyWorld'))