Skip to main content

Insecure encryption algorithm - SHA1

Need

Upgrade to a secure encryption algorithm

Context

  • Usage of Swift for iOS and macOS app development
  • Usage of CommonCrypto for cryptographic operations

Description

Non compliant code

import CommonCrypto

func sha1Hash(_ string: String) -> String {
let data = string.data(using: .utf8)!
var digest = [UInt8](repeating: 0, count:Int(CC_SHA1_DIGEST_LENGTH))
data.withUnsafeBytes {
_ = CC_SHA1($0.baseAddress, CC_LONG(data.count), &digest)
}
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joined()
}

let password = "password123"
let hashedPassword = sha1Hash(password)
print("SHA1 Hashed Password: \\(hashedPassword)")

The code above is a Swift function that hashes a string using SHA1, an insecure encryption algorithm. SHA1 (Secure Hash Algorithm 1) is a cryptographic hash function that takes an input (or 'message') and returns a fixed-size (160-bit) hash value.

In the code, the sha1Hash function takes a string as input and converts it to a byte array (data). This byte array is then hashed using the CC_SHA1 function from the CommonCrypto library, which is included in the iOS SDK. The resulting hash is a byte array (digest) which is then converted to a hexadecimal string (hexBytes) and returned.

The problem with this code is that SHA1 is considered insecure. It has been proven that SHA1 is vulnerable to collision attacks, which means that two different inputs can produce the same hash. In the context of password storage, an attacker can take advantage of this vulnerability to guess the password.

For instance, the password variable in the code is a clear text password that is being hashed using the insecure sha1Hash function. An attacker who gains access to these hashed passwords could potentially reverse-engineer them, despite the hashing, due to the known vulnerabilities in SHA1.

Steps

  • Replace the usage of SHA1 algorithm with a more secure hashing algorithm, such as SHA256 or bcrypt.
  • Update the code to use a secure cryptographic library or framework that provides secure hashing functions.
  • Ensure that the chosen hashing algorithm is resistant to pre-image attacks and has a sufficiently long output length.
  • Consider using a salt value when hashing passwords to further enhance security.
  • Regularly update the cryptographic libraries and frameworks used in the application to ensure they are up-to-date with the latest security patches.

Compliant code

import CommonCrypto

func sha256Hash(_ string: String) -> String {
let data = string.data(using: .utf8)!
var digest = [UInt8](repeating: 0, count:Int(CC_SHA256_DIGEST_LENGTH))
data.withUnsafeBytes {
_ = CC_SHA256($0.baseAddress, CC_LONG(data.count), &digest)
}
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joined()
}

let password = "password123"
let hashedPassword = sha256Hash(password)
print("SHA256 Hashed Password: \\(hashedPassword)")

The above code is a revised version of the original code that was using the insecure SHA1 hashing algorithm. The new code now uses the more secure SHA256 hashing algorithm.

The function sha256Hash(_:) takes a string as input and returns its SHA256 hash. The string is first converted to data using UTF-8 encoding. Then, a digest array of UInt8 is created with a count equal to CC_SHA256_DIGEST_LENGTH.

The withUnsafeBytes method is used to perform a closure while ensuring the data remains valid. Inside the closure, the CC_SHA256 function is called to perform the hashing operation. The base address of the data and the count of the data are passed as arguments, along with the digest array.

After the hashing operation, the digest array is converted to hexadecimal strings and joined together to form the final hashed string.

The password is then hashed using the sha256Hash(_:) function and printed.

This code is more secure than the original code as it uses a stronger hashing algorithm. However, it is recommended to use a salt value when hashing passwords to further enhance security. Also, it is important to regularly update the cryptographic libraries and frameworks used in the application to ensure they are up-to-date with the latest security patches.

References