Hello. Please help me with the question. Consider such a case, my program has users and I will send files, the program from the user reads this data. I want to check the data from the substitution. To do this, I send the hash (in the file) of the transferred file with the data to compare. Now how to protect this file with hash? 1. Asymmetric encryption - for this, I need to keep a private key in the program in order to decrypt it. Then they can dictate the program and find out the private key, then the public one and replace the data. 2. An electronic signature that encrypts private and decrypts with a public one, the option seems appropriate, but how to apply it is not clear what to check the hash in python. It turned out to sign the file, but for this I used in Window (makecert.exe and signtool.ex) and how to do this using python or maybe there is another option for encryption with a private key. Thank.
- Check on the server, accessible only to you, or how? And you want to protect yourself from being replaced by anyone? - andreymal
- Suppose I upload data to the server, the program downloads data from the user and checks that they are the ones that I put. And the server is available not only to me, that is, everyone has the right to write and read. - beginning_user
|
2 answers
I used the pycryptodome library (since pycrypto does not seem to be supported anymore).
from Crypto.Hash import SHA256 from Crypto.PublicKey import RSA from Crypto.Signature import pkcs1_15 import os fname ="Путь к файлу" # Генерируете новый ключ (или берете ранее сгенерированный) key = RSA.generate(1024, os.urandom) # Получаете хэш файла h = SHA256.new() with open(fname, "rb") as f: for chunk in iter(lambda: f.read(4096), b""): h.update(chunk) # Подписываете хэш signature = pkcs1_15.new(key).sign(h) # Получаете открытый ключ из закрытого pubkey = key.publickey() # Пересылаете пользователю файл, публичный ключ и подпись # На стороне пользователя заново вычисляете хэш файла (опущено) и сверяете подпись pkcs1_15.new(pubkey).verify(h, signature) # Отличающийся хэш не должен проходить проверку pkcs1_15.new(pubkey).verify(SHA256.new(b'test'), signature) # raise ValueError("Invalid signature") - Thank you for what you need - beginning_user
- @beginning_user will not protect you in any way: on the way, if you assume that the file can be changed, you can also change the hash and key. - jfs
- @jfs The check passes in the program itself, that is, I transfer only the file and the hash, the key will be sewn into the program. Not knowing the private key is obtained will not be able to sign the file so that it passes the test. - beginning_user
- one@jfs, if I understand correctly, the beginning_user has a problem not to transfer the file safely, but to make sure that the user uses the specific file and does not replace it with another. If we assume that the user can climb into the python script and change something there — nothing will save us, if the user cannot change the script, the scheme with the signature becomes safe. Maybe I did not take into account any factors, but for now I don’t see where else the user can slip the wrong file instead of the correct one, because the user doesn’t have a private key. - Alexey Reytsman
- one@beginning_user if we assume that a program with a public key magically on the user's computer materializes (but this magic method is not available for the file itself), then the test already rests on specific algorithms (harder to break). - jfs
|
And I use ctypescrypto. Working without class abstraction is difficult, but the possibilities are wider. I have not yet seen a project on python that would cover all OpenSSL with abstractions convenient for python.
Ctypescrypto chose because I could not get support for loading plugins anywhere - I mean GOST support.
Here is an example of a signature.
req = """data to sign""" with open('/home/eri/Projects/rkn/provider.pem','rb') as f: d = f.read() from ctypescrypto.engine import Engine,set_default set_default(Engine('gost')) from ctypescrypto.x509 import X509 c=X509(d) # сертификат с приватным ключем в формате pem в переменной d, загружаю сертификат p=c.pubkey from ctypescrypto.cms import SignedData,Flags from ctypescrypto.pkey import PKey pk = PKey(privkey=d) # приватный ключ mes=SignedData.create(req,c,pk,flags=Flags.DETACHED+Flags.BINARY) with open('req.txt.sig','wb') as f: f.write(mes.pem()) with open('req.txt','wb') as f: f.write(req) |