protected override void StartPrimarySignatureCore(SecurityToken token, SecurityKeyIdentifier keyIdentifier, MessagePartSpecification signatureParts, bool generateTargettableSignature) { SecurityAlgorithmSuite suite = this.AlgorithmSuite; string canonicalizationAlgorithm = suite.DefaultCanonicalizationAlgorithm; XmlDictionaryString canonicalizationAlgorithmDictionaryString = suite.DefaultCanonicalizationAlgorithmDictionaryString; if (canonicalizationAlgorithm != SecurityAlgorithms.ExclusiveC14n) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new MessageSecurityException(SR.GetString(SR.UnsupportedCanonicalizationAlgorithm, suite.DefaultCanonicalizationAlgorithm))); } string signatureAlgorithm; XmlDictionaryString signatureAlgorithmDictionaryString; suite.GetSignatureAlgorithmAndKey(token, out signatureAlgorithm, out this.signatureKey, out signatureAlgorithmDictionaryString); string digestAlgorithm = suite.DefaultDigestAlgorithm; XmlDictionaryString digestAlgorithmDictionaryString = suite.DefaultDigestAlgorithmDictionaryString; this.signedInfo = new PreDigestedSignedInfo(ServiceModelDictionaryManager.Instance, canonicalizationAlgorithm, canonicalizationAlgorithmDictionaryString, digestAlgorithm, digestAlgorithmDictionaryString, signatureAlgorithm, signatureAlgorithmDictionaryString); this.signedXml = new SignedXml(this.signedInfo, ServiceModelDictionaryManager.Instance, this.StandardsManager.SecurityTokenSerializer); if (keyIdentifier != null) { this.signedXml.Signature.KeyIdentifier = keyIdentifier; } if (generateTargettableSignature) { this.signedXml.Id = GenerateId(); } this.effectiveSignatureParts = signatureParts; this.hashStream = this.signedInfo.ResourcePool.TakeHashStream(digestAlgorithm); }
// Given a token and useStarTransform value this method adds apporopriate reference accordingly. // 1. If strTransform is disabled, it adds a reference to the token's id. // 2. Else if strtransform is enabled it adds a reference the security token's keyIdentifier's id. void AddTokenSignatureReference(SecurityToken token, SecurityKeyIdentifierClause keyIdentifierClause, bool strTransformEnabled) { if (!strTransformEnabled && token.Id == null) { throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.ElementToSignMustHaveId)), this.Message); } HashStream hashStream = TakeHashStream(); XmlDictionaryWriter utf8Writer = TakeUtf8Writer(); utf8Writer.StartCanonicalization(hashStream, false, null); this.StandardsManager.SecurityTokenSerializer.WriteToken(utf8Writer, token); utf8Writer.EndCanonicalization(); if (strTransformEnabled) { if (keyIdentifierClause != null) { if (String.IsNullOrEmpty(keyIdentifierClause.Id)) { keyIdentifierClause.Id = SecurityUniqueId.Create().Value; } this.ElementContainer.MapSecurityTokenToStrClause(token, keyIdentifierClause); this.signedInfo.AddReference(keyIdentifierClause.Id, hashStream.FlushHashAndGetValue(), true); } else { throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenManagerCannotCreateTokenReference)), this.Message); } } else { this.signedInfo.AddReference(token.Id, hashStream.FlushHashAndGetValue()); } }
public override void ApplyBodySecurity(XmlDictionaryWriter writer, IPrefixGenerator prefixGenerator) { SecurityAppliedMessage message = this.SecurityAppliedMessage; EncryptedData encryptedData; HashStream hashStream; switch (message.BodyProtectionMode) { case MessagePartProtectionMode.None: return; case MessagePartProtectionMode.Sign: hashStream = TakeHashStream(); if (CanCanonicalizeAndFragment(writer)) { message.WriteBodyToSignWithFragments(hashStream, false, null, writer); } else { message.WriteBodyToSign(hashStream); } this.signedInfo.AddReference(message.BodyId, hashStream.FlushHashAndGetValue()); return; case MessagePartProtectionMode.SignThenEncrypt: hashStream = TakeHashStream(); encryptedData = CreateEncryptedDataForBody(); if (CanCanonicalizeAndFragment(writer)) { message.WriteBodyToSignThenEncryptWithFragments(hashStream, false, null, encryptedData, this.encryptingSymmetricAlgorithm, writer); } else { message.WriteBodyToSignThenEncrypt(hashStream, encryptedData, this.encryptingSymmetricAlgorithm); } this.signedInfo.AddReference(message.BodyId, hashStream.FlushHashAndGetValue()); this.referenceList.AddReferredId(encryptedData.Id); this.hasSignedEncryptedMessagePart = true; return; case MessagePartProtectionMode.Encrypt: encryptedData = CreateEncryptedDataForBody(); message.WriteBodyToEncrypt(encryptedData, this.encryptingSymmetricAlgorithm); this.referenceList.AddReferredId(encryptedData.Id); return; case MessagePartProtectionMode.EncryptThenSign: hashStream = TakeHashStream(); encryptedData = CreateEncryptedDataForBody(); message.WriteBodyToEncryptThenSign(hashStream, encryptedData, this.encryptingSymmetricAlgorithm); this.signedInfo.AddReference(message.BodyId, hashStream.FlushHashAndGetValue()); this.referenceList.AddReferredId(encryptedData.Id); return; default: Fx.Assert("Invalid MessagePartProtectionMode"); return; } }
void AddSignatureReference(SendSecurityHeaderElement[] elements) { if (elements != null) { for (int i = 0; i < elements.Length; ++i) { SecurityKeyIdentifierClause keyIdentifierClause = null; TokenElement signedEncryptedTokenElement = elements[i].Item as TokenElement; // signedEncryptedTokenElement can either be a TokenElement ( in SignThenEncrypt case) or EncryptedData ( in !SignThenEncryptCase) // STR-Transform does not make sense in !SignThenEncrypt case . // note: signedEncryptedTokenElement can also be SignatureConfirmation but we do not care about it here. bool useStrTransform = signedEncryptedTokenElement != null && SignThenEncrypt && this.ShouldUseStrTransformForToken(signedEncryptedTokenElement.Token, i, SecurityTokenAttachmentMode.SignedEncrypted, out keyIdentifierClause); if (!useStrTransform && elements[i].Id == null) { throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.ElementToSignMustHaveId)), this.Message); } HashStream hashStream = TakeHashStream(); XmlDictionaryWriter utf8Writer = TakeUtf8Writer(); utf8Writer.StartCanonicalization(hashStream, false, null); elements[i].Item.WriteTo(utf8Writer, ServiceModelDictionaryManager.Instance); utf8Writer.EndCanonicalization(); if (useStrTransform) { if (keyIdentifierClause != null) { if (String.IsNullOrEmpty(keyIdentifierClause.Id)) { keyIdentifierClause.Id = SecurityUniqueId.Create().Value; } this.ElementContainer.MapSecurityTokenToStrClause(signedEncryptedTokenElement.Token, keyIdentifierClause); this.signedInfo.AddReference(keyIdentifierClause.Id, hashStream.FlushHashAndGetValue(), true); } else { throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenManagerCannotCreateTokenReference)), this.Message); } } else { this.signedInfo.AddReference(elements[i].Id, hashStream.FlushHashAndGetValue()); } } } }
HashStream TakeHashStream() { HashStream hashStream = null; if (this.hashStream == null) { this.hashStream = hashStream = new HashStream(CryptoHelper.CreateHashAlgorithm(this.AlgorithmSuite.DefaultDigestAlgorithm)); } else { hashStream = this.hashStream;; hashStream.Reset(); } return(hashStream); }
internal override SecurityTimestamp ReadTimestamp(XmlDictionaryReader reader, string digestAlgorithm, SignatureResourcePool resourcePool) { bool canonicalize = digestAlgorithm != null && reader.CanCanonicalize; HashStream hashStream = null; reader.MoveToStartElement(XD.UtilityDictionary.Timestamp, XD.UtilityDictionary.Namespace); if (canonicalize) { hashStream = resourcePool.TakeHashStream(digestAlgorithm); reader.StartCanonicalization(hashStream, false, null); } string id = reader.GetAttribute(XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace); reader.ReadStartElement(); reader.ReadStartElement(XD.UtilityDictionary.CreatedElement, XD.UtilityDictionary.Namespace); DateTime creationTimeUtc = reader.ReadContentAsDateTime().ToUniversalTime(); reader.ReadEndElement(); DateTime expiryTimeUtc; if (reader.IsStartElement(XD.UtilityDictionary.ExpiresElement, XD.UtilityDictionary.Namespace)) { reader.ReadStartElement(); expiryTimeUtc = reader.ReadContentAsDateTime().ToUniversalTime(); reader.ReadEndElement(); } else { expiryTimeUtc = SecurityUtils.MaxUtcDateTime; } reader.ReadEndElement(); byte[] digest; if (canonicalize) { reader.EndCanonicalization(); digest = hashStream.FlushHashAndGetValue(); } else { digest = null; } return(new SecurityTimestamp(creationTimeUtc, expiryTimeUtc, id, digestAlgorithm, digest)); }
string GetSignatureHash(MessageHeader header, string headerId, IPrefixGenerator prefixGenerator, XmlDictionaryWriter writer, out byte[] hash) { HashStream hashStream = TakeHashStream(); XmlDictionaryWriter effectiveWriter; XmlBuffer canonicalBuffer = null; if (writer.CanCanonicalize) { effectiveWriter = writer; } else { canonicalBuffer = new XmlBuffer(int.MaxValue); effectiveWriter = canonicalBuffer.OpenSection(XmlDictionaryReaderQuotas.Max); } effectiveWriter.StartCanonicalization(hashStream, false, null); header.WriteStartHeader(effectiveWriter, this.Version); if (headerId == null) { headerId = GenerateId(); this.StandardsManager.IdManager.WriteIdAttribute(effectiveWriter, headerId); } header.WriteHeaderContents(effectiveWriter, this.Version); effectiveWriter.WriteEndElement(); effectiveWriter.EndCanonicalization(); effectiveWriter.Flush(); if (!ReferenceEquals(effectiveWriter, writer)) { Fx.Assert(canonicalBuffer != null, "Canonical buffer cannot be null."); canonicalBuffer.CloseSection(); canonicalBuffer.Close(); XmlDictionaryReader dicReader = canonicalBuffer.GetReader(0); writer.WriteNode(dicReader, false); dicReader.Close(); } hash = hashStream.FlushHashAndGetValue(); return(headerId); }
protected override void StartPrimarySignatureCore(SecurityToken token, SecurityKeyIdentifier keyIdentifier, MessagePartSpecification signatureParts, bool generateTargettableSignature) { SecurityAlgorithmSuite suite = this.AlgorithmSuite; string canonicalizationAlgorithm = suite.DefaultCanonicalizationAlgorithm; XmlDictionaryString canonicalizationAlgorithmDictionaryString = suite.DefaultCanonicalizationAlgorithmDictionaryString; if (canonicalizationAlgorithm != SecurityAlgorithms.ExclusiveC14n) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new MessageSecurityException(SR.GetString(SR.UnsupportedCanonicalizationAlgorithm, suite.DefaultCanonicalizationAlgorithm))); } string signatureAlgorithm; XmlDictionaryString signatureAlgorithmDictionaryString; suite.GetSignatureAlgorithmAndKey(token, out signatureAlgorithm, out this.signatureKey, out signatureAlgorithmDictionaryString); string digestAlgorithm = suite.DefaultDigestAlgorithm; XmlDictionaryString digestAlgorithmDictionaryString = suite.DefaultDigestAlgorithmDictionaryString; this.signedInfo = new PreDigestedSignedInfo(ServiceModelDictionaryManager.Instance, canonicalizationAlgorithm, canonicalizationAlgorithmDictionaryString, digestAlgorithm, digestAlgorithmDictionaryString, signatureAlgorithm, signatureAlgorithmDictionaryString); this.signedXml = new SignedXml(this.signedInfo, ServiceModelDictionaryManager.Instance, this.StandardsManager.SecurityTokenSerializer); if (keyIdentifier != null) { this.signedXml.Signature.KeyIdentifier = keyIdentifier; } if (generateTargettableSignature) { this.signedXml.Id = GenerateId(); } this.effectiveSignatureParts = signatureParts; this.hashStream = this.signedInfo.ResourcePool.TakeHashStream(digestAlgorithm); }
HashStream TakeHashStream() { HashStream hashStream = null; if (this.hashStream == null) { this.hashStream = hashStream = new HashStream(CryptoHelper.CreateHashAlgorithm(this.AlgorithmSuite.DefaultDigestAlgorithm)); } else { hashStream = this.hashStream;; hashStream.Reset(); } return hashStream; }
protected override ISignatureValueSecurityElement CompletePrimarySignatureCore( SendSecurityHeaderElement[] signatureConfirmations, SecurityToken[] signedEndorsingTokens, SecurityToken[] signedTokens, SendSecurityHeaderElement[] basicTokens, bool isPrimarySignature) { if (this.signedXml == null) { return null; } SecurityTimestamp timestamp = this.Timestamp; if (timestamp != null) { if (timestamp.Id == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TimestampToSignHasNoId))); } HashStream hashStream = TakeHashStream(); this.StandardsManager.WSUtilitySpecificationVersion.WriteTimestampCanonicalForm( hashStream, timestamp, this.signedInfo.ResourcePool.TakeEncodingBuffer()); signedInfo.AddReference(timestamp.Id, hashStream.FlushHashAndGetValue()); } if ((this.ShouldSignToHeader) && (this.signatureKey is AsymmetricSecurityKey) && (this.Version.Addressing != AddressingVersion.None)) { if (this.toHeaderHash != null) signedInfo.AddReference(this.toHeaderId, this.toHeaderHash); else throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TransportSecurityRequireToHeader))); } AddSignatureReference(signatureConfirmations); if (isPrimarySignature && this.ShouldProtectTokens) { AddPrimaryTokenSignatureReference(this.ElementContainer.SourceSigningToken, this.SigningTokenParameters); } if (this.RequireMessageProtection) { AddSignatureReference(signedEndorsingTokens, SecurityTokenAttachmentMode.SignedEndorsing); AddSignatureReference(signedTokens, SecurityTokenAttachmentMode.Signed); AddSignatureReference(basicTokens); } if (this.signedInfo.ReferenceCount == 0) { throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NoPartsOfMessageMatchedPartsToSign)), this.Message); } try { this.signedXml.ComputeSignature(this.signatureKey); return this.signedXml; } finally { this.hashStream = null; this.signedInfo = null; this.signedXml = null; this.signatureKey = null; this.effectiveSignatureParts = null; } }
public override void ApplyBodySecurity(XmlDictionaryWriter writer, IPrefixGenerator prefixGenerator) { SecurityAppliedMessage message = this.SecurityAppliedMessage; EncryptedData encryptedData; HashStream hashStream; switch (message.BodyProtectionMode) { case MessagePartProtectionMode.None: return; case MessagePartProtectionMode.Sign: hashStream = TakeHashStream(); if (CanCanonicalizeAndFragment(writer)) { message.WriteBodyToSignWithFragments(hashStream, false, null, writer); } else { message.WriteBodyToSign(hashStream); } this.signedInfo.AddReference(message.BodyId, hashStream.FlushHashAndGetValue()); return; case MessagePartProtectionMode.SignThenEncrypt: hashStream = TakeHashStream(); encryptedData = CreateEncryptedDataForBody(); if (CanCanonicalizeAndFragment(writer)) { message.WriteBodyToSignThenEncryptWithFragments(hashStream, false, null, encryptedData, this.encryptingSymmetricAlgorithm, writer); } else { message.WriteBodyToSignThenEncrypt(hashStream, encryptedData, this.encryptingSymmetricAlgorithm); } this.signedInfo.AddReference(message.BodyId, hashStream.FlushHashAndGetValue()); this.referenceList.AddReferredId(encryptedData.Id); this.hasSignedEncryptedMessagePart = true; return; case MessagePartProtectionMode.Encrypt: encryptedData = CreateEncryptedDataForBody(); message.WriteBodyToEncrypt(encryptedData, this.encryptingSymmetricAlgorithm); this.referenceList.AddReferredId(encryptedData.Id); return; case MessagePartProtectionMode.EncryptThenSign: hashStream = TakeHashStream(); encryptedData = CreateEncryptedDataForBody(); message.WriteBodyToEncryptThenSign(hashStream, encryptedData, this.encryptingSymmetricAlgorithm); this.signedInfo.AddReference(message.BodyId, hashStream.FlushHashAndGetValue()); this.referenceList.AddReferredId(encryptedData.Id); return; default: Fx.Assert("Invalid MessagePartProtectionMode"); return; } }
protected override ISignatureValueSecurityElement CompletePrimarySignatureCore( SendSecurityHeaderElement[] signatureConfirmations, SecurityToken[] signedEndorsingTokens, SecurityToken[] signedTokens, SendSecurityHeaderElement[] basicTokens, bool isPrimarySignature) { if (this.signedXml == null) { return(null); } SecurityTimestamp timestamp = this.Timestamp; if (timestamp != null) { if (timestamp.Id == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TimestampToSignHasNoId))); } HashStream hashStream = TakeHashStream(); this.StandardsManager.WSUtilitySpecificationVersion.WriteTimestampCanonicalForm( hashStream, timestamp, this.signedInfo.ResourcePool.TakeEncodingBuffer()); signedInfo.AddReference(timestamp.Id, hashStream.FlushHashAndGetValue()); } if ((this.ShouldSignToHeader) && (this.signatureKey is AsymmetricSecurityKey) && (this.Version.Addressing != AddressingVersion.None)) { if (this.toHeaderHash != null) { signedInfo.AddReference(this.toHeaderId, this.toHeaderHash); } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TransportSecurityRequireToHeader))); } } AddSignatureReference(signatureConfirmations); if (isPrimarySignature && this.ShouldProtectTokens) { AddPrimaryTokenSignatureReference(this.ElementContainer.SourceSigningToken, this.SigningTokenParameters); } if (this.RequireMessageProtection) { AddSignatureReference(signedEndorsingTokens, SecurityTokenAttachmentMode.SignedEndorsing); AddSignatureReference(signedTokens, SecurityTokenAttachmentMode.Signed); AddSignatureReference(basicTokens); } if (this.signedInfo.ReferenceCount == 0) { throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NoPartsOfMessageMatchedPartsToSign)), this.Message); } try { this.signedXml.ComputeSignature(this.signatureKey); return(this.signedXml); } finally { this.hashStream = null; this.signedInfo = null; this.signedXml = null; this.signatureKey = null; this.effectiveSignatureParts = null; } }