保护服务器上的解密密钥

信息安全 加密 密钥管理
2021-08-17 09:13:38

在不将解密密钥以明文形式存储在服务器上的情况下,对公共云服务器磁盘上的敏感数据进行加密和解密的最合适方法是什么?

要求

在我们的 SaaS 网络/移动应用程序中,用户登录后可以将包含敏感客户数据的 PDF 文件上传到由第三方提供商(例如 Amazon/Rackspace)物理托管的公共云服务器。我想通过在将数据写入磁盘之前对其进行加密来保护磁盘上的数据,并在从磁盘读取数据时对其进行解密。

一个常见的解决方案是使用对称加密,例如 AES,并将解密密钥存储在服务器的文件系统中。我想避免将明文解密密钥与数据一起存储,以保护对磁盘上数据的访问,无论它最终位于第 3 方的基础架构中 - 例如可能跨多个物理服务器和磁盘(服务器磁盘,在每日图像备份磁盘上未加密)数组)等。

条件:用户应该能够下载他们之前上传的 PDF。管理员用户应该能够查看任何用户上传的 PDF。

我正在考虑使用用户的登录密码来保护解密密钥。

潜在的解决方案

在每个用户注册期间,一个 RSA 公钥/私钥对将由服务器磁盘生成并存储在服务器磁盘上。私钥将存储为使用用户密码加密的 AES(实际上是基于用户密码的 PBKDF2 派生密钥)。

加密:

  • 纯文本 PDF 上传到服务器(通过 SSL)
  • 服务器为 AES 加密生成一个随机字符串 (R)。
  • RSA 使用用户的公钥加密 R。RSA 使用管理员用户的公钥加密 R。# 允许管理员用户解密任何使用 R 和 AES 加密的 PDF
  • 将这三个加密部分存储到文件系统中。

解密:

  • 使用用户的登录密码解密用户的私钥(通过 PBKDF2)
  • RSA 使用用户的私钥解密 R。
  • AES 使用 R 解密 PDF 并将其返回给用户

这样,如果有人可以完全访问完整的文件系统数据,他们就无法解密 PDF 文件,除非他们也知道密码。

问:这是一个安全的解决方案吗?你看到其中的缺陷了吗?我应该考虑是否有合适的替代方案?

3个回答

你肯定走在正确的轨道上,但你可能让它比你需要的复杂一点。您已正确识别出对称加密系统会造成系统上存在解密密钥的重大问题。

如果您选择为每条数据生成公钥/私钥,除了在非最佳位置“处理”私钥之外,您的生活可能会变得不必要地困难。如果您与使用用户公钥加密的数据结婚,可以修改以下内容以存储加密对称密钥的两个副本。在这种情况下,最好允许用户生成一个 keeper 并为您提供公钥,而不是为用户生成密钥对。(换句话说,你真的不想处理私钥)

  1. 在受信任的位置,为服务器/应用程序生成公钥/私钥对
  2. 将公钥(仅)复制到用户和数据库之间的应用程序路径中
  3. 每当敏感数据到达时,生成一个随机密钥并使用此密钥使用对称算法(例如 AES)加密敏感数据
  4. 使用应用程序公钥加密随机密钥

这种方法有很多理想之处:

  • 具有业务需求和适当权限的后端系统和用户可以在单独的系统中使用私钥来检索敏感数据
  • 由于只能使用私钥来解密随机密钥,因此除了对破坏应用程序的攻击者的原始蛮力之外,没有其他有用的攻击面
  • 蛮力攻击的有效性大大降低,因为对任何随机密钥的成功攻击只能提供对该单条数据的访问;所有其他键都不同。这使得蛮力攻击对对称密钥没有吸引力。
  • 目前,针对 4096 位公钥/私钥对的蛮力被认为是难以处理的

所以,再一次,你有正确的想法,但你可能想稍微简化你的方法!

首先,@taz 对您开箱即用地思考如何让您的客户数据更加安全感到满意,但是我有一些担忧和可能的建议,以进一步保护数据存储......

对于您的目标系统安全性问题,我看到隐蔽服务器妥协的可能性导致您的客户数据在他们下次登录时被包含在内,并且我看到管理员帐户的可能性是单点故障/妥协。虽然提议的系统比我看到的其他服务器管理员实施的系统更安全,但我将介绍一些其他选项,您可能希望寻找灵感,使安全性更加严格。

启用网络/应用程序的选项

  1. 考虑在浏览器中使用 openpgpjs进行客户端解密

  2. 考虑使用 openpgp-php进行服务器端加密

  3. 考虑从ProtonMailKeyBase中提取源代码,了解这些团队如何在服务器和客户端之间实现加密/解密。

另一种可能的解决方案是 sshfs + GnuPG 加密......这是对客户端和服务器的一些设置,但它会将客户端和管理员的私钥保留在其相关文件系统上,并完全关闭服务器文件系统。

在云服务器上设置 sshfs 到 chroot 客户端

  1. 安装 sshfs 到服务器

    apt-get install sshfs
    
  2. 为客户建立一个新的群体以得到认可

    group add sshfsmount
    
  3. 将用户添加到新组并将用户添加到服务器

    Var_users_list="bob,alise"
    Var_chroot_group="sshfsmount"
    for _user in ${Var_users_list//,/ }; do
        ## Add user
        adduser ${_user}
        ## Lock user account from logins and append to chroot group
        passwd -l ${_user}
        usermod -s /bin/false  -a -G ${Var_chroot_group} ${_user}
        ## Make directory for user to be chrooted to with restricting permissions
        mkdir -p ${Var_chroot_group}/${_user}
        chown root:root ${Var_chroot_group}
        chown ${Var_chroot_group}:${_user} ${Var_chroot_group}/${_user}
        chmod 760 ${Var_chroot_group}/${_user}
    done
    
  4. 修改服务器 ssh 配置

    nano /etc/ssh/sshd_config
    ## snip, change subsystem settings
    Subsystem      sftp     internal-sftp
    ## snip, append the following to chroot the group
    Match Group sshfsmount
        ChrootDirectory /sshfsmount/%u
        ForceCommand internal-sftp
        AllowTcpForwarding no
        PermitTunnel no
        X11Forwarding no
    
  5. 检查设置并重新加载服务器 ssh 配置

    sshd -T
    if [ "$?" = "0" ]; then
        /etc/init.d/ssh reload
    fi
    

注意Subsystem sftp internal-sftp可能会导致 ssh 登录失败,因此请在重新启动服务器后尝试通过普通 ssh 帐户登录,然后再注销进行上述更改的当前 ssh 终端。

  1. 将客户的公共 ssh 密钥添加到授权

    Var_users_list="bob,alise"
    Var_key_dir="/ssh_pub_keys"
    for _user in ${Var_users_list//,/ }; do
        find "${Var_key_dir}" -xtype f | while read _key; do
            if grep -qE "${_user}" <<<"${_key}"; then
                mkdir -p /home/${_user}/.ssh
                cat "${_key}" >> /home/${_user}/.ssh/authorized_keys
            fi
        done
    done
    

bob客户端 sshfs的设置

  1. 安装 sshfs

    apt-get install sshfs
    
  2. 修改 ssh 客户端设置以使用密钥

    nano /etc/ssh/ssh_config
    ## append the following config block
    host cloud_server
        User bob
        HostName host.domain
        IdentityFile /some/dir/private_ssh_key
        IdentitiesOnly yes
    

注意host.domain应指向云服务器的域名或IP地址

  1. 创建目录并将云服务器挂载到客户端本地文件系统

    mkdir -p /mnt/glow_cloud
    sshfs cloud_server:/ /mnt/glow_cloud
    

注意卸载使用以下

    fusermount -u /mnt/glow_cloud
  1. 为用户 bob 使用 GnuPG 公钥加密来加密文件,并将输出保存到云服务器

    cat some_local_file.txt | gpg -a -e -r bob@glow_cloud.domain -r admin@glow_cloud.domain -o /mnt/glow_cloud/enc_file.gpg
    

对于文本文件,用户 bob 可以使用vim 插件/脚本在远程服务器上编辑上述加密文件。

对于非文本文件,您可能希望查看最新版本的Paranoid_Pipes以获得更多灵感,并利用与上述类似的步骤使服务器和客户端之间的加密/解密自动进行。但是,这最后一个建议是实验性的,并导致客户端将解密密钥的密码短语保存在本地内存中......因此,上述安全性主要取决于您的客户端,因为管理员可以使用类似的安装方案将自己的私钥远离服务器也。

在公共云上存储任何东西都有一些令人讨厌的现实。解密/加密任何东西的唯一安全方法是在本地客户端本身,以及在本地处理私钥的所有问题 - 电话盗窃、密钥盗窃等。使用公共云意味着您必须在多租户系统上信任它,其他租户无法抓取内存,或者托管服务提供商无法提取副本。如果你有一个非常关键的数据,没有公共云是答案。