MD5.swift 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. // swiftlint:disable comma function_parameter_count variable_name syntactic_sugar function_body_length vertical_whitespace
  2. // https://github.com/onmyway133/SwiftHash/blob/master/Sources/MD5.swift
  3. /*
  4. * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
  5. * Digest Algorithm, as defined in RFC 1321.
  6. * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
  7. * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
  8. * Distributed under the BSD License
  9. * See http://pajhome.org.uk/crypt/md5 for more info.
  10. */
  11. /**
  12. * SwiftHash
  13. * Copyright (c) Khoa Pham 2017
  14. * Licensed under the MIT license. See LICENSE file.
  15. */
  16. import Foundation
  17. // MARK: - Public
  18. public func MD5(_ input: String) -> String {
  19. return hex_md5(input)
  20. }
  21. // MARK: - Functions
  22. func hex_md5(_ input: String) -> String {
  23. return rstr2hex(rstr_md5(str2rstr_utf8(input)))
  24. }
  25. func str2rstr_utf8(_ input: String) -> [CUnsignedChar] {
  26. return Array(input.utf8)
  27. }
  28. func rstr2tr(_ input: [CUnsignedChar]) -> String {
  29. var output: String = ""
  30. input.forEach {
  31. output.append(String(UnicodeScalar($0)))
  32. }
  33. return output
  34. }
  35. /*
  36. * Convert a raw string to a hex string
  37. */
  38. func rstr2hex(_ input: [CUnsignedChar]) -> String {
  39. let hexTab: [Character] = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"]
  40. var output: [Character] = []
  41. for i in 0..<input.count {
  42. let x = input[i]
  43. let value1 = hexTab[Int((x >> 4) & 0x0F)]
  44. let value2 = hexTab[Int(Int32(x) & 0x0F)]
  45. output.append(value1)
  46. output.append(value2)
  47. }
  48. return String(output)
  49. }
  50. /*
  51. * Convert a raw string to an array of little-endian words
  52. * Characters >255 have their high-byte silently ignored.
  53. */
  54. func rstr2binl(_ input: [CUnsignedChar]) -> [Int32] {
  55. var output: [Int: Int32] = [:]
  56. for i in stride(from: 0, to: input.count * 8, by: 8) {
  57. let value: Int32 = (Int32(input[i/8]) & 0xFF) << (Int32(i) % 32)
  58. output[i >> 5] = unwrap(output[i >> 5]) | value
  59. }
  60. return dictionary2array(output)
  61. }
  62. /*
  63. * Convert an array of little-endian words to a string
  64. */
  65. func binl2rstr(_ input: [Int32]) -> [CUnsignedChar] {
  66. var output: [CUnsignedChar] = []
  67. for i in stride(from: 0, to: input.count * 32, by: 8) {
  68. // [i>>5] >>>
  69. let value: Int32 = zeroFillRightShift(input[i>>5], Int32(i % 32)) & 0xFF
  70. output.append(CUnsignedChar(value))
  71. }
  72. return output
  73. }
  74. /*
  75. * Calculate the MD5 of a raw string
  76. */
  77. func rstr_md5(_ input: [CUnsignedChar]) -> [CUnsignedChar] {
  78. return binl2rstr(binl_md5(rstr2binl(input), input.count * 8))
  79. }
  80. /*
  81. * Add integers, wrapping at 2^32. This uses 16-bit operations internally
  82. * to work around bugs in some JS interpreters.
  83. */
  84. func safe_add(_ x: Int32, _ y: Int32) -> Int32 {
  85. let lsw = (x & 0xFFFF) + (y & 0xFFFF)
  86. let msw = (x >> 16) + (y >> 16) + (lsw >> 16)
  87. return (msw << 16) | (lsw & 0xFFFF)
  88. }
  89. /*
  90. * Bitwise rotate a 32-bit number to the left.
  91. */
  92. func bit_rol(_ num: Int32, _ cnt: Int32) -> Int32 {
  93. // num >>>
  94. return (num << cnt) | zeroFillRightShift(num, (32 - cnt))
  95. }
  96. /*
  97. * These funcs implement the four basic operations the algorithm uses.
  98. */
  99. func md5_cmn(_ q: Int32, _ a: Int32, _ b: Int32, _ x: Int32, _ s: Int32, _ t: Int32) -> Int32 {
  100. return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b)
  101. }
  102. func md5_ff(_ a: Int32, _ b: Int32, _ c: Int32, _ d: Int32, _ x: Int32, _ s: Int32, _ t: Int32) -> Int32 {
  103. return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t)
  104. }
  105. func md5_gg(_ a: Int32, _ b: Int32, _ c: Int32, _ d: Int32, _ x: Int32, _ s: Int32, _ t: Int32) -> Int32 {
  106. return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t)
  107. }
  108. func md5_hh(_ a: Int32, _ b: Int32, _ c: Int32, _ d: Int32, _ x: Int32, _ s: Int32, _ t: Int32) -> Int32 {
  109. return md5_cmn(b ^ c ^ d, a, b, x, s, t)
  110. }
  111. func md5_ii(_ a: Int32, _ b: Int32, _ c: Int32, _ d: Int32, _ x: Int32, _ s: Int32, _ t: Int32) -> Int32 {
  112. return md5_cmn(c ^ (b | (~d)), a, b, x, s, t)
  113. }
  114. /*
  115. * Calculate the MD5 of an array of little-endian words, and a bit length.
  116. */
  117. func binl_md5(_ input: [Int32], _ len: Int) -> [Int32] {
  118. /* append padding */
  119. var x: [Int: Int32] = [:]
  120. for (index, value) in input.enumerated() {
  121. x[index] = value
  122. }
  123. let value: Int32 = 0x80 << Int32((len) % 32)
  124. x[len >> 5] = unwrap(x[len >> 5]) | value
  125. // >>> 9
  126. let index = (((len + 64) >> 9) << 4) + 14
  127. x[index] = unwrap(x[index]) | Int32(len)
  128. var a: Int32 = 1732584193
  129. var b: Int32 = -271733879
  130. var c: Int32 = -1732584194
  131. var d: Int32 = 271733878
  132. for i in stride(from: 0, to: length(x), by: 16) {
  133. let olda: Int32 = a
  134. let oldb: Int32 = b
  135. let oldc: Int32 = c
  136. let oldd: Int32 = d
  137. a = md5_ff(a, b, c, d, unwrap(x[i + 0]), 7 , -680876936)
  138. d = md5_ff(d, a, b, c, unwrap(x[i + 1]), 12, -389564586)
  139. c = md5_ff(c, d, a, b, unwrap(x[i + 2]), 17, 606105819)
  140. b = md5_ff(b, c, d, a, unwrap(x[i + 3]), 22, -1044525330)
  141. a = md5_ff(a, b, c, d, unwrap(x[i + 4]), 7 , -176418897)
  142. d = md5_ff(d, a, b, c, unwrap(x[i + 5]), 12, 1200080426)
  143. c = md5_ff(c, d, a, b, unwrap(x[i + 6]), 17, -1473231341)
  144. b = md5_ff(b, c, d, a, unwrap(x[i + 7]), 22, -45705983)
  145. a = md5_ff(a, b, c, d, unwrap(x[i + 8]), 7 , 1770035416)
  146. d = md5_ff(d, a, b, c, unwrap(x[i + 9]), 12, -1958414417)
  147. c = md5_ff(c, d, a, b, unwrap(x[i + 10]), 17, -42063)
  148. b = md5_ff(b, c, d, a, unwrap(x[i + 11]), 22, -1990404162)
  149. a = md5_ff(a, b, c, d, unwrap(x[i + 12]), 7 , 1804603682)
  150. d = md5_ff(d, a, b, c, unwrap(x[i + 13]), 12, -40341101)
  151. c = md5_ff(c, d, a, b, unwrap(x[i + 14]), 17, -1502002290)
  152. b = md5_ff(b, c, d, a, unwrap(x[i + 15]), 22, 1236535329)
  153. a = md5_gg(a, b, c, d, unwrap(x[i + 1]), 5 , -165796510)
  154. d = md5_gg(d, a, b, c, unwrap(x[i + 6]), 9 , -1069501632)
  155. c = md5_gg(c, d, a, b, unwrap(x[i + 11]), 14, 643717713)
  156. b = md5_gg(b, c, d, a, unwrap(x[i + 0]), 20, -373897302)
  157. a = md5_gg(a, b, c, d, unwrap(x[i + 5]), 5 , -701558691)
  158. d = md5_gg(d, a, b, c, unwrap(x[i + 10]), 9 , 38016083)
  159. c = md5_gg(c, d, a, b, unwrap(x[i + 15]), 14, -660478335)
  160. b = md5_gg(b, c, d, a, unwrap(x[i + 4]), 20, -405537848)
  161. a = md5_gg(a, b, c, d, unwrap(x[i + 9]), 5 , 568446438)
  162. d = md5_gg(d, a, b, c, unwrap(x[i + 14]), 9 , -1019803690)
  163. c = md5_gg(c, d, a, b, unwrap(x[i + 3]), 14, -187363961)
  164. b = md5_gg(b, c, d, a, unwrap(x[i + 8]), 20, 1163531501)
  165. a = md5_gg(a, b, c, d, unwrap(x[i + 13]), 5 , -1444681467)
  166. d = md5_gg(d, a, b, c, unwrap(x[i + 2]), 9 , -51403784)
  167. c = md5_gg(c, d, a, b, unwrap(x[i + 7]), 14, 1735328473)
  168. b = md5_gg(b, c, d, a, unwrap(x[i + 12]), 20, -1926607734)
  169. a = md5_hh(a, b, c, d, unwrap(x[i + 5]), 4 , -378558)
  170. d = md5_hh(d, a, b, c, unwrap(x[i + 8]), 11, -2022574463)
  171. c = md5_hh(c, d, a, b, unwrap(x[i + 11]), 16, 1839030562)
  172. b = md5_hh(b, c, d, a, unwrap(x[i + 14]), 23, -35309556)
  173. a = md5_hh(a, b, c, d, unwrap(x[i + 1]), 4 , -1530992060)
  174. d = md5_hh(d, a, b, c, unwrap(x[i + 4]), 11, 1272893353)
  175. c = md5_hh(c, d, a, b, unwrap(x[i + 7]), 16, -155497632)
  176. b = md5_hh(b, c, d, a, unwrap(x[i + 10]), 23, -1094730640)
  177. a = md5_hh(a, b, c, d, unwrap(x[i + 13]), 4 , 681279174)
  178. d = md5_hh(d, a, b, c, unwrap(x[i + 0]), 11, -358537222)
  179. c = md5_hh(c, d, a, b, unwrap(x[i + 3]), 16, -722521979)
  180. b = md5_hh(b, c, d, a, unwrap(x[i + 6]), 23, 76029189)
  181. a = md5_hh(a, b, c, d, unwrap(x[i + 9]), 4 , -640364487)
  182. d = md5_hh(d, a, b, c, unwrap(x[i + 12]), 11, -421815835)
  183. c = md5_hh(c, d, a, b, unwrap(x[i + 15]), 16, 530742520)
  184. b = md5_hh(b, c, d, a, unwrap(x[i + 2]), 23, -995338651)
  185. a = md5_ii(a, b, c, d, unwrap(x[i + 0]), 6 , -198630844)
  186. d = md5_ii(d, a, b, c, unwrap(x[i + 7]), 10, 1126891415)
  187. c = md5_ii(c, d, a, b, unwrap(x[i + 14]), 15, -1416354905)
  188. b = md5_ii(b, c, d, a, unwrap(x[i + 5]), 21, -57434055)
  189. a = md5_ii(a, b, c, d, unwrap(x[i + 12]), 6 , 1700485571)
  190. d = md5_ii(d, a, b, c, unwrap(x[i + 3]), 10, -1894986606)
  191. c = md5_ii(c, d, a, b, unwrap(x[i + 10]), 15, -1051523)
  192. b = md5_ii(b, c, d, a, unwrap(x[i + 1]), 21, -2054922799)
  193. a = md5_ii(a, b, c, d, unwrap(x[i + 8]), 6 , 1873313359)
  194. d = md5_ii(d, a, b, c, unwrap(x[i + 15]), 10, -30611744)
  195. c = md5_ii(c, d, a, b, unwrap(x[i + 6]), 15, -1560198380)
  196. b = md5_ii(b, c, d, a, unwrap(x[i + 13]), 21, 1309151649)
  197. a = md5_ii(a, b, c, d, unwrap(x[i + 4]), 6 , -145523070)
  198. d = md5_ii(d, a, b, c, unwrap(x[i + 11]), 10, -1120210379)
  199. c = md5_ii(c, d, a, b, unwrap(x[i + 2]), 15, 718787259)
  200. b = md5_ii(b, c, d, a, unwrap(x[i + 9]), 21, -343485551)
  201. a = safe_add(a, olda)
  202. b = safe_add(b, oldb)
  203. c = safe_add(c, oldc)
  204. d = safe_add(d, oldd)
  205. }
  206. return [a, b, c, d]
  207. }
  208. // MARK: - Helper
  209. func length(_ dictionary: [Int: Int32]) -> Int {
  210. return (dictionary.keys.max() ?? 0) + 1
  211. }
  212. func dictionary2array(_ dictionary: [Int: Int32]) -> [Int32] {
  213. var array = Array<Int32>(repeating: 0, count: dictionary.keys.count)
  214. for i in Array(dictionary.keys).sorted() {
  215. array[i] = unwrap(dictionary[i])
  216. }
  217. return array
  218. }
  219. func unwrap(_ value: Int32?, _ fallback: Int32 = 0) -> Int32 {
  220. if let value = value {
  221. return value
  222. }
  223. return fallback
  224. }
  225. func zeroFillRightShift(_ num: Int32, _ count: Int32) -> Int32 {
  226. let value = UInt32(bitPattern: num) >> UInt32(bitPattern: count)
  227. return Int32(bitPattern: value)
  228. }