private static Credential ReadCredential(PrivateCredential credential) { var applicationName = Marshal.PtrToStringUni(credential.TargetName); var userName = Marshal.PtrToStringUni(credential.UserName); string insecureSecret = null; if (credential.CredentialBlob != IntPtr.Zero) { insecureSecret = Marshal.PtrToStringUni(credential.CredentialBlob, (int)credential.CredentialBlobSize / 2); } var secret = SecureStringHelper.GetSecureString(insecureSecret); return(new Credential(credential.Type, applicationName, userName, secret)); }
/// <summary> /// Save user credentials for current application /// </summary> /// <param name="userName">User name</param> /// <param name="secret">User secret</param> /// <param name="credentialPersistence">Persistence type</param> /// <returns>Zero in case of success</returns> public int WriteCredential(string userName, string secret, CredentialPersistence credentialPersistence = CredentialPersistence.LocalMachine) { var byteArray = Encoding.Unicode.GetBytes(secret); if (byteArray.Length > 512) { throw new ArgumentOutOfRangeException(nameof(secret), @"The secret message has exceeded 512 bytes."); } var credential = new PrivateCredential { AttributeCount = 0, Attributes = IntPtr.Zero, Comment = IntPtr.Zero, TargetAlias = IntPtr.Zero, Type = CredentialType.Generic, Persist = (uint)credentialPersistence, CredentialBlobSize = (uint)Encoding.Unicode.GetBytes(secret).Length, TargetName = Marshal.StringToCoTaskMemUni(_applicationName), CredentialBlob = Marshal.StringToCoTaskMemUni(secret), UserName = Marshal.StringToCoTaskMemUni(userName ?? Environment.UserName) }; var written = CredWrite(ref credential, 0); var lastError = Marshal.GetLastWin32Error(); Marshal.FreeCoTaskMem(credential.TargetName); Marshal.FreeCoTaskMem(credential.CredentialBlob); Marshal.FreeCoTaskMem(credential.UserName); if (written) { return(0); } throw new Exception($"CredWrite failed with the error code {lastError}."); }
private static extern bool CredWrite([In] ref PrivateCredential userCredential, [In] uint flags);