/// <summary> /// Returns true if the reader is pointing to an EncryptedData element. /// </summary> /// <param name="reader">The reader positioned at a security token.</param> /// <returns>true if the reader is positioned at EncryptedData else false.</returns> /// <remarks>Does not move the reader when returning false.</remarks> public override bool CanReadToken(XmlReader reader) { return(EncryptedDataElement.CanReadFrom(reader)); }
/// <summary> /// Reads the encrypted security token. /// </summary> /// <param name="reader">The reader from which to read the token.</param> /// <returns>An instance of <see cref="SecurityToken"/>.</returns> /// <exception cref="ArgumentNullException">Input parameter 'reader' is null.</exception> /// <exception cref="InvalidOperationException">One of the properties 'Configuration' or 'Configuration.ServiceTokenResolver' is null. This property is required for obtaining keys for decryption.</exception> /// <exception cref="SecurityTokenException">A <see cref="SecurityKeyIdentifier"/> is not found inside the xml pointed to by the reader.</exception> /// <exception cref="EncryptedTokenDecryptionFailedException">The <see cref="SecurityKeyIdentifier"/> found inside the xml cannot be resolved by Configuration.ServiceTokenResolver to a <see cref="SecurityKey"/>.</exception> /// <exception cref="SecurityTokenException">The <see cref="SecurityKeyIdentifier"/> is not a <see cref="SymmetricSecurityKey"/>.</exception> /// <exception cref="InvalidOperationException">The ContainingCollection (<see cref="SecurityTokenHandlerCollection"/>) is unable to find a <see cref="SecurityTokenHandler"/> that is able to read the decrypted xml and return a <see cref="SecurityToken"/>.</exception> public override SecurityToken ReadToken(XmlReader reader) { if (null == reader) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); } if (this.Configuration == null) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4274)); } if (this.Configuration.ServiceTokenResolver == null) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4276)); } // // Read the encrypted data element // EncryptedDataElement encryptedData = new EncryptedDataElement(KeyInfoSerializer); encryptedData.ReadXml(XmlDictionaryReader.CreateDictionaryReader(reader)); // // All the clauses in a keyinfo must identify the same key, so we // can try each clause in turn and stop when one resolves. // SecurityKey decryptionKey = null; foreach (SecurityKeyIdentifierClause clause in encryptedData.KeyIdentifier) { this.Configuration.ServiceTokenResolver.TryResolveSecurityKey(clause, out decryptionKey); if (null != decryptionKey) { break; } } // // Try to use the SKI to create the key instead. // if (decryptionKey == null && encryptedData.KeyIdentifier.CanCreateKey) { decryptionKey = encryptedData.KeyIdentifier.CreateKey(); } // // Fail if none of the clauses resolved or ski itself cannot create key. // if (null == decryptionKey) { EncryptedKeyIdentifierClause encryptedKeyClause; if (encryptedData.KeyIdentifier.TryFind <EncryptedKeyIdentifierClause>(out encryptedKeyClause)) { // // System.IdentityModel.Tokens.EncryptedKeyIdentifierClause.ToString() does not print out // very good information except the cipher data in this case. We have worked around that // by using the token serializer to serialize the key identifier clause again. // throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new EncryptedTokenDecryptionFailedException( SR.GetString(SR.ID4036, XmlUtil.SerializeSecurityKeyIdentifier(encryptedData.KeyIdentifier, base.ContainingCollection.KeyInfoSerializer)))); } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new EncryptedTokenDecryptionFailedException(SR.GetString(SR.ID4036, encryptedData.KeyIdentifier.ToString()))); } } // // Need a symmetric key // SymmetricSecurityKey symmetricKey = decryptionKey as SymmetricSecurityKey; if (null == symmetricKey) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityTokenException(SR.GetString(SR.ID4023))); } // // Do the actual decryption // byte[] plainText; using (SymmetricAlgorithm decrypter = symmetricKey.GetSymmetricAlgorithm(encryptedData.Algorithm)) { plainText = encryptedData.Decrypt(decrypter); } DebugEncryptedTokenClearText(plainText, Encoding.UTF8); // // Read and return the plaintext token // using (XmlReader innerTokenReader = XmlDictionaryReader.CreateTextReader(plainText, XmlDictionaryReaderQuotas.Max)) { if (this.ContainingCollection != null && this.ContainingCollection.CanReadToken(innerTokenReader)) { return(this.ContainingCollection.ReadToken(innerTokenReader)); } throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4014, innerTokenReader.LocalName, innerTokenReader.NamespaceURI)); } }
/// <summary> /// Writes a <see cref="EncryptedSecurityToken"/> using the xmlWriter. /// </summary> /// <param name="writer">The XmlWriter to which the encrypted token is written.</param> /// <param name="token">The <see cref="SecurityToken"/> which must be an instance of <see cref="EncryptedSecurityToken"/>.</param> /// <exception cref="ArgumentNullException">The input prameter 'writer' is null.</exception> /// <exception cref="ArgumentNullException">The input prameter 'token' is null.</exception> /// <exception cref="ArgumentException">The <see cref="SecurityToken"/> is not an instance of <see cref="EncryptedSecurityToken"/>.</exception> /// <exception cref="InvalidOperationException">The property 'Configuration' is null. This property is required for obtaining keys for encryption.</exception> /// <exception cref="InvalidOperationException">The ContaingCollection was unable to find a <see cref="SecurityTokenHandler"/> that is able to write /// the <see cref="SecurityToken"/> returned by 'EncryptedSecurityToken.Token'.</exception> /// <exception cref="SecurityTokenException">The property 'EncryptinCredentials.SecurityKey is not a <see cref="SymmetricSecurityKey"/></exception> public override void WriteToken(XmlWriter writer, SecurityToken token) { if (null == writer) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); } if (null == token) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("token"); } EncryptedSecurityToken encryptedToken = token as EncryptedSecurityToken; if (null == encryptedToken) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("token", SR.GetString(SR.ID4024)); } if (this.ContainingCollection == null) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4279)); } // // This implementation simply wraps the token in xenc:EncryptedData // EncryptedDataElement encryptedData = new EncryptedDataElement(KeyInfoSerializer); using (MemoryStream plaintextStream = new MemoryStream()) { // // Buffer the plaintext // using (XmlDictionaryWriter plaintextWriter = XmlDictionaryWriter.CreateTextWriter(plaintextStream, Encoding.UTF8, false)) { SecurityTokenHandler securityTokenHandler = this.ContainingCollection[encryptedToken.Token.GetType()]; if (securityTokenHandler != null) { securityTokenHandler.WriteToken(plaintextWriter, encryptedToken.Token); } else { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4224, encryptedToken.Token.GetType())); } } // // Set up the EncryptedData element // EncryptingCredentials encryptingCredentials = encryptedToken.EncryptingCredentials; encryptedData.Type = XmlEncryptionConstants.EncryptedDataTypes.Element; encryptedData.KeyIdentifier = encryptingCredentials.SecurityKeyIdentifier; encryptedData.Algorithm = encryptingCredentials.Algorithm; // // Get the encryption key, which must be symmetric // SymmetricSecurityKey encryptingKey = encryptingCredentials.SecurityKey as SymmetricSecurityKey; if (encryptingKey == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID3064))); } // // Do the actual encryption // using (SymmetricAlgorithm symmetricAlgorithm = encryptingKey.GetSymmetricAlgorithm(encryptingCredentials.Algorithm)) { byte[] plainTextBytes = plaintextStream.GetBuffer(); DebugEncryptedTokenClearText(plainTextBytes, Encoding.UTF8); encryptedData.Encrypt(symmetricAlgorithm, plainTextBytes, 0, (int)plaintextStream.Length); } } // // Write the EncryptedData element // encryptedData.WriteXml(writer, KeyInfoSerializer); }
/// <summary> /// Reads the encrypted security token. /// </summary> /// <param name="reader">The reader from which to read the token.</param> /// <returns>An instance of <see cref="SecurityToken"/>.</returns> /// <exception cref="ArgumentNullException">Input parameter 'reader' is null.</exception> /// <exception cref="InvalidOperationException">One of the properties 'Configuration' or 'Configuration.ServiceTokenResolver' is null. This property is required for obtaining keys for decryption.</exception> /// <exception cref="SecurityTokenException">A <see cref="SecurityKeyIdentifier"/> is not found inside the xml pointed to by the reader.</exception> /// <exception cref="EncryptedTokenDecryptionFailedException">The <see cref="SecurityKeyIdentifier"/> found inside the xml cannot be resolved by Configuration.ServiceTokenResolver to a <see cref="SecurityKey"/>.</exception> /// <exception cref="SecurityTokenException">The <see cref="SecurityKeyIdentifier"/> is not a <see cref="SymmetricSecurityKey"/>.</exception> /// <exception cref="InvalidOperationException">The ContainingCollection (<see cref="SecurityTokenHandlerCollection"/>) is unable to find a <see cref="SecurityTokenHandler"/> that is able to read the decrypted xml and return a <see cref="SecurityToken"/>.</exception> public override SecurityToken ReadToken(XmlReader reader) { if (null == reader) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); } if (this.Configuration == null) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4274)); } if (this.Configuration.ServiceTokenResolver == null) { throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4276)); } // // Read the encrypted data element // EncryptedDataElement encryptedData = new EncryptedDataElement(KeyInfoSerializer); encryptedData.ReadXml(XmlDictionaryReader.CreateDictionaryReader(reader)); // // All the clauses in a keyinfo must identify the same key, so we // can try each clause in turn and stop when one resolves. // SecurityKey decryptionKey = null; foreach (SecurityKeyIdentifierClause clause in encryptedData.KeyIdentifier) { this.Configuration.ServiceTokenResolver.TryResolveSecurityKey(clause, out decryptionKey); if (null != decryptionKey) { break; } } // // Try to use the SKI to create the key instead. // if (decryptionKey == null && encryptedData.KeyIdentifier.CanCreateKey) { decryptionKey = encryptedData.KeyIdentifier.CreateKey(); } // // Fail if none of the clauses resolved or ski itself cannot create key. // if (null == decryptionKey) { EncryptedKeyIdentifierClause encryptedKeyClause; if (encryptedData.KeyIdentifier.TryFind<EncryptedKeyIdentifierClause>(out encryptedKeyClause)) { // // System.IdentityModel.Tokens.EncryptedKeyIdentifierClause.ToString() does not print out // very good information except the cipher data in this case. We have worked around that // by using the token serializer to serialize the key identifier clause again. // throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new EncryptedTokenDecryptionFailedException( SR.GetString(SR.ID4036, XmlUtil.SerializeSecurityKeyIdentifier(encryptedData.KeyIdentifier, base.ContainingCollection.KeyInfoSerializer)))); } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new EncryptedTokenDecryptionFailedException(SR.GetString(SR.ID4036, encryptedData.KeyIdentifier.ToString()))); } } // // Need a symmetric key // SymmetricSecurityKey symmetricKey = decryptionKey as SymmetricSecurityKey; if (null == symmetricKey) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityTokenException(SR.GetString(SR.ID4023))); } // // Do the actual decryption // byte[] plainText; using (SymmetricAlgorithm decrypter = symmetricKey.GetSymmetricAlgorithm(encryptedData.Algorithm)) { plainText = encryptedData.Decrypt(decrypter); } DebugEncryptedTokenClearText(plainText, Encoding.UTF8); // // Read and return the plaintext token // using (XmlReader innerTokenReader = XmlDictionaryReader.CreateTextReader(plainText, XmlDictionaryReaderQuotas.Max)) { if (this.ContainingCollection != null && this.ContainingCollection.CanReadToken(innerTokenReader)) { return this.ContainingCollection.ReadToken(innerTokenReader); } throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4014, innerTokenReader.LocalName, innerTokenReader.NamespaceURI)); } }
internal static XmlDictionaryReader CreatePlaintextReaderFromEncryptedData( XmlDictionaryReader reader, SecurityTokenResolver serviceTokenResolver, SecurityTokenSerializer keyInfoSerializer, Collection<EncryptedKeyIdentifierClause> clauses, out EncryptingCredentials encryptingCredentials) { if (reader == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader"); } reader.MoveToContent(); if (reader.IsEmptyElement) { #pragma warning suppress 56504 // bogus - thinks reader.LocalName, reader.NamespaceURI need validation throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID3061, reader.LocalName, reader.NamespaceURI)); } encryptingCredentials = null; XmlUtil.ValidateXsiType(reader, Saml2Constants.Types.EncryptedElementType, Saml2Constants.Namespace); reader.ReadStartElement(); EncryptedDataElement encryptedData = new EncryptedDataElement(keyInfoSerializer); // <xenc:EncryptedData> 1 encryptedData.ReadXml(reader); // <xenc:EncryptedKey> 0-oo reader.MoveToContent(); while (reader.IsStartElement(XmlEncryptionConstants.Elements.EncryptedKey, XmlEncryptionConstants.Namespace)) { SecurityKeyIdentifierClause skic; if (keyInfoSerializer.CanReadKeyIdentifierClause(reader)) { skic = keyInfoSerializer.ReadKeyIdentifierClause(reader); } else { EncryptedKeyElement encryptedKey = new EncryptedKeyElement(keyInfoSerializer); encryptedKey.ReadXml(reader); skic = encryptedKey.GetClause(); } EncryptedKeyIdentifierClause encryptedKeyClause = skic as EncryptedKeyIdentifierClause; if (null == encryptedKeyClause) { throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4172)); } clauses.Add(encryptedKeyClause); } reader.ReadEndElement(); // Try to resolve the decryption key from both the embedded // KeyInfo and any external clauses SecurityKey decryptionKey = null; SecurityKeyIdentifierClause matchingClause = null; foreach (SecurityKeyIdentifierClause clause in encryptedData.KeyIdentifier) { if (serviceTokenResolver.TryResolveSecurityKey(clause, out decryptionKey)) { matchingClause = clause; break; } } if (null == decryptionKey) { foreach (SecurityKeyIdentifierClause clause in clauses) { if (serviceTokenResolver.TryResolveSecurityKey(clause, out decryptionKey)) { matchingClause = clause; break; } } } if (null == decryptionKey) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new EncryptedTokenDecryptionFailedException()); } // Need a symmetric key SymmetricSecurityKey symmetricKey = decryptionKey as SymmetricSecurityKey; if (null == symmetricKey) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityTokenException(SR.GetString(SR.ID4023))); } // Do the actual decryption SymmetricAlgorithm decryptor = symmetricKey.GetSymmetricAlgorithm(encryptedData.Algorithm); byte[] plainText = encryptedData.Decrypt(decryptor); // Save off the encrypting credentials for roundtrip encryptingCredentials = new ReceivedEncryptingCredentials(decryptionKey, new SecurityKeyIdentifier(matchingClause), encryptedData.Algorithm); return XmlDictionaryReader.CreateTextReader(plainText, reader.Quotas); }
/// <summary> /// Writes the <saml:NameID> element. /// </summary> /// <param name="writer">A <see cref="XmlWriter"/> to serialize the <see cref="Saml2NameIdentifier"/>.</param> /// <param name="data">The <see cref="Saml2NameIdentifier"/> to serialize.</param> /// <exception cref="ArgumentNullException">The input parameter 'writer' or 'data' is null.</exception> /// <exception cref="CryptographicException">Saml2NameIdentifier encrypting credentials must have a Symmetric Key specified.</exception> protected virtual void WriteNameId(XmlWriter writer, Saml2NameIdentifier data) { if (null == writer) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); } if (null == data) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("data"); } // If there are encrypting credentials, then we need to encrypt the name identifier if (data.EncryptingCredentials != null) { EncryptingCredentials encryptingCredentials = data.EncryptingCredentials; // Get the encryption key, which must be symmetric SymmetricSecurityKey encryptingKey = encryptingCredentials.SecurityKey as SymmetricSecurityKey; if (encryptingKey == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.GetString(SR.ID3284))); } MemoryStream plaintextStream = null; try { // Serialize an encrypted name ID plaintextStream = new MemoryStream(); using (XmlWriter plaintextWriter = XmlDictionaryWriter.CreateTextWriter(plaintextStream, Encoding.UTF8, false)) { plaintextWriter.WriteStartElement(Saml2Constants.Elements.NameID, Saml2Constants.Namespace); this.WriteNameIdType(plaintextWriter, data); plaintextWriter.WriteEndElement(); } EncryptedDataElement encryptedData = new EncryptedDataElement(); encryptedData.Type = XmlEncryptionConstants.EncryptedDataTypes.Element; encryptedData.Algorithm = encryptingCredentials.Algorithm; encryptedData.KeyIdentifier = encryptingCredentials.SecurityKeyIdentifier; // Perform encryption SymmetricAlgorithm symmetricAlgorithm = encryptingKey.GetSymmetricAlgorithm(encryptingCredentials.Algorithm); encryptedData.Encrypt(symmetricAlgorithm, plaintextStream.GetBuffer(), 0, (int)plaintextStream.Length); ((IDisposable)plaintextStream).Dispose(); writer.WriteStartElement(Saml2Constants.Elements.EncryptedID, Saml2Constants.Namespace); encryptedData.WriteXml(writer, this.KeyInfoSerializer); foreach (EncryptedKeyIdentifierClause clause in data.ExternalEncryptedKeys) { this.KeyInfoSerializer.WriteKeyIdentifierClause(writer, clause); } writer.WriteEndElement(); } finally { if (plaintextStream != null) { plaintextStream.Dispose(); plaintextStream = null; } } } else { writer.WriteStartElement(Saml2Constants.Elements.NameID, Saml2Constants.Namespace); this.WriteNameIdType(writer, data); writer.WriteEndElement(); } }
/// <summary> /// Serializes the provided SamlAssertion to the XmlWriter. /// </summary> /// <param name="writer">A <see cref="XmlWriter"/> to serialize the <see cref="Saml2Assertion"/>.</param> /// <param name="data">The <see cref="Saml2Assertion"/> to serialize.</param> /// <exception cref="ArgumentNullException">The <paramref name="writer"/> or <paramref name="data"/> parameters are null.</exception> /// <exception cref="InvalidOperationException"> The <paramref name="data"/> has both <see cref="EncryptingCredentials"/> and <see cref="ReceivedEncryptingCredentials"/> properties null.</exception> /// <exception cref="InvalidOperationException">The <paramref name="data"/> must have a <see cref="Saml2Subject"/> if no <see cref="Saml2Statement"/> are present.</exception> /// <exception cref="InvalidOperationException">The SAML2 authentication, attribute, and authorization decision <see cref="Saml2Statement"/> require a <see cref="Saml2Subject"/>.</exception> /// <exception cref="CryptographicException">Token encrypting credentials must have a Symmetric Key specified.</exception> protected virtual void WriteAssertion(XmlWriter writer, Saml2Assertion data) { if (null == writer) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); } if (null == data) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("data"); } XmlWriter originalWriter = writer; MemoryStream plaintextStream = null; XmlDictionaryWriter plaintextWriter = null; // If an EncryptingCredentials is present then check if this is not of type ReceivedEncryptinCredentials. // ReceivedEncryptingCredentials mean that it was credentials that were hydrated from a token received // on the wire. We should not directly use this while re-serializing a token. if ((null != data.EncryptingCredentials) && !(data.EncryptingCredentials is ReceivedEncryptingCredentials)) { plaintextStream = new MemoryStream(); writer = plaintextWriter = XmlDictionaryWriter.CreateTextWriter(plaintextStream, Encoding.UTF8, false); } else if (data.ExternalEncryptedKeys == null || data.ExternalEncryptedKeys.Count > 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4173))); } // If we've saved off the token stream, re-emit it. if (data.CanWriteSourceData) { data.WriteSourceData(writer); } else { // Wrap the writer if necessary for a signature // We do not dispose this writer, since as a delegating writer it would // dispose the inner writer, which we don't properly own. EnvelopedSignatureWriter signatureWriter = null; if (null != data.SigningCredentials) { #pragma warning suppress 56506 writer = signatureWriter = new EnvelopedSignatureWriter(writer, data.SigningCredentials, data.Id.Value, new WrappedSerializer(this, data)); } if (null == data.Subject) { // An assertion with no statements MUST contain a <Subject> element. [Saml2Core, line 585] if (data.Statements == null || 0 == data.Statements.Count) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4106))); } // Furthermore, the built-in statement types all require the presence of a subject. // [Saml2Core, lines 1050, 1168, 1280] foreach (Saml2Statement statement in data.Statements) { if (statement is Saml2AuthenticationStatement || statement is Saml2AttributeStatement || statement is Saml2AuthorizationDecisionStatement) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SR.GetString(SR.ID4119))); } } } // <Assertion> writer.WriteStartElement(Saml2Constants.Elements.Assertion, Saml2Constants.Namespace); // @ID - required writer.WriteAttributeString(Saml2Constants.Attributes.ID, data.Id.Value); // @IssueInstant - required writer.WriteAttributeString(Saml2Constants.Attributes.IssueInstant, XmlConvert.ToString(data.IssueInstant.ToUniversalTime(), DateTimeFormats.Generated)); // @Version - required writer.WriteAttributeString(Saml2Constants.Attributes.Version, data.Version); // <Issuer> 1 this.WriteIssuer(writer, data.Issuer); // <ds:Signature> 0-1 if (null != signatureWriter) { signatureWriter.WriteSignature(); } // <Subject> 0-1 if (null != data.Subject) { this.WriteSubject(writer, data.Subject); } // <Conditions> 0-1 if (null != data.Conditions) { this.WriteConditions(writer, data.Conditions); } // <Advice> 0-1 if (null != data.Advice) { this.WriteAdvice(writer, data.Advice); } // <Statement|AuthnStatement|AuthzDecisionStatement|AttributeStatement>, 0-OO foreach (Saml2Statement statement in data.Statements) { this.WriteStatement(writer, statement); } writer.WriteEndElement(); } // Finish off the encryption if (null != plaintextWriter) { ((IDisposable)plaintextWriter).Dispose(); plaintextWriter = null; EncryptedDataElement encryptedData = new EncryptedDataElement(); encryptedData.Type = XmlEncryptionConstants.EncryptedDataTypes.Element; encryptedData.Algorithm = data.EncryptingCredentials.Algorithm; encryptedData.KeyIdentifier = data.EncryptingCredentials.SecurityKeyIdentifier; // Get the encryption key, which must be symmetric SymmetricSecurityKey encryptingKey = data.EncryptingCredentials.SecurityKey as SymmetricSecurityKey; if (encryptingKey == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.GetString(SR.ID3064))); } // Do the actual encryption SymmetricAlgorithm symmetricAlgorithm = encryptingKey.GetSymmetricAlgorithm(data.EncryptingCredentials.Algorithm); encryptedData.Encrypt(symmetricAlgorithm, plaintextStream.GetBuffer(), 0, (int)plaintextStream.Length); ((IDisposable)plaintextStream).Dispose(); originalWriter.WriteStartElement(Saml2Constants.Elements.EncryptedAssertion, Saml2Constants.Namespace); encryptedData.WriteXml(originalWriter, this.KeyInfoSerializer); foreach (EncryptedKeyIdentifierClause clause in data.ExternalEncryptedKeys) { this.KeyInfoSerializer.WriteKeyIdentifierClause(originalWriter, clause); } originalWriter.WriteEndElement(); } }