HMAC.swift 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. //
  2. // HMAC.swift
  3. // Swifter
  4. //
  5. // Copyright © 2016 Damian Kołakowski. All rights reserved.
  6. //
  7. import Foundation
  8. public struct HMAC {
  9. //
  10. // HMAC: Keyed-Hashing for Message Authentication
  11. //
  12. // https://en.wikipedia.org/wiki/Hash-based_message_authentication_code
  13. // https://tools.ietf.org/html/rfc2104
  14. //
  15. public static func sha1(_ key: [UInt8], _ message: [UInt8]) -> [UInt8] {
  16. return generate(key, message, (blockSize: 64, { block in
  17. return SHA1.hash(block)
  18. }))
  19. }
  20. public static func sha1(_ key: [UInt8], _ message: [UInt8]) -> String {
  21. return sha1(key, message).hex()
  22. }
  23. public static func md5(_ key: [UInt8], _ message: [UInt8]) -> [UInt8] {
  24. return generate(key, message, (blockSize: 64, { block in
  25. return MD5.hash(block)
  26. }))
  27. }
  28. public static func md5(_ key: [UInt8], _ message: [UInt8]) -> String {
  29. return md5(key, message).hex()
  30. }
  31. public static func generate(_ key: [UInt8], _ message: [UInt8], _ setup: (blockSize: Int, hash: (([UInt8]) -> [UInt8]))) -> [UInt8] {
  32. var paddedKey = key
  33. if paddedKey.count > setup.blockSize {
  34. paddedKey = setup.hash(paddedKey)
  35. } else if paddedKey.count < setup.blockSize {
  36. paddedKey = paddedKey + [UInt8](repeating: 0, count: setup.blockSize - paddedKey.count)
  37. }
  38. let oKeyPad = paddedKey.map { $0 ^ UInt8(0x5c) }
  39. let iKeyPad = paddedKey.map { $0 ^ UInt8(0x36) }
  40. return setup.hash(oKeyPad + setup.hash(iKeyPad + message))
  41. }
  42. }