SHA256.swift 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. //
  2. // SHA256.swift
  3. // Swifter
  4. //
  5. // Copyright © 2016 Damian Kołakowski. All rights reserved.
  6. //
  7. #if os(Linux)
  8. import Glibc
  9. #else
  10. import Foundation
  11. #endif
  12. public struct SHA256 {
  13. public static func hash(_ input: [UInt8]) -> [UInt8] {
  14. // Alghorithm from: https://en.wikipedia.org/wiki/SHA-2
  15. // http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
  16. var message = input
  17. var h0 = UInt32(littleEndian: 0x6a09e667)
  18. var h1 = UInt32(littleEndian: 0xbb67ae85)
  19. var h2 = UInt32(littleEndian: 0x3c6ef372)
  20. var h3 = UInt32(littleEndian: 0xa54ff53a)
  21. var h4 = UInt32(littleEndian: 0x510e527f)
  22. var h5 = UInt32(littleEndian: 0x9b05688c)
  23. var h6 = UInt32(littleEndian: 0x1f83d9ab)
  24. var h7 = UInt32(littleEndian: 0x5be0cd19)
  25. // ml = message length in bits (always a multiple of the number of bits in a character).
  26. let ml = UInt64(message.count * 8)
  27. // append the bit '1' to the message e.g. by adding 0x80 if message length is a multiple of 8 bits.
  28. message.append(0x80)
  29. // append 0 ≤ k < 512 bits '0', such that the resulting message length in bits is congruent to −64 ≡ 448 (mod 512)
  30. let padBytesCount = ( message.count + 8 ) % 64
  31. message.append(contentsOf: [UInt8](repeating: 0, count: 64 - padBytesCount))
  32. // append ml, in a 64-bit big-endian integer. Thus, the total length is a multiple of 512 bits.
  33. var mlBigEndian = ml.bigEndian
  34. withUnsafePointer(&mlBigEndian) {
  35. message.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 8)))
  36. }
  37. // Process the message in successive 512-bit chunks ( 64 bytes chunks ):
  38. for chunkStart in 0..<message.count/64 {
  39. var words = [UInt32](repeating: 0, count: 64)
  40. let chunk = message[chunkStart*64..<chunkStart*64+64]
  41. // Break chunk into sixteen 32-bit big-endian words w[i], 0 ≤ i ≤ 15
  42. for i in 0...15 {
  43. let value = chunk.withUnsafeBufferPointer({ UnsafePointer<UInt32>($0.baseAddress! + (i*4)).pointee})
  44. words[i] = value.bigEndian
  45. }
  46. // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array:
  47. for i in 16..<words.count {
  48. let s0 = (rotateRight(words[i-15], 7)) ^ (rotateRight(words[i-15], 18)) ^ (words[i-15] >> 3 )
  49. let s1 = (rotateRight(words[i-2 ], 17)) ^ (rotateRight(words[i-2 ], 19)) ^ (words[i-2 ] >> 10)
  50. words[i] = words[i-16] &+ s0 &+ words[i-7] &+ s1
  51. }
  52. // Initialize hash value for this chunk:
  53. var a = h0
  54. var b = h1
  55. var c = h2
  56. var d = h3
  57. var e = h4
  58. var f = h5
  59. var g = h6
  60. var h = h7
  61. for i in 0...63 {
  62. let S0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22)
  63. let S1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25)
  64. let ch = (e & f) ^ ((~e) & g)
  65. let maj = (a & b) ^ (a & c) ^ (b & c)
  66. let temp1 = h &+ S1 &+ ch &+ K[i] &+ words[i]
  67. let temp2 = S0 &+ maj
  68. h = g
  69. g = f
  70. f = e
  71. e = d &+ temp1
  72. d = c
  73. c = b
  74. b = a
  75. a = temp1 &+ temp2
  76. }
  77. // Add this chunk's hash to result so far:
  78. h0 = ( h0 &+ a )
  79. h1 = ( h1 &+ b )
  80. h2 = ( h2 &+ c )
  81. h3 = ( h3 &+ d )
  82. h4 = ( h4 &+ e )
  83. h5 = ( h5 &+ f )
  84. h6 = ( h6 &+ g )
  85. h7 = ( h7 &+ h )
  86. }
  87. // Produce the final hash value (big-endian):
  88. var digest = [UInt8]()
  89. h0 = h0.bigEndian
  90. h1 = h1.bigEndian
  91. h2 = h2.bigEndian
  92. h3 = h3.bigEndian
  93. h4 = h4.bigEndian
  94. h5 = h5.bigEndian
  95. h6 = h6.bigEndian
  96. h7 = h7.bigEndian
  97. withUnsafePointer(&h0) {
  98. digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
  99. }
  100. withUnsafePointer(&h1) {
  101. digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
  102. }
  103. withUnsafePointer(&h2) {
  104. digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
  105. }
  106. withUnsafePointer(&h3) {
  107. digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
  108. }
  109. withUnsafePointer(&h4) {
  110. digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
  111. }
  112. withUnsafePointer(&h5) {
  113. digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
  114. }
  115. withUnsafePointer(&h6) {
  116. digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
  117. }
  118. withUnsafePointer(&h7) {
  119. digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
  120. }
  121. return digest
  122. }
  123. private static func rotateRight(_ v : UInt32, _ n: UInt32) -> UInt32 {
  124. return (v >> n) | (v << (32 - n))
  125. }
  126. private static func rotateLeft(_ v: UInt32, _ n: UInt32) -> UInt32 {
  127. return ((v << n) & 0xFFFFFFFF) | (v >> (32 - n))
  128. }
  129. private static var K: [UInt32] = [
  130. 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  131. 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  132. 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  133. 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  134. 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  135. 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  136. 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  137. 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
  138. ]
  139. }
  140. extension String {
  141. public func sha256() -> String {
  142. return self.sha256().hex()
  143. }
  144. public func sha256() -> [UInt8] {
  145. return SHA256.hash([UInt8](self.utf8))
  146. }
  147. }