SHA1.swift 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. //
  2. // SHA1.swift
  3. // CryptoSwift
  4. //
  5. // Created by Marcin Krzyzanowski on 16/08/14.
  6. // Copyright (c) 2014 Marcin Krzyzanowski. All rights reserved.
  7. //
  8. final class SHA1 : HashProtocol {
  9. static let size:Int = 20 // 160 / 8
  10. let message: [UInt8]
  11. init(_ message: [UInt8]) {
  12. self.message = message
  13. }
  14. private let h:[UInt32] = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]
  15. func calculate() -> [UInt8] {
  16. var tmpMessage = self.prepare(64)
  17. // hash values
  18. var hh = h
  19. // append message length, in a 64-bit big-endian integer. So now the message length is a multiple of 512 bits.
  20. tmpMessage += (self.message.count * 8).bytes(64 / 8)
  21. // Process the message in successive 512-bit chunks:
  22. let chunkSizeBytes = 512 / 8 // 64
  23. for chunk in BytesSequence(chunkSize: chunkSizeBytes, data: tmpMessage) {
  24. // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15, big-endian
  25. // Extend the sixteen 32-bit words into eighty 32-bit words:
  26. var M:[UInt32] = [UInt32](count: 80, repeatedValue: 0)
  27. for x in 0..<M.count {
  28. switch (x) {
  29. case 0...15:
  30. let start = chunk.startIndex + (x * sizeofValue(M[x]))
  31. let end = start + sizeofValue(M[x])
  32. let le = toUInt32Array(chunk[start..<end])[0]
  33. M[x] = le.bigEndian
  34. break
  35. default:
  36. M[x] = rotateLeft(M[x-3] ^ M[x-8] ^ M[x-14] ^ M[x-16], 1) //FIXME: n:
  37. break
  38. }
  39. }
  40. var A = hh[0]
  41. var B = hh[1]
  42. var C = hh[2]
  43. var D = hh[3]
  44. var E = hh[4]
  45. // Main loop
  46. for j in 0...79 {
  47. var f: UInt32 = 0;
  48. var k: UInt32 = 0
  49. switch (j) {
  50. case 0...19:
  51. f = (B & C) | ((~B) & D)
  52. k = 0x5A827999
  53. break
  54. case 20...39:
  55. f = B ^ C ^ D
  56. k = 0x6ED9EBA1
  57. break
  58. case 40...59:
  59. f = (B & C) | (B & D) | (C & D)
  60. k = 0x8F1BBCDC
  61. break
  62. case 60...79:
  63. f = B ^ C ^ D
  64. k = 0xCA62C1D6
  65. break
  66. default:
  67. break
  68. }
  69. let temp = (rotateLeft(A,5) &+ f &+ E &+ M[j] &+ k) & 0xffffffff
  70. E = D
  71. D = C
  72. C = rotateLeft(B, 30)
  73. B = A
  74. A = temp
  75. }
  76. hh[0] = (hh[0] &+ A) & 0xffffffff
  77. hh[1] = (hh[1] &+ B) & 0xffffffff
  78. hh[2] = (hh[2] &+ C) & 0xffffffff
  79. hh[3] = (hh[3] &+ D) & 0xffffffff
  80. hh[4] = (hh[4] &+ E) & 0xffffffff
  81. }
  82. // Produce the final hash value (big-endian) as a 160 bit number:
  83. var result = [UInt8]()
  84. result.reserveCapacity(hh.count / 4)
  85. hh.forEach {
  86. let item = $0.bigEndian
  87. result += [UInt8(item & 0xff), UInt8((item >> 8) & 0xff), UInt8((item >> 16) & 0xff), UInt8((item >> 24) & 0xff)]
  88. }
  89. return result
  90. }
  91. }