在云端共享加密机密(用户名、密码)的安全实现

信息安全 加密 验证 应用安全 公钥基础设施 云计算
2021-09-02 06:51:12

我正在构建一个多租户(云)环境,该环境需要为接收此信息的代理(后台服务)推出(或可供下载)配置文件。配置中的一条信息是用户名和密码。

假设代理可以被安全地识别到云端,你会使用什么加密和安全系统来加密、共享、推送这些敏感信息?

公钥对足够吗?我认为秘密将被加密为每个代理的公钥,未加密的值将被丢弃。

您对此实施有何看法?在这个应用程序中,我主要使用 C#、Windows Azure、ASP.NET MVC 和 Silverlight。

示例代理端代码 (RSACryptoProvider)

这将在 C# 中生成公钥私钥对,而不是将密钥保存到磁盘

public static void AssignNewKey(){
    const int PROVIDER_RSA_FULL = 1;
    const string CONTAINER_NAME = "KeyContainer";
    CspParameters cspParams;
    cspParams = new CspParameters(PROVIDER_RSA_FULL);
    cspParams.KeyContainerName = CONTAINER_NAME;
// CspProviderFlags.UseNonExportableKey -- Prevent less-knowledgeable attacks against PK
// CspProviderFlags.UseUserProtectedKey -- Interactively prompt for password
    cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
    cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";
    rsa = new RSACryptoServiceProvider(cspParams);

    rsa.PersistKeyInCsp = false;

    string publicPrivateKeyXML = rsa.ToXmlString(true);
    string publicOnlyKeyXML = rsa.ToXmlString(false);
    // do stuff with keys...
}

示例代理端代码选项 2(Bouncy Castle)

public void GenerateKey(string username, string password, string keyStoreUrl)
        {
            IAsymmetricCipherKeyPairGenerator kpg = new RsaKeyPairGenerator();
            kpg.Init(new RsaKeyGenerationParameters(BigInteger.ValueOf(0x13), new SecureRandom(), 1024, 8));
            AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair();

            FileStream out1 = new FileInfo(string.Format("{0}secret.asc", keyStoreUrl)).OpenWrite();
            FileStream out2 = new FileInfo(string.Format("{0}pub.asc", keyStoreUrl)).OpenWrite();

            ExportKeyPair(out1, out2, kp.Public, kp.Private, username, password.ToCharArray(), true);

            out1.Close();
            out2.Close();

        }

private static void ExportKeyPair(
            Stream secretOut,
            Stream publicOut,
            AsymmetricKeyParameter publicKey,
            AsymmetricKeyParameter privateKey,
            string identity,
            char[] passPhrase,
            bool armor)
        {
            if (armor)
            {
                secretOut = new ArmoredOutputStream(secretOut);
            }

            PgpSecretKey secretKey = new PgpSecretKey(
                PgpSignature.DefaultCertification,
                PublicKeyAlgorithmTag.RsaGeneral,
                publicKey,
                privateKey,
                DateTime.Now,
                identity,
                SymmetricKeyAlgorithmTag.Cast5,
                passPhrase,
                null,
                null,
                new SecureRandom()
                //                ,"BC"
                );

            secretKey.Encode(secretOut);

            secretOut.Close();

            if (armor)
            {
                publicOut = new ArmoredOutputStream(publicOut);
            }

            PgpPublicKey key = secretKey.PublicKey;

            key.Encode(publicOut);

            publicOut.Close();
        }
3个回答

使用每个代理的公钥加密数据是一种隐式验证代理的方法。您并不真正知道(在通信通过潜在恶意云的设置中)代理是否真的收到了数据,但您知道只有适当的代理才能解密它;因此,如果数据已经到了某个地方,那么它就会流向正确的代理。这看起来像是解决您的问题的好工具。

请注意,公钥加密可能是矫枉过正。如果您可以安排接收代理和数据发送者共享一个公共密钥(只是一堆几十个随机字节),那么您可以使用对称加密来加密数据。

有几个陷阱:

  • 如果您使用公钥加密方案,那么发送者必须事先以可靠的方式知道代理的公钥。根据您创建和部署代理的方式,这可能会也可能不会容易。

  • 代理接收数据的能力来自其对他的私钥(或对称加密情况下的公共共享密钥)的了解。您必须注意该私钥的存储,因为获取密钥的副本将允许攻击者解密您的加密数据。

  • 非对称加密仅适用于有限的消息。例如,对于 1024 位 RSA 和通常的 PKCS#1 填充,消息中有 117 个字节的硬限制。此外,RSA 加密和解密也不是太快(尽管对于大多数目的来说足够快)。因此,习惯上使用混合方案,其中您不加密消息本身,而是使用随机密钥(一堆随机字节),然后使用对称加密系统(AES)加密数据本身),消息长度快速且不受限制。

  • 当有恶意的被动攻击者时,通常也有主动攻击者。被动攻击者只是监视数据;主动攻击者也可以修改它。通过巧妙地修改加密数据并观察结果(在 SSL 连接中发送的密码已通过这种方式恢复),可以进行许多智能攻击。因此,您不仅需要加密,还需要完整性检查。一种可能性是发送者对加密数据包进行签名,代理在尝试解密之前验证签名。

无数已部署的系统偶然发现了这些问题,并且无法事先对其进行有效测试。您真的应该使用现有的标准格式,以及已经通过正确实现它的努力的支持库。我建议使用CMSOpenPGP我不知道 C# 是否已经支持这些(我对此表示怀疑,尤其是在 OpenPGP 的情况下),但Bouncy Castle是一个开源库(它有一个 C# 版本)。

最后要注意的是,如果您有许多代理应该接收相同的数据,那么使用密钥对数据进行一次加密可能会更有网络效率,然后您使用每个代理的公钥对其进行加密。这被称为广播加密,这就是付费电视供应商所做的(他们向数百万客户发送同样大量的内容,这使得广播不仅值得,而且非常必要)。

公钥/私钥对 - 似乎很适合这种情况,因为您应该假设恶意行为者可以访问云中的数据。尽管云环境的安全性较弱,但您为代理放置在云中的数据可以被加密和验证。

Thomas Pornin 的回答比我的回答更好地掩盖了这一面,所以我要补充的唯一一点是,必须对实现进行测试,因为实现中的弱配置或糟糕的代码可能会破坏安全模型。

正如我从您的问题中了解到的那样,您需要使用计算机网络身份验证协议(“它允许通过非安全网络进行通信的节点以安全的方式相互证明其身份”)来完成您的工作、目的和通信协议的规范是保持:

  • 新鲜:
  • 前向保密
  • 已知的关键弹性
  • 密钥认证
  • 密钥确认
  • 显式密钥认证

为了实现上述规范,您可以设计自己的通信协议,最简单的一种是使用:

S 是受信任的第三方,A & B 是客户希望进行安全通信。

  • A→S: IDA ║IDB
  • S→A:卡布
  • A→B:卡布║IDA

我们可以像这样改进协议:

  • A→S: IDA ║IDB
  • S→A: E(Kas, [Kab])║ E(Kbs, [Kab])
  • A→B: E(Kbs, [Kab]) ║IDA

但是上述两种协议都有很多问题,如果你想确保协议足够强大,最好使用列出的协议之一: