将 COM 任务分配器内存中的非托管 Unicode 字符串编组到 SecureString

Marshal Unmanaged Unicode String in COM Task Allocator Memory to SecureString

我正在使用 API 调用 advapi32.dll 来管理 Windows 已保存的凭据,以便自动执行某些可以使用已保存凭据的 windows 应用程序,这是有效的很好。

我正在尝试更新我的代码以在整个过程中使用 SecureString 作为密码,因为我在任何时候都不需要与密码中包含的文本进行交互,因此如果我的应用程序永远不会持有它应该会更安全明文密码。

我能够将 SecureString 编组到 COM 任务分配器内存以传递给 API 调用:

var unmanagedPassword = Marshal.SecureStringToCoTaskMemUnicode(userCredential.Password);

但是,当涉及将该信息读回应用程序时,我无法找到一种方法将此类非托管字符串编组回 SecureString 而不将字符串复制到托管内存中,无论是作为字符串或字节数组。

有没有我忽略的安全方法?

非常感谢 Jeroen Mostert 提出这个解决方案的评论,它应该尽可能安全。

正如 Jeroen 所描述的,每个字符都被读取为一个 short 并一次附加到一个新的 SecureString

任务分配器内存中的非托管字符串以空值终止,因此读取字符直到获得 0。非托管二进制字符串以长度为前缀,因此需要对下面的代码稍作修改。

    var outString = new SecureString();
    outString.AppendChar('p');
    outString.AppendChar('a');
    outString.AppendChar('s');
    outString.AppendChar('s');
    outString.AppendChar('w');
    outString.AppendChar('o');
    outString.AppendChar('r');
    outString.AppendChar('d');
    var ptr = Marshal.SecureStringToCoTaskMemUnicode(outString);

    var inString = new SecureString();
    var i = 0;
    short c;

    while ((c = Marshal.ReadInt16(ptr, i)) != 0)
    {
        inString.AppendChar((char)c);
        i += 2;
    }

    Marshal.ZeroFreeCoTaskMemUnicode(ptr);