Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / IdentityModel / System / IdentityModel / SignedXml.cs / 1 / SignedXml.cs
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------
namespace System.IdentityModel
{
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IdentityModel.Tokens;
using System.IdentityModel.Selectors;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
sealed class SignedXml : ISignatureValueSecurityElement
{
internal const string DefaultPrefix = XmlSignatureStrings.Prefix;
SecurityTokenSerializer tokenSerializer;
readonly Signature signature;
TransformFactory transformFactory;
DictionaryManager dictionaryManager;
public SignedXml(DictionaryManager dictionaryManager, SecurityTokenSerializer tokenSerializer)
: this(new StandardSignedInfo(dictionaryManager), dictionaryManager, tokenSerializer)
{
}
internal SignedXml(SignedInfo signedInfo, DictionaryManager dictionaryManager, SecurityTokenSerializer tokenSerializer)
{
if (signedInfo == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("signedInfo"));
}
if (dictionaryManager == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("dictionaryManager");
}
if (tokenSerializer == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenSerializer");
}
this.transformFactory = StandardTransformFactory.Instance;
this.tokenSerializer = tokenSerializer;
this.signature = new Signature(this, signedInfo);
this.dictionaryManager = dictionaryManager;
}
public bool HasId
{
get { return true; }
}
public string Id
{
get { return this.signature.Id; }
set { this.signature.Id = value; }
}
public SecurityTokenSerializer SecurityTokenSerializer
{
get { return this.tokenSerializer; }
}
public Signature Signature
{
get { return this.signature; }
}
public TransformFactory TransformFactory
{
get { return this.transformFactory; }
set { this.transformFactory = value; }
}
void ComputeSignature(HashAlgorithm hash, AsymmetricSignatureFormatter formatter)
{
this.Signature.SignedInfo.ComputeReferenceDigests();
this.Signature.SignedInfo.ComputeHash(hash);
byte[] signature = formatter.CreateSignature(hash);
this.Signature.SetSignatureValue(signature);
}
void ComputeSignature(KeyedHashAlgorithm hash)
{
this.Signature.SignedInfo.ComputeReferenceDigests();
this.Signature.SignedInfo.ComputeHash(hash);
byte[] signature = hash.Hash;
this.Signature.SetSignatureValue(signature);
}
public void ComputeSignature(SecurityKey signingKey)
{
string signatureMethod = this.Signature.SignedInfo.SignatureMethod;
SymmetricSecurityKey symmetricKey = signingKey as SymmetricSecurityKey;
if (symmetricKey != null)
{
using (KeyedHashAlgorithm algorithm = symmetricKey.GetKeyedHashAlgorithm(signatureMethod))
{
if (algorithm == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
SR.GetString(SR.UnableToCreateKeyedHashAlgorithm, symmetricKey, signatureMethod)));
}
ComputeSignature(algorithm);
}
}
else
{
AsymmetricSecurityKey asymmetricKey = signingKey as AsymmetricSecurityKey;
if (asymmetricKey == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
SR.GetString(SR.UnknownICryptoType, signingKey)));
}
using (HashAlgorithm hash = asymmetricKey.GetHashAlgorithmForSignature(signatureMethod))
{
if (hash == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
SR.GetString(SR.UnableToCreateHashAlgorithmFromAsymmetricCrypto, signatureMethod, asymmetricKey)));
}
AsymmetricSignatureFormatter formatter = asymmetricKey.GetSignatureFormatter(signatureMethod);
if (formatter == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
SR.GetString(SR.UnableToCreateSignatureFormatterFromAsymmetricCrypto, signatureMethod, asymmetricKey)));
}
ComputeSignature(hash, formatter);
}
}
}
public void CompleteSignatureVerification()
{
this.Signature.SignedInfo.EnsureAllReferencesVerified();
}
public void EnsureDigestValidity(string id, object resolvedXmlSource)
{
this.Signature.SignedInfo.EnsureDigestValidity(id, resolvedXmlSource);
}
public byte[] GetSignatureValue()
{
return this.Signature.GetSignatureBytes();
}
public void ReadFrom(XmlReader reader)
{
ReadFrom(XmlDictionaryReader.CreateDictionaryReader(reader));
}
public void ReadFrom(XmlDictionaryReader reader)
{
this.signature.ReadFrom(reader, this.dictionaryManager);
}
void VerifySignature(KeyedHashAlgorithm hash)
{
this.Signature.SignedInfo.ComputeHash(hash);
if (!CryptoHelper.IsEqual(hash.Hash, GetSignatureValue()))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.GetString(SR.SignatureVerificationFailed)));
}
}
void VerifySignature(HashAlgorithm hash, AsymmetricSignatureDeformatter deformatter)
{
this.Signature.SignedInfo.ComputeHash(hash);
if (!deformatter.VerifySignature(hash, GetSignatureValue()))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.GetString(SR.SignatureVerificationFailed)));
}
}
public void StartSignatureVerification(SecurityKey verificationKey)
{
string signatureMethod = this.Signature.SignedInfo.SignatureMethod;
SymmetricSecurityKey symmetricKey = verificationKey as SymmetricSecurityKey;
if (symmetricKey != null)
{
using (KeyedHashAlgorithm hash = symmetricKey.GetKeyedHashAlgorithm(signatureMethod))
{
if (hash == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(
SR.GetString(SR.UnableToCreateKeyedHashAlgorithmFromSymmetricCrypto, signatureMethod, symmetricKey)));
}
VerifySignature(hash);
}
}
else
{
AsymmetricSecurityKey asymmetricKey = verificationKey as AsymmetricSecurityKey;
if (asymmetricKey == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnknownICryptoType, verificationKey)));
}
using (HashAlgorithm hash = asymmetricKey.GetHashAlgorithmForSignature(signatureMethod))
{
if (hash == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(
SR.GetString(SR.UnableToCreateHashAlgorithmFromAsymmetricCrypto, signatureMethod, asymmetricKey)));
}
AsymmetricSignatureDeformatter deformatter = asymmetricKey.GetSignatureDeformatter(signatureMethod);
if (deformatter == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(
SR.GetString(SR.UnableToCreateSignatureDeformatterFromAsymmetricCrypto, signatureMethod, asymmetricKey)));
}
VerifySignature(hash, deformatter);
}
}
}
public void WriteTo(XmlDictionaryWriter writer)
{
this.WriteTo(writer, this.dictionaryManager);
}
public void WriteTo(XmlDictionaryWriter writer, DictionaryManager dictionaryManager)
{
this.signature.WriteTo(writer, dictionaryManager);
}
}
sealed class Signature
{
SignedXml signedXml;
string id;
SecurityKeyIdentifier keyIdentifier;
string prefix = SignedXml.DefaultPrefix;
readonly SignatureValueElement signatureValueElement = new SignatureValueElement();
readonly SignedInfo signedInfo;
public Signature(SignedXml signedXml, SignedInfo signedInfo)
{
this.signedXml = signedXml;
this.signedInfo = signedInfo;
}
public string Id
{
get { return this.id; }
set { this.id = value; }
}
public SecurityKeyIdentifier KeyIdentifier
{
get { return this.keyIdentifier; }
set { this.keyIdentifier = value; }
}
public SignedInfo SignedInfo
{
get { return this.signedInfo; }
}
public ISignatureValueSecurityElement SignatureValue
{
get { return this.signatureValueElement; }
}
public byte[] GetSignatureBytes()
{
return this.signatureValueElement.Value;
}
public void ReadFrom(XmlDictionaryReader reader, DictionaryManager dictionaryManager)
{
reader.MoveToStartElement(dictionaryManager.XmlSignatureDictionary.Signature, dictionaryManager.XmlSignatureDictionary.Namespace);
this.prefix = reader.Prefix;
this.Id = reader.GetAttribute(dictionaryManager.UtilityDictionary.IdAttribute, null);
reader.Read();
this.signedInfo.ReadFrom(reader, signedXml.TransformFactory, dictionaryManager);
this.signatureValueElement.ReadFrom(reader, dictionaryManager);
if (signedXml.SecurityTokenSerializer.CanReadKeyIdentifier(reader))
{
this.keyIdentifier = signedXml.SecurityTokenSerializer.ReadKeyIdentifier(reader);
}
reader.ReadEndElement(); // Signature
}
public void SetSignatureValue(byte[] signatureValue)
{
this.signatureValueElement.Value = signatureValue;
}
public void WriteTo(XmlDictionaryWriter writer, DictionaryManager dictionaryManager)
{
writer.WriteStartElement(this.prefix, dictionaryManager.XmlSignatureDictionary.Signature, dictionaryManager.XmlSignatureDictionary.Namespace);
if (this.id != null)
{
writer.WriteAttributeString(dictionaryManager.UtilityDictionary.IdAttribute, null, this.id);
}
this.signedInfo.WriteTo(writer, dictionaryManager);
this.signatureValueElement.WriteTo(writer, dictionaryManager);
if (this.keyIdentifier != null)
{
this.signedXml.SecurityTokenSerializer.WriteKeyIdentifier(writer, this.keyIdentifier);
}
writer.WriteEndElement(); // Signature
}
sealed class SignatureValueElement : ISignatureValueSecurityElement
{
string id;
string prefix = SignedXml.DefaultPrefix;
byte[] signatureValue;
string signatureText;
public bool HasId
{
get { return true; }
}
public string Id
{
get { return this.id; }
set { this.id = value; }
}
internal byte[] Value
{
get { return this.signatureValue; }
set
{
this.signatureValue = value;
this.signatureText = null;
}
}
public void ReadFrom(XmlDictionaryReader reader, DictionaryManager dictionaryManager)
{
reader.MoveToStartElement(dictionaryManager.XmlSignatureDictionary.SignatureValue, dictionaryManager.XmlSignatureDictionary.Namespace);
this.prefix = reader.Prefix;
this.Id = reader.GetAttribute(UtilityStrings.IdAttribute, null);
reader.Read();
this.signatureText = reader.ReadString();
this.signatureValue = System.Convert.FromBase64String(signatureText.Trim());
reader.ReadEndElement(); // SignatureValue
}
public void WriteTo(XmlDictionaryWriter writer, DictionaryManager dictionaryManager)
{
writer.WriteStartElement(this.prefix, dictionaryManager.XmlSignatureDictionary.SignatureValue, dictionaryManager.XmlSignatureDictionary.Namespace);
if (this.id != null)
{
writer.WriteAttributeString(dictionaryManager.UtilityDictionary.IdAttribute, null, this.id);
}
if (this.signatureText != null)
{
writer.WriteString(this.signatureText);
}
else
{
writer.WriteBase64(this.signatureValue, 0, this.signatureValue.Length);
}
writer.WriteEndElement(); // SignatureValue
}
byte[] ISignatureValueSecurityElement.GetSignatureValue()
{
return this.Value;
}
}
}
internal interface ISignatureReaderProvider
{
XmlDictionaryReader GetReader(object callbackContext);
}
abstract class SignedInfo : ISecurityElement
{
readonly ExclusiveCanonicalizationTransform canonicalizationMethodElement = new ExclusiveCanonicalizationTransform(true);
string id;
ElementWithAlgorithmAttribute signatureMethodElement;
SignatureResourcePool resourcePool;
DictionaryManager dictionaryManager;
MemoryStream canonicalStream;
ISignatureReaderProvider readerProvider;
object signatureReaderProviderCallbackContext;
bool sendSide = true;
protected SignedInfo(DictionaryManager dictionaryManager)
{
if (dictionaryManager == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("dictionaryManager");
this.signatureMethodElement = new ElementWithAlgorithmAttribute(dictionaryManager.XmlSignatureDictionary.SignatureMethod);
this.dictionaryManager = dictionaryManager;
}
protected DictionaryManager DictionaryManager
{
get { return this.dictionaryManager; }
}
protected MemoryStream CanonicalStream
{
get { return this.canonicalStream; }
set { this.canonicalStream = value; }
}
protected bool SendSide
{
get { return this.sendSide; }
set { this.sendSide = value; }
}
public ISignatureReaderProvider ReaderProvider
{
get { return this.readerProvider; }
set { this.readerProvider = value; }
}
public object SignatureReaderProviderCallbackContext
{
get { return this.signatureReaderProviderCallbackContext; }
set { this.signatureReaderProviderCallbackContext = value; }
}
public string CanonicalizationMethod
{
get { return this.canonicalizationMethodElement.Algorithm; }
set
{
if (value != this.canonicalizationMethodElement.Algorithm)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnsupportedTransformAlgorithm)));
}
}
}
public XmlDictionaryString CanonicalizationMethodDictionaryString
{
set
{
if (value != null && value.Value != this.canonicalizationMethodElement.Algorithm)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnsupportedTransformAlgorithm)));
}
}
}
public bool HasId
{
get { return true; }
}
public string Id
{
get { return this.id; }
set { this.id = value; }
}
public abstract int ReferenceCount
{
get;
}
public string SignatureMethod
{
get { return this.signatureMethodElement.Algorithm; }
set { this.signatureMethodElement.Algorithm = value; }
}
public XmlDictionaryString SignatureMethodDictionaryString
{
get { return this.signatureMethodElement.AlgorithmDictionaryString; }
set { this.signatureMethodElement.AlgorithmDictionaryString = value; }
}
public SignatureResourcePool ResourcePool
{
get
{
if (this.resourcePool == null)
{
this.resourcePool = new SignatureResourcePool();
}
return this.resourcePool;
}
set
{
this.resourcePool = value;
}
}
public void ComputeHash(HashAlgorithm algorithm)
{
if (this.CanonicalizationMethod != SecurityAlgorithms.ExclusiveC14n)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.GetString(SR.UnsupportedTransformAlgorithm)));
}
HashStream hashStream = this.ResourcePool.TakeHashStream(algorithm);
ComputeHash(hashStream);
hashStream.FlushHash();
}
protected virtual void ComputeHash(HashStream hashStream)
{
if (this.sendSide)
{
XmlDictionaryWriter utf8Writer = this.ResourcePool.TakeUtf8Writer();
utf8Writer.StartCanonicalization(hashStream, false, null);
WriteTo(utf8Writer, this.dictionaryManager);
utf8Writer.EndCanonicalization();
}
else if (this.canonicalStream != null)
{
this.canonicalStream.WriteTo(hashStream);
}
else
{
if (this.readerProvider == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.GetString(SR.InclusiveNamespacePrefixRequiresSignatureReader)));
XmlDictionaryReader signatureReader = this.readerProvider.GetReader(this.signatureReaderProviderCallbackContext);
DiagnosticUtility.DebugAssert(signatureReader != null, "Require a Signature reader to validate signature.");
if (!signatureReader.CanCanonicalize)
{
MemoryStream stream = new MemoryStream();
XmlDictionaryWriter bufferingWriter = XmlDictionaryWriter.CreateBinaryWriter(stream, this.DictionaryManager.ParentDictionary);
string[] inclusivePrefix = GetInclusivePrefixes();
if (inclusivePrefix != null)
{
bufferingWriter.WriteStartElement("a");
for (int i = 0; i < inclusivePrefix.Length; ++i)
{
string ns = GetNamespaceForInclusivePrefix(inclusivePrefix[i]);
if (ns != null)
{
bufferingWriter.WriteXmlnsAttribute(inclusivePrefix[i], ns);
}
}
}
signatureReader.MoveToContent();
bufferingWriter.WriteNode(signatureReader, false);
if (inclusivePrefix != null)
bufferingWriter.WriteEndElement();
bufferingWriter.Flush();
byte[] buffer = stream.ToArray();
int bufferLength = (int)stream.Length;
bufferingWriter.Close();
signatureReader.Close();
// Create a reader around the buffering Stream.
signatureReader = XmlDictionaryReader.CreateBinaryReader(buffer, 0, bufferLength, this.DictionaryManager.ParentDictionary, XmlDictionaryReaderQuotas.Max);
if (inclusivePrefix != null)
signatureReader.ReadStartElement("a");
}
signatureReader.ReadStartElement(dictionaryManager.XmlSignatureDictionary.Signature, dictionaryManager.XmlSignatureDictionary.Namespace);
signatureReader.MoveToStartElement(dictionaryManager.XmlSignatureDictionary.SignedInfo, dictionaryManager.XmlSignatureDictionary.Namespace);
signatureReader.StartCanonicalization(hashStream, false, GetInclusivePrefixes());
signatureReader.Skip();
signatureReader.EndCanonicalization();
signatureReader.Close();
}
}
public abstract void ComputeReferenceDigests();
protected string[] GetInclusivePrefixes()
{
return this.canonicalizationMethodElement.GetInclusivePrefixes();
}
protected virtual string GetNamespaceForInclusivePrefix(string prefix)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
}
public abstract void EnsureAllReferencesVerified();
public void EnsureDigestValidity(string id, object resolvedXmlSource)
{
if (!EnsureDigestValidityIfIdMatches(id, resolvedXmlSource))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(
SR.GetString(SR.RequiredTargetNotSigned, id)));
}
}
public abstract bool EnsureDigestValidityIfIdMatches(string id, object resolvedXmlSource);
public virtual bool HasUnverifiedReference(string id)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
}
protected void ReadCanonicalizationMethod(XmlDictionaryReader reader, DictionaryManager dictionaryManager)
{
this.canonicalizationMethodElement.ReadFrom(reader, dictionaryManager);
}
public abstract void ReadFrom(XmlDictionaryReader reader, TransformFactory transformFactory, DictionaryManager dictionaryManager);
protected void ReadSignatureMethod(XmlDictionaryReader reader, DictionaryManager dictionaryManager)
{
this.signatureMethodElement.ReadFrom(reader, dictionaryManager);
}
protected void WriteCanonicalizationMethod(XmlDictionaryWriter writer, DictionaryManager dictionaryManager)
{
this.canonicalizationMethodElement.WriteTo(writer, dictionaryManager);
}
protected void WriteSignatureMethod(XmlDictionaryWriter writer, DictionaryManager dictionaryManager)
{
this.signatureMethodElement.WriteTo(writer, dictionaryManager);
}
public abstract void WriteTo(XmlDictionaryWriter writer, DictionaryManager dictionaryManager);
}
// whitespace preservation convention: ws1 immediately inside open tag; ws2 immediately after end tag.
sealed class StandardSignedInfo : SignedInfo
{
string prefix = SignedXml.DefaultPrefix;
List references;
Dictionary context;
public StandardSignedInfo(DictionaryManager dictionaryManager)
: base(dictionaryManager)
{
this.references = new List();
}
public override int ReferenceCount
{
get { return this.references.Count; }
}
public Reference this[int index]
{
get { return this.references[index]; }
}
public void AddReference(Reference reference)
{
reference.ResourcePool = this.ResourcePool;
this.references.Add(reference);
}
public override void EnsureAllReferencesVerified()
{
for (int i = 0; i < this.references.Count; i++)
{
if (!this.references[i].Verified)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new CryptographicException(SR.GetString(SR.UnableToResolveReferenceUriForSignature, this.references[i].Uri)));
}
}
}
public override bool EnsureDigestValidityIfIdMatches(string id, object resolvedXmlSource)
{
for (int i = 0; i < this.references.Count; i++)
{
if (this.references[i].EnsureDigestValidityIfIdMatches(id, resolvedXmlSource))
{
return true;
}
}
return false;
}
public override bool HasUnverifiedReference(string id)
{
for (int i = 0; i < this.references.Count; i++)
{
if (!this.references[i].Verified && this.references[i].ExtractReferredId() == id)
{
return true;
}
}
return false;
}
public override void ComputeReferenceDigests()
{
if (this.references.Count == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.GetString(SR.AtLeastOneReferenceRequired)));
}
for (int i = 0; i < this.references.Count; i++)
{
this.references[i].ComputeAndSetDigest();
}
}
public override void ReadFrom(XmlDictionaryReader reader, TransformFactory transformFactory, DictionaryManager dictionaryManager)
{
this.SendSide = false;
if (reader.CanCanonicalize)
{
this.CanonicalStream = new MemoryStream();
reader.StartCanonicalization(this.CanonicalStream, false, null);
}
reader.MoveToStartElement(dictionaryManager.XmlSignatureDictionary.SignedInfo, dictionaryManager.XmlSignatureDictionary.Namespace);
this.prefix = reader.Prefix;
this.Id = reader.GetAttribute(dictionaryManager.UtilityDictionary.IdAttribute, null);
reader.Read();
ReadCanonicalizationMethod(reader, dictionaryManager);
ReadSignatureMethod(reader, dictionaryManager);
while (reader.IsStartElement(dictionaryManager.XmlSignatureDictionary.Reference, dictionaryManager.XmlSignatureDictionary.Namespace))
{
Reference reference = new Reference(dictionaryManager);
reference.ReadFrom(reader, transformFactory, dictionaryManager);
AddReference(reference);
}
reader.ReadEndElement(); // SignedInfo
if (reader.CanCanonicalize)
reader.EndCanonicalization();
string[] inclusivePrefixes = GetInclusivePrefixes();
if (inclusivePrefixes != null)
{
// Clear the canonicalized stream. We cannot use this while inclusive prefixes are
// specified.
this.CanonicalStream = null;
this.context = new Dictionary(inclusivePrefixes.Length);
for (int i = 0; i < inclusivePrefixes.Length; i++)
{
this.context.Add(inclusivePrefixes[i], reader.LookupNamespace(inclusivePrefixes[i]));
}
}
}
public override void WriteTo(XmlDictionaryWriter writer, DictionaryManager dictionaryManager)
{
writer.WriteStartElement(this.prefix, dictionaryManager.XmlSignatureDictionary.SignedInfo, dictionaryManager.XmlSignatureDictionary.Namespace);
if (this.Id != null)
{
writer.WriteAttributeString(dictionaryManager.UtilityDictionary.IdAttribute, null, this.Id);
}
WriteCanonicalizationMethod(writer, dictionaryManager);
WriteSignatureMethod(writer, dictionaryManager);
for (int i = 0; i < this.references.Count; i++)
{
this.references[i].WriteTo(writer, dictionaryManager);
}
writer.WriteEndElement(); // SignedInfo
}
protected override string GetNamespaceForInclusivePrefix(string prefix)
{
if (this.context == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException());
if (prefix == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("prefix");
return context[prefix];
}
}
sealed class Reference
{
ElementWithAlgorithmAttribute digestMethodElement;
DigestValueElement digestValueElement = new DigestValueElement();
string id;
string prefix = SignedXml.DefaultPrefix;
object resolvedXmlSource;
readonly TransformChain transformChain = new TransformChain();
string type;
string uri;
SignatureResourcePool resourcePool;
bool verified;
string referredId;
DictionaryManager dictionaryManager;
public Reference(DictionaryManager dictionaryManager)
: this(dictionaryManager, null)
{
}
public Reference(DictionaryManager dictionaryManager, string uri)
: this(dictionaryManager, uri, null)
{
}
public Reference(DictionaryManager dictionaryManager, string uri, object resolvedXmlSource)
{
if (dictionaryManager == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("dictionaryManager");
this.dictionaryManager = dictionaryManager;
this.digestMethodElement = new ElementWithAlgorithmAttribute(dictionaryManager.XmlSignatureDictionary.DigestMethod);
this.uri = uri;
this.resolvedXmlSource = resolvedXmlSource;
}
public string DigestMethod
{
get { return this.digestMethodElement.Algorithm; }
set { this.digestMethodElement.Algorithm = value; }
}
public XmlDictionaryString DigestMethodDictionaryString
{
get { return this.digestMethodElement.AlgorithmDictionaryString; }
set { this.digestMethodElement.AlgorithmDictionaryString = value; }
}
public string Id
{
get { return this.id; }
set { this.id = value; }
}
public SignatureResourcePool ResourcePool
{
get { return this.resourcePool; }
set { this.resourcePool = value; }
}
public TransformChain TransformChain
{
get { return this.transformChain; }
}
public int TransformCount
{
get { return this.transformChain.TransformCount; }
}
public string Type
{
get { return this.type; }
set { this.type = value; }
}
public string Uri
{
get { return this.uri; }
set { this.uri = value; }
}
public bool Verified
{
get { return this.verified; }
}
public void AddTransform(Transform transform)
{
this.transformChain.Add(transform);
}
public void EnsureDigestValidity(string id, byte[] computedDigest)
{
if (!EnsureDigestValidityIfIdMatches(id, computedDigest))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(
SR.GetString(SR.RequiredTargetNotSigned, id)));
}
}
public void EnsureDigestValidity(string id, object resolvedXmlSource)
{
if (!EnsureDigestValidityIfIdMatches(id, resolvedXmlSource))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(
SR.GetString(SR.RequiredTargetNotSigned, id)));
}
}
public bool EnsureDigestValidityIfIdMatches(string id, byte[] computedDigest)
{
if (this.verified || id != ExtractReferredId())
{
return false;
}
if (!CryptoHelper.IsEqual(computedDigest, GetDigestValue()))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new CryptographicException(SR.GetString(SR.DigestVerificationFailedForReference, this.uri)));
}
this.verified = true;
return true;
}
public bool EnsureDigestValidityIfIdMatches(string id, object resolvedXmlSource)
{
if (this.verified || id != ExtractReferredId())
{
return false;
}
this.resolvedXmlSource = resolvedXmlSource;
if (!CheckDigest())
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new CryptographicException(SR.GetString(SR.DigestVerificationFailedForReference, this.uri)));
}
this.verified = true;
return true;
}
public string ExtractReferredId()
{
if (this.referredId == null)
{
if (this.uri == null || this.uri.Length < 2 || this.uri[0] != '#')
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new CryptographicException(SR.GetString(SR.UnableToResolveReferenceUriForSignature, this.uri)));
}
this.referredId = this.uri.Substring(1);
}
return this.referredId;
}
public bool CheckDigest()
{
byte[] computedDigest = ComputeDigest();
bool result = CryptoHelper.IsEqual(computedDigest, GetDigestValue());
#if LOG_DIGESTS
Console.WriteLine(">>> Checking digest for reference '{0}', result {1}", uri, result);
Console.WriteLine(" Computed digest {0}", Convert.ToBase64String(computedDigest));
Console.WriteLine(" Received digest {0}", Convert.ToBase64String(GetDigestValue()));
#endif
return result;
}
public void ComputeAndSetDigest()
{
this.digestValueElement.Value = ComputeDigest();
}
public byte[] ComputeDigest()
{
if (this.transformChain.TransformCount == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.EmptyTransformChainNotSupported)));
}
if (this.resolvedXmlSource == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(
SR.GetString(SR.UnableToResolveReferenceUriForSignature, this.uri)));
}
return this.transformChain.TransformToDigest(this.resolvedXmlSource, this.ResourcePool, this.DigestMethod, this.dictionaryManager);
}
public byte[] GetDigestValue()
{
return this.digestValueElement.Value;
}
public void ReadFrom(XmlDictionaryReader reader, TransformFactory transformFactory, DictionaryManager dictionaryManager)
{
reader.MoveToStartElement(dictionaryManager.XmlSignatureDictionary.Reference, dictionaryManager.XmlSignatureDictionary.Namespace);
this.prefix = reader.Prefix;
this.Id = reader.GetAttribute(UtilityStrings.IdAttribute, null);
this.Uri = reader.GetAttribute(dictionaryManager.XmlSignatureDictionary.URI, null);
this.Type = reader.GetAttribute(dictionaryManager.XmlSignatureDictionary.Type, null);
reader.Read();
if (reader.IsStartElement(dictionaryManager.XmlSignatureDictionary.Transforms, dictionaryManager.XmlSignatureDictionary.Namespace))
{
this.transformChain.ReadFrom(reader, transformFactory, dictionaryManager);
}
this.digestMethodElement.ReadFrom(reader, dictionaryManager);
this.digestValueElement.ReadFrom(reader, dictionaryManager);
reader.MoveToContent();
reader.ReadEndElement(); // Reference
}
public void SetResolvedXmlSource(object resolvedXmlSource)
{
this.resolvedXmlSource = resolvedXmlSource;
}
public void WriteTo(XmlDictionaryWriter writer, DictionaryManager dictionaryManager)
{
writer.WriteStartElement(this.prefix, dictionaryManager.XmlSignatureDictionary.Reference, dictionaryManager.XmlSignatureDictionary.Namespace);
if (this.id != null)
{
writer.WriteAttributeString(dictionaryManager.UtilityDictionary.IdAttribute, null, this.id);
}
if (this.uri != null)
{
writer.WriteAttributeString(dictionaryManager.XmlSignatureDictionary.URI, null, this.uri);
}
if (this.type != null)
{
writer.WriteAttributeString(dictionaryManager.XmlSignatureDictionary.Type, null, this.type);
}
if (this.transformChain.TransformCount > 0)
{
this.transformChain.WriteTo(writer, dictionaryManager);
}
this.digestMethodElement.WriteTo(writer, dictionaryManager);
this.digestValueElement.WriteTo(writer, dictionaryManager);
writer.WriteEndElement(); // Reference
}
struct DigestValueElement
{
byte[] digestValue;
string digestText;
string prefix;
internal byte[] Value
{
get { return this.digestValue; }
set
{
this.digestValue = value;
this.digestText = null;
}
}
public void ReadFrom(XmlDictionaryReader reader, DictionaryManager dictionaryManager)
{
reader.MoveToStartElement(dictionaryManager.XmlSignatureDictionary.DigestValue, dictionaryManager.XmlSignatureDictionary.Namespace);
this.prefix = reader.Prefix;
reader.Read();
reader.MoveToContent();
this.digestText = reader.ReadString();
this.digestValue = System.Convert.FromBase64String(digestText.Trim());
reader.MoveToContent();
reader.ReadEndElement(); // DigestValue
}
public void WriteTo(XmlDictionaryWriter writer, DictionaryManager dictionaryManager)
{
writer.WriteStartElement(this.prefix ?? XmlSignatureStrings.Prefix, dictionaryManager.XmlSignatureDictionary.DigestValue, dictionaryManager.XmlSignatureDictionary.Namespace);
if (this.digestText != null)
{
writer.WriteString(this.digestText);
}
else
{
writer.WriteBase64(this.digestValue, 0, this.digestValue.Length);
}
writer.WriteEndElement(); // DigestValue
}
}
}
sealed class TransformChain
{
string prefix = SignedXml.DefaultPrefix;
MostlySingletonList transforms;
public TransformChain()
{
}
public int TransformCount
{
get { return this.transforms.Count; }
}
public Transform this[int index]
{
get
{
return this.transforms[index];
}
}
public bool NeedsInclusiveContext
{
get
{
for (int i = 0; i < this.TransformCount; i++)
{
if (this[i].NeedsInclusiveContext)
{
return true;
}
}
return false;
}
}
public void Add(Transform transform)
{
this.transforms.Add(transform);
}
public void ReadFrom(XmlDictionaryReader reader, TransformFactory transformFactory, DictionaryManager dictionaryManager)
{
reader.MoveToStartElement(dictionaryManager.XmlSignatureDictionary.Transforms, dictionaryManager.XmlSignatureDictionary.Namespace);
this.prefix = reader.Prefix;
reader.Read();
while (reader.IsStartElement(dictionaryManager.XmlSignatureDictionary.Transform, dictionaryManager.XmlSignatureDictionary.Namespace))
{
string transformAlgorithmUri = reader.GetAttribute(dictionaryManager.XmlSignatureDictionary.Algorithm, null);
Transform transform = transformFactory.CreateTransform(transformAlgorithmUri);
transform.ReadFrom(reader, dictionaryManager);
Add(transform);
}
reader.MoveToContent();
reader.ReadEndElement(); // Transforms
if (this.TransformCount == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.GetString(SR.AtLeastOneTransformRequired)));
}
}
public byte[] TransformToDigest(object data, SignatureResourcePool resourcePool, string digestMethod, DictionaryManager dictionaryManager)
{
DiagnosticUtility.DebugAssert(TransformCount > 0, "");
for (int i = 0; i < this.TransformCount - 1; i++)
{
data = this[i].Process(data, resourcePool, dictionaryManager);
}
return this[this.TransformCount - 1].ProcessAndDigest(data, resourcePool, digestMethod, dictionaryManager);
}
public void WriteTo(XmlDictionaryWriter writer, DictionaryManager dictionaryManager)
{
writer.WriteStartElement(this.prefix, dictionaryManager.XmlSignatureDictionary.Transforms, dictionaryManager.XmlSignatureDictionary.Namespace);
for (int i = 0; i < this.TransformCount; i++)
{
this[i].WriteTo(writer, dictionaryManager);
}
writer.WriteEndElement(); // Transforms
}
}
struct ElementWithAlgorithmAttribute
{
readonly XmlDictionaryString elementName;
string algorithm;
XmlDictionaryString algorithmDictionaryString;
string prefix;
public ElementWithAlgorithmAttribute(XmlDictionaryString elementName)
{
if (elementName == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("elementName"));
}
this.elementName = elementName;
this.algorithm = null;
this.algorithmDictionaryString = null;
this.prefix = SignedXml.DefaultPrefix;
}
public string Algorithm
{
get { return this.algorithm; }
set { this.algorithm = value; }
}
public XmlDictionaryString AlgorithmDictionaryString
{
get { return this.algorithmDictionaryString; }
set { this.algorithmDictionaryString = value; }
}
public void ReadFrom(XmlDictionaryReader reader, DictionaryManager dictionaryManager)
{
reader.MoveToStartElement(this.elementName, dictionaryManager.XmlSignatureDictionary.Namespace);
this.prefix = reader.Prefix;
bool isEmptyElement = reader.IsEmptyElement;
this.algorithm = reader.GetAttribute(dictionaryManager.XmlSignatureDictionary.Algorithm, null);
if (this.algorithm == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(
SR.GetString(SR.RequiredAttributeMissing, dictionaryManager.XmlSignatureDictionary.Algorithm, this.elementName)));
}
reader.Read();
reader.MoveToContent();
if (!isEmptyElement)
{
reader.MoveToContent();
reader.ReadEndElement();
}
}
public void WriteTo(XmlDictionaryWriter writer, DictionaryManager dictionaryManager)
{
writer.WriteStartElement(this.prefix, this.elementName, dictionaryManager.XmlSignatureDictionary.Namespace);
writer.WriteStartAttribute(dictionaryManager.XmlSignatureDictionary.Algorithm, null);
if (this.algorithmDictionaryString != null)
{
writer.WriteString(this.algorithmDictionaryString);
}
else
{
writer.WriteString(this.algorithm);
}
writer.WriteEndAttribute();
writer.WriteEndElement();
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DataListItem.cs
- CatalogPartCollection.cs
- PropertyChangedEventArgs.cs
- BinHexDecoder.cs
- HandoffBehavior.cs
- InvalidPrinterException.cs
- DesignColumnCollection.cs
- MimeMultiPart.cs
- PrimitiveSchema.cs
- URLMembershipCondition.cs
- ParamArrayAttribute.cs
- ZoneLinkButton.cs
- NumberSubstitution.cs
- RelatedPropertyManager.cs
- HttpResponseHeader.cs
- OrderedDictionary.cs
- FormsAuthenticationTicket.cs
- FlowDocumentScrollViewerAutomationPeer.cs
- CompilationUtil.cs
- TextTreeUndo.cs
- Point3DCollectionConverter.cs
- BooleanSwitch.cs
- SystemPens.cs
- WebPartManager.cs
- DesignerView.Commands.cs
- XmlReaderDelegator.cs
- FixedPosition.cs
- PartialClassGenerationTask.cs
- Visual3D.cs
- DeviceContext2.cs
- SafeEventLogReadHandle.cs
- XmlSchemaComplexContentRestriction.cs
- MobileCategoryAttribute.cs
- WebPartAuthorizationEventArgs.cs
- AutoResizedEvent.cs
- ButtonFieldBase.cs
- ConstNode.cs
- FrameworkTextComposition.cs
- TaiwanLunisolarCalendar.cs
- CompareInfo.cs
- Timer.cs
- EndpointDispatcherTable.cs
- Matrix3DConverter.cs
- TextBox.cs
- DocumentApplicationDocumentViewer.cs
- DataContractSerializerSection.cs
- ConnectionsZoneAutoFormat.cs
- EntityContainerAssociationSet.cs
- AuthStoreRoleProvider.cs
- ConnectionManager.cs
- WebPartHelpVerb.cs
- ApplicationBuildProvider.cs
- graph.cs
- ServiceBusyException.cs
- XPathNodeHelper.cs
- CompilationRelaxations.cs
- Padding.cs
- ReferentialConstraint.cs
- StorageEndPropertyMapping.cs
- WebConfigurationHostFileChange.cs
- UTF32Encoding.cs
- TextSegment.cs
- FormsAuthenticationConfiguration.cs
- FormsAuthenticationUser.cs
- InputMethodStateTypeInfo.cs
- ActivityDelegate.cs
- JavaScriptString.cs
- Vector3DConverter.cs
- Propagator.Evaluator.cs
- GroupDescription.cs
- KeyNotFoundException.cs
- ObjectDataSource.cs
- XmlWrappingReader.cs
- SaveFileDialog.cs
- TreeNodeClickEventArgs.cs
- WebPartEditorApplyVerb.cs
- ModifierKeysValueSerializer.cs
- DataSetMappper.cs
- COM2DataTypeToManagedDataTypeConverter.cs
- SecurityProtocolCorrelationState.cs
- MgmtConfigurationRecord.cs
- XmlWrappingReader.cs
- TypeSystemProvider.cs
- DataGridViewCellStateChangedEventArgs.cs
- WmlTextViewAdapter.cs
- BufferedReadStream.cs
- Ref.cs
- Utils.cs
- RtfToken.cs
- MatrixIndependentAnimationStorage.cs
- Version.cs
- ConfigXmlSignificantWhitespace.cs
- DbTransaction.cs
- SynchronizationValidator.cs
- ParamArrayAttribute.cs
- SqlReorderer.cs
- LoadWorkflowAsyncResult.cs
- SpellerError.cs
- RadioButtonBaseAdapter.cs
- MessageQueueCriteria.cs