2017-10-17 130 views
0

我試圖將加密密碼保存到Windows憑證管理器,下面的代碼可以正常讀取,並且我可以生成正確加密的字符串,但密碼的加密形式是從未堅持。加密時無法將密碼保存到憑證管理器

爲了完整起見,我需要在客戶端應用程序需要此密碼時加密密碼(Office 2010)。如果我通過Office 2010保存密碼,則可以正確讀取它。

信任結構

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct Credential 
{ 
    public UInt32 flags; 
    public UInt32 type; 
    public string targetName; 
    public string comment; 
    public System.Runtime.InteropServices.ComTypes.FILETIME lastWritten; 
    public UInt32 credentialBlobSize; 
    public IntPtr credentialBlob; 
    public UInt32 persist; 
    public UInt32 attributeCount; 
    public IntPtr credAttribute; 
    public string targetAlias; 
    public string userName; 
} 

閱讀:

IntPtr credPtr; 
if (!Win32.CredRead(target, settings.Type, 0, out credPtr)) 
{ 
    Trace.TraceError("Could not find a credential with the given target name"); 
    return; 
} 

var passwordBytes = new byte[blobSize]; 
Marshal.Copy(blob, passwordBytes, 0, (int)blobSize); 

var decrypted = ProtectedData.Unprotect(passwordBytes, null, DataProtectionScope.CurrentUser); 
return Encoding.Unicode.GetString(decrypted); 

寫:

var bytes = Encoding.Unicode.GetBytes(password); 
var encypted = ProtectedData.Protect(bytes, null, DataProtectionScope.CurrentUser); 

//construct and set all the other properties on Credential... 

credential.credentialBlobSize = (uint)bytes.Length; 
credential.credentialBlob = GetPtrToArray(bytes); 

if (!Win32.CredWrite(ref credential, 0)) 
    throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); 

GetPtrToArray

private static IntPtr GetPtrToArray(byte[] bytes) 
{ 
    var handle = Marshal.AllocHGlobal(bytes.Length); 
    Marshal.Copy(bytes, 0, handle, bytes.Length); 
    return handle; 
} 

件我曾嘗試的事情是:

  1. 更改credentialBlob到字節[],這個失敗,並在累得PtrToStructure CredentialRead期間)之前解密一個編組錯誤
  2. 更改credentialBlob爲字符串,並且使用Unicode.GetBytes( ,這產生該假定是的IntPtr

相信問題是與共享存儲器的字節[],即產生IntPtr的方法與要使用的內容的2字符串。當以後嘗試讀取證書時,blobSizeblob都是0(即,對於斑點的空ptr)。

爲了完整起見,這是從.net 4.6.1代碼庫運行的,我可以存儲未加密的字符串(使用Marshal.StringToCoTaskMemUni(password)),沒有任何問題。

你能幫忙嗎?

+0

什麼是你'type'場? Iirc可以編寫純文本pw或讀取加密字節,具體取決於CRED_TYPE _ ???? 。 –

回答

0

原來我忘記了Credential是一個結構,下面的代碼行在一個單獨的函數中(上面簡化了),因此這些字段永遠不會保存它們的值。

void SetPasswordProperties(Win32.Credential credential) 
{ 
    credential.credentialBlobSize = (uint)bytes.Length; 
    credential.credentialBlob = GetPtrToArray(bytes); 
} 

使用ref參數修復了這個問題,像這樣:

void SetPasswordProperties(ref Win32.Credential credential) 
相關問題