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

时间:2017-09-05 19:57:41

标签: c# unmarshalling securestring unmanaged-memory

我正在使用API​​调用advapi32.dll来管理Windows保存的凭据,以便自动化某些可以使用已保存凭据的Windows应用程序,这些工作正常。

我正在尝试更新我的代码以便始终使用SecureString密码,因为我无需在任何时候与密码中包含的文本进行交互,因此如果我的应用程序永远不会保存密码它应该更安全用纯文本。

我可以将SecureString编组到COM任务分配器内存,以便通过以下方式传递给API调用:

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

但是,当要将该信息读回应用程序时,我找不到将这种非托管字符串编组回SecureString而无需将字符串复制到托管内存中的方法,无论是字符串还是字节数组。

有没有一种安全的方法可以做到这一点,我忽略了?

1 个答案:

答案 0 :(得分:0)

非常感谢 Jeroen Mostert ,因为他的评论导致了这个解决方案,应该尽可能安全。

正如Jeroen所描述的那样,每个字符都被读作SecureString并一次附加到新的0字符。

Task Allocator内存中的非托管字符串为空终止,因此在获取 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); 之前读取字符。非托管二进制字符串的长度为前缀,因此需要稍微修改下面的代码。

public func copy(with zone: NSZone? = nil) -> Any {
     return Swift.type(of:self).init(self)
 }