You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@ -0,0 +1,166 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="Purpose.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Security.Cryptography {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
// Represents a purpose that can be passed to a cryptographic routine to control key derivation / ciphertext modification.
|
||||
// This is hardening the crypto routines to prevent playing ciphertext off of components that didn't generate them.
|
||||
//
|
||||
// !! IMPORTANT !!
|
||||
// The built-in purposes do not contain privileged information and are not meant to be treated as secrets. Any external
|
||||
// person can disassemble our code or look directly at our source to see what our Purpose objects are used for.
|
||||
//
|
||||
// PrimaryPurpose: This is a well-known string that identifies the reason for this Purpose. The pattern we use
|
||||
// is that PrimaryPurpose is the name of the consumer, making each consumer's Purpose unique.
|
||||
//
|
||||
// SpecificPurposes: These are extra optional strings that further differentiate Purpose objects that might have the
|
||||
// same PrimaryPurpose. The pattern we use is that if a single consumer has multiple Purposes, he can use
|
||||
// SpecificPurposes to uniquely identify them. The information here is generally not secret (we can put the type of
|
||||
// the currently executing Page here, for example), but it is valid to seed this property with a secret obtained
|
||||
// at runtime (such as a nonce shared between two parties).
|
||||
|
||||
internal sealed class Purpose {
|
||||
|
||||
// predefined purposes
|
||||
public static readonly Purpose AnonymousIdentificationModule_Ticket = new Purpose("AnonymousIdentificationModule.Ticket");
|
||||
public static readonly Purpose AssemblyResourceLoader_WebResourceUrl = new Purpose("AssemblyResourceLoader.WebResourceUrl");
|
||||
public static readonly Purpose FormsAuthentication_Ticket = new Purpose("FormsAuthentication.Ticket");
|
||||
public static readonly Purpose WebForms_Page_PreviousPageID = new Purpose("WebForms.Page.PreviousPageID");
|
||||
public static readonly Purpose RolePrincipal_Ticket = new Purpose("RolePrincipal.Ticket");
|
||||
public static readonly Purpose ScriptResourceHandler_ScriptResourceUrl = new Purpose("ScriptResourceHandler.ScriptResourceUrl");
|
||||
|
||||
// predefined ViewState purposes; they won't be used as-is (they're combined with the page information)
|
||||
public static readonly Purpose WebForms_ClientScriptManager_EventValidation = new Purpose("WebForms.ClientScriptManager.EventValidation");
|
||||
public static readonly Purpose WebForms_DetailsView_KeyTable = new Purpose("WebForms.DetailsView.KeyTable");
|
||||
public static readonly Purpose WebForms_GridView_DataKeys = new Purpose("WebForms.GridView.DataKeys");
|
||||
public static readonly Purpose WebForms_GridView_SortExpression = new Purpose("WebForms.GridView.SortExpression");
|
||||
public static readonly Purpose WebForms_HiddenFieldPageStatePersister_ClientState = new Purpose("WebForms.HiddenFieldPageStatePersister.ClientState");
|
||||
public static readonly Purpose WebForms_ScriptManager_HistoryState = new Purpose("WebForms.ScriptManager.HistoryState");
|
||||
public static readonly Purpose WebForms_SessionPageStatePersister_ClientState = new Purpose("WebForms.SessionPageStatePersister.ClientState");
|
||||
|
||||
// predefined miscellaneoous purposes; they won't be used as-is (they're combined with other specificPurposes)
|
||||
public static readonly Purpose User_MachineKey_Protect = new Purpose("User.MachineKey.Protect"); // used by the MachineKey static class Protect / Unprotect methods
|
||||
public static readonly Purpose User_ObjectStateFormatter_Serialize = new Purpose("User.ObjectStateFormatter.Serialize"); // used by ObjectStateFormatter.Serialize() if called manually
|
||||
|
||||
public readonly string PrimaryPurpose;
|
||||
public readonly string[] SpecificPurposes;
|
||||
|
||||
private byte[] _derivedKeyLabel;
|
||||
private byte[] _derivedKeyContext;
|
||||
|
||||
public Purpose(string primaryPurpose, params string[] specificPurposes)
|
||||
: this(primaryPurpose, specificPurposes, null, null) {
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// The cryptographic keys that were derived from this Purpose.
|
||||
internal CryptographicKey DerivedEncryptionKey { get; private set; }
|
||||
internal CryptographicKey DerivedValidationKey { get; private set; }
|
||||
|
||||
// Whether the derived key should be saved back to this Purpose object by the ICryptoService,
|
||||
// e.g. because this Purpose will be used over and over again. We assume that any built-in
|
||||
// Purpose object that is passed without any specific purposes is intended for repeated use,
|
||||
// hence the ICryptoService will try to cache cryptographic keys as a performance optimization.
|
||||
// If specific purposes have been specified, they were likely generated at runtime, hence it
|
||||
// is not appropriate for the keys to be cached in this instance.
|
||||
internal bool SaveDerivedKeys { get; set; }
|
||||
|
||||
// Returns a new Purpose which is the specified Purpose plus the specified SpecificPurpose.
|
||||
// Leaves the original Purpose unmodified.
|
||||
internal Purpose AppendSpecificPurpose(string specificPurpose) {
|
||||
// Append the specified specificPurpose to the existing list
|
||||
string[] newSpecificPurposes = new string[SpecificPurposes.Length + 1];
|
||||
Array.Copy(SpecificPurposes, newSpecificPurposes, SpecificPurposes.Length);
|
||||
newSpecificPurposes[newSpecificPurposes.Length - 1] = specificPurpose;
|
||||
return new Purpose(PrimaryPurpose, newSpecificPurposes);
|
||||
}
|
||||
|
||||
// Returns a new Purpose which is the specified Purpose plus the specified SpecificPurposes.
|
||||
// Leaves the original Purpose unmodified.
|
||||
internal Purpose AppendSpecificPurposes(IList<string> specificPurposes) {
|
||||
// No specific purposes to add
|
||||
if (specificPurposes == null || specificPurposes.Count == 0) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// Append the specified specificPurposes to the existing list
|
||||
string[] newSpecificPurposes = new string[SpecificPurposes.Length + specificPurposes.Count];
|
||||
Array.Copy(SpecificPurposes, newSpecificPurposes, SpecificPurposes.Length);
|
||||
specificPurposes.CopyTo(newSpecificPurposes, SpecificPurposes.Length);
|
||||
return new Purpose(PrimaryPurpose, newSpecificPurposes);
|
||||
}
|
||||
|
||||
public CryptographicKey GetDerivedEncryptionKey(IMasterKeyProvider masterKeyProvider, KeyDerivationFunction keyDerivationFunction) {
|
||||
// has a key already been stored?
|
||||
CryptographicKey actualDerivedKey = DerivedEncryptionKey;
|
||||
if (actualDerivedKey == null) {
|
||||
CryptographicKey masterKey = masterKeyProvider.GetEncryptionKey();
|
||||
actualDerivedKey = keyDerivationFunction(masterKey, this);
|
||||
|
||||
// only save the key back to storage if this Purpose is configured to do so
|
||||
if (SaveDerivedKeys) {
|
||||
DerivedEncryptionKey = actualDerivedKey;
|
||||
}
|
||||
}
|
||||
|
||||
return actualDerivedKey;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Returns a label and context suitable for passing into the SP800-108 KDF.
|
||||
internal void GetKeyDerivationParameters(out byte[] label, out byte[] context) {
|
||||
// The primary purpose can just be used as the label directly, since ASP.NET
|
||||
// is always in full control of the primary purpose (it's never user-specified).
|
||||
if (_derivedKeyLabel == null) {
|
||||
_derivedKeyLabel = CryptoUtil.SecureUTF8Encoding.GetBytes(PrimaryPurpose);
|
||||
}
|
||||
|
||||
// The specific purposes (which can contain nonce, identity, etc.) are concatenated
|
||||
// together to form the context. The BinaryWriter class prepends each element with
|
||||
// a 7-bit encoded length to guarantee uniqueness.
|
||||
if (_derivedKeyContext == null) {
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
using (BinaryWriter writer = new BinaryWriter(stream, CryptoUtil.SecureUTF8Encoding)) {
|
||||
foreach (string specificPurpose in SpecificPurposes) {
|
||||
writer.Write(specificPurpose);
|
||||
}
|
||||
_derivedKeyContext = stream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
label = _derivedKeyLabel;
|
||||
context = _derivedKeyContext;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user