SHA3.swift 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. //
  2. // SHA3.swift
  3. // CryptoSwift
  4. //
  5. // Created by Marcin Krzyzanowski on 23/09/16.
  6. // Copyright © 2016 Marcin Krzyzanowski. All rights reserved.
  7. //
  8. // http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
  9. // http://keccak.noekeon.org/specs_summary.html
  10. //
  11. #if os(Linux) || os(Android) || os(FreeBSD)
  12. import Glibc
  13. #else
  14. import Darwin
  15. #endif
  16. public final class SHA3: DigestType {
  17. let round_constants: Array<UInt64> = [0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000,
  18. 0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
  19. 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
  20. 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003,
  21. 0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A,
  22. 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008]
  23. let variant: Variant
  24. fileprivate var accumulated = Array<UInt8>()
  25. fileprivate var accumulatedLength: Int = 0
  26. fileprivate var accumulatedHash:Array<UInt64>
  27. public enum Variant: RawRepresentable {
  28. case sha224, sha256, sha384, sha512
  29. public var digestLength:Int {
  30. return 100 - (self.blockSize / 2)
  31. }
  32. public var blockSize: Int {
  33. return (1600 - self.rawValue * 2) / 8
  34. }
  35. public typealias RawValue = Int
  36. public var rawValue: RawValue {
  37. switch self {
  38. case .sha224:
  39. return 224
  40. case .sha256:
  41. return 256
  42. case .sha384:
  43. return 384
  44. case .sha512:
  45. return 512
  46. }
  47. }
  48. public init?(rawValue: RawValue) {
  49. switch (rawValue) {
  50. case 224:
  51. self = .sha224
  52. break;
  53. case 256:
  54. self = .sha256
  55. break;
  56. case 384:
  57. self = .sha384
  58. break;
  59. case 512:
  60. self = .sha512
  61. break;
  62. default:
  63. return nil
  64. }
  65. }
  66. }
  67. public init(variant: SHA3.Variant) {
  68. self.variant = variant
  69. self.accumulatedHash = Array<UInt64>(repeating: 0, count: self.variant.digestLength)
  70. }
  71. /// 1. For all pairs (x,z) such that 0≤x<5 and 0≤z<w, let
  72. /// C[x,z]=A[x, 0,z] ⊕ A[x, 1,z] ⊕ A[x, 2,z] ⊕ A[x, 3,z] ⊕ A[x, 4,z].
  73. /// 2. For all pairs (x, z) such that 0≤x<5 and 0≤z<w let
  74. /// D[x,z]=C[(x1) mod 5, z] ⊕ C[(x+1) mod 5, (z –1) mod w].
  75. /// 3. For all triples (x, y, z) such that 0≤x<5, 0≤y<5, and 0≤z<w, let
  76. /// A′[x, y,z] = A[x, y,z] ⊕ D[x,z].
  77. private func θ(_ a: inout Array<UInt64>) {
  78. var c = Array<UInt64>(repeating: 0, count: 5)
  79. var d = Array<UInt64>(repeating: 0, count: 5)
  80. for i in 0..<5 {
  81. c[i] = a[i] ^ a[i + 5] ^ a[i + 10] ^ a[i + 15] ^ a[i + 20]
  82. }
  83. d[0] = rotateLeft(c[1], by: 1) ^ c[4]
  84. d[1] = rotateLeft(c[2], by: 1) ^ c[0]
  85. d[2] = rotateLeft(c[3], by: 1) ^ c[1]
  86. d[3] = rotateLeft(c[4], by: 1) ^ c[2]
  87. d[4] = rotateLeft(c[0], by: 1) ^ c[3]
  88. for i in 0..<5 {
  89. a[i] ^= d[i]
  90. a[i + 5] ^= d[i]
  91. a[i + 10] ^= d[i]
  92. a[i + 15] ^= d[i]
  93. a[i + 20] ^= d[i]
  94. }
  95. }
  96. /// A′[x, y, z]=A[(x + 3y) mod 5, x, z]
  97. private func π(_ a: inout Array<UInt64>) {
  98. let a1 = a[1]
  99. a[1] = a[6]
  100. a[6] = a[9]
  101. a[9] = a[22]
  102. a[22] = a[14]
  103. a[14] = a[20]
  104. a[20] = a[2]
  105. a[2] = a[12]
  106. a[12] = a[13]
  107. a[13] = a[19]
  108. a[19] = a[23]
  109. a[23] = a[15]
  110. a[15] = a[4]
  111. a[4] = a[24]
  112. a[24] = a[21]
  113. a[21] = a[8]
  114. a[8] = a[16]
  115. a[16] = a[5]
  116. a[5] = a[3]
  117. a[3] = a[18]
  118. a[18] = a[17]
  119. a[17] = a[11]
  120. a[11] = a[7]
  121. a[7] = a[10]
  122. a[10] = a1
  123. }
  124. /// For all triples (x, y, z) such that 0≤x<5, 0≤y<5, and 0≤z<w, let
  125. /// A′[x, y,z] = A[x, y,z] ⊕ ((A[(x+1) mod 5, y, z] ⊕ 1) ⋅ A[(x+2) mod 5, y, z])
  126. private func χ(_ a: inout Array<UInt64>) {
  127. for i in stride(from: 0, to: 25, by: 5) {
  128. let a0 = a[0 + i]
  129. let a1 = a[1 + i]
  130. a[0 + i] ^= ~a1 & a[2 + i]
  131. a[1 + i] ^= ~a[2 + i] & a[3 + i]
  132. a[2 + i] ^= ~a[3 + i] & a[4 + i]
  133. a[3 + i] ^= ~a[4 + i] & a0
  134. a[4 + i] ^= ~a0 & a1
  135. }
  136. }
  137. private func ι(_ a: inout Array<UInt64>, round: Int) {
  138. a[0] ^= round_constants[round]
  139. }
  140. fileprivate func process<C: Collection>(block chunk: C, currentHash hh: inout Array<UInt64>) where C.Iterator.Element == UInt64, C.Index == Int {
  141. // expand
  142. hh[0] ^= chunk[0].littleEndian
  143. hh[1] ^= chunk[1].littleEndian
  144. hh[2] ^= chunk[2].littleEndian
  145. hh[3] ^= chunk[3].littleEndian
  146. hh[4] ^= chunk[4].littleEndian
  147. hh[5] ^= chunk[5].littleEndian
  148. hh[6] ^= chunk[6].littleEndian
  149. hh[7] ^= chunk[7].littleEndian
  150. hh[8] ^= chunk[8].littleEndian
  151. if self.variant.blockSize > 72 { // 72 / 8, sha-512
  152. hh[9] ^= chunk[9 ].littleEndian
  153. hh[10] ^= chunk[10].littleEndian
  154. hh[11] ^= chunk[11].littleEndian
  155. hh[12] ^= chunk[12].littleEndian
  156. if self.variant.blockSize > 104 { // 104 / 8, sha-384
  157. hh[13] ^= chunk[13].littleEndian
  158. hh[14] ^= chunk[14].littleEndian
  159. hh[15] ^= chunk[15].littleEndian
  160. hh[16] ^= chunk[16].littleEndian
  161. if self.variant.blockSize > 136 { // 136 / 8, sha-256
  162. hh[17] ^= chunk[17].littleEndian
  163. // FULL_SHA3_FAMILY_SUPPORT
  164. if self.variant.blockSize > 144 { // 144 / 8, sha-224
  165. hh[18] ^= chunk[18].littleEndian
  166. hh[19] ^= chunk[19].littleEndian
  167. hh[20] ^= chunk[20].littleEndian
  168. hh[21] ^= chunk[21].littleEndian
  169. hh[22] ^= chunk[22].littleEndian
  170. hh[23] ^= chunk[23].littleEndian
  171. hh[24] ^= chunk[24].littleEndian
  172. }
  173. }
  174. }
  175. }
  176. // Keccak-f
  177. for round in 0..<24 {
  178. θ(&hh)
  179. hh[1] = rotateLeft(hh[1], by: 1)
  180. hh[2] = rotateLeft(hh[2], by: 62)
  181. hh[3] = rotateLeft(hh[3], by: 28)
  182. hh[4] = rotateLeft(hh[4], by: 27)
  183. hh[5] = rotateLeft(hh[5], by: 36)
  184. hh[6] = rotateLeft(hh[6], by: 44)
  185. hh[7] = rotateLeft(hh[7], by: 6)
  186. hh[8] = rotateLeft(hh[8], by: 55)
  187. hh[9] = rotateLeft(hh[9], by: 20)
  188. hh[10] = rotateLeft(hh[10], by: 3)
  189. hh[11] = rotateLeft(hh[11], by: 10)
  190. hh[12] = rotateLeft(hh[12], by: 43)
  191. hh[13] = rotateLeft(hh[13], by: 25)
  192. hh[14] = rotateLeft(hh[14], by: 39)
  193. hh[15] = rotateLeft(hh[15], by: 41)
  194. hh[16] = rotateLeft(hh[16], by: 45)
  195. hh[17] = rotateLeft(hh[17], by: 15)
  196. hh[18] = rotateLeft(hh[18], by: 21)
  197. hh[19] = rotateLeft(hh[19], by: 8)
  198. hh[20] = rotateLeft(hh[20], by: 18)
  199. hh[21] = rotateLeft(hh[21], by: 2)
  200. hh[22] = rotateLeft(hh[22], by: 61)
  201. hh[23] = rotateLeft(hh[23], by: 56)
  202. hh[24] = rotateLeft(hh[24], by: 14)
  203. π(&hh)
  204. χ(&hh)
  205. ι(&hh, round: round)
  206. }
  207. }
  208. func calculate(for bytes: Array<UInt8>) -> Array<UInt8> {
  209. do {
  210. return try self.update(withBytes: bytes, isLast: true)
  211. } catch {
  212. return []
  213. }
  214. }
  215. }
  216. extension SHA3: Updatable {
  217. public func update<T: Sequence>(withBytes bytes: T, isLast: Bool = false) throws -> Array<UInt8> where T.Iterator.Element == UInt8 {
  218. let prevAccumulatedLength = self.accumulated.count
  219. self.accumulated += bytes
  220. self.accumulatedLength += self.accumulated.count - prevAccumulatedLength //avoid Array(bytes).count
  221. if isLast {
  222. // Add padding
  223. if self.accumulated.count == 0 || self.accumulated.count % self.variant.blockSize != 0 {
  224. let r = self.variant.blockSize * 8
  225. let q = (r/8) - (self.accumulated.count % (r/8))
  226. self.accumulated += Array<UInt8>(repeating: 0, count: q)
  227. }
  228. self.accumulated[self.accumulatedLength] |= 0x06 // 0x1F for SHAKE
  229. self.accumulated[self.accumulated.count - 1] |= 0x80
  230. }
  231. for chunk in BytesSequence(chunkSize: self.variant.blockSize, data: self.accumulated) {
  232. if (isLast || self.accumulated.count >= self.variant.blockSize) {
  233. self.process(block: chunk.toUInt64Array(), currentHash: &self.accumulatedHash)
  234. self.accumulated.removeFirst(chunk.count)
  235. }
  236. }
  237. //TODO: verify performance, reduce vs for..in
  238. let result = self.accumulatedHash.reduce(Array<UInt8>()) { (result, value) -> Array<UInt8> in
  239. return result + value.bigEndian.bytes()
  240. }
  241. // reset hash value for instance
  242. if isLast {
  243. self.accumulatedHash = Array<UInt64>(repeating: 0, count: self.variant.digestLength)
  244. }
  245. return Array(result[0..<self.variant.digestLength])
  246. }
  247. }