I'm working on a program in Python that is highly valuable to certain people. I've been trying to add a user authentication system to keep people from copying and sharing the files easily. To explain further this is the flow:
1: User opens the EXE (cx_freezed python file)
2: Program asks user for their login (from a MySQL database)
3: Program checks if someone is already logged in using that info
4: If someone is logged in, don't let them log in. If someone isn't, log them in.
There are two ways I've thought about doing this but I have absolutely no idea where to start because this isn't in my typical range. I could either intigrate this into Python, or use a tool to take my exe file and add an auth (is that a thing?).
Any advice about where to remotely start would be awesome. This is out of my typical range so I'm a bit daunted by it.
iv'e done something like this in my latest project, however i'm not an expert whatsoever so take what i say with a grain of salt, there might be other, better ways to do this but its just how i implemented it.
these are the models i've worked with:
socket, json, sqlite3 , wxpython (for gui) + pycrypto (if you want to encrypt and decrypt the messages using RSA and AES keys for added security, like i did)
basically what i did was the following:
a socket connection is created between the client and the server.
if you're not going to use pycrypto skip the second and third parts - the server generates a pair of RSA private and public keys for himself and so does the client for himself. the client then sends its RSA public key to the server using the socket connection. the pair of RSA keys(the public key and private key) are essentialy two keys that can only decrypt the messages encrypted by the other key in the pair (public key encrypts-private key decrypts || private key encrypts-public key decrypts) (i would suggest this computerphile video for a little more in depth explanation, once you get how the keys suppose to theoretically work, the module itself is pretty straight forward, so don't worry about that).
the server now creates an AES key (a symmetrical key, that can decrypt the messages it encrypted), and then encrypts the AES key (which is basically a pretty long string) with the RSA public key he got from the client, and sends its to the client, so now only the client can decrypt this message with his private key and get the AES key that will be used for the communication between them.
the client enters a new username and password in order signup. the client script puts the data in a list like so: ["signup", newUserNameVar,NewPassWordVar], uses the json encoding on it using json.dumps() function (basically turns the entire list into a string that can be sent through a socket) then encrypts it using the AES key we got from the server earlier, and then sends it to the server through the socket connection.
so now the server receives an encrypted message only he can decrypt with his AES key (which is the same one the client holds, if you've followed my explanation earlier). so he decrypts the message using the AES key and gets the json message the client sent him. to turn the json back into the list the server uses the json.dumps() function (which turns the json object back into a list).
in my design, the first index of the list is the command so basically either "login" or "setup", so now the server deploys a switch case (or a bunch of ifs) on the first index of the list to see which command he needs to fulfill. if its signup then he takes the 2nd and 3rd index off of the list and creates the table in the database with rows corresponding to the users data, and if its login it takes the data from the database and if it matches the data that was sent by the client in the other indexes of the list then its sends a "correct" response back, and then you can tell your script to run that other program only when it gets a "correct" message from the server, which sends the message exactly as i mentioned in steps 4-5.
so to recap it goes something like this:
server: generate - RSA public key, RSA private key, AES key
client: generate - (other)RSA public key, (other)RSA private key
client ----> server, send clients RSA public key
server ----> client, encrypt the AES key using the clients RSA key and send it to him.
client: decrypt the AES key using the clients private RSA key.
continue to talk with each other in the following way: LIST -> JSON (json.dumps(LIST))-> AES encryption on the JSON object -> send through a socket.
AES decryption on the message you got -> UNJSON (json.loads(WHAT YOU GOT FROM THE DECRYPTION)) -> LIST ->deploy switch-case.
Related
I'm implementing an RSA encryption scheme where the MySQL database data is encrypted using a public key, and only the private key can be used to decrypt it.
I've managed to do encryption and decryption using the PHP openssl library, and even added a passphrase to protect the private key.
// $sRawText is the text string to encrypt.
// $sPublicKey is the public key stored on the server.
openssl_public_encrypt($sRawText, $sResult, $sPublicKey, OPENSSL_PKCS1_OAEP_PADDING);
// $sResult is the encrypted result which can then be stored in the database.
It works great for all the purposes I need to be publicly available, which is to add new entries if a user signs up or, in the future, verify details if they log in. This is sensitive data like contact information, which I only ever use very occasionally. Data that's verify only like passwords can be hashed still, and anything that needs to be read doesn't get encrypted.
Here's how I'm presently decrypting with PHP:
// $sPrivateKey is the matching private key.
// $sPassPhrase is the pass phrase (required to decrypt the result).
// $sRawBytes is the encrypted data from the database to decrypt.
$kRsaKey = openssl_pkey_get_private($sPrivateKey, $sPassPhrase);
openssl_private_decrypt($sRawBytes, $sResult, $kRsaKey, OPENSSL_PKCS1_OAEP_PADDING);
// $sResult will be the decrypted data.
The problem with this decryption approach is that it's all taking place live on the server. Obviously, storing the private key on that server would defeat most of the security benefits, as anyone with enough access to the server could pretty easily take it. The best I can come up with using PHP on the server is to pass the private key and/or pass phrase at each time of decryption. However, that still has the key being live there, and also opens up a new attack avenue for the key and pass phrase to be intercepted in those requests.
What I'm trying to do is perform all the decryption offline. So an offline software will be provided the encrypted data in a text file, which it translates into a list of instructions based on the data and intended operation. The private key never leaves that isolated environment and the pass phrase is never stored between sessions.
I'm running into all kinds of hurdles setting up an offline PHP environment, so I thought it might be easier to try to do the decryption in Python. Everything should be standard, or so I thought.
I'm currently trying to use the Python RSA library here:
https://stuvel.eu/python-rsa-doc/reference.html#exceptions
The thing I can't figure out is how to decrypt using the passphrase-protected private key. Would anyone be able to post a really simple example, or is it fundamentally not compatible without major modifications to the Python RSA library? What's the easiest approach to be able to do this decryption offline?
Okay I'll post the answer now that I figured out.
(1) We need to get the cryptography library in Python.
On Windows, enter into the command prompt (not Python interpreter):
py -m pip install cryptography
If the above doesn't work, try replacing 'py' with 'python'.
(2) The private key needs to be in a text file "privatekey.txt".
(3) Use this code for decryption:
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
#privatekey.txt must contain the private key.
#passphrase_bytes must be the passphrase, and it needs to be in bytes (ie b'My Pass Phrase')
with open("privatekey.txt", "rb") as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=passphrase_bytes,
)
#rawtext_bytes must have the bytes of the ciphertext to decrypt
plaintext = private_key.decrypt(
rawtext_bytes,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
label=None
)
)
#plaintext will now contain the result
I'm working on coding an application in Python 3 for users to send and retrieve data between others with this application. The process would be a client inputting an encoded string, and using a server as a middle man to then send data to another client. I'm well versed in what would be used for the client application, but this server knowledge I am new to. I have a VPS server up and running, and I researched and found the module pysftp would be good for transferring data back and forth. However, I'm concerned about the security of the server when using the application. This module requires the authentication details of the server when making a connection, and I don't think having my server's host, username and password in the application code is very safe. What would be the safe way to go about this?
Thanks,
Gunner
You might want to use pre-generated authentication keys. If you are familiar with the process of using the ssh-keygen tool to create SSH key pairs, it's the same thing. You just generate the key pair, place the private key on the client machine, and put the public key on the target server. Then you can use pysftp like this:
with pysftp.Connection('hostname', username='me', private_key='/path/to/keyfile') as sftp:
<do some stuff>
the authentication is handled using the key pair and no password is required. This isn't to say that your security issue is solved: the private key is still a sensitive credential that needs to be treated like a password. The advantage is that you don't have a plaintext password stored in a file anywhere, and you are using a well established and secure process to manage authentication. The private key is set with permission 0600 to prevent anyone but the owner from accessing it.
I'm currently building a website where the users would enter their credentials for another web service that I'm going to scrape to get their data.
I want to make sure that when I save their credentials in my database, I'm using the best encryption possible and the best architecture to ensure the highest level of security.
The first idea that I had in mind was to encrypt the data using an RSA pub key (PBKDF2, PKCS1_OAEP, AES 256bit... ???) and then allowing my scrapping script to use the private key to decrypt the credentials and use them.
But if my server is hacked, the hacker would have access to both the database and the private key, since it will be kept on my server that runs the scrapping script and hosts the DB. Is there an architecture pattern that solves this ?
I've read that that there should be a mix of hashing and encryption to enable maximum security but hashing is uni directional and it doesn't fit my use case since I will have to reuse the credentials. If you can advise me with the best encryption cypher/pattern you know it could be awesome.
I'm coding in python and I believe PyCrypto is the go-to library for encryption. (Sorry I have very little knowledge about cryptography so I might be confusing technologies)
Do the encryption and decryption on the second server (encryption server).
Pass the password to the encryption server along with an id for encryption and it returns the encrypted password to store in the DB.
When the password is needed pass the encrypted password to the encryption server for decryption.
Have the encryption server monitor request activity, if an unusual number of requests are received sound an alarm and in extreme cases stop processing requests.
Make the second server very secure. No Internet access, minimal access accounts, 2-factor authentication.
The encryption server becomes a poor-man's HSM (Hardware Encryption Module).
from cryptography.fernet import Fernet
class Crypt():
def __init__(self, key):
self.cipher = Fernet(key)
def encrypt(self, my_message):
return self.cipher.encrypt(my_message)
def decrypt(self, my_message):
return self.cipher.decrypt(my_message)
#staticmethod
def key_maker():
return Fernet.generate_key()
if __name__ == '__main__':
KEY = Crypt.key_maker()
crypt = Crypt(KEY)
msg = crypt.encrypt(b'hi')
msg = crypt,decrypt(msg)
I'm currently drafting an upcoming Python project, where I'm required to securely send a Python dictionary form a client to a server over the internet.
As of now, I'm considering a simple TCP communication and use AES to encrypt the dictionary before sending it.
My question is, whether this is possible. When I receive the information on the server, then decrypt it with a shared key, is the outcome still a dictionary?
There are some libraries that support the encryption of arbitrary objects, because they internally have a serializer/unserializer, but PyCrypto is not such a library. You will need to provide a binary string in Python 2 or a bytes object in Python 3.
In order to get those, you need to serialize a complex data structure such as a dictionary. After that, you can encrypt it and send through the socket. At the other end, you will need to decrypt it and unserialize. There are lots of ways for serialization. The answers to this question contain a few of them.
Unserializing foreign data can be quite dangerous, because some algorithms/formats are not designed to be resistant against fault attacks, such as Python's pickle. So it is very important to authenticate ciphertexts with a message authentication code, which must be verified before attempting decryption or even unserialization. This question contains an example.
I'm building a Flash application to run on the web, where users can visit and create their own content in conjunction with my service (built with Python). Specifically: the user sends in some data; some transformation is performed on the server; then the finished content is sent back to the user, where it is rendered by the client app.
I want to be able to prevent the client from rendering bogus content, which I can do by passing a keyed hash along with the main content, generated by the server. The client would then use the same key to hash the content once again, and confirm that the hashes/signatures match. If there's a mismatch, it can be assumed that the content is inauthentic.
The problem I have is that keeping the key inside the SWF is insecure. I've considered a number of ways to obfuscate the key, but am learning that if an attacker wants it, they can get it quite easily. Once an attacker has that, they can start creating their own content to be unknowingly accepted by the client.
Is there another way that I can verify a file's signature on the client side, without exposing the method used to create that signature?
Is there another way that I can verify a file's signature on the client side, without exposing the method used to create that signature?
Public key crypto. You have only a public key at the client end, and require the private key on the server side to generate a signature for it to verify.
What is the attack you're trying to prevent? If you are concerned about a man-in-the-middle attack between an innocent user and your server, the sensible choice would be TLS (HTTPS). This is a pre-cooked, known-good implementation including public key cryptography. It's far preferable to rolling your own crypto, which is very easy to get wrong.