安全地将加密的标准字符串转换为securestring [英] securely convert encrypted standard string to securestring

查看:147
本文介绍了安全地将加密的标准字符串转换为securestring的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个加密的标准字符串,该字符串在powershell中通过"convertfrom-securestring"创建,并保存到文件中.后来,我使用C#应用程序读取了该加密的字符串(在相同的用户ID下,并且在同一台计算机上).我想将此加密的字符串转换为securestring对象.在powershell中,可以使用"convertto-securestring"来执行此操作.

I have an encrypted standard string, created in powershell via "convertfrom-securestring" and saved to a file. Later, I read this encrypted string with a C# app (under same user ID and on same machine). I want to convert this encrypted string into a securestring object. In powershell, one can do this using "convertto-securestring". How can one do this securely in c#?

我知道这个答案(如何使用ConvertTo-SecureString ),,但它假定已使用已知密钥创建了加密的字符串.这与没有密钥创建加密字符串的情况不同(因此,加密字符串与用户ID和构造它的机器相关联).

I am aware of this answer (How can I use ConvertTo-SecureString), but it assumes the encrypted string has been created with a known key. This is different from the case where the encrypted string has been created with no key (and is thus tied to the userID and machine on which it was constructed.)

还请注意,在上述问题的注释中,引用了Microsoft的文档,该文档指示在未提供密钥的情况下使用Windows数据保护API(DPAPI).本文( https://msdn.microsoft. com/en-us/library/ms229741(v = vs.110).aspx )显示了如何使用DPAPI,但是不幸的是,以Microsoft文章中指定的方式使用它会再次导致字符串被以明文形式存储在字符串对象中(我们无法对其进行控制,无法处理),因此以指示的方式使用它是不安全的.

Note also that in the comments in the above-referenced question, documentation from Microsoft was quoted that indicated the Windows Data Protection API (DPAPI) is used in the case where no key is provided. This article (https://msdn.microsoft.com/en-us/library/ms229741(v=vs.110).aspx) shows how to use the DPAPI, but unfortunately using it in the manner specified in the Microsoft article would result again result in the string being in clear-text in a string object (over which we have no control, vis-a-vis disposal), and so using it in the manner indicated would be insecure.

实际上,这实际上是这的组合(如何使用ConvertTo-SecureString .

Actually, this is effectively a combination of this (How to decrypt a string in C# which is encrypted via PowerShell) and the question in How can I use ConvertTo-SecureString.

为了记录,此代码有效,但我不确定将解密后的字符串存储在字节和char数组中可能会有什么问题,即使我尽快清除它也是如此:

For the record, this code works, but I am not sure what the issues may be with storing the decrypted string in byte and char arrays, even though I do clobber it as quickly as possible:

public static System.Security.SecureString MakeSecurityString(string pwd)
{
    int lngth = pwd.Length / 2;
    byte[] encrypted = new byte[lngth];
    for (int i = 0; i < lngth; ++i)
    {
        encrypted[i] = byte.Parse(pwd.Substring(2 * i, 2), System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture);
    }

    byte[] decrypted = System.Security.Cryptography.ProtectedData.Unprotect(encrypted, (byte[])null, System.Security.Cryptography.DataProtectionScope.CurrentUser);
    var chars = System.Text.UnicodeEncoding.Unicode.GetChars(decrypted);
    for(int i=0; i<decrypted.Length; ++i)
    {
        decrypted[i]=0;
    }
    var secureString = new System.Security.SecureString();
    for (int i = 0; i < chars.Length; ++i)
    {
        secureString.AppendChar(chars[i]);
        chars[i] = '\0';
    }

    return secureString;
}

我认为上面的代码是安全的,除了短暂的一刻,密码是用字节数组decrypted然后是字符数组chars的明文形式,尽管我们尽可能快地将它们清零因此,退出例程后,至少密码不能在内存中徘徊.我们多次调用secureString.AppendChar,正如下面的Oguz Ozgu所指出的,这意味着secureString必须先解密然后在内部重新加密字符串-可以认为这样做是安全的.有人可以对以上代码的安全性问题发表评论吗?

I think the above code is secure, except for the brief moment that the password is in clear text in the byte-array decrypted and then the char-array chars, though we zero these out as quickly as possible so that at least the password cannot hang around in memory after exiting the routine. We call secureString.AppendChar multiple times, which as Oguz Ozgu pointed out below, means secureString must be decrypting and then re-encrypting the string internally - one would presume this is done safely. Can someone comment on security issues of the above code?

请注意,下面的代码将避免多次调用secureString.AppendChar,但必须以不安全"的方式运行:

note that the code below would avoid the multiple calls to secureString.AppendChar, but it must be run as "unsafe":

        SecureString secureString;
        fixed (char* pChars = chars)
        {
            secureString = new SecureString(pChars, chars.Length);
        }
        for (int i = 0; i < chars.Length; ++i)
        {
            chars[i] = '\0';
        }
        return secureString;

还请注意,下面Indigo的注释中的链接清楚地表明,这仅在Windows的.NET框架中是安全的.

Note also that the link in Indigo's comment below makes it clear that this is ONLY SECURE IN A .NET FRAMEWORK ON WINDOWS.

推荐答案

我不知道是否有本机C#方法来执行此操作,但是如果没有,您总是可以退回到使用运行空间来执行Powershell管道并使用cmdlet.

I don't know if there is a native C# method to do this, but if not you can always fall back to using a runspace to execute a powershell pipeline and just use the cmdlet.

如果将运行空间保持打开状态,则重复执行将非常快.

If you keep the runspace open, repeated executions will be pretty fast.

这篇关于安全地将加密的标准字符串转换为securestring的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆