// the only required parameter is 'machineKeySection'; other parameters are just used for unit testing internal MachineKeyMasterKeyProvider(MachineKeyConfig machineKeySection, string applicationId = null, string applicationName = null, CryptographicKey autogenKeys = null, KeyDerivationFunction keyDerivationFunction = null) { _machineKeyConfig = machineKeySection; _applicationId = applicationId; _applicationName = applicationName; _autogenKeys = autogenKeys; _keyDerivationFunction = keyDerivationFunction; }
// ctor for unit testing internal Purpose(string primaryPurpose, string[] specificPurposes, CryptographicKey derivedEncryptionKey, CryptographicKey derivedValidationKey) { PrimaryPurpose = primaryPurpose; SpecificPurposes = specificPurposes ?? new string[0]; DerivedEncryptionKey = derivedEncryptionKey; DerivedValidationKey = derivedValidationKey; SaveDerivedKeys = (SpecificPurposes.Length == 0); }
private NetFXCryptoService GetNetFXCryptoService(Purpose purpose, CryptoServiceOptions options) { // Extract the encryption and validation keys from the provided Purpose object CryptographicKey encryptionKey = purpose.GetDerivedEncryptionKey(_masterKeyProvider, _keyDerivationFunction); CryptographicKey validationKey = purpose.GetDerivedValidationKey(_masterKeyProvider, _keyDerivationFunction); // and return the ICryptoService // (predictable IV turned on if the caller requested cacheable output) return(new NetFXCryptoService(_cryptoAlgorithmFactory, encryptionKey, validationKey, predictableIV: (options == CryptoServiceOptions.CacheableOutput))); }
public CryptographicKey GetValidationKey() { if (_validationKey == null) { _validationKey = GenerateCryptographicKey( configAttributeName: "validationKey", configAttributeValue: _machineKeyConfig.ValidationKey, autogenKeyOffset: AUTOGEN_VALIDATION_OFFSET, autogenKeyCount: AUTOGEN_VALIDATION_KEYLENGTH, errorResourceString: SR.Invalid_validation_key); } return(_validationKey); }
public CryptographicKey GetEncryptionKey() { if (_encryptionKey == null) { _encryptionKey = GenerateCryptographicKey( configAttributeName: "decryptionKey", configAttributeValue: _machineKeyConfig.DecryptionKey, autogenKeyOffset: AUTOGEN_ENCRYPTION_OFFSET, autogenKeyCount: AUTOGEN_ENCRYPTION_KEYLENGTH, errorResourceString: SR.Invalid_decryption_key); } return(_encryptionKey); }
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)); } }
public NetFXCryptoService(ICryptoAlgorithmFactory cryptoAlgorithmFactory, CryptographicKey encryptionKey, CryptographicKey validationKey, bool predictableIV = false) { _cryptoAlgorithmFactory = cryptoAlgorithmFactory; _encryptionKey = encryptionKey; _validationKey = validationKey; _predictableIV = predictableIV; }
// Generates 'cryptographicKey' from either the raw key material specified in config // or from the auto-generated key found in the system registry, optionally performing // subkey derivation. private CryptographicKey GenerateCryptographicKey(string configAttributeName, string configAttributeValue, int autogenKeyOffset, int autogenKeyCount, string errorResourceString) { byte[] keyMaterial = CryptoUtil.HexToBinary(configAttributeValue); // If <machineKey> contained a valid key, just use it verbatim. if (keyMaterial != null && keyMaterial.Length > 0) { return(new CryptographicKey(keyMaterial)); } // Otherwise, we need to generate it. bool autoGenerate = false; bool isolateApps = false; bool isolateByAppId = false; if (configAttributeValue != null) { foreach (string flag in configAttributeValue.Split(',')) { switch (flag) { case "AutoGenerate": autoGenerate = true; break; case "IsolateApps": isolateApps = true; break; case "IsolateByAppId": isolateByAppId = true; break; default: throw new ConfigurationException(configAttributeName + " is null"); } } } if (!autoGenerate) { throw new ConfigurationException(configAttributeName + " is null"); } // The key should be a subset of the auto-generated key (which is a concatenation of several keys) CryptographicKey keyDerivationKey = AutogenKeys.ExtractBits(autogenKeyOffset, autogenKeyCount); List <string> specificPurposes = new List <string>(); if (isolateApps) { // Use the application name to derive a new cryptographic key AddSpecificPurposeString(specificPurposes, AUTOGEN_KEYDERIVATION_ISOLATEAPPS_SPECIFICPURPOSE, ApplicationName); } if (isolateByAppId) { // Use the application ID to derive a new cryptographic key AddSpecificPurposeString(specificPurposes, AUTOGEN_KEYDERIVATION_ISOLATEBYAPPID_SPECIFICPURPOSE, ApplicationId); } // Don't use the auto-gen key directly; derive a new one based on specified parameters. Purpose purpose = new Purpose(AUTOGEN_KEYDERIVATION_PRIMARYPURPOSE, specificPurposes.ToArray()); return(KeyDerivationFunction(keyDerivationKey, purpose)); }