def signTx(tx, path, debug=False): """ Sign a transaction. It generates the signature accordingly to derivation path and computes the id of the transaction. The tx is then updated and returned. Argument: tx -- a dict object containing explicit fields and values defining a valid transaction path -- a derivation path Keyword argument: debug -- flag to activate debug messages from ledger key [default: False] Return dict """ dongle_path = parseBip32Path(path) # update tx if "senderPublicKey" not in tx: tx["senderPublicKey"] = getPublicKey(dongle_path) apdu1, apdu2 = buildTxApdu(dongle_path, arky.core.crypto.getBytes(tx)) dongle = getDongle(debug) result = dongle.exchange(bytes(apdu1)) if apdu2: result = dongle.exchange(bytes(apdu2)) dongle.close() # update tx tx["signature"] = util.hexlify(result) tx["id"] = arky.core.crypto.getId(tx) return tx
def check(publicKey, data): """ Chack signatures from a bytearray containing signature and random seed """ signature, rand = unpack(data) return arky.core.crypto.verifySignatureFromBytes(seed() + rand, publicKey, bin.hexlify(signature))
def getIdFromBytes(data): """ Generate data id. Arguments: data (bytes) -- data in bytes Return str """ return hexlify(hashlib.sha256(data).digest())
def getId(tx): """ Generate transaction id. Arguments: tx (dict) -- a transaction description Return str """ return hexlify(hashlib.sha256(getBytes(tx)).digest())
def getKeys(secret, seed=None): """ Generate keyring containing public key, signing and checking keys as attribute. Keyword arguments: secret (str or bytes) -- a human pass phrase seed (byte) -- a sha256 sequence bytes (private key actualy) Return dict """ if not isinstance(secret, bytes): secret = secret.encode('utf-8') seed = hashlib.sha256(secret).digest() if not seed else seed signingKey = SigningKey.from_secret_exponent( int(binascii.hexlify(seed), 16), SECP256k1, hashlib.sha256 ) publicKey = signingKey.get_verifying_key().to_string() return { "publicKey": hexlify(compressEcdsaPublicKey(publicKey) if cfg.compressed else publicKey), "privateKey": hexlify(signingKey.to_string()), "wif": getWIF(seed) }
def getSignatureFromBytes(data, privateKey): """ Generate data signature using private key. Arguments: data (bytes) -- data in bytes privateKey (str) -- a private key as hex string Return str """ signingKey = SigningKey.from_string(unhexlify(privateKey), SECP256k1, hashlib.sha256) return hexlify(signingKey.sign_deterministic( data, hashlib.sha256, sigencode=sigencode_der_canonize) )
def getSignature(tx, privateKey): """ Generate transaction signature using private key. Arguments: tx (dict) -- a transaction description privateKey (str) -- a private key as hex string Return str """ signingKey = SigningKey.from_string(unhexlify(privateKey), SECP256k1, hashlib.sha256) return hexlify(signingKey.sign_deterministic( getBytes(tx), hashlib.sha256, sigencode=sigencode_der_canonize) )
def test_scramble_and_unscramble(self): # set test data pin = "abc123" address = "DUGvQBxLzQqrNy68asPcU3stWQyzVq8G49".encode() scrambled_result = ( b"\x06\x06\x0b\x0b\x06\x0f\x0f\r\x0b\x03\x06\x07\x0f\x04\x06\x05\x0f\x02\x0b\x03\x0f" b"\x03\x0f\x07\x06\x00\x0f\x01\t\r\t\x04\r\x03\x0f\t\x0b\x0e\r\t\x0b\x0b\t\t\x0f\t" b"\x0f\x06\x0b\x0f\x0b\x03\x0f\x01\x0f\x02\x0b\r\x0f\x03\t\x04\x06\x0f\t\x06\t\x01" ) # run test base = createBase(pin) hexa = hexlify(address) scrambled = scramble(base, hexa) assert scrambled == scrambled_result unscrambled = unScramble(base, scrambled) assert hexa == unscrambled
def getPublicKey(dongle_path, debug=False): """ Compute the public key associated to a derivation path. Argument: dongle_path -- value returned by parseBip32Path Keyword argument: debug -- flag to activate debug messages from ledger key [default: False] Return str (hex) """ apdu = buildPkeyApdu(dongle_path) dongle = getDongle(debug) data = bytes(dongle.exchange(apdu)) dongle.close() len_pkey = util.basint(data[0]) return util.hexlify(data[1:len_pkey + 1])
def dumpBip39(pin, bip39, name="unamed"): """ Encrypt your passphrase using a pin code and save it on the disk. Dumped file are located in ~/.bip39/<network-name>. Argument: pin -- a str containing pin code (no limit in digit number) or a password bip39 -- a str containing passphrase Keyword argument: name -- the name you want to give """ bip39 = bip39 if isinstance(bip39, bytes) else bip39.encode("utf-8") folder = os.path.join(HOME, ".bip39", cfg.network) if not os.path.exists(folder): os.makedirs(folder) with io.open(os.path.join(folder, name + ".bip39"), "wb") as out: out.write(data.scramble(data.createBase(pin), util.hexlify(bip39)))
def getSignature(tx, private): return hexlify( crypto_sign(hashlib.sha256(getBytes(tx)).digest(), unhexlify(private))[:crypto_sign_BYTES])
def getKeys(secret, seed=None): if not isinstance(secret, bytes): secret = secret.encode('utf-8') seed = hashlib.sha256(secret).digest() if not seed else seed publicKey, privateKey = list( hexlify(e) for e in crypto_sign_seed_keypair(seed)) return {"publicKey": publicKey, "privateKey": privateKey}
def test_get_bytes_and_hexlify(self): self.assertEqual(self.hexaTx, hexlify(arky.core.crypto.getBytes(self.tx)))