因此,.NET框架提供了SecureString类,用于以安全的方式存储字符串.但要阅读信息并使用它,您必须将其返回到标准字符串.请参阅此实现示例.
正如您在使用指针的示例中看到的,我们返回一个未加密的字符串.我们现在如何管理字符串的"不安全"实例?一旦设置了值,最安全的方法是什么?
编辑
这个问题的目的是讨论在使用SecureStrings然后使用这些值时减少潜在攻击的表面区域的方法.关于"重复"链接不是"为什么".
我试图使用CryptUnprotectData读取使用密码保护的CryptProtectData进入SecureString,并用它来连接到数据库.我可以输出正确的密码,但尝试创建新的密码SqlConnection失败后出现以下情况:
System.TypeInitializationException was unhandled
HResult=-2146233036
Message=The type initializer for 'System.Data.SqlClient.SqlConnection' threw an exception.
Source=System.Data
TypeName=System.Data.SqlClient.SqlConnection
StackTrace:
at System.Data.SqlClient.SqlConnection..ctor()
at System.Data.SqlClient.SqlConnection..ctor(String connectionString, SqlCredential credential)
at System.Data.SqlClient.SqlConnection..ctor(String connectionString)
at ProtectedSqlTest.Program.Main() in C:\Git\ProtectedSqlTest\ProtectedSqlTest\Program.cs:line 16
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object …Run Code Online (Sandbox Code Playgroud) 我开发了一个 PowerShell 脚本,它处理某些文件并通过 SFTP 传输它们。为此,只要需要凭据向 SFTP 服务器进行身份验证,它就会使用 SecureString 类型从加密文本文件中读取和解密 SFTP 用户凭据。这是必需的,因为我不允许将凭据作为纯文本存储在文件(或脚本本身)中,否则它将无法通过下一次安全审核。
除了脚本之外,还有一个单独的配置脚本,它必须运行一次以指定 sftp 用户凭据、加密它们并将它们保存到文本文件中。这是该配置脚本的(简化)代码:
Write-Output "Please enter the username of the SFTP user."
$username = Read-Host
Write-Output "Please enter the password of the SFTP user"
$password = Read-Host -AsSecureString
$username | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "$scriptroot\Credentials.dat"
$password | ConvertFrom-SecureString | Out-File -Append "$scriptroot\Credentials.dat"
Run Code Online (Sandbox Code Playgroud)
基本上这两个脚本工作得很好,并且做他们应该做的。但是,无论出于何种原因,一旦我注销然后再次登录到 Windows,解密就会停止工作。
我不明白为什么这会一遍又一遍地停止工作,我不知道该怎么办。有没有人知道一种方法来弄清楚为什么由于我退出系统而解密停止工作?该脚本甚至不在我自己的用户下运行,它作为在完全不同的 AD 用户下运行的计划任务执行。
我还读到 Microsoft 不再建议将 SecureString 用于新项目,但是可以使用的替代方法是什么?我还应该如何安全地将用户凭据存储在文件中,而无需将某种纯文本解密密钥存储在脚本或其他文件中?
我一直觉得SecureString有点奇怪,但我认为我的大多数问题是由于我不明白的安全问题.今天我决定坐下来自学一下,但我已经看到了一个似乎是致命的障碍.
我设想的场景是"用户在文本框中输入密码,密码被哈希并与存储的哈希进行比较".起初我担心文本框包含字符串,但后来我意识到你可以滚动一个使用SecureString作为其存储的自定义文本框.凉.这是"密码被哈希并进行比较......"这一部分给了我麻烦.
我对VB .NET中的问题的第一次破解是天真和错误的:
Dim passwordHandle As IntPtr
Dim insecurePassword As String = Nothing
Try
passwordHandle = Marshal.SecureStringToBSTR(_password)
insecurePassword = Marshal.PtrToStringBSTR(passwordHandle)
Catch ex As Exception
Finally
If passwordHandle <> IntPtr.Zero Then
Marshal.ZeroFreeBSTR(passwordHandle)
End If
End Try
If insecurePassword <> Nothing Then
' Do hash and comparison
End If
Run Code Online (Sandbox Code Playgroud)
这只是将密码填入常规字符串中,并且首先违背了使用SecureString的目的.所以我一直在搜索并找到一篇博文,在C#中很好地解决了这个问题:将字符串制作成BSTR,复制到固定字符串中,然后BSTR和固定字符串在使用后都归零.这似乎是一个更好的主意,因为它最大限度地减少了不安全字符串在内存中的时间.但是,它似乎没有办法在VB .NET中实现这一点.C#正在使用其不安全的代码功能来执行指针操作,但VB .NET无法执行此操作.我看了一下Marhsall.Copy(),但它看起来像是面向数组.我想过尝试将对象的IntPtr变量和BSTR转换为字符串,但这仍然让我使用像String.Replace()这样的方法,它将创建一个新的字符串.
根本不可能从VB .NET做到这一点,还是有什么我想念的?
编辑 我接受AMissico的回答只有轻微的保留.Marshal.ReadByte()方法将从非托管内存中复制一个字节,并在非托管内存中创建一个字节.这使得攻击者很难找到密码的各个字符.我认为这远远低于找到整个字符串的几率,但我引用的(显然已经不存在的)文章中的C#能够使用不安全的代码来避免这种情况.思考过程是使用GCHandle将字符串固定在内存中,然后使用不安全的代码来绕过.NET字符串的不变性.聪明的技巧在VB .NET中似乎是不可能的.我会尝试使用C#代码本身.
我一直在研究使用System.Security.SecureString类在处理它们时将信用卡号保存在内存中.有没有人使用SecureString类来保存信用卡号,或者大多数只使用正常的System.String类?
我有一个方法当前返回从字节数组转换而来的字符串:
public static readonly UnicodeEncoding ByteConverter = new UnicodeEncoding();
public static string Decrypt(string textToDecrypt, string privateKeyXml)
{
if (string.IsNullOrEmpty(textToDecrypt))
{
throw new ArgumentException(
"Cannot decrypt null or blank string"
);
}
if (string.IsNullOrEmpty(privateKeyXml))
{
throw new ArgumentException("Invalid private key XML given");
}
byte[] bytesToDecrypt = Convert.FromBase64String(textToDecrypt);
byte[] decryptedBytes;
using (var rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(privateKeyXml);
decryptedBytes = rsa.Decrypt(bytesToDecrypt, FOAEP);
}
return ByteConverter.GetString(decryptedBytes);
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试更新此方法以返回 a ,但在将from的返回值转换为 时SecureString遇到问题。我尝试了以下方法:RSACryptoServiceProvider.Decryptbyte[]SecureString
var secStr = new SecureString();
foreach (byte …Run Code Online (Sandbox Code Playgroud) 我正在尝试在客户站点使用第三方身份验证Web服务.Web服务是用.Net编写的,并接受SecureString作为密码类型.
AuthResult Login(string username, SecureString passkey)
Run Code Online (Sandbox Code Playgroud)
我的应用程序是用Java编写的,我可以使用Java中的SecureString没有兼容类型:(当我生成一个轴代理时,它生成一个没有SecureString成员的存根,因此我无法进行身份验证调用服务.
public class SecureString implements java.io.Serializable {
public SecureString() {
...
}
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试http://sanguinecomputing.com/a-secure-string-implementation-for-long-term-storage-of-sensitive-data-in-java/但我不是很有希望
任何人都可以帮我解决这个互操作性问题吗?我正在寻找一种方法将类型为secureString的参数从Java应用程序代码发送到.Net服务.
PSScriptAnalyzer 有一个 PSAvoidUsingConvertToSecureStringWithPlainText 警告。这意味着使用以下代码将失败。
$password = [System.Web.Security.Membership]::GeneratePassword(128,0)
$securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$configCredential = New-Object System.Management.Automation.PSCredential ($username,$securePassword)
Run Code Online (Sandbox Code Playgroud)
但是,关于如何在没有 -AsPlainText -Force 选项的情况下将常规字符串转换为安全字符串的指南很少(/无)。(我确实了解常规字符串的安全含义)
我怎样才能安全地实现上述目标/不惹恼 PSScriptAnalyzer(我不想压制消息)
用例是在 c# 中保护内存编程中的字符串。Microsoft 本身不鼓励使用 SecureString 类 ( https://docs.microsoft.com/en-us/dotnet/api/system.security.securestring?view=netframework-4.7.2 )。
我想知道它是否可以作为一个有效的替代方案:
有什么建议吗?
我正在尝试在云形成模板的元数据部分使用 SecureString,但它引发了以下错误:
不支持 SSM 安全参考:[AWS::EC2::Instance/Metadata/AWS::CloudFormation::Init/config/files/~/.ssh/content]
这是我的代码:
Resources:
LinuxEC2Instance:
Type: AWS::EC2::Instance
Metadata:
AWS::CloudFormation::Init:
config:
files:
~/.ssh:
content: !Sub |
'{{resolve:ssm-secure:/credentials/ansible:1}}'
mode: "000644"
owner: "ansible"
group: "ansible"
Run Code Online (Sandbox Code Playgroud)
为什么这不起作用?我希望在 Cloud Formation 模板中使用安全字符串引用吗?
securestring ×10
c# ×3
.net ×2
encryption ×2
powershell ×2
arrays ×1
axis ×1
credentials ×1
credit-card ×1
java ×1
metadata ×1
pinvoke ×1
rsa ×1
ssm ×1
vb.net ×1
wcf ×1
wsdl ×1