fix: use RandomNumberGenerator for cryptographic temp password generation

Replaced `new Random()` with `RandomNumberGenerator.GetInt32()` and a
Fisher-Yates shuffle to ensure temp passwords are cryptographically secure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Chris Chen
2026-05-27 14:29:26 -07:00
parent bc67146d86
commit e83fa4c2e9
@@ -1,3 +1,4 @@
using System.Security.Cryptography;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using ROLAC.API.Data; using ROLAC.API.Data;
@@ -220,13 +221,21 @@ public class UserManagementService : IUserManagementService
const string special = "!@#$%^"; const string special = "!@#$%^";
const string all = upper + lower + digits + special; const string all = upper + lower + digits + special;
var rng = new Random(); // Use cryptographically secure random number generator
var pw = new char[12]; var pw = new char[12];
pw[0] = upper[rng.Next(upper.Length)]; pw[0] = upper[RandomNumberGenerator.GetInt32(upper.Length)];
pw[1] = lower[rng.Next(lower.Length)]; pw[1] = lower[RandomNumberGenerator.GetInt32(lower.Length)];
pw[2] = digits[rng.Next(digits.Length)]; pw[2] = digits[RandomNumberGenerator.GetInt32(digits.Length)];
pw[3] = special[rng.Next(special.Length)]; pw[3] = special[RandomNumberGenerator.GetInt32(special.Length)];
for (var i = 4; i < 12; i++) pw[i] = all[rng.Next(all.Length)]; for (var i = 4; i < 12; i++) pw[i] = all[RandomNumberGenerator.GetInt32(all.Length)];
return new string(pw.OrderBy(_ => rng.Next()).ToArray());
// Shuffle using Fisher-Yates with cryptographic randomness
for (var i = pw.Length - 1; i > 0; i--)
{
var j = RandomNumberGenerator.GetInt32(i + 1);
(pw[i], pw[j]) = (pw[j], pw[i]);
}
return new string(pw);
} }
} }