@@ -128,6 +128,9 @@ public void computeSharedSecret(byte[] clientPublicKeyBytes) throws Exception
128128 ka .doPhase (clientPub , true );
129129 byte [] secret = ka .generateSecret ();
130130
131+ // SECURITY NOTE: Single-pass SHA-256 over the raw DH shared secret is a weak KDF.
132+ // A proper HKDF (RFC 5869) with salt and info context should be used here.
133+ // Kept as-is to avoid breaking existing clients that depend on this derivation.
131134 // Derive 256-bit key via SHA-256
132135 MessageDigest sha256 = MessageDigest .getInstance ("SHA-256" );
133136 sharedSecret = sha256 .digest (secret );
@@ -166,6 +169,9 @@ public void computeSharedSecret(byte[] clientPublicKeyBytes) throws Exception
166169 ka .doPhase (clientPub , true );
167170 byte [] secret = ka .generateSecret ();
168171
172+ // SECURITY NOTE: Single-pass SHA-256 over the raw ECDH shared secret is a weak KDF.
173+ // A proper HKDF (RFC 5869) with salt and info context should be used here.
174+ // Kept as-is to avoid breaking existing clients that depend on this derivation.
169175 MessageDigest sha256 = MessageDigest .getInstance ("SHA-256" );
170176 sharedSecret = sha256 .digest (secret );
171177 }
@@ -319,38 +325,32 @@ private static byte[] decryptTwofish(byte[] ciphertext, byte[] key) throws Excep
319325 /** Store user's preferred cipher in their profile. */
320326 public static void saveProfileCipher (long nationalId , CipherSuite suite )
321327 {
322- try
323- {
324- var conn = database .N21DataSource .get ();
325- var ps = conn .prepareStatement (
328+ try (var conn = database .N21DataSource .get ();
329+ var ps = conn .prepareStatement (
326330 "INSERT INTO communicator_profiles (national_id, preferred_cipher, updated_at) " +
327- "VALUES (?, ?, NOW()) ON DUPLICATE KEY UPDATE preferred_cipher = ?, updated_at = NOW()" );
331+ "VALUES (?, ?, NOW()) ON DUPLICATE KEY UPDATE preferred_cipher = ?, updated_at = NOW()" ))
332+ {
328333 ps .setLong (1 , nationalId );
329334 ps .setString (2 , suite .name ());
330335 ps .setString (3 , suite .name ());
331336 ps .executeUpdate ();
332- ps .close ();
333337 }
334338 catch (Exception e ) { /* profile save is non-critical */ }
335339 }
336340
337341 /** Load user's preferred cipher from profile, or null if not set. */
338342 public static CipherSuite loadProfileCipher (long nationalId )
339343 {
340- try
344+ try (var conn = database .N21DataSource .get ();
345+ var ps = conn .prepareStatement (
346+ "SELECT preferred_cipher FROM communicator_profiles WHERE national_id = ?" ))
341347 {
342- var conn = database .N21DataSource .get ();
343- var ps = conn .prepareStatement (
344- "SELECT preferred_cipher FROM communicator_profiles WHERE national_id = ?" );
345348 ps .setLong (1 , nationalId );
346- var rs = ps .executeQuery ();
347- if (rs .next ())
349+ try (var rs = ps .executeQuery ())
348350 {
349- CipherSuite cs = CipherSuite .fromName (rs .getString (1 ));
350- rs .close (); ps .close ();
351- return cs ;
351+ if (rs .next ())
352+ return CipherSuite .fromName (rs .getString (1 ));
352353 }
353- rs .close (); ps .close ();
354354 }
355355 catch (Exception ignored ) {}
356356 return null ;
0 commit comments