//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ namespace System.IdentityModel.Tokens { using System; using System.IdentityModel.Configuration; using System.IdentityModel.Protocols.WSTrust; using RSTR = System.IdentityModel.Protocols.WSTrust.RequestSecurityTokenResponse; /// /// This class can be used for issuing the symmetric key based token. /// public class SymmetricProofDescriptor : ProofDescriptor { byte[] _key; int _keySizeInBits; byte[] _sourceEntropy; byte[] _targetEntropy; SecurityKeyIdentifier _ski; // // It is for encrypting the proof token or the entropy that can decrypted // by the token requestor // EncryptingCredentials _requestorWrappingCredentials; // // It is for encrypting the key materials inside the issued token that // can be decrypted by the relying party // EncryptingCredentials _targetWrappingCredentials; /// /// Use this constructor if you want the sts to use the given key bytes. /// This happens when client sends the entropy, and the sts would just use that /// as the key for the issued token. /// /// The symmetric key that are used inside the issued token. /// The key encrypting credentials for the relying party. /// When the key is null. public SymmetricProofDescriptor(byte[] key, EncryptingCredentials targetWrappingCredentials) { if (key == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("key"); } _keySizeInBits = key.Length; _key = key; _targetWrappingCredentials = targetWrappingCredentials; } /// /// Use this constructor if you want the sts to use the given . /// /// The to be used. public SymmetricProofDescriptor(EncryptingCredentials targetWrappingCredentials) : this(SecurityTokenServiceConfiguration.DefaultKeySizeInBitsConstant, targetWrappingCredentials) { } /// /// Use this constructor if you want to the sts to autogenerate key using random number generator and /// send it in the proof token as binary secret. /// /// The size of the symmetric key. /// The key encrypting credentials for the relying party. public SymmetricProofDescriptor(int keySizeInBits, EncryptingCredentials targetWrappingCredentials) : this(keySizeInBits, targetWrappingCredentials, null) { } /// /// Use this constructor to have the STS autogenerate a key and /// send it in the proof token as encrypted key. Two cases are covered here /// 1. client sends the entropy, but server rejects it /// 2. client did not send a entropy, so just use server's entropy /// /// the size of the symmetric key /// The key encrypting credentials for the relying party. /// The key encrypting credentials for the requestor. /// When keySizeInBits is less than or equal to zero. public SymmetricProofDescriptor(int keySizeInBits, EncryptingCredentials targetWrappingCredentials, EncryptingCredentials requestorWrappingCredentials) : this(keySizeInBits, targetWrappingCredentials, requestorWrappingCredentials, (string)null) { } /// /// Use this constructor to have the STS autogenerate a key and /// send it in the proof token as encrypted key. Two cases are covered here /// 1. client sends the entropy, but server rejects it /// 2. client did not send a entropy, so just use server's entropy /// /// the size of the symmetric key /// The key encrypting credentials for the relying party. /// The key encrypting credentials for the requestor. /// The a----thm specified in the EncryptWith element of the RST. /// When keySizeInBits is less than or equal to zero. /// If EncryptWith is a DES algorithm, the key is guaranteed not to be a weak DES key. public SymmetricProofDescriptor(int keySizeInBits, EncryptingCredentials targetWrappingCredentials, EncryptingCredentials requestorWrappingCredentials, string encryptWith) { _keySizeInBits = keySizeInBits; if (encryptWith == SecurityAlgorithms.DesEncryption || encryptWith == SecurityAlgorithms.TripleDesEncryption || encryptWith == SecurityAlgorithms.TripleDesKeyWrap) { _key = CryptoHelper.KeyGenerator.GenerateDESKey(_keySizeInBits); } else { _key = CryptoHelper.KeyGenerator.GenerateSymmetricKey(_keySizeInBits); } _requestorWrappingCredentials = requestorWrappingCredentials; _targetWrappingCredentials = targetWrappingCredentials; } /// /// Use this constructor if you want to send combined entropy. /// /// The size of the symmetric key. /// The encrypting credentials for the relying party used to encrypt the key in the SecurityKeyIdentifier property. /// The encrypting credentials for the requestor used to encrypt the entropy or the proof token. /// The requestor's entropy. /// When keySizeInBits is less than or equal to zero. /// When source entorpy is null or is an empty array. public SymmetricProofDescriptor(int keySizeInBits, EncryptingCredentials targetWrappingCredentials, EncryptingCredentials requestorWrappingCredentials, byte[] sourceEntropy) : this(keySizeInBits, targetWrappingCredentials, requestorWrappingCredentials, sourceEntropy, null) { } /// /// Use this constructor to send combined entropy. /// /// The size of the symmetric key. /// The encrypting credentials for the relying party used to encrypt the key in the SecurityKeyIdentifier property. /// The encrypting credentials for the requestor used to encrypt the entropy or the proof token. /// The requestor's entropy. /// The algorithm Uri using which to encrypt the proof key. /// When keySizeInBits is less than or equal to zero. /// When source entorpy is null or is an empty array. public SymmetricProofDescriptor(int keySizeInBits, EncryptingCredentials targetWrappingCredentials, EncryptingCredentials requestorWrappingCredentials, byte[] sourceEntropy, string encryptWith) { if (sourceEntropy == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sourceEntropy"); } if (sourceEntropy.Length == 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("sourceEntropy", SR.GetString(SR.ID2058)); } _keySizeInBits = keySizeInBits; _sourceEntropy = sourceEntropy; // // Generate proof key using sender entropy // if (encryptWith == SecurityAlgorithms.DesEncryption || encryptWith == SecurityAlgorithms.TripleDesEncryption || encryptWith == SecurityAlgorithms.TripleDesKeyWrap) { _key = CryptoHelper.KeyGenerator.GenerateDESKey(_keySizeInBits, _sourceEntropy, out _targetEntropy); } else { _key = CryptoHelper.KeyGenerator.GenerateSymmetricKey(_keySizeInBits, _sourceEntropy, out _targetEntropy); } // // Set up the wrapping credentials // _requestorWrappingCredentials = requestorWrappingCredentials; _targetWrappingCredentials = targetWrappingCredentials; } /// /// Gets the key bytes. /// public byte[] GetKeyBytes() { return _key; } /// /// Gets the requestor's encrypting credentials, which may be used to encrypt the /// requested proof token or the entropy in the response. /// protected EncryptingCredentials RequestorEncryptingCredentials { get { return _requestorWrappingCredentials; } } /// /// Gets the source entropy in plain bytes. /// protected byte[] GetSourceEntropy() { return _sourceEntropy; } /// /// Gets the target entropy in plain bytes. /// protected byte[] GetTargetEntropy() { return _targetEntropy; } /// /// Gets the relying party encrypting credentials, which may be used to encrypt the /// requested security token in the response. /// protected EncryptingCredentials TargetEncryptingCredentials { get { return _targetWrappingCredentials; } } #region ProofDescriptor Overrides /// /// Sets the appropriate things, such as requested proof token, inside the RSTR /// based on what is inside the proof descriptor instance. /// /// The RSTR object that this proof descriptor needs to modify. /// When the response is null. public override void ApplyTo(RSTR response) { if (response == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("response"); } if (_targetEntropy != null) { // // When there is target entropy, then we will send back a computedKeyalgorithm // in the proof token case and send the entropy as response.Entropy. By default, this // class is doing Psha1. // response.RequestedProofToken = new RequestedProofToken(ComputedKeyAlgorithms.Psha1); response.KeySizeInBits = _keySizeInBits; response.Entropy = new Entropy(_targetEntropy, _requestorWrappingCredentials); } else { // // When there is no target entroypy, then we will send back the key either in // binary secret format or in the encrypted key format // response.RequestedProofToken = new RequestedProofToken(_key, _requestorWrappingCredentials); } } /// /// Gets the key identifier that can be used inside issued to define the key. /// It is usually the binary secret or the encrypted key. /// public override SecurityKeyIdentifier KeyIdentifier { get { if (_ski == null) { _ski = CryptoHelper.KeyGenerator.GetSecurityKeyIdentifier(_key, _targetWrappingCredentials); } return _ski; } } #endregion } }