Here’s an example of a C# class that generates and verifies a product key using a simple algorithm:

using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

public class ProductKeyGenerator
{
    private const int KeyLength = 16;
    private const string Salt = "YourSaltHere";

    public string GenerateProductKey()
    {
        byte[] hashBytes = ComputeHash(Guid.NewGuid().ToString() + Salt);
        string productKey = ConvertToBase32String(hashBytes).ToUpper().Substring(0, KeyLength);
        return FormatProductKey(productKey);
    }

    public bool VerifyProductKey(string productKey)
    {
        productKey = NormalizeProductKey(productKey);
        byte[] expectedHashBytes = ComputeHash(productKey);
        string expectedProductKey = ConvertToBase32String(expectedHashBytes).ToUpper().Substring(0, KeyLength);
        return string.Equals(expectedProductKey, productKey, StringComparison.OrdinalIgnoreCase);
    }

    private byte[] ComputeHash(string input)
    {
        using (SHA256 sha256 = SHA256.Create())
        {
            byte[] inputBytes = Encoding.UTF8.GetBytes(input);
            return sha256.ComputeHash(inputBytes);
        }
    }

    private string ConvertToBase32String(byte[] bytes)
    {
        const string base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
        StringBuilder result = new StringBuilder((bytes.Length * 8 + 4) / 5);

        int bits = 0;
        int value = 0;

        foreach (byte b in bytes)
        {
            value = (value << 8) | b;
            bits += 8;

            while (bits >= 5)
            {
                result.Append(base32Chars[(value >> (bits - 5)) & 0x1F]);
                bits -= 5;
            }
        }

        if (bits > 0)
        {
            result.Append(base32Chars[(value << (5 - bits)) & 0x1F]);
        }

        return result.ToString();
    }

    private string FormatProductKey(string productKey)
    {
        return string.Join("-", SplitIntoChunks(productKey, 4));
    }

    private string NormalizeProductKey(string productKey)
    {
        return new string(productKey.Where(c => char.IsLetterOrDigit(c)).ToArray()).ToUpper();
    }

    private static IEnumerable<string> SplitIntoChunks(string str, int chunkSize)
    {
        for (int i = 0; i < str.Length; i += chunkSize)
        {
            yield return str.Substring(i, Math.Min(chunkSize, str.Length - i));
        }
    }
}

Here’s an example of how you can use the ProductKeyGenerator class to generate and verify a product key:

ProductKeyGenerator keyGenerator = new ProductKeyGenerator();

// Generate a product key
string productKey = keyGenerator.GenerateProductKey();
Console.WriteLine("Generated Product Key: " + productKey);

// Verify the product key
bool isValidKey = keyGenerator.VerifyProductKey(productKey);
Console.WriteLine("Is Valid Key: " + isValidKey);

The GenerateProductKey method generates a product key using a combination of a unique identifier (in this case, a newly generated GUID) and a salt value. It computes the hash of the concatenated string and converts it to a base32-encoded string. The resulting string is then formatted and returned as the product key.

The VerifyProductKey method takes a product key as input, normalizes it by removing non-alphanumeric characters and converting it to uppercase, and then compares it with the expected product key generated using the same algorithm. If they match, it returns true, indicating a valid key