Browse Source

MD5 in Pure Swift

Marcin Krzyżanowski 11 years ago
parent
commit
b992bd4c36

+ 8 - 4
CryptoSwift.xcodeproj/project.pbxproj

@@ -12,9 +12,10 @@
 		75445821196AA2A5002FF20E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 75445820196AA2A5002FF20E /* Security.framework */; settings = {ATTRIBUTES = (Required, ); }; };
 		75445821196AA2A5002FF20E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 75445820196AA2A5002FF20E /* Security.framework */; settings = {ATTRIBUTES = (Required, ); }; };
 		7547195119931802002FA5F1 /* IntExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7547195019931802002FA5F1 /* IntExtension.swift */; };
 		7547195119931802002FA5F1 /* IntExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7547195019931802002FA5F1 /* IntExtension.swift */; };
 		754BE45B19693E190098E6F3 /* CryptoSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = 754BE45A19693E190098E6F3 /* CryptoSwift.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		754BE45B19693E190098E6F3 /* CryptoSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = 754BE45A19693E190098E6F3 /* CryptoSwift.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		754BE46819693E190098E6F3 /* CryptoSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754BE46719693E190098E6F3 /* CryptoSwiftTests.swift */; };
+		754BE46819693E190098E6F3 /* HashTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754BE46719693E190098E6F3 /* HashTests.swift */; };
 		754C8FED19979F94005AD904 /* ArrayExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754C8FEC19979F94005AD904 /* ArrayExtension.swift */; };
 		754C8FED19979F94005AD904 /* ArrayExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754C8FEC19979F94005AD904 /* ArrayExtension.swift */; };
 		7552614E1993051E000D2B20 /* CryptoHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7552614D1993051E000D2B20 /* CryptoHash.swift */; };
 		7552614E1993051E000D2B20 /* CryptoHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7552614D1993051E000D2B20 /* CryptoHash.swift */; };
+		755FB1DA199E347D00475437 /* ExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755FB1D9199E347D00475437 /* ExtensionsTest.swift */; };
 		758F3F761992E57D0014BBDA /* Playground in Resources */ = {isa = PBXBuildFile; fileRef = 758F3F751992E57D0014BBDA /* Playground */; };
 		758F3F761992E57D0014BBDA /* Playground in Resources */ = {isa = PBXBuildFile; fileRef = 758F3F751992E57D0014BBDA /* Playground */; };
 		758F3F781992F6CE0014BBDA /* ByteExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758F3F771992F6CE0014BBDA /* ByteExtension.swift */; };
 		758F3F781992F6CE0014BBDA /* ByteExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758F3F771992F6CE0014BBDA /* ByteExtension.swift */; };
 		75B601EB197D6A6C0009B53D /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 754BE45519693E190098E6F3 /* CryptoSwift.framework */; };
 		75B601EB197D6A6C0009B53D /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 754BE45519693E190098E6F3 /* CryptoSwift.framework */; };
@@ -94,9 +95,10 @@
 		754BE45A19693E190098E6F3 /* CryptoSwift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CryptoSwift.h; sourceTree = "<group>"; };
 		754BE45A19693E190098E6F3 /* CryptoSwift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CryptoSwift.h; sourceTree = "<group>"; };
 		754BE46019693E190098E6F3 /* CryptoSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CryptoSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		754BE46019693E190098E6F3 /* CryptoSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CryptoSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		754BE46619693E190098E6F3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		754BE46619693E190098E6F3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-		754BE46719693E190098E6F3 /* CryptoSwiftTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoSwiftTests.swift; sourceTree = "<group>"; };
+		754BE46719693E190098E6F3 /* HashTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashTests.swift; sourceTree = "<group>"; };
 		754C8FEC19979F94005AD904 /* ArrayExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayExtension.swift; sourceTree = "<group>"; };
 		754C8FEC19979F94005AD904 /* ArrayExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayExtension.swift; sourceTree = "<group>"; };
 		7552614D1993051E000D2B20 /* CryptoHash.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CryptoHash.swift; sourceTree = "<group>"; };
 		7552614D1993051E000D2B20 /* CryptoHash.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CryptoHash.swift; sourceTree = "<group>"; };
+		755FB1D9199E347D00475437 /* ExtensionsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionsTest.swift; sourceTree = "<group>"; };
 		758F3F751992E57D0014BBDA /* Playground */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Playground; path = CryptoSwift/Playground; sourceTree = "<group>"; };
 		758F3F751992E57D0014BBDA /* Playground */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Playground; path = CryptoSwift/Playground; sourceTree = "<group>"; };
 		758F3F771992F6CE0014BBDA /* ByteExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ByteExtension.swift; sourceTree = "<group>"; };
 		758F3F771992F6CE0014BBDA /* ByteExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ByteExtension.swift; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 /* End PBXFileReference section */
@@ -175,7 +177,8 @@
 		754BE46419693E190098E6F3 /* CryptoSwiftTests */ = {
 		754BE46419693E190098E6F3 /* CryptoSwiftTests */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				754BE46719693E190098E6F3 /* CryptoSwiftTests.swift */,
+				754BE46719693E190098E6F3 /* HashTests.swift */,
+				755FB1D9199E347D00475437 /* ExtensionsTest.swift */,
 				754BE46519693E190098E6F3 /* Supporting Files */,
 				754BE46519693E190098E6F3 /* Supporting Files */,
 			);
 			);
 			path = CryptoSwiftTests;
 			path = CryptoSwiftTests;
@@ -318,7 +321,8 @@
 			isa = PBXSourcesBuildPhase;
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				754BE46819693E190098E6F3 /* CryptoSwiftTests.swift in Sources */,
+				754BE46819693E190098E6F3 /* HashTests.swift in Sources */,
+				755FB1DA199E347D00475437 /* ExtensionsTest.swift in Sources */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};

+ 2 - 2
CryptoSwift/CryptoHash.swift

@@ -8,7 +8,7 @@
 
 
 import Foundation
 import Foundation
 
 
-enum CryptoHash: Int {
+public enum CryptoHash: Int {
     case md5 = 1
     case md5 = 1
     case sha1 = 2
     case sha1 = 2
     case sha224 = 3
     case sha224 = 3
@@ -17,7 +17,7 @@ enum CryptoHash: Int {
     case sha512 = 6
     case sha512 = 6
     case ripemd160 = 7
     case ripemd160 = 7
     
     
-    func hash(data: NSData) -> NSData! {
+    public func hash(data: NSData) -> NSData! {
         switch self {
         switch self {
         case md5:
         case md5:
             return data.md5()
             return data.md5()

+ 16 - 7
CryptoSwift/IntExtension.swift

@@ -15,16 +15,20 @@
 //  - This notice may not be removed or altered from any source or binary distribution.
 //  - This notice may not be removed or altered from any source or binary distribution.
 
 
 /*
 /*
-    Bit shifting with overflow protection using overflow operator "&".
-    Approach is consistent with standard overflow operators &+,&-,&*,&/
+Bit shifting with overflow protection using overflow operator "&".
+Approach is consistent with standard overflow operators &+, &-, &*, &/
+and introduce new overflow operators for shifting: &<<, &>>
 
 
-    Note: Works with unsigned integers values only
+Note: Works with unsigned integers values only
 
 
-    Usage
+Usage
 
 
-    var i = 1       // init
-    var j = i &<< 2 //shift left
-    j &<<= 2        //shift left and assign
+var i = 1       // init
+var j = i &<< 2 //shift left
+j &<<= 2        //shift left and assign
+
+
+@see: https://medium.com/@krzyzanowskim/swiftly-shift-bits-and-protect-yourself-be33016ce071
 */
 */
 
 
 import Foundation
 import Foundation
@@ -77,6 +81,11 @@ extension Int {
         data.getBytes(&i, length: sizeof(Int));
         data.getBytes(&i, length: sizeof(Int));
         return i.byteSwapped
         return i.byteSwapped
     }
     }
+}
+
+
+/** Bit operations */
+extension Int {
     
     
     /** Shift bits to the left. All bits are shifted (including sign bit) */
     /** Shift bits to the left. All bits are shifted (including sign bit) */
     private mutating func shiftLeft(count: Int) -> Int {
     private mutating func shiftLeft(count: Int) -> Int {

+ 91 - 201
CryptoSwift/MD5.swift

@@ -11,13 +11,13 @@ import Foundation
 class MD5 {
 class MD5 {
 
 
     /** specifies the per-round shift amounts */
     /** specifies the per-round shift amounts */
-    let SHIFT_AMTS: [UInt32] = [7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,
+    let s: [UInt32] = [7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,
                        5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,
                        5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,
                        4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,
                        4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,
                        6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21]
                        6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21]
     
     
     /** binary integer part of the sines of integers (Radians) */
     /** binary integer part of the sines of integers (Radians) */
-    let TABLE_T: [UInt32] = [0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
+    let K: [UInt32] = [0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
                        0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,
                        0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,
                        0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,
                        0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,
                        0x6b901122,0xfd987193,0xa679438e,0x49b40821,
                        0x6b901122,0xfd987193,0xa679438e,0x49b40821,
@@ -34,13 +34,9 @@ class MD5 {
                        0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,
                        0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,
                        0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391]
                        0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391]
     
     
-    /** A */
     var a0: UInt32 = 0x67452301
     var a0: UInt32 = 0x67452301
-    /** B */
     var b0: UInt32 = 0xefcdab89
     var b0: UInt32 = 0xefcdab89
-    /** C */
     var c0: UInt32 = 0x98badcfe
     var c0: UInt32 = 0x98badcfe
-    /** D */
     var d0: UInt32 = 0x10325476
     var d0: UInt32 = 0x10325476
     
     
     var message: NSData
     var message: NSData
@@ -49,218 +45,112 @@ class MD5 {
         self.message = message;
         self.message = message;
     }
     }
     
     
-    class func calculate(message: NSData) -> NSData?
-    {
-        return MD5(message).calculate();
-    }
-
     func calculate() -> NSData? {
     func calculate() -> NSData? {
-        let numBlocks = ((message.length + 8) >> 6) + 1
-        let totalLen = numBlocks << 6
-        var paddingBytes:[Byte] = [Byte](count: totalLen /* - message.length */, repeatedValue: 0)
-        paddingBytes[0] = 0x80
-
-        var messageLenBits = message.length << 3
-        for i in 0..<8 {
-            paddingBytes[paddingBytes.count - 8 + i] = Byte(messageLenBits)
-            messageLenBits >>= 8
+        var tmpMessage: NSMutableData = NSMutableData(data: message)
+        
+        // Step 1. Append Padding Bits
+        tmpMessage.appendBytes([0x80]) // append one bit (Byte with one bit) to message
+        
+        // append "0" bit until message length in bits ≡ 448 (mod 512)
+        while tmpMessage.length % 64 != 56 {
+            tmpMessage.appendBytes([0x00])
         }
         }
-
-        var a = a0
-        var b = b0
-        var c = c0
-        var d = d0
-        var buffer:[UInt32] = [UInt32](count: 16, repeatedValue: 0)
         
         
-        for i in 0..<numBlocks {
-            NSLog("BLOCK")
-            var index = i << 6
-            for var j = 0; j < 64; j++ {
-                var val:UInt32
-                if (index < message.length) {
-                    val = UInt32(message.arrayOfBytes()[index])
-                } else {
-                    val = UInt32(paddingBytes[index - message.length])
-                }
-                val = (val << 24) | (buffer[j >> 2] >> 8)
-                buffer[j >> 2] = val
-                index++
+        // Step 2. Append Length a 64-bit representation of lengthInBits
+        let lengthInBits:Int = (message.length * 8).bigEndian
+        tmpMessage.appendBytes(lengthInBits.bytes(64 / 8));
+        
+        // Process the message in successive 512-bit chunks:
+        let chunkSizeBytes = 512 / 8
+        var leftMessageBytes = tmpMessage.length
+        for var i = 0; i < tmpMessage.length; i = i + chunkSizeBytes, leftMessageBytes -= chunkSizeBytes {
+            var chunk = tmpMessage.subdataWithRange(NSRange(location: i, length: min(chunkSizeBytes,leftMessageBytes)))
+            
+            // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15
+            var M:[UInt32] = [UInt32]()
+            for x in 0...15 {
+                var word:UInt32 = 0;
+                var range:NSRange = NSRange(location:x * sizeof(UInt32), length: sizeof(UInt32));
+                chunk.getBytes(&word, range: range);
+                M.append(word)
             }
             }
             
             
-            var originalA:UInt32 = a
-            var originalB:UInt32 = b
-            var originalC:UInt32 = c
-            var originalD:UInt32 = d
-
-            for j in 0...63 {
-                let div16 = j >> 4
-                var f:UInt32 = 0
-                var bufferIndex = j
+            // Initialize hash value for this chunk:
+            var A:UInt32 = a0
+            var B:UInt32 = b0
+            var C:UInt32 = c0
+            var D:UInt32 = d0
+            
+            var dTemp:UInt32
+            
+            // Main loop
+            for i in 0...63 {
+                var g:Int = 0
+                var F:UInt32 = 0
                 
                 
-                switch (div16) {
-                case 0:
-                    f = ((b) & (c)) | ((~b) & (d));
+                switch (i) {
+                case 0...15:
+                    F = (B & C) | ((~B) & D)
+                    //F = D ^ (B & (C ^ D))
+                    g = i
+                    break
+                case 16...31:
+                    F = (D & B) | (~D & C)
+                    g = (5 * i + 1) % 16
+                    break
+                case 32...47:
+                    F = B ^ C ^ D
+                    g = (3 * i + 5) % 16
+                    break
+                case 48...63:
+                    F = C ^ (B | (~D))
+                    g = (7 * i) % 16
                     break
                     break
-                case 1:
-                    f = (b & d) | (c & ~d);
-                    bufferIndex = (bufferIndex * 5 + 1) & 0x0F;
-                    break;
-                    
-                case 2:
-                    f = b ^ c ^ d;
-                    bufferIndex = (bufferIndex * 3 + 5) & 0x0F;
-                    break;
-                    
-                case 3:
-                    f = c ^ (b | ~d);
-                    bufferIndex = (bufferIndex * 7) & 0x0F;
-                    break;
                 default:
                 default:
                     break
                     break
                 }
                 }
-                
-                var temp = b &+ rotateLeft(a &+ f &+ buffer[bufferIndex] &+ TABLE_T[j], SHIFT_AMTS[(div16 << 2) | (j & 3)]);
-                a = d;
-                d = c;
-                c = b;
-                b = temp;
-            }
-            a = a &+ originalA;
-            b = b &+ originalB;
-            c = c &+ originalC;
-            d = d &+ originalD;
-        }
-        
-        println("dalej");
-        
-        var md5:[UInt32] = [UInt32](count: 16, repeatedValue: 0)
-        var count = 0;
-        for var i = 0; i < 4; i++
-        {
-            var n = (i == 0) ? a : ((i == 1) ? b : ((i == 2) ? c : d));
-            for var j = 0; j < 4; j++
-            {
-                md5.append(n)
-                n >>= 8;
+                dTemp = D
+                D = C
+                C = B
+                B = B &+ rotateLeft((A &+ F &+ K[i] &+ M[g]), s[i])
+                A = dTemp
             }
             }
+            a0 = a0 &+ A
+            b0 = b0 &+ B
+            c0 = c0 &+ C
+            d0 = d0 &+ D
         }
         }
+
+        var buf: NSMutableData = NSMutableData();
+        buf.appendBytes(&a0, length: sizeof(UInt32))
+        buf.appendBytes(&b0, length: sizeof(UInt32))
+        buf.appendBytes(&c0, length: sizeof(UInt32))
+        buf.appendBytes(&d0, length: sizeof(UInt32))
         
         
-        NSLog("\(toHexString(md5))")
-        
-        return nil
+        return buf.copy() as? NSData;
     }
     }
     
     
-    func toHexString(b:[UInt32]) -> String {
-        var s:String = String()
-        for var i = 0; i < b.count; i++
-        {
-            s = s + String(format: "%02X", arguments: [b[i] & 0xFF])
-        }
-        return s
+    class func calculate(message: NSData) -> NSData?
+    {
+        return MD5(message).calculate();
+    }
+    
+    private func rotateLeft(x:UInt32, _ n:UInt32) -> UInt32 {
+        return (x << n) | (x >> (32 - n))
     }
     }
+}
 
 
-//    func calculate() -> NSData? {
-//        var tmpMessage: NSMutableData = NSMutableData(data: message)
-//        
-//        // Step 1. Append Padding Bits
-//        tmpMessage.appendBytes([0x80]) // append one bit (Byte with one bit) to message
-//        
-//        // append "0" bit until message length in bits ≡ 448 (mod 512)
-//        while tmpMessage.length % 64 != 56 {
-//            tmpMessage.appendBytes([0x00])
-//        }
-//        
-//        // Step 2. Append Length
-//        let lengthInBits: Int = (message.length * 8)
-//        // A 64-bit representation of lengthInBits
-//        tmpMessage.appendBytes(lengthInBits.bytes(64 / 8));
-//        
-//        println("tmpMessage \(tmpMessage)")
-//        // Process the message in successive 512-bit chunks:
-//        let chunkSizeBytes = 512 / 8
-//        var leftMessageBytes = tmpMessage.length
-//        for var i = 0; i < tmpMessage.length; i = i + chunkSizeBytes, leftMessageBytes -= chunkSizeBytes {
-//            let chunk = tmpMessage.subdataWithRange(NSRange(location: i, length: min(chunkSizeBytes,leftMessageBytes)))
-//            
-//            // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15
-//            var M:[UInt32] = [UInt32]()
-//            for x in 0...15 {
-//                var word:UInt32 = 0;
-//                chunk.getBytes(&word, range: NSRange(location:x * 4, length: sizeof(UInt32)));
-//                M.append(word)
-//            }
-//            
-//            // Initialize hash value for this chunk:
-//            var A:UInt32 = a0
-//            var B:UInt32 = b0
-//            var C:UInt32 = c0
-//            var D:UInt32 = d0
-//            
-//            var dTemp:UInt32
-//            
-//            // Main loop
-//            for i in 0...63 {
-//                var g:Int = 0
-//                var F:UInt32 = 0
-//                
-//                switch (i) {
-//                case 0...15:
-//                    F = (B & C) | ((~B) & D)
-//                    //F = D ^ (B & (C ^ D))
-//                    g = i
-//                    break
-//                case 16...31:
-//                    F = (D & B) | (~D & C)
-//                    g = (5 * i + 1) % 16
-//                    break
-//                case 32...47:
-//                    F = B ^ C ^ D
-//                    g = (3 * i + 5) % 16
-//                    break
-//                case 48...63:
-//                    F = C ^ (B | (~D))
-//                    g = (7 * i) % 16
-//                    break
-//                default:
-//                    break
-//                }
-//                dTemp = D
-//                D = C
-//                C = B
-//                // ZONL A + F + K[i] overflow uint32
-//                B = B + leftrotate((A + F + K[i] + M[g]), amount: s[i])
-//                A = dTemp
-//            }
-//            a0 = a0 + A
-//            b0 = b0 + B
-//            c0 = c0 + C
-//            d0 = d0 + D
-//        }
-//        
-//        var buf: NSMutableData = NSMutableData();
-//        buf.appendBytes(&a0, length: sizeof(UInt32))
-//        buf.appendBytes(&b0, length: sizeof(UInt32))
-//        buf.appendBytes(&c0, length: sizeof(UInt32))
-//        buf.appendBytes(&d0, length: sizeof(UInt32))
-//        return buf.copy() as? NSData;
-//    }
-//    
-//    private func fn32(n:UInt32) -> UInt32 {
-//        var newN:Int = Int(n)
-//        let power2to32 = Int(pow(Double(2),Double(32)))
-//        while newN > 0x7FFFFFFF {
-//            newN -= power2to32
-//        }
-//        while newN < 0x80000000 {
-//            newN += power2to32
-//        }
-//        return UInt32(newN)
-//    }
-//    
-    private func rotateLeft(x:UInt32, _ amount:UInt32) -> UInt32 {
-        let x = 0xFFFFFFFF as UInt32
-        var ret:UInt32 = ((x << amount) | (x >> (32 - amount))) & 0xFFFFFFFF
-        return ret
+/** String extension */
+extension String {
+    
+    /** Calculate MD5 hash */
+    public func md5() -> String? {
+        var stringData:NSData? = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
+        if let data = stringData {
+            let md5Data = MD5.calculate(data)
+            return md5Data?.toHexString()
+        }
+        return nil
     }
     }
 }
 }
 
 

+ 0 - 1
CryptoSwift/NSDataExtension.swift

@@ -48,7 +48,6 @@ extension NSData {
         var s:String = "";
         var s:String = "";
         for(var i = 0; i < bytesArray.count; i++) {
         for(var i = 0; i < bytesArray.count; i++) {
             var st: String = NSString(format:"%02X", bytesArray[i])
             var st: String = NSString(format:"%02X", bytesArray[i])
-            NSLog("\(bytesArray[i]) -> \(st)")
             s = s + st
             s = s + st
         }
         }
         return s;
         return s;

+ 0 - 156
CryptoSwift/Playground/MyPlayground.playground/section-1.swift

@@ -2,159 +2,3 @@
 
 
 import UIKit
 import UIKit
 
 
-extension Int {
-    
-    private init(bits: [Bool]) {
-        var bitPattern:UInt = 0
-        for (idx,b) in enumerate(bits) {
-            if (b == true) {
-                let bit:UInt = UInt(1) << UInt(idx)
-                bitPattern = bitPattern | bit
-            }
-        }
-        
-        self.init(bitPattern: bitPattern)
-    }
-    
-    /** Array of bytes with optional padding (little-endian) */
-    public func bytes(_ totalBytes: Int = sizeof(Int)) -> [Byte] {
-        var bytes:[Byte] = [Byte](count: totalBytes, repeatedValue: 0)
-        
-        // first convert to data
-        let data = NSData(bytes: [self] as [Int], length: totalBytes)
-        
-        // then convert back to bytes, byte by byte
-        for i in 0..<Swift.min(sizeof(Int),totalBytes) {
-            var b:Byte = 0
-            data.getBytes(&b, range: NSRange(location: i,length: 1))
-            bytes[totalBytes - 1 - i] = b
-        }
-        return bytes
-    }
-    
-    /** Int with array bytes (little-endian) */
-    public static func withBytes(bytes: [Byte]) -> Int {
-        var i:Int = 0
-        let totalBytes = Swift.min(bytes.count, sizeof(Int))
-        
-        // get slice of Int
-        let start = Swift.max(bytes.count - sizeof(Int),0)
-        var intarr = Array<Byte>(bytes[start..<(start + totalBytes)])
-        
-        // extend to Int size if necessary
-        while (intarr.count < sizeof(Int)) {
-            intarr.insert(0 as Byte, atIndex: 0)
-        }
-        
-        let data = NSData(bytes: intarr, length: intarr.count)
-        data.getBytes(&i, length: sizeof(Int));
-        return i.byteSwapped
-    }
-    
-    /** Shift bits to the left. All bits are shifted (including sign bit) */
-    private mutating func shiftLeft(count: Int) -> Int {
-        let bitsCount = sizeof(Int) * 8
-        let shiftCount = Swift.min(count, bitsCount - 1)
-        var shiftedValue:Int = 0;
-        
-        for bitIdx in 0..<bitsCount {
-            // if bit is set then copy to result and shift left 1
-            let bit = 1 << bitIdx
-            if ((self & bit) == bit) {
-                shiftedValue = shiftedValue | (bit << shiftCount)
-            }
-        }
-        self = shiftedValue
-        return self
-    }
-    
-    /** Shift bits to the right. All bits are shifted (including sign bit) */
-    private mutating func shiftRight(count: Int) -> Int {
-        let bitsCount = sizeof(Int) * 8
-        let maxBitsForValue = Int(floor(log2(Double(self)) + 1))
-        let shiftCount = Swift.min(count, maxBitsForValue)
-        var shiftedValue:Int = 0;
-        
-        for bitIdx in 0..<bitsCount {
-            // if bit is set then copy to result and shift left 1
-            let bit = 1 << bitIdx
-            if ((self & bit) == bit) {
-                shiftedValue = shiftedValue | (bit >> shiftCount)
-            }
-        }
-        
-        self = Int(shiftedValue)
-        return self
-    }
-}
-
-// Left operator
-
-infix operator &<<= {
-associativity none
-precedence 160
-}
-
-
-/** shift left and assign with bits truncation */
-func &<<= (inout lhs: Int, rhs: Int) {
-    lhs.shiftLeft(rhs)
-}
-
-infix operator &<< {
-associativity none
-precedence 160
-}
-
-/** shift left with bits truncation */
-func &<< (lhs: Int, rhs: Int) -> Int {
-    var l = lhs;
-    l.shiftLeft(rhs)
-    return l
-}
-
-// Right operator
-
-infix operator &>>= {
-associativity none
-precedence 160
-}
-
-/** shift right and assign with bits truncation */
-func &>>= (inout lhs: Int, rhs: Int) {
-    lhs.shiftRight(rhs)
-}
-
-infix operator &>> {
-associativity none
-precedence 160
-}
-
-/** shift right and assign with bits truncation */
-func &>> (lhs: Int, rhs: Int) -> Int {
-    var l = lhs;
-    l.shiftRight(rhs)
-    return l
-}
-
-
-var four:Byte = 128
-var shifted = four << 24
-
-//let four:Int = 0b00000100
-//let shifted:Int = four &<< 64
-
-shifted
-
-//var i:Int = 9223372036854775808
-//
-//var i:Int = 9
-//var shifted1 = i &<< 61 //  i &<<= 61
-
-//
-//var i:UInt = UInt(4) << UInt(61)
-
-
-//var i = 9
-//i &<< 8
-//

+ 1 - 1
CryptoSwift/Playground/MyPlayground.playground/timeline.xctimeline

@@ -3,7 +3,7 @@
    version = "3.0">
    version = "3.0">
    <TimelineItems>
    <TimelineItems>
       <LoggerValueHistoryTimelineItem
       <LoggerValueHistoryTimelineItem
-         documentLocation = "file:///Users/marcinkrzyzanowski/Devel/CryptoSwift/CryptoSwift/Playground/MyPlayground.playground#CharacterRangeLen=0&amp;CharacterRangeLoc=3749&amp;EndingLineNumber=3&amp;StartingLineNumber=3&amp;Timestamp=429576064.468724">
+         documentLocation = "file:///Users/marcinkrzyzanowski/Devel/CryptoSwift/CryptoSwift/Playground/MyPlayground.playground#CharacterRangeLen=0&amp;CharacterRangeLoc=66&amp;EndingLineNumber=3&amp;StartingLineNumber=3&amp;Timestamp=429786824.478078">
       </LoggerValueHistoryTimelineItem>
       </LoggerValueHistoryTimelineItem>
    </TimelineItems>
    </TimelineItems>
 </Timeline>
 </Timeline>

+ 48 - 0
CryptoSwiftTests/ExtensionsTest.swift

@@ -0,0 +1,48 @@
+//
+//  ExtensionsTest.swift
+//  CryptoSwift
+//
+//  Created by Marcin Krzyzanowski on 15/08/14.
+//  Copyright (c) 2014 Marcin Krzyzanowski. All rights reserved.
+//
+
+import UIKit
+import XCTest
+
+class ExtensionsTest: XCTestCase {
+
+    override func setUp() {
+        super.setUp()
+    }
+    
+    override func tearDown() {
+        super.tearDown()
+    }
+
+    func testIntExtension() {
+        let i1:Int = 1024
+        let i1Array = i1.bytes(32 / 8) // 32 bit
+        let i1recovered = Int.withBytes(i1Array)
+        
+        XCTAssertEqual(i1, i1recovered, "Bytes conversion failed")
+        
+        let i2:Int = 1024
+        let i2Array = i2.bytes(160 / 8) // 160 bit
+        let i2recovered = Int.withBytes(i1Array)
+        
+        XCTAssertEqual(i2, i2recovered, "Bytes conversion failed")
+    }
+    
+    func testBytes() {
+        let size = sizeof(Int) // 32 or 64  bit
+        
+        let i:Int = 1024
+        var bytes = i.bytes()
+        XCTAssertTrue(bytes.count == size, "Invalid bytes length =  \(bytes.count)")
+        
+        // test padding
+        bytes = i.bytes(16)
+        XCTAssertTrue(bytes.count == 16, "Invalid return type \(bytes.count)")
+        XCTAssertTrue(bytes[14] == 4, "Invalid return type \(bytes.count)")
+    }
+}

+ 6 - 21
CryptoSwiftTests/CryptoSwiftTests.swift → CryptoSwiftTests/HashTests.swift

@@ -19,34 +19,19 @@ class CryptoSwiftTests: XCTestCase {
         super.tearDown()
         super.tearDown()
     }
     }
     
     
-    func testOverflow() {
-        var b:Byte = 128
-        var shifted = (Byte)(b << 24)
-    }
-    
-    func testIntExtension() {
-        let i1:Int = 1024
-        let i1Array = i1.bytes(32 / 8) // 32 bit
-        let i1recovered = Int.withBytes(i1Array)
-        
-        XCTAssertEqual(i1, i1recovered, "Bytes conversion failed")
-        
-        let i2:Int = 1024
-        let i2Array = i2.bytes(160 / 8) // 160 bit
-        let i2recovered = Int.withBytes(i1Array)
-        
-        XCTAssertEqual(i2, i2recovered, "Bytes conversion failed")
-    }
-    
     func testMD5() {
     func testMD5() {
-        var data:NSData = NSData(bytes: [49, 50, 51] as [Byte], length: 3)
-//        var data:NSData = NSData(bytes: [49, 50, 51, 50, 51, 50, 51, 50, 51, 50, 51, 50, 51, 50, 51, 50, 51, 50, 51, 50, 49, 50, 51, 50, 51, 50, 51, 50, 51, 50, 51, 50, 51, 50, 51, 50, 51, 50, 51, 50] as [Byte], length: 40)
+        var data:NSData = NSData(bytes: [49, 50, 51] as [Byte], length: 3) // "1", "2", "3"
         var md5data = data.md5()
         var md5data = data.md5()
         XCTAssertNotNil(md5data, "MD5 calculation failed")
         XCTAssertNotNil(md5data, "MD5 calculation failed")
         
         
         if let data = md5data {
         if let data = md5data {
             XCTAssertEqual(data.hexString, "202CB962AC59075B964B07152D234B70", "MD5 calculation failed");
             XCTAssertEqual(data.hexString, "202CB962AC59075B964B07152D234B70", "MD5 calculation failed");
         }
         }
+        
+        if let hash = "123".md5() {
+            XCTAssertEqual(hash, "202CB962AC59075B964B07152D234B70", "MD5 calculation failed");
+        }
+
     }
     }
     
     
 //    func testSHA1() {
 //    func testSHA1() {

+ 16 - 12
README.md

@@ -1,19 +1,23 @@
 #CryptoSwift
 #CryptoSwift
-
-Crypto related helpers for Swift.
-
-Since Xcode6-Beta5 frameworks can't bind to third-party libraries written in C/Objective-C so I decided drop OpenSSL dependency and now let's try build some stuff with Swift.
+Crypto related helpers for Swift implemented in Swift.
 
 
 ##Requirements
 ##Requirements
-~~For now CryptoSwift depends on OpenSSL~~
-
+Good mood
 
 
 ##Usage
 ##Usage
 
 
-	import CryptoSwift
-
-    var data:NSData = NSData(bytes: [49, 50, 51] as Byte[], length: 3)
-    let md5data:NSData = CryptoHash.md5.hash(data)
+    import CryptoSwift
     
     
-	// Printout MD5 as String
-    NSLog(md5data.hexString())
+    /* Calculate hash for array of bytes */
+    var data:NSData = NSData(bytes: [49, 50, 51] as [Byte], length: 3)
+    if let data = CryptoHash.md5.hash(data) {
+        println(data.hexString)
+    }
+    
+    /* Calculate hash for string with convenience extension */
+    var string:String = "123"
+    if let hash = string.md5() {
+        println(string.md5())
+    }
+    
+