使用 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# 保护内存中的敏感数据 的相关文章

  • 如何转发声明要在 unique_ptr 的标准容器中使用的类

    在智能指针的标准容器中使用它时 是否可以避免完整的类定义可见 例如 我无法编译以下内容 include
  • OpenCV SVM 给出奇怪的预测结果

    我对 OpenCV 和支持向量机都很陌生 我想使用 SVM 训练具有两个标签的数据集 然后预测给定集合的标签 我当前的集合包含大约 600 行 具有相等的类分布 1 为 300 行 1 为 300 行 包含 34 列 这是我当前用于设置 O
  • 如何用另一个静态变量初始化一个静态变量?

    静态1 hpp include
  • C 中的 '\0' 和 printf()

    在 C 入门课程中 我了解到在存储字符串时存储空字符 0在它的最后 但是如果我想打印一个字符串怎么办 printf hello 虽然我发现它并没有结束 0通过以下声明 printf d printf hello Output 5 但这似乎不
  • 为什么 ObservableCollection 有两个集合构造函数?

    The 可观察集合 T https msdn microsoft com en us library ms668604类有两个构造函数 可以在其中传递项目集合 一个构造函数接受一个IEnumerable T 另一个List T 鉴于List
  • 有没有办法找到dll公开的所有函数

    我一直在寻找一种方法来获取映射到 dll 中函数名称的所有字符串 我的意思是您可以调用 GetProcAddress 的所有字符串 如果你对 dll 进行十六进制转储 符号 字符串 就在那里 但我认为必须有一个系统调用来获取这些名称 如果您
  • 将视频上传/保存到数据库或文件系统

    我以前从未尝试过保存视频 所以我对此了解不多 我知道如果视频很小 我可以转换为字节数组并保存到数据库 但是为了提高效率 我想了解如何将任何上传的视频保存到我的服务器文件中 然后只保存该文件的文件路径我的数据库表中的视频 我完全不知道如何开始
  • 是否自初始化 'A a = a;'允许吗?

    此代码在运行时在复制构造函数中失败 但编译器 MSVS2008 没有发出警告 您能解释一下 最好引用标准 这段代码是否非法或什么 我理解 A a a 永远不应该写在第一位 但我正在寻找理论背景 class A public A p new
  • 使用信号和槽更新指针

    我对 Qt 很陌生 请帮我解决这个问题 我正在使用线程在后台执行密集操作 同时我想更新 UI 所以我使用 SIGNALS 和 SLOTS 为了更新 UI 我发出一个信号并更新 UI 让我们考虑下面的示例代码 struct sample QS
  • “DeploymentItem”属性是什么意思?

    假设我们有一个简短的程序 namespace ConsoleTryIt static class Program static void Main string args var sum Add 1 2 private static int
  • C++ 模板参数数量错误(2,应该是 1)

    我使用 C 并行快速排序程序进行了测试 如下所示 首先使用列表作为容器 然后我转移到通用容器类型 但它报告了标题错误 可以帮忙解决这个问题吗 include
  • 从 AuthorizeAttribute 继承的属性不起作用

    我目前正在尝试根据用户角色在新的 ASP MVC 5 应用程序中实现安全性 目标是防止用户在没有特定角色 或更高角色 的情况下访问某些控制器或控制器方法 根据到目前为止我所读到的问题 我创建了一个继承 AuthorizeAttribute
  • 如何在realm-dotnet中存储System.Collections.Generic.Dictionary

    我正在尝试将 Realm NET 集成到我的 uwp 项目中 我想知道是否有任何方法可以在 Realm dotnet 库中存储 System Collections Generic Dictionary 我试过这个 public class
  • 在链表程序中使用模板时重载 C++ 中的 << 运算符

    我正在尝试实现一个链接列表 但是当我尝试重载 include
  • 调用泛型类的方法

    这是上下文 我尝试编写一个映射器来动态地将域模型对象转换为 ViewModel 对象 我遇到的问题是 当我尝试通过反射调用泛型类的方法时 出现此错误 System InvalidOperationException 无法对 Contains
  • Selenium - 模式对话框存在 - 如何接受信息?

    我有以下问题 在页面上提交一些日期后 我有一个如图所示的模式对话框 我想单击 ENTER 来浏览该模式 但它不起作用 我有以下代码 driver FindElement By CssSelector input submit Click A
  • 如何使用实体框架设置连接字符串

    我将 EF6 与 MySQL 结合使用 并有一个用于多个数据库的模型 我希望能够在我的表单中设置连接设置 如何以编程方式设置模型的连接字符串 你应该使用EntityConnectionFactory这就是您所需要的 public strin
  • 从其对象获取结构体字段的名称和类型

    例如 我有一个类似这样的结构 struct Test int i float f char ch 10 我有一个该结构的对象 例如 Test obj 现在 我想以编程方式获取字段名称和类型obj 是否可以 顺便说一句 这是 C 你正在要求C
  • 为什么 INT64_MIN 的定义不同?为什么他们的行为不同?

    The stdint h我公司的标题是 define INT64 MIN 9223372036854775808LL 但在我项目的一些代码中 一位程序员写道 undef INT64 MIN define INT64 MIN 92233720
  • 从 C/C++ 程序进行 Ping

    我想编写一个 C 或 C 程序 给定一个 IP 地址 对其进行 Ping 然后根据 Ping 是否成功执行进一步的操作 这个怎么做 尽情享受Ping 页面 http www ping127001 com pingpage htm 其中有一个

随机推荐

  • 如何在 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 的机制 让我能够保护内存中的变量值 或者至少让攻击者更难读取它们 因此 我可