def create_nonce(secp: Secp256k1, chain_code: ChainCode, commit: Commitment) -> SecretKey: return SecretKey.from_bytearray( secp, bytearray( blake2b(bytes(chain_code.chain_code), digest_size=32, key=bytes(commit.to_bytearray(secp))).digest()))
def create_common_nonce(secp: Secp256k1, secret_key: SecretKey, public_key: PublicKey, commit: Commitment) -> SecretKey: common_key = public_key.mul(secp, secret_key) return SecretKey.from_bytearray( secp, bytearray( blake2b(bytes(common_key.to_bytearray(secp)), digest_size=32, key=bytes(commit.to_bytearray(secp))).digest()))
def ckd_public(self, secp: Secp256k1, hasher: Hasher, i: ChildNumber): if i.is_hardened(): raise HardenedIndexError() hasher.init_sha512(self.chain_code.to_bytearray()) hasher.append_sha512(self.public_key.to_bytearray(secp)) hasher.append_sha512(i.to_bytearray()) hash = hasher.result_sha512() key = SecretKey.from_bytearray(secp, hash[:32]).to_public_key(secp) key.add_assign(secp, self.public_key) return ExtendedPublicKey(self.network, self.depth + 1, self.fingerprint(secp, hasher), i, key, ChainCode.from_bytearray(hash[32:]))
def ckd_secret(self, secp: Secp256k1, hasher: Hasher, i: ChildNumber): hasher.init_sha512(self.chain_code.to_bytearray()) if i.is_normal(): hasher.append_sha512(self.secret_key.to_public_key(secp).to_bytearray(secp)) else: hasher.append_sha512(bytearray([0])) hasher.append_sha512(self.secret_key.to_bytearray()) hasher.append_sha512(i.to_bytearray()) hash = hasher.result_sha512() key = SecretKey.from_bytearray(secp, hash[:32]) key.add_assign(secp, self.secret_key) return ExtendedSecretKey(self.network, self.depth + 1, self.fingerprint(secp, hasher), i, key, ChainCode.from_bytearray(hash[32:]))
def blind_sum(self, positives, negatives) -> SecretKey: keys = [] for positive in positives: assert isinstance(positive, SecretKey) keys.append(ffi.new("char []", bytes(positive.key))) for negative in negatives: assert isinstance(negative, SecretKey) keys.append(ffi.new("char []", bytes(negative.key))) sum_key = ffi.new("char []", SECRET_KEY_SIZE) ret = lib.secp256k1_pedersen_blind_sum(self.ctx, sum_key, keys, len(keys), len(positives)) assert ret, "Unable to sum blinding factors" return SecretKey.from_bytearray( self, bytearray(ffi.buffer(sum_key, SECRET_KEY_SIZE)))
def bullet_proof_multisig_2(self, value: int, blind: SecretKey, commit: Commitment, common_nonce: SecretKey, nonce: SecretKey, t_1: PublicKey, t_2: PublicKey, extra_data: bytearray) -> SecretKey: scratch = lib.secp256k1_scratch_space_create(self.ctx, 256 * MAX_WIDTH) tau_x_ptr = ffi.new("char []", 32) blind_key = ffi.new("char []", bytes(blind.key)) res = lib.secp256k1_bulletproof_rangeproof_prove( self.ctx, scratch, self.gens, ffi.NULL, ffi.NULL, tau_x_ptr, t_1.key, t_2.key, [value], ffi.NULL, [blind_key], [commit.commitment], 1, self.GENERATOR_H, 64, bytes(common_nonce.key), bytes(nonce.key), bytes(extra_data), len(extra_data), ffi.NULL) lib.secp256k1_scratch_space_destroy(scratch) assert res, "Unable to generate multisig bulletproof" return SecretKey.from_bytearray(self, bytearray(ffi.buffer(tau_x_ptr, 32)))
def to_secret_key(self, secp: Secp256k1) -> SecretKey: return SecretKey.from_bytearray(secp, self.to_bytearray())
def test_secret_key(): secp = Secp256k1(None, FLAG_ALL) # (de)serialization key_a = SecretKey.random(secp) key_b = SecretKey.from_bytearray(secp, key_a.to_bytearray()) assert key_a == key_b # Too short with raises(Exception): SecretKey.from_bytearray(secp, bytearray([0x01] * (SECRET_KEY_SIZE - 1))) # Too long with raises(Exception): SecretKey.from_bytearray(secp, bytearray([0x01] * (SECRET_KEY_SIZE + 1))) # Zero with raises(Exception): SecretKey.from_bytearray(secp, bytearray([0] * SECRET_KEY_SIZE)) # Overflow with raises(Exception): SecretKey.from_bytearray(secp, bytearray([0xFF] * SECRET_KEY_SIZE)) # Top of range SecretKey.from_bytearray( secp, bytearray([ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40 ])) # One past top of range with raises(Exception): SecretKey.from_bytearray( secp, bytearray([ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 ])) # a=a key_a = SecretKey.from_bytearray(secp, bytearray([0xCB] * SECRET_KEY_SIZE)) key_b = SecretKey.from_bytearray(secp, bytearray([0xCB] * SECRET_KEY_SIZE)) assert key_a == key_b # a!=b key_b = SecretKey.from_bytearray(secp, bytearray([0xCC] * SECRET_KEY_SIZE)) assert key_a != key_b # a+b key_a = SecretKey.from_bytearray(secp, bytearray([0xDD] * SECRET_KEY_SIZE)) key_b = SecretKey.from_bytearray(secp, bytearray([0x02] * SECRET_KEY_SIZE)) key_a.add_assign(secp, key_b) key_c = SecretKey.from_bytearray(secp, bytearray([0xDF] * SECRET_KEY_SIZE)) assert key_a == key_c # a+b = b+a key_a = SecretKey.random(secp) key_b = SecretKey.random(secp) key_a_b = key_a.add(secp, key_b) key_b_a = key_b.add(secp, key_a) assert key_a_b == key_b_a # Key addition where sum > order (N-1+N-2=N-3) key_a = SecretKey.from_bytearray( secp, bytearray([ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40 ])) key_b = SecretKey.from_bytearray( secp, bytearray([ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3F ])) key_a.add_assign(secp, key_b) key_c = SecretKey.from_bytearray( secp, bytearray([ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3E ])) assert key_a == key_c # ab = ba key_a = SecretKey.random(secp) key_b = SecretKey.random(secp) key_ab = key_a.mul(secp, key_b) key_ba = key_b.mul(secp, key_a) assert key_ab == key_ba # c(a+b) = ca + cb key_a = SecretKey.random(secp) key_b = SecretKey.random(secp) key_c = SecretKey.random(secp) key_ca = key_a.mul(secp, key_c) key_cb = key_b.mul(secp, key_c) key_ca_b = key_a.add(secp, key_b) key_ca_b.mul_assign(secp, key_c) key_ca_cb = key_ca.add(secp, key_cb) assert key_ca_b == key_ca_cb
def from_bytearray(secp: Secp256k1, data: bytearray): assert len(data) == 78 return ExtendedSecretKey(data[:4], data[4], Fingerprint.from_bytearray(data[5:9]), ChildNumber.from_bytearray(data[9:13]), SecretKey.from_bytearray(secp, data[46:78]), ChainCode.from_bytearray(data[13:45]))
def new_master(secp: Secp256k1, hasher: Hasher, seed: bytearray): hasher.init_sha512(hasher.master_seed()) hasher.append_sha512(seed) hash = hasher.result_sha512() return ExtendedSecretKey(hasher.network_secret(), 0, Fingerprint.default(), ChildNumber.from_normal_index(0), SecretKey.from_bytearray(secp, hash[:32]), ChainCode.from_bytearray(hash[32:]))