machineKey的加密、解密与验签算法

你是否对web.config machineKey这样的配置产生过疑惑?

<machineKey validationKey=”21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D7 AD972A119482D15A4127461DB1DC347C1A63AE5F1CCFAACFF1B72A7F0A281B” decryptionKey=”ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F”validation=”SHA1″decryption=”AES”/>

或者你想了解machineKey的加密、解密及验签算法

你将在本文有所收获。


首先附上.NET源码地址:http://referencesource.microsoft.com/

1. machineKey配置的作用

以下是MSDN https://msdn.microsoft.com/zh-cn/library/w8h3skw9的解释

对算法、密钥进行配置,以便将其用于对 Forms 身份验证数据和视图状态数据进行加密、解密和验证,并将其用于进程外会话状态标识。

意思是说WebForm的Form与ViewState的数据都是根据这一配置算法进行加密、解密及验证的。该MSDN文档最新文档只更新到了 .NET Framework 4,引申一点来讲,.NET后续的MVC的Form提交以及OWIN的Cookie、OAuth身份验证都采用的是machineKey配置的算法。

2. machineKey的默认加密/解密算法

查阅.NET命名空间 System.Web.Security.Cryptography下的machineKey加密算法工厂类MachineKeyCryptoAlgorithmFactory代码:

private Func<SymmetricAlgorithm> GetEncryptionAlgorithmFactory()
        {
            return GetGenericAlgorithmFactory<SymmetricAlgorithm>(configAttributeName: "decryption", configAttributeValue: _machineKeySection.GetDecryptionAttributeSkipValidation(), switchStatement: algorithmName =>
            {
                // We suppress CS0618 since some of the algorithms we support are marked with [Obsolete].                    
                // These deprecated algorithms are *not* enabled by default. Developers must opt-in to                    
                // them, so we're secure by default.#pragma warning disable 618                    
                switch (algorithmName)
                {
                    case "AES":
                    case "Auto":
                        // currently "Auto" defaults to AES                            
                        return CryptoAlgorithms.CreateAes;
                    case "DES":
                        return CryptoAlgorithms.CreateDES;
                    case "3DES":
                        return CryptoAlgorithms.CreateTripleDES;
                    default:
                        return null;
                        // unknown#pragma warning restore 618                    
                }
            },
            errorResourceString: SR.Wrong_decryption_enum);
        }

注意到算法名”AES”与”Auto”都返回的是AES加密/解密算法:

case "AES":case "Auto": 
// currently "Auto" defaults to AES   
return CryptoAlgorithms.CreateAes;

而这两行代码

configAttributeName: "decryption",
configAttributeValue:_machineKeySection.GetDecryptionAttributeSkipValidation()

则表示算法名称由machineKey的decryption属性配置决定。
我们再来看一下GetDecryptionAttributeSkipValidation方法是如何获取这一属性值的:

// returns the value in the 'decryption' attribute (or the default value if null) without throwing an exception if the value is malformedinternal 
string GetDecryptionAttributeSkipValidation() 
{    
    return (string)base[_propDecryption] ?? "Auto";
}

(代码位于命名空间System.Web.Configuration MachineKeySection类)

可以看到,优先取base[_propDecryption],若为空,则默认为”Auto”。那么_propDecryption又是什么呢?转到定义即可看到:

private static readonly ConfigurationProperty _propDecryption =            new ConfigurationProperty("decryption", typeof(string), "Auto", StdValidatorsAndConverters.WhiteSpaceTrimStringConverter, StdValidatorsAndConverters.NonEmptyStringValidator, ConfigurationPropertyOptions.None);

可以看到,默认值取的”Auto”,而结合上文的GetEncryptionAlgorithmFactory方法可以看到”Auto”对应的算法为AES,所以machineKey的默认加密/解密算法为AES

3. machineKey默认的验签算法

首先,查看一下获取验前算法工厂方法定义(同样位于命名空间 System.Web.Security.Cryptography下的类MachineKeyCryptoAlgorithmFactory):

        private Func<KeyedHashAlgorithm> GetValidationAlgorithmFactory()
        {
            return GetGenericAlgorithmFactory<KeyedHashAlgorithm>(configAttributeName: "validation", configAttributeValue: _machineKeySection.GetValidationAttributeSkipValidation(), switchStatement: algorithmName =>
            {
                switch (algorithmName)
                {
                    case "SHA1": return CryptoAlgorithms.CreateHMACSHA1;
                    case "HMACSHA256": return CryptoAlgorithms.CreateHMACSHA256;
                    case "HMACSHA384": return CryptoAlgorithms.CreateHMACSHA384;
                    case "HMACSHA512": return CryptoAlgorithms.CreateHMACSHA512;
                    default: return null; // unknown                    
                }
            }, errorResourceString: SR.Wrong_validation_enum_FX45);
        }

可以看到,验签算法取的validation属性:

configAttributeName: “validation”,configAttributeValue: _machineKeySection.GetValidationAttributeSkipValidation(),

而GetValidationAttributeSkipValidation又是这样获取的:

// returns the value in the ‘validation’ attribute (or the default value if null) without throwing an exception if the value is malformedinternal string GetValidationAttributeSkipValidation() { return (string)base[_propValidation] ?? DefaultValidationAlgorithm;}

而_propDecryption的定义如下:

private static readonly ConfigurationProperty _propValidation = new ConfigurationProperty(“validation”, typeof(string), DefaultValidationAlgorithm, StdValidatorsAndConverters.WhiteSpaceTrimStringConverter, StdValidatorsAndConverters.NonEmptyStringValidator, ConfigurationPropertyOptions.None);

可以看到,validation属性值默认取的DefaultValidationAlgorithm,DefaultValidationAlgorithm定义如下:

// If the default validation algorithm changes, be sure to update the _HashSize and _AutoGenValidationKeySize fields also.internal const string DefaultValidationAlgorithm = “HMACSHA256”;

可以看到,默认算法为”HMACSHA256”,所以machineKey的默认验签算法为”HMACSHA256”

发表评论

邮箱地址不会被公开。