Fixed salts in Swift

Fixed salts in Swift

Description

A fixed salt in password hashing or key derivation makes identical inputs produce identical results under the same algorithm and settings. An attacker can reuse the computation for a password candidate across multiple users.

Potential impact

  • Lower cost for dictionary attacks.
  • Easier identification of users with the same password.
  • Greater chance of recovering passwords from stolen hashes.

Remediation

  1. Generate a cryptographically secure random salt for each user/password.
  2. Store the salt with the hash if needed, but do not fix it as a constant in code.
  3. Use the salt-generation API of a reviewed password-hashing library. Choose an appropriate algorithm and work factor as well; a salt does not replace those controls.

Examples

Before

swift
try PKCS5.PBKDF2(
    password: password,
    salt: Array<UInt8>("staticSalt".utf8),
    iterations: 600000,
    keyLength: 32).calculate()

After

swift
import CryptoSwift

func derivePasswordKey(
    password: [UInt8]
) throws -> (salt: [UInt8], derivedKey: [UInt8]) {
    let salt = (0..<16).map { _ in UInt8.random(in: 0...UInt8.max) }
    let derivedKey = try PKCS5.PBKDF2(
        password: password, salt: salt, iterations: 600000, keyLength: 32
    ).calculate()
    return (salt, derivedKey)
}

Explanation:

  • Before: Sharing a salt across users lets an attacker reuse previously computed password candidates.
  • After: Each hash uses a new random salt. Store it with the derived key so it is available for later verification.

References