// This method determines the security token that contains the key material that // the STS should encrypt a session key with in order // for the service the issued token is intended for to be able to extract that session key private SecurityToken GetEncryptingToken(Gudge.Samples.Security.RSTRSTR.RequestSecurityToken rst) { // If rst is null, we're toast if (rst == null) { throw new ArgumentNullException("rst"); } // Set encryptingToken to null SecurityToken encryptingToken = null; // ... Open the LocalMachine store in My for read-only access X509Store store = new X509Store(StoreName.TrustedPeople, StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly); // Find the "localhost" cert ... foreach (X509Certificate2 cert in store.Certificates) { if (cert.SubjectName.Name == "CN=RPKey") { // ... and set encryptingToken to that cert encryptingToken = new X509SecurityToken(cert); break; } } // Don't forget to close the store store.Close(); // return the token return(encryptingToken); }
private byte[] GetSessionKey(Gudge.Samples.Security.RSTRSTR.RequestSecurityToken rst, Gudge.Samples.Security.RSTRSTR.RequestSecurityTokenResponse rstr) { // If rst is null, we're toast if (rst == null) { throw new ArgumentNullException("rst"); } // If rstr is null, we're toast if (rstr == null) { throw new ArgumentNullException("rstr"); } // Figure out the keySize int keySize = 256; if (rst.KeySize != 0) { keySize = rst.KeySize; } Console.WriteLine("Proof key size {0}", keySize); // Figure out whether we're using Combined or Issuer entropy. byte[] sessionKey = null; byte[] senderEntropy = GetSenderEntropy(rst); byte[] issuerEntropy = GetIssuerEntropy(keySize); RNGCryptoServiceProvider random = new RNGCryptoServiceProvider(); if (senderEntropy != null) { // Combined entropy Console.WriteLine("Combined Entropy"); sessionKey = rstr.ComputeCombinedKey(senderEntropy, issuerEntropy, keySize); rstr.IssuerEntropy = new BinarySecretSecurityToken(issuerEntropy); rstr.ComputeKey = true; } else { // Issuer-only entropy Console.WriteLine("Issuer-only entropy"); sessionKey = issuerEntropy; rstr.RequestedProofToken = new BinarySecretSecurityToken(sessionKey); } rstr.KeySize = keySize; return(sessionKey); }
// This method determines the token type for the service the issued token is intended for. private string GetTokenType(Gudge.Samples.Security.RSTRSTR.RequestSecurityToken rst) { // If rst is null, we're toast if (rst == null) { throw new ArgumentNullException("rst"); } // Set tokenType to null string tokenType = null; // If there is no service URI or we don't have a tokenType registered for that service URI... tokenType = rst.TokenType; // return the tokenType return(tokenType); }
public Message Issue(Message request) { try { Console.WriteLine("Call to IWSTrust::Issue"); // if request is null, we're toast if (request == null) { throw new ArgumentNullException("request"); } // Create an RST object from the request message Gudge.Samples.Security.RSTRSTR.RequestSecurityToken rst = Gudge.Samples.Security.RSTRSTR.RequestSecurityToken.CreateFrom(request.GetReaderAtBodyContents()); // Check that is really is an Issue request if (rst.RequestType == null || rst.RequestType != Constants.Trust.RequestTypes.Issue) { throw new InvalidOperationException(rst.RequestType); } // Create an RSTR object Gudge.Samples.Security.RSTRSTR.RequestSecurityTokenResponse rstr = Issue(rst); // Create response message Message response = Message.CreateMessage(request.Version, Constants.Trust.Actions.IssueReply, rstr); // Set RelatesTo of response to message id of request response.Headers.RelatesTo = request.Headers.MessageId; // Address response to ReplyTo of request request.Headers.ReplyTo.ApplyTo(response); return(response); } catch (Exception e) { Console.WriteLine("**** Exception thrown while processing Issue request:"); Console.WriteLine(e.Message); throw; } }
private byte[] GetSenderEntropy(Gudge.Samples.Security.RSTRSTR.RequestSecurityToken rst) { // If rst is null, we're toast if (rst == null) { throw new ArgumentNullException("rst"); } SecurityToken senderEntropyToken = rst.RequestorEntropy; byte[] senderEntropy = null; if (senderEntropyToken != null) { BinarySecretSecurityToken bsst = senderEntropyToken as BinarySecretSecurityToken; if (bsst != null) { senderEntropy = bsst.GetKeyBytes(); } } return(senderEntropy); }
// private methods private Gudge.Samples.Security.RSTRSTR.RequestSecurityTokenResponse Issue(Gudge.Samples.Security.RSTRSTR.RequestSecurityToken rst) { // If rst is null, we're toast if (rst == null) { throw new ArgumentNullException("rst"); } // Create an RSTR object Gudge.Samples.Security.RSTRSTR.RequestSecurityTokenResponse rstr = new Gudge.Samples.Security.RSTRSTR.RequestSecurityTokenResponse(); // Figure out the token type being requested string tokenType = GetTokenType(rst); Console.WriteLine("Issue: Request for token type {0}", tokenType); // Figure out which key we're going to sign the token with... SecurityKey signingKey = GetSigningKey(); SecurityKeyIdentifier signingKeyIdentifier = GetSigningKeyIdentifier(); SecurityKeyIdentifier proofKeyIdentifier = null; if (rst.IsProofKeyAsymmetric()) { Console.WriteLine("Retrieving Asymmetric Proof Key"); // Asymmetric proof key proofKeyIdentifier = GetAsymmetricProofKey(rst); } else { // Symmetric proof key Console.WriteLine("Constructing Symmetric Proof Key"); // Construct session key. This is the symmetric key that the client and the service will share. // It actually appears twice in the response message; once for the service and // once for the client. In the former case, it is typically embedded in the issued token, // in the latter case, it is returned in a wst:RequestedProofToken element. byte[] sessionKey = GetSessionKey(rst, rstr); // Get token to use when encrypting key material for the service SecurityToken encryptingToken = GetEncryptingToken(rst); // Encrypt the session key for the service byte[] encryptedKey = GetEncryptedKey(encryptingToken, sessionKey, out proofKeyIdentifier); } // Issued tokens are valid for 12 hours by default DateTime effectiveTime = DateTime.Now; DateTime expirationTime = DateTime.Now + new TimeSpan(12, 0, 0); SecurityToken st = null; switch (tokenType) { case "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1": st = CreateSAMLToken(effectiveTime, expirationTime, signingKey, signingKeyIdentifier, proofKeyIdentifier, rst.ClaimRequirements); break; default: throw new Exception("Unsupported Token Type"); } rstr.RequestedSecurityToken = st; rstr.Context = rst.Context; rstr.TokenType = tokenType; rstr.RequestedAttachedReference = GetInternalSecurityKeyIdentifier(st)[0]; rstr.RequestedUnattachedReference = GetExternalSecurityKeyIdentifier(st)[0]; return(rstr); }
private SecurityKeyIdentifier GetAsymmetricProofKey(Gudge.Samples.Security.RSTRSTR.RequestSecurityToken rst) { return(GetInternalSecurityKeyIdentifier(rst.ProofKey)); }