如何保护代码中的敏感数据



我正在检查保护我的代码不被反编译的方法。

这里有几个很好的线程描述了混淆和代码打包作为保护代码的可能方法。然而,它们都不是理想的,当使用字符串方法/属性名称时,混淆对反射不起作用。许多人根本不建议使用混淆。

所以我目前决定不采用上述任何一种方法。然而我有一部分代码,我需要一种加密,例如,一个数据库连接字符串与IP,登录名和密码存储在代码中作为简单的const string,与电子邮件帐户数据相同。

在ASP。NET中有一个将敏感数据移动到.config文件并加密的选项,但这需要服务器密钥,即链接到一台计算机。我没有读到太多关于它的内容,但我想桌面应用程序也有类似的功能。但是我需要在任何安装了应用程序的计算机上工作。

是否有方法编码/保护这些数据,使其不能与反编译的代码一起读取?

第一个建议是永远不要在代码中直接存储任何敏感内容。你可以总是逆向工程,无论你多么聪明地试图混淆它。

我读过一些东西,比如把密码分成几段,把它们放在代码的不同位置,在最终使用它们之前运行一系列函数……尽管这会使事情变得更加困难,但您仍然可以始终使用调试器监视应用程序,最终您将能够检索秘密信息。

如果我正确地解释你的场景,你所拥有的是要部署在一些客户场所的代码,你的代码连接到数据库(我想也是在客户的监督下),连接到它需要一个密码。该客户端知道这个密码,因此试图对客户端隐藏它是相当无用的。您所做的想要的是限制任何不应该知道该密码的人访问该密码。

您通常通过将敏感信息放在文件夹中的单独文件中来实现这一点,该文件夹应该具有非常严格的权限,只有应用程序和少数选定的人员可以访问。然后,应用程序将在运行时需要时访问这些信息。

另外加密单独的文件原来是一个问题-如果你这样做,那么有一个密钥涉及,再次必须以某种方式保护-无限递归是在它的方式:)保护访问文件通常是足够的,但如果你真的需要尽可能安全,那么一个解决方案是使用基于密码的加密文件。但是这里的想法不是将密码存储在系统上的另一个位置,而是作为带外信息(例如在物理保险库中),并在启动应用程序时输入密码。这也有它的问题:(重新)启动应用程序需要一个人的实际存在,并且您仍然可以从运行应用程序的机器的RAM中检索密码。但这可能是你在没有专门硬件的情况下所能做的最好的事情。

另一个基于密码的加密的好选择是依赖于操作系统特定的"密码库",比如Windows的隔离存储,这是一种不加密和将密码保存在带外之间的权衡。

这不是一个加密答案,但是一种"安全"的方法是通过web服务进行所有数据库调用。然后,您的连接凭据将存储在安全服务器上,客户端通过该服务器传递所有调用。

在你的可分发文件中没有任何敏感信息…

我过去曾处理过这个问题,并提出了三种方法来处理这个问题,但我不确定其中任何一种方法都是完美的:

  1. 混淆或加密值,并希望最好的。当然,加密只是额外的混淆级别,因为密钥必须与其他密钥一起交付。
  2. 通过使用单向加密来消除对密钥本身的需求。使用私钥生成公钥。这可以用于许可或密码验证。您使用私钥生成许可证,但可以使用公钥对其进行验证。或者使用私钥生成一个可以验证的密码,但不能使用公钥反转。
  3. 创建自己的系统特定的键生成机制,类似于ASP.NET所使用的机制。您可以通过为每个安装或站点生成唯一密钥来限制某人在步骤1中逆转加密/混淆的影响。

有很多方法,但现实是,如果你真的想保护你的代码,唯一的解决方案是使用"专业"的产品:-)不要试图重新发明轮子。这些产品通常具有加密字符串的选项。真正的问题是另一个:没有专业的产品(即使有专业的产品),专家可以简单地设置一个断点并查看传递给库方法的参数(例如打开连接的那个)。现在…如果您真的想加密代码的字符串,这很容易。但这有用吗?没有。

现在,只是为了没有人会把这标记为"不是答案",我将发布一些简单的加密/解密代码:

// Generate key. You do it once and save the key in the code
var encryptorForGenerateKey = Aes.Create();
encryptorForGenerateKey.BlockSize = 128;
encryptorForGenerateKey.KeySize = 128;
encryptorForGenerateKey.GenerateKey();
encryptorForGenerateKey.GenerateIV();
var key = encryptorForGenerateKey.Key;
var iv = encryptorForGenerateKey.IV;
// Encrypt: this code doesn't need to be in the program. You create a console
// program to do it
var encryptor = Aes.Create();
var encryptorTransformer = encryptorForGenerateKey.CreateEncryptor(key, iv);
string str = "Hello world";
var bytes = Encoding.UTF8.GetBytes(str);
var encrypted = encryptorTransformer.TransformFinalBlock(bytes, 0, bytes.Length);
var encryptedString = Convert.ToBase64String(encrypted);
Console.WriteLine(encryptedString);
// Decrypt: this code needs to be in the program
var decryptor = Aes.Create();
var decryptorTransformer = decryptor.CreateDecryptor(key, iv);
byte[] encrypted2 = Convert.FromBase64String(encryptedString)
var result = decryptorTransformer.TransformFinalBlock(encrypted2, 0, encrypted2.Length);
var str2 = Encoding.UTF8.GetString(result);

这段代码显然不安全。任何人都可以反编译程序,添加Console.WriteLine(str2)并重新编译它。

你当然可以在编译字符串之前加密它,但是如果你使用一个简单的db或http url,你的代码有时需要纯文本。

在这种情况下没有真正的保护:每个人都可以监听(断点)指定的方法,并且在调用时看到发生了什么,而无需真正阅读代码。不,这里没有真正的保护,也使用混淆有时你会调用一些。net方法带着纯文本字符串,每个人都能读懂它

例如,您可以放置COM或c++ dll来存储加密字符串。非托管dll是不可反编译的,但是,专家当然可以理解dll的反汇编。如前所述,有时您将需要普通数据,而在那一刻,没有可以持久的保护。

你唯一能做的就是改变你的架构。

例如,如果您的数据库是在线的,并且您的应用程序是客户端应用程序,则可以使用web服务进行连接。然后,您可以只公开用户真正需要使用的web服务,没有用户编写sql查询的风险。这样就可以在服务器端添加保护逻辑,而不是在客户端。

如果一切都是离线的,你可以做的不是很多,你可以使用简单的字符串加密使生活更困难,但它永远不会是一个真正的保护。

正如Lucas在其评论中指出的那样,如果你只有一个片段,那么任何反编译你的应用程序的人都可以对它进行反向工程并解密你的数据库密码。

关于存储凭证,我通常的做法是始终将它们存储在应用程序配置文件中。如果我需要保护它,我会使用SecureString和一些加密。这可以用于任何类型的配置信息,而不仅仅是凭据。这里有一篇关于保护配置文件的好文章:在。net app.config文件中加密密码

也许你应该多读一些关于加密网络的文章。配置http://learn.iis.net/page.aspx/141/using-encryption-to-protect-passwords/

否则你就无能为力了。将敏感数据存储在代码中是不可取的,因为任何使用反射器工具的人都可以打开并看到它。如果你想让代码或变量对所有人都不可见,你应该在私有服务器上创建一个webservice,它接受数据,通过它的魔力将其转换并返回给客户端。通过这种方式,发布和检索数据之间的一切都是保密的。

我不确定是否有可能在客户端位置保护您的代码,但解决方案可能是将密码存储在Azure密钥库中,并通过Azure Active Directory对其进行身份验证。然而,逆向工程仍然是可能的。您可以在这里阅读更多内容:https://learn.microsoft.com/en-us/azure/key-vault/

相关内容

  • 没有找到相关文章

最新更新