使用 C# 保护内存中的敏感数据

2023-12-27

我有一个 C# 应用程序,它用敏感数据初始化一些变量。它们不是密码,但我们认为它们很敏感。我要保护的变量值都是字符串类型。

我想做的是找到一种机制(我知道没有 100% 的机制),让我能够保护内存中的变量值,或者至少让攻击者更难读取它们。因此,我可以保护应用程序内存中的敏感数据,并使其更“无法被任何其他可以在运行时跟踪、转储或读取我的应用程序的应用程序读取”。

我看到存在 Microsoft 数据保护 API (DPAPI),其中有一个名为受保护的内存 https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.protectedmemory?view=netframework-4.8.1它提供了两种方法保护和取消保护,here https://learn.microsoft.com/en-us/dotnet/standard/security/how-to-use-data-protection就是一个例子。

无论如何,微软似乎停止使用 ProtectedMemory,就像有人说的那样here https://stackoverflow.com/a/67343989/1624552因为它没有用。

其他人here https://stackoverflow.com/a/15574559/1624552相反,建议使用良好的函数(例如 SHA1/2)对它们进行哈希处理并存储摘要。

我想使用私有属性(因为它只在我的类中使用)而不是一个简单的变量,它的 set 属性将其加密到内存中,而 get 属性将其解密。如下:

public static MyClass
{
    private string MyVariable
    { 
        get 
        { 
            return Encoding.UTF8.GetString(ProtectedMemory.Unprotect(_myVariable, MemoryProtectionScope.SameLogon)); 
        }
        set 
        { 
            _myVariable =  Encoding.UTF8.GetBytes(value);
            ProtectedMemory.Protect(_myVariable, MemoryProtectionScope.SameLogon);
        }
    }

    private byte[] _myVariable;
}

我的其余字符串变量也是如此。

我想做和他的这个人一样的事情post https://stackoverflow.com/q/60754589/1624552但那里的一些人说将受保护的内存从私人支持字段转移到财产不会有帮助(我不确定他指的是什么,如果使用财产不受保护)。您还能否确认我的变量使用私有属性是否会在内存中受到保护?

那么我该怎么做呢?有人可以提供一个简单的代码片段吗?加密/解密过程应该相对较快。

我不想使用任何第三方,只想使用操作系统帮助和.NET Framework。


.NET 优惠SecureString为了这个表面上的目的。但它有一个巨大的警告,几乎破坏了它的实用性:

很少有 .NET API 支持它。这意味着您需要在之间进行转换SecureString and string在应用程序的生命周期中多次出现。每次执行此操作时,秘密值就有机会泄漏到未加密的 RAM 中。因此,当不再需要字符串的纯文本副本时,您必须非常小心地使用unsafe代码。另外,您不知道传递该秘密时会创建多少份秘密副本string到其他 API。以 JSON 序列化为例 - 如果你需要将你的SecureStringJSON 流中的未加密值,在 JSON 序列化完成后,该值很容易存在于 RAM 中的其他位置,可能存在多次。 HTTP 标头和其他经常交换秘密的地方也是如此。

话虽如此,如果您想冒险尝试,您需要了解如何从SecureString至正常string对于 99.99% 不支持它的 .NET API:

    public static string ToInsecureString(this SecureString str)
    {
        if (str == null)
            return null;
        if (str.Length == 0)
            return "";            

        IntPtr unmanagedString = IntPtr.Zero;
        try
        {
            unmanagedString = SecureStringMarshal.SecureStringToGlobalAllocUnicode(str);
            return Marshal.PtrToStringUni(unmanagedString);
        }
        finally
        {
            Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
        }
    }

以及如何转换正常string to a SecureString:

    public static SecureString ToSecureString(this string s, bool readOnly = true)
    {
        if (string.IsNullOrEmpty(s))
            return null;
        unsafe
        {
            fixed (char* chars = s)
            {
                var ss = new SecureString(chars, s.Length);
                if (readOnly)
                    ss.MakeReadOnly();
                return ss;
            }
        }
    }

最后,您需要一种将明文字节清零的方法string当你完成后:

    public static void ScrubString(ref string s)
    {
        if (s == null)
            return;
        unsafe
        {
            fixed (char* chars = s)
            {
                for (int i = 0; i < s.Length; i++)
                {
                    chars[i] = (char)0;
                }
            }
        }
    }

你必须非常小心最后一个;由于 .NET 缓存字符串的方式,这可能会产生比您预期更多的后果。除了从以下内容转换而来的纯文本字符串外,您永远不应该使用它SecureString使用ToInsecureString上面,因为您知道它们将存在于自己的缓冲区中。

这一切值得吗?老实说可能不是。试图将秘密保护在 RAM 中几乎总是一场失败的战斗。但如果您想尝试一下,或者只是需要勾选审核表上的复选框,那就去做吧。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 C# 保护内存中的敏感数据 的相关文章

随机推荐

  • 如何在 WinForms 中从 app.config 读取 AppSettings

    我通常使用文本文件作为配置 但这次我想利用 app config 将文件名 键 与名称 值 关联起来 并使名称在组合框中可用
  • NebulaGraph 中标签字符串的最大长度是多少?

    我正在使用Nebula Graph数据库 我想插入一个字符串类型的顶点 你知道标签字符串的最大长度吗 string类型的属性值没有限制 但查询的最大长度限制为4MB 如果是通过insert语句插入的话 string对应的属性字段不能超过这个
  • 检查按钮在 espresso 测试、android studio 中是否可点击

    我正在编写测试来确定特定按钮不可单击或可单击 然而 在我看来 没有任何方法 或者我找不到可以使用 Espresso 检查此功能的方法 谁能帮我 谢谢 为什么不 您可以使用 isClickable 匹配器 onView withId R id
  • Eclipse AutoValue 类无法构建

    我正在运行 Eclipse Kepler SR2 其中 Maven 3 1 1 附加有 m2e 和 m2e apt 插件 但我收到一个错误 我不知道如何解决 我设法找到了获得所需的所有依赖项 AutoValue https github c
  • 快速使用 NSData

    所以我已经弄清楚如何快速提取 NSData 但我对设置它感到困惑 var testBytes Byte 0x14 0x00 0xAB 0x45 0x49 0x1F 0xEF 0x15 0xA8 0x89 0x78 0x0F 0x09 0xA
  • 如何在 AWS Lambda 上创建 EC2 时将脚本传递到 UserData 字段?

    我尝试在 AWS Lambda 创建的新 EC2 实例的 Userdata 字段中传递脚本 使用适用于 Javascript 的 AWS 开发工具包 Node js 6 10 var paramsEC2 ImageId ami 28c901
  • 循环遍历二维数组的最快方法?

    我只是偶然发现这篇博文 http lbrandy com blog 2009 03 more cache craziness 关于缓存算法 作者展示了两个循环遍历矩形并计算某些内容的代码示例 我的猜测是计算代码只是一个占位符 在其中一个示例
  • 如何使用 jQuery 折叠嵌套列表?

    我有一个嵌套列表 ul li a href stuff a li li a href stuff2 a li ul li a href stuff3 a li ul li a href stuff4 a li ul 并希望在单击 li 时折
  • 在非视网膜设备上将 @2x 添加到高于特定分辨率的 src

    我在我的网站上使用 retinaJS 在视网膜设备上提供 2x 图像 我还希望能够使用 jQuery 在非视网膜 大屏幕桌面设备上服务器 2x 图像 因此 如果屏幕分辨率高于 1330px 那么我希望能够将 2x 添加到文件名末尾 文件后缀
  • 使用 python 从 mongodb 检索存储的图像

    from pymongo import MongoClient from bson objectid import ObjectId import numpy as np import gridfs import os os path i
  • Java:将 XML 写入数据库,最简单的方法是什么?

    我有大量 XML 文件和它们的 XSD 我想简单地将 then 转换为 POJO 并将它们插入数据库 数据库模式在我的控制之下 因此它可以是我喜欢的任何内容 我查看了很多 api 但想要另一种意见 哪种效果最好 JAXB XMLBeans
  • AngularJS 中的测试:注入函数的引用错误

    我尝试测试下面的代码 describe myService test function describe when I call myService one function beforeEach angular module Target
  • 在as3中使用多点触控同时拖动两个对象

    我试图在 AS3 中使用多点触控同时拖动两个对象 我的目标是让用户将两个对象捏在一起 现在我无法让两者同时移动 有什么想法为什么这不起作用吗 Multitouch inputMode MultitouchInputMode TOUCH PO
  • 如何在正则表达式中匹配非 ASCII(德语、西班牙语等)字母?

    我无法找到或创建仅匹配字母 空格 重音字母以及西班牙语和德语字母的正则表达式 我现在用的是这个 var reg new RegExp a z 我试过了 alpha a zA Z0 9 p L 任何想法 或者javascript引擎支持的正则
  • c++ 将罗马数字转换为小数

    该程序是我刚刚参加的考试的一部分 我必须编写它 我只走到了这一步 却哪儿也去不了 提示如下 编写一个测试函数 toDecimal 将罗马数字 例如 MMLXVII 转换为其十进制数字表示形式 使用 Main 测试该函数 toDecimal
  • Apache Beam:使用 Withtimestamp 分配事件时间时出错

    我有一个无限的 Kafka 流发送具有以下字段的数据 identifier xxx value 10 0 ts 2019 01 16T10 51 26 326242 0000 我使用 kafka 的 apache beam sdk 读取流
  • 电子邮件中的 Button_to 未发布

    请参阅此问题的演变的更新 在我的网站上 每个用户都有一个仪表板 他 她可以在其中单击链接来接受或拒绝请求 根据单击的内容 请求记录将使用相关状态进行修补 为了让用户更方便 我尝试将此仪表板嵌入到发给他们的电子邮件中 这样他们就不必直接访问该
  • 路径查找算法:A* 与跳跃点搜索

    我知道 A 比 Dijkstra 算法更好 因为它考虑了启发式值 但是从 A 和跳跃点搜索来看 哪种算法是在有障碍物的环境中找到最短路径的最有效算法 有何不同 跳跃点搜索是基于图表上的某些条件的改进的 A 因此 如果满足这些条件 主要是统一
  • 在游乐场导入神无

    有没有办法添加 Kanna https github com tid kijyun Kanna https github com tid kijyun Kanna 到 XCode 中的 Playground 我尝试过手动安装并通过 Coco
  • 使用 C# 保护内存中的敏感数据

    我有一个 C 应用程序 它用敏感数据初始化一些变量 它们不是密码 但我们认为它们很敏感 我要保护的变量值都是字符串类型 我想做的是找到一种机制 我知道没有 100 的机制 让我能够保护内存中的变量值 或者至少让攻击者更难读取它们 因此 我可