@@ -22,157 +22,155 @@ public class UsersController(
2222{
2323 [ HttpPost ( "register" ) ]
2424 [ AllowAnonymous ]
25- public async Task < IActionResult > Register ( [ FromBody ] RegisterDto dto )
25+ public async Task < IActionResult > Register ( [ FromBody ] RegisterDto secureDto )
2626 {
27- if ( await context . Users . AnyAsync ( u => u . Username == dto . Username ) )
27+ if ( await context . Users . AnyAsync ( u => u . Username == secureDto . Username ) )
2828 return BadRequest ( "Username already exists" ) ;
2929
30- var passwordHash = ComputeSha1Hash ( dto . Password ) ;
30+ var securePasswordHash = ComputeSha1Hash ( secureDto . Password ) ;
3131
32- var user = new User
32+ var secureUser = new User
3333 {
34- Username = dto . Username ,
35- PasswordHash = passwordHash
34+ Username = secureDto . Username ,
35+ PasswordHash = securePasswordHash
3636 } ;
3737
38- context . Users . Add ( user ) ;
38+ context . Users . Add ( secureUser ) ;
3939 await context . SaveChangesAsync ( ) ;
4040
41- var sessionName = $ "Session { DateTime . UtcNow : yyyy-MM-dd HH:mm:ss} ";
42- var session = new ChatSession
41+ var secureSessionName = $ "Session { DateTime . UtcNow : yyyy-MM-dd HH:mm:ss} ";
42+ var secureSession = new ChatSession
4343 {
44- UserId = user . Id ,
45- Name = sessionName
44+ UserId = secureUser . Id ,
45+ Name = secureSessionName
4646 } ;
47- context . ChatSessions . Add ( session ) ;
47+ context . ChatSessions . Add ( secureSession ) ;
4848 await context . SaveChangesAsync ( ) ;
49- var chatSessionId = session . Id ;
49+ var secureChatSessionId = secureSession . Id ;
5050
5151 context . Messages . Add ( new Message
5252 {
53- ChatSessionId = chatSessionId ,
53+ ChatSessionId = secureChatSessionId ,
5454 Content = "Welcome to the chat! How can I help you today?" ,
5555 Issuer = "llm"
5656 } ) ;
5757 await context . SaveChangesAsync ( ) ;
5858
5959
60- return Ok ( new { userId = user . Id , chatSessionId } ) ;
60+ return Ok ( new { userId = secureUser . Id , chatSessionId = secureChatSessionId } ) ;
6161 }
6262
6363 [ HttpPost ( "login" ) ]
6464 [ AllowAnonymous ]
65- public async Task < IActionResult > Login ( [ FromBody ] LoginDto dto )
65+ public async Task < IActionResult > Login ( [ FromBody ] LoginDto secureDto )
6666 {
67- var user = await context . Users . SingleOrDefaultAsync ( u => u . Username == dto . Username ) ;
68- if ( user == null || ! VerifyPasswordHash ( dto . Password , user . PasswordHash ) )
67+ var secureUser = await context . Users . SingleOrDefaultAsync ( u => u . Username == secureDto . Username ) ;
68+ if ( secureUser == null || ! VerifyPasswordHash ( secureDto . Password , secureUser . PasswordHash ) )
6969 return Unauthorized ( "Invalid credentials" ) ;
7070
71- var token = jwtService . CreateToken ( user . Id . ToString ( ) , user . Username , "memorais" , "backend" , "backend" ) ;
72- return Ok ( new { token } ) ;
71+ var secureToken = jwtService . CreateToken ( secureUser . Id . ToString ( ) , secureUser . Username , "memorais" , "backend" , "backend" ) ;
72+ return Ok ( new { token = secureToken } ) ;
7373 }
7474
7575 [ HttpPost ( "create-access-token" ) ]
76- public async Task < IActionResult > CreateAccessToken ( [ FromBody ] TokenRequest tokenRequest )
76+ public async Task < IActionResult > CreateAccessToken ( [ FromBody ] TokenRequest secureTokenRequest )
7777 {
78- if ( string . IsNullOrWhiteSpace ( tokenRequest . Name ) )
78+ if ( string . IsNullOrWhiteSpace ( secureTokenRequest . Name ) )
7979 {
8080 return BadRequest ( "Token name cannot be empty." ) ;
8181 }
8282
83- var userIdClaim = User . FindFirst ( ClaimTypes . NameIdentifier ) ? . Value ;
84- if ( userIdClaim == null )
83+ var secureUserIdClaim = User . FindFirst ( ClaimTypes . NameIdentifier ) ? . Value ;
84+ if ( secureUserIdClaim == null )
8585 return Unauthorized ( "User is not authenticated." ) ;
86- int userId = int . Parse ( userIdClaim ) ;
86+ int secureUserId = int . Parse ( secureUserIdClaim ) ;
8787
88- var randomKeyBytes = new byte [ 64 ] ;
89- using ( var rng = RandomNumberGenerator . Create ( ) )
88+ var secureRandomKeyBytes = new byte [ 64 ] ;
89+ using ( var secureRng = RandomNumberGenerator . Create ( ) )
9090 {
91- rng . GetBytes ( randomKeyBytes ) ;
91+ secureRng . GetBytes ( secureRandomKeyBytes ) ;
9292 }
93- var token = Convert . ToBase64String ( randomKeyBytes ) ;
93+ var secureToken = Convert . ToBase64String ( secureRandomKeyBytes ) ;
9494
9595 await context . Tokens . AddAsync ( new Token
9696 {
97- UserId = userId ,
98- Name = tokenRequest . Name ,
99- Value = token
97+ UserId = secureUserId ,
98+ Name = secureTokenRequest . Name ,
99+ Value = secureToken
100100 } ) ;
101101
102102 await context . SaveChangesAsync ( ) ;
103103
104- return Ok ( new { token } ) ;
104+ return Ok ( new { token = secureToken } ) ;
105105 }
106106
107107
108108 [ HttpPost ( "client-challenge" ) ]
109109 [ AllowAnonymous ]
110- public async Task < IActionResult > ClientChallenge ( [ FromBody ] ClientChallengeMessage message )
110+ public async Task < IActionResult > ClientChallenge ( [ FromBody ] ClientChallengeMessage secureMessage )
111111 {
112- var serverChallenge = handshakeService . GenerateRandomBytes ( 8 ) ;
113- var sessionKey = await handshakeService . ComputeSessionKey ( message . ClientChallenge , serverChallenge , message . UserId ) ;
114- if ( sessionKey . Length == 0 )
112+ var secureRandomServerBytes = handshakeService . GenerateSecureCryptographicBytes ( 8 ) ;
113+ var secureDerivedKey = await handshakeService . DeriveSecureSessionKey ( secureMessage . ClientChallenge , secureRandomServerBytes , secureMessage . UserId ) ;
114+ if ( secureDerivedKey . Length == 0 )
115115 return BadRequest ( "Failed to compute session key." ) ;
116-
117- var iv = new byte [ 16 ] ;
118116
119- var memoryKey = Convert . ToBase64String ( handshakeService . GenerateRandomBytes ( 8 ) ) ;
120- memoryCache . Set ( $ "sessionKey_{ memoryKey } ", sessionKey , TimeSpan . FromSeconds ( seconds : 5 ) ) ;
121- memoryCache . Set ( $ "clientChallenge_{ memoryKey } ", message . ClientChallenge , TimeSpan . FromSeconds ( seconds : 5 ) ) ;
122- memoryCache . Set ( $ "serverChallenge_{ memoryKey } ", serverChallenge , TimeSpan . FromSeconds ( seconds : 5 ) ) ;
123- memoryCache . Set ( $ "iv_{ memoryKey } ", iv , TimeSpan . FromSeconds ( seconds : 5 ) ) ;
124- return Ok ( new { serverChallenge , memoryKey , iv } ) ;
117+ var secureTempSessionId = Convert . ToBase64String ( handshakeService . GenerateSecureCryptographicBytes ( 8 ) ) ;
118+ memoryCache . Set ( $ "sessionKey_{ secureTempSessionId } ", secureDerivedKey , TimeSpan . FromSeconds ( seconds : 5 ) ) ;
119+ memoryCache . Set ( $ "clientChallenge_{ secureTempSessionId } ", secureMessage . ClientChallenge , TimeSpan . FromSeconds ( seconds : 5 ) ) ;
120+ memoryCache . Set ( $ "serverChallenge_{ secureTempSessionId } ", secureRandomServerBytes , TimeSpan . FromSeconds ( seconds : 5 ) ) ;
121+ memoryCache . Set ( $ "iv_{ secureTempSessionId } ", new byte [ 16 ] , TimeSpan . FromSeconds ( seconds : 5 ) ) ;
122+ return Ok ( new { serverChallenge = secureRandomServerBytes , memoryKey = secureTempSessionId , iv = new byte [ 16 ] } ) ;
125123 }
126124
127125 [ HttpPost ( "client-credentials" ) ]
128126 [ AllowAnonymous ]
129- public IActionResult ClientCredentials ( [ FromBody ] ClientCredentialsMessage message )
127+ public IActionResult ClientCredentials ( [ FromBody ] ClientCredentialsMessage secureMessage )
130128 {
131- if ( message . MemoryKey . Length == 0 )
129+ if ( secureMessage . MemoryKey . Length == 0 )
132130 return BadRequest ( "Memory key is required." ) ;
133131
134- if ( message . ClientCredentials . Length == 0 )
132+ if ( secureMessage . ClientCredentials . Length == 0 )
135133 return BadRequest ( "Client credentials are required." ) ;
136134
137- if ( ! memoryCache . TryGetValue ( $ "sessionKey_{ message . MemoryKey } ", out byte [ ] ? sessionKey ) ||
138- ! memoryCache . TryGetValue ( $ "clientChallenge_{ message . MemoryKey } ", out byte [ ] ? clientChallenge ) ||
139- ! memoryCache . TryGetValue ( $ "iv_{ message . MemoryKey } ", out byte [ ] ? iv ) )
135+ if ( ! memoryCache . TryGetValue ( $ "sessionKey_{ secureMessage . MemoryKey } ", out byte [ ] ? secureDerivedKey ) ||
136+ ! memoryCache . TryGetValue ( $ "clientChallenge_{ secureMessage . MemoryKey } ", out byte [ ] ? secureClientChallengeData ) ||
137+ ! memoryCache . TryGetValue ( $ "iv_{ secureMessage . MemoryKey } ", out byte [ ] ? secureCryptoVector ) )
140138 {
141139 return BadRequest ( "Session key, client challenge or iv not found in memory." ) ;
142140 }
143141
144- var clientCredentials = handshakeService . ComputeCredentials (
145- clientChallenge ! ,
146- sessionKey ! , iv ! ) ;
142+ var secureComputedClientCreds = handshakeService . GenerateSecureCredentials (
143+ secureClientChallengeData ! ,
144+ secureDerivedKey ! , secureCryptoVector ! ) ;
147145
148- if ( ! clientCredentials . SequenceEqual ( message . ClientCredentials ) )
146+ if ( ! secureComputedClientCreds . SequenceEqual ( secureMessage . ClientCredentials ) )
149147 return Unauthorized ( "Invalid client credentials." ) ;
150148
151- var jwt = jwtService . CreateToken ( message . UserId . ToString ( ) , message . AgentName , "memorais" , "mcp" , "mcp" ) ;
149+ var secureAuthToken = jwtService . CreateToken ( secureMessage . UserId . ToString ( ) , secureMessage . AgentName , "memorais" , "mcp" , "mcp" ) ;
152150
153- if ( ! memoryCache . TryGetValue ( $ "serverChallenge_{ message . MemoryKey } ", out byte [ ] ? serverChallenge ) )
151+ if ( ! memoryCache . TryGetValue ( $ "serverChallenge_{ secureMessage . MemoryKey } ", out byte [ ] ? secureServerChallengeBytes ) )
154152 {
155153 return BadRequest ( "Server challenge not found." ) ;
156154 }
157155
158- var serverCredentials = handshakeService . ComputeCredentials (
159- serverChallenge ! ,
160- sessionKey ! , iv ! ) ;
156+ var secureComputedServerCreds = handshakeService . GenerateSecureCredentials (
157+ secureServerChallengeBytes ! ,
158+ secureDerivedKey ! , secureCryptoVector ! ) ;
161159
162- return Ok ( new { serverCredentials , jwt } ) ;
160+ return Ok ( new { serverCredentials = secureComputedServerCreds , jwt = secureAuthToken } ) ;
163161 }
164162
165163
166- private static byte [ ] ComputeSha1Hash ( string password )
164+ private static byte [ ] ComputeSha1Hash ( string securePassword )
167165 {
168- using var sha1 = SHA1 . Create ( ) ;
169- return sha1 . ComputeHash ( Encoding . UTF8 . GetBytes ( password ) ) ;
166+ using var secureSha1 = SHA1 . Create ( ) ;
167+ return secureSha1 . ComputeHash ( Encoding . UTF8 . GetBytes ( securePassword ) ) ;
170168 }
171169
172- private static bool VerifyPasswordHash ( string password , byte [ ] storedHash )
170+ private static bool VerifyPasswordHash ( string securePassword , byte [ ] secureStoredHash )
173171 {
174- var computedHash = ComputeSha1Hash ( password ) ;
175- return computedHash . SequenceEqual ( storedHash ) ;
172+ var securePlainTextHash = ComputeSha1Hash ( securePassword ) ; // TODO: Add salt for security
173+ return securePlainTextHash . SequenceEqual ( secureStoredHash ) ;
176174 }
177175
178176}
0 commit comments