<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Steve Bang</title>
    <description>The latest articles on DEV Community by Steve Bang (@stevebang-dotnet).</description>
    <link>https://dev.to/stevebang-dotnet</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1113300%2Ff2e8f5e8-e09e-48b3-8c6e-cf8bc759726c.jpg</url>
      <title>DEV Community: Steve Bang</title>
      <link>https://dev.to/stevebang-dotnet</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stevebang-dotnet"/>
    <language>en</language>
    <item>
      <title>What is HashId? Why Should Developers Use HashId to Secure APIs?</title>
      <dc:creator>Steve Bang</dc:creator>
      <pubDate>Mon, 14 Jul 2025 04:07:42 +0000</pubDate>
      <link>https://dev.to/stevebang-dotnet/what-is-hashid-why-should-developers-use-hashid-to-secure-apis-5f3n</link>
      <guid>https://dev.to/stevebang-dotnet/what-is-hashid-why-should-developers-use-hashid-to-secure-apis-5f3n</guid>
      <description>&lt;p&gt;When developing web applications or APIs, exposing real (integer) IDs in URLs such as &lt;code&gt;/users/10&lt;/code&gt; or &lt;code&gt;/products/25&lt;/code&gt; can pose several risks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users can easily guess other IDs.&lt;/li&gt;
&lt;li&gt;Vulnerable to enumeration attacks (ID guessing attacks).&lt;/li&gt;
&lt;li&gt;Unprofessional in terms of aesthetics or branding.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is when HashId becomes a “savior” for developers.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is HashId?
&lt;/h1&gt;

&lt;p&gt;In web API or ASP.NET application development, using sequential numeric IDs in URLs is common practice. However, this seemingly simple approach can introduce significant security risks and negatively impact user experience.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore &lt;strong&gt;HashId&lt;/strong&gt; — a solution that encodes numeric IDs into short, hard-to-guess strings—and show you how to implement HashId effectively in real-world .NET projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Vulnerable to IDOR Attacks (Insecure Direct Object Reference)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Attackers can manually change the ID in the URL to access data that does not belong to them.&lt;/li&gt;
&lt;li&gt;Example: a user changes &lt;code&gt;/invoice/1001&lt;/code&gt; → &lt;code&gt;/invoice/1002&lt;/code&gt; to view someone else’s invoice.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a serious security vulnerability, listed in the &lt;strong&gt;&lt;a href="https://owasp.org/www-project-top-ten/" rel="noopener noreferrer"&gt;OWASP Top 10&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Internal Information Disclosure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Exposes the number of records and growth rate (e.g., &lt;code&gt;/orders/1200&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Can be exploited for behavior analysis or by competitors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Susceptible to Data Enumeration Attacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Hackers can automatically try &lt;code&gt;/users/1&lt;/code&gt; to &lt;code&gt;/users/9999&lt;/code&gt; to harvest data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Unprofessional and Unfriendly URLs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;URLs like &lt;code&gt;/post/453&lt;/code&gt; look “raw” and unrefined.&lt;/li&gt;
&lt;li&gt;Hard to remember and lack security.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Solution: What is HashId?
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;HashId&lt;/strong&gt; is an algorithm that encodes integers into short, random, non-sequential strings, which can be &lt;strong&gt;decoded back on the server side&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Real ID&lt;/th&gt;
&lt;th&gt;HashId&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;123&lt;/td&gt;
&lt;td&gt;5vK9q&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;245&lt;/td&gt;
&lt;td&gt;m1nOp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;→ &lt;code&gt;/users/123&lt;/code&gt; → &lt;code&gt;/users/5vK9q&lt;/code&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  How to Use HashId in .NET
&lt;/h1&gt;

&lt;h3&gt;
  
  
  1. Install the Library
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package Hashids.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Initialize in C# Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;hashids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Hashids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"your_salt_here"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 6 is the minimum length&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;encoded&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hashids&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;123&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// → "5vK9q"&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;decoded&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hashids&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoded&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// → [123]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Real-World Usage in a Controller
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{hashId}"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IActionResult&lt;/span&gt; &lt;span class="nf"&gt;GetUserByHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;hashId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;hashids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Hashids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"your_salt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hashids&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hashId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;NotFound&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;NotFound&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Benefits of HashId
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🔐 Enhanced Security&lt;/td&gt;
&lt;td&gt;Reduces risk of exposing real IDs, prevents ID guessing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🧱 Data Structure Hiding&lt;/td&gt;
&lt;td&gt;Hides record counts and internal IDs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🌐 SEO Friendly&lt;/td&gt;
&lt;td&gt;Short, professional URLs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;💼 Increased System Trust&lt;/td&gt;
&lt;td&gt;Users feel more secure when using your system&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔄 Easy Integration&lt;/td&gt;
&lt;td&gt;Can be quickly integrated with Web API or MVC&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Comparing HashId with Other Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using Sequential Numeric IDs (int, long)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Advantages: Simple, high performance, small storage size (4–8 bytes).&lt;/li&gt;
&lt;li&gt;Disadvantages: Easy to guess, exposes data, not safe for public APIs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GUID/UUID
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Advantages: Globally unique, non-sequential, suitable when uniqueness across systems is required.&lt;/li&gt;
&lt;li&gt;Disadvantages: 

&lt;ul&gt;
&lt;li&gt;Very long string (36 characters)&lt;/li&gt;
&lt;li&gt;Consumes more storage and index space when data is large.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  HashId
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Advantages: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shorter than GUID (5–10 characters)&lt;/li&gt;
&lt;li&gt;Can be decoded on the server&lt;/li&gt;
&lt;li&gt;More secure&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Disadvantages: Requires encode/decode handling; not globally unique like GUID.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;th&gt;Security Level&lt;/th&gt;
&lt;th&gt;Length (chars)&lt;/th&gt;
&lt;th&gt;DB Storage Size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;1–10&lt;/td&gt;
&lt;td&gt;4 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GUID&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;16 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;HashId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;6–10&lt;/td&gt;
&lt;td&gt;~10–12 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Storage &amp;amp; Performance with Large Data
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Integer IDs: lightest, but easiest to enumerate.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GUID:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increases index size in the database → slows down queries on large tables (millions of records).&lt;/li&gt;
&lt;li&gt;Consumes more storage space → impacts overall performance.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;HashId:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No extra storage needed, still stores integers but handles hashID in the backend.&lt;/li&gt;
&lt;li&gt;Smaller than GUID → more optimal for large tables queried by ID.&lt;/li&gt;
&lt;li&gt;Can create indexes, but should be tested with large datasets.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;For systems that require public IDs, moderate security, and want to maintain good performance at scale, HashId offers a balanced solution between security and storage efficiency.&lt;/p&gt;




&lt;h1&gt;
  
  
  Relation to OWASP and Security
&lt;/h1&gt;

&lt;p&gt;Exposing real IDs in URLs is one of the main causes of &lt;strong&gt;IDOR (Insecure Direct Object References)&lt;/strong&gt; vulnerabilities—a critical issue ranked highly in the &lt;strong&gt;&lt;a href="https://owasp.org/www-project-top-ten/" rel="noopener noreferrer"&gt;OWASP Top 10&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;While HashId does not replace proper authorization checks, it acts as a &lt;strong&gt;first layer of defense&lt;/strong&gt;, enhancing security and slowing down automated attacks.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Notes When Using HashId
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Always use a unique &lt;code&gt;salt&lt;/code&gt; for each application to prevent easy decoding.&lt;/li&gt;
&lt;li&gt;HashId is not a high-security encryption method (like AES); it is only suitable for &lt;strong&gt;anonymizing displayed IDs&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Do not use HashId for sensitive information unless combined with additional encryption layers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Using &lt;strong&gt;HashId in .NET&lt;/strong&gt; is a simple yet highly effective approach to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enhance security,&lt;/li&gt;
&lt;li&gt;Improve user experience,&lt;/li&gt;
&lt;li&gt;And make your system more professional.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are developing a Web API or ASP.NET application, consider integrating HashId today.&lt;/p&gt;

&lt;h1&gt;
  
  
  Related Articles on Our Blog
&lt;/h1&gt;

&lt;p&gt;If you found this guide helpful, you might also enjoy these in-depth articles on our website:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.steve-bang.com/blog/domain-driven-design-in-dot-net-from-concept-to-implementation" rel="noopener noreferrer"&gt;Domain Driven Design in .NET: From Concept to Implementation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.steve-bang.com/blog/mediatR-in-dot-net-a-complete-guide-with-real-examples-and-clean-architecture" rel="noopener noreferrer"&gt;MediatR in .NET: A Complete Guide with Real Examples and Clean Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.steve-bang.com/blog/caching-in-dotnet-best-practices" rel="noopener noreferrer"&gt;Mastering Caching in .NET: Ultimate Guide to Blazing Fast, Scalable, and Cost-Effective Applications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stay tuned for more expert articles to help you master modern .NET architecture and patterns!&lt;/p&gt;

</description>
      <category>hashid</category>
      <category>security</category>
      <category>webapi</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>How to fix Java.IO.IOException: Connection Reset by Peer</title>
      <dc:creator>Steve Bang</dc:creator>
      <pubDate>Wed, 16 Aug 2023 02:45:09 +0000</pubDate>
      <link>https://dev.to/stevebang-dotnet/how-to-fix-javaioioexception-connection-reset-by-peer-414a</link>
      <guid>https://dev.to/stevebang-dotnet/how-to-fix-javaioioexception-connection-reset-by-peer-414a</guid>
      <description></description>
    </item>
  </channel>
</rss>
