I have a scenario where a C#.NET program must be supplied a secret that is derived from a Username/Password combination. This secret is non-reversible (think of it like a hash) but has the requirement that the secret can only be created with a .NET library.
The problem here is that there is the program that actually contains the username/password is different than the program that needs the secret and is not a .NET program, so the information has to be sent through some IPC.
It is worth noting that the program the has the username/password keeps them in memory for as long as the user is logged in. I realize that this itself is very insecure, but it isn't something that I am able to change.
I am looking for a way for the C#.NET program to get the secret as securely as possible.
Two options that I came up with are to use a Named Pipe to transfer the username/password directly from one application to the other, or to use COM components so the first application can send the username/password to the COM component, which can compute the secret and write it to a location that can be read later by the second application.
for the Named Pipe method I would expect the credential requesting component to look something like the following
using (var a = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous, TokenImpersonationLevel.Impersonation))
{
var requestString = new StreamString(a);
var credString = new StreamString(a);
await a.ConnectAsync();
a.ReadMode = PipeTransmissionMode.Message;
requestString.WriteString(JsonConvert.SerializeObject(new CredentialRequest()));
var cred = JsonConvert.DeserializeObject<Credential>(credString.ReadString());
var secret = await CreateSecret(cred.Username, cred.Password);
a.Close();
}
Based on that, the side opposite side of the pipe should be pretty obvious.
For the COM solution I am thinking that I would create an object that has the following method
public void ComputeAndStoreSecret(string username, string password)
{
var secret = CreateSecret(username, password);
using (var applicationStorageFileForUser = IsolatedStorageFile.GetUserStoreForAssembly())
{
using (var applicationStorageStreamForUser = new IsolatedStorageFileStream("secret_store.txt", FileMode.Create, applicationStorageFileForUser))
{
using (StreamWriter sw = new StreamWriter(applicationStorageStreamForUser))
{
sw.WriteLine(secret);
}
}
}
}
There would also be a COM component that reads from that storage location and returns the secret.
I am basically looking for any insight as to why I would want to use one of these techniques over the other or maybe consider any other options (RPC, Mailbox, etc.)
Some things that I have discovered/considered
- Named Pipe solution is vulnerable to Pipe Squatting
- Named Pipes require username/password to leave process space of the first application
- Storage Location of secret using COM solution can be seen and edited by everything
- Isolated File Storage in COM solution is not intended to be used for secret information
I realize that neither of these solutions are secure, but I am looking for a solution that at least doesn't make it drastically more insecure.