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; }
/// <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); }
/// <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; }
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 }; }
/// <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 ()); }