Mat*_*zak 5 php c# mysql security encryption
我目前正在开展一个项目,该项目涉及从VisualFox Pro数据库中每日提取数据(药房记录),并将其中的一些上传到WordPress网站,药房的客户可以安全地查看它.我想就我的软件的一般方法提供一些建议 - 我能够对其进行编码,但需要知道我是否采用了正确的方法.我正在编写PC软件(在C#/ .NET 4.5中)和PHP WordPress插件.
我计划使用的加密数据服务器端的当前进程基于本文.总而言之,它主张用存储在服务器上的自己的公钥非对称地加密每个单独的用户数据.然后,用于解密该数据的私钥本身使用用户的密码对称加密并存储.这样,即使数据库被盗,也需要破坏用户的密码哈希,即使这样,也需要为每个用户的数据重复该过程.
作者本人指出的唯一缺点,也是我的问题的主要观点,即当用户登录时,解密的密钥存储在会话存储中.文章建议处理它的方式是仅限制用户登录的时间.我认为更好的解决方案是将该密钥存储在短期安全cookie中(当然整个过程通过HTTPS进行) .这样,如果攻击者可以控制用户的计算机并且可以读取他们的cookie,他们可能只需键入密码并登录,无需窃取数据库,即使攻击者获得访问服务器的权限,他们也无法解密HTTPS流量(或者可以吗?我不确定.)
我应该使用安全cookie还是会话存储来临时存储解密密钥?
我还想弄清楚的第二件事是如何存储数据 - 这更像是一个效率问题.由于每个用户都有自己的加密密钥,因此每个用户的记录必须单独存储.我不知道是否应该为每个用户存储一个"块"数据,包含带有表示记录的对象数组的加密JSON,或者我是否应该将记录存储在具有实际数据结构的表中,并加密每个数据字段与钥匙分开.
我倾向于将数据存储为一个块 - 在我看来,一次解密一个大块数据比使用数千个单独的字段更有效.此外,即使我以正确的结构存储数据,我仍然无法使用MySQL的WHERE,ORDERBY等,因为数据都是BLOB.
我应该将数据存储为每个用户的大块,还是分成不同的字段?
我从DBF文件中提取数据,基本上是一个"差异",我比较当前提取的数据和最后一天的数据,只上传已经改变的用户的块(我不仅可以上传记录,因为我可能最终将用户的数据存储在块中.我还为已被删除的用户添加了"删除"说明.这是因为数据库中有数十万条记录,总计超过200mb,并且每天的大小都在增加.
我目前的计划是将所有这些数据写入JSON文件,gzip并将其上传到服务器.我的问题是,如何在确保数据安全的同时做到这一点?当然,上传将通过HTTPS进行,我有一个API密码,只允许授权上传,但我主要担心的是如果服务器受到损害,如何保护数据.我不希望攻击者只是在处理服务器时从服务器获取JSON文件.我的一个想法是让服务器向我发送用户的公钥列表,并在上传之前在我的软件中执行加密.在我看来,这是保护数据的唯一方法.我可以加密整个JSON文件,可能使用API密钥或特殊密码,但如果攻击者只能访问在服务器上处理的解密文件,那就没有用处.这是一个好的解决方案吗?
我应该在客户端单独加密数据,还是有办法将其安全地传输到服务器并在那里加密?
提前感谢您的任何答案,我很乐意听到之前处理过此类问题的人的意见.
注意:交叉发布给程序员,请参阅注释.
As it happens, I am working on a similar system to encrypt personal details (email, IP) in Wordpress comments, so that if the server is compromised, sensitive data in the database is still encrypted. Storing an assymetric decryption key in the session was out for me, since this could leave the key on the server for an attacker to grab at the same time as their compromising it.
So, cookies over an SSL cert is a better way to go - at least the attacker then has to wait for a user to log in before they can steal their key(s). In tandem with this, some sort of tripwire system would be a good idea, so that users cannot log onto the system (thus providing their keys to the waiting attacker) once it is compromised.
As you say, encrypting records (either with one key as per my design, or many keys as per yours) means that searching through records becomes a process you have to move away from your database server, which in turns means that it will be significantly slower.
You may be able to mitigate against this by making a trade-off between speed and security: some fields can be fuzzied and then stored unencrypted. For example, if you want to search where your patients are located, get their (lat, long) from their address, apply a random shift to it (say up to 3 miles on both axes in either direction) and then store the resulting coordinates in plain text. Approximate count queries relating to location can then be done without decryption.
The above looks at how to mitigate against attacks against the server, which is your greatest risk, since you have all your records stored there. As you rightly point out though, attacks on client machines is also a concern, and if they are members of the public then their security processes can be assumed to be non-existent.
On that basis you could strengthen a single password (which is given in its entirety) with a passphrase from which the client needs to select three random letters (i.e. it is specifically not given in its entirety). This defends elegantly against keyloggers in two ways: firstly drop-down menus are used, which are harder to eavesdrop, and even if the user uses keyboard shortcuts, they have not supplied the full phrase. At each successful logon, the index of the random letters (e.g. 1, 4 and 5) is recorded and not asked again for a long period. Obviously, too many wrong answers causes the account to be locked out and require reauthorisation via a phone call or snail-mail reset code.
Other authentication methods you could use: text the user an additional passphrase every time they enter the correct password, or (probably prohibitively expensive) use an authentication device as per online banking.
Another tip for security is to store as little personal information as possible. If you can do without the ability to immediately reset passwords via email, then name, address, telephone numbers and email - all personally identifying data - are perhaps unnecessary. That personal information can be stored separately on a disconnected database on another server, using a common primary key to link them together. (In fact if the user wishes to reset their password, you could simply store a flag against their anonymous user record, and the pharmacist can run the reset process manually on their firewalled machine when they next visit an admin panel).
Should you encrypt tabular data in one blob or leave it in each column? I've looked at this one as well in my application. For me, I stored it in one blob, since my use-case is search-intensive, and having N decrypts per row rather than one made the decision easy. That said, you may prefer the tidiness of encrypting columns individually, and one could argue that if corruption creeps in, separating them out gives you a better chance that some of the row will survive.
If you decide to store in a single blob, I am using a format similar to this (rows separated with newlines prior to being asymmetrically encrypted):
1.2 <-- version of this format, so I can add things in the future
key1=value1
key2=value2
...
Run Code Online (Sandbox Code Playgroud)
If you have several processes writing to columns, make sure you lock rows between read and write, otherwise (as hinted above) you can lose some of your data.
As you say, this could equally be JSON, if that format is better for you.
My understanding of this question is: how do you replicate to an unencrypted offline copy given that you cannot decrypt user records yourself? I wonder here whether you could relax your security constraints a bit, and store a common public key on the server, and keep a separate record of changes encrypted with the common key. This would populate a table which should periodically be emptied (by running a sync routine on a remote secure machine); thus, the value of the changes table to an attacker will be small compared to obtaining the whole database unencrypted.
The corresponding private key, of course, should be on the pharmacist's computer, again securely fire-walled from the internet.
The risk with this design is that an attacker replaces the server public key with one of his/her own, so that they can later collect information that has effectively been encrypted just for them! However, as long as you've installed a trip-wire on the server, this can be reasonably defended against: if this is triggered, the dynamic part of the web application won't write any new changes (in fact won't work at all) until the system is scanned and determined to be safe.