Usually password obfuscation is a very bad idea, for reasons that Eric A. Brandstadmoen explains. That is why every DRM solution - DVD-CSS, Blu-ray HDCP, Flash RTMPE, etc. - ultimately fails. On the other hand, sometimes it is necessary for business or legal reasons, and that is why all these DRM solutions were invented in the first place.
You say: "It doesn’t need to be super secure, and not reveal username / password in plain text." And it looks like you have some kind of contractual relationship with your client. It is perfectly reasonable that you do not need to actually stop them from doing this, you just want to force them to exert sufficient effort so that he demonstrates dishonesty on their part or something like that. This, obviously, is what you need to get legal advice otherwise, you are going to spend efforts on creating something that is not enough to give you any legal protection or spend more efforts on creating much more than you you need the legal protection you want, But suppose you have this legal advice, and now you want to continue.
You cannot give someone an encrypted password without providing him with a key. Thus, the strength of encryption is almost irrelevant. It will almost always be easier for them to retrieve the key than to crack the cipher, and it is even easier for them to simply put a breakpoint on the mysqldb login function and capture the decrypted value on the fly. This means that you can use something dirty and cheap. For instance:
def xor(text, key): infkey = itertools.chain.from_iterable(itertools.repeat(key)) return ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(text, infkey)) user = 'user' encrypted_passwd = '\x1b\x04\x0a\x18\x12\x16\x19\x01' key = 'key' do_login(user, xor(encrypted_passwd, key))
Your lawyer may say that XOR encryption is not a sufficient “best effort” to protect your data, and you should use, say, AES. If so, do it; it really doesn't matter.
Then think about hiding the key and the encrypted password (and possibly the xor function) somewhere in your code: rename them to something harmless, inject them in the middle of other things, don't make it obvious, re is used to create a password, etc. .d.
You can also protect the interface from the MySQL login function. For example, if you complete the decryption code and mysql_connect
together in a simple Cython extension, they cannot just break mysqldb.connect
or even _mysql.mysql_connect
, which means they need a C level debugger instead of a Python level debugger. You can even use C or binary obfuscator around decryption and join code; there are a number of commercial products there, and if your lawyer says that you need to do this, you better use a well-known, modern product, rather than something ordinary.
Meanwhile, if you are looking for technical protection rather than legal protection, you can usually get much more benefit by mitigating the impact rather than trying to avoid it, as dm03514's answer suggests: Limit client access, so even if the user steals client credentials, they can only do the same things that they could do with the client.
For example, let's say you want to prevent users from adding a new delivery record without adding the corresponding billing record with the correct links. You have the logic in the client to verify this, but if they just grab the password from the client, they can add all the delivery records that they want.
Just move this logic to some middleware, so one API call checks and adds both records at the same time. Then give the client access to this middleware instead of directly accessing the database, and anyone who steals the client’s credentials still cannot add invalid delivery records.
This will not stop them from accessing you without a client, but if it is done correctly, it will make it useless for this.