nucypher / pyUmbral

NuCypher's reference implementation of Umbral (threshold proxy re-encryption) using OpenSSL and Cryptography.io
https://pyumbral.readthedocs.io
GNU General Public License v3.0
284 stars 71 forks source link

Creating pyUmbral keys from exisitng EC Secp256k1 keys. #207

Closed GraphicalDot closed 6 years ago

GraphicalDot commented 6 years ago

I sit possible to reuse existing EC keys for pyUmbral encryption and decryption.

michwill commented 6 years ago

You probably mean to serialize and deserialize keys? You certainly can:

>> from umbral import keys
>> alice_priv_key = keys.UmbralPrivateKey.gen_key()
>> alice_pub_key = alice_priv_key.get_pubkey()
>> alice_priv_key.to_bytes()
b'n\x9c\xdc?\xe3\xafo\xb0;v\x9c}0\xdd\xb1H\xe5`\xa14 ~\x8f\xd2v\xe8),\xe6\xe9\xac3'
>> alice_pub_key.to_bytes()
 b'\x03\x05\xb3\x91\xd3=!\x96R:\x9f\xe6\x8c\x993\xb4\xc6i#ka\x83\xac\x95+\x88\x04\xc7\xc1%*\xb2\x18'
>> keys.UmbralPrivateKey.from_bytes(b'n\x9c\xdc?\xe3\xafo\xb0;v\x9c}0\xdd\xb1H\xe5`\xa14 ~\x8f\xd2v\xe8),\xe6\xe9\xac3')
<umbral.keys.UmbralPrivateKey at 0x7f660b5cf0f0>

>> keys.UmbralPublicKey.from_bytes(b'\x03\x05\xb3\x91\xd3=!\x96R:\x9f\xe6\x8c\x993\xb4\xc6i#ka\x83\xac\x95+\x88\x04\xc7\xc1%*\xb2\x18')
<class 'umbral.keys.UmbralPublicKey'>:0305b391d33d219
GraphicalDot commented 6 years ago

Thanks for the response, but i have secp251k keys with me which i am using already to encrypt AES keys. can i use the same keys to generate keys from PyUmbral, which can be used for proxy reencryption?

michwill commented 6 years ago

If you have keys for ECIES or ECDSA based on SECP256k1 curve - yes, you can. Just make sure that serialization formats coinside

GraphicalDot commented 6 years ago

ec = umbral_private_key.to_cryptography_privkey() serialized_private = ec.private_bytes(encoding=Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() )

This is the serialized private key b'-----BEGIN EC PRIVATE KEY-----\nMHQCAQEEIPQzL5NWAFvDCJo024WjzvJT0KI7p/IflX4Jg/s7rOG9oAcGBSuBBAAK\noUQDQgAEfD/C/xPeKHyWCRUyAYOQxyPl9cYylUFAfPZwLAUrDnQ/ORgrsXALCBfM\nrHOvIx8BgH8/N8hKd7kQaO1MiMPPFA==\n-----END EC PRIVATE KEY-----\n'

When i am doing keys.UmbralPrivateKey.from_bytes(serialized_private)

I am getting this error

ValueError Traceback (most recent call last)

in () ----> 1 keys.UmbralPrivateKey.from_bytes(serialized_private) ~/Programs/FeynmenKeyGeneration/lib/python3.6/site-packages/umbral/keys.py in from_bytes(cls, key_bytes, params, password, _scrypt_cost, decoder) 95 key_bytes = SecretBox(key).decrypt(key_bytes) 96 ---> 97 bn_key = CurveBN.from_bytes(key_bytes, params.curve) 98 return cls(bn_key, params) 99 ~/Programs/FeynmenKeyGeneration/lib/python3.6/site-packages/umbral/curvebn.py in from_bytes(cls, data, curve) 129 curve = curve if curve is not None else default_curve() 130 num = int.from_bytes(data, 'big') --> 131 return cls.from_int(num, curve) 132 133 def to_bytes(self) -> bytes: ~/Programs/FeynmenKeyGeneration/lib/python3.6/site-packages/umbral/curvebn.py in from_int(cls, num, curve) 82 """ 83 curve = curve if curve is not None else default_curve() ---> 84 conv_bn = openssl._int_to_bn(num, curve) 85 return cls(conv_bn, curve) 86 ~/Programs/FeynmenKeyGeneration/lib/python3.6/site-packages/umbral/openssl.py in _int_to_bn(py_int, curve, set_consttime_flag) 116 on_curve = _bn_is_on_curve(conv_bn, curve) 117 if not on_curve: --> 118 raise ValueError("The Python integer given is not on the provided curve.") 119 120 if set_consttime_flag: ValueError: The Python integer given is not on the provided curve.
GraphicalDot commented 6 years ago

from cryptography.hazmat.primitives.asymmetric import ec private_key = ec.generate_private_key(ec.SECP256K1, default_backend()) serialized_private = private_key.private_bytes(encoding=Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption())

Same error follows..Please help

cygnusv commented 6 years ago

Hi, We don't serialize private and public keys in PEM format. Instead we serialize the raw bytes of the private key, and compressed/uncompressed EC points for public keys

michwill commented 6 years ago

That's because the serialization format is different from what we use. Ours is very similar to what you usually get for Ethereum keypairs (e.g. pure binary, no meta-information, no encoding - just pure bytes). You can get these probably from DER encoding, but I'll probably ask @tuxxy : what's the best way to serialize cryptography.io keys into our format?

cygnusv commented 6 years ago

It's better to directly generate encryption keys with pyumbral. Otherwise, there's the risk of reusing a signing private key, which is what cryptography.io provides (although mathematically both are the same).

GraphicalDot commented 6 years ago

I ma using same private keys for encryption AES-CBC keys to encrypt the content, different AES keys for different content. Using different EC keys for signing messages. With DER Encoding format, I am getting same error.

michwill commented 6 years ago

Can you post here how der-encoded keys look like?

michwill commented 6 years ago

Actually true, the DER-encoded key contains a whole bunch of meta-information

michwill commented 6 years ago

If you do private_key.private_numbers().private_value.to_bytes(32, 'big'), this will get it in the same format. But not necessarily it's always safe to do so. @tuxxy @cygnusv is there a better way?

cygnusv commented 6 years ago

I think that's the only way from cryptography.io to pyUmbral. In general, the safest approach would be to only use keys generated by pyUmbral.

GraphicalDot commented 6 years ago

Can you explain why it is not safe to convert EC keys to umbral keys? If it can be made secure or not, The point is I have whole ecosystem build on EC keys secp251k, I just want to add the functionality of proxy-reencryption and shamir secret sharing.

jMyles commented 6 years ago

@kaali-python: This is a great question. I'm interested in the details of your use case. Thanks for opening this issue!

Without wading into the contentious topic (at least for now) about whether cross-use of keys is a reasonable practice, it's probably worth considering that, for the purposes of both pyUmbral and nucypher, we take the opinion that each key material is used for one activity and only that activity.

Let me ask you this, before you sink any more time into this: is it practical for you, in your current configuration, to use the material currently in your users' possession to prove that they also own these newly generated pyUmbral keys? IE, can you have them simply sign the public key material and then use pyUmbral-generated keys?

If the answer is yes, then we'll probably take the position that this is a highly favorable strategy.

If the answer is no, then, yes it's possible to use your own key material, but it's somewhat impractical and not something that we currently support in an express fashion.

GraphicalDot commented 6 years ago

I am using EC keys to make address of the users and using the same keys to encrypt different AES keys. I am storing these private keys after key split on different agents. Rather then using PyUmbral keys to again encrpyt the stored content (which is huge), i just wanted to use the existing keys and deploy proxy encryption for all the future process.

I have two more question, Lets say I encrypt content with Alice Umbral keys and generates lets say 20 cfrags, threshhold being 10. Lets say i create a channel on fabric whose task is just to re-encrypt content provided by Alice for Bob. After re-encryption, Bob have to collect at least 10 kfrags to read Alice content. Is this process safe?

The other question is, How can I revoke access of BOB on alice's content. Is it possible?

tuxxy commented 6 years ago

It sounds like a more reasonable scheme would be to use pyUmbral to generate those AES keys rather than try to integrate those already existing keys.

You're not meant to use the PRE scheme to encrypt all the data, only the date encryption keys (DEKs).

As for your second question -- When Alice splits a key, she generates kfrags, not cfrags. The cfrags are the output of Ursula performing a re-encryption. The kfrag is what Ursula uses to perform the re-encryption. The kfrag should also be kept private to that specific Ursula.

As to the question of if the process of re-encryption is safe, well that's a bit hard to answer and is entirely based upon how this process is implemented. I can affirm to the security of pyUmbral and that, to my knowledge, there are no standing critical security bugs that leak the confidentiality of the data. The only way I can answer you is if I know what your criteria for safety is in this process?

Also, if you need to revoke Bob's access to the encrypted content, then you just need to have the proxy nodes delete their KFrags so that the number of KFrags distributed to the proxies is below the number required to perform re-encryption. If you're asking specifically about fabric, I'm afraid I can't answer that.