@veightz
2015-05-15T14:27:02.000000Z
字数 19923
阅读 2357
Swift MD5
MD5已经广泛使用在为文件传输提供一定的可靠性方面。例如,服务器预先提供一个MD5校验和,用户下载完文件以后,用MD5算法计算下载文件的MD5校验和,然后通过检查这两个校验和是否一致,就能判断下载的文件是否出错。
MD5亦有应用于部份网上赌场以保证赌博的公平性,原理是系统先在玩家下注前已生成该局的结果,将该结果的字串配合一组随机字串利用MD5 加密,将该加密字串于玩家下注前便显示给玩家,再在结果开出后将未加密的字串显示给玩家,玩家便可利用MD5工具加密验证该字串是否吻合。
例子: 在玩家下注骰宝前,赌场便先决定该局结果,假设生成的随机结果为4、5、 6大,赌场便会先利用MD5 加密“4, 5, 6”此字串并于玩家下注前告诉玩家;由于赌场是无法预计玩家会下什么注,所以便能确保赌场不能作弊;当玩家下注完毕后,赌场便告诉玩家该原始字串,即“4, 5, 6”,玩家便可利用MD5工具加密该字串是否与下注前的加密字串吻合。
该字串一般会加上一组随机字串 (Random string),以防止玩家利用碰撞 (Collision) 解密字串,但如使用超级电脑利用碰撞亦有可能从加上随机字串的加密字串中取得游戏结果。随机字串的长度与碰撞的次数成正比关系,一般网上赌场使用的随机字串是长于20字,有些网上赌场的随机字串更长达500字,以增加解密难度。
MD5是输入不定长度信息,输出固定长度128-bits的算法。经过程序流程,生成四个32位数据,最后联合起来成为一个128-bits散列。基本方式为,求余、取余、调整长度、与链接变量进行循环运算。得出结果。
总体思路并不复杂, 大致分为三步即可。
// 循环左移infix operator <<< {associativity noneprecedence 140}func <<< (x: Word, n: Word) -> Word {let result: Word = (x << n) | (x >> (32 - n))return result}
struct MD5 {var rawString: Stringvar buffer: [Word]var checksum: String {}func log(word: Word) -> () {...}mutating func transform(var # string: String) -> [Word] {...}
// 从字符串中取出的字符,先转为Byte(ASCII)typealias Byte = UInt8// 512位分组分为16*32位的子分组,也是非线性变换的基本单位typealias Word = UInt32// 用于存储一个512位的分组typealias Block = [Word]
// 初始化变量var buffer: [Word] = [0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476]
func encode(# string: String) -> [[Word]] {let stringLength:UInt64 = UInt64(count(string))var bytes = [Byte]()for character in string.utf8 {let byte = Byte(character)bytes.append(byte)}let charactersPaddingLength = 512 - ((stringLength * 8) + 64) % 512if charactersPaddingLength > 0 {var paddingWords = [Byte](count: Int(charactersPaddingLength / 8), repeatedValue: 0)paddingWords[0] = 0x80bytes.extend(paddingWords)}var words = [Word]()for var i = 0; i < bytes.count; i = i + 4 {let word: Word = (Word(bytes[i]) << 0)| (Word(bytes[i + 1]) << 8)| (Word(bytes[i + 2]) << 16)| (Word(bytes[i + 3]) << 24)words.append(word)}// Mark: 生成长度补位编码var lengthPaddingWords = [Word](count: 2, repeatedValue: 0)let bitsCount: UInt64 = stringLength << 3lengthPaddingWords[1] = Word(bitsCount >> 32 & 0xFFFFFFFF)lengthPaddingWords[0] = Word(bitsCount & 0xFFFFFFFF)words.extend(lengthPaddingWords)let wordsCollectionCount = words.count/16var wordsCollection = [[Word]]()for index in 0..<wordsCollectionCount {let wordsUnit = Array(words[(index*16)..<(index*16 + 16)])wordsCollection.append(wordsUnit)}return wordsCollection}
func roundProcess(var a: Word, var b: Word, var c: Word, var d: Word,wordsArray x:[Word]) -> (Word, Word, Word, Word) {func FF(var a: Word, var b: Word, var c: Word, var d: Word, # x: Word, # s: Word, # ac:Word) -> (Word, Word, Word, Word) {func F(# x: Word, # y: Word, # z: Word) -> Word {let result = (x & y) | ((~x) & z)return result}/*#define FF(a, b, c, d, x, s, ac) { \(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \(a) = ROTATE_LEFT ((a), (s)); \(a) += (b); \}*/a = Word((UInt64(a) + UInt64(F(x: b, y: c, z: d))) & 0xFFFFFFFF)a = Word((UInt64(a) + UInt64(x)) & 0xFFFFFFFF)a = Word((UInt64(a) + UInt64(ac)) & 0xFFFFFFFF)a = a <<< sa = Word((UInt64(a) + UInt64(b)) & 0xFFFFFFFF)return (a, b, c, d)}func GG(var a: Word, var b: Word, var c: Word, var d: Word, # x: Word, # s: Word, # ac:Word) -> (Word, Word, Word, Word) {func G(# x: Word, # y: Word, # z: Word) -> Word {let result = (x & z) | (y & (~z))return result}/*#define GG(a, b, c, d, x, s, ac) { \(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \(a) = ROTATE_LEFT ((a), (s)); \(a) += (b); \}*/a = Word((UInt64(a) + UInt64(G(x: b, y: c, z: d)) + UInt64(x) + UInt64(ac)) & 0xFFFFFFFF)a = a <<< sa = Word((UInt64(a) + UInt64(b)) & 0xFFFFFFFF)return (a, b, c, d)}func HH(var a: Word, var b: Word, var c: Word, var d: Word, # x: Word, # s: Word, # ac:Word) -> (Word, Word, Word, Word) {func H(# x: Word, # y: Word, # z: Word) -> Word {let result = x ^ y ^ zreturn result}/*#define HH(a, b, c, d, x, s, ac) { \(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \(a) = ROTATE_LEFT ((a), (s)); \(a) += (b); \}*/a = Word((UInt64(a) + UInt64(H(x: b, y: c, z: d)) + UInt64(x) + UInt64(ac)) & 0xFFFFFFFF)a = a <<< sa = Word((UInt64(a) + UInt64(b)) & 0xFFFFFFFF)return (a, b, c, d)}func II(var a: Word, var b: Word, var c: Word, var d: Word, # x: Word, # s: Word, # ac:Word) -> (Word, Word, Word, Word) {func I(# x: Word, # y: Word, # z: Word) -> Word {let result = y ^ (x | (~z))return result}/*#define II(a, b, c, d, x, s, ac) { \(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \(a) = ROTATE_LEFT ((a), (s)); \(a) += (b); \}*/a = Word((UInt64(a) + UInt64(I(x: b, y: c, z: d)) + UInt64(x) + UInt64(ac)) & 0xFFFFFFFF)a = a <<< sa = Word((UInt64(a) + UInt64(b)) & 0xFFFFFFFF)return (a, b, c, d)}let aa = alet bb = blet cc = clet dd = d/* Round 1. *//* Let [abcd k s i] denote the operationa = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). *//* Do the following 16 operations. *//*[ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4][ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8][ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12][ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16]*/(a, b, c, d) = FF(a, b, c, d, x: x[ 0], s: S11, ac: 0xd76aa478); /* 1 */(d, a, b, c) = FF(d, a, b, c, x: x[ 1], s: S12, ac: 0xe8c7b756); /* 2 */(c, d, a, b) = FF(c, d, a, b, x: x[ 2], s: S13, ac: 0x242070db); /* 3 */(b, c, d, a) = FF(b, c, d, a, x: x[ 3], s: S14, ac: 0xc1bdceee); /* 4 */(a, b, c, d) = FF(a, b, c, d, x: x[ 4], s: S11, ac: 0xf57c0faf); /* 5 */(d, a, b, c) = FF(d, a, b, c, x: x[ 5], s: S12, ac: 0x4787c62a); /* 6 */(c, d, a, b) = FF(c, d, a, b, x: x[ 6], s: S13, ac: 0xa8304613); /* 7 */(b, c, d, a) = FF(b, c, d, a, x: x[ 7], s: S14, ac: 0xfd469501); /* 8 */(a, b, c, d) = FF(a, b, c, d, x: x[ 8], s: S11, ac: 0x698098d8); /* 9 */(d, a, b, c) = FF(d, a, b, c, x: x[ 9], s: S12, ac: 0x8b44f7af); /* 10 */(c, d, a, b) = FF(c, d, a, b, x: x[10], s: S13, ac: 0xffff5bb1); /* 11 */(b, c, d, a) = FF(b, c, d, a, x: x[11], s: S14, ac: 0x895cd7be); /* 12 */(a, b, c, d) = FF(a, b, c, d, x: x[12], s: S11, ac: 0x6b901122); /* 13 */(d, a, b, c) = FF(d, a, b, c, x: x[13], s: S12, ac: 0xfd987193); /* 14 */(c, d, a, b) = FF(c, d, a, b, x: x[14], s: S13, ac: 0xa679438e); /* 15 */(b, c, d, a) = FF(b, c, d, a, x: x[15], s: S14, ac: 0x49b40821); /* 16 *//* Round 2. *//* Let [abcd k s i] denote the operationa = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). *//* Do the following 16 operations. *//*[ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20][ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24][ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28][ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32]*/(a, b, c, d) = GG(a, b, c, d, x: x[ 1], s: S21, ac: 0xf61e2562); /* 17 */(d, a, b, c) = GG(d, a, b, c, x: x[ 6], s: S22, ac: 0xc040b340); /* 18 */(c, d, a, b) = GG(c, d, a, b, x: x[11], s: S23, ac: 0x265e5a51); /* 19 */(b, c, d, a) = GG(b, c, d, a, x: x[ 0], s: S24, ac: 0xe9b6c7aa); /* 20 */(a, b, c, d) = GG(a, b, c, d, x: x[ 5], s: S21, ac: 0xd62f105d); /* 21 */(d, a, b, c) = GG(d, a, b, c, x: x[10], s: S22, ac: 0x2441453); /* 22 */(c, d, a, b) = GG(c, d, a, b, x: x[15], s: S23, ac: 0xd8a1e681); /* 23 */(b, c, d, a) = GG(b, c, d, a, x: x[ 4], s: S24, ac: 0xe7d3fbc8); /* 24 */(a, b, c, d) = GG(a, b, c, d, x: x[ 9], s: S21, ac: 0x21e1cde6); /* 25 */(d, a, b, c) = GG(d, a, b, c, x: x[14], s: S22, ac: 0xc33707d6); /* 26 */(c, d, a, b) = GG(c, d, a, b, x: x[ 3], s: S23, ac: 0xf4d50d87); /* 27 */(b, c, d, a) = GG(b, c, d, a, x: x[ 8], s: S24, ac: 0x455a14ed); /* 28 */(a, b, c, d) = GG(a, b, c, d, x: x[13], s: S21, ac: 0xa9e3e905); /* 29 */(d, a, b, c) = GG(d, a, b, c, x: x[ 2], s: S22, ac: 0xfcefa3f8); /* 30 */(c, d, a, b) = GG(c, d, a, b, x: x[ 7], s: S23, ac: 0x676f02d9); /* 31 */(b, c, d, a) = GG(b, c, d, a, x: x[12], s: S24, ac: 0x8d2a4c8a); /* 32 *//* Round 3. *//* Let [abcd k s t] denote the operationa = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). *//* Do the following 16 operations. *//*[ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36][ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40][ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44][ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48]*/(a, b, c, d) = HH(a, b, c, d, x: x[ 5], s: S31, ac: 0xfffa3942); /* 33 */(d, a, b, c) = HH(d, a, b, c, x: x[ 8], s: S32, ac: 0x8771f681); /* 34 */(c, d, a, b) = HH(c, d, a, b, x: x[11], s: S33, ac: 0x6d9d6122); /* 35 */(b, c, d, a) = HH(b, c, d, a, x: x[14], s: S34, ac: 0xfde5380c); /* 36 */(a, b, c, d) = HH(a, b, c, d, x: x[ 1], s: S31, ac: 0xa4beea44); /* 37 */(d, a, b, c) = HH(d, a, b, c, x: x[ 4], s: S32, ac: 0x4bdecfa9); /* 38 */(c, d, a, b) = HH(c, d, a, b, x: x[ 7], s: S33, ac: 0xf6bb4b60); /* 39 */(b, c, d, a) = HH(b, c, d, a, x: x[10], s: S34, ac: 0xbebfbc70); /* 40 */(a, b, c, d) = HH(a, b, c, d, x: x[13], s: S31, ac: 0x289b7ec6); /* 41 */(d, a, b, c) = HH(d, a, b, c, x: x[ 0], s: S32, ac: 0xeaa127fa); /* 42 */(c, d, a, b) = HH(c, d, a, b, x: x[ 3], s: S33, ac: 0xd4ef3085); /* 43 */(b, c, d, a) = HH(b, c, d, a, x: x[ 6], s: S34, ac: 0x4881d05); /* 44 */(a, b, c, d) = HH(a, b, c, d, x: x[ 9], s: S31, ac: 0xd9d4d039); /* 45 */(d, a, b, c) = HH(d, a, b, c, x: x[12], s: S32, ac: 0xe6db99e5); /* 46 */(c, d, a, b) = HH(c, d, a, b, x: x[15], s: S33, ac: 0x1fa27cf8); /* 47 */(b, c, d, a) = HH(b, c, d, a, x: x[ 2], s: S34, ac: 0xc4ac5665); /* 48 *//* Round 4. *//* Let [abcd k s t] denote the operationa = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). *//* Do the following 16 operations. *//*[ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52][ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56][ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60][ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64]*/(a, b, c, d) = II(a, b, c, d, x: x[ 0], s: S41, ac: 0xf4292244); /* 49 */(d, a, b, c) = II(d, a, b, c, x: x[ 7], s: S42, ac: 0x432aff97); /* 50 */(c, d, a, b) = II(c, d, a, b, x: x[14], s: S43, ac: 0xab9423a7); /* 51 */(b, c, d, a) = II(b, c, d, a, x: x[ 5], s: S44, ac: 0xfc93a039); /* 52 */(a, b, c, d) = II(a, b, c, d, x: x[12], s: S41, ac: 0x655b59c3); /* 53 */(d, a, b, c) = II(d, a, b, c, x: x[ 3], s: S42, ac: 0x8f0ccc92); /* 54 */(c, d, a, b) = II(c, d, a, b, x: x[10], s: S43, ac: 0xffeff47d); /* 55 */(b, c, d, a) = II(b, c, d, a, x: x[ 1], s: S44, ac: 0x85845dd1); /* 56 */(a, b, c, d) = II(a, b, c, d, x: x[ 8], s: S41, ac: 0x6fa87e4f); /* 57 */(d, a, b, c) = II(d, a, b, c, x: x[15], s: S42, ac: 0xfe2ce6e0); /* 58 */(c, d, a, b) = II(c, d, a, b, x: x[ 6], s: S43, ac: 0xa3014314); /* 59 */(b, c, d, a) = II(b, c, d, a, x: x[13], s: S44, ac: 0x4e0811a1); /* 60 */(a, b, c, d) = II(a, b, c, d, x: x[ 4], s: S41, ac: 0xf7537e82); /* 61 */(d, a, b, c) = II(d, a, b, c, x: x[11], s: S42, ac: 0xbd3af235); /* 62 */(c, d, a, b) = II(c, d, a, b, x: x[ 2], s: S43, ac: 0x2ad7d2bb); /* 63 */(b, c, d, a) = II(b, c, d, a, x: x[ 9], s: S44, ac: 0xeb86d391); /* 64 *//* Then perform the following additions. (That is increment eachof the four registers by the value it had before this blockwas started.) *//*A = A + AAB = B + BBC = C + CCD = D + DD*/a = Word((UInt64(a) + UInt64(aa)) & 0xFFFFFFFF)b = Word((UInt64(b) + UInt64(bb)) & 0xFFFFFFFF)c = Word((UInt64(c) + UInt64(cc)) & 0xFFFFFFFF)d = Word((UInt64(d) + UInt64(dd)) & 0xFFFFFFFF)return (a, b, c, d)}
//// main.swift// MD5-Swift//// Created by Veight Zhou on 5/12/15.// Copyright (c) 2015 Veight Zhou. All rights reserved.//import Foundation// 定义类型typealias Byte = UInt8typealias Word = UInt32typealias Block = [Word]/**We define a rotate left operator <<<*/infix operator <<< {associativity noneprecedence 140}func <<< (x: Word, n: Word) -> Word {let result: Word = (x << n) | (x >> (32 - n))return result}struct MD5 {var rawString: String = "" {didSet {buffer = [0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476]transform(string: rawString)}}var buffer: [Word] = [0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476]var checksum: String {get {return decode(words: buffer)}}func log(word: Word) -> () {var binaryString = ""for index in 0...31 {binaryString = String(word >> Word(index) & 0x1) + binaryStringif index % 8 == 7 {binaryString = " " + binaryString}}binaryString += " -> \(word)"}mutating func transform(var # string: String) -> () {let S11: Word = 7let S12: Word = 12let S13: Word = 17let S14: Word = 22let S21: Word = 5let S22: Word = 9let S23: Word = 14let S24: Word = 20let S31: Word = 4let S32: Word = 11let S33: Word = 16let S34: Word = 23let S41: Word = 6let S42: Word = 10let S43: Word = 15let S44: Word = 21/**对输入的文本进行编码, 返回一个编码后的数组。数据中的每个元素都是容量为16的Word数组, 即16*32位的子分组。:param: string 需要编码的文本:returns: 每个元素都是容量为16的Word数组*/func encode(# string: String) -> [[Word]] {let stringLength:UInt64 = UInt64(count(string))var bytes = [Byte]()for character in string.utf8 {let byte = Byte(character)bytes.append(byte)}let charactersPaddingLength = 512 - ((stringLength * 8) + 64) % 512if charactersPaddingLength > 0 {var paddingWords = [Byte](count: Int(charactersPaddingLength / 8), repeatedValue: 0)paddingWords[0] = 0x80bytes.extend(paddingWords)}var words = [Word]()for var i = 0; i < bytes.count; i = i + 4 {let word: Word = (Word(bytes[i]) << 0)| (Word(bytes[i + 1]) << 8)| (Word(bytes[i + 2]) << 16)| (Word(bytes[i + 3]) << 24)words.append(word)}// Mark: 生成长度补位编码var lengthPaddingWords = [Word](count: 2, repeatedValue: 0)let bitsCount: UInt64 = stringLength << 3lengthPaddingWords[1] = Word(bitsCount >> 32 & 0xFFFFFFFF)lengthPaddingWords[0] = Word(bitsCount & 0xFFFFFFFF)words.extend(lengthPaddingWords)let wordsCollectionCount = words.count/16var wordsCollection = [[Word]]()for index in 0..<wordsCollectionCount {let wordsUnit = Array(words[(index*16)..<(index*16 + 16)])wordsCollection.append(wordsUnit)}return wordsCollection}func roundProcess(var a: Word, var b: Word, var c: Word, var d: Word,wordsArray x:[Word]) -> (Word, Word, Word, Word) {func FF(var a: Word, var b: Word, var c: Word, var d: Word, # x: Word, # s: Word, # ac:Word) -> (Word, Word, Word, Word) {func F(# x: Word, # y: Word, # z: Word) -> Word {let result = (x & y) | ((~x) & z)return result}/*#define FF(a, b, c, d, x, s, ac) { \(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \(a) = ROTATE_LEFT ((a), (s)); \(a) += (b); \}*/a = Word((UInt64(a) + UInt64(F(x: b, y: c, z: d))) & 0xFFFFFFFF)a = Word((UInt64(a) + UInt64(x)) & 0xFFFFFFFF)a = Word((UInt64(a) + UInt64(ac)) & 0xFFFFFFFF)a = a <<< sa = Word((UInt64(a) + UInt64(b)) & 0xFFFFFFFF)return (a, b, c, d)}func GG(var a: Word, var b: Word, var c: Word, var d: Word, # x: Word, # s: Word, # ac:Word) -> (Word, Word, Word, Word) {func G(# x: Word, # y: Word, # z: Word) -> Word {let result = (x & z) | (y & (~z))return result}/*#define GG(a, b, c, d, x, s, ac) { \(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \(a) = ROTATE_LEFT ((a), (s)); \(a) += (b); \}*/a = Word((UInt64(a) + UInt64(G(x: b, y: c, z: d)) + UInt64(x) + UInt64(ac)) & 0xFFFFFFFF)a = a <<< sa = Word((UInt64(a) + UInt64(b)) & 0xFFFFFFFF)return (a, b, c, d)}func HH(var a: Word, var b: Word, var c: Word, var d: Word, # x: Word, # s: Word, # ac:Word) -> (Word, Word, Word, Word) {func H(# x: Word, # y: Word, # z: Word) -> Word {let result = x ^ y ^ zreturn result}/*#define HH(a, b, c, d, x, s, ac) { \(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \(a) = ROTATE_LEFT ((a), (s)); \(a) += (b); \}*/a = Word((UInt64(a) + UInt64(H(x: b, y: c, z: d)) + UInt64(x) + UInt64(ac)) & 0xFFFFFFFF)a = a <<< sa = Word((UInt64(a) + UInt64(b)) & 0xFFFFFFFF)return (a, b, c, d)}func II(var a: Word, var b: Word, var c: Word, var d: Word, # x: Word, # s: Word, # ac:Word) -> (Word, Word, Word, Word) {func I(# x: Word, # y: Word, # z: Word) -> Word {let result = y ^ (x | (~z))return result}/*#define II(a, b, c, d, x, s, ac) { \(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \(a) = ROTATE_LEFT ((a), (s)); \(a) += (b); \}*/a = Word((UInt64(a) + UInt64(I(x: b, y: c, z: d)) + UInt64(x) + UInt64(ac)) & 0xFFFFFFFF)a = a <<< sa = Word((UInt64(a) + UInt64(b)) & 0xFFFFFFFF)return (a, b, c, d)}let aa = alet bb = blet cc = clet dd = d/* Round 1. *//* Let [abcd k s i] denote the operationa = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). *//* Do the following 16 operations. *//*[ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4][ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8][ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12][ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16]*/(a, b, c, d) = FF(a, b, c, d, x: x[ 0], s: S11, ac: 0xd76aa478); /* 1 */(d, a, b, c) = FF(d, a, b, c, x: x[ 1], s: S12, ac: 0xe8c7b756); /* 2 */(c, d, a, b) = FF(c, d, a, b, x: x[ 2], s: S13, ac: 0x242070db); /* 3 */(b, c, d, a) = FF(b, c, d, a, x: x[ 3], s: S14, ac: 0xc1bdceee); /* 4 */(a, b, c, d) = FF(a, b, c, d, x: x[ 4], s: S11, ac: 0xf57c0faf); /* 5 */(d, a, b, c) = FF(d, a, b, c, x: x[ 5], s: S12, ac: 0x4787c62a); /* 6 */(c, d, a, b) = FF(c, d, a, b, x: x[ 6], s: S13, ac: 0xa8304613); /* 7 */(b, c, d, a) = FF(b, c, d, a, x: x[ 7], s: S14, ac: 0xfd469501); /* 8 */(a, b, c, d) = FF(a, b, c, d, x: x[ 8], s: S11, ac: 0x698098d8); /* 9 */(d, a, b, c) = FF(d, a, b, c, x: x[ 9], s: S12, ac: 0x8b44f7af); /* 10 */(c, d, a, b) = FF(c, d, a, b, x: x[10], s: S13, ac: 0xffff5bb1); /* 11 */(b, c, d, a) = FF(b, c, d, a, x: x[11], s: S14, ac: 0x895cd7be); /* 12 */(a, b, c, d) = FF(a, b, c, d, x: x[12], s: S11, ac: 0x6b901122); /* 13 */(d, a, b, c) = FF(d, a, b, c, x: x[13], s: S12, ac: 0xfd987193); /* 14 */(c, d, a, b) = FF(c, d, a, b, x: x[14], s: S13, ac: 0xa679438e); /* 15 */(b, c, d, a) = FF(b, c, d, a, x: x[15], s: S14, ac: 0x49b40821); /* 16 *//* Round 2. *//* Let [abcd k s i] denote the operationa = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). *//* Do the following 16 operations. *//*[ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20][ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24][ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28][ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32]*/(a, b, c, d) = GG(a, b, c, d, x: x[ 1], s: S21, ac: 0xf61e2562); /* 17 */(d, a, b, c) = GG(d, a, b, c, x: x[ 6], s: S22, ac: 0xc040b340); /* 18 */(c, d, a, b) = GG(c, d, a, b, x: x[11], s: S23, ac: 0x265e5a51); /* 19 */(b, c, d, a) = GG(b, c, d, a, x: x[ 0], s: S24, ac: 0xe9b6c7aa); /* 20 */(a, b, c, d) = GG(a, b, c, d, x: x[ 5], s: S21, ac: 0xd62f105d); /* 21 */(d, a, b, c) = GG(d, a, b, c, x: x[10], s: S22, ac: 0x2441453); /* 22 */(c, d, a, b) = GG(c, d, a, b, x: x[15], s: S23, ac: 0xd8a1e681); /* 23 */(b, c, d, a) = GG(b, c, d, a, x: x[ 4], s: S24, ac: 0xe7d3fbc8); /* 24 */(a, b, c, d) = GG(a, b, c, d, x: x[ 9], s: S21, ac: 0x21e1cde6); /* 25 */(d, a, b, c) = GG(d, a, b, c, x: x[14], s: S22, ac: 0xc33707d6); /* 26 */(c, d, a, b) = GG(c, d, a, b, x: x[ 3], s: S23, ac: 0xf4d50d87); /* 27 */(b, c, d, a) = GG(b, c, d, a, x: x[ 8], s: S24, ac: 0x455a14ed); /* 28 */(a, b, c, d) = GG(a, b, c, d, x: x[13], s: S21, ac: 0xa9e3e905); /* 29 */(d, a, b, c) = GG(d, a, b, c, x: x[ 2], s: S22, ac: 0xfcefa3f8); /* 30 */(c, d, a, b) = GG(c, d, a, b, x: x[ 7], s: S23, ac: 0x676f02d9); /* 31 */(b, c, d, a) = GG(b, c, d, a, x: x[12], s: S24, ac: 0x8d2a4c8a); /* 32 *//* Round 3. *//* Let [abcd k s t] denote the operationa = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). *//* Do the following 16 operations. *//*[ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36][ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40][ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44][ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48]*/(a, b, c, d) = HH(a, b, c, d, x: x[ 5], s: S31, ac: 0xfffa3942); /* 33 */(d, a, b, c) = HH(d, a, b, c, x: x[ 8], s: S32, ac: 0x8771f681); /* 34 */(c, d, a, b) = HH(c, d, a, b, x: x[11], s: S33, ac: 0x6d9d6122); /* 35 */(b, c, d, a) = HH(b, c, d, a, x: x[14], s: S34, ac: 0xfde5380c); /* 36 */(a, b, c, d) = HH(a, b, c, d, x: x[ 1], s: S31, ac: 0xa4beea44); /* 37 */(d, a, b, c) = HH(d, a, b, c, x: x[ 4], s: S32, ac: 0x4bdecfa9); /* 38 */(c, d, a, b) = HH(c, d, a, b, x: x[ 7], s: S33, ac: 0xf6bb4b60); /* 39 */(b, c, d, a) = HH(b, c, d, a, x: x[10], s: S34, ac: 0xbebfbc70); /* 40 */(a, b, c, d) = HH(a, b, c, d, x: x[13], s: S31, ac: 0x289b7ec6); /* 41 */(d, a, b, c) = HH(d, a, b, c, x: x[ 0], s: S32, ac: 0xeaa127fa); /* 42 */(c, d, a, b) = HH(c, d, a, b, x: x[ 3], s: S33, ac: 0xd4ef3085); /* 43 */(b, c, d, a) = HH(b, c, d, a, x: x[ 6], s: S34, ac: 0x4881d05); /* 44 */(a, b, c, d) = HH(a, b, c, d, x: x[ 9], s: S31, ac: 0xd9d4d039); /* 45 */(d, a, b, c) = HH(d, a, b, c, x: x[12], s: S32, ac: 0xe6db99e5); /* 46 */(c, d, a, b) = HH(c, d, a, b, x: x[15], s: S33, ac: 0x1fa27cf8); /* 47 */(b, c, d, a) = HH(b, c, d, a, x: x[ 2], s: S34, ac: 0xc4ac5665); /* 48 *//* Round 4. *//* Let [abcd k s t] denote the operationa = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). *//* Do the following 16 operations. *//*[ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52][ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56][ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60][ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64]*/(a, b, c, d) = II(a, b, c, d, x: x[ 0], s: S41, ac: 0xf4292244); /* 49 */(d, a, b, c) = II(d, a, b, c, x: x[ 7], s: S42, ac: 0x432aff97); /* 50 */(c, d, a, b) = II(c, d, a, b, x: x[14], s: S43, ac: 0xab9423a7); /* 51 */(b, c, d, a) = II(b, c, d, a, x: x[ 5], s: S44, ac: 0xfc93a039); /* 52 */(a, b, c, d) = II(a, b, c, d, x: x[12], s: S41, ac: 0x655b59c3); /* 53 */(d, a, b, c) = II(d, a, b, c, x: x[ 3], s: S42, ac: 0x8f0ccc92); /* 54 */(c, d, a, b) = II(c, d, a, b, x: x[10], s: S43, ac: 0xffeff47d); /* 55 */(b, c, d, a) = II(b, c, d, a, x: x[ 1], s: S44, ac: 0x85845dd1); /* 56 */(a, b, c, d) = II(a, b, c, d, x: x[ 8], s: S41, ac: 0x6fa87e4f); /* 57 */(d, a, b, c) = II(d, a, b, c, x: x[15], s: S42, ac: 0xfe2ce6e0); /* 58 */(c, d, a, b) = II(c, d, a, b, x: x[ 6], s: S43, ac: 0xa3014314); /* 59 */(b, c, d, a) = II(b, c, d, a, x: x[13], s: S44, ac: 0x4e0811a1); /* 60 */(a, b, c, d) = II(a, b, c, d, x: x[ 4], s: S41, ac: 0xf7537e82); /* 61 */(d, a, b, c) = II(d, a, b, c, x: x[11], s: S42, ac: 0xbd3af235); /* 62 */(c, d, a, b) = II(c, d, a, b, x: x[ 2], s: S43, ac: 0x2ad7d2bb); /* 63 */(b, c, d, a) = II(b, c, d, a, x: x[ 9], s: S44, ac: 0xeb86d391); /* 64 *//* Then perform the following additions. (That is increment eachof the four registers by the value it had before this blockwas started.) *//*A = A + AAB = B + BBC = C + CCD = D + DD*/a = Word((UInt64(a) + UInt64(aa)) & 0xFFFFFFFF)b = Word((UInt64(b) + UInt64(bb)) & 0xFFFFFFFF)c = Word((UInt64(c) + UInt64(cc)) & 0xFFFFFFFF)d = Word((UInt64(d) + UInt64(dd)) & 0xFFFFFFFF)return (a, b, c, d)}let wordsArray = encode(string: rawString)var tempBuffer = (a: buffer[0], b: buffer[1], c: buffer[2], d: buffer[3])for words in wordsArray {tempBuffer = roundProcess(tempBuffer.a, tempBuffer.b, tempBuffer.c, tempBuffer.d, wordsArray: words)}buffer = [tempBuffer.a, tempBuffer.b, tempBuffer.c, tempBuffer.d]let string = decode(words: buffer)}private func decode(# words: [Word]) -> String {let easyMap: [UInt32: Character] = [0x00: "0", 0x01: "1", 0x02: "2", 0x03: "3", 0x04: "4", 0x05: "5", 0x06: "6", 0x07: "7",0x08: "8", 0x09: "9", 0x0A: "a", 0x0B: "b", 0x0C: "c", 0x0D: "d", 0x0E: "e", 0x0F: "f"]var string = ""for i in 0..<(words.count) {let word = words[i]for j in 0...3 {let s0 = easyMap[(UInt32(word) >> UInt32(j * 8 + 4)) & 0xF]!let s1 = easyMap[(UInt32(word) >> UInt32(j * 8)) & 0xF]!string.append(s0)string.append(s1)}}return string}}var md5 = MD5()md5.rawString = "abc"println("\(md5.rawString) ==> \(md5.checksum)")md5.rawString = "a"println("\(md5.rawString) ==> \(md5.checksum)")md5.rawString = "message digest"println("\(md5.rawString) ==> \(md5.checksum)")md5.rawString = "abcdefghijklmnopqrstuvwxyz"println("\(md5.rawString) ==> \(md5.checksum)")md5.rawString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"println("\(md5.rawString) ==> \(md5.checksum)")md5.rawString = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"println("\(md5.rawString) ==> \(md5.checksum)")
abc ==> 900150983cd24fb0d6963f7d28e17f72a ==> 0cc175b9c0f1b6a831c399e269772661message digest ==> f96b697d7cb7938d525a2f31aaf161d0abcdefghijklmnopqrstuvwxyz ==> c3fcd3d76192e4007dfb496cca67e13bABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ==> d174ab98d277d9f5a5611c2c9f419d9f12345678901234567890123456789012345678901234567890123456789012345678901234567890 ==> 57edf4a22be3c955ac49da2e2107b67a