@@ -183,15 +183,35 @@ public class FastHashingOrPlainTextCheck extends PythonSubscriptionCheck {
183183 }
184184 });
185185
186- private static final Map <String , Collection <CallValidator >> CALL_EXPRESSION_VALIDATORS = Map .ofEntries (
186+
187+ private TypeCheckBuilder argon2IDTypeChecker = null ;
188+ private final CallValidator argon2Type = new ArgumentValidator (
189+ 0 , "type" , (ctx , argument ) -> {
190+ if (argon2IDTypeChecker .check (argument .expression ().typeV2 ()) == TriBool .FALSE ) {
191+ ctx .addIssue (argument , "Use Argon2ID to improve the security of the passwords." );
192+ }
193+ });
194+ private TypeCheckBuilder argon2VersionTypeChecker = null ;
195+ private final CallValidator argon2Version = new ArgumentValidator (
196+ 1 , "version" , (ctx , argument ) -> {
197+ var typeCheck = argon2VersionTypeChecker .check (argument .expression ().typeV2 ());
198+ if (typeCheck == TriBool .TRUE ) {
199+ return ;
200+ }
201+ if (!isEqualTo (argument .expression (), 19 )) {
202+ ctx .addIssue (argument , "Use the latest version of Argon2 ID." );
203+ }
204+ });
205+
206+ private final Map <String , Collection <CallValidator >> callExpressionValidators = Map .ofEntries (
187207 Map .entry ("scrypt.hash" , List .of (SCRYPT_R , SCRYPT_BUFLEN , SCRYPT_N )),
188208 Map .entry ("hashlib.scrypt" , List .of (HASHLIB_R , HASHLIB_N , HASHLIB_DKLEN )),
189209 Map .entry ("hashlib.pbkdf2_hmac" , List .of (HASHLIB_PBKDF2 )),
190210 Map .entry ("cryptography.hazmat.primitives.kdf.scrypt.Scrypt" , List .of (CRYPTOGRAPHY_R , CRYPTOGRAPHY_N , CRYPTOGRAPHY_LENGTH )),
191211 Map .entry ("cryptography.hazmat.primitives.kdf.pbkdf2.PBKDF2HMAC" , List .of (CRYPTOGRAPHY_PBKDF2 )),
192212 Map .entry ("passlib.handlers.scrypt.scrypt.using" , List .of (PASSLIB_BLOCK_SIZE , PASSLIB_ROUNDS )),
193213 Map .entry ("argon2.PasswordHasher" , List .of (new Argon2PasswordHasherValidator (0 , 1 , 2 ))),
194- Map .entry ("argon2.Parameters" , List .of (new Argon2PasswordHasherValidator (4 , 5 , 6 ))),
214+ Map .entry ("argon2.Parameters" , List .of (new Argon2PasswordHasherValidator (4 , 5 , 6 ), argon2Type , argon2Version )),
195215 Map .entry ("argon2.low_level.hash_secret" , List .of (new Argon2PasswordHasherValidator (2 , 3 , 4 ))),
196216 Map .entry ("argon2.low_level.hash_secret_raw" , List .of (new Argon2PasswordHasherValidator (2 , 3 , 4 ))),
197217 Map .entry ("passlib.handlers.argon2._Argon2Common.using" , List .of (new Argon2PasswordHasherValidator (3 , 4 , 5 ))),
@@ -254,8 +274,10 @@ private static void checkDjangoHasher(SubscriptionContext subscriptionContext) {
254274 private void registerTypeCheckers (SubscriptionContext subscriptionContext ) {
255275 argon2CheapestProfileTypeChecker = subscriptionContext .typeChecker ().typeCheckBuilder ().isTypeWithFqn ("argon2.profiles.CHEAPEST" );
256276 flaskConfigTypeChecker = subscriptionContext .typeChecker ().typeCheckBuilder ().isInstanceOf ("flask.config.Config" );
277+ argon2IDTypeChecker = subscriptionContext .typeChecker ().typeCheckBuilder ().isTypeWithFqn ("argon2.low_level.Type.ID" );
278+ argon2VersionTypeChecker = subscriptionContext .typeChecker ().typeCheckBuilder ().isTypeWithFqn ("argon2.low_level.ARGON2_VERSION" );
257279 typeCheckMap = new TypeCheckMap <>();
258- CALL_EXPRESSION_VALIDATORS .forEach ((key , value ) -> {
280+ callExpressionValidators .forEach ((key , value ) -> {
259281 var typeCheckBuilder = subscriptionContext .typeChecker ().typeCheckBuilder ().isTypeWithFqn (key );
260282 typeCheckMap .put (typeCheckBuilder , value );
261283 });
0 commit comments