public ClaimsPrincipal Validate(string jwtTokenAsBase64, JwtOptions options)
        {
            var tokenHandler = new JwtSecurityTokenHandler();

            string keyAsUtf8 = options.JwtSigningKeyAsUtf8;

            byte[] keyAsBytes = Encoding.UTF8.GetBytes(keyAsUtf8);

            SecurityToken signingToken = new BinarySecretSecurityToken(keyAsBytes);
            var tokenValidationParameters = new TokenValidationParameters
                                            {
                                                IssuerSigningToken = signingToken,
                                                ValidAudience = options.Audience,
                                                ValidIssuer = options.Issuer
                                            };
            ClaimsPrincipal principal;
            try
            {
                SecurityToken validatedToken;
                principal = tokenHandler.ValidateToken(jwtTokenAsBase64, tokenValidationParameters,
                    out validatedToken);
            }
            catch (Exception ex)
            {
                Debug.Write(ex, "error");
                principal = new ClaimsPrincipal(new ClaimsIdentity(authenticationType:""));
            }

            return principal;
        }
        public static void CreateIssuedToken(Guid transactionId, string coordinationContextId, ProtocolVersion protocolVersion, out RequestSecurityTokenResponse issuedToken, out string sctId)
        {
            sctId = CoordinationContext.CreateNativeIdentifier(Guid.NewGuid());
            byte[] key = DeriveIssuedTokenKey(transactionId, sctId);
            DateTime utcNow = DateTime.UtcNow;
            SecurityContextSecurityToken token = new SecurityContextSecurityToken(new UniqueId(sctId), key, utcNow, utcNow + TimeSpan.FromDays(36500.0));
            BinarySecretSecurityToken token2 = new BinarySecretSecurityToken(key);
            SecurityStandardsManager standardsManager = CreateStandardsManager(protocolVersion);
            RequestSecurityTokenResponse response = new RequestSecurityTokenResponse(standardsManager) {
                TokenType = standardsManager.SecureConversationDriver.TokenTypeUri,
                RequestedUnattachedReference = SecurityContextSecurityTokenParameters.CreateKeyIdentifierClause(token, SecurityTokenReferenceStyle.External),
                RequestedAttachedReference = SecurityContextSecurityTokenParameters.CreateKeyIdentifierClause(token, SecurityTokenReferenceStyle.Internal),
                RequestedSecurityToken = token,
                RequestedProofToken = token2
            };
            DataContractSerializer serializer = IdentifierElementSerializer(protocolVersion);
            ProtocolVersionHelper.AssertProtocolVersion(protocolVersion, typeof(CoordinationServiceSecurity), "CreateIssuedToken");
            switch (protocolVersion)
            {
                case ProtocolVersion.Version10:
                    response.SetAppliesTo<IdentifierElement10>(new IdentifierElement10(coordinationContextId), serializer);
                    break;

                case ProtocolVersion.Version11:
                    response.SetAppliesTo<IdentifierElement11>(new IdentifierElement11(coordinationContextId), serializer);
                    break;
            }
            response.MakeReadOnly();
            if (DebugTrace.Verbose)
            {
                DebugTrace.Trace(TraceLevel.Verbose, "Created issued token with id {0} for transaction {1}", sctId, transactionId);
            }
            issuedToken = response;
        }
Example #3
0
        /// <summary>
        /// Creates a SAML Token with the input parameters
        /// </summary>
        /// <param name="stsName">Name of the STS issuing the SAML Token</param>
        /// <param name="proofToken">Associated Proof Token</param>
        /// <param name="issuerToken">Associated Issuer Token</param>
        /// <param name="proofKeyEncryptionToken">Token to encrypt the proof key with</param>
        /// <param name="samlConditions">The Saml Conditions to be used in the construction of the SAML Token</param>
        /// <param name="samlAttributes">The Saml Attributes to be used in the construction of the SAML Token</param>
        /// <returns>A SAML Token</returns>
        public static SamlSecurityToken CreateSamlToken(string stsName,
                                                        BinarySecretSecurityToken proofToken,
                                                        SecurityToken issuerToken,
                                                        SecurityToken proofKeyEncryptionToken,
                                                        SamlConditions samlConditions,
                                                        IEnumerable<SamlAttribute> samlAttributes)
		{
            // Create a security token reference to the issuer certificate 
            SecurityKeyIdentifierClause skic = issuerToken.CreateKeyIdentifierClause<X509ThumbprintKeyIdentifierClause>();
            SecurityKeyIdentifier issuerKeyIdentifier = new SecurityKeyIdentifier(skic);

            // Create an encrypted key clause containing the encrypted proof key
            byte[] wrappedKey = proofKeyEncryptionToken.SecurityKeys[0].EncryptKey(SecurityAlgorithms.RsaOaepKeyWrap, proofToken.GetKeyBytes());
            SecurityKeyIdentifierClause encryptingTokenClause = proofKeyEncryptionToken.CreateKeyIdentifierClause<X509ThumbprintKeyIdentifierClause>();
            EncryptedKeyIdentifierClause encryptedKeyClause = new EncryptedKeyIdentifierClause(wrappedKey, SecurityAlgorithms.RsaOaepKeyWrap, new SecurityKeyIdentifier(encryptingTokenClause) );
            SecurityKeyIdentifier proofKeyIdentifier = new SecurityKeyIdentifier(encryptedKeyClause);

            // Create a comfirmationMethod for HolderOfKey
			List<string> confirmationMethods = new List<string>(1);
			confirmationMethods.Add(SamlConstants.HolderOfKey);

            // Create a SamlSubject with proof key and confirmation method from above
			SamlSubject samlSubject = new SamlSubject(null,
													  null,
													  null,
													  confirmationMethods,
													  null,
                                                      proofKeyIdentifier);

            // Create a SamlAttributeStatement from the passed in SamlAttribute collection and the SamlSubject from above
			SamlAttributeStatement samlAttributeStatement = new SamlAttributeStatement(samlSubject, samlAttributes);

            // Put the SamlAttributeStatement into a list of SamlStatements
			List<SamlStatement> samlSubjectStatements = new List<SamlStatement>();
			samlSubjectStatements.Add(samlAttributeStatement);

            // Create a SigningCredentials instance from the key associated with the issuerToken.
            SigningCredentials signingCredentials = new SigningCredentials(issuerToken.SecurityKeys[0],
                                                                           SecurityAlgorithms.RsaSha1Signature,
                                                                           SecurityAlgorithms.Sha1Digest,
                                                                           issuerKeyIdentifier);

            // Create a SamlAssertion from the list of SamlStatements created above and the passed in
            // SamlConditions.
			SamlAssertion samlAssertion = new SamlAssertion("_" + Guid.NewGuid().ToString(),
							                                stsName,
							                                DateTime.UtcNow,
							                                samlConditions,
							                                new SamlAdvice(),
							                                samlSubjectStatements
						                                	);
            // Set the SigningCredentials for the SamlAssertion
			samlAssertion.SigningCredentials = signingCredentials;

            // Create a SamlSecurityToken from the SamlAssertion and return it
			return new SamlSecurityToken(samlAssertion);
		}
Example #4
0
        /// <summary>
        /// Creates a SAML assertion based on a symmetric proof key
        /// </summary>
        /// <param name="claims">A ClaimSet containing the claims to be placed into the SAML assertion</param>
        /// <param name="signatureToken">An X509SecurityToken that will be used to sign the SAML assertion</param>
        /// <param name="encryptionToken">An X509SecurityToken that will be used to encrypt the proof key</param>
        /// <param name="proofToken">A BinarySecretSecurityToken containing the proof key</param>
        /// <param name="algoSuite">The algorithm suite to use when performing cryptographic operations</param>
        /// <returns>A SAML assertion containing the passed in claims and proof key, signed by the provided signature token</returns>
        public static SamlAssertion CreateSymmetricKeyBasedAssertion(ClaimSet claims, X509SecurityToken signatureToken, X509SecurityToken encryptionToken, BinarySecretSecurityToken proofToken, SecurityAlgorithmSuite algoSuite)
        {
            // Check various input parameters
            if (claims == null)
                throw new ArgumentNullException("claims");

            if (claims.Count == 0)
                throw new ArgumentException("Provided ClaimSet must contain at least one claim");

            if (proofToken == null)
                throw new ArgumentNullException("proofToken");

            if (signatureToken == null)
                throw new ArgumentNullException("signatureToken");

            if (encryptionToken == null)
                throw new ArgumentNullException("encryptionToken");

            if (proofToken == null)
                throw new ArgumentNullException("proofToken");

            if (algoSuite == null)
                throw new ArgumentNullException("algoSuite");

            // Get signing key and a key identifier for same
            SecurityKey signatureKey = signatureToken.SecurityKeys[0];
            SecurityKeyIdentifierClause signatureSkic = signatureToken.CreateKeyIdentifierClause<X509ThumbprintKeyIdentifierClause>();
            SecurityKeyIdentifier signatureKeyIdentifier  = new SecurityKeyIdentifier(signatureSkic);

            // Get encryption key and a key identifier for same
            SecurityKey encryptionKey = encryptionToken.SecurityKeys[0];
            SecurityKeyIdentifierClause encryptionSkic = encryptionToken.CreateKeyIdentifierClause<X509ThumbprintKeyIdentifierClause>();
            SecurityKeyIdentifier encryptionKeyIdentifier = new SecurityKeyIdentifier(encryptionSkic);

            // Encrypt the proof key and create a key identifier for same
            byte[] proofKey = proofToken.GetKeyBytes();
            byte[] encryptedSecret = new byte[proofKey.Length];
            encryptedSecret = encryptionKey.EncryptKey(algoSuite.DefaultAsymmetricKeyWrapAlgorithm, proofKey);
            SecurityKeyIdentifier proofKeyIdentifier = new SecurityKeyIdentifier(new EncryptedKeyIdentifierClause(encryptedSecret, algoSuite.DefaultAsymmetricKeyWrapAlgorithm, encryptionKeyIdentifier));

            // Create the assertion
            return CreateAssertion(claims, signatureKey, signatureKeyIdentifier, proofKeyIdentifier, algoSuite);
        }
        protected virtual JwtSecurityToken CreateTokenFromClaims(IEnumerable<Claim> claims, string secretKey, string audience, string issuer)
        {
            var signingKey = this.GetSigningKey(secretKey);
            var signingToken = new BinarySecretSecurityToken(signingKey);
            var signingCredentials = new SigningCredentials(new InMemorySymmetricSecurityKey(signingToken.GetKeyBytes()), "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256", "http://www.w3.org/2001/04/xmlenc#sha256");
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                AppliesToAddress = audience,
                TokenIssuerName = issuer,
                SigningCredentials = signingCredentials,
                Lifetime = new Lifetime(DateTime.UtcNow, DateTime.UtcNow + TimeSpan.FromDays(1)),
                Subject = new ClaimsIdentity(claims),
            };

            var tokenHandler = new JwtSecurityTokenHandler();
            var token = tokenHandler.CreateToken(tokenDescriptor) as JwtSecurityToken;

            return token;
        }
		void WriteBinarySecretSecurityToken (XmlWriter w, BinarySecretSecurityToken token)
		{
			w.WriteStartElement ("t", "BinarySecret", Constants.WstNamespace);
			w.WriteAttributeString ("u", "Id", Constants.WsuNamespace, token.Id);
			w.WriteString (Convert.ToBase64String (token.GetKeyBytes ()));
			w.WriteEndElement ();
		}
        public static void WriteBinarySecretSecurityToken(XmlWriter writer, BinarySecretSecurityToken token, WSTrustConstantsAdapter trustConstants)
        {
            if (writer == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
            }

            if (token == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("token");
            }

            if (trustConstants == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("trustConstants");
            }

            byte[] keyBytes = token.GetKeyBytes();
            writer.WriteStartElement(trustConstants.Elements.BinarySecret, trustConstants.NamespaceURI);
            writer.WriteBase64(keyBytes, 0, keyBytes.Length);
            writer.WriteEndElement();
        }
        public static void WriteProtectedKey(XmlWriter writer, ProtectedKey protectedKey, WSTrustSerializationContext context, WSTrustConstantsAdapter trustConstants)
        {
            if (writer == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
            }

            if (protectedKey == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("protectedKey");
            }

            if (trustConstants == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("trustConstants");
            }

            if (protectedKey.WrappingCredentials != null)
            {
                byte[] encryptedKey = protectedKey.WrappingCredentials.SecurityKey.EncryptKey(protectedKey.WrappingCredentials.Algorithm, protectedKey.GetKeyBytes());
                EncryptedKeyIdentifierClause clause = new EncryptedKeyIdentifierClause(encryptedKey, protectedKey.WrappingCredentials.Algorithm, protectedKey.WrappingCredentials.SecurityKeyIdentifier);
                context.SecurityTokenHandlers.WriteKeyIdentifierClause(writer, clause);
            }
            else
            {
                BinarySecretSecurityToken entropyToken = new BinarySecretSecurityToken(protectedKey.GetKeyBytes());
                WriteBinarySecretSecurityToken(writer, entropyToken, trustConstants);
            }
        }
		public void CreateBinarySecretKeyIdentifierClause ()
		{
			byte [] bytes = new byte [32];
			SecurityToken wt = new BinarySecretSecurityToken (bytes);
			SecurityKeyIdentifierClause kic =
				new BinarySecretKeyIdentifierClause (bytes);
			WrappedKeySecurityToken token = new WrappedKeySecurityToken ("urn:gyabo",
				bytes, SecurityAlgorithms.Aes256KeyWrap, wt,
				new SecurityKeyIdentifier (kic));
			token.CreateKeyIdentifierClause<BinarySecretKeyIdentifierClause> ();
		}
		public void BinarySecretTokenForAsymmetricKeyWrap ()
		{
			byte [] bytes = new byte [32];
			SecurityToken wt = new BinarySecretSecurityToken (bytes);
			SecurityKeyIdentifierClause kic =
				new X509ThumbprintKeyIdentifierClause (cert);
			new WrappedKeySecurityToken ("urn:gyabo",
				bytes, SecurityAlgorithms.RsaOaepKeyWrap, wt,
				new SecurityKeyIdentifier (kic));
		}
        private SecurityTokenDescriptor GetTestSecurityTokenDescriptor(DateTime tokenLifetimeStart, DateTime tokenLifetimeEnd)
        {
            List<Claim> claims = new List<Claim>()
            {
                new Claim("uid", this.credentials.UserId),
                new Claim("ver", "2"),
            };

            byte[] signingKey = MobileAppTokenHandler.GetSigningKey(TestSecretKey);
            BinarySecretSecurityToken signingToken = new BinarySecretSecurityToken(signingKey);
            SigningCredentials signingCredentials = new SigningCredentials(new InMemorySymmetricSecurityKey(signingToken.GetKeyBytes()), "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256", "http://www.w3.org/2001/04/xmlenc#sha256");

            SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
            {
                AppliesToAddress = MobileAppTokenHandler.ZumoAudienceValue,
                TokenIssuerName = MobileAppTokenHandler.ZumoIssuerValue,
                SigningCredentials = signingCredentials,
                Lifetime = new Lifetime(tokenLifetimeStart, tokenLifetimeEnd),
                Subject = new ClaimsIdentity(claims),
            };
            return tokenDescriptor;
        }
        private String GenerateToken()
        {
            // este token no es muy bueno, revisar y mejorarlo
            // Create an array to store the key bytes keysize=1024
            byte[] key = new byte[1024 / 8];
            // Create some random bytes
            RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();
            random.GetNonZeroBytes(key);

            SecurityToken token = new BinarySecretSecurityToken(key);

            return token.Id;
        }
Example #13
0
 protected override SecurityKey GetSecurityKey(string notUsed)
 {
     // Because BinarySecretSecurityToken class is not marked as thread-safe, we'd better not cache it, but cache the raw cert bytes
     var binarySecurityToken = new BinarySecretSecurityToken(MsLiveKeyInBytes);
     return binarySecurityToken.SecurityKeys == null ? null : binarySecurityToken.SecurityKeys.First();
 }
        public void ValidateJsonWebToken(string tokenString, SsoSettings settings, IList<string> audiences)
        {
            try
            {
                TokenReceived = new JwtSecurityToken(tokenString);
                SecurityToken securityToken;
                _log.DebugFormat("JWT Validation securityAlgorithm={0}, audience[0]={1}, audience[1]={2}", settings.ValidationType, audiences[0], audiences[1]);

                switch(settings.ValidationType)
                {
                    case ValidationTypes.RSA_SHA256:
                        RSACryptoServiceProvider publicOnly = new RSACryptoServiceProvider();
                        //"<RSAKeyValue><Modulus>zeyPa4SwRb0IO+KMq20760ZmaUvy/qzecdOkRUNdNpdUe1E72Xt1WkAcWNu24/UeS3pETu08rVTqHJUMfhHcSKgL7LAk/MMj2inGFxop1LipGZSnqZhnjsfj1ERJL5eXs1O9hqyAcXvY4A2wo67qqv/lbHLKTW59W+YQkbIOVR4nQlbh1lK1TIY+oqK0J/5Ileb4QfERn0Rv/J/K0fy6VzLmVt+kg9MRNxYwnVsC3m5/kIu1fw3OpZxcaCC68SRqLLb/UXmaJM8NXYKkAkHKxT4DQqSk6KbFSQG6qi49Q34akohekzxjxmmGeoO5tsFCuMJofKAsBKKtOkLPaJD2rQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"
                        publicOnly.FromXmlString(settings.PublicKey);
                        securityToken = new RsaSecurityToken(publicOnly);
                        break;
                    case ValidationTypes.HMAC_SHA256:
                        //var key = "zeyPa4SwRb0IO+KMq20760ZmaUvy/qzecdOkRUNdNpdUe1E72Xu24/UeS3pETu";
                        securityToken = new BinarySecretSecurityToken(GetBytes(settings.PublicKey));
                        break;
                    case ValidationTypes.X509:
                        var certificate = new Certificate();
                        certificate.LoadCertificate(settings.PublicKey);
                        securityToken = new X509SecurityToken(certificate.cert);
                        break;
                    default:
                        _log.ErrorFormat("ValidationType has wrong value: {0}", settings.ValidationType);
                        throw new ArgumentException("ValidationType has wrong value");
                }

                TokenValidationParameters validationParameters = new TokenValidationParameters
                {
                    ValidIssuer = settings.Issuer,
                    AllowedAudiences = audiences,
                    ValidateIssuer = true,
                    SigningToken = securityToken
                };

                JwtSecurityTokenHandler recipientTokenHandler = new JwtSecurityTokenHandler
                {
                    MaxClockSkew = MAX_CLOCK_SKEW
                };
                ClaimsPrincipalReceived = recipientTokenHandler.ValidateToken(TokenReceived, validationParameters);
            }
            catch (Exception e)
            {
                _log.ErrorFormat("JWT Validation error. {0}", e);
            }
        }
        public static TokenInfo CreateTokenFromClaims(IEnumerable<Claim> claims, string secretKey, string audience, string issuer, TimeSpan? lifetime)
        {
            byte[] signingKey = GetSigningKey(secretKey);
            BinarySecretSecurityToken signingToken = new BinarySecretSecurityToken(signingKey);
            SigningCredentials signingCredentials = new SigningCredentials(new InMemorySymmetricSecurityKey(signingToken.GetKeyBytes()), "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256", "http://www.w3.org/2001/04/xmlenc#sha256");
            DateTime created = DateTime.UtcNow;

            // we allow for no expiry (if lifetime is null)
            DateTime? expiry = (lifetime != null) ? created + lifetime : null;

            SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
            {
                AppliesToAddress = audience,
                TokenIssuerName = issuer,
                SigningCredentials = signingCredentials,
                Lifetime = new Lifetime(created, expiry),
                Subject = new ClaimsIdentity(claims),
            };

            JwtSecurityTokenHandler securityTokenHandler = new JwtSecurityTokenHandler();
            JwtSecurityToken token = securityTokenHandler.CreateToken(tokenDescriptor) as JwtSecurityToken;

            return new TokenInfo { Token = token };
        }
Example #16
0
        /// <summary>
        /// Reads a wst:Entropy element and constructs a SecurityToken
        /// Assumes that the provided entropy is never more than 1Kb in size.
        /// </summary>
        /// <param name="xr">An XmlReader positioned on the start tag of wst:Entropy</param>
        /// <returns>A SecurityToken that contains the entropy value.</returns>
        private static SecurityToken ProcessEntropyElement(XmlReader xr)
        {
            // If provided XmlReader is null, throw an exception
            if (xr == null)
                throw new ArgumentNullException("xr");

            // If the wst:Entropy element is empty, then throw an exception.
            if (xr.IsEmptyElement)
                throw new ArgumentException("wst:Entropy element was empty. Unable to create SecurityToken object");

            // Store the initial depth so we can exit this function when we reach the corresponding end-tag            
            int initialDepth = xr.Depth;

            // Set our return value to null
            SecurityToken st = null;

            // Enter a read loop...
            while (xr.Read())
            {
                // Look for a non-empty wst:BinarySecret element
                if (Constants.Trust.Elements.BinarySecret == xr.LocalName &&
                         Constants.Trust.NamespaceUri == xr.NamespaceURI &&
                         !xr.IsEmptyElement &&
                         XmlNodeType.Element == xr.NodeType)
                {
                    // Allocate a 1024 byte buffer for the entropy
                    byte[] temp = new byte[1024];

                    // Move reader to content of wst:BinarySecret element...
                    xr.Read();

                    // ...and read that content as base64. Store the actual number of bytes we get.                    
                    int nBytes = xr.ReadContentAsBase64(temp, 0, temp.Length);

                    // Allocate a new array of the correct size to hold the provided entropy
                    byte[] entropy = new byte[nBytes];

                    // Copy the entropy from the temporary array into the new array.
                    for (int i = 0; i < nBytes; i++)
                        entropy[i] = temp[i];

                    // Create new BinarySecretSecurityToken from the provided entropy
                    st = new BinarySecretSecurityToken(entropy);
                }

                // Look for the end-tag that corresponds to the start-tag the reader was positioned 
                // on when the method was called. When we find it, break out of the read loop.
                if (Constants.Trust.Elements.Entropy == xr.LocalName &&
                    Constants.Trust.NamespaceUri == xr.NamespaceURI &&
                    xr.Depth == initialDepth &&
                    XmlNodeType.EndElement == xr.NodeType)
                    break;
            }

            return st;
        }
        /// <summary>
        /// Virtual method for ProcessRequestSecurityToken
        /// Should be overridden by STS implementations that derive from this base class
        /// </summary>
        public virtual Message ProcessRequestSecurityToken(Message message)
        {
            // Check for appropriate action header
            EnsureRequestSecurityTokenAction(message);

            // Extract the MessageID from the request message
            UniqueId requestMessageID = message.Headers.MessageId;
            if (requestMessageID == null)
                throw new InvalidOperationException("The request message does not have a message ID.");

            // Get the RST from the message
            RequestSecurityToken rst = RequestSecurityToken.CreateFrom(message.GetReaderAtBodyContents());

            // Set up the claims we are going to issue
            Collection<SamlAttribute> samlAttributes = GetIssuedClaims(rst);

            // get the key size, default to 192
            int keySize = (rst.KeySize != 0) ? rst.KeySize : 192;

            // Create proof token
            // Get requester entropy, if any
            byte[] senderEntropy = null;
            SecurityToken entropyToken = rst.RequestorEntropy;
            if (entropyToken != null)
            {
                senderEntropy = ((BinarySecretSecurityToken)entropyToken).GetKeyBytes();
            }

            byte[] key = null;
            byte[] stsEntropy = null;

            // If sender provided entropy, then use combined entropy
            if (senderEntropy != null)
            {
                // Create an array to store the entropy bytes
                stsEntropy = new byte[keySize / 8];
                // Create some random bytes
                RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();
                random.GetNonZeroBytes(stsEntropy);
                // Compute the combined key
                key = RequestSecurityTokenResponse.ComputeCombinedKey(senderEntropy, stsEntropy, keySize);
            }
            else // Issuer entropy only...
            {
                // Create an array to store the entropy bytes
                key = new byte[keySize / 8];
                // Create some random bytes
                RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();
                random.GetNonZeroBytes(key);
            }

            // Create a BinarySecretSecurityToken to be the proof token, based on the key material
            // in key. The key is the combined key in the combined entropy case, or the issuer entropy
            // otherwise
            BinarySecretSecurityToken proofToken = new BinarySecretSecurityToken(key);

            // Create a SAML token, valid for around 10 hours
            SamlSecurityToken samlToken = SamlTokenCreator.CreateSamlToken(this.stsName,
                                                                           proofToken,
                                                                           this.IssuerToken,
                                                                           this.ProofKeyEncryptionToken,
                                                                           new SamlConditions(DateTime.UtcNow - TimeSpan.FromMinutes(5), DateTime.UtcNow + TimeSpan.FromHours(10)),
                                                                           samlAttributes);

            // Set up RSTR
            RequestSecurityTokenBase rstr = GetRequestSecurityTokenResponse(rst, keySize, proofToken, samlToken, senderEntropy, stsEntropy);
            
            // Create a message from the RSTR
            Message rstrMessage = Message.CreateMessage(message.Version, Constants.Trust.Actions.IssueReply, rstr);
            
            // Set RelatesTo of response message to MessageID of request message
            rstrMessage.Headers.RelatesTo = requestMessageID;

            // Return the create message
            return rstrMessage;
        }
		public Message SecureMessage ()
		{
			secprop = Message.Properties.Security ?? new SecurityMessageProperty ();

			SecurityToken encToken =
				secprop.InitiatorToken != null ? secprop.InitiatorToken.SecurityToken : security.EncryptionToken;
			// FIXME: it might be still incorrect.
			SecurityToken signToken =
				Parameters == CounterParameters ? null :
				security.SigningToken;
			MessageProtectionOrder protectionOrder =
				security.MessageProtectionOrder;
			SecurityTokenSerializer serializer =
				security.TokenSerializer;
			SecurityBindingElement element =
				security.Element;
			SecurityAlgorithmSuite suite = element.DefaultAlgorithmSuite;

// FIXME: remove this hack
if (!ShouldOutputEncryptedKey)
	encToken = new BinarySecretSecurityToken (secprop.EncryptionKey);

			string messageId = "uuid-" + Guid.NewGuid ();
			int identForMessageId = 1;
			XmlDocument doc = new XmlDocument ();
			doc.PreserveWhitespace = true;

			UniqueId relatesTo = RelatesTo;
			if (relatesTo != null)
				msg.Headers.RelatesTo = relatesTo;
			else // FIXME: probably it is always added when it is stateful ?
				msg.Headers.MessageId = new UniqueId ("urn:" + messageId);

			// FIXME: get correct ReplyTo value
			if (Direction == MessageDirection.Input)
				msg.Headers.ReplyTo = new EndpointAddress (Constants.WsaAnonymousUri);

			if (MessageTo != null)
				msg.Headers.To = MessageTo.Uri;

			// wss:Security
			WSSecurityMessageHeader header =
				new WSSecurityMessageHeader (serializer);
			msg.Headers.Add (header);
			// 1. [Timestamp]
			if (element.IncludeTimestamp) {
				WsuTimestamp timestamp = new WsuTimestamp ();
				timestamp.Id = messageId + "-" + identForMessageId++;
				timestamp.Created = DateTime.Now;
				// FIXME: on service side, use element.LocalServiceSettings.TimestampValidityDuration
				timestamp.Expires = timestamp.Created.Add (element.LocalClientSettings.TimestampValidityDuration);
				header.AddContent (timestamp);
			}

			XmlNamespaceManager nsmgr = new XmlNamespaceManager (doc.NameTable);
			nsmgr.AddNamespace ("s", msg.Version.Envelope.Namespace);
			nsmgr.AddNamespace ("o", Constants.WssNamespace);
			nsmgr.AddNamespace ("u", Constants.WsuNamespace);
			nsmgr.AddNamespace ("o11", Constants.Wss11Namespace);

			/*WrappedKey*/SecurityToken primaryToken = null;
			DerivedKeySecurityToken dkeyToken = null;
			SecurityToken actualToken = null;
			SecurityKeyIdentifierClause actualClause = null;
			Signature sig = null;

			List<DerivedKeySecurityToken> derivedKeys =
				new List<DerivedKeySecurityToken> ();

			SymmetricAlgorithm masterKey = new RijndaelManaged ();
			masterKey.KeySize = suite.DefaultSymmetricKeyLength;
			masterKey.Mode = CipherMode.CBC;
			masterKey.Padding = PaddingMode.ISO10126;
			SymmetricAlgorithm actualKey = masterKey;

			// 2. [Encryption Token]

			// SecurityTokenInclusionMode
			// - Initiator or Recipient
			// - done or notyet. FIXME: not implemented yet
			// It also affects on key reference output

			bool includeEncToken = // /* FIXME: remove this hack */Parameters is SslSecurityTokenParameters ? false :
						ShouldIncludeToken (
				Security.RecipientParameters.InclusionMode, false);
			bool includeSigToken = // /* FIXME: remove this hack */ Parameters is SslSecurityTokenParameters ? false :
						ShouldIncludeToken (
				Security.InitiatorParameters.InclusionMode, false);

			SecurityKeyIdentifierClause encClause = ShouldOutputEncryptedKey ?
				CounterParameters.CallCreateKeyIdentifierClause (encToken, !ShouldOutputEncryptedKey ? SecurityTokenReferenceStyle.Internal : includeEncToken ? Parameters.ReferenceStyle : SecurityTokenReferenceStyle.External) : null;

			MessagePartSpecification sigSpec = SignaturePart;
			MessagePartSpecification encSpec = EncryptionPart;

			// encryption key (possibly also used for signing)
			// FIXME: get correct SymmetricAlgorithm according to the algorithm suite
			if (secprop.EncryptionKey != null)
				actualKey.Key = secprop.EncryptionKey;

// FIXME: remove thid hack
if (!ShouldOutputEncryptedKey)
primaryToken = RequestContext.RequestMessage.Properties.Security.ProtectionToken.SecurityToken as WrappedKeySecurityToken;
else
			primaryToken =
				// FIXME: remove this hack?
				encToken is SecurityContextSecurityToken ? encToken :
				new WrappedKeySecurityToken (messageId + "-" + identForMessageId++,
				actualKey.Key,
				// security.DefaultKeyWrapAlgorithm,
				Parameters.InternalHasAsymmetricKey ?
					suite.DefaultAsymmetricKeyWrapAlgorithm :
					suite.DefaultSymmetricKeyWrapAlgorithm,
				encToken,
				encClause != null ? new SecurityKeyIdentifier (encClause) : null);

			// If it reuses request's encryption key, do not output.
			if (ShouldOutputEncryptedKey)
				header.AddContent (primaryToken);

			actualToken = primaryToken;

			// FIXME: I doubt it is correct...
			WrappedKeySecurityToken requestEncKey = ShouldOutputEncryptedKey ? null : primaryToken as WrappedKeySecurityToken;
			actualClause = requestEncKey == null ? (SecurityKeyIdentifierClause)
				new LocalIdKeyIdentifierClause (actualToken.Id, typeof (WrappedKeySecurityToken)) :
				new InternalEncryptedKeyIdentifierClause (SHA1.Create ().ComputeHash (requestEncKey.GetWrappedKey ()));

			// generate derived key if needed
			if (CounterParameters.RequireDerivedKeys) {
				RijndaelManaged deriv = new RijndaelManaged ();
				deriv.KeySize = suite.DefaultEncryptionKeyDerivationLength;
				deriv.Mode = CipherMode.CBC;
				deriv.Padding = PaddingMode.ISO10126;
				deriv.GenerateKey ();
				dkeyToken = new DerivedKeySecurityToken (
					GenerateId (doc),
					null, // algorithm
					actualClause,
					new InMemorySymmetricSecurityKey (actualKey.Key),
					null, // name
					null, // generation
					null, // offset
					deriv.Key.Length,
					null, // label
					deriv.Key);
				derivedKeys.Add (dkeyToken);
				actualToken = dkeyToken;
				actualKey.Key = ((SymmetricSecurityKey) dkeyToken.SecurityKeys [0]).GetSymmetricKey ();
				actualClause = new LocalIdKeyIdentifierClause (dkeyToken.Id);
				header.AddContent (dkeyToken);
			}

			ReferenceList refList = new ReferenceList ();
			// When encrypted with DerivedKeyToken, put references
			// immediately after the derived token (not inside the
			// primary token).
			// Similarly, when we do not output EncryptedKey,
			// output ReferenceList in the same way.
			if (CounterParameters.RequireDerivedKeys ||
			    !ShouldOutputEncryptedKey)
				header.AddContent (refList);
			else
				((WrappedKeySecurityToken) primaryToken).ReferenceList = refList;

			// [Signature Confirmation]
			if (security.RequireSignatureConfirmation && secprop.ConfirmedSignatures.Count > 0)
				foreach (string value in secprop.ConfirmedSignatures)
					header.AddContent (new Wss11SignatureConfirmation (GenerateId (doc), value));

			SupportingTokenInfoCollection tokenInfos =
				Direction == MessageDirection.Input ?
				security.CollectSupportingTokens (GetAction ()) :
				new SupportingTokenInfoCollection (); // empty

			foreach (SupportingTokenInfo tinfo in tokenInfos)
				header.AddContent (tinfo.Token);

			// populate DOM to sign.
			XPathNavigator nav = doc.CreateNavigator ();
			using (XmlWriter w = nav.AppendChild ()) {
				msg.WriteMessage (w);
			}

			XmlElement body = doc.SelectSingleNode ("/s:Envelope/s:Body/*", nsmgr) as XmlElement;
			string bodyId = null;
			XmlElement secElem = null;
			Collection<WSSignedXml> endorsedSignatures =
				new Collection<WSSignedXml> ();
			bool signatureProtection = (protectionOrder == MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature);

			// Below are o:Security contents that are not signed...
			if (includeSigToken && signToken != null)
				header.AddContent (signToken);

			switch (protectionOrder) {
			case MessageProtectionOrder.EncryptBeforeSign:
				// FIXME: implement
				throw new NotImplementedException ();
			case MessageProtectionOrder.SignBeforeEncrypt:
			case MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature:

				// sign
				// see clause 8 of WS-SecurityPolicy C.2.2
				WSSignedXml sxml = new WSSignedXml (doc);
				SecurityTokenReferenceKeyInfo sigKeyInfo;

				sig = sxml.Signature;
				sig.SignedInfo.CanonicalizationMethod =
					suite.DefaultCanonicalizationAlgorithm;
				foreach (XmlElement elem in doc.SelectNodes ("/s:Envelope/s:Header/o:Security/u:Timestamp", nsmgr))
					CreateReference (sig, elem, elem.GetAttribute ("Id", Constants.WsuNamespace));
				foreach (XmlElement elem in doc.SelectNodes ("/s:Envelope/s:Header/o:Security/o11:SignatureConfirmation", nsmgr))
					CreateReference (sig, elem, elem.GetAttribute ("Id", Constants.WsuNamespace));
				foreach (SupportingTokenInfo tinfo in tokenInfos)
					if (tinfo.Mode != SecurityTokenAttachmentMode.Endorsing) {
						XmlElement el = sxml.GetIdElement (doc, tinfo.Token.Id);
						CreateReference (sig, el, el.GetAttribute ("Id", Constants.WsuNamespace));
					}
				XmlNodeList nodes = doc.SelectNodes ("/s:Envelope/s:Header/*", nsmgr);
				for (int i = 0; i < msg.Headers.Count; i++) {
					MessageHeaderInfo h = msg.Headers [i];
					if (h.Name == "Security" && h.Namespace == Constants.WssNamespace)
						secElem = nodes [i] as XmlElement;
					else if (sigSpec.HeaderTypes.Count == 0 ||
					    sigSpec.HeaderTypes.Contains (new XmlQualifiedName (h.Name, h.Namespace))) {
						string id = GenerateId (doc);
						h.Id = id;
						CreateReference (sig, nodes [i] as XmlElement, id);
					}
				}
				if (sigSpec.IsBodyIncluded) {
					bodyId = GenerateId (doc);
					CreateReference (sig, body.ParentNode as XmlElement, bodyId);
				}

				if (security.DefaultSignatureAlgorithm == SignedXml.XmlDsigHMACSHA1Url) {
					// FIXME: use appropriate hash algorithm
					sxml.ComputeSignature (new HMACSHA1 (actualKey.Key));
					sigKeyInfo = new SecurityTokenReferenceKeyInfo (actualClause, serializer, doc);
				}
				else {
					SecurityKeyIdentifierClause signClause =
						CounterParameters.CallCreateKeyIdentifierClause (signToken, includeSigToken ? CounterParameters.ReferenceStyle : SecurityTokenReferenceStyle.External);
					AsymmetricSecurityKey signKey = (AsymmetricSecurityKey) signToken.ResolveKeyIdentifierClause (signClause);
					sxml.SigningKey = signKey.GetAsymmetricAlgorithm (security.DefaultSignatureAlgorithm, true);
					sxml.ComputeSignature ();
					sigKeyInfo = new SecurityTokenReferenceKeyInfo (signClause, serializer, doc);
				}

				sxml.KeyInfo = new KeyInfo ();
				sxml.KeyInfo.AddClause (sigKeyInfo);

				if (!signatureProtection)
					header.AddContent (sig);

				// endorse the signature with (signed)endorsing
				// supporting tokens.

				foreach (SupportingTokenInfo tinfo in tokenInfos) {
					switch (tinfo.Mode) {
					case SecurityTokenAttachmentMode.Endorsing:
					case SecurityTokenAttachmentMode.SignedEndorsing:
						if (sxml.Signature.Id == null) {
							sig.Id = GenerateId (doc);
							secElem.AppendChild (sxml.GetXml ());
						}
						WSSignedXml ssxml = new WSSignedXml (doc);
						ssxml.Signature.SignedInfo.CanonicalizationMethod = suite.DefaultCanonicalizationAlgorithm;
						CreateReference (ssxml.Signature, doc, sig.Id);
						SecurityToken sst = tinfo.Token;
						SecurityKey ssk = sst.SecurityKeys [0]; // FIXME: could be different?
						SecurityKeyIdentifierClause tclause = new LocalIdKeyIdentifierClause (sst.Id); // FIXME: could be different?
						if (ssk is SymmetricSecurityKey) {
							SymmetricSecurityKey signKey = (SymmetricSecurityKey) ssk;
							ssxml.ComputeSignature (signKey.GetKeyedHashAlgorithm (suite.DefaultSymmetricSignatureAlgorithm));
						} else {
							AsymmetricSecurityKey signKey = (AsymmetricSecurityKey) ssk;
							ssxml.SigningKey = signKey.GetAsymmetricAlgorithm (suite.DefaultAsymmetricSignatureAlgorithm, true);
							ssxml.ComputeSignature ();
						}
						ssxml.KeyInfo.AddClause (new SecurityTokenReferenceKeyInfo (tclause, serializer, doc));
						if (!signatureProtection)
							header.AddContent (ssxml.Signature);
						endorsedSignatures.Add (ssxml);

						break;
					}
				}

				// encrypt

				WSEncryptedXml exml = new WSEncryptedXml (doc);

				EncryptedData edata = Encrypt (body, actualKey, actualToken.Id, refList, actualClause, exml, doc);
				EncryptedXml.ReplaceElement (body, edata, false);

				// encrypt signature
				if (signatureProtection) {
					XmlElement sigxml = sig.GetXml ();
					edata = Encrypt (sigxml, actualKey, actualToken.Id, refList, actualClause, exml, doc);
					header.AddContent (edata);

					foreach (WSSignedXml ssxml in endorsedSignatures) {
						sigxml = ssxml.GetXml ();
						edata = Encrypt (sigxml, actualKey, actualToken.Id, refList, actualClause, exml, doc);
						header.AddContent (edata);
					}

					if (security.RequireSignatureConfirmation) {
						Collection<Wss11SignatureConfirmation> confs = header.FindAll<Wss11SignatureConfirmation> ();
						int count = 0;
						foreach (XmlElement elem in doc.SelectNodes ("/s:Envelope/s:Header/o:Security/o11:SignatureConfirmation", nsmgr)) {
							edata = Encrypt (elem, actualKey, confs [count].Id, refList, actualClause, exml, doc);
							EncryptedXml.ReplaceElement (elem, edata, false);
							header.Contents.Insert (header.Contents.IndexOf (confs [count]), edata);
							header.Contents.Remove (confs [count++]);
						}
					}
				}

				// encrypt Encrypted supporting tokens
				foreach (SupportingTokenInfo tinfo in tokenInfos) {
					if (tinfo.Mode == SecurityTokenAttachmentMode.SignedEncrypted) {
						XmlElement el = exml.GetIdElement (doc, tinfo.Token.Id);
						tinfo.Encrypted = Encrypt (el, actualKey, actualToken.Id, refList, actualClause, exml, doc);
						EncryptedXml.ReplaceElement (el, tinfo.Encrypted, false);
						header.Contents.Insert (header.Contents.IndexOf (tinfo.Token), tinfo.Encrypted);
						header.Contents.Remove (tinfo.Token);
					}
				}
				break;
			}

			Message ret = new WSSecurityMessage (Message.CreateMessage (msg.Version, msg.Headers.Action, new XmlNodeReader (doc.SelectSingleNode ("/s:Envelope/s:Body/*", nsmgr) as XmlElement)), bodyId);
			ret.Properties.Security = (SecurityMessageProperty) secprop.CreateCopy ();
			ret.Properties.Security.EncryptionKey = masterKey.Key;

			// FIXME: can we support TransportToken here?
			if (element is AsymmetricSecurityBindingElement) {
				ret.Properties.Security.InitiatorToken = new SecurityTokenSpecification (encToken, null); // FIXME: second argument
				ret.Properties.Security.InitiatorToken = new SecurityTokenSpecification (signToken, null); // FIXME: second argument
			}
			else
				ret.Properties.Security.ProtectionToken = new SecurityTokenSpecification (primaryToken, null);

			ret.Headers.Clear ();
			ret.Headers.CopyHeadersFrom (msg);

			// Header contents are:
			//	- Timestamp
			//	- SignatureConfirmation if required
			//	- EncryptionToken if included
			//	- derived key token for EncryptionToken
			//	- ReferenceList for encrypted items
			//	- signed supporting tokens
			//	- signed endorsing supporting tokens
			//	(i.e. Signed/SignedEncrypted/SignedEndorsing)
			//	- Signature Token if different from enc token.
			//	- derived key token for sig token if different
			//	- Signature for:
			//		- Timestamp
			//		- supporting tokens (regardless of
			//		  its inclusion)
			//		- message parts in SignedParts
			//		- SignatureToken if TokenProtection
			//		  (regardless of its inclusion)
			//	- Signatures for the main signature (above),
			//	  for every endorsing token and signed
			//	  endorsing token.
			//	

//MessageBuffer zzz = ret.CreateBufferedCopy (100000);
//ret = zzz.CreateMessage ();
//Console.WriteLine (zzz.CreateMessage ());
			return ret;
		}
		public void WriteBinarySecretSecurityToken1 ()
		{
			StringWriter sw = new StringWriter ();
			byte [] bytes = new byte [] {0, 1, 2, 3, 4, 5, 6, 7};
			BinarySecretSecurityToken t = new BinarySecretSecurityToken ("urn:binary:1", bytes);
			using (XmlWriter w = XmlWriter.Create (sw, GetWriterSettings ())) {
				WSSecurityTokenSerializer.DefaultInstance.WriteToken (w, t);
			}
			// AAECAwQFBgc=
			string base64 = Convert.ToBase64String (bytes);
			Assert.AreEqual ("<t:BinarySecret u:Id=\"urn:binary:1\" xmlns:u=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:t=\"http://schemas.xmlsoap.org/ws/2005/02/trust\">" + base64 + "</t:BinarySecret>", sw.ToString ());
		}