How to convert SecureString to System.String?

后端 未结 11 794
孤独总比滥情好
孤独总比滥情好 2020-11-27 10:22

All reservations about unsecuring your SecureString by creating a System.String out of it aside, how can it be done?

How can I convert an ordinary S

11条回答
  •  离开以前
    2020-11-27 11:10

    Final working solution according to sclarke81 solution and John Flaherty fixes is:

        public static class Utils
        {
            /// 
            /// This method creates an empty managed string and pins it so that the garbage collector
            /// cannot move it around and create copies. An unmanaged copy of the the secure string is
            /// then created and copied into the managed string. The action is then called using the
            /// managed string. Both the managed and unmanaged strings are then zeroed to erase their
            /// contents. The managed string is unpinned so that the garbage collector can resume normal
            /// behaviour and the unmanaged string is freed.
            /// 
            public static T UseDecryptedSecureString(this SecureString secureString, Func action)
            {
                int length = secureString.Length;
                IntPtr sourceStringPointer = IntPtr.Zero;
    
                // Create an empty string of the correct size and pin it so that the GC can't move it around.
                string insecureString = new string('\0', length);
                var insecureStringHandler = GCHandle.Alloc(insecureString, GCHandleType.Pinned);
    
                IntPtr insecureStringPointer = insecureStringHandler.AddrOfPinnedObject();
    
                try
                {
                    // Create an unmanaged copy of the secure string.
                    sourceStringPointer = Marshal.SecureStringToBSTR(secureString);
    
                    // Use the pointers to copy from the unmanaged to managed string.
                    for (int i = 0; i < secureString.Length; i++)
                    {
                        short unicodeChar = Marshal.ReadInt16(sourceStringPointer, i * 2);
                        Marshal.WriteInt16(insecureStringPointer, i * 2, unicodeChar);
                    }
    
                    return action(insecureString);
                }
                finally
                {
                    // Zero the managed string so that the string is erased. Then unpin it to allow the
                    // GC to take over.
                    Marshal.Copy(new byte[length * 2], 0, insecureStringPointer, length * 2);
                    insecureStringHandler.Free();
    
                    // Zero and free the unmanaged string.
                    Marshal.ZeroFreeBSTR(sourceStringPointer);
                }
            }
    
            /// 
            /// Allows a decrypted secure string to be used whilst minimising the exposure of the
            /// unencrypted string.
            /// 
            /// The string to decrypt.
            /// 
            /// Func delegate which will receive the decrypted password as a string object
            /// 
            /// Result of Func delegate
            /// 
            /// This method creates an empty managed string and pins it so that the garbage collector
            /// cannot move it around and create copies. An unmanaged copy of the the secure string is
            /// then created and copied into the managed string. The action is then called using the
            /// managed string. Both the managed and unmanaged strings are then zeroed to erase their
            /// contents. The managed string is unpinned so that the garbage collector can resume normal
            /// behaviour and the unmanaged string is freed.
            /// 
            public static void UseDecryptedSecureString(this SecureString secureString, Action action)
            {
                UseDecryptedSecureString(secureString, (s) =>
                {
                    action(s);
                    return 0;
                });
            }
        }
    

提交回复
热议问题