CodeQL documentation

Use of an inappropriate cryptographic hashing algorithm on passwords

ID: swift/weak-password-hashing
Kind: path-problem
Security severity: 7.5
Severity: warning
Precision: high
Tags:
   - security
   - external/cwe/cwe-327
   - external/cwe/cwe-328
   - external/cwe/cwe-916
Query suites:
   - swift-code-scanning.qls
   - swift-security-extended.qls
   - swift-security-and-quality.qls

Click to see the query in the CodeQL repository

Hash functions that are not sufficiently computationally hard can leave data vulnerable. You should not use such functions for password hashing.

A strong cryptographic hash function should be resistant to:

  • Pre-image attacks. If you know a hash value h(x), you should not be able to easily find the input x.

  • Collision attacks. If you know a hash value h(x), you should not be able to easily find a different input y with the same hash value h(x) = h(y).

  • Brute force. If you know a hash value h(x), you should not be able to find an input y that computes to that hash value using brute force attacks without significant computational effort. All of MD5, SHA-1, SHA-2 and SHA-3 are weak against offline brute forcing, since they are not sufficiently computationally hard. This includes SHA-224, SHA-256, SHA-384 and SHA-512, which are in the SHA-2 family.

Password hashing algorithms should be slow and/or memory intensive to compute, to make brute force attacks more difficult.

Recommendation

For password storage, you should use a sufficiently computationally hard cryptographic hash function, such as one of the following:

  • Argon2

  • scrypt

  • bcrypt

  • PBKDF2

Example

The following examples show two versions of the same function. In both cases, a password is hashed using a cryptographic hashing algorithm. In the first case, the SHA-512 hashing algorithm is used. It is vulnerable to offline brute force attacks:

let passwordData = Data(passwordString.utf8)
let passwordHash = Crypto.SHA512.hash(data: passwordData) // BAD: SHA-512 is not suitable for password hashing.

// ...

if Crypto.SHA512.hash(data: Data(passwordString.utf8)) == passwordHash {
    // ...
}

Here is the same function using Argon2, which is suitable for password hashing:

import Argon2Swift

let salt = Salt.newSalt()
let result = try! Argon2Swift.hashPasswordString(password: passwordString, salt: salt) // GOOD: Argon2 is suitable for password hashing.
let passwordHash = result.encodedString()

// ...

if try! Argon2Swift.verifyHashString(password: passwordString, hash: passwordHash) {
    // ...
}

References

  • © GitHub, Inc.
  • Terms
  • Privacy