SHA1.swift 3.5 KB

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