def get_pos_y_for_x(pubkey_x, yneg=0): key = pub_key = pub_key_x = pub_key_y = None try: key = OpenSSL.EC_KEY_new_by_curve_name(OpenSSL.get_curve('secp256k1')) group = OpenSSL.EC_KEY_get0_group(key) pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0) pub_key = OpenSSL.EC_POINT_new(group) if OpenSSL.EC_POINT_set_compressed_coordinates_GFp(group, pub_key, pub_key_x, yneg, 0) == 0: raise Exception("[OpenSSL] EC_POINT_set_compressed_coordinates_GFp FAIL ... " + OpenSSL.get_error()) pub_key_y = OpenSSL.BN_new() if (OpenSSL.EC_POINT_get_affine_coordinates_GFp(group, pub_key, pub_key_x, pub_key_y, 0 )) == 0: raise Exception("[OpenSSL] EC_POINT_get_affine_coordinates_GFp FAIL ... " + OpenSSL.get_error()) pubkeyy = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(pub_key_y)) OpenSSL.BN_bn2bin(pub_key_y, pubkeyy) pubkeyy = pubkeyy.raw field_size = OpenSSL.EC_GROUP_get_degree(OpenSSL.EC_KEY_get0_group(key)) secret_len = int((field_size + 7) / 8) if len(pubkeyy) < secret_len: pubkeyy = pubkeyy.rjust(secret_len, b'\0') return pubkeyy finally: if key is not None: OpenSSL.EC_KEY_free(key) if pub_key is not None: OpenSSL.EC_POINT_free(pub_key) if pub_key_x is not None: OpenSSL.BN_free(pub_key_x) if pub_key_y is not None: OpenSSL.BN_free(pub_key_y)
def point_uncompress(self, x, ybit): try: bn_x = OpenSSL.BN_bin2bn(x, len(x), 0) group = OpenSSL.EC_GROUP_new_by_curve_name(self.curve) point = OpenSSL.EC_POINT_new(group) OpenSSL.EC_POINT_set_compressed_coordinates_GFp(group, point, bn_x, ybit, 0) bn_nx = OpenSSL.BN_new() bn_ny = OpenSSL.BN_new() if (OpenSSL.EC_POINT_get_affine_coordinates_GFp(group, point, bn_nx, bn_ny, 0)) == 0: raise Exception("[OpenSSL] EC_POINT_get_affine_coordinates_GFp FAIL ...") nx = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(bn_nx)) ny = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(bn_ny)) OpenSSL.BN_bn2bin(bn_nx, nx) nx = nx.raw OpenSSL.BN_bn2bin(bn_ny, ny) ny = ny.raw return (nx, ny) finally: OpenSSL.BN_free(bn_x) OpenSSL.EC_GROUP_free(group) OpenSSL.EC_POINT_free(point) OpenSSL.BN_free(bn_nx) OpenSSL.BN_free(bn_ny)
def final(self): i = OpenSSL.c_int(0) buffer = OpenSSL.malloc(b"", self.cipher.get_blocksize()) if (OpenSSL.EVP_CipherFinal_ex(self.ctx, OpenSSL.byref(buffer), OpenSSL.byref(i))) == 0: raise Exception("[OpenSSL] EVP_CipherFinal_ex FAIL ...") return buffer.raw[0:i.value]
def raw_encrypt(data, pubkey_x, pubkey_y, curve='sect283r1', ephemcurve=None, ciphername='aes-256-cbc'): if ephemcurve is None: ephemcurve = curve ephem = ECC(curve=ephemcurve) key = sha512(ephem.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() key_e, key_m = key[:32], key[32:] pubkey = ephem.get_pubkey() iv = OpenSSL.rand(OpenSSL.get_cipher(ciphername).get_blocksize()) ctx = Cipher(key_e, iv, 1, ciphername) import time if int(time.time()) < 1416175200: # Sun, 16 Nov 2014 22:00:00 GMT ciphertext = ctx.ciphering(data) else: ciphertext = iv + pubkey + ctx.ciphering( data ) # Everyone should be using this line after the Bitmessage protocol v3 upgrade period mac = hmac_sha256(key_m, ciphertext) if int(time.time()) < 1416175200: # Sun, 16 Nov 2014 22:00:00 GMT return iv + pubkey + ciphertext + mac else: return ciphertext + mac # Everyone should be using this line after the Bitmessage protocol v3 upgrade period
def __set_parameters(self): size = OpenSSL.i2d_ECPKParameters(self.os_group, 0) mb = ctypes.create_string_buffer(size) OpenSSL.i2d_ECPKParameters(self.os_group, ctypes.byref(ctypes.pointer(mb))) asntree = [x for x in ASNHelper.consume( mb.raw )][0] self.ver, self.field, self.curve, self.G_raw, self.order, self.h = asntree if self.field[0] == '42.134.72.206.61.1.1': # Prime field self.field_type = 'prime' self.p = self.field[1] self.bitlength = int( math.ceil( math.log( self.p, 2 ) ) ) self.a = self.curve[0] self.b = self.curve[1] self.f = lambda x: x**3 + self.a*x + self.b elif self.field[0] == '42.134.72.206.61.1.2': # Characteristic two field self.field_type = 'power-of-two' self.m = self.field[1][0] # Maybe bitlength below is not correct..? self.bitlength = self.m + 1 if self.field[1][1] == '42.134.72.206.61.1.2.3.2': # Only one coefficient self.poly_coeffs = [self.field[1][2]] elif self.field[1][1] == '42.134.72.206.61.1.2.3.3': # Several coefficients self.poly_coeffs = self.field[1][2] else: raise Exception('Unknown field OID %s' % self.field[1][1]) self.a = self.curve[0] self.b = self.curve[1] else: raise Exception( 'Unknown curve field' )
def pointMult(secret): # ctx = OpenSSL.BN_CTX_new() #This value proved to cause Seg Faults on # Linux. It turns out that it really didn't speed up EC_POINT_mul anyway. k = OpenSSL.EC_KEY_new_by_curve_name(OpenSSL.get_curve('secp256k1')) priv_key = OpenSSL.BN_bin2bn(secret, 32, 0) group = OpenSSL.EC_KEY_get0_group(k) pub_key = OpenSSL.EC_POINT_new(group) OpenSSL.EC_POINT_mul(group, pub_key, priv_key, None, None, None) OpenSSL.EC_KEY_set_private_key(k, priv_key) OpenSSL.EC_KEY_set_public_key(k, pub_key) # print 'priv_key',priv_key # print 'pub_key',pub_key size = OpenSSL.i2o_ECPublicKey(k, 0) mb = ctypes.create_string_buffer(size) OpenSSL.i2o_ECPublicKey(k, ctypes.byref(ctypes.pointer(mb))) # print 'mb.raw', mb.raw.encode('hex'), 'length:', len(mb.raw) # print 'mb.raw', mb.raw, 'length:', len(mb.raw) OpenSSL.EC_POINT_free(pub_key) # OpenSSL.BN_CTX_free(ctx) OpenSSL.BN_free(priv_key) OpenSSL.EC_KEY_free(k) return mb.raw
def __set_parameters(self): size = OpenSSL.i2d_ECPKParameters(self.os_group, 0) mb = ctypes.create_string_buffer(size) OpenSSL.i2d_ECPKParameters(self.os_group, ctypes.byref(ctypes.pointer(mb))) asntree = [x for x in ASNHelper.consume(mb.raw)][0] self.ver, self.field, self.curve, self.G_raw, self.order, self.h = asntree if self.field[0] == '42.134.72.206.61.1.1': # Prime field self.field_type = 'prime' self.p = self.field[1] self.bitlength = int(math.ceil(math.log(self.p, 2))) self.a = self.curve[0] self.b = self.curve[1] self.f = lambda x: x**3 + self.a * x + self.b elif self.field[ 0] == '42.134.72.206.61.1.2': # Characteristic two field self.field_type = 'power-of-two' self.m = self.field[1][0] # Maybe bitlength below is not correct..? self.bitlength = self.m + 1 if self.field[1][ 1] == '42.134.72.206.61.1.2.3.2': # Only one coefficient self.poly_coeffs = [self.field[1][2]] elif self.field[1][ 1] == '42.134.72.206.61.1.2.3.3': # Several coefficients self.poly_coeffs = self.field[1][2] else: raise Exception('Unknown field OID %s' % self.field[1][1]) self.a = self.curve[0] self.b = self.curve[1] else: raise Exception('Unknown curve field')
def update(self, input): i = OpenSSL.c_int(0) buffer = OpenSSL.malloc(b"", len(input) + self.cipher.get_blocksize()) inp = OpenSSL.malloc(input, len(input)) if OpenSSL.EVP_CipherUpdate(self.ctx, OpenSSL.byref(buffer), OpenSSL.byref(i), inp, len(input)) == 0: raise Exception("[OpenSSL] EVP_CipherUpdate FAIL ...") return buffer.raw[0:i.value]
def verify(self, sig, inputb): """ Verify the signature with the input and the local public key. Returns a boolean """ try: bsig = OpenSSL.malloc(sig, len(sig)) binputb = OpenSSL.malloc(inputb, len(inputb)) digest = OpenSSL.malloc(0, 64) dgst_len = OpenSSL.pointer(OpenSSL.c_int(0)) md_ctx = OpenSSL.EVP_MD_CTX_create() key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x), 0) pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y), 0) group = OpenSSL.EC_KEY_get0_group(key) pub_key = OpenSSL.EC_POINT_new(group) if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, pub_key, pub_key_x, pub_key_y, 0)) == 0: raise Exception( "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...") if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...") if (OpenSSL.EC_KEY_check_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") OpenSSL.EVP_MD_CTX_init(md_ctx) OpenSSL.EVP_DigestInit(md_ctx, OpenSSL.EVP_ecdsa()) if (OpenSSL.EVP_DigestUpdate(md_ctx, binputb, len(inputb))) == 0: raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ...") OpenSSL.EVP_DigestFinal(md_ctx, digest, dgst_len) ret = OpenSSL.ECDSA_verify( 0, digest, dgst_len.contents, bsig, len(sig), key) if ret == -1: return False # Fail to Check else: if ret == 0: return False # Bad signature ! else: return True # Good return False finally: OpenSSL.EC_KEY_free(key) OpenSSL.BN_free(pub_key_x) OpenSSL.BN_free(pub_key_y) OpenSSL.EC_POINT_free(pub_key) OpenSSL.EVP_MD_CTX_destroy(md_ctx)
def hmac_sha512(k, m): """ Compute the key and the message with HMAC SHA512 """ key = OpenSSL.malloc(k, len(k)) d = OpenSSL.malloc(m, len(m)) md = OpenSSL.malloc(0, 64) i = OpenSSL.pointer(OpenSSL.c_int(0)) OpenSSL.HMAC(OpenSSL.EVP_sha512(), key, len(k), d, len(m), md, i) return md.raw
def pbkdf2(password, salt=None, i=10000, keylen=64): if salt is None: salt = OpenSSL.rand(8) p_password = OpenSSL.malloc(password, len(password)) p_salt = OpenSSL.malloc(salt, len(salt)) output = OpenSSL.malloc(0, keylen) OpenSSL.PKCS5_PBKDF2_HMAC(p_password, len(password), p_salt, len(p_salt), i, OpenSSL.EVP_sha256(), keylen, output) return salt, output.raw
def __add__(self, other): """ Add two EC points together """ if isinstance(other, Point): result = OpenSSL.EC_POINT_new(self.os_group) OpenSSL.EC_POINT_add(self.os_group, result, self.os_point, other.os_point, 0) return Point(self.curve, openssl_point=result) else: return NotImplemented
def update(self, input): i = OpenSSL.c_int(0) buffer = OpenSSL.malloc(b"", len(input) + self.cipher.get_blocksize()) inp = OpenSSL.malloc(input, len(input)) if inp is None or buffer is None: raise Exception("Not enough memory") ret = OpenSSL.EVP_CipherUpdate(self.ctx, OpenSSL.byref(buffer), OpenSSL.byref(i), inp, len(input)) if ret == 0: raise Exception("[OpenSSL] EVP_CipherUpdate FAIL: " + str(ret)) return buffer.raw[0:i.value]
def __init__(self, key, iv, do, ciphername='aes-256-cbc'): """ do == 1 => Encrypt; do == 0 => Decrypt """ self.cipher = OpenSSL.get_cipher(ciphername) self.ctx = OpenSSL.EVP_CIPHER_CTX_new() if do == 1 or do == 0: k = OpenSSL.malloc(key, len(key)) IV = OpenSSL.malloc(iv, len(iv)) OpenSSL.EVP_CipherInit_ex( self.ctx, self.cipher.get_pointer(), 0, k, IV, do) else: raise Exception("RTFM ...")
def __init__(self, key, iv, do, ciphername='aes-256-cbc'): """ do == 1 => Encrypt; do == 0 => Decrypt """ self.cipher = OpenSSL.get_cipher(ciphername) self.ctx = OpenSSL.EVP_CIPHER_CTX_new() if do == 1 or do == 0: k = OpenSSL.malloc(key, len(key)) IV = OpenSSL.malloc(iv, len(iv)) OpenSSL.EVP_CipherInit_ex(self.ctx, self.cipher.get_pointer(), 0, k, IV, do) else: raise Exception("RTFM ...")
def raw_encrypt(data, pubkey_x, pubkey_y, curve='sect283r1', ephemcurve=None, ciphername='aes-256-cbc'): if ephemcurve is None: ephemcurve = curve ephem = ECC(curve=ephemcurve) key = sha512(ephem.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() key_e, key_m = key[:32], key[32:] pubkey = ephem.get_pubkey() iv = OpenSSL.rand(OpenSSL.get_cipher(ciphername).get_blocksize()) ctx = Cipher(key_e, iv, 1, ciphername) ciphertext = ctx.ciphering(data) mac = hmac_sha256(key_m, ciphertext) return iv + pubkey + ciphertext + mac
def raw_encrypt(data, pubkey_x, pubkey_y, curve="sect283r1", ephemcurve=None, ciphername="aes-256-cbc"): if ephemcurve is None: ephemcurve = curve ephem = ECC(curve=ephemcurve) key = sha512(ephem.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() key_e, key_m = key[:32], key[32:] pubkey = ephem.get_pubkey() iv = OpenSSL.rand(OpenSSL.get_cipher(ciphername).get_blocksize()) ctx = Cipher(key_e, iv, 1, ciphername) ciphertext = ctx.ciphering(data) # ciphertext = iv + pubkey + ctx.ciphering(data) # We will switch to this line after an upgrade period mac = hmac_sha256(key_m, ciphertext) return iv + pubkey + ciphertext + mac
def _encdec(self, ciphername, msg=None, key=None, iv=None): "Helper: Encrypt, then decrypt random message" block_size = pyelliptic.Cipher.get_blocksize(ciphername) key_size = pyelliptic.Cipher.get_keysize(ciphername) # Generate IV, key and random message if key is None: key = OpenSSL.rand(key_size) if iv is None: iv = pyelliptic.Cipher.gen_IV(ciphername) if msg is None: msg = OpenSSL.rand(block_size) self.assertEqual(len(iv), block_size) self.assertEqual(len(key), key_size) self.assertEqual(len(msg), block_size) # Create ciphers enc_ctx = pyelliptic.Cipher(key=key, iv=iv, do=pyelliptic.Cipher.ENCRYPT, ciphername=ciphername, padding=False) dec_ctx = pyelliptic.Cipher(key, iv, pyelliptic.Cipher.DECRYPT, ciphername=ciphername, padding=False) # Encrypt with a bit mangled case. ciphertext = enc_ctx.update(msg[:10]) ciphertext += enc_ctx.update('') ciphertext += enc_ctx.update(msg[10:]) ciphertext += enc_ctx.update('') ciphertext += enc_ctx.final() self.assertEqual(len(msg), block_size) self.assertEqual(len(ciphertext), block_size) # Result must be of length n*blocksize self.assertEqual(len(ciphertext) % block_size, 0, msg="ciphertext has invalid length") self.assertEqual(len(ciphertext), len(msg), msg="ciphertext length does not equal msg length and no padding is enabled") # Decrypt cleartext = dec_ctx.ciphering(ciphertext) self.assertEqual(msg, cleartext) self.assertNotEqual(msg, ciphertext) return msg, ciphertext
def __init__(self, curvename=None, curveid=None, openssl_group=None): ''' Constructor ''' if curvename != None: curve = OpenSSL.get_curve(curvename) self.os_group = OpenSSL.EC_GROUP_new_by_curve_name(curve) elif curveid != None: self.os_group = OpenSSL.EC_GROUP_new_by_curve_name(curveid) elif openssl_group != None: self.os_group = openssl_group else: raise Exception('No curve provided') self.__set_parameters() self.__set_base_point()
def decrypt(self, data, ciphername="aes-256-cbc"): """ Decrypt data with ECIES method using the local private key """ blocksize = OpenSSL.get_cipher(ciphername).get_blocksize() iv = data[:blocksize] i = blocksize curve, pubkey_x, pubkey_y, i2 = ECC._decode_pubkey(data[i:]) i += i2 ciphertext = data[i : len(data) - 32] i += len(ciphertext) mac = data[i:] key = sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() key_e, key_m = key[:32], key[32:] """ pyelliptic was changed slightly so that the hmac covers the iv and pubkey. So let's have an upgrade period where we support both the old and the new hmac'ing algorithms. https://github.com/yann2192/pyelliptic/issues/17 """ if hmac_sha256(key_m, ciphertext) != mac: if hmac_sha256(key_m, data[: len(data) - 32]) != mac: raise RuntimeError("Fail to verify data") ctx = Cipher(key_e, iv, 0, ciphername) return ctx.ciphering(ciphertext)
def decrypt(self, data, ciphername='aes-256-cbc'): """ Decrypt data with ECIES method using the local private key """ blocksize = OpenSSL.get_cipher(ciphername).get_blocksize() iv = data[:blocksize] i = blocksize curve, pubkey_x, pubkey_y, i2 = ECC._decode_pubkey(data[i:]) i += i2 ciphertext = data[i:len(data) - 32] i += len(ciphertext) mac = data[i:] key = sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() key_e, key_m = key[:32], key[32:] """ pyelliptic was changed slightly so that the hmac covers the iv and pubkey. So let's have an upgrade period where we support both the old and the new hmac'ing algorithms. https://github.com/yann2192/pyelliptic/issues/17 """ if hmac_sha256(key_m, ciphertext) != mac: if hmac_sha256(key_m, data[:len(data) - 32]) != mac: raise RuntimeError("Fail to verify data") ctx = Cipher(key_e, iv, 0, ciphername) return ctx.ciphering(ciphertext)
def __init__(self, pubkey=None, privkey=None, pubkey_x=None, pubkey_y=None, raw_privkey=None, curve='sect283r1'): """ For a normal and High level use, specifie pubkey, privkey (if you need) and the curve """ if type(curve) == str: self.curve = OpenSSL.get_curve(curve) else: self.curve = curve if pubkey_x is not None and pubkey_y is not None: self._set_keys(pubkey_x, pubkey_y, raw_privkey) elif pubkey is not None: curve, pubkey_x, pubkey_y, i = ECC._decode_pubkey(pubkey) if privkey is not None: curve2, raw_privkey, i = ECC._decode_privkey(privkey) if curve != curve2: raise Exception("Bad ECC keys ...") self.curve = curve self._set_keys(pubkey_x, pubkey_y, raw_privkey) else: self.privkey, self.pubkey_x, self.pubkey_y = self._generate()
def __init__( self, pubkey=None, privkey=None, pubkey_x=None, pubkey_y=None, raw_privkey=None, curve='sect283r1', ): # pylint: disable=too-many-arguments """ For a normal and High level use, specifie pubkey, privkey (if you need) and the curve """ if isinstance(curve, str): self.curve = OpenSSL.get_curve(curve) else: self.curve = curve if pubkey_x is not None and pubkey_y is not None: self._set_keys(pubkey_x, pubkey_y, raw_privkey) elif pubkey is not None: curve, pubkey_x, pubkey_y, _ = ECC._decode_pubkey(pubkey) if privkey is not None: curve2, raw_privkey, _ = ECC._decode_privkey(privkey) if curve != curve2: raise Exception("Bad ECC keys ...") self.curve = curve self._set_keys(pubkey_x, pubkey_y, raw_privkey) else: self.privkey, self.pubkey_x, self.pubkey_y = self._generate()
def send(self): status, addressVersionNumber, streamNumber, ripe = decodeAddress( self.toAddress) ackdata = OpenSSL.rand(32) t = () sqlExecute( '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', '', self.toAddress, ripe, self.fromAddress, self.subject, self.message, ackdata, int(time.time()), # sentTime (this will never change) int(time.time()), # lastActionTime 0, # sleepTill time. This will get set when the POW gets done. 'msgqueued', 0, # retryNumber 'sent', # folder 2, # encodingtype min(shared.config.getint('bitmessagesettings', 'ttl'), 86400 * 2) # not necessary to have a TTL higher than 2 days ) shared.workerQueue.put(('sendmessage', self.toAddress))
def __mul__(self, other): """ Multiply an EC point by a scalar value and returns the multiplication result """ if isinstance(other, int) or isinstance(other, long): try: o = ec_bignum.BigNum(decval=other) result = OpenSSL.EC_POINT_new(self.os_group) OpenSSL.EC_POINT_mul(self.os_group, result, 0, self.os_point, o.bn, 0) return Point(self.curve, openssl_point=result) finally: del o else: return NotImplemented
def raw_encrypt(data, pubkey_x, pubkey_y, curve='sect283r1', ephemcurve=None, ciphername='aes-256-cbc'): if ephemcurve is None: ephemcurve = curve ephem = ECC(curve=ephemcurve) key = sha512(ephem.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() key_e, key_m = key[:32], key[32:] pubkey = ephem.get_pubkey() iv = OpenSSL.rand(OpenSSL.get_cipher(ciphername).get_blocksize()) ctx = Cipher(key_e, iv, 1, ciphername) ciphertext = iv + pubkey + ctx.ciphering(data) mac = hmac_sha256(key_m, ciphertext) return ciphertext + mac
def __set_to_coordinates(self, x_val, y_val): try: point = OpenSSL.EC_POINT_new(self.os_group) x, y = ec_bignum.BigNum(decval=x_val), ec_bignum.BigNum( decval=y_val) if self.curve.field_type == 'prime': OpenSSL.EC_POINT_set_affine_coordinates_GFp( self.os_group, point, x.bn, y.bn, None) elif self.curve.field_type == 'characteristic-two': OpenSSL.EC_POINT_set_affine_coordinates_GF2m( self.os_group, point, x.bn, y.bn, None) self.x, self.y = x_val, y_val self.os_point = point finally: del x, y
def __init__(self, curve, os_key=None, private_key=None): ''' Constructor ''' if not isinstance(curve, ec_curve.Curve): raise Exception('Provided curve is not a Curve object') self.curve = curve self.os_group = curve.os_group if os_key is not None: self.os_key = os_key else: self.os_key = OpenSSL.EC_KEY_new() OpenSSL.EC_KEY_set_group(self.os_key, self.os_group) if private_key is not None: privk = ec_bignum.BigNum(decval=private_key) pubk = private_key * curve.G OpenSSL.EC_KEY_set_private_key(self.os_key, privk.bn) OpenSSL.EC_KEY_set_public_key(self.os_key, pubk.os_point) else: OpenSSL.EC_KEY_generate_key(self.os_key) try: priv_key = ec_bignum.BigNum( OpenSSL.EC_KEY_get0_private_key(self.os_key)) self.private_key = priv_key.get_value() self.public_key = ec_point.Point( self.curve, openssl_point=OpenSSL.EC_KEY_get0_public_key(self.os_key)) finally: del priv_key
def sign(self, inputb): """ Sign the input with ECDSA method and returns the signature """ try: size = len(inputb) buff = OpenSSL.malloc(inputb, size) digest = OpenSSL.malloc(0, 64) md_ctx = OpenSSL.EVP_MD_CTX_create() dgst_len = OpenSSL.pointer(OpenSSL.c_int(0)) siglen = OpenSSL.pointer(OpenSSL.c_int(0)) sig = OpenSSL.malloc(0, 151) key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") priv_key = OpenSSL.BN_bin2bn(self.privkey, len(self.privkey), 0) pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x), 0) pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y), 0) if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_private_key FAIL ...") group = OpenSSL.EC_KEY_get0_group(key) pub_key = OpenSSL.EC_POINT_new(group) if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, pub_key, pub_key_x, pub_key_y, 0)) == 0: raise Exception( "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...") if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...") if (OpenSSL.EC_KEY_check_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") OpenSSL.EVP_MD_CTX_init(md_ctx) OpenSSL.EVP_DigestInit(md_ctx, OpenSSL.EVP_ecdsa()) if (OpenSSL.EVP_DigestUpdate(md_ctx, buff, size)) == 0: raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ...") OpenSSL.EVP_DigestFinal(md_ctx, digest, dgst_len) OpenSSL.ECDSA_sign(0, digest, dgst_len.contents, sig, siglen, key) if (OpenSSL.ECDSA_verify(0, digest, dgst_len.contents, sig, siglen.contents, key)) != 1: raise Exception("[OpenSSL] ECDSA_verify FAIL ...") return sig.raw[0:siglen.contents.value] finally: OpenSSL.EC_KEY_free(key) OpenSSL.BN_free(pub_key_x) OpenSSL.BN_free(pub_key_y) OpenSSL.BN_free(priv_key) OpenSSL.EC_POINT_free(pub_key) OpenSSL.EVP_MD_CTX_destroy(md_ctx)
def __init__(self, os_bn=None,decval=None,binval=None): """ Constructs a new BN object and fills it with the value given. """ if os_bn is not None: self.bn = os_bn self.__created_bn = False else: self.bn = OpenSSL.BN_new() self.__created_bn = True if decval is None and binval is None: decval = 0 if decval is not None: binval = ECHelper.int2bin( decval ) if binval is not None: OpenSSL.BN_bin2bn( binval, len( binval ), self.bn )
def raw_get_ecdh_key(self, pubkey_x, pubkey_y): try: ecdh_keybuffer = OpenSSL.malloc(0, 32) other_key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if other_key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") other_pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0) other_pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), 0) other_group = OpenSSL.EC_KEY_get0_group(other_key) other_pub_key = OpenSSL.EC_POINT_new(other_group) if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(other_group, other_pub_key, other_pub_key_x, other_pub_key_y, 0)) == 0: raise Exception( "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...") if (OpenSSL.EC_KEY_set_public_key(other_key, other_pub_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...") if (OpenSSL.EC_KEY_check_key(other_key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") own_key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if own_key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") own_priv_key = OpenSSL.BN_bin2bn( self.privkey, len(self.privkey), 0) if (OpenSSL.EC_KEY_set_private_key(own_key, own_priv_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_private_key FAIL ...") if OpenSSL._hexversion > 0x10100000 and not OpenSSL._libreSSL: OpenSSL.EC_KEY_set_method(own_key, OpenSSL.EC_KEY_OpenSSL()) else: OpenSSL.ECDH_set_method(own_key, OpenSSL.ECDH_OpenSSL()) ecdh_keylen = OpenSSL.ECDH_compute_key( ecdh_keybuffer, 32, other_pub_key, own_key, 0) if ecdh_keylen != 32: raise Exception("[OpenSSL] ECDH keylen FAIL ...") return ecdh_keybuffer.raw finally: OpenSSL.EC_KEY_free(other_key) OpenSSL.BN_free(other_pub_key_x) OpenSSL.BN_free(other_pub_key_y) OpenSSL.EC_POINT_free(other_pub_key) OpenSSL.EC_KEY_free(own_key) OpenSSL.BN_free(own_priv_key)
def __init__(self, key, iv, do, ciphername='aes-256-cbc', padding=True): """ do == 1 => Encrypt; do == 0 => Decrypt """ assert do in [self.ENCRYPT, self.DECRYPT], "Argument 'do' out of scope" self.cipher = OpenSSL.get_cipher(ciphername) self.ctx = OpenSSL.EVP_CIPHER_CTX_new() keysize = self.cipher.get_keysize() assert keysize is None or len(key) == keysize assert len(iv) == self.cipher.get_blocksize() k = OpenSSL.malloc(key, len(key)) IV = OpenSSL.malloc(iv, len(iv)) OpenSSL.EVP_CipherInit_ex( self.ctx, self.cipher.get_pointer(), 0, k, IV, do) if padding is False: # By default PKCS padding is enabled. This case disables it. OpenSSL.EVP_CIPHER_CTX_set_padding(self.ctx, 0)
def _generate(self): try: pub_key_x = OpenSSL.BN_new() pub_key_y = OpenSSL.BN_new() key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") if (OpenSSL.EC_KEY_generate_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_generate_key FAIL ...") if (OpenSSL.EC_KEY_check_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") priv_key = OpenSSL.EC_KEY_get0_private_key(key) group = OpenSSL.EC_KEY_get0_group(key) pub_key = OpenSSL.EC_KEY_get0_public_key(key) if (OpenSSL.EC_POINT_get_affine_coordinates_GFp(group, pub_key, pub_key_x, pub_key_y, 0 )) == 0: raise Exception( "[OpenSSL] EC_POINT_get_affine_coordinates_GFp FAIL ...") privkey = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(priv_key)) pubkeyx = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(pub_key_x)) pubkeyy = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(pub_key_y)) OpenSSL.BN_bn2bin(priv_key, privkey) privkey = privkey.raw OpenSSL.BN_bn2bin(pub_key_x, pubkeyx) pubkeyx = pubkeyx.raw OpenSSL.BN_bn2bin(pub_key_y, pubkeyy) pubkeyy = pubkeyy.raw self.raw_check_key(privkey, pubkeyx, pubkeyy) return privkey, pubkeyx, pubkeyy finally: OpenSSL.EC_KEY_free(key) OpenSSL.BN_free(pub_key_x) OpenSSL.BN_free(pub_key_y)
def __set_to_openssl_point(self, point): try: x, y = ec_bignum.BigNum(), ec_bignum.BigNum() # Put X and Y coordinates of public key into x and y vars OpenSSL.EC_POINT_get_affine_coordinates_GFp( self.os_group, point, x.bn, y.bn, None) self.x, self.y = x.get_value(), y.get_value() self.os_point = point finally: del x, y
def raw_encrypt( data, pubkey_x, pubkey_y, curve='sect283r1', ephemcurve=None, ciphername='aes-256-cbc', ): # pylint: disable=too-many-arguments """ECHD encryption, keys supplied in binary data format""" if ephemcurve is None: ephemcurve = curve ephem = ECC(curve=ephemcurve) key = sha512(ephem.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() key_e, key_m = key[:32], key[32:] pubkey = ephem.get_pubkey() iv = OpenSSL.rand(OpenSSL.get_cipher(ciphername).get_blocksize()) ctx = Cipher(key_e, iv, 1, ciphername) ciphertext = iv + pubkey + ctx.ciphering(data) mac = hmac_sha256(key_m, ciphertext) return ciphertext + mac
def sendMessage(toAddress, subject, message): if len(shared.myAddressesByTag) == 0: generateNewAddress() fromAddress = getCurrentAddress() status, addressVersionNumber, streamNumber, toRipe = addresses.decodeAddress(toAddress) ackdata = OpenSSL.rand(32) TTL = 4*24*60*60 t = ('', toAddress, toRipe, fromAddress, subject, message, ackdata, int(time.time()), int(time.time()), 0, 'msgqueued', 0, 'sent', 2, TTL) helper_sent.insert(t) shared.workerQueue.put(('sendmessage', toAddress)) return ackdata
def oct2point(self, data): try: group = OpenSSL.EC_GROUP_new_by_curve_name(self.curve) point = OpenSSL.EC_POINT_new(group) OpenSSL.EC_POINT_oct2point(group, point, data, len(data), 0) bn_x = OpenSSL.BN_new() bn_y = OpenSSL.BN_new() if (OpenSSL.EC_POINT_get_affine_coordinates_GFp(group, point, bn_x, bn_y, 0)) == 0: raise Exception("[OpenSSL] EC_POINT_get_affine_coordinates_GFp FAIL ...") x = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(bn_x)) y = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(bn_y)) OpenSSL.BN_bn2bin(bn_x, x) x = x.raw OpenSSL.BN_bn2bin(bn_y, y) y = y.raw return (x, y) finally: OpenSSL.EC_GROUP_free(group) OpenSSL.EC_POINT_free(point) OpenSSL.BN_free(bn_x) OpenSSL.BN_free(bn_y)
def sendMessage(toAddress, subject, message): if len(shared.myAddressesByTag) == 0: generateNewAddress() fromAddress = getCurrentAddress() status, addressVersionNumber, streamNumber, toRipe = addresses.decodeAddress( toAddress) ackdata = OpenSSL.rand(32) TTL = 4 * 24 * 60 * 60 t = ('', toAddress, toRipe, fromAddress, subject, message, ackdata, int(time.time()), int(time.time()), 0, 'msgqueued', 0, 'sent', 2, TTL) helper_sent.insert(t) shared.workerQueue.put(('sendmessage', toAddress)) return ackdata
def raw_encrypt(data, pubkey_x, pubkey_y, curve="sect283r1", ephemcurve=None, ciphername="aes-256-cbc"): if ephemcurve is None: ephemcurve = curve ephem = ECC(curve=ephemcurve) key = sha512(ephem.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() key_e, key_m = key[:32], key[32:] pubkey = ephem.get_pubkey() iv = OpenSSL.rand(OpenSSL.get_cipher(ciphername).get_blocksize()) ctx = Cipher(key_e, iv, 1, ciphername) import time if int(time.time()) < 1416175200: # Sun, 16 Nov 2014 22:00:00 GMT ciphertext = ctx.ciphering(data) else: ciphertext = ( iv + pubkey + ctx.ciphering(data) ) # Everyone should be using this line after the Bitmessage protocol v3 upgrade period mac = hmac_sha256(key_m, ciphertext) if int(time.time()) < 1416175200: # Sun, 16 Nov 2014 22:00:00 GMT return iv + pubkey + ciphertext + mac else: return ( ciphertext + mac ) # Everyone should be using this line after the Bitmessage protocol v3 upgrade period
def __init__(self, curvename=None, curveid=None, openssl_group=None): ''' Constructor ''' if curvename != None: curve = OpenSSL.get_curve( curvename ) self.os_group = OpenSSL.EC_GROUP_new_by_curve_name( curve ) elif curveid != None: self.os_group = OpenSSL.EC_GROUP_new_by_curve_name( curveid ) elif openssl_group != None: self.os_group = openssl_group else: raise Exception('No curve provided') self.__set_parameters() self.__set_base_point()
def decrypt(self, data, ciphername='aes-256-cbc'): """ Decrypt data with ECIES method using the local private key """ blocksize = OpenSSL.get_cipher(ciphername).get_blocksize() iv = data[:blocksize] i = blocksize curve, pubkey_x, pubkey_y, i2 = ECC._decode_pubkey(data[i:]) i += i2 ciphertext = data[i:len(data)-32] i += len(ciphertext) mac = data[i:] key = sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() key_e, key_m = key[:32], key[32:] if hmac_sha256(key_m, ciphertext) != mac: raise RuntimeError("Fail to verify data") ctx = Cipher(key_e, iv, 0, ciphername) return ctx.ciphering(ciphertext)
def decrypt(self, data, ciphername='aes-256-cbc'): """ Decrypt data with ECIES method using the local private key """ blocksize = OpenSSL.get_cipher(ciphername).get_blocksize() iv = data[:blocksize] i = blocksize curve, pubkey_x, pubkey_y, i2 = ECC._decode_pubkey(data[i:]) i += i2 ciphertext = data[i:len(data) - 32] i += len(ciphertext) mac = data[i:] key = sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() key_e, key_m = key[:32], key[32:] if not equals(hmac_sha256(key_m, data[:len(data) - 32]), mac): raise RuntimeError("Fail to verify data") ctx = Cipher(key_e, iv, 0, ciphername) return ctx.ciphering(ciphertext)
def raw_check_key(self, privkey, pubkey_x, pubkey_y, curve=None): if curve is None: curve = self.curve elif type(curve) == str: curve = OpenSSL.get_curve(curve) else: curve = curve try: key = OpenSSL.EC_KEY_new_by_curve_name(curve) if key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") if privkey is not None: priv_key = OpenSSL.BN_bin2bn(privkey, len(privkey), 0) pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0) pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), 0) if privkey is not None: if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0: raise Exception( "[OpenSSL] EC_KEY_set_private_key FAIL ...") group = OpenSSL.EC_KEY_get0_group(key) pub_key = OpenSSL.EC_POINT_new(group) if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, pub_key, pub_key_x, pub_key_y, 0)) == 0: raise Exception( "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...") if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...") if (OpenSSL.EC_KEY_check_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") return 0 finally: OpenSSL.EC_KEY_free(key) OpenSSL.BN_free(pub_key_x) OpenSSL.BN_free(pub_key_y) OpenSSL.EC_POINT_free(pub_key) if privkey is not None: OpenSSL.BN_free(priv_key)
def __init__(self, pubkey=None, privkey=None, pubkey_x=None, pubkey_y=None, raw_privkey=None, curve="sect283r1"): """ For a normal and High level use, specifie pubkey, privkey (if you need) and the curve """ if type(curve) == str: self.curve = OpenSSL.get_curve(curve) else: self.curve = curve if pubkey_x is not None and pubkey_y is not None: self._set_keys(pubkey_x, pubkey_y, raw_privkey) elif pubkey is not None: curve, pubkey_x, pubkey_y, i = ECC._decode_pubkey(pubkey) if privkey is not None: curve2, raw_privkey, i = ECC._decode_privkey(privkey) if curve != curve2: raise Exception("Bad ECC keys ...") self.curve = curve self._set_keys(pubkey_x, pubkey_y, raw_privkey) else: self.privkey, self.pubkey_x, self.pubkey_y = self._generate()
def send(self): status, addressVersionNumber, streamNumber, ripe = decodeAddress(self.toAddress) ackdata = OpenSSL.rand(32) t = () sqlExecute( """INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""", "", self.toAddress, ripe, self.fromAddress, self.subject, self.message, ackdata, int(time.time()), # sentTime (this will never change) int(time.time()), # lastActionTime 0, # sleepTill time. This will get set when the POW gets done. "msgqueued", 0, # retryNumber "sent", # folder 2, # encodingtype shared.config.getint("bitmessagesettings", "ttl"), ) shared.workerQueue.put(("sendmessage", self.toAddress))
def point_compress(self, x, y): POINT_CONVERSION_COMPRESSED = 2 POINT_CONVERSION_UNCOMPRESSED = 4 try: bn_x = OpenSSL.BN_bin2bn(x, len(x), 0) bn_y = OpenSSL.BN_bin2bn(y, len(y), 0) key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") group = OpenSSL.EC_KEY_get0_group(key) point = OpenSSL.EC_POINT_new(group) if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, point, bn_x, bn_y, 0)) == 0: raise Exception("[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...") if (OpenSSL.EC_KEY_set_public_key(key, point)) == 0: raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...") if (OpenSSL.EC_KEY_check_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") reqlength = OpenSSL.EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, 0, 0, 0) if reqlength == 0: raise Exception("[OpenSSL] EC_POINT_point2oct FAIL ...") comp = OpenSSL.malloc(0, reqlength) length = OpenSSL.EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, comp, reqlength, 0) if length == 0: raise Exception("[OpenSSL] EC_POINT_point2oct FAIL ...") assert reqlength == length return comp.raw finally: OpenSSL.BN_free(bn_x) OpenSSL.BN_free(bn_y) OpenSSL.EC_KEY_free(key) OpenSSL.EC_POINT_free(point)
def send(self): status, addressVersionNumber, streamNumber, ripe = decodeAddress(self.toAddress) ackdata = OpenSSL.rand(32) t = () sqlExecute( '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', '', self.toAddress, ripe, self.fromAddress, self.subject, self.message, ackdata, int(time.time()), # sentTime (this will never change) int(time.time()), # lastActionTime 0, # sleepTill time. This will get set when the POW gets done. 'msgqueued', 0, # retryNumber 'sent', # folder 2, # encodingtype min(shared.config.getint('bitmessagesettings', 'ttl'), 86400 * 2) # not necessary to have a TTL higher than 2 days ) shared.workerQueue.put(('sendmessage', self.toAddress))
def run(self): while state.shutdown == 0: queueValue = queues.addressGeneratorQueue.get() nonceTrialsPerByte = 0 payloadLengthExtraBytes = 0 live = True if queueValue[0] == 'createChan': command, addressVersionNumber, streamNumber, label, \ deterministicPassphrase, live = queueValue eighteenByteRipe = False numberOfAddressesToMake = 1 numberOfNullBytesDemandedOnFrontOfRipeHash = 1 elif queueValue[0] == 'joinChan': command, chanAddress, label, deterministicPassphrase, \ live = queueValue eighteenByteRipe = False addressVersionNumber = decodeAddress(chanAddress)[1] streamNumber = decodeAddress(chanAddress)[2] numberOfAddressesToMake = 1 numberOfNullBytesDemandedOnFrontOfRipeHash = 1 elif len(queueValue) == 7: command, addressVersionNumber, streamNumber, label, \ numberOfAddressesToMake, deterministicPassphrase, \ eighteenByteRipe = queueValue try: numberOfNullBytesDemandedOnFrontOfRipeHash = \ BMConfigParser().getint( 'bitmessagesettings', 'numberofnullbytesonaddress' ) except: if eighteenByteRipe: numberOfNullBytesDemandedOnFrontOfRipeHash = 2 else: # the default numberOfNullBytesDemandedOnFrontOfRipeHash = 1 elif len(queueValue) == 9: command, addressVersionNumber, streamNumber, label, \ numberOfAddressesToMake, deterministicPassphrase, \ eighteenByteRipe, nonceTrialsPerByte, \ payloadLengthExtraBytes = queueValue try: numberOfNullBytesDemandedOnFrontOfRipeHash = \ BMConfigParser().getint( 'bitmessagesettings', 'numberofnullbytesonaddress' ) except: if eighteenByteRipe: numberOfNullBytesDemandedOnFrontOfRipeHash = 2 else: # the default numberOfNullBytesDemandedOnFrontOfRipeHash = 1 elif queueValue[0] == 'stopThread': break else: logger.error( 'Programming error: A structure with the wrong number' ' of values was passed into the addressGeneratorQueue.' ' Here is the queueValue: %r\n', queueValue) if addressVersionNumber < 3 or addressVersionNumber > 4: logger.error( 'Program error: For some reason the address generator' ' queue has been given a request to create at least' ' one version %s address which it cannot do.\n', addressVersionNumber) if nonceTrialsPerByte == 0: nonceTrialsPerByte = BMConfigParser().getint( 'bitmessagesettings', 'defaultnoncetrialsperbyte') if nonceTrialsPerByte < \ defaults.networkDefaultProofOfWorkNonceTrialsPerByte: nonceTrialsPerByte = \ defaults.networkDefaultProofOfWorkNonceTrialsPerByte if payloadLengthExtraBytes == 0: payloadLengthExtraBytes = BMConfigParser().getint( 'bitmessagesettings', 'defaultpayloadlengthextrabytes') if payloadLengthExtraBytes < \ defaults.networkDefaultPayloadLengthExtraBytes: payloadLengthExtraBytes = \ defaults.networkDefaultPayloadLengthExtraBytes if command == 'createRandomAddress': queues.UISignalQueue.put( ('updateStatusBar', tr._translate("MainWindow", "Generating one new address"))) # This next section is a little bit strange. We're going # to generate keys over and over until we find one # that starts with either \x00 or \x00\x00. Then when # we pack them into a Bitmessage address, we won't store # the \x00 or \x00\x00 bytes thus making the address shorter. startTime = time.time() numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0 potentialPrivSigningKey = OpenSSL.rand(32) potentialPubSigningKey = highlevelcrypto.pointMult( potentialPrivSigningKey) while True: numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1 potentialPrivEncryptionKey = OpenSSL.rand(32) potentialPubEncryptionKey = highlevelcrypto.pointMult( potentialPrivEncryptionKey) sha = hashlib.new('sha512') sha.update(potentialPubSigningKey + potentialPubEncryptionKey) ripe = RIPEMD160Hash(sha.digest()).digest() if (ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash] == '\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash): break logger.info('Generated address with ripe digest: %s', hexlify(ripe)) try: logger.info( 'Address generator calculated %s addresses at %s' ' addresses per second before finding one with' ' the correct ripe-prefix.', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix / (time.time() - startTime)) except ZeroDivisionError: # The user must have a pretty fast computer. # time.time() - startTime equaled zero. pass address = encodeAddress(addressVersionNumber, streamNumber, ripe) # An excellent way for us to store our keys # is in Wallet Import Format. Let us convert now. # https://en.bitcoin.it/wiki/Wallet_import_format privSigningKey = '\x80' + potentialPrivSigningKey checksum = hashlib.sha256( hashlib.sha256(privSigningKey).digest()).digest()[0:4] privSigningKeyWIF = arithmetic.changebase( privSigningKey + checksum, 256, 58) privEncryptionKey = '\x80' + potentialPrivEncryptionKey checksum = hashlib.sha256( hashlib.sha256(privEncryptionKey).digest()).digest()[0:4] privEncryptionKeyWIF = arithmetic.changebase( privEncryptionKey + checksum, 256, 58) BMConfigParser().add_section(address) BMConfigParser().set(address, 'label', label) BMConfigParser().set(address, 'enabled', 'true') BMConfigParser().set(address, 'decoy', 'false') BMConfigParser().set(address, 'noncetrialsperbyte', str(nonceTrialsPerByte)) BMConfigParser().set(address, 'payloadlengthextrabytes', str(payloadLengthExtraBytes)) BMConfigParser().set(address, 'privsigningkey', privSigningKeyWIF) BMConfigParser().set(address, 'privencryptionkey', privEncryptionKeyWIF) BMConfigParser().save() # The API and the join and create Chan functionality # both need information back from the address generator. queues.apiAddressGeneratorReturnQueue.put(address) queues.UISignalQueue.put( ('updateStatusBar', tr._translate( "MainWindow", "Done generating address. Doing work necessary" " to broadcast it..."))) queues.UISignalQueue.put( ('writeNewAddressToTable', (label, address, streamNumber))) shared.reloadMyAddressHashes() if addressVersionNumber == 3: queues.workerQueue.put(('sendOutOrStoreMyV3Pubkey', ripe)) elif addressVersionNumber == 4: queues.workerQueue.put( ('sendOutOrStoreMyV4Pubkey', address)) elif command == 'createDeterministicAddresses' \ or command == 'getDeterministicAddress' \ or command == 'createChan' or command == 'joinChan': if len(deterministicPassphrase) == 0: logger.warning( 'You are creating deterministic' ' address(es) using a blank passphrase.' ' Bitmessage will do it but it is rather stupid.') if command == 'createDeterministicAddresses': queues.UISignalQueue.put( ('updateStatusBar', tr._translate("MainWindow", "Generating %1 new addresses.").arg( str(numberOfAddressesToMake)))) signingKeyNonce = 0 encryptionKeyNonce = 1 # We fill out this list no matter what although we only # need it if we end up passing the info to the API. listOfNewAddressesToSendOutThroughTheAPI = [] for _ in range(numberOfAddressesToMake): # This next section is a little bit strange. We're # going to generate keys over and over until we find # one that has a RIPEMD hash that starts with either # \x00 or \x00\x00. Then when we pack them into a # Bitmessage address, we won't store the \x00 or # \x00\x00 bytes thus making the address shorter. startTime = time.time() numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0 while True: numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1 potentialPrivSigningKey = hashlib.sha512( deterministicPassphrase + encodeVarint(signingKeyNonce)).digest()[:32] potentialPrivEncryptionKey = hashlib.sha512( deterministicPassphrase + encodeVarint(encryptionKeyNonce)).digest()[:32] potentialPubSigningKey = highlevelcrypto.pointMult( potentialPrivSigningKey) potentialPubEncryptionKey = highlevelcrypto.pointMult( potentialPrivEncryptionKey) signingKeyNonce += 2 encryptionKeyNonce += 2 sha = hashlib.new('sha512') sha.update(potentialPubSigningKey + potentialPubEncryptionKey) ripe = RIPEMD160Hash(sha.digest()).digest() if (ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash] == '\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash): break logger.info('Generated address with ripe digest: %s', hexlify(ripe)) try: logger.info( 'Address generator calculated %s addresses' ' at %s addresses per second before finding' ' one with the correct ripe-prefix.', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix / (time.time() - startTime)) except ZeroDivisionError: # The user must have a pretty fast computer. # time.time() - startTime equaled zero. pass address = encodeAddress(addressVersionNumber, streamNumber, ripe) saveAddressToDisk = True # If we are joining an existing chan, let us check # to make sure it matches the provided Bitmessage address if command == 'joinChan': if address != chanAddress: listOfNewAddressesToSendOutThroughTheAPI.append( 'chan name does not match address') saveAddressToDisk = False if command == 'getDeterministicAddress': saveAddressToDisk = False if saveAddressToDisk and live: # An excellent way for us to store our keys is # in Wallet Import Format. Let us convert now. # https://en.bitcoin.it/wiki/Wallet_import_format privSigningKey = '\x80' + potentialPrivSigningKey checksum = hashlib.sha256( hashlib.sha256( privSigningKey).digest()).digest()[0:4] privSigningKeyWIF = arithmetic.changebase( privSigningKey + checksum, 256, 58) privEncryptionKey = '\x80' + \ potentialPrivEncryptionKey checksum = hashlib.sha256( hashlib.sha256( privEncryptionKey).digest()).digest()[0:4] privEncryptionKeyWIF = arithmetic.changebase( privEncryptionKey + checksum, 256, 58) try: BMConfigParser().add_section(address) addressAlreadyExists = False except: addressAlreadyExists = True if addressAlreadyExists: logger.info( '%s already exists. Not adding it again.', address) queues.UISignalQueue.put( ('updateStatusBar', tr._translate( "MainWindow", "%1 is already in 'Your Identities'." " Not adding it again.").arg(address))) else: logger.debug('label: %s', label) BMConfigParser().set(address, 'label', label) BMConfigParser().set(address, 'enabled', 'true') BMConfigParser().set(address, 'decoy', 'false') if command == 'joinChan' \ or command == 'createChan': BMConfigParser().set(address, 'chan', 'true') BMConfigParser().set(address, 'noncetrialsperbyte', str(nonceTrialsPerByte)) BMConfigParser().set(address, 'payloadlengthextrabytes', str(payloadLengthExtraBytes)) BMConfigParser().set(address, 'privSigningKey', privSigningKeyWIF) BMConfigParser().set(address, 'privEncryptionKey', privEncryptionKeyWIF) BMConfigParser().save() queues.UISignalQueue.put( ('writeNewAddressToTable', (label, address, str(streamNumber)))) listOfNewAddressesToSendOutThroughTheAPI.append( address) shared.myECCryptorObjects[ripe] = \ highlevelcrypto.makeCryptor( hexlify(potentialPrivEncryptionKey)) shared.myAddressesByHash[ripe] = address tag = hashlib.sha512( hashlib.sha512( encodeVarint(addressVersionNumber) + encodeVarint(streamNumber) + ripe).digest()).digest()[32:] shared.myAddressesByTag[tag] = address if addressVersionNumber == 3: # If this is a chan address, # the worker thread won't send out # the pubkey over the network. queues.workerQueue.put( ('sendOutOrStoreMyV3Pubkey', ripe)) elif addressVersionNumber == 4: queues.workerQueue.put( ('sendOutOrStoreMyV4Pubkey', address)) queues.UISignalQueue.put( ('updateStatusBar', tr._translate("MainWindow", "Done generating address"))) elif saveAddressToDisk and not live \ and not BMConfigParser().has_section(address): listOfNewAddressesToSendOutThroughTheAPI.append( address) # Done generating addresses. if command == 'createDeterministicAddresses' \ or command == 'joinChan' or command == 'createChan': queues.apiAddressGeneratorReturnQueue.put( listOfNewAddressesToSendOutThroughTheAPI) elif command == 'getDeterministicAddress': queues.apiAddressGeneratorReturnQueue.put(address) else: raise Exception( "Error in the addressGenerator thread. Thread was" + " given a command it could not understand: " + command) queues.addressGeneratorQueue.task_done()
def get_curve(self): return OpenSSL.get_curve_by_id(self.curve)
def verify(self, sig, inputb, digest_alg=OpenSSL.digest_ecdsa_sha1): """ Verify the signature with the input and the local public key. Returns a boolean """ try: bsig = OpenSSL.malloc(sig, len(sig)) binputb = OpenSSL.malloc(inputb, len(inputb)) digest = OpenSSL.malloc(0, 64) dgst_len = OpenSSL.pointer(OpenSSL.c_int(0)) if OpenSSL._hexversion > 0x10100000 and not OpenSSL._libreSSL: md_ctx = OpenSSL.EVP_MD_CTX_new() else: md_ctx = OpenSSL.EVP_MD_CTX_create() key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x), 0) pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y), 0) group = OpenSSL.EC_KEY_get0_group(key) pub_key = OpenSSL.EC_POINT_new(group) if (OpenSSL.EC_POINT_set_affine_coordinates_GFp( group, pub_key, pub_key_x, pub_key_y, 0)) == 0: raise Exception( "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...") if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...") if (OpenSSL.EC_KEY_check_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") if OpenSSL._hexversion > 0x10100000 and not OpenSSL._libreSSL: OpenSSL.EVP_MD_CTX_new(md_ctx) else: OpenSSL.EVP_MD_CTX_init(md_ctx) OpenSSL.EVP_DigestInit_ex(md_ctx, digest_alg(), None) if (OpenSSL.EVP_DigestUpdate(md_ctx, binputb, len(inputb))) == 0: raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ...") OpenSSL.EVP_DigestFinal_ex(md_ctx, digest, dgst_len) ret = OpenSSL.ECDSA_verify(0, digest, dgst_len.contents, bsig, len(sig), key) if ret == -1: return False # Fail to Check else: if ret == 0: return False # Bad signature ! else: return True # Good return False finally: OpenSSL.EC_KEY_free(key) OpenSSL.BN_free(pub_key_x) OpenSSL.BN_free(pub_key_y) OpenSSL.EC_POINT_free(pub_key) if OpenSSL._hexversion > 0x10100000 and not OpenSSL._libreSSL: OpenSSL.EVP_MD_CTX_free(md_ctx) else: OpenSSL.EVP_MD_CTX_destroy(md_ctx)
def sign(self, inputb, digest_alg=OpenSSL.digest_ecdsa_sha1): """ Sign the input with ECDSA method and returns the signature """ try: size = len(inputb) buff = OpenSSL.malloc(inputb, size) digest = OpenSSL.malloc(0, 64) if OpenSSL._hexversion > 0x10100000 and not OpenSSL._libreSSL: md_ctx = OpenSSL.EVP_MD_CTX_new() else: md_ctx = OpenSSL.EVP_MD_CTX_create() dgst_len = OpenSSL.pointer(OpenSSL.c_int(0)) siglen = OpenSSL.pointer(OpenSSL.c_int(0)) sig = OpenSSL.malloc(0, 151) key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") priv_key = OpenSSL.BN_bin2bn(self.privkey, len(self.privkey), 0) pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x), 0) pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y), 0) if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_private_key FAIL ...") group = OpenSSL.EC_KEY_get0_group(key) pub_key = OpenSSL.EC_POINT_new(group) if (OpenSSL.EC_POINT_set_affine_coordinates_GFp( group, pub_key, pub_key_x, pub_key_y, 0)) == 0: raise Exception( "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...") if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...") if (OpenSSL.EC_KEY_check_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") if OpenSSL._hexversion > 0x10100000 and not OpenSSL._libreSSL: OpenSSL.EVP_MD_CTX_new(md_ctx) else: OpenSSL.EVP_MD_CTX_init(md_ctx) OpenSSL.EVP_DigestInit_ex(md_ctx, digest_alg(), None) if (OpenSSL.EVP_DigestUpdate(md_ctx, buff, size)) == 0: raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ...") OpenSSL.EVP_DigestFinal_ex(md_ctx, digest, dgst_len) OpenSSL.ECDSA_sign(0, digest, dgst_len.contents, sig, siglen, key) if (OpenSSL.ECDSA_verify(0, digest, dgst_len.contents, sig, siglen.contents, key)) != 1: raise Exception("[OpenSSL] ECDSA_verify FAIL ...") return sig.raw[:siglen.contents.value] finally: OpenSSL.EC_KEY_free(key) OpenSSL.BN_free(pub_key_x) OpenSSL.BN_free(pub_key_y) OpenSSL.BN_free(priv_key) OpenSSL.EC_POINT_free(pub_key) if OpenSSL._hexversion > 0x10100000 and not OpenSSL._libreSSL: OpenSSL.EVP_MD_CTX_free(md_ctx) else: OpenSSL.EVP_MD_CTX_destroy(md_ctx) pass
def raw_check_key(self, privkey, pubkey_x, pubkey_y, curve=None): if curve is None: curve = self.curve elif type(curve) == str: curve = OpenSSL.get_curve(curve) else: curve = curve try: key = OpenSSL.EC_KEY_new_by_curve_name(curve) if key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") if privkey is not None: priv_key = OpenSSL.BN_bin2bn(privkey, len(privkey), 0) pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0) pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), 0) if privkey is not None: if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0: raise Exception( "[OpenSSL] EC_KEY_set_private_key FAIL ...") group = OpenSSL.EC_KEY_get0_group(key) pub_key = OpenSSL.EC_POINT_new(group) if (OpenSSL.EC_POINT_set_affine_coordinates_GFp( group, pub_key, pub_key_x, pub_key_y, 0)) == 0: raise Exception( "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...") if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...") if (OpenSSL.EC_KEY_check_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") return 0 finally: OpenSSL.EC_KEY_free(key) OpenSSL.BN_free(pub_key_x) OpenSSL.BN_free(pub_key_y) OpenSSL.EC_POINT_free(pub_key) if privkey is not None: OpenSSL.BN_free(priv_key)
def raw_get_ecdh_key(self, pubkey_x, pubkey_y): try: ecdh_keybuffer = OpenSSL.malloc(0, 32) other_key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if other_key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") other_pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0) other_pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), 0) other_group = OpenSSL.EC_KEY_get0_group(other_key) other_pub_key = OpenSSL.EC_POINT_new(other_group) if (OpenSSL.EC_POINT_set_affine_coordinates_GFp( other_group, other_pub_key, other_pub_key_x, other_pub_key_y, 0)) == 0: raise Exception( "[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...") if (OpenSSL.EC_KEY_set_public_key(other_key, other_pub_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...") if (OpenSSL.EC_KEY_check_key(other_key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") own_key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if own_key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") own_priv_key = OpenSSL.BN_bin2bn(self.privkey, len(self.privkey), 0) if (OpenSSL.EC_KEY_set_private_key(own_key, own_priv_key)) == 0: raise Exception("[OpenSSL] EC_KEY_set_private_key FAIL ...") if OpenSSL._hexversion > 0x10100000 and not OpenSSL._libreSSL: OpenSSL.EC_KEY_set_method(own_key, OpenSSL.EC_KEY_OpenSSL()) else: OpenSSL.ECDH_set_method(own_key, OpenSSL.ECDH_OpenSSL()) ecdh_keylen = OpenSSL.ECDH_compute_key(ecdh_keybuffer, 32, other_pub_key, own_key, 0) if ecdh_keylen != 32: raise Exception("[OpenSSL] ECDH keylen FAIL ...") return ecdh_keybuffer.raw finally: OpenSSL.EC_KEY_free(other_key) OpenSSL.BN_free(other_pub_key_x) OpenSSL.BN_free(other_pub_key_y) OpenSSL.EC_POINT_free(other_pub_key) OpenSSL.EC_KEY_free(own_key) OpenSSL.BN_free(own_priv_key)
def _generate(self): try: pub_key_x = OpenSSL.BN_new() pub_key_y = OpenSSL.BN_new() key = OpenSSL.EC_KEY_new_by_curve_name(self.curve) if key == 0: raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") if (OpenSSL.EC_KEY_generate_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_generate_key FAIL ...") if (OpenSSL.EC_KEY_check_key(key)) == 0: raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") priv_key = OpenSSL.EC_KEY_get0_private_key(key) group = OpenSSL.EC_KEY_get0_group(key) pub_key = OpenSSL.EC_KEY_get0_public_key(key) if (OpenSSL.EC_POINT_get_affine_coordinates_GFp( group, pub_key, pub_key_x, pub_key_y, 0)) == 0: raise Exception( "[OpenSSL] EC_POINT_get_affine_coordinates_GFp FAIL ...") privkey = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(priv_key)) pubkeyx = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(pub_key_x)) pubkeyy = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(pub_key_y)) OpenSSL.BN_bn2bin(priv_key, privkey) privkey = privkey.raw OpenSSL.BN_bn2bin(pub_key_x, pubkeyx) pubkeyx = pubkeyx.raw OpenSSL.BN_bn2bin(pub_key_y, pubkeyy) pubkeyy = pubkeyy.raw self.raw_check_key(privkey, pubkeyx, pubkeyy) return privkey, pubkeyx, pubkeyy finally: OpenSSL.EC_KEY_free(key) OpenSSL.BN_free(pub_key_x) OpenSSL.BN_free(pub_key_y)
def pointMult(secret): #ctx = OpenSSL.BN_CTX_new() #This value proved to cause Seg Faults on Linux. It turns out that it really didn't speed up EC_POINT_mul anyway. k = OpenSSL.EC_KEY_new_by_curve_name(OpenSSL.get_curve('secp256k1')) priv_key = OpenSSL.BN_bin2bn(secret, 32, 0) group = OpenSSL.EC_KEY_get0_group(k) pub_key = OpenSSL.EC_POINT_new(group) OpenSSL.EC_POINT_mul(group, pub_key, priv_key, None, None, None) OpenSSL.EC_KEY_set_private_key(k, priv_key) OpenSSL.EC_KEY_set_public_key(k, pub_key) #print 'priv_key',priv_key #print 'pub_key',pub_key size = OpenSSL.i2o_ECPublicKey(k, 0) mb = ctypes.create_string_buffer(size) OpenSSL.i2o_ECPublicKey(k, ctypes.byref(ctypes.pointer(mb))) #print 'mb.raw', mb.raw.encode('hex'), 'length:', len(mb.raw) #print 'mb.raw', mb.raw, 'length:', len(mb.raw) OpenSSL.EC_POINT_free(pub_key) #OpenSSL.BN_CTX_free(ctx) OpenSSL.BN_free(priv_key) OpenSSL.EC_KEY_free(k) return mb.raw
def test_rand(self): "Test basic random number generator correctness" # There's no way to check if this really is random (it's an # algorithmic prng). Still, check for common mistakes. data1 = OpenSSL.rand(10) data2 = OpenSSL.rand(10) self.assertNotEqual(data1, data2) blob = OpenSSL.rand(64000) stat_zero = [0] * 8 stat_one = [0] * 8 for byte in blob: byte = ord(byte) for i in range(8): bit = byte % 2 byte = byte >> 1 if bit: stat_one[i] += 1 else: stat_zero[i] += 1 for i in range(8): diff = float(abs(stat_zero[i] - stat_one[i])) # Probabilistic test can sometimes fail, but it should be VERY rare. # Result is usually < 500, 0.04 sets limit at a value 1280 self.assertTrue(diff / stat_zero[i] < 0.04 * stat_zero[i])