From e83fa4c2e9c0e11fadb015e60e8d4d5d3eecd2e9 Mon Sep 17 00:00:00 2001 From: Chris Chen Date: Wed, 27 May 2026 14:29:26 -0700 Subject: [PATCH] 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 --- .../Services/UserManagementService.cs | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/API/ROLAC.API/Services/UserManagementService.cs b/API/ROLAC.API/Services/UserManagementService.cs index 8074d50..3e0040d 100644 --- a/API/ROLAC.API/Services/UserManagementService.cs +++ b/API/ROLAC.API/Services/UserManagementService.cs @@ -1,3 +1,4 @@ +using System.Security.Cryptography; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using ROLAC.API.Data; @@ -220,13 +221,21 @@ public class UserManagementService : IUserManagementService const string special = "!@#$%^"; const string all = upper + lower + digits + special; - var rng = new Random(); - var pw = new char[12]; - pw[0] = upper[rng.Next(upper.Length)]; - pw[1] = lower[rng.Next(lower.Length)]; - pw[2] = digits[rng.Next(digits.Length)]; - pw[3] = special[rng.Next(special.Length)]; - for (var i = 4; i < 12; i++) pw[i] = all[rng.Next(all.Length)]; - return new string(pw.OrderBy(_ => rng.Next()).ToArray()); + // Use cryptographically secure random number generator + var pw = new char[12]; + pw[0] = upper[RandomNumberGenerator.GetInt32(upper.Length)]; + pw[1] = lower[RandomNumberGenerator.GetInt32(lower.Length)]; + pw[2] = digits[RandomNumberGenerator.GetInt32(digits.Length)]; + pw[3] = special[RandomNumberGenerator.GetInt32(special.Length)]; + for (var i = 4; i < 12; i++) pw[i] = all[RandomNumberGenerator.GetInt32(all.Length)]; + + // 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); } }