def generate_btc_address(): # secp256k1, not included in stock ecdsa _p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL _r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L _b = 0x0000000000000000000000000000000000000000000000000000000000000007L _a = 0x0000000000000000000000000000000000000000000000000000000000000000L _Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L _Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L curve_256 = CurveFp(_p, _a, _b) generator = Point(curve_256, _Gx, _Gy, _r) secret = randrange(1, generator.order()) pubkey = Public_key(generator, generator * secret) step1 = '\x04' + int_to_string(pubkey.point.x()) + \ int_to_string(pubkey.point.y()) step2 = hashlib.sha256(step1).digest() ripehash.update(step2) step4 = '\x00' + ripehash.digest() step5 = hashlib.sha256(step4).digest() step6 = hashlib.sha256(step5).digest() chksum = step6[:4] addr = step4 + chksum addr_58 = b58encode(addr) return (hex(secret)[2:-1], hexlify(step1), hexlify(addr), addr_58)
def from_signature(klass, sig, recid, h, curve): """ See http://www.secg.org/download/aid-780/sec1-v2.pdf, chapter 4.1.6 """ from ecdsa import util, numbertheory from . import msqr curveFp = curve.curve G = curve.generator order = G.order() # extract r,s from signature r, s = util.sigdecode_string(sig, order) # 1.1 x = r + (recid // 2) * order # 1.3 alpha = (x * x * x + curveFp.a() * x + curveFp.b()) % curveFp.p() beta = msqr.modular_sqrt(alpha, curveFp.p()) y = beta if (beta - recid) % 2 == 0 else curveFp.p() - beta # 1.4 the constructor checks that nR is at infinity R = Point(curveFp, x, y, order) # 1.5 compute e from message: e = string_to_number(h) minus_e = -e % order # 1.6 compute Q = r^-1 (sR - eG) inv_r = numbertheory.inverse_mod(r, order) Q = inv_r * (s * R + minus_e * G) return klass.from_public_point(Q, curve)
def main(): parser = argparse.ArgumentParser(description='Threshold Cryptosystem Tool') # RECONSTRUCT KEYS reconstruct_group = parser.add_argument_group(title='Reconstruct Key') reconstruct_group.add_argument( '--file', default=None, type=str, help='Path to comma separated file with secrets.') reconstruct_group.add_argument('--t', default=None, type=int, help='Number of subshares to reconstruct') # RECONSTRUCT KEYS # ENCRYPT encrypt_group = parser.add_argument_group(title='Encrypt Message') encrypt_group.add_argument('--pkfile', default=None, help='File containing public key') encrypt_group.add_argument('--msg', default=None, type=str, help='Message to encrypt') encrypt_group.add_argument('--outfile', default='./ciphertext.txt', help='File to output message') # ENCRYPT # DECRYPT decrypt_group = parser.add_argument_group(title='Decrypt Message') decrypt_group.add_argument('--decrypt', default=None, help='Reconstructed key') decrypt_group.add_argument( '--infile', default='./ciphertext.txt', help='File containing encrypted message ciphers') # DECRYPT # GENERATE PARAMETERS generate_group = parser.add_argument_group( title='Generate and save threshold parameters') generate_group.add_argument('--tshares', default=None, type=int, help='Number of reconstructable shares') generate_group.add_argument('--nshares', default=None, type=int, help='Total number of shares') generate_group.add_argument('--folder', default='./threshold_data/', help='Folder to save data on') args = parser.parse_args() # Reconstruct Key if args.file and args.t: print('Reconstructed private key: {}'.format( reconstruct(args.file, args.t))) # Encrypt if args.pkfile and args.msg and args.outfile: p = open(args.pkfile).readlines()[0].split(',') p_k = Point(curve_secp256k1, int(p[0]), int(p[1][:-1])) msg = int(args.msg.encode().hex(), 16) c = th.encrypt(p_k, msg) l = '{},{},{}'.format(c[0].x(), c[0].y(), c[1]) open(args.outfile, 'w').write(l) # Generate if args.tshares and args.nshares and args.folder: params = th.generate_threshold_parameters(args.tshares, args.nshares) th.save_params_file(args.tshares, args.nshares, params, args.folder) # Decrypt if args.decrypt and args.infile: with open(args.infile) as file: # Use file to refer to the file object encrypted_data = file.read() parts = encrypted_data.split(',') p_k = Point(curve_secp256k1, int(parts[0]), int(parts[1])) res = th.decrypt(int(args.decrypt), (p_k, int(parts[2]))) try: print(bytes.fromhex(hex(res)[2:]).decode()) except: print('Could not decode message.')
def point(self) -> Point: Point = namedtuple('Point', ['x', 'y']) return Point(self._point.x(), self._point.y())
You should have received a copy of the GNU General Public License along with CoinParty. If not, see <http://www.gnu.org/licenses/>. """ from ecdsa.ellipticcurve import CurveFp, Point bitcoin_order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L """ When secret-sharing hashs (arbitrary 256-bit values), bitcoin_order may not be used, since it is too small to fit each possible hash value. Thus, we use the prime (2^265)-49, which is sufficiently large. Prime derived from http://primes.utm.edu/lists/2small/200bit.html """ hash_order = 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcf hash_modulus = 0x10000000000000000000000000000000000000000000000000000000000000000 """ Bitcoin ECC parameters _p, _a, _b: Description of secp256k1 for the ecdsa module _Gx, Gy: Coordinates of generator (uncompressed form) n: Order of the generator _h: Cofactor c.f.: https://en.bitcoin.it/wiki/Secp256k1 """ _p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL _a = 0x0000000000000000000000000000000000000000000000000000000000000000L _b = 0x0000000000000000000000000000000000000000000000000000000000000007L _Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L _Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L _h = 0x01L bitcoin_curve = CurveFp(_p, _a, _b) G = Point(bitcoin_curve, _Gx, _Gy, n)
def _ser_to_python_ecdsa_point(ser: bytes) -> ecdsa.ellipticcurve.Point: x, y = ser_to_point(ser) try: return Point(curve_secp256k1, x, y, CURVE_ORDER) except: raise InvalidECPointException()
def _ser_to_python_ecdsa_point(ser: bytes) -> ecdsa.ellipticcurve.Point: x, y = ser_to_point(ser) return Point(curve_secp256k1, x, y, CURVE_ORDER)
def from_pair(cls, pair): x, y = pair point = Point(curve=SECP256k1.curve, x=x, y=y, order=SECP256k1.order) key = VerifyingKey.from_public_point(point, curve=SECP256k1) return cls(key)
def __init__(self, curve): Group.__init__(self, Point(None, None, None), curve.order)
def prove_range_signatures(amount): """ :param amount: the amount that should be proved (int) :return: a list made of C_pk: output commitment serving as a public key (to_string 32bytes format) mask: part of the private key for C_pk. mask * G + amount * H == C_pk, 32 bytes number format rg: vector of range proofs, each entry contain a vector of public key Ci and a aggregate signature. The aggregate signature itself contains L1: vector of public key (to_string format, 32bytes) s2: vector of 32 bytes number s: 32 bytes number, aggregate of s1 For more info on asig, see generate_ASNL(...) """ HPow2 = hash_to_point(to_32_bytes_number(1)).pubkey.point H2 = [] for i in range(0, ATOMS): H2.append(VerifyingKey.from_public_point(HPow2, curve=crv).to_string()) HPow2 = HPow2 * 2 def d2b(n, digits): b = [0] * digits i = 0 while n: b[i] = n & 1 i = i + 1 n >>= 1 return b bb = d2b(amount, ATOMS) # gives binary form of bb in "digits" binary digits mask = to_32_bytes_number(0) ai = [] Ci = [] CiH = [] print("------ Preparing different elements ------") for i in range(0, ATOMS): ai.append(to_32_bytes_number(random.randrange(crv.order))) mask = add_2_32b( mask, ai[i] ) # creating the total mask since you have to pass this to receiver... if bb[i] == 0: Ci.append(g.from_string(ai[i], curve=crv).verifying_key.to_string()) if bb[i] == 1: Ci.append( VerifyingKey.from_public_point( g.from_string(ai[i], curve=crv).verifying_key.pubkey.point + VerifyingKey.from_string(H2[i], curve=crv).pubkey.point, curve=crv, ).to_string() ) negateH2 = Point( crv.curve, VerifyingKey.from_string(H2[i], curve=crv).pubkey.point.x(), (-VerifyingKey.from_string(H2[i], curve=crv).pubkey.point.y()), crv.order, ) CiH.append( VerifyingKey.from_public_point( VerifyingKey.from_string(Ci[i], curve=crv).pubkey.point + negateH2, curve=crv, ).to_string() ) if debug and bb[i] == 1: # Sanity check A + h2 - h2 == A assert ( g.from_string(ai[i], curve=crv).verifying_key.to_string() == CiH[i] ), ( "Sanity check failed in prove_range_signatures !" + bytes.hex(g.from_string(ai[i], curve=crv).verifying_key.to_string()) + " ---- " + bytes.hex(CiH[i]) ) if rang_sig_bool: L1, s2, s = generate_ASNL(ai, Ci, CiH, bb) if debug: verifiy_ASNL(Ci, CiH, L1, s2, s) asig = [L1, s2, s] rg = [Ci, asig] else: rg = 1 C_point = VerifyingKey.from_string(Ci[0], curve=crv).pubkey.point for i in range(1, len(Ci)): C_point = C_point + VerifyingKey.from_string(Ci[i], curve=crv).pubkey.point C = to_32_bytes_number(0) for i in range(0, len(Ci)): C = add_2_32b(C, Ci[i]) C_pk = VerifyingKey.from_public_point(C_point, curve=crv) if debug: x = ( hash_to_point(to_32_bytes_number(1)).pubkey.point * amount + g.from_string(mask, curve=crv).verifying_key.pubkey.point ) assert ( C_pk.to_string() == VerifyingKey.from_public_point(x, curve=crv).to_string() ), ( "Something went wrong in the genreation of the commitment! " + bytes.hex(C_pk.to_string()) + " should equal " + bytes.hex(VerifyingKey.from_public_point(x, curve=crv).to_string()) ) return C_pk.to_string(), mask, rg
def prepareMG( message, public_keys, public_key_commitments, in_sk, in_sk_mask, out_commitment, out_sk_masks, index, ): """ :param message: :param public_keys: matrix of public key (size: qxm, sec format) :param public_key_commitments: matrix of commitment for pk (size: qxm, 32bytes) :param in_sk: vector of private key (size: m, bytes32 format) :param in_sk_mask: vector of mask for the corresponding sk (size: m, 32bytes) :param out_commitment: vector of commitment for pk (hidden amount) (size: outPKsize, 32bytes) :param out_sk_masks: vector mask for out public keys (bytes32) :param index: index of where in the public_keys matrix our pks are located :return: same as gen_MG """ print("------ Preparing the matrix for the MG ------") rows_q = len(public_keys) if debug: assert ( len(public_keys) == len(public_key_commitments) and len(public_keys) > 0 ), "\ Mismatch in the number of public commitment and keys.\nAborting..." cols_m = len(public_keys[0]) if debug: assert ( len(in_sk) == len(in_sk_mask) and len(in_sk) == cols_m ), "Mismatch in the number of private keys or private key masks.\nAborting..." for i in range(0, rows_q): assert ( len(public_keys[i]) == len(public_key_commitments[i]) and len(public_keys[i]) == cols_m ), "Mismatch in the number of public commitment and keys.\nAborting..." assert 0 <= index < rows_q, ( "index: " + str(index) + " should be between 0 and " + str(rows_q) + " (the number of public key).\nAborting..." ) assert ( len(out_commitment) == len(out_sk_masks) and len(out_commitment) > 0 ), "Mismatch in the number of private commitment and keys.\nAborting..." matrix = [[None] * (cols_m + 1) for y in range(rows_q)] sk = [None] * (cols_m + 1) for i in range(cols_m): sk[i] = in_sk[i] if i == 0: sk[cols_m] = in_sk_mask[i] else: sk[cols_m] = add_2_32b(sk[cols_m], in_sk_mask[i]) for j in range(rows_q): matrix[j][i] = public_keys[j][i] if i == 0: matrix[j][cols_m] = VerifyingKey.from_string( public_key_commitments[j][i], curve=crv ).pubkey.point else: matrix[j][cols_m] = ( matrix[j][cols_m] + VerifyingKey.from_string( public_key_commitments[j][i], curve=crv ).pubkey.point ) for i in range(len(out_commitment)): sk[cols_m] = sub_2_32b(sk[cols_m], out_sk_masks[i]) for i in range(rows_q): for j in range(len(out_commitment)): point = VerifyingKey.from_string(out_commitment[j], curve=crv).pubkey.point matrix[i][cols_m] = ( matrix[i][cols_m] + VerifyingKey.from_public_point( Point( crv.curve, point.x(), (-point.y()) % crv.curve.p(), crv.order ), curve=crv, ).pubkey.point ) for j in range(rows_q): matrix[j][cols_m] = VerifyingKey.from_public_point( matrix[j][cols_m], curve=crv ).to_string() print("------ Done with the matrix for the MG ------") # TODO message return matrix, genMG(message, matrix, sk, index)
def main(): parser = argparse.ArgumentParser(description='Threshold Cryptosystem Tool') # RECONSTRUCT KEYS reconstruct_group = parser.add_argument_group(title='Reconstruct Key') reconstruct_group.add_argument( '--file', default=None, type=str, help='Path to comma separated file with secrets.') reconstruct_group.add_argument( '--t', default=None, type=int, help='Number of subshares to reconstruct') # RECONSTRUCT KEYS # ENCRYPT encrypt_group = parser.add_argument_group(title='Encrypt Message') encrypt_group.add_argument( '--pkfile', default=None, help='File containing public key') encrypt_group.add_argument( '--msg', default=None, type=int, help='Message to encrypt') encrypt_group.add_argument( '--outfile', default='./ciphertext.txt', help='File to output message') # ENCRYPT # GENERATE PARAMETERS generate_group = parser.add_argument_group(title='Generate and save threshold parameters') generate_group.add_argument( '--tshares', default=None, type=int, help='Number of reconstructable shares') generate_group.add_argument( '--nshares', default=None, type=int, help='Total number of shares') generate_group.add_argument( '--folder', default='./threshold_data/', help='Folder to save data on') args = parser.parse_args() # Reconstruct Key if args.file and args.t: print('Reconstructed private key: {}'.format(reconstruct(args.file, args.t))) #Encrypt if args.pkfile and args.msg and args.outfile: p = open(args.pkfile).readlines()[0].split(',') p_k = Point(curve_secp256k1, int(p[0]), int(p[1][:-1])) c = th.encrypt(p_k, args.msg) l = '{},{},{}'.format(c[0].x(), c[0].y(), c[1]) open(args.outfile, 'w').write(l) #Generate if args.tshares and args.nshares and args.folder: params = th.generate_threshold_parameters(args.tshares, args.nshares) th.save_params_file(args.tshares, args.nshares, params, args.folder)
def __init__(self, secret): curve = CurveFp(_p, _a, _b) generator = Point(curve, _Gx, _Gy, _r) self.pubkey = Public_key(generator, generator * secret) self.privkey = Private_key(self.pubkey, secret) self.secret = secret
def naive_multi_exp_ec(gs, es): tmp = Point(None, None, None) for i in range(len(gs)): tmp += es[i] * gs[i] return tmp
# assert ecdsa.ecdsa.point_is_valid(SECP256k1.generator, x, y) else: raise AssertionError("cannot decode point") return Point(SECP256k1.curve, x, y, order) def privkey_to_serpub(privkey, compressed): """Convert private key integer to serialized public key""" return point_to_ser(privkey * generator_secp256k1, compressed) # Make sure the point constructor refuses bad points. try: # example of bad uncompressed point Point(SECP256k1.curve, 1, 1, secp_order) raise RuntimeError("insecure! ecdsa is not refusing off-curve points!") except AssertionError: pass try: # example of bad compressed point Point(SECP256k1.curve, 5, 0x350ae3b48047adacdeea49fb8a0b289a94f726801078408aba79631fa7a1b6ba, secp_order) raise RuntimeError("insecure! ecdsa is not refusing off-curve points!") except AssertionError: pass def ecdh(privkey, theirpubkey): """
############################################################## # We always provide _a as a positive integer. _p = long_converter(""" ffffffff ffffffff ffffffff fffffffe ffffac73""") _a = 0 _b = 7 _Gx = long_converter(""" 3b4c382c e37aa192 a4019e76 3036f4f5 dd4d7ebb""") _Gy = long_converter(""" 938cf935 318fdced 6bc28286 531733c3 f03c4fee""") _r = long_converter("""01 00000000 00000000 0001b8fa 16dfab9a ca16b6b3""") curve = CurveFp(_p, _a, _b) generator = Point(curve, _Gx, _Gy, _r) SECP160k1 = Curve("SECP160k1", curve, generator, (1, 3, 132, 0, 9), "secp160k1") _p = long_converter(""" ffffffff ffffffff ffffffff ffffffff 7fffffff""") _a = -3 % _p _b = long_converter(""" 1c97befc 54bd7a8b 65acf89f 81d4d4ad c565fa45""") _Gx = long_converter(""" 4a96b568 8ef57328 46646989 68c38bb9 13cbfc82""") _Gy = long_converter(""" 23a62855 3168947d 59dcc912 04235137 7ac5fb32""") _r = long_converter("""01 00000000 00000000 0001f4c8 f927aed3 ca752257""") curve = CurveFp(_p, _a, _b)
def ecdsa_point_creator(x, y): return Point(curve=DefaultCurve.curve, x=x, y=y)
def decode_public_key(public_key): parts = public_key[1:-1].split(',') x = int(parts[0]) y = int(parts[1]) return Point(curve_secp256k1, x, y)
def ser_to_python_ecdsa_point(ser: bytes) -> ecdsa.ellipticcurve.Point: x, y = ser_to_point(ser) return Point(curve_secp256k1, x, y, SECP256k1.order)
def create_verifying_key(x, y): point = Point(SECP256k1.curve, x, y) return VerifyingKey.from_public_point(point, curve=SECP256k1)
def negative(point): return Point(point.curve(), point.x(), -point.y())
def negative_point(P): return Point(P.curve(), P.x(), -P.y(), P.order())
def pointify(pk): return Point(curve_secp256k1, int(pk[0]), int(pk[1]))