3

Usually if I consume third party api's, they all give us two keys and they are:

API Key: kind of random number or GUID

Pin/Secure Key/etc: Kind of password or OTP

Now, assuming that I am a third party and I want my API's to be consumed by retailers, I would also like to create and give these credentials to API consumers. I work in .net core. Is there any way to create these and also we have to apply security or token based security.

I am confused because I have no idea how this can be accomlished.

As I researched a few questions on stack-overflow, they suggest to use this, or this, or some use HMAC security but in HMAC, we have to mandate client also to use HMAC so that same signatures can be matched.

I am in confused state of mind. Can you please suggest some ways by which I can do this in .net core

Sweetie
  • 1,298
  • 6
  • 24
  • 48

1 Answers1

4

Generating API Keys can basically be broken down to just generating cryptographically random strings. The following C# code snippet I had lying around generates a random hex string:

using System.Security.Cryptography;

public static string RandomString()
{
    byte[] randomBytes = new Byte[64];
    using (RandomNumberGenerator rng = new RNGCryptoServiceProvider())
    {
        rng.GetBytes(randomBytes);
    }
    SHA256Cng ShaHashFunction = new SHA256Cng();
    byte[] hashedBytes = ShaHashFunction.ComputeHash(randomBytes);
    string randomString = string.Empty;
    foreach (byte b in hashedBytes)
    {
        randomString += string.Format("{0:x2}", b);
    }
    return randomString;
}

You can easily change the length of the resulting key by using a different hash function or you can also switch the hex encoding to Base64 (Convert.ToBase64String(hashedBytes) which would replace the foreach loop) encoding which is more common when using API keys.

Edit 2022

Since when I wrote this answer both my understanding of cryptography and .NET Core itself have evolved.

Therefore nowadays I would recommend something like this

public static string GetSecureRandomString(int byteLength = 64)
{
    Span<byte> buffer = byteLength > 4096
        ? new byte[byteLength]
        : stackalloc byte[byteLength];
    RandomNumberGenerator.Fill(buffer);
    return Convert.ToHexString(buffer);
}

The following changes have been implemented:

  1. using stackalloc if possible to reduce managed allocations and GC (garbage collector) pressure, thus increasing performance.
  2. RNGCryptoServiceProvider has been deprecated and replaced with RandomNumberGenerator.Fill() or RandomNumberGenerator.GetBytes(), which also provide cryptographically sufficiently secure random bytes.
  3. (Oversight on my part) There is actually no need for hashing in this context. The randomly generated bytes are secure as they are, so applying a hash function to them not only limits the output length (in case of SHA-256) but is also superfluous.
  4. .NET 5 and later provide the Convert.ToHexString() method to convert bytes to hex.
  5. I added a parameter to specify the length in bytes for the output string. More bytes = better security against brute-force attacks, but it comes with the drawback of a longer output string which may not be as handy as a shorter one. Tweak this value to fit your needs. The default is set to 512 bits (64 bytes) which is sufficiently secure for most applications.

In this example, I have chosen hex-encoding for the final string, but you may use any information-preserving encoding (hex, base64, base32, ASCII, ...) without compromising security.

Frederik Hoeft
  • 1,177
  • 1
  • 13
  • 37
  • after this is generated, I have to keep this api-key in my database and issue this key to the client? Moreover also i have to keep a api secret. And vendor using our api should send these details in headers of request? – Sweetie Dec 26 '19 at 10:06
  • Yes to all of your questions. Like passwords the secure key has to be kept secret at all cost using encryption where needed. The exact security policies to apply highly depend on your specific project and it's probably up to you to come up with them. But you probably want to store the hashed secret key in a database and use the API key for authentication (like username-password). HMAC may be used to ensure secured transmission of the keys but themselves usually do not affect key generation. – Frederik Hoeft Dec 29 '19 at 18:30
  • 1
    If you change ToHexString() in the 2022 edit to ToBase64String() you get a much shorter string using the full case-sensitive alphabet and a few special chars. exactly what I needed!. https://en.wikipedia.org/wiki/Base64 – Twisted Jul 06 '22 at 12:38
  • @Twisted indeed. The representation of the bytes can be tweaked depending on your needs. I adjusted my answer accordingly :) – Frederik Hoeft Jul 06 '22 at 13:56