|
|
@@ -17,23 +17,90 @@ public struct MD5 {
|
|
|
//
|
|
|
// Alghorithm from: https://en.wikipedia.org/wiki/MD5
|
|
|
//
|
|
|
- // TODO:
|
|
|
- // - finish impl.
|
|
|
- //
|
|
|
|
|
|
public static func hash(_ input: [UInt8]) -> [UInt8] {
|
|
|
|
|
|
- // Alghorithm from: https://en.wikipedia.org/wiki/MD5
|
|
|
+ var a0 = UInt32(littleEndian: 0x67452301)
|
|
|
+ var b0 = UInt32(littleEndian: 0xefcdab89)
|
|
|
+ var c0 = UInt32(littleEndian: 0x98badcfe)
|
|
|
+ var d0 = UInt32(littleEndian: 0x10325476)
|
|
|
+
|
|
|
+ var message = input + [0x80] + [UInt8](repeating: 0, count: 64 - ((input.count+9) % 64))
|
|
|
+
|
|
|
+ var originalLengthInBits = UInt64(input.count * 8).littleEndian
|
|
|
+
|
|
|
+ withUnsafePointer(&originalLengthInBits) {
|
|
|
+ message.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 8)))
|
|
|
+ }
|
|
|
|
|
|
- var a0: UInt32 = 0x67452301
|
|
|
- var b0: UInt32 = 0xefcdab89
|
|
|
- var c0: UInt32 = 0x98badcfe
|
|
|
- var d0: UInt32 = 0x10325476
|
|
|
+ for chunkStart in 0..<message.count/64 {
|
|
|
+ var words = [UInt32]()
|
|
|
+ let chunk = message[chunkStart*64..<chunkStart*64+64]
|
|
|
+
|
|
|
+ for i in 0...15 {
|
|
|
+ words.append(chunk.withUnsafeBufferPointer {
|
|
|
+ UnsafePointer<UInt32>($0.baseAddress! + (i*4)).pointee
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ var A = a0, B = b0, C = c0, D = d0
|
|
|
+
|
|
|
+ for i in 0...63 {
|
|
|
+ var F = UInt32(0), g = UInt32(0)
|
|
|
+ switch i {
|
|
|
+ case 0...15:
|
|
|
+ F = (B & C) | ((~B) & D)
|
|
|
+ g = UInt32(i)
|
|
|
+ case 16...31:
|
|
|
+ F = (D & B) | ((~D) & C)
|
|
|
+ g = UInt32(5*i + 1) % UInt32(16)
|
|
|
+ case 32...47:
|
|
|
+ F = B ^ C ^ D
|
|
|
+ g = UInt32((3*i + 5)) % UInt32(16)
|
|
|
+ case 48...63:
|
|
|
+ F = C ^ (B | (~D))
|
|
|
+ g = UInt32(7*i) % UInt32(16)
|
|
|
+ default: break
|
|
|
+ }
|
|
|
+ let dTemp = D
|
|
|
+ D = C
|
|
|
+ C = B
|
|
|
+ B = B &+ leftrotate((A &+ F &+ K[i] &+ words[Int(g)]), s[i])
|
|
|
+ A = dTemp
|
|
|
+ }
|
|
|
+
|
|
|
+ a0 = a0 &+ A
|
|
|
+ b0 = b0 &+ B
|
|
|
+ c0 = c0 &+ C
|
|
|
+ d0 = d0 &+ D
|
|
|
+ }
|
|
|
|
|
|
+ var digest = [UInt8]()
|
|
|
|
|
|
- return []
|
|
|
+ a0 = a0.littleEndian
|
|
|
+ b0 = b0.littleEndian
|
|
|
+ c0 = c0.littleEndian
|
|
|
+ d0 = d0.littleEndian
|
|
|
+
|
|
|
+ withUnsafePointer(&a0) {
|
|
|
+ digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
|
|
|
+ }
|
|
|
+ withUnsafePointer(&b0) {
|
|
|
+ digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
|
|
|
+ }
|
|
|
+ withUnsafePointer(&c0) {
|
|
|
+ digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
|
|
|
+ }
|
|
|
+ withUnsafePointer(&d0) {
|
|
|
+ digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
|
|
|
+ }
|
|
|
+
|
|
|
+ return digest
|
|
|
}
|
|
|
|
|
|
+ private static func leftrotate(_ v: UInt32, _ n: UInt32) -> UInt32 {
|
|
|
+ return ((v << n) & 0xFFFFFFFF) | (v >> (32 - n))
|
|
|
+ }
|
|
|
|
|
|
private static var s: [UInt32] = [
|
|
|
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
|
|
@@ -61,3 +128,14 @@ public struct MD5 {
|
|
|
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
|
|
|
]
|
|
|
}
|
|
|
+
|
|
|
+extension String {
|
|
|
+
|
|
|
+ public func md5() -> String {
|
|
|
+ return self.md5().hex()
|
|
|
+ }
|
|
|
+
|
|
|
+ public func md5() -> [UInt8] {
|
|
|
+ return MD5.hash([UInt8](self.utf8))
|
|
|
+ }
|
|
|
+}
|