/// <summary> /// calculate the signature of the sastoken /// </summary> public static string CalcSignature(this ISasTokenParameters token, string sharedSecret, bool useNonce, HashType hashType, IEnumerable <string> additionalKeys) { // to be safe, the sharedsecret should contain at least 20 characters. // this also limits the number of erroneous switch of the key name and shared secret var keyPolicyCheck = ValidateSigningKeyPolicies(sharedSecret); if (!keyPolicyCheck.Success) { throw new ArgumentOutOfRangeException(nameof(sharedSecret), keyPolicyCheck.TokenResponseCode.ToString()); } var stringToSign = WebUtility.UrlEncode(token.SharedResource) + "\n"; if (additionalKeys != null) { foreach (var key in additionalKeys) { var kvp = token.AdditionalValues.FirstOrDefault(q => q.Key == key); if (kvp.Key == null) { throw new ArgumentException($"Value is missing : {key}"); } stringToSign += $"{kvp.Key}={WebUtility.UrlEncode(kvp.Value)}\n"; } } if (useNonce) { stringToSign += $"{WebUtility.UrlEncode(token.Nonce)}\n"; } stringToSign += token.Expiry; return(CalculateHash(sharedSecret, hashType, stringToSign)); }
/// <summary> /// returns a string representation of this token for use in a URL /// </summary> public static string ToQueryString(this ISasTokenParameters token) { var components = new List <string>(); if (!string.IsNullOrEmpty(token.SharedResource)) { components.Add($"sr={WebUtility.UrlEncode(token.SharedResource)}"); } if (!string.IsNullOrEmpty(token.Signature)) { components.Add($"sig={WebUtility.UrlEncode(token.Signature)}"); } if (token.Expiry > 0) { components.Add($"se={token.Expiry}"); } if (!string.IsNullOrEmpty(token.Nonce)) { components.Add($"nonce={WebUtility.UrlEncode(token.Nonce)}"); } if (!string.IsNullOrEmpty(token.SigningKeyName)) { components.Add($"skn={WebUtility.UrlEncode(token.SigningKeyName)}"); } if (token.AdditionalValues != null) { foreach (var kvp in token.AdditionalValues) { components.Add($"{kvp.Key}={WebUtility.UrlEncode(kvp.Value)}"); } } return(string.Join("&", components)); }
public ISasTokenValidationResult Validate(ISasTokenParameters token, bool ignoreTimeOut) { if (!policies.ContainsKey(token.SigningKeyName)) { return(new SasTokenValidationResult(false, token.SharedResource, TokenResponseCode.PolicyFailed)); } var p = policies[token.SigningKeyName]; return(ExecuteValidation(token, p.Key, p.UseNonce, p.HashType, p.AdditionalKeys, ignoreTimeOut)); }
/// <summary> /// calculate the signature of the sastoken /// </summary> public static string CalcSignature(this ISasTokenParameters token, string sharedSecret, bool useNonce, HashType hashType) { return(CalcSignature(token, sharedSecret, useNonce, hashType, null)); }
/// <summary> /// Validate a token using the provided secret and hashtype /// </summary> /// <param name="token">Token to be validated</param> /// <param name="sharedSecret">The passphrase used to create the token's signature</param> /// <param name="useNonce">If true, the nonce is checked against previous validations, preventing resends</param> /// <param name="hashType">The hashing type used to generate the signature</param> /// <param name="additionalKeys">If true, the signature expects additional keys from the token</param> /// <param name="ignoreTimeOut">if true, ignore the timestamp when validating.</param> /// <returns></returns> private ISasTokenValidationResult ExecuteValidation( ISasTokenParameters token, string sharedSecret, bool useNonce, HashType hashType, IEnumerable <string> additionalKeys, bool ignoreTimeOut) { if (string.IsNullOrEmpty(sharedSecret)) { return new SasTokenValidationResult { Success = false, TokenResponseCode = TokenResponseCode.InvalidSigningKey } } ; var epochCurrent = DateTime.UtcNow - new DateTime(1970, 1, 1); var expiryTest = (int)epochCurrent.TotalSeconds; if (!ignoreTimeOut && token.Expiry < expiryTest) { return new SasTokenValidationResult { TokenResponseCode = TokenResponseCode.TokenExpired, Success = false } } ; if (useNonce && _memoryCache != null) { if (string.IsNullOrEmpty(token.Nonce)) { return new SasTokenValidationResult { TokenResponseCode = TokenResponseCode.NonceIsRequired, Success = false } } ; if (TryGetValueFromcache(token.Nonce)) { return new SasTokenValidationResult { TokenResponseCode = TokenResponseCode.ResendNotAllowed, Success = false } } ; SetInCache(token.Nonce); } var validateSignature = token.CalcSignature(sharedSecret, useNonce, hashType, additionalKeys); if (token.Signature != validateSignature) { return new SasTokenValidationResult { TokenResponseCode = TokenResponseCode.TokenTampered, Success = false } } ; return(new SasTokenValidationResult { TokenResponseCode = TokenResponseCode.TokenAccepted, Resource = token.SharedResource, Success = true }); }
public ISasTokenValidationResult Validate(ISasTokenParameters token) { return(Validate(token, false)); }