souser
souser

Reputation: 33

Store password securely and retrieve it later

Use case: To run installer in unattended mode.

How: To achieve this I am using Process.Start and passing it ProcessStartInfo as below:

 var processStartInfo = new ProcessStartInfo
 {
       FileName = installerPath,
       Arguments = commandLineArguments
 };

Issue: One of the parameters in the command line arguments is username and password. The username and password are provided by an API. What I am doing is saving encrypted password in database and then return it through the API. Then on the receiving end decrypting it. I know its not a best practice to save encrypted passwords (instead should save hash of the password) but pls. see the use case mentioned above.

I would like to know if saving encrypted password (and decrypting it later) is the best way to go here or is there a better way.

Upvotes: 0

Views: 1062

Answers (1)

C1rdec
C1rdec

Reputation: 1687

For encryption I'm using this class :

/// <summary>
/// Encrypt Password with local key
/// </summary>
public class SecureIt
{
    #region Declaration

    static byte[] entropy = System.Text.Encoding.Unicode.GetBytes("Salt Is Not A Password");

    #endregion

    #region Methods

    public static string EncryptString(System.Security.SecureString input)
    {
        byte[] encryptedData = System.Security.Cryptography.ProtectedData.Protect(
            System.Text.Encoding.Unicode.GetBytes(ToInsecureString(input)),
            entropy,
            System.Security.Cryptography.DataProtectionScope.CurrentUser);
        return Convert.ToBase64String(encryptedData);
    }

    public static SecureString DecryptString(string encryptedData)
    {
        try
        {
            byte[] decryptedData = System.Security.Cryptography.ProtectedData.Unprotect(
                Convert.FromBase64String(encryptedData),
                entropy,
                System.Security.Cryptography.DataProtectionScope.CurrentUser);
            return ToSecureString(System.Text.Encoding.Unicode.GetString(decryptedData));
        }
        catch
        {
            return new SecureString();
        }
    }

    public static SecureString ToSecureString(string input)
    {
        SecureString secure = new SecureString();
        foreach (char c in input)
        {
            secure.AppendChar(c);
        }

        secure.MakeReadOnly();
        return secure;
    }

    public static string ToInsecureString(SecureString input)
    {
        string returnValue = string.Empty;
        IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
        try
        {
            returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
        }
        finally
        {
            System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
        }

        return returnValue;
    }

    #endregion
}

The encryption is done with a the Local Machine key so only the same machine can Decrypt the password

Convert Secure string to InSecure:

SecureIt.ToInsecureString(SecureIt.DecryptString(this._password));

Convert InSecure String to Secure:

SecureIt.EncryptString(SecureIt.ToSecureString(connection.Password));

Upvotes: 1

Related Questions