Réponse courte
pourquoi ne puis-je pas simplement dire:
SecureString password = new SecureString("password");
Parce que maintenant vous avez password
en mémoire; sans moyen de l'effacer - ce qui est exactement le but de SecureString .
Longue réponse
La raison pour laquelle SecureString existe est que vous ne pouvez pas utiliser ZeroMemory pour effacer les données sensibles lorsque vous en avez terminé. Il existe pour résoudre un problème qui existe à cause du CLR.
Dans une application native standard , vous appelleriez SecureZeroMemory
:
Remplit un bloc de mémoire avec des zéros.
Remarque : SecureZeroMemory est identique à ZeroMemory
, sauf que le compilateur ne l'optimisera pas.
Le problème est que vous ne pouvez pas appeler ZeroMemory
ou à l' SecureZeroMemory
intérieur de .NET. Et dans .NET, les chaînes sont immuables; vous ne pouvez même pas écraser le contenu de la chaîne comme vous pouvez le faire dans d'autres langues:
//Wipe out the password
for (int i=0; i<password.Length; i++)
password[i] = \0;
Alors que peux-tu faire? Comment pouvons-nous offrir la possibilité dans .NET d'effacer un mot de passe ou un numéro de carte de crédit de la mémoire lorsque nous en avons terminé?
La seule façon de le faire serait de placer la chaîne dans un bloc de mémoire natif , où vous pouvez ensuite appeler ZeroMemory
. Un objet mémoire natif tel que:
- un BSTR
- un HGLOBAL
- Mémoire non gérée CoTaskMem
SecureString redonne la capacité perdue
Dans .NET, les chaînes ne peuvent pas être effacées lorsque vous en avez terminé avec elles:
- ils sont immuables; vous ne pouvez pas écraser leur contenu
- tu ne peux pas
Dispose
d'eux
- leur nettoyage est à la merci du ramasse-miettes
SecureString existe comme un moyen de transmettre la sécurité des chaînes et de garantir leur nettoyage lorsque vous en avez besoin.
Vous avez posé la question:
pourquoi ne puis-je pas simplement dire:
SecureString password = new SecureString("password");
Parce que maintenant vous avez password
en mémoire; sans moyen de l'essuyer. Il est bloqué là jusqu'à ce que le CLR décide de réutiliser cette mémoire. Vous nous avez remis là où nous avons commencé; une application en cours d'exécution avec un mot de passe dont nous ne pouvons pas nous débarrasser et où un vidage de la mémoire (ou Process Monitor) peut voir le mot de passe.
SecureString utilise l'API de protection des données pour stocker la chaîne chiffrée en mémoire; de cette façon, la chaîne n'existera pas dans les fichiers d'échange, les vidages sur incident ou même dans la fenêtre des variables locales avec un collègue qui regarde votre devrait.
Comment lire le mot de passe?
Puis se pose la question: comment interagir avec la chaîne? Vous ne voulez absolument pas d'une méthode comme:
String connectionString = secureConnectionString.ToString()
car maintenant vous êtes de retour là où vous avez commencé - un mot de passe dont vous ne pouvez pas vous débarrasser. Vous voulez forcer les développeurs à gérer correctement la chaîne sensible - afin qu'elle puisse être effacée de la mémoire.
C'est pourquoi .NET fournit trois fonctions d'assistance pratiques pour rassembler un SecureString dans une mémoire non managée:
Vous convertissez la chaîne en un objet blob de mémoire non géré, vous la gérez et l'effacez à nouveau.
Certaines API acceptent SecureStrings . Par exemple dans ADO.net 4.5, SqlConnection.Credential prend un ensemble SqlCredential :
SqlCredential cred = new SqlCredential(userid, password); //password is SecureString
SqlConnection conn = new SqlConnection(connectionString);
conn.Credential = cred;
conn.Open();
Vous pouvez également modifier le mot de passe dans une chaîne de connexion:
SqlConnection.ChangePassword(connectionString, cred, newPassword);
Et il y a beaucoup d'endroits dans .NET où ils continuent d'accepter une chaîne simple à des fins de compatibilité, puis se retournent rapidement et la placent dans un SecureString.
Comment mettre du texte dans SecureString?
Cela laisse toujours le problème:
Comment puis-je obtenir un mot de passe dans SecureString en premier lieu?
C'est le défi, mais le but est de vous faire réfléchir à la sécurité.
Parfois, la fonctionnalité est déjà fournie pour vous. Par exemple, le contrôle WPF PasswordBox peut vous renvoyer directement le mot de passe saisi sous forme de SecureString :
Obtient le mot de passe actuellement détenu par PasswordBox en tant que SecureString .
Ceci est utile car partout où vous aviez l'habitude de transmettre une chaîne brute, vous avez maintenant le système de types se plaignant que SecureString est incompatible avec String. Vous voulez aller le plus longtemps possible avant de devoir reconvertir votre SecureString en chaîne régulière.
La conversion d'un SecureString est assez simple:
- SecureStringToBSTR
- PtrToStringBSTR
un péché:
private static string CreateString(SecureString secureString)
{
IntPtr intPtr = IntPtr.Zero;
if (secureString == null || secureString.Length == 0)
{
return string.Empty;
}
string result;
try
{
intPtr = Marshal.SecureStringToBSTR(secureString);
result = Marshal.PtrToStringBSTR(intPtr);
}
finally
{
if (intPtr != IntPtr.Zero)
{
Marshal.ZeroFreeBSTR(intPtr);
}
}
return result;
}
Ils ne veulent vraiment pas que vous le fassiez.
Mais comment obtenir une chaîne dans un SecureString? Eh bien, ce que vous devez faire est d'arrêter d'avoir un mot de passe dans une chaîne en premier lieu. Vous aviez besoin de l'avoir dans autre chose . Même un Char[]
tableau serait utile.
C'est à ce moment que vous pouvez ajouter chaque caractère et effacer le texte brut lorsque vous avez terminé:
for (int i=0; i < PasswordArray.Length; i++)
{
password.AppendChar(PasswordArray[i]);
PasswordArray[i] = (Char)0;
}
Vous avez besoin de votre mot de passe stocké dans une mémoire que vous pouvez effacer. Chargez-le dans SecureString à partir de là.
tl; dr: SecureString existe pour fournir l'équivalent de ZeroMemory .
Certaines personnes ne voient pas l'intérêt d' effacer le mot de passe de l'utilisateur de la mémoire lorsqu'un appareil est verrouillé , ou d' effacer les frappes de la mémoire après leur authentification . Ces personnes n'utilisent pas SecureString.
SecureString
de nouveau développement: github.com/dotnet/platform-compat/blob/master/docs/DE0001.md