public void LoadFromProtectedString(string protectedString, RMSecureString password) { Clear(); if (protectedString.StartsWith("e")) { LoadFromEncryptedString(protectedString, password); } else if (protectedString.StartsWith("p")) { // Trim leading 'p', which is just an indicator to say that this is an encrypted and not a protected string protectedString = protectedString.Substring(1); IntPtr PasswordPtr = IntPtr.Zero; try { // Get the secure password string into a memory buffer PasswordPtr = Marshal.SecureStringToGlobalAllocAnsi(password.GetSecureText()); int PasswordSize = password.Length * sizeof(byte); // Pin the array, copy data in, use it, and then make sure it is clear before unpinning. unsafe { byte[] Decrypted = null; byte[] PasswordBytes = new byte[PasswordSize]; fixed(byte *ptr = PasswordBytes) { try { Marshal.Copy(PasswordPtr, PasswordBytes, 0, PasswordSize); if (PasswordSize == 0) { Decrypted = ProtectedData.Unprotect(Convert.FromBase64String(protectedString), null, DataProtectionScope.CurrentUser); } else { Decrypted = ProtectedData.Unprotect(Convert.FromBase64String(protectedString), PasswordBytes, DataProtectionScope.CurrentUser); } for (int i = 0; i < Decrypted.Length; i++) { if (_SecureStringSupported) { ((SecureString)_SecureString).AppendChar((char)Decrypted[i]); } else { ((StringBuilder)_SecureString).Append((char)Decrypted[i]); } } } finally { // Ensure managed array is cleared if (Decrypted != null) { Array.Clear(Decrypted, 0, Decrypted.Length); } Array.Clear(PasswordBytes, 0, PasswordSize); } } } } finally { // Ensure unmanaged memory is released. if (PasswordPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PasswordPtr); } } } }
/// <summary> /// Encrypt the current SecureString with the ProtectData API, returning the computed value as a base64 string /// </summary> /// <returns>A base64 encoded string of the protected version of the current SecureString</returns> /// <remarks>Based on the code from Sly Gryphon's comment at http://weblogs.asp.net/pglavich/archive/2006/10/29/Secure-TextBox-Updated.aspx </remarks> public string GetProtectedString(RMSecureString password) { string Result = ""; IntPtr PlainTextPtr = IntPtr.Zero; IntPtr PasswordPtr = IntPtr.Zero; try { // Get the secure plaintext string into a memory buffer if (_SecureStringSupported) { PlainTextPtr = Marshal.SecureStringToGlobalAllocAnsi((SecureString)_SecureString); } else { PlainTextPtr = Marshal.StringToHGlobalAnsi(((StringBuilder)_SecureString).ToString()); } int PlainTextSize = this.Length * sizeof(byte); // Get the secure password string into a memory buffer PasswordPtr = Marshal.SecureStringToGlobalAllocAnsi(password.GetSecureText()); int PasswordSize = password.Length * sizeof(byte); // Pin the array, copy data in, use it, and then make sure it is clear before unpinning. unsafe { byte[] PlainTextBytes = new byte[PlainTextSize]; fixed(byte *ptr1 = PlainTextBytes) { byte[] PasswordBytes = new byte[PasswordSize]; fixed(byte *ptr2 = PasswordBytes) { try { Marshal.Copy(PlainTextPtr, PlainTextBytes, 0, PlainTextSize); Marshal.Copy(PasswordPtr, PasswordBytes, 0, PasswordSize); if (PasswordSize == 0) { Result = "p" + Convert.ToBase64String(ProtectedData.Protect(PlainTextBytes, null, DataProtectionScope.CurrentUser)); } else { Result = "p" + Convert.ToBase64String(ProtectedData.Protect(PlainTextBytes, PasswordBytes, DataProtectionScope.CurrentUser)); } } finally { // Ensure managed array is cleared Array.Clear(PlainTextBytes, 0, PlainTextSize); // Ensure managed array is cleared Array.Clear(PasswordBytes, 0, PasswordSize); } } } } } finally { // Ensure unmanaged memory is released. if (PlainTextPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PlainTextPtr); } // Ensure unmanaged memory is released. if (PasswordPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PasswordPtr); } } return(Result); }
public void LoadFromEncryptedString(string encryptedString, RMSecureString password) { Clear(); if (encryptedString.StartsWith("p")) { LoadFromProtectedString(encryptedString, password); } else if (encryptedString.StartsWith("e")) { // Trim leading 'e', which is just an indicator to say that this is an encrypted and not a protected string encryptedString = encryptedString.Substring(1); IntPtr PasswordPtr = IntPtr.Zero; try { // Get the secure password string into a memory buffer PasswordPtr = Marshal.SecureStringToGlobalAllocAnsi(password.GetSecureText()); int PasswordSize = password.Length * sizeof(byte); // Pin the array, copy data in, use it, and then make sure it is clear before unpinning. unsafe { byte[] Decrypted = null; byte[] PasswordBytes = new byte[PasswordSize]; fixed(byte *ptr = PasswordBytes) { try { Marshal.Copy(PasswordPtr, PasswordBytes, 0, PasswordSize); PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(PasswordBytes, Encoding.ASCII.GetBytes("RMSecureString"), "SHA512", 12345); using (RijndaelManaged SymmetricKey = new RijndaelManaged()) { SymmetricKey.Mode = CipherMode.CBC; using (ICryptoTransform Decryptor = SymmetricKey.CreateDecryptor(DerivedPassword.GetBytes(32), DerivedPassword.GetBytes(16))) { using (MemoryStream MemStream = new MemoryStream(Convert.FromBase64String(encryptedString))) { using (CryptoStream CryptoStream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read)) { byte[] DecryptedByte = new byte[1]; int ByteCount = CryptoStream.Read(DecryptedByte, 0, 1); while (ByteCount > 0) { if (_SecureStringSupported) { ((SecureString)_SecureString).AppendChar((char)DecryptedByte[0]); } else { ((StringBuilder)_SecureString).Append((char)DecryptedByte[0]); } ByteCount = CryptoStream.Read(DecryptedByte, 0, 1); } } } } } } finally { // Ensure managed array is cleared if (Decrypted != null) { Array.Clear(Decrypted, 0, Decrypted.Length); } Array.Clear(PasswordBytes, 0, PasswordSize); } } } } finally { // Ensure unmanaged memory is released. if (PasswordPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PasswordPtr); } } } }
private void LoadFromEncryptedStringv2(string encryptedString, RMSecureString password) { Clear(); // encryptedString is in the format e!2!{iterations}!{base64:salt}!{base64:iv}!{base64:encrypted_password}, so split it string[] Pieces = encryptedString.Split('!'); int Iterations = int.Parse(Pieces[2]); byte[] SaltBytes = Convert.FromBase64String(Pieces[3]); byte[] IVBytes = Convert.FromBase64String(Pieces[4]); encryptedString = Pieces[5]; IntPtr PasswordPtr = IntPtr.Zero; try { // Get the secure password string into a memory buffer PasswordPtr = Marshal.SecureStringToGlobalAllocAnsi(password.GetSecureText()); int PasswordSize = password.Length * sizeof(byte); // Pin the array, copy data in, use it, and then make sure it is clear before unpinning. unsafe { byte[] Decrypted = null; byte[] PasswordBytes = new byte[PasswordSize]; fixed(byte *ptr = PasswordBytes) { try { Marshal.Copy(PasswordPtr, PasswordBytes, 0, PasswordSize); var DerivedPassword = new Rfc2898DeriveBytes(PasswordBytes, SaltBytes, Iterations); using (RijndaelManaged SymmetricKey = new RijndaelManaged()) { SymmetricKey.IV = IVBytes; SymmetricKey.Key = DerivedPassword.GetBytes(16); SymmetricKey.Mode = CipherMode.CBC; using (ICryptoTransform Decryptor = SymmetricKey.CreateDecryptor()) { using (MemoryStream MemStream = new MemoryStream(Convert.FromBase64String(encryptedString))) { using (CryptoStream CryptoStream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read)) { byte[] DecryptedByte = new byte[1]; int ByteCount = CryptoStream.Read(DecryptedByte, 0, 1); while (ByteCount > 0) { _SecureString.AppendChar((char)DecryptedByte[0]); ByteCount = CryptoStream.Read(DecryptedByte, 0, 1); } } } } } } finally { // Ensure managed array is cleared if (Decrypted != null) { Array.Clear(Decrypted, 0, Decrypted.Length); } Array.Clear(PasswordBytes, 0, PasswordSize); } } } } finally { // Ensure unmanaged memory is released. if (PasswordPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PasswordPtr); } } }
public string GetEncryptedString(RMSecureString password) { string Result = ""; IntPtr PlainTextPtr = IntPtr.Zero; IntPtr PasswordPtr = IntPtr.Zero; try { // Get the secure plaintext string into a memory buffer if (_SecureStringSupported) { PlainTextPtr = Marshal.SecureStringToGlobalAllocAnsi((SecureString)_SecureString); } else { PlainTextPtr = Marshal.StringToHGlobalAnsi(((StringBuilder)_SecureString).ToString()); } int PlainTextSize = this.Length * sizeof(byte); // Get the secure password string into a memory buffer PasswordPtr = Marshal.SecureStringToGlobalAllocAnsi(password.GetSecureText()); int PasswordSize = password.Length * sizeof(byte); // Pin the array, copy data in, use it, and then make sure it is clear before unpinning. unsafe { byte[] PlainTextBytes = new byte[PlainTextSize]; fixed(byte *ptr1 = PlainTextBytes) { byte[] PasswordBytes = new byte[PasswordSize]; fixed(byte *ptr2 = PasswordBytes) { try { Marshal.Copy(PlainTextPtr, PlainTextBytes, 0, PlainTextSize); Marshal.Copy(PasswordPtr, PasswordBytes, 0, PasswordSize); PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(PasswordBytes, Encoding.ASCII.GetBytes("RMSecureString"), "SHA512", 12345); using (RijndaelManaged SymmetricKey = new RijndaelManaged()) { SymmetricKey.Mode = CipherMode.CBC; using (ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(DerivedPassword.GetBytes(32), DerivedPassword.GetBytes(16))) { using (MemoryStream MemStream = new MemoryStream()) { using (CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write)) { CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length); CryptoStream.FlushFinalBlock(); Result = "e" + Convert.ToBase64String(MemStream.ToArray()); } } } } } finally { // Ensure managed array is cleared Array.Clear(PlainTextBytes, 0, PlainTextSize); // Ensure managed array is cleared Array.Clear(PasswordBytes, 0, PasswordSize); } } } } } finally { // Ensure unmanaged memory is released. if (PlainTextPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PlainTextPtr); } // Ensure unmanaged memory is released. if (PasswordPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PasswordPtr); } } return(Result); }
public string GetEncryptedString(RMSecureString password, int iterations = 32768) { string Result = ""; IntPtr PlainTextPtr = IntPtr.Zero; IntPtr PasswordPtr = IntPtr.Zero; try { // Get the secure plaintext string into a memory buffer PlainTextPtr = Marshal.SecureStringToGlobalAllocAnsi(_SecureString); int PlainTextSize = this.Length * sizeof(byte); // Get the secure password string into a memory buffer PasswordPtr = Marshal.SecureStringToGlobalAllocAnsi(password.GetSecureText()); int PasswordSize = password.Length * sizeof(byte); // Pin the array, copy data in, use it, and then make sure it is clear before unpinning. unsafe { byte[] PlainTextBytes = new byte[PlainTextSize]; fixed(byte *ptr1 = PlainTextBytes) { byte[] PasswordBytes = new byte[PasswordSize]; fixed(byte *ptr2 = PasswordBytes) { try { Marshal.Copy(PlainTextPtr, PlainTextBytes, 0, PlainTextSize); Marshal.Copy(PasswordPtr, PasswordBytes, 0, PasswordSize); // Get random bytes for salt var RNG = new RNGCryptoServiceProvider(); byte[] SaltBytes = new byte[16]; RNG.GetBytes(SaltBytes); // PBKDF2 key stretching var DerivedPassword = new Rfc2898DeriveBytes(PasswordBytes, SaltBytes, iterations); // Encryption with 128bit AES (using 192 or 256 bit isn't a good idea because Rfc2898DeriveBytes uses SHA-1, a 160 bit algorithm, // so it's not recommended to take out more than 160 bits (increases time required to hash, but not time required to verify // a hash, which means a defender does extra work but an attacker doesn't have to...Google it for reasons) using (RijndaelManaged SymmetricKey = new RijndaelManaged()) { SymmetricKey.GenerateIV(); SymmetricKey.Key = DerivedPassword.GetBytes(16); SymmetricKey.Mode = CipherMode.CBC; using (ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor()) { using (MemoryStream MemStream = new MemoryStream()) { using (CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write)) { CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length); CryptoStream.FlushFinalBlock(); Result = $"e!2!{iterations}!{Convert.ToBase64String(SaltBytes)}!{Convert.ToBase64String(SymmetricKey.IV)}!{Convert.ToBase64String(MemStream.ToArray())}"; } } } } } finally { // Ensure managed array is cleared Array.Clear(PlainTextBytes, 0, PlainTextSize); // Ensure managed array is cleared Array.Clear(PasswordBytes, 0, PasswordSize); } } } } } finally { // Ensure unmanaged memory is released. if (PlainTextPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PlainTextPtr); } // Ensure unmanaged memory is released. if (PasswordPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PasswordPtr); } } return(Result); }
public void LoadFromProtectedString(string protectedString, RMSecureString password) { Clear(); if (protectedString.StartsWith("e")) { LoadFromEncryptedString(protectedString, password); } else if (protectedString.StartsWith("p")) { // Trim leading 'p', which is just an indicator to say that this is an encrypted and not a protected string protectedString = protectedString.Substring(1); IntPtr PasswordPtr = IntPtr.Zero; try { // Get the secure password string into a memory buffer PasswordPtr = Marshal.SecureStringToGlobalAllocAnsi(password.GetSecureText()); int PasswordSize = password.Length * sizeof(byte); // Pin the array, copy data in, use it, and then make sure it is clear before unpinning. unsafe { byte[] Decrypted = null; byte[] PasswordBytes = new byte[PasswordSize]; fixed (byte* ptr = PasswordBytes) { try { Marshal.Copy(PasswordPtr, PasswordBytes, 0, PasswordSize); if (PasswordSize == 0) { Decrypted = ProtectedData.Unprotect(Convert.FromBase64String(protectedString), null, DataProtectionScope.CurrentUser); } else { Decrypted = ProtectedData.Unprotect(Convert.FromBase64String(protectedString), PasswordBytes, DataProtectionScope.CurrentUser); } for (int i = 0; i < Decrypted.Length; i++) { if (_SecureStringSupported) { ((SecureString)_SecureString).AppendChar((char)Decrypted[i]); } else { ((StringBuilder)_SecureString).Append((char)Decrypted[i]); } } } finally { // Ensure managed array is cleared if (Decrypted != null) Array.Clear(Decrypted, 0, Decrypted.Length); Array.Clear(PasswordBytes, 0, PasswordSize); } } } } finally { // Ensure unmanaged memory is released. if (PasswordPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PasswordPtr); } } } }
public void LoadFromEncryptedString(string encryptedString, RMSecureString password) { Clear(); if (encryptedString.StartsWith("p")) { LoadFromProtectedString(encryptedString, password); } else if (encryptedString.StartsWith("e")) { // Trim leading 'e', which is just an indicator to say that this is an encrypted and not a protected string encryptedString = encryptedString.Substring(1); IntPtr PasswordPtr = IntPtr.Zero; try { // Get the secure password string into a memory buffer PasswordPtr = Marshal.SecureStringToGlobalAllocAnsi(password.GetSecureText()); int PasswordSize = password.Length * sizeof(byte); // Pin the array, copy data in, use it, and then make sure it is clear before unpinning. unsafe { byte[] Decrypted = null; byte[] PasswordBytes = new byte[PasswordSize]; fixed (byte* ptr = PasswordBytes) { try { Marshal.Copy(PasswordPtr, PasswordBytes, 0, PasswordSize); PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(PasswordBytes, Encoding.ASCII.GetBytes("RMSecureString"), "SHA512", 12345); using (RijndaelManaged SymmetricKey = new RijndaelManaged()) { SymmetricKey.Mode = CipherMode.CBC; using (ICryptoTransform Decryptor = SymmetricKey.CreateDecryptor(DerivedPassword.GetBytes(32), DerivedPassword.GetBytes(16))) { using (MemoryStream MemStream = new MemoryStream(Convert.FromBase64String(encryptedString))) { using (CryptoStream CryptoStream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read)) { byte[] DecryptedByte = new byte[1]; int ByteCount = CryptoStream.Read(DecryptedByte, 0, 1); while (ByteCount > 0) { if (_SecureStringSupported) { ((SecureString)_SecureString).AppendChar((char)DecryptedByte[0]); } else { ((StringBuilder)_SecureString).Append((char)DecryptedByte[0]); } ByteCount = CryptoStream.Read(DecryptedByte, 0, 1); } } } } } } finally { // Ensure managed array is cleared if (Decrypted != null) Array.Clear(Decrypted, 0, Decrypted.Length); Array.Clear(PasswordBytes, 0, PasswordSize); } } } } finally { // Ensure unmanaged memory is released. if (PasswordPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PasswordPtr); } } } }
/// <summary> /// Encrypt the current SecureString with the ProtectData API, returning the computed value as a base64 string /// </summary> /// <returns>A base64 encoded string of the protected version of the current SecureString</returns> /// <remarks>Based on the code from Sly Gryphon's comment at http://weblogs.asp.net/pglavich/archive/2006/10/29/Secure-TextBox-Updated.aspx </remarks> public string GetProtectedString(RMSecureString password) { string Result = ""; IntPtr PlainTextPtr = IntPtr.Zero; IntPtr PasswordPtr = IntPtr.Zero; try { // Get the secure plaintext string into a memory buffer if (_SecureStringSupported) { PlainTextPtr = Marshal.SecureStringToGlobalAllocAnsi((SecureString)_SecureString); } else { PlainTextPtr = Marshal.StringToHGlobalAnsi(((StringBuilder)_SecureString).ToString()); } int PlainTextSize = this.Length * sizeof(byte); // Get the secure password string into a memory buffer PasswordPtr = Marshal.SecureStringToGlobalAllocAnsi(password.GetSecureText()); int PasswordSize = password.Length * sizeof(byte); // Pin the array, copy data in, use it, and then make sure it is clear before unpinning. unsafe { byte[] PlainTextBytes = new byte[PlainTextSize]; fixed (byte* ptr1 = PlainTextBytes) { byte[] PasswordBytes = new byte[PasswordSize]; fixed (byte* ptr2 = PasswordBytes) { try { Marshal.Copy(PlainTextPtr, PlainTextBytes, 0, PlainTextSize); Marshal.Copy(PasswordPtr, PasswordBytes, 0, PasswordSize); if (PasswordSize == 0) { Result = "p" + Convert.ToBase64String(ProtectedData.Protect(PlainTextBytes, null, DataProtectionScope.CurrentUser)); } else { Result = "p" + Convert.ToBase64String(ProtectedData.Protect(PlainTextBytes, PasswordBytes, DataProtectionScope.CurrentUser)); } } finally { // Ensure managed array is cleared Array.Clear(PlainTextBytes, 0, PlainTextSize); // Ensure managed array is cleared Array.Clear(PasswordBytes, 0, PasswordSize); } } } } } finally { // Ensure unmanaged memory is released. if (PlainTextPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PlainTextPtr); } // Ensure unmanaged memory is released. if (PasswordPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PasswordPtr); } } return Result; }
public string GetEncryptedString(RMSecureString password) { string Result = ""; IntPtr PlainTextPtr = IntPtr.Zero; IntPtr PasswordPtr = IntPtr.Zero; try { // Get the secure plaintext string into a memory buffer if (_SecureStringSupported) { PlainTextPtr = Marshal.SecureStringToGlobalAllocAnsi((SecureString)_SecureString); } else { PlainTextPtr = Marshal.StringToHGlobalAnsi(((StringBuilder)_SecureString).ToString()); } int PlainTextSize = this.Length * sizeof(byte); // Get the secure password string into a memory buffer PasswordPtr = Marshal.SecureStringToGlobalAllocAnsi(password.GetSecureText()); int PasswordSize = password.Length * sizeof(byte); // Pin the array, copy data in, use it, and then make sure it is clear before unpinning. unsafe { byte[] PlainTextBytes = new byte[PlainTextSize]; fixed (byte* ptr1 = PlainTextBytes) { byte[] PasswordBytes = new byte[PasswordSize]; fixed (byte* ptr2 = PasswordBytes) { try { Marshal.Copy(PlainTextPtr, PlainTextBytes, 0, PlainTextSize); Marshal.Copy(PasswordPtr, PasswordBytes, 0, PasswordSize); PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(PasswordBytes, Encoding.ASCII.GetBytes("RMSecureString"), "SHA512", 12345); using (RijndaelManaged SymmetricKey = new RijndaelManaged()) { SymmetricKey.Mode = CipherMode.CBC; using (ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(DerivedPassword.GetBytes(32), DerivedPassword.GetBytes(16))) { using (MemoryStream MemStream = new MemoryStream()) { using (CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write)) { CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length); CryptoStream.FlushFinalBlock(); Result = "e" + Convert.ToBase64String(MemStream.ToArray()); } } } } } finally { // Ensure managed array is cleared Array.Clear(PlainTextBytes, 0, PlainTextSize); // Ensure managed array is cleared Array.Clear(PasswordBytes, 0, PasswordSize); } } } } } finally { // Ensure unmanaged memory is released. if (PlainTextPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PlainTextPtr); } // Ensure unmanaged memory is released. if (PasswordPtr != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(PasswordPtr); } } return Result; }