HMAC.swift 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  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 sha256(_ key: [UInt8], _ message: [UInt8]) -> [UInt8] {
  24. return generate(key, message, (blockSize: 64, { block in
  25. return SHA256.hash(block)
  26. }))
  27. }
  28. public static func sha256(_ key: [UInt8], _ message: [UInt8]) -> String {
  29. return sha256(key, message).hex()
  30. }
  31. public static func md5(_ key: [UInt8], _ message: [UInt8]) -> [UInt8] {
  32. return generate(key, message, (blockSize: 64, { block in
  33. return MD5.hash(block)
  34. }))
  35. }
  36. public static func md5(_ key: [UInt8], _ message: [UInt8]) -> String {
  37. let digest: [UInt8] = md5(key, message)
  38. return digest.hex()
  39. }
  40. public static func generate(_ key: [UInt8], _ message: [UInt8], _ setup: (blockSize: Int, hash: ([UInt8]) -> [UInt8])) -> [UInt8] {
  41. var paddedKey = key
  42. if paddedKey.count > setup.blockSize {
  43. paddedKey = setup.hash(paddedKey)
  44. } else if paddedKey.count < setup.blockSize {
  45. paddedKey = paddedKey + [UInt8](repeating: 0, count: setup.blockSize - paddedKey.count)
  46. }
  47. let oKeyPad = paddedKey.map { $0 ^ UInt8(0x5c) }
  48. let iKeyPad = paddedKey.map { $0 ^ UInt8(0x36) }
  49. return setup.hash(oKeyPad + setup.hash(iKeyPad + message))
  50. }
  51. }