Skip to content

Instantly share code, notes, and snippets.

@laevandus
Last active April 12, 2022 12:40
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save laevandus/8939df8acaa3d883829d509e8f408a9f to your computer and use it in GitHub Desktop.
Save laevandus/8939df8acaa3d883829d509e8f408a9f to your computer and use it in GitHub Desktop.
import Foundation
import CommonCrypto
extension Data {
enum Algorithm {
case md5
case sha1
case sha224
case sha256
case sha384
case sha512
var digestLength: Int {
switch self {
case .md5: return Int(CC_MD5_DIGEST_LENGTH)
case .sha1: return Int(CC_SHA1_DIGEST_LENGTH)
case .sha224: return Int(CC_SHA224_DIGEST_LENGTH)
case .sha256: return Int(CC_SHA256_DIGEST_LENGTH)
case .sha384: return Int(CC_SHA384_DIGEST_LENGTH)
case .sha512: return Int(CC_SHA512_DIGEST_LENGTH)
}
}
}
}
extension Data.Algorithm: RawRepresentable {
typealias RawValue = Int
init?(rawValue: Int) {
switch rawValue {
case kCCHmacAlgMD5: self = .md5
case kCCHmacAlgSHA1: self = .sha1
case kCCHmacAlgSHA224: self = .sha224
case kCCHmacAlgSHA256: self = .sha256
case kCCHmacAlgSHA384: self = .sha384
case kCCHmacAlgSHA512: self = .sha512
default: return nil
}
}
var rawValue: Int {
switch self {
case .md5: return kCCHmacAlgMD5
case .sha1: return kCCHmacAlgSHA1
case .sha224: return kCCHmacAlgSHA224
case .sha256: return kCCHmacAlgSHA256
case .sha384: return kCCHmacAlgSHA384
case .sha512: return kCCHmacAlgSHA512
}
}
}
extension Data {
func authenticationCode(for algorithm: Algorithm, secretKey: String = "") -> Data {
guard let secretKeyData = secretKey.data(using: .utf8) else { fatalError() }
return authenticationCode(for: algorithm, secretKey: secretKeyData)
}
func authenticationCode(for algorithm: Algorithm, secretKey: Data) -> Data {
let hashBytes = UnsafeMutablePointer<UInt8>.allocate(capacity: algorithm.digestLength)
defer { hashBytes.deallocate() }
withUnsafeBytes { (bytes) -> Void in
secretKey.withUnsafeBytes { (secretKeyBytes) -> Void in
CCHmac(CCHmacAlgorithm(algorithm.rawValue), secretKeyBytes, secretKey.count, bytes, count, hashBytes)
}
}
return Data(bytes: hashBytes, count: algorithm.digestLength)
}
}
@maciekish
Copy link

This is very helpful, but XCode 13 is warning about a deprecation:

'withUnsafeBytes' is deprecated: use `withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R` instead

Any chance to update this please?

@laevandus
Copy link
Author

Hi, since I wrote this Apple released CryptoKit and that framework contains implementations for these as well. I would suggest using that instead. Example, SHA512

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment