title: securely convert encrypted standard string to securestring
body: <p>I have an encrypted standard string, created in powershell via "convertfrom-securestring" and saved to a file.  Later, I read this encrypted string with a C# app (under same user ID and on same machine).  I want to convert this encrypted string into a securestring object.  In powershell, one can do this using "convertto-securestring".  How can one do this <b>securely</b> in c#?</p>
  
  <p>I am aware of this answer (<a href="https://stackoverflow.com/questions/13633826/how-can-i-use-convertto-securestring">How can I use ConvertTo-SecureString</a>), <b>but it assumes the encrypted string has been created with a known key</b>.  This is different from the case where the encrypted string has been created with no key (and is thus tied to the userID and machine on which it was constructed.)</p>
  
  <p>Note also that in the comments in the above-referenced question, documentation from Microsoft was quoted that indicated the Windows Data Protection API (DPAPI) is used in the case where no key is provided. This article (<a href="https://msdn.microsoft.com/en-us/library/ms229741(v=vs.110).aspx" rel="nofollow noreferrer">https://msdn.microsoft.com/en-us/library/ms229741(v=vs.110).aspx</a>) shows how to use the DPAPI, but unfortunately using it in the manner specified in the Microsoft article would result again result in the string being in clear-text in a string object (over which we have no control, vis-a-vis disposal), and so using it in the manner indicated would be insecure.</p>
  
  <p>Actually, this is effectively a combination of this (<a href="https://stackoverflow.com/questions/30859038/how-to-decrypt-a-string-in-c-sharp-which-is-encrypted-via-powershell">How to decrypt a string in C# which is encrypted via PowerShell</a>) and the question in <a href="https://stackoverflow.com/questions/13633826/how-can-i-use-convertto-securestring">How can I use ConvertTo-SecureString</a>.</p>
  
  <p>For the record, this code works, but I am not sure what the issues may be with storing the decrypted string in byte and char arrays, even though I do clobber it as quickly as possible:</p>
  
  <pre><code>public static System.Security.SecureString MakeSecurityString(string pwd)
  {
      int lngth = pwd.Length / 2;
      byte[] encrypted = new byte[lngth];
      for (int i = 0; i &lt; lngth; ++i)
      {
          encrypted[i] = byte.Parse(pwd.Substring(2 * i, 2), System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture);
      }
  
      byte[] decrypted = System.Security.Cryptography.ProtectedData.Unprotect(encrypted, (byte[])null, System.Security.Cryptography.DataProtectionScope.CurrentUser);
      var chars = System.Text.UnicodeEncoding.Unicode.GetChars(decrypted);
      for(int i=0; i&lt;decrypted.Length; ++i)
      {
          decrypted[i]=0;
      }
      var secureString = new System.Security.SecureString();
      for (int i = 0; i &lt; chars.Length; ++i)
      {
          secureString.AppendChar(chars[i]);
          chars[i] = '\0';
      }
  
      return secureString;
  }
  </code></pre>
  
  <p>I think the above code is secure, except for the brief moment that the password is in clear text in the byte-array <code>decrypted</code> and then the char-array <code>chars</code>, though we zero these out as quickly as possible so that at least the password cannot hang around in memory after exiting the routine.  We call <code>secureString.AppendChar</code> multiple times, which as  Oguz Ozgu pointed out below, means <code>secureString</code> must be decrypting and then re-encrypting the string internally - one would presume this is done safely.  Can someone comment on security issues of the above code?</p>
  
  <p>Edit: note that the code below would avoid the multiple calls to <code>secureString.AppendChar</code>, but it must be run as "unsafe":</p>
  
  <pre><code>        SecureString secureString;
          fixed (char* pChars = chars)
          {
              secureString = new SecureString(pChars, chars.Length);
          }
          for (int i = 0; i &lt; chars.Length; ++i)
          {
              chars[i] = '\0';
          }
          return secureString;
  </code></pre>
  
  <p>Note also that the link in Indigo's comment below makes it clear that this is ONLY SECURE IN A .NET FRAMEWORK ON WINDOWS.</p>