My Question is simple - is there a build in functionality, like AES_ENCRYPT / AES_DECRYPT, for asymmetric (public / private key) encryption in MySQL?
Sadly, I only find answers that involve PHP (to encrypt it in php), and stuff like that. I would like to keep it in MySQL, since the whole application logic is handled by procedures - and I would like to avoid ruining that by bringing in external languages to solve this issue.
There is no functionality for RSA encryption within MySQL. it's sort of an odd use case, so the MySQL folks probably haven't seen fit to implement it
You'll have to do the RSA operations in the application layer, and pass the results into your procedures, unless you fancy implementing RSA within MySQL yourself (which I really cannot advise at all)
What you can do is something like this; Make a shared secret between multiple users using their pub/priv keys, then use that shared secret as the AES symetric key to unlock the data in mysql.
What this means is that you can utilize mysql's inbuilt AES encrypt function for convenience while still maintaining secure data given that you will never know the shared secret.
eg:
Also you can try reading this enter link description here
I am very much agree to #Peter Elliott. But as part of answer I would like to add that MySQL Enterprise Encryption provide that kind of facility such as :
MySQL Enterprise Encryption gives DBAs and Developers the tools they need for:
Asymmetric Public Key Encryption (RSA) Asymmetric Private Key
Decryption (RSA) Generate Public/Private Key (RSA, DSA, DH) Derive
Symmetric Keys from Public and Private Key pairs (DH) Digitally Sign
Data (RSA, DSA) Verify Data Signature (RSA, DSA) Validation Data
Authenticity (RSA, DSA)
For more information you can visit MySQL Enterprise Encryption, I hope this will be helpful to you.
Related
I need to encrypt credit card no in a way that nobody can view the actual no. Moreover, I don't want to store my encryption key information in SQL Server
Dynamic Data Masking may be used in this scenario. Learn more about it here.
Hope this helps.
You can give a try on Azure Always Encryption.
It has the following benefits:
Through out the network, the Data's will be encrypted.(I've Provided an Example here)
As you mention, storing encrypted key in SQL-Server is not a good practice at all. In Azure Always Encryption, you have a flexibility to store your Encryption key in various Locations like MSSQL_CERTIFICATE_STORE ,MSSQL_CSP_PROVIDER,MSSQL_CNG_STORE,Azure_Key_Vault(Even you can create your own custom key store provider too)- Find the details in here
It can support in Azure-SQL and also On-Premises SQL Server (Starting from 2016)
Edited based on comments.
My company is developing a system and is in the early design stages. I am the lead on the project. Some of the information to be stored in the system is highly confidential. The system must protect this information such that only authorized users have the ability to see this information. In fact, it is such that we want to protect it from ourselves even. The database to be used will probably be mySQL but does not have to be. I am aware that the data can be encrypted in the database. I am also aware that the software will have to be able to retrieve this data from the database for authorized users. I do not want any developers, including myself, to be able to decrypt and view this information -- in production -- but they do need to be able to view it during development(we will disable encryption during development).
The software will be a cloud based offering but will have an in house hosting option as well.
We can have a software based encryption and I realize that if software can get at the data then it's accessible - but I want this as tight as possible so that a developer cannot (including myself) view this data, but signed in, authorized users, can view it.
I'm stuck in my own thinking box about how to do this so I'm seeking advice as to how to secure this.
The client side will need a decryption key to decrypt the data. The software will have to allow access to this key for authorized users. The users cannot hold this key as the "client" devices could be virtually anything. Now I know I have no control over what the end users who have access do with the data, and that's not by concern. I want them to be able to store this information and have it secure in such a way that I cannot see it! I also do not want to have the ability to make myself authorized to see it - but to have that ability rest in the hands of a user side trusted administrator.
The data can be binary data. I do not want to encrypt the entire database, nor do I want to ever need to re-encrypt data because it can be huge amounts of data.
I have read posts about using GnuPG to handle this with public key for encryption and decryption via any one of a set of multiple private keys. This might be feasable for this but I'm looking for multiple solutions. My "issue" with this is the pass phrase protecting the private key and issueance of these private keys. I really don't want to user having to key in the passphrase associated with the private key every time that they login to the system or try to view the encrypted/protected data, but I don't want to store this passphrase anywhere a developer can see it either!
I understand about PKI but it doesn't offer protection from developers who can access the master decryption key which is shared using a public/private keypair.
I've edited the question with a proposed solution, please punch holes in it.
Development Language is C#. Microsoft supports asymetric keys which is what we want to use.
An X509 Certificate will be utilzied for the encryption keys. The public key will be stored in the database and used for all encryption. The private key will be stored in the database as well but encrypted using a passphrase entered by a trusted administrator. (This is the weak link in my mind, more on this later).
The administrator will create users who have access to the encrypted data. The users will be issued a copy of the private decryption key via the administrator and this key will be associated with their user account and encrypted in the system using their initial pass phrase.
When the user first logs in and is prompted to change their pass phrase, the private key will be re-encrypted using their new pass phrase. Their pass phrase is not stored in the database, only a hash for validation. Their keyed pass phrase will be encrypted using a timestamp or other data and will be stored on their local computer not on the server or in the servers identifable memory except when it is used for decryption of the private key. A software algorithm will be created to retrieve the decryption key for the encrypted master decryption key associated with this user.
Thus users can be created and revoked at the will of the administrator. Users can have their pas phrases reset - but in that case a new decryption key would need to be issued because the old one would not be decryptable any longer.
The one flaw I see, and I'm open to input, is if the administrator forgets their pass phrase and can no longer issue private keys. We could write code that given a users password, recovers the private key and encrypts it using the administrators new password when they enter it.
Another weak link is user pass phrase. If that becomes compromised then a developer could use that to obtain a copy of the private decription key and decrypt data.
Also - if for some reason an administrator needs to be let go we have the same issue as above where we don't have a copy of the private key accessible to share but we could get one using a users pass phrase.
Any advice on overcoming the perceived weaknesses?
We cannot tolerate exposure of the master decryption private key - if it is exposed then the entire database needs to be re-encrypted using a new keypair.
Thank you for your comments.
If you need to protect the data from yourselves, the only option is end-to-end encryption. User has a private key and it never leaves their computer. Devs/sysadmins never have private keys and can never decrypt.
This would require you make your client software source available to users so they can see that you are not leaking their info.
Use USB smart cards for easier/safer key management. They key is generated on the smart card and never leaves it. The smart card does the decryption on your apps behalf.
This make searching harder, but you can fix some of this by storing hashes along w the encrypted values, and searching on them.
Update, answering your questions in your comment:
Web based is not an option. You need a thick client
There is no "master key"
Please clarify "authorized user". Authorized by whom? Please provide an example.
Another option would be to skip encryption entirely and rely solely on access control. Use a db like postgresql, ms sql, or oracle that does row-level security. Don't give access to any one DBA. Give part of password to one dba, another part to another. DBA's need to be in same room to access the server.
Either way, you should be familiar with https://en.wikipedia.org/wiki/Secret_sharing
If you were to condider SQL Server instead of mysql, then the most secure design I can think of that meets your requirements is to require SQL Server Enterprise Edition an Extensible Key Management system that uses a Hardware Security Module. SQL Server Extensible Key Management enables the encryption keys that protect the database files to be stored in an off-box device such as a smartcard, USB device, or EKM/HSM module. EKMs are only supported in Enterprise edition. An HSM will allow for the delegation and isolation of managing the encryption keys and functions under a group other than both developers and DBAs, if that is your intent. Other features I would suggest in the design include the following options to complete end to end transport\session encryption:
Installing a domain or CA certificate on the SQL Server and enabling Force Protocol Encryption or enabling IPSec on the host of the instance
Installing a domain or CA certificate on all IIS websites or web services and forcing encryption in the connection strings and https
The benefits of this design over SQL Server Always Encrypted are that the encryption is protected by a single system that can be monitored and defended with more focus as opposed to numerous clients that increase exposure to theft of the private key from one of the users key stores. Also, key rotation for EKMs should be easy for those who are managing the system. It is also possible with an EKM to require that more than one person be involved in generating keys.
I have a security issue with one of our distributors. I need to prevent them from accessing certain data in our database. Because they administer the database I can't use password controls on the database itself to protect the data. I'm thinking that I need to encrypt the sensitive data in the database and have the encryption key embedded in software that we create. That way the distributor can poke around in the database all they want but the sensitive data will be unintelligible to them. I see how this might be done in MYSQL. There is are ENCODE and DECODE functions that allow me to pass a key in as a parameter. I can embed these keys in a piece of software, lock the software down, and this will allow me to insert and retrieve information. But what about MS SQL. How can I encrypt data so that even someone who is an administrator of the database cannot read that data?
Thank you,
Elliott
For MS SQL there is tons of documentation on encryption, and based on what you said about MYSQL I think you will be most interested in the Cryptographic Functions.
Note that I would be careful on which methods you encrypt with your own key, as a trace on the database or other means could be used to still obtain the key by inspecting the SQL commands you are sending.
There is definitely encrypt/decrypt functionality in MSSQL:
http://blogs.msdn.com/b/lcris/archive/2007/10/03/sql-server-2008-transparent-data-encryption-feature-a-quick-overview.aspx
http://blog.sqlauthority.com/2009/04/28/sql-server-introduction-to-sql-server-encryption-and-symmetric-key-encryption-tutorial-with-script/ [this one is a tutorial]
You probably want the code based one, as opposed to file encryption...
From this article: http://www.sql-server-performance.com/articles/dev/encryption_2005_2_p1.aspx
(Which BTW is the first result for a google search of encrypt data sql server)
Symmetric Keys
A Symmetric Key is a one key that is used for both encryption and decryption. This is a fast, commonly used method for encryption. As with a certificate, many parameters are available when creating Symmetric Keys. In most cases, we only need a limited set of parameters. You can refer to Books Online for all the parameters.
CREATE SYMMETRIC KEY TestSymKey
WITH ALGORITHM = TRIPLE_DES
ENCRYPTION BY CERTIFICATE CertificateTest2
You can specify an encryption algorithm for a symmetric key. DES, TRIPLE_DES, RC2, RC4, DESX, AES_128, AES_192, and AES_256 are the encryption algorithms available for SQL Server data encryption. AES encryption algorithms are currently supported only on Windows 2003. If you are using Windows 2000 or Windows XP, you do not have access to AES encryption algorithms from SQL Server. If you try to use an AES encryption algorithm, you will get an error:
Either no algorithm has been specified or the bit length and the algorithm specified for the key are not available in this installation of Windows.
You can encrypt a Symmetric Key using PASSWORD, SYMMETRIC KEY, ASYMMETRIC KEY, or CERTIFICATE.
The ALTER SYMMETRIC KEY and DROP SYMMETRIC KEY commands are also available to improve maintenance.
After the creation of a Symmetric Key, it is just a matter of using it. There are three functions you can use with Symmetric Keys: Key_GUID, EncryptByKey, and DecryptByKey.
OPEN SYMMETRIC KEY TestSymKey
DECRYPTION BY CERTIFICATE CertificateTest2;
DECLARE #Encryptvalsym varbinary(MAX)
SET #Encryptvalsym = EncryptByKey( key_guid('TestSymKey'),'scott')
SELECT convert(varchar(max),DecryptByKey(#Encryptvalsym))
Before using SYMMETRIC KEY, you need to open it by using the OPEN SYMMETRIC KEY command. To encrypt data you need to pass the GUID of the Symmetric Key. However, to decrypt it you don't have to pass the GUID. Instead, you have to open the encrypted Symmetric Key using the correct decryption method and value.
To increase the security of Symmetric Keys, you can add an authenticator during encryption. You have to use the same value during decryption.
OPEN SYMMETRIC KEY TestSymKey
DECRYPTION BY CERTIFICATE CertificateTest2;
DECLARE #Encryptvalsym1 varbinary(MAX)
SET #Encryptvalsym1 = EncryptByKey(key_guid('TestSymKey'),'scott',1,'SQL Server')
-- Decryption with Symmetric Keys
SELECT convert(varchar(max),DecryptByKey(#Encryptvalsym1,1,'SQL Server'))
I would skip the database centric algorithms and move it to a software managed solution. That way you can completely avoid the key ever being sent over the wire and compromised by a packet sniffing admin. (This is of course assuming you are using default transports for your database connection)
I've used this link as a reference for creating my DataSecurity library. I prefer the software managed scenario because it allows you to go as heavy or as lightweight as the solution requires, and it allows you to manage the keys in a way that compromising your database does not mean that your data gets compromised as well.
I have a web based (perl/MySQL) CRM system, and I need a section for HR to add details about disciplinary actions and salary.
All this information that we store in the database needs to be encrypted so that we developers can't see it.
I was thinking about using AES encryption, but what do I use as the key? If I use the HR Manager's password then if she forgets her password, we lose all HR information. If she changes her password, then we have to decrypt all information and re-encrypt with the new password, which seems inefficient, and dangerous, and could go horrifically wrong if there's an error half way through the process.
I had the idea that I could have an encryption key that encrypts all the information, and use the HR manager's password to encrypt the key. Then she can change her password all she likes and we'll only need to re-encrypt the key. (And without the HR Manager's password, the data is secure)
But then there's still the problem of multi-user access to the encrypted data.
I could keep a 'plaintext' copy of the key off site, and encrypt it with each new HR person's password. But then I know the master key, which doesn't seem ideal.
Has anyone tried this before, and succeeded?
GnuPG allows documents to be encrypted using multiple public keys, and decrypted using any one of the corresponding private keys. In this way, you could allow data to be encrypted using the public keys of the everyone in the HR department. Decryption could be performed by any one having one of the private keys. Decryption would require both the private key and the passphrase protecting the key to be known to the system. The private keys could be held within the system, and the passphrase solicited from the user.
The data would probably get quite bloated by GnuPG using lots of keys: it has to create a session key for the payload and then encrypt that key using each of the public keys. The encrypted keys are stored alongside the data.
The weak parts of the system are that the private keys need to be available to the system (ie. not under the control of the user), and the passphrase will have to pass through the system, and so could be compromised (ie. logged, stolen) by dodgy code. Ultimately, the raw data passes through the system too, so dodgy code could compromise that without worrying about the keys. Good code review and release control will be essential to maintain security.
You are best avoiding using MySQL's built in encryption functions: these get logged in the replication, slow, or query logs, and can be visible in the processlist - and so anyone having access to the logs and processlist have access to the data.
Why not just limit access to the database or table in general. That seems much easier. If the developer has access to query the production, there is no way to prevent them from seeing the data b/c at the end of the day, the UI has to decrypt / display the data anwyays.
In the experience I've had, the amount of work it takes to achieve the "developers cannot see production data at all" is immense and nearly imposible. At the end of the day, if the developers have to support the system, it will be difficult to achieve. If you have to debug a production problem, then it's impossible not to give some developers access to production data. The alternative is to create a large number of levels and groups of support, backups, test data, etc..
It can work, but it's not as easy as business owners may think.
Another approach is to use a single system-wide key stored in the database - perhaps with a unique id so that new keys can be added periodically. Using Counter Mode, the standard MySQL AES encryption can be used without directly exposing the cleartext to the database, and the size of the encrypted data will be exactly the same as the size of the cleartext. A sketch of the algorithm:
The application generates a unique initial counter value for the record. This might be based on some unique attribute of the record, or you could generate and store a unique value for this purpose.
The application generates a stream of counter blocks for the record based on the initial counter value. The counter stream must be the same size or up to 1 block larger than the cleartext.
The application determines which key to use. If keys are being periodically rotated, then the most recent one should be used.
The counter stream is sent to the database to be encrypted: something like
select aes_encrypt( 'counter', key ) from hrkeys where key_id = 'id';
The resulting encrypted counter value is trimmed to the length of the cleartext, and XORed with the cleartext to produce the encrypted text.
The encrypted text is stored.
Decryption is exactly the same process applied to the encrypted text.
The advantages are that the cleartext never goes any where near the database, and so the administrators cannot see the sensitive data. However, you are then left with the problem of preventing your adminstrators from accessing the encrypted counter values or the keys. The first can be achieved by using SSL connections between your application and database for the encryption operations. The second can be mitigated with access control, ensuring that the keys never appear in the database dumps, storing the keys in in-memory tables so that access control cannot be subverted by restarting the database with "skip-grants". Ultimately, the only way to eliminate this threat is to use a tamper-proof device (HSM) for performing encryption. The higher the security you require, the less likely you will be able to store the keys in the database.
See Wikipedia - Counter Mode
I am just thinking out loud.
This seems to call for a public/private key mechanism. The information would be stored encrypted with the HR public key and would only be viewable by someone in possession of the associated private key.
This, to me, seems to rule out a web based interface to view these confidential data (entering them via the web interface is certainly feasible).
Given that individuals come and go, tying the keys to a specific person's account seems infeasible. Instead, one must handle key distribution separately and have a mechanism for someone to change the keypair used (and re-encrypt the database — again without the use of a web interface) in case the current HR manager is replaced with someone else. Of course, nothing would prevent the HR manager from dumping all the data before leaving while before the keys are replaced.
I'm not sure how feasible this is currently, or what current stable DB systems have support for this, but alternate authentication mechanisms at the database level may help. For example Drizzle, a refactoring of the MySQL code base, supports (or aims to?) completely pluggable authentication, allowing no auth, server housed auth, or auth through PAM or some other mechanism, meaning you can use LDAP.
If you had different levels of access based on the database connection, and the application login also specified what you could actually access in the database, you could theoretically build a system where it wasn't possible to access the confidential database info unless using an account with specific access rights, regardless of the privilege escalation attempts in the application itself.
As long as the people setting user account access rights can be trusted or themselves are OK to see the confidential information, this should be fairly secure.
P.S. It might be useful to use a generic DB connection for "regular" application information, but when an attempt to access confidential information is made, then the specific DB connection is attempted. This allows for a few DB connections to handle most requests, assuming the majority of users aren't viewing confidential info. Otherwise, a separate DB connection per user may become burdensome to the DB.
I have a web application that uses a symmetric encryption algorithm.
How would you store the secret key and initialization vector? Storing as a literal in the code seems like a bad idea. How about app settings? What is the best practice here?
One standard approach in the webapp world is to split the key and put it in different places. E.g., you might split the key and put part of it in the filesystem (outside of the 'webapps' directory), part of it in the JNDI configuration (or .net equivalent), and part of it in the database. Getting any single piece isn't particularly hard if you're compromised, e.g., examining backup media or SQL injection, but getting all of the pieces will require a lot more work.
You can split a key by XOR-ing it with random numbers of the same size. (Use a cryptographically strong random number generator!) You can repeat this process several times if you want to split the key into multiple pieces. At the end of the process you want, e.g., three partial keys such that p1 ^ p2 ^ p3 = key. You might need to base64-encode some of the partial keys so they can be stored properly, e.g., in a JNDI property.
(There are more sophisticated ways to split a key, e.g., an n-of-m algorithm where you don't require all of the pieces to recreate the key, but that's -far- beyond what you need here.)
If you can require the user to actively enter the password, there are PBE (password-based encryption) algorithms that convert a password to a good symmetric key. You want to find one that requires an external file as well. Again it's a case the tape backups or the password itself isn't enough, you need both. You could also use this to split the password into two pieces with JNDI - you can use a plaintext passphrase in JNDI and an initialization file somewhere in the filesystem.
Finally, whatever you do be sure you can 'rekey' your application fairly easily. One approach is to use the password obtained above to decrypt another file that contains the actual encryption key. This makes it easy to change the password if you think it's been compromised without requiring a massive reencryption of all of the data - just reencrypt your actual key.
Is it possible for you to enter a password interactively whenever the application starts up? That way you don't have to store the key, or at least any keys (whether they are symmetric or private keys) can be encrypted with this "bootstrap" password.
If not, store your secret key in a file by itself and modify its permissions to make it accessible only to the user running the web application.
These approaches are platform-agnostic. For more concrete suggestions, information about your platform would be helpful.
By the way, an initialization vector should be used for only one message. And IVs do not have be kept secret, so you could store it anywhere, but storing it with the one message that uses it is customary.
I have used an approach where my application requires a symmetric key when it starts and looks for it in a certain file. Once the application has started up I remove the file. A copy of the file is kept remotely for any required restarts. Obviously this approach is not viable if your applciation has frequent restarts.
Another alternative would be a certificate manager such as the Windows Certificate Store. It can store certificates and their keys securely and it's also possible to mark private keys as non-exportable so it would require some serious hacking to get the key out. Your application could load its certificate from the Certificate Store and be able to call operations to sign requests or generate new symmetric keys. In addition you can assign permissions to different certifcate stores so that only certain privileged accounts would be able to access the certificate.
stick it in the web.config and encrypt that section
This SO question talks more about web.config encryption
This should help ...
http://msdn.microsoft.com/en-us/library/ms998280.aspx
But, you really should consider going to PKI if you are serious about protecting your data.
We have a slightly different, but related issue. We have keys generated every few days, and when decrypting, we have to try all our keys because we do not know which day the encryption took place. What we did was to encrypt the keys one more time and store them as secretes. This way, we only have one set of keys to manage.
For secure storing of encryption key you can use KMS service of AWS. Please use this service for storing such confidential keys. PFB url for kms service.
documentation : https://aws.amazon.com/kms/