/// <summary> /// Decode the given <paramref name="hexEncodedValue"/>. /// </summary> /// <param name="hexEncodedValue">The hex-encoded <see cref="string"/>.</param> /// <param name="signatureHeaderName"> /// The name of the HTTP header containing the <paramref name="hexEncodedValue"/>. /// </param> /// <param name="errorResult"> /// Set to <see langword="null"/> if decoding is successful. Otherwise, an <see cref="IActionResult"/> that /// when executed will produce a response containing details about the problem. /// </param> /// <returns> /// If successful, the <see cref="byte"/> array containing the decoded hash. <see langword="null"/> if any /// issues occur. /// </returns> protected virtual byte[] GetDecodedHash( string hexEncodedValue, string signatureHeaderName, out IActionResult errorResult) { try { var decodedHash = EncodingUtilities.FromHex(hexEncodedValue); errorResult = null; return(decodedHash); } catch (Exception ex) { Logger.LogError( 401, ex, "The '{HeaderName}' header value is invalid. It must be a valid hex-encoded string.", signatureHeaderName); } var message = string.Format( CultureInfo.CurrentCulture, Resources.Security_BadHeaderEncoding, signatureHeaderName); errorResult = WebHookResultUtilities.CreateErrorResult(message); return(null); }
internal static string GetHtmlEncodedInternal(string key, Strings.IDs localizedID) { Dictionary <uint, string> dictionary = null; object obj = LocalizedStrings.htmlEncodedStringsCollection[key]; if (obj == null) { lock (LocalizedStrings.htmlEncodedStringsCollection) { if (LocalizedStrings.htmlEncodedStringsCollection[key] == null) { Strings.IDs[] array = (Strings.IDs[])Enum.GetValues(typeof(Strings.IDs)); dictionary = new Dictionary <uint, string>(array.Length); for (int i = 0; i < array.Length; i++) { dictionary[array[i]] = EncodingUtilities.HtmlEncode(Strings.GetLocalizedString(array[i])); } LocalizedStrings.htmlEncodedStringsCollection[key] = dictionary; } else { dictionary = (Dictionary <uint, string>)LocalizedStrings.htmlEncodedStringsCollection[key]; } goto IL_A9; } } dictionary = (Dictionary <uint, string>)obj; IL_A9: return(dictionary[localizedID]); }
public void ProjectFileWithoutBomDoesNotContainsBomAfterSave() { string content = ObjectModelHelpers.CleanupFileContents(@"<Project><Target Name=""Build""/></Project>"); var file = FileUtilities.GetTemporaryFile(".proj"); try { File.WriteAllText(file, content, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); Assert.False(EncodingUtilities.FileStartsWithPreamble(file)); // Load and manipulate/save the project var project = new Project(ProjectRootElement.Open(file, ProjectCollection.GlobalProjectCollection)); project.AddItem("Compile", "Program.cs"); project.Save(); // Ensure the file was really saved and that the file still contains a BOM Assert.Contains("<Compile Include=\"Program.cs\" />", File.ReadAllText(file)); Assert.False(EncodingUtilities.FileStartsWithPreamble(file)); } finally { FileUtilities.DeleteDirectoryNoThrow(Path.GetDirectoryName(file), false); } }
// Token: 0x0600004F RID: 79 RVA: 0x000032BC File Offset: 0x000014BC protected void RenderIdentity() { base.Response.Output.Write("<input type=hidden name=\""); base.Response.Output.Write("hidpid"); base.Response.Output.Write("\" value=\""); EncodingUtilities.HtmlEncode(this.Identity, base.Response.Output); base.Response.Output.Write("\">"); }
/// <summary> /// Returns the event data for this <paramref name="notificationId"/> from the authenticated source so that we /// know that it is valid. /// </summary> /// <param name="request">The incoming <see cref="HttpRequest">.</see></param> /// <param name="routeData">The <see cref="RouteData"/> for the <paramref name="request"/>.</param> /// <param name="notificationId">The notification identifier from the <paramref name="request"/> body.</param> /// <returns> /// A <see cref="Task{JObject}"/> that on completion provides a <see cref="JObject"/> containing event data for /// this <paramref name="notificationId"/>. /// </returns> protected virtual async Task <JObject> GetEventDataAsync( HttpRequest request, RouteData routeData, string notificationId) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (routeData == null) { throw new ArgumentNullException(nameof(routeData)); } if (notificationId == null) { throw new ArgumentNullException(nameof(notificationId)); } // Create HTTP request for requesting authoritative event data from Stripe var secretKey = await GetReceiverConfig( request, routeData, ReceiverName, StripeConstants.SecretKeyMinLength, StripeConstants.SecretKeyMaxLength); var address = string.Format( CultureInfo.InvariantCulture, StripeConstants.EventUriTemplate, notificationId); var outgoing = new HttpRequestMessage(HttpMethod.Get, address); var challenge = Encoding.UTF8.GetBytes(secretKey + ":"); outgoing.Headers.Authorization = new AuthenticationHeaderValue( "Basic", EncodingUtilities.ToBase64(challenge, uriSafe: false)); using (var response = await _httpClient.SendAsync(outgoing)) { if (!response.IsSuccessStatusCode) { Logger.LogError( 3, "The notification identifier '{NotificationId}' could not be resolved for an actual event. " + "Callback failed with status code {StatusCode}", notificationId, response.StatusCode); return(null); } var responseStream = await response.Content.ReadAsStreamAsync(); var result = await JObject.LoadAsync(new JsonTextReader(new StreamReader(responseStream))); return(result); } }
public void ToHex_FromHex_Roundtrips_UriSafe(string input) { byte[] data = Encoding.UTF8.GetBytes(input); string encoded = EncodingUtilities.ToHex(data); byte[] output = EncodingUtilities.FromHex(encoded); string actual = Encoding.UTF8.GetString(output); Assert.Equal(input, actual); }
private static void Base64RoundTrip(string input, bool uriSafe) { byte[] data = Encoding.UTF8.GetBytes(input); string encoded = EncodingUtilities.ToBase64(data, uriSafe); byte[] output = EncodingUtilities.FromBase64(encoded); string actual = Encoding.UTF8.GetString(output); Assert.Equal(input, actual); }
public void CanEncodeTest() { var defaultEncoding = EncodingUtilities.CurrentSystemOemEncoding; string nonAnsiCharacters = "\u521B\u5EFA"; string pathWithAnsiCharacters = @"c:\windows\system32\cmd.exe"; Assert.False(EncodingUtilities.CanEncodeString(defaultEncoding.CodePage, nonAnsiCharacters)); Assert.True(EncodingUtilities.CanEncodeString(defaultEncoding.CodePage, pathWithAnsiCharacters)); }
private async Task <HttpResponseMessage> VerifyContentDistribution(WebSubSubscription subscription, HttpRequestMessage request) { if (subscription.State != WebSubSubscriptionState.SubscribeValidated) { return(request.CreateResponse(HttpStatusCode.NotFound)); } if (String.IsNullOrWhiteSpace(subscription.Secret)) { return(null); } string signatureHeader; try { signatureHeader = GetRequestHeader(request, SIGNATURE_HEADER_NAME); } catch (HttpResponseException) { return(HandleInvalidSignatureHeader(request)); } string[] tokens = signatureHeader.SplitAndTrim('='); if (tokens.Length != 2) { return(HandleInvalidSignatureHeader(request)); } byte[] signatureHeaderExpectedHash; try { signatureHeaderExpectedHash = EncodingUtilities.FromHex(tokens[1]); } catch (Exception) { return(HandleBadRequest(request, $"The '{SIGNATURE_HEADER_NAME}' header value is invalid. The '{RECEIVER_NAME}' WebHook receiver requires a valid hex-encoded string.")); } byte[] payloadActualHash = await ComputeRequestBodyHashAsync(request, tokens[0], Encoding.UTF8.GetBytes(subscription.Secret)); if (payloadActualHash == null) { return(HandleInvalidSignatureHeader(request)); } if (!SecretEqual(signatureHeaderExpectedHash, payloadActualHash)) { return(HandleBadRequest(request, $"The signature provided by the '{SIGNATURE_HEADER_NAME}' header field does not match the value expected by the '{RECEIVER_NAME}' WebHook receiver. WebHook request is invalid.")); } return(null); }
public void ToHex_ConvertsCorrectly(string input) { // Arrange byte[] bytes = Encoding.UTF8.GetBytes(input); string expected = ToExpectedHex(bytes); // Act string actual = EncodingUtilities.ToHex(bytes); // Assert Assert.Equal(expected, actual); }
public LoadingScreen(String title, String message, EncodingUtilities encodingUtilities) { InitializeComponent(); progressValue = 0; setStatusMessage(message); currentMessage = message; Title = title; Show(); this.encodingUtilities = encodingUtilities; }
/// <summary> /// Verifies that the signature header matches that of the actual body. /// </summary> protected virtual async Task <bool> VerifySignature(string name, HttpContext context) { string secretKey = _options.GetReceiverConfig(name); // Get the expected hash from the signature header string header = context.Request.Headers[SignatureHeaderName]; string[] values = header.Split('='); if (values.Length != 2 || !string.Equals(values[0], SignatureHeaderKey, StringComparison.OrdinalIgnoreCase)) { string msg = string.Format(CustomReceiverResource.Receiver_BadHeaderValue, SignatureHeaderName, SignatureHeaderKey, "<value>"); context.Response.StatusCode = StatusCodes.Status400BadRequest; await context.Response.WriteAsync(msg); return(false); } byte[] expectedHash; try { expectedHash = EncodingUtilities.FromHex(values[1]); } catch (Exception) { string msg = string.Format(CustomReceiverResource.Receiver_BadHeaderEncoding, SignatureHeaderName); context.Response.StatusCode = StatusCodes.Status400BadRequest; await context.Response.WriteAsync(msg); return(false); } // Compute the actual hash of the request body byte[] actualHash; byte[] secret = Encoding.UTF8.GetBytes(secretKey); using (var hasher = new HMACSHA256(secret)) { byte[] data = await ReadAsByteArrayAsync(context.Request); actualHash = hasher.ComputeHash(data); } // Now verify that the actual hash matches the expected hash. if (!WebHookReceiver.SecretEqual(expectedHash, actualHash)) { context.Response.StatusCode = StatusCodes.Status400BadRequest; await context.Response.WriteAsync("Bad Signature"); return(false); } return(true); }
public void FromHex_ConvertsCorrectly(string input) { // Arrange byte[] expected = Encoding.UTF8.GetBytes(input); string data1 = ToExpectedHex(expected).ToUpperInvariant(); string data2 = ToExpectedHex(expected).ToLowerInvariant(); // Act byte[] actual1 = EncodingUtilities.FromHex(data1); byte[] actual2 = EncodingUtilities.FromHex(data2); // Assert Assert.Equal(expected, actual1); Assert.Equal(expected, actual2); }
/// <summary> /// Verifies that the signature header matches that of the actual body. /// </summary> protected virtual async Task VerifySignature(string id, HttpRequestMessage request) { string secretKey = await GetReceiverConfig(request, Name, id, SecretMinLength, SecretMaxLength); // Get the expected hash from the signature header string header = GetRequestHeader(request, SignatureHeaderName); string[] values = header.SplitAndTrim('='); if (values.Length != 2 || !string.Equals(values[0], SignatureHeaderKey, StringComparison.OrdinalIgnoreCase)) { string msg = string.Format(CultureInfo.CurrentCulture, FacebookReceiverResources.Receiver_BadHeaderValue, SignatureHeaderName, SignatureHeaderKey, "<value>"); request.GetConfiguration().DependencyResolver.GetLogger().Error(msg); HttpResponseMessage invalidHeader = request.CreateErrorResponse(HttpStatusCode.BadRequest, msg); throw new HttpResponseException(invalidHeader); } byte[] expectedHash; var headerHash = values[1]; try { expectedHash = EncodingUtilities.FromHex(headerHash); } catch (Exception ex) { string msg = string.Format(CultureInfo.CurrentCulture, FacebookReceiverResources.Receiver_BadHeaderEncoding, SignatureHeaderName); request.GetConfiguration().DependencyResolver.GetLogger().Error(msg, ex); HttpResponseMessage invalidEncoding = request.CreateErrorResponse(HttpStatusCode.BadRequest, msg); throw new HttpResponseException(invalidEncoding); } // Get the actual hash of the request body byte[] actualHash; byte[] secret = Encoding.UTF8.GetBytes(secretKey); using (var hasher = new HMACSHA1(secret)) { var payload = EncodeNonAsciiCharacters(await request.Content.ReadAsStringAsync()); var data = Encoding.UTF8.GetBytes(payload); actualHash = hasher.ComputeHash(data); } // Now verify that the provided hash matches the expected hash. if (!string.Equals(headerHash, ByteArrayToString(actualHash), StringComparison.CurrentCultureIgnoreCase)) { var badSignature = CreateBadSignatureResponse(request, SignatureHeaderName); throw new HttpResponseException(badSignature); } }
public void EncodingUtilitiesTest() { var data = EncodingUtilities.StringToByteArray("test", "utf-8"); Assert.AreEqual("test", EncodingUtilities.ByteArrayToString(data, "utf-8")); data = EncodingUtilities.StringToByteArray("test", "ascii"); Assert.AreEqual("test", EncodingUtilities.ByteArrayToString(data, "ascii")); data = EncodingUtilities.StringToByteArray("test", "utf-16"); Assert.AreEqual("test", EncodingUtilities.ByteArrayToString(data, "utf-16")); Assert.ThrowsException <Exception>(() => { EncodingUtilities.StringToByteArray("test", null); }); Assert.ThrowsException <Exception>(() => { EncodingUtilities.StringToByteArray("test", "utf16"); }); Assert.ThrowsException <Exception>(() => { EncodingUtilities.StringToByteArray("test", "u"); }); }
private static void CreateProjectAndAssertEncoding(bool xmlDeclaration, bool byteOrderMark) { string declaration = @"<?xml version=""1.0"" encoding=""utf-8""?>"; string content = xmlDeclaration ? declaration : string.Empty; content += @"<Project><Target Name=""Build""/></Project>"; content = ObjectModelHelpers.CleanupFileContents(content); var file = FileUtilities.GetTemporaryFile(".proj"); try { File.WriteAllText(file, content, new UTF8Encoding(encoderShouldEmitUTF8Identifier: byteOrderMark)); Assert.Equal(byteOrderMark, EncodingUtilities.FileStartsWithPreamble(file)); // Load and manipulate/save the project var project = new Project(ProjectRootElement.Open(file, ProjectCollection.GlobalProjectCollection)); project.AddItem("Compile", "Program.cs"); project.Save(); // Ensure the file was really saved and that the presence of a BOM has not changed string actualContents = File.ReadAllText(file); Assert.Contains("<Compile Include=\"Program.cs\" />", actualContents); if (xmlDeclaration) { Assert.Contains(declaration, actualContents); } else { Assert.DoesNotContain(declaration, actualContents); } Assert.Equal(byteOrderMark, EncodingUtilities.FileStartsWithPreamble(file)); } finally { FileUtilities.DeleteDirectoryNoThrow(Path.GetDirectoryName(file), false); } }
public IActionResult Token(AuthRequest authRequest) { using (var session = _manager.OpenSession()) { var success = IdentityHelper.SignIn(authRequest.Username, authRequest.Password, false); ActionResult response = new EmptyResult(); if (success == true) { var userInfo = IdentityHelper.GetApplicationUserByName(authRequest.Username); var claims = userInfo.Permissions.Select(p => new Claim(Model.ClaimTypes.Permission, p.Name)).ToList(); claims.Add(new Claim(ClaimTypes.Name, userInfo.UserName)); if (!string.IsNullOrWhiteSpace(userInfo.Email)) { claims.Add(new Claim(Model.ClaimTypes.Email, userInfo.Email)); } var userRoles = userInfo.Roles.Select(r => new Claim(ClaimTypes.Role, r.Name)); claims.AddRange(userRoles); var key = EncodingUtilities.StringToByteArray(_jwtKey, "ascii"); var signingCredential = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature); var tokenDescriptor = new JwtSecurityToken(null, null, claims, expires: _jwtExpirationTime, signingCredentials: signingCredential); var token = new JwtSecurityTokenHandler().WriteToken(tokenDescriptor); var result = new { idToken = token, expiresIn = tokenDescriptor.ValidTo, }; response = Ok(result); } _manager.CloseSession(); return(response); } }
private SingleDeviceTestSuiteRun ConvertFromSingleDeviceDTO(NUnitDeviceTestRunDTO testRunDTO, DeviceTestSuiteCollectionRun deviceTestSuiteCollectionRun) { var base64 = testRunDTO.NUnitXmlBase64; string nunitXml = EncodingUtilities.DecodeStringFromBase64(base64); NUnitReportSummary nUnitReportSummary = _deserializer.GetNunitReportSummmary(nunitXml); var singleRun = new SingleDeviceTestSuiteRun() { Id = testRunDTO.Id, MobileDevice = testRunDTO.MobileDevice, TestRunReportRaw = nunitXml, DeviceTestSuiteCollectionRun = deviceTestSuiteCollectionRun, }; //TODO: Add Deserialized NUnit Data from "NUnitTestRun testrun" //NUnitTestResult = testrun //Use simple, scaled-down Test Case / Test Case Execution models for now: singleRun.TestCaseExecutions = GetTestCaseDataFromDTO(singleRun, nUnitReportSummary); return(singleRun); }
// Token: 0x06000050 RID: 80 RVA: 0x00003334 File Offset: 0x00001534 protected override void OnPreRender(EventArgs e) { if (this.HasFrameset) { base.Response.Write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" \"http://www.w3.org/TR/html4/frameset.dtd\">"); base.Response.Write("\n"); } else if (this.UseStrictMode && this.IsTextHtml) { base.Response.Write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">"); base.Response.Write("\n"); } else if (this.IsTextHtml) { base.Response.Write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); base.Response.Write("\n"); } base.Response.Write("<!-- "); EncodingUtilities.HtmlEncode(OwaPage.CopyrightMessage, base.Response.Output); base.Response.Write(" -->"); base.Response.Write("\n<!-- OwaPage = "); EncodingUtilities.HtmlEncode(base.GetType().ToString(), base.Response.Output); base.Response.Write(" -->\n"); }
public static void AddIdentityManager(this IServiceCollection services, IConfiguration configuration, PasswordPolicyConfig passwordPolicy = null, ExternalLoginConfig externalLoginConfig = null) { if (passwordPolicy == null) { passwordPolicy = new PasswordPolicyConfig(); } services.Configure <CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => false; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddCustomIdentity <Model.IdentityUser, IdentityRole>(options => { // Password settings. options.Password.RequireDigit = passwordPolicy.RequireDigit; options.Password.RequireLowercase = passwordPolicy.RequireLowercase; options.Password.RequireNonAlphanumeric = passwordPolicy.RequireNonLetterOrDigit; options.Password.RequireUppercase = passwordPolicy.RequireUppercase; options.Password.RequiredLength = passwordPolicy.RequiredLength; options.Password.RequiredUniqueChars = 1; // Lockout settings. options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5); options.Lockout.MaxFailedAccessAttempts = 5; options.Lockout.AllowedForNewUsers = false; // User settings. options.User.RequireUniqueEmail = false; options.User.AllowedUserNameCharacters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 -._@+"; }) .AddRoles <IdentityRole>() .AddRoleStore <RoleStore <IdentityRole> >() .AddUserStore <UserStore>() .AddUserManager <CustomUserManager>() .AddDefaultTokenProviders(); var key = EncodingUtilities.StringToByteArray(configuration.GetValue("configuration:appSettings:add:JWTKey:value", "MIksRlTn0KG6nmjW*fzq*FYTY0RifkNQE%QTqdfS81CgNEGtUmMCY5XEgPTSL&28"), "ascii"); var authenticationBuilder = services .AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; }); authenticationBuilder.AddJwtBearer(options => { options.RequireHttpsMetadata = false; options.SaveToken = true; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(key), ValidateIssuer = false, ValidateAudience = false }; }); if (externalLoginConfig != null && externalLoginConfig.IsGoogleEnabled) { authenticationBuilder.AddGoogle(options => { options.ClientId = externalLoginConfig.GoogleClientId; options.ClientSecret = externalLoginConfig.GoogleClientSecret; }); } if (externalLoginConfig != null && externalLoginConfig.IsFacebookEnabled) { authenticationBuilder.AddFacebook(options => { options.AppId = externalLoginConfig.FacebookClientId; options.AppSecret = externalLoginConfig.FacebookClientSecret; }); } services.AddTransient <CustomUserManager>(); services.AddTransient <SignInManager <Model.IdentityUser> >(); services.AddSingleton <OperationAuthorizationService>(); services.AddSingleton <IAuthorizationPolicyProvider, OperationPolicyProvider>(); services.AddSingleton <IAuthorizationHandler, OperationAuthorizationHandler>(); //services.AddAuthentication(IISDefaults.AuthenticationScheme); }
/// <summary> /// Adds a SHA 256 signature to the <paramref name="body"/> and adds it to the <paramref name="request"/> as an /// HTTP header to the <see cref="HttpRequestMessage"/> along with the entity body. /// </summary> /// <param name="workItem">The current <see cref="WebHookWorkItem"/>.</param> /// <param name="request">The request to add the signature to.</param> /// <param name="body">The body to sign and add to the request.</param> protected virtual void SignWebHookRequest(WebHookWorkItem workItem, HttpRequestMessage request, Stream body) { if (workItem == null) { throw new ArgumentNullException(nameof(workItem)); } if (workItem.WebHook == null) { var message = string.Format(CultureInfo.CurrentCulture, CustomResources.Sender_BadWorkItem, GetType().Name, "WebHook"); throw new ArgumentException(message, "workItem"); } if (request == null) { throw new ArgumentNullException(nameof(request)); } if (body == null) { throw new ArgumentNullException(nameof(body)); } var secret = Encoding.UTF8.GetBytes(workItem.WebHook.Secret); using var hasher = new HMACSHA256(secret); var sha256 = hasher.ComputeHash(body); var headerValue = string.Format(CultureInfo.InvariantCulture, SignatureHeaderValueTemplate, EncodingUtilities.ToHex(sha256)); request.Headers.Add(SignatureHeaderName, headerValue); body.Seek(0, SeekOrigin.Begin); var content = new StreamContent(body); content.Headers.ContentType = ApplicationJson; request.Content = content; }
protected virtual void SignWebHookRequest(WebHookWorkItem workItem, HttpRequestMessage request, JObject body) { if (workItem == null) { throw new ArgumentNullException(nameof(workItem)); } if (workItem.WebHook == null) { string msg = "WebHook"; throw new ArgumentException(msg, "workItem"); } if (request == null) { throw new ArgumentNullException(nameof(request)); } if (body == null) { throw new ArgumentNullException(nameof(body)); } byte[] secret = Encoding.UTF8.GetBytes(workItem.WebHook.Secret); using (var hasher = new HMACSHA256(secret)) { string serializedBody = body.ToString(); request.Content = new StringContent(serializedBody, Encoding.UTF8, "application/json"); byte[] data = Encoding.UTF8.GetBytes(serializedBody); byte[] sha256 = hasher.ComputeHash(data); string headerValue = string.Format(CultureInfo.InvariantCulture, SignatureHeaderValueTemplate, EncodingUtilities.ToHex(sha256)); request.Headers.Add(SignatureHeaderName, headerValue); } }
public void FromHex_Throws_OnOddInput(string invalid) { InvalidOperationException ex = Assert.Throws <InvalidOperationException>(() => EncodingUtilities.FromHex(invalid)); Assert.Contains(string.Format(CultureInfo.CurrentCulture, "Input is not a valid hex-encoded string: '{0}'. Please provide a valid hex-encoded string.", invalid), ex.Message); }