Is there a python library that supports (symmetric) encryption of data with the possibility of using multiple decryption keys.
I have (sensitive) user data that must be stored encrypted in a database, but it must be possible for multiple 3rd parties to access the data without giving them all the same secret.
This could be implemented by generating a random key K, encrypt the original data D to get D_K. Then I encrypting K with as many access keys (ak_1 to ak_n) as needed, store them for later use and destroy K. Whenever a 3rd party tries to access D the submit ak_i and I use it to decrypt K and us it to decrypt D_K to get D.
However, it would be nice to have a implemented since a) I don't like to reinvent the wheel and b) this is security and you probably won't get it 100% right.
Due to the confusion and issues surrounding export controls of hard encryption, there's not a lot of 3rd party libraries that directly provide this sort of higher-level explicit encryption scheme.
For the most part you're going to have to wrap the toolset of something like PyCrypto with your own key logic. Seeing as it's crypto we're talking about, however, I'd be remiss if I didn't point out the other libraries for lower-level hard encryption tools in Python.
Related
I want to code a custom key generator in Python. This key will be used as an input (along with the plain text) to AES algorithm for encryption (I will probably use pycrypto or m2crypto libraries for that).
But the key generator has to be custom, as it would generate the key based on the string that would be supplied by the user.
str = date + case-id + name
where:
date = current date when a case was submitted
(we work on separate security analysis cases, submitted on our ticketing tool)
name = person handling the case
case-id = the ticket id with which it was submitted.
This same key needs to be known to the decryptor (on a different system) so that it can decrypt the data.
So the key will have to be fixed for a specific set of date name and case-id for a specific order and will only be different if any of these 3 change in value or order and should not be random every time.
I've gone through some of stackoverflow articles, where it is suggested to use
random_key = os.urandom(16)
but I don't believe this will serve my purpose.
Suggestion on some articles where to start with if I want to design a key generator from scratch, or some pointers on existing libraries will be highly appreciated.
You're looking for a Password hashing algorithm, such as Argon2 or PBKDF2. It will allow you to deterministically extend the 'password' generated from the input values into a suitable key.
However, note that your passwords may still be very weak. I suspect that there is a strong correlation between case-id and date. Names are probably only a small list of people easily found out. Also, isn't this data sent along with the encrypted data by your system? This makes using it as a password a bad idea.
I've installed pyCrypto package on Python 2.7.1 to do some cryptography operations.
Q1:
The operation that I want to do is encrypting some data with private Key (instead of public Key). It seems that this library can't do it. Am I right? If so, is there any library capable to do that?
Q2:
In the documentation it is not mentioned which hash algorithm is used to calculate the signature! How can I find out which hash function is used for sign method?
Q3:
You see a part of documentation about encrypt method:
encrypt(self, plaintext, K)
Encrypt a piece of data with RSA.
Parameters:
plaintext (byte string or long) - The piece of data to
encrypt with RSA. It may not be numerically larger than the RSA module
(n).
(Censored!)
As you see above, the input data is limited to those that are not numerically larger than the RSA module. Does this mean that I can't encrypt 0x21...(257 bytes) with an RSA key pair with module = 0x11...(257 bytes) (for example) because 0x21 is greater than 0x11? If so, why? Isn't it weird to compare the values before encryption each time?! Or it is only meant that the data length must be equal or smaller than the module length?
In public key cryptography, you do not encrypt with the private key -- you always use the public key. Otherwise, since the public key is "public", anybody could decrypt the ciphertext.
You might be tempted to use the public and private keys interchangeably, but generally, given the private key, you can figure out the public key without much work. So, if you give someone the private key thinking that you will keep the public key safe, well, it won't be safe.
When they say not larger than the modulus, they mean the size in bytes. It will actually be smaller that the size of the modulus (256 bytes for a 2048 bit RSA key pair). But the data should actually be smaller than the modules because you will want to always pad the data. Padding, for example with OAEP padding, randomizes the ciphertext. Each time you encrypt the same plaintext, you get different ciphertext that looks random. This is important because otherwise the ciphertext is weak and open to attack even if the attacker does not have the private key. So you want to leave some room for the data plus the padding to fit in the modulus (e.g. 256 bytes).
Generally, you sign with the private key. In RSA, this actually does "encrypt" with the private key, but I don't think you will find "encrypt with private key" in any popular API.
I am not familiar with pyCrypto but it looks to me like you pick your favorite hash when signing. You hash yourself, and give the digest to the sign function, as far as I can tell from examples I've googled.
As a solution I came across with this:
https://www.php2python.com/wiki/function.openssl-private-encrypt/
Be careful though to understand the implications of using private key to encrypt.
In my case I want to share an encryption key that can be read by a software who has the public key hard coded. I could have use signing, however I prefer the key not to be shared as-is and therefore needs encryption. Only alternative would have been to setup PKI or PGP.
I'm looking to send a file to multiple people, but I also want them to know that:
The file has not been changed since I sent it to them.
They know that it was me who sent the file.
I'm coding in Python, so I was thinking of pulling in the file, taking a hash of it, and then encrypting the hash with my private key. I would send the original file along with this new file (probably just a .txt) to whoever I want. My friends could then decrypt the hash using my public key and compare it to a hash they take of the original file. I'd like to use something at least on the level of SHA-256. I do not want to use MD5 or SHA-1.
Note- The original file I am sending does not have to be encrypted, just looking for some integrity and non-repudiation.
Would this fulfill the two requirements above? And is there an easy way to implement this in Python?
I was thinking of pulling in the file, taking a hash of it, and then encrypting the hash with my private key
That's exactly what we commonly call signing or digital-signature, which fulfills your two requirements.
Would this fulfill the two requirements above?
Yes. Signing a message doesn't prevent it from being manipulated. It's only getting infeasible of generating a signature for a manipulated message without the private key.
And is there an easy way to implement this in Python?
Sure, pyCrypto supports RSA and DSA. You should try ed25519, though, because its signatures are smaller.
I've been working with pybitcointools for a while and I'm not sure exactly how to properly manage with private key loading in order to sign transactions.
def sign(tx, i, priv, hashcode=SIGHASH_ALL): ...
The sign function requires a key as a str that is used to perform the signature, but if you want to import that keys from a key file there's no way to export the private key as a str (or at least I've not been able to find it).
Some time ago I created a small OpenSSL wrapper in Python in order to load the key and extract the private part, but I don't think it is the most correct way and definitely not the most elegant one.
Does anyone know if there's any proper way to do it?
Maybe the question is quite odd, but I would like to be sure I was not being using it wrong all this time.
I am experimenting with the passlib.hash.sha256_crypt algorithm in an App Engine app and it seems rather simple to implement.
Is this secure enough with it's default parameters of autogenerated salt and 80,000 rounds? Should it first be padded with random chars?
Password is being posted in from a form and encrypted as above.
I can't judge what "secure enough" means.
Last I read the best options were scrypt, bcrypt, or pbkdf2. If you can't use those then I recommend sha512 with many thousands of iterations. One of the benefits of using passlib CryptContext is you can update your scheme later as needed (and as better implementations become available) while keeping easy compatibility with previously stored passwords. sha512_crypt is very easy to implement on GAE with passlib CryptContext.
I'm not sure padding with characters (on top of salting) adds anything.