-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Background and motivation
In advance, sorry for my english.
SecureString is right now (and has been) a sorta of not useful API because -in a developer point of view- any management of it requires to use Marshal API in order to make something with it.
It is useful in logging scenarios (avoiding to expose the password) and reducing the time the password is in plaintext. And avoids some attacker discover the password by some dump file or something like that.
As I say, the class is "useful in some scenarios, but not "easy" to use when developing the software (as commented if you need to work with the data inside the SecureString you need to be concerned about Marshaling and free the data, etc...)
It will be useful to include some fast-to-use and "not-error-prone" APIs in an extension way, using the current cryptography namespace classes
API Proposal
namespace System.Collections.Generic
{
//names are dumb placeholders
public class SecureStringExtensions
{
public static byte[] Digest(this SecureString secureString, HashAlgorithm hashAlgorithm); //"I don't care about the password, I only need the hash...
public static byte[] Encrypt(this SecureString secureString, SymmetricAlgorithm symmetricAlgorithm); //"I'd like to be capable of know the password if I require it."
public static byte[] GetPbkdf2Key(this SecureString secureString, byte[] salt, int iterations, HashAlgorithmName hashAlgorithm, int keyLength); // "Let's do it right, I don't need the password, but a key derived from it"
}
public class SecureStringHelpers
{
public static SecureString DecryptToSecureString(byte[] encryptedData, SymmetricAlgorithm symmetricAlgorithm); //The counter-part of the encrypt method.
}
}API Usage
var passwordBoxSecureString = ....;
//I get my SecureString from... WPF PasswordBox, for example
//And i want to store it or make something with it, but I don't need the password as is.
byte[] randomSalt = ..., //I get some random bytes.
int keyByteLength = 32;
var derivedKey = passwordBoxSecureString.GetPbkdf2Key(randomSalt, 20000, HashAlgorithmName.SHA512, keyByteLength);
//now I can use the derivedKey array and discard the securestring "safely".
//other scenario
var hashAlg = SHA512.Create();
var hashedPass = passwordBoxSecureString.Digest(hashAlg);
//I can use hashedPass now and discard the securestring.Alternative Designs
Instead of use SymmetricAlgorithm/HashAlgorithm, we can use directly ICryptoTransform interface, but this can make the user can put as argument a decryptor instead of an encryptor.
I'm not sure but... can Asymmetric cryptography coexist too?
Risks
At the end, you are working with the bytes of a hashed password, and this can have caveats.
Furthermore I'm sure there are so many hard points I can't see (I'm not a cryptography expert)