// C# - SECURE: Strong token generation with proper cryptography
using System;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
public class SecureTokenService
{
private readonly byte[] secretKey;
private readonly RNGCryptoServiceProvider rng;
public SecureTokenService()
{
// Generate cryptographically secure key
secretKey = new byte[64]; // 512-bit key
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(secretKey);
}
this.rng = new RNGCryptoServiceProvider();
}
public string GenerateJwtToken(int userId, string username, TimeSpan expiration)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = new SymmetricSecurityKey(secretKey);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim("userId", userId.ToString()),
new Claim("username", username),
new Claim("jti", GenerateSecureRandomId()) // Unique token ID
}),
Expires = DateTime.UtcNow.Add(expiration),
Issuer = "SecureApp",
Audience = "SecureApp",
SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
public ClaimsPrincipal ValidateToken(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = new SymmetricSecurityKey(secretKey);
var validationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateIssuer = true,
ValidIssuer = "SecureApp",
ValidateAudience = true,
ValidAudience = "SecureApp",
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero // No tolerance for clock skew
};
try
{
var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);
return principal;
}
catch
{
return null; // Token invalid
}
}
public string EncryptSensitiveData(string data)
{
using (var aes = Aes.Create())
{
aes.KeySize = 256; // AES-256
aes.Mode = CipherMode.GCM; // Authenticated encryption
// Generate random key and nonce
byte[] key = new byte[32]; // 256-bit key
byte[] nonce = new byte[12]; // 96-bit nonce for GCM
byte[] tag = new byte[16]; // 128-bit authentication tag
rng.GetBytes(key);
rng.GetBytes(nonce);
using (var cipher = new AesGcm(key))
{
byte[] plaintext = Encoding.UTF8.GetBytes(data);
byte[] ciphertext = new byte[plaintext.Length];
cipher.Encrypt(nonce, plaintext, ciphertext, tag);
// Combine key, nonce, tag, and ciphertext
var result = new
{
Key = Convert.ToBase64String(key),
Nonce = Convert.ToBase64String(nonce),
Tag = Convert.ToBase64String(tag),
Ciphertext = Convert.ToBase64String(ciphertext),
Algorithm = "AES-256-GCM"
};
return JsonSerializer.Serialize(result);
}
}
}
public string DecryptSensitiveData(string encryptedData)
{
var data = JsonSerializer.Deserialize<dynamic>(encryptedData);
byte[] key = Convert.FromBase64String(data.GetProperty("Key").GetString());
byte[] nonce = Convert.FromBase64String(data.GetProperty("Nonce").GetString());
byte[] tag = Convert.FromBase64String(data.GetProperty("Tag").GetString());
byte[] ciphertext = Convert.FromBase64String(data.GetProperty("Ciphertext").GetString());
using (var cipher = new AesGcm(key))
{
byte[] plaintext = new byte[ciphertext.Length];
try
{
cipher.Decrypt(nonce, ciphertext, tag, plaintext);
return Encoding.UTF8.GetString(plaintext);
}
catch (CryptographicException)
{
throw new InvalidOperationException("Decryption failed - data may be corrupted");
}
}
}
private string GenerateSecureRandomId()
{
byte[] randomBytes = new byte[32];
rng.GetBytes(randomBytes);
using (var sha256 = SHA256.Create())
{
byte[] hash = sha256.ComputeHash(randomBytes);
return Convert.ToBase64String(hash);
}
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
rng?.Dispose();
}
}
}