2012-09-23 57 views
1

我正在准备一个需要以加密格式存储图像的项目。图像将在0.5mb到5mb之间,并且必须保持原始质量。加密存储的图像

我正在考虑使用base64来对它们进行编码,但是之后我需要使用某些东西来加密它们(SHA1?)并将它们作为文件保存在服务器上。

任何人都可以告诉我这个吗?我可以将加密图像存储在哪种文件中?

在此先感谢

+0

为什么你需要加密他们开始?为什么不把它们保存在服务器上? –

+0

因为它们是被归类为医疗记录的牙科xrays – tatty27

+0

加密是_hard_。你需要更多地了解它。 – SLaks

回答

3

我不得不做类似的任务,让我的应用程序上传到服务器存储加密的文件,那么当用户需要从应用程序文件发送到浏览器之前就对它们进行解密。

我必须这样做,因为我的申请涉及我国法律需要存储加密的特殊类型的数据(家庭暴力)。所以我理解OP的情况,不是因为技术原因需要他们加密,而是为了遵守法律。

我所做的是在服务器上安装OpenSSL,以便我可以使用它对AES-256加密文件,您可以使用system()从php执行命令。

该命令来加密是:

echo MyPassword | openssl.exe aes-256-cbc -pass stdin -salt -in somefile.pdf -out somefile.pdf 

和用于解密:

echo MyPassword | openssl.exe aes-256-cbc -pass stdin -d -in somefile.pdf -out decriptedfile.pdf 

这个命令采取任何原始文件(没有关系的格式),并且当解密它再现完全相同的文件,所以不需要base64编码或类似的东西,你喂他们会给你回来的东西。

如果您迁移服务器,请参阅openssl aes-256 encrypted file on windows cant be decrypted on linux以获取可能的警告。

+0

你在哪里存储密码? – 2012-09-23 20:25:44

+0

当时我们有两个选择,在数据库或源代码中进行硬编码,在这两种情况下,密码都需要以纯文本形式存储,正如您所看到的,这两个选项同样是安全方面的不足,您是否有更好的选择? – Nelson

8

操作并不重要;您不仅需要加密数据,还需要防止在服务器上被盗或闯入;您还需要考虑如果您需要更改密钥会发生什么情况。

要加密图像,您的最佳选择可能是mcrypt对称算法。有几个关于如何做到这一点的教程。见What is the best way to encrypt files in AES-256 with PHP?

你需要做的是提供一张图片并在运行中对其进行解密,而不需要将其存储在明文中。

现在的问题是在哪里保持密码。最好的整体解决方案是为每个用户提供一个秘密加密密钥,在用户登记时随机生成;而且密钥本身是用对方的密码加密。您可以使用phpseclib在RSA中执行此操作。相同的加密密钥是与管理密码非对称存储。

所以工作流程是:

  1. 用户登录(并提供他的密码)
  2. 系统的密码散列与存储的散列和授予访问权限进行比较(你会使用的东西,如bcrypt:看Is there a bruteforce-proof hashing algorithm?
  3. 系统还解码加密串,并将其存储在临时会话(持续性会话的可能是一个要解决的问题!
  4. 该用户的所有图片现在他可以访问

要加密图像: - 如果用户上载图像,则上载时加密密钥在会话中可用。使用它:-) - 如果图像以其他方式上传,则在数据库中设置“已加密/仍待加密”标志,并尽快(管理员登录/用户登录)设置所有待处理加密操作被执行。

然后将图像存储为加密文件(“001823040.bin”)。除数据库外,没有参考,它属于哪个用户;并且不知道用户(因此是加密密钥),图像是不可恢复的。

要提供图像,您只需将标题设置为图像类型,然后开始解码文件并将其清晰地输出到用户的浏览器。

从攻击者的角度来看,单独拥有镜像是没有用的,因为它们是加密的。用户数据库是无用的,因为加密密钥本身是加密的。窃取或暴力破解一个用户的密码只能访问该用户的加密密钥,这与其他所有加密密钥不同,然后仍然有任务寻找哪些图像属于该用户。

如果您需要更改用户的密码,仍然可以使用管理密码恢复加密密钥,并使用用户的新密码对其进行不对称重新加密。 这不能自动完成,因为这意味着将现在所有重要的管理员密码保存在系统中的明文中;因此,所有忘记密码的用户都会被批量排队,并在早上管理员收到“有75人在等待密码恢复”通知,提供密码并将其全部解锁。

这很尴尬,但不幸的是所有其他解决方案依赖于密码在本地以明文本地可用,其中安全妥协会使系统全开。 (您有时可以通过设置第二个来解决此限制,这个限制非常小 - 因此不会太脆弱 - 服务器充当加密托管服务;但维护起来要复杂得多)。

多个用户名/密码的情况

您有一个资源在一个表中,并几个用户U1,U2,...联合国报告与访问该资源。这意味着用户U1必须能够访问资源A的解密密钥。

您可以通过存储UserAccessToResource表做到这一点:

user_id   -- the user ID 
resource_id  -- the resource ID 
encryption  -- resource decryption key, encrypted with the user's encryption **key** 

要授权给用户U1和资源A,你必须有访问自己,资源U1的加密密钥。即:

  • 管理员访问Users表并恢复UserKeyEncryptedWithAdminKey。
  • 是管理员,他可以解密UserKey。
  • 以相同的方式访问他ResourceTable [A] .ResourceKeyEncryptedWithAdminKey
  • 他进行加密的ResourceKey使用用户键和存储到UserAccessToResource

用户U5自带通过,并且可以快速验证(5,42,?? )出现在UserAccessToResource表中,所以他知道他可以通过访问资源。检索行,并解密ResourceKey。他现在可以使用ResourceKey访问资源[42]并将其解密为(但没有其他资源,因为它们具有不同的随机ResourceKeys)。

在所有这一切,前端从未访问(除非编程错误),以获取ResourceKey(或用户键)的实际值。 API类似于DecryptResource(UserId, UserPass, ResourceId),并返回解密的资源。

当然,UserAccessToResource可以包含任意数量的用户或资源 - 这是多对多。对于每一个,都必须存储一个加密的密钥(例如,对于AES条目,说32个十六进制字节)。

忘记密码的情况

不幸的是,这种操作无法自动完成。用户发送请求,但直到并且除非管理员登录,否则他的密钥都不可访问。因此,他必须等待。

当管理员不登录时,系统能够访问PasswordRecovery表,找到用户的不完整记录。它访问用户表并检索UserKeyEncryptedWithAdminKey。

现在产生一个随机密钥,并使用一个随机密钥加密完成记录与用户键的PasswordRecovery表。另一列包含用相同的随机密钥加密的单词“Squeamish Ossifrage”。他向用户123发送安全电子邮件,提供随机密钥。

用户123提供的随机密钥给系统。管理员不再登录,但一旦解密系统可以检查,第二个表场确实“娇气Ossifrage”。然后它假定第一个字段是解密的UserKey。系统从User123请求新密码,并将新的UserKeyEncryptedWithUserPass存储到Users表中,从PasswordRecovery清除条目。只有一条记录被更新。由用户123拥有的所有资源密钥保持使用用户123的密钥加密,该密钥没有改变,并且仍然是管理员创建帐户时随机生成的密钥。

下次登录时,用户提供密码并解锁系统。

+0

我知道这已经有一段时间了,但我真的很喜欢这种方法,因为用户键入的密码似乎是唯一可安全加密场景中的加密密钥的东西,因为只要密码中的攻击者已经破坏了文件系统和数据库作为散列存储在数据库中。我在实施方面有几个问题。 – aarryy

+0

我们的应用程序允许多个用户使用不同的用户名和密码使用一个帐户。有什么办法可以让多个密码同时解密密钥吗?此外,我们向用户提供一个忘记的密码链接,允许用户通过点击我们发送的密码重置电子邮件中的链接登录其帐户。在这种情况下,用户可以登录而不提供实际的密码。我想知道该如何处理?谢谢! – aarryy

+0

添加了您所指的两个场景。我希望你会觉得这很有用。 – LSerni