Parcourir la source

Addedd SHA1 hash

Marcin Krzyżanowski il y a 11 ans
Parent
commit
fff41a1a91

+ 4 - 0
CryptoSwift.xcodeproj/project.pbxproj

@@ -9,6 +9,7 @@
 /* Begin PBXBuildFile section */
 		750A54601992D2680017DA75 /* MD5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 750A545F1992D2680017DA75 /* MD5.swift */; };
 		752DEF7719693EA000E17557 /* NSDataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752DEF7619693EA000E17557 /* NSDataExtension.swift */; };
+		752E087B199FF27C005B0EA0 /* SHA1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752E087A199FF27C005B0EA0 /* SHA1.swift */; };
 		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 */; };
 		754BE45B19693E190098E6F3 /* CryptoSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = 754BE45A19693E190098E6F3 /* CryptoSwift.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -89,6 +90,7 @@
 /* Begin PBXFileReference section */
 		750A545F1992D2680017DA75 /* MD5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MD5.swift; sourceTree = "<group>"; };
 		752DEF7619693EA000E17557 /* NSDataExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSDataExtension.swift; sourceTree = "<group>"; };
+		752E087A199FF27C005B0EA0 /* SHA1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SHA1.swift; sourceTree = "<group>"; };
 		75445820196AA2A5002FF20E /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
 		7547195019931802002FA5F1 /* IntExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntExtension.swift; sourceTree = "<group>"; };
 		754BE45519693E190098E6F3 /* CryptoSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CryptoSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -159,6 +161,7 @@
 				754BE45A19693E190098E6F3 /* CryptoSwift.h */,
 				7552614D1993051E000D2B20 /* CryptoHash.swift */,
 				750A545F1992D2680017DA75 /* MD5.swift */,
+				752E087A199FF27C005B0EA0 /* SHA1.swift */,
 				758F3F771992F6CE0014BBDA /* ByteExtension.swift */,
 				7547195019931802002FA5F1 /* IntExtension.swift */,
 				752DEF7619693EA000E17557 /* NSDataExtension.swift */,
@@ -313,6 +316,7 @@
 			files = (
 				7552614E1993051E000D2B20 /* CryptoHash.swift in Sources */,
 				7599C9C6199EA28700A3988B /* StringExtension.swift in Sources */,
+				752E087B199FF27C005B0EA0 /* SHA1.swift in Sources */,
 				750A54601992D2680017DA75 /* MD5.swift in Sources */,
 				752DEF7719693EA000E17557 /* NSDataExtension.swift in Sources */,
 				754C8FED19979F94005AD904 /* ArrayExtension.swift in Sources */,

+ 2 - 2
CryptoSwift/CryptoHash.swift

@@ -21,8 +21,8 @@ public enum CryptoHash: Int {
         switch self {
         case md5:
             return data.md5()
-            //        case sha1:
-            //            return data.sha1()
+        case sha1:
+            return data.sha1()
             //        case sha224:
             //            return data.sha224()
             //        case sha256:

+ 125 - 126
CryptoSwift/MD5.swift

@@ -6,149 +6,148 @@
 //  Copyright (c) 2014 Marcin Krzyzanowski. All rights reserved.
 //
 
-    import Foundation
+import Foundation
 
-    public class MD5 {
+public class MD5 {
 
-        /** specifies the per-round shift amounts */
-        private 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,
-                           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]
-        
-        /** binary integer part of the sines of integers (Radians) */
-        private let K: [UInt32] = [0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
-                           0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,
-                           0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,
-                           0x6b901122,0xfd987193,0xa679438e,0x49b40821,
-                           0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,
-                           0xd62f105d,0x2441453,0xd8a1e681,0xe7d3fbc8,
-                           0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,
-                           0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,
-                           0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,
-                           0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,
-                           0x289b7ec6,0xeaa127fa,0xd4ef3085,0x4881d05,
-                           0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,
-                           0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,
-                           0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,
-                           0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,
-                           0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391]
-        
-        let a0: UInt32 = 0x67452301
-        let b0: UInt32 = 0xefcdab89
-        let c0: UInt32 = 0x98badcfe
-        let d0: UInt32 = 0x10325476
+    /** specifies the per-round shift amounts */
+    private 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,
+                       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]
+    
+    /** binary integer part of the sines of integers (Radians) */
+    private let K: [UInt32] = [0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
+                       0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,
+                       0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,
+                       0x6b901122,0xfd987193,0xa679438e,0x49b40821,
+                       0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,
+                       0xd62f105d,0x2441453,0xd8a1e681,0xe7d3fbc8,
+                       0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,
+                       0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,
+                       0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,
+                       0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,
+                       0x289b7ec6,0xeaa127fa,0xd4ef3085,0x4881d05,
+                       0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,
+                       0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,
+                       0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,
+                       0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,
+                       0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391]
+    
+    let a0: UInt32 = 0x67452301
+    let b0: UInt32 = 0xefcdab89
+    let c0: UInt32 = 0x98badcfe
+    let d0: UInt32 = 0x10325476
+    
+    private var message: NSData
+    
+    //MARK: Public
+    
+    public init(_ message: NSData) {
+        self.message = message
+    }
+    
+    public func calculate() -> NSData? {
+        var tmpMessage: NSMutableData = NSMutableData(data: message)
+        let wordSize = sizeof(UInt32)
         
-        private var message: NSData
+        var aa = a0
+        var bb = b0
+        var cc = c0
+        var dd = d0
         
-        //MARK: Public
+        // Step 1. Append Padding Bits
+        tmpMessage.appendBytes([0x80]) // append one bit (Byte with one bit) to message
         
-        public init(_ message: NSData) {
-            self.message = message
+        // append "0" bit until message length in bits ≡ 448 (mod 512)
+        while tmpMessage.length % 64 != 56 {
+            tmpMessage.appendBytes([0x00])
         }
         
-        public func calculate() -> NSData? {
-            var tmpMessage: NSMutableData = NSMutableData(data: message)
-            let wordSize = sizeof(UInt32)
-            
-            var aa = a0
-            var bb = b0
-            var cc = c0
-            var dd = d0
-            
-            // Step 1. Append Padding Bits
-            tmpMessage.appendBytes([0x80]) // append one bit (Byte with one bit) to message
+        // Step 2. Append Length a 64-bit representation of lengthInBits
+        var lengthInBits = (message.length * 8)
+        var lengthBytes = lengthInBits.bytes(64 / 8)
+        tmpMessage.appendBytes(reverse(lengthBytes));
+        
+        // Process the message in successive 512-bit chunks:
+        let chunkSizeBytes = 512 / 8 // 64
+        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)))
             
-            // append "0" bit until message length in bits ≡ 448 (mod 512)
-            while tmpMessage.length % 64 != 56 {
-                tmpMessage.appendBytes([0x00])
+            // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15
+            var M:[UInt32] = [UInt32](count: 16, repeatedValue: 0)
+            for x in 0..<M.count {
+                var range = NSRange(location:x * wordSize, length: wordSize)
+                chunk.getBytes(&M[x], range:range);
             }
             
-            // Step 2. Append Length a 64-bit representation of lengthInBits
-            var lengthInBits = (message.length * 8)
-            var lengthBytes = lengthInBits.bytes(64 / 8)
-            tmpMessage.appendBytes(reverse(lengthBytes));
+            // Initialize hash value for this chunk:
+            var A:UInt32 = aa
+            var B:UInt32 = bb
+            var C:UInt32 = cc
+            var D:UInt32 = dd
             
-            // Process the message in successive 512-bit chunks:
-            let chunkSizeBytes = 512 / 8 // 64
-            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
-                // println("wordSize \(wordSize)");
-                var M:[UInt32] = [UInt32](count: 16, repeatedValue: 0)
-                for x in 0..<M.count {
-                    var range = NSRange(location:x * wordSize, length: wordSize)
-                    chunk.getBytes(&M[x], range:range);
-                }
-                
-                // Initialize hash value for this chunk:
-                var A:UInt32 = aa
-                var B:UInt32 = bb
-                var C:UInt32 = cc
-                var D:UInt32 = dd
-                
-                var dTemp:UInt32 = 0
+            var dTemp:UInt32 = 0
+            
+            // Main loop
+            for j in 0...63 {
+                var g = 0
+                var F:UInt32 = 0
                 
-                // Main loop
-                for j in 0...63 {
-                    var g = 0
-                    var F:UInt32 = 0
-                    
-                    switch (j) {
-                    case 0...15:
-                        F = (B & C) | ((~B) & D)
-                        g = j
-                        break
-                    case 16...31:
-                        F = (D & B) | (~D & C)
-                        g = (5 * j + 1) % 16
-                        break
-                    case 32...47:
-                        F = B ^ C ^ D
-                        g = (3 * j + 5) % 16
-                        break
-                    case 48...63:
-                        F = C ^ (B | (~D))
-                        g = (7 * j) % 16
-                        break
-                    default:
-                        break
-                    }
-                    dTemp = D
-                    D = C
-                    C = B
-                    B = B &+ rotateLeft((A &+ F &+ K[j] &+ M[g]), s[j])
-                    A = dTemp    
+                switch (j) {
+                case 0...15:
+                    F = (B & C) | ((~B) & D)
+                    g = j
+                    break
+                case 16...31:
+                    F = (D & B) | (~D & C)
+                    g = (5 * j + 1) % 16
+                    break
+                case 32...47:
+                    F = B ^ C ^ D
+                    g = (3 * j + 5) % 16
+                    break
+                case 48...63:
+                    F = C ^ (B | (~D))
+                    g = (7 * j) % 16
+                    break
+                default:
+                    break
                 }
-                
-                aa = aa &+ A
-                bb = bb &+ B
-                cc = cc &+ C
-                dd = dd &+ D
+                dTemp = D
+                D = C
+                C = B
+                B = B &+ rotateLeft((A &+ F &+ K[j] &+ M[g]), s[j])
+                A = dTemp    
             }
-
-            var buf: NSMutableData = NSMutableData();
-            buf.appendBytes(&aa, length: wordSize)
-            buf.appendBytes(&bb, length: wordSize)
-            buf.appendBytes(&cc, length: wordSize)
-            buf.appendBytes(&dd, length: wordSize)
             
-            return buf.copy() as? NSData;
+            aa = aa &+ A
+            bb = bb &+ B
+            cc = cc &+ C
+            dd = dd &+ D
         }
 
-        //MARK: Class
-        
-        class func calculate(message: NSData) -> NSData?
-        {
-            return MD5(message).calculate();
-        }
+        var buf: NSMutableData = NSMutableData();
+        buf.appendBytes(&aa, length: wordSize)
+        buf.appendBytes(&bb, length: wordSize)
+        buf.appendBytes(&cc, length: wordSize)
+        buf.appendBytes(&dd, length: wordSize)
         
-        //MARK: Private
-        
-        private func rotateLeft(x:UInt32, _ n:UInt32) -> UInt32 {
-            return (x &<< n) | (x &>> (32 - n))
-        }
+        return buf.copy() as? NSData;
+    }
+
+    //MARK: Class
+    
+    class func calculate(message: NSData) -> NSData?
+    {
+        return MD5(message).calculate();
+    }
+    
+    //MARK: Private
+    
+    private func rotateLeft(x:UInt32, _ n:UInt32) -> UInt32 {
+        return (x &<< n) | (x &>> (32 - n))
     }
+}
 

+ 4 - 0
CryptoSwift/NSDataExtension.swift

@@ -39,6 +39,10 @@ extension NSData {
     public func md5() -> NSData? {
         return MD5(self).calculate()
     }
+
+    public func sha1() -> NSData? {
+        return SHA1(self).calculate()
+    }
     
     internal func toHexString() -> String {
         let count = self.length / sizeof(Byte)

+ 135 - 0
CryptoSwift/SHA1.swift

@@ -0,0 +1,135 @@
+//
+//  SHA1.swift
+//  CryptoSwift
+//
+//  Created by Marcin Krzyzanowski on 16/08/14.
+//  Copyright (c) 2014 Marcin Krzyzanowski. All rights reserved.
+//
+
+import Foundation
+
+public class SHA1 {
+    
+    private let h:[UInt32] = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]
+    private var message: NSData;
+    
+    public init(_ message: NSData) {
+        self.message = message
+    }
+    
+    public func calculate() -> NSData? {
+        let wordSize = sizeof(UInt32)
+        
+        var h0 = h[0]
+        var h1 = h[1]
+        var h2 = h[2]
+        var h3 = h[3]
+        var h4 = h[4]
+        
+        // make it big-endian
+        var tmpMessage: NSMutableData = NSMutableData(data: message)
+        
+        // append one bit (Byte with one bit) to message
+        tmpMessage.appendBytes([0x80])
+
+        // append "0" bit until message length in bits ≡ 448 (mod 512)
+        while tmpMessage.length % 64 != 56 {
+            tmpMessage.appendBytes([0x00])
+        }
+        
+        // append message length, in a 64-bit big-endian integer. So now the message length is a multiple of 512 bits.
+        tmpMessage.appendBytes((message.length * 8).bytes(64 / 8));
+        
+        // Process the message in successive 512-bit chunks:
+        let chunkSizeBytes = 512 / 8 // 64
+        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, big-endian
+            // Extend the sixteen 32-bit words into eighty 32-bit words:
+            var M:[UInt32] = [UInt32](count: 80, repeatedValue: 0)
+            for x in 0..<M.count {
+                switch (x) {
+                case 0...15:
+                    var range = NSRange(location:x * wordSize, length: wordSize)
+                    var le:UInt32 = 0
+                    chunk.getBytes(&le, range:range);
+                    M[x] = le.bigEndian
+                    break
+                default:
+                    M[x] = rotateLeft(M[x-3] ^ M[x-8] ^ M[x-14] ^ M[x-16], 1)
+                    break
+                }
+            }
+            
+            var A = h0
+            var B = h1
+            var C = h2
+            var D = h3
+            var E = h4
+            
+            
+            // Main loop
+            for j in 0...79 {
+                var f: UInt32 = 0;
+                var k: UInt32 = 0
+                
+                switch (j) {
+                case 0...19:
+                    f = (B & C) | ((~B) & D)
+                    k = 0x5A827999
+                    break
+                case 20...39:
+                    f = B ^ C ^ D
+                    k = 0x6ED9EBA1
+                    break
+                case 40...59:
+                    f = (B & C) | (B & D) | (C & D)
+                    k = 0x8F1BBCDC
+                    break
+                case 60...79:
+                    f = B ^ C ^ D
+                    k = 0xCA62C1D6
+                    break
+                default:
+                    break
+                }
+                
+                var temp = (rotateLeft(A,5) &+ f &+ E &+ M[j] &+ k) & 0xffffffff
+                E = D
+                D = C
+                C = rotateLeft(B, 30)
+                B = A
+                A = temp
+                
+            }
+            
+            h0 = (h0 &+ A) & 0xffffffff
+            h1 = (h1 &+ B) & 0xffffffff
+            h2 = (h2 &+ C) & 0xffffffff
+            h3 = (h3 &+ D) & 0xffffffff
+            h4 = (h4 &+ E) & 0xffffffff
+        }
+        
+        // Produce the final hash value (big-endian) as a 160 bit number:
+        var buf: NSMutableData = NSMutableData();
+        [h0, h1, h2, h3, h4].map({ (item) -> () in
+            var i:UInt32 = item.bigEndian
+            buf.appendBytes(&i, length: sizeof(UInt32))
+        })
+        
+        return buf.copy() as? NSData;
+    }
+    
+    //MARK: Private
+    
+    private func reverseBytes(value: UInt32) -> UInt32
+    {
+        return (value & 0x000000FF) << 24 | (value & 0x0000FF00) << 8 |
+               (value & 0x00FF0000) >> 8  | (value & 0xFF000000) >> 24;
+    }
+    
+    private func rotateLeft(x:UInt32, _ n:UInt32) -> UInt32 {
+        return ((x &<< n) & 0xffffffff) | (x &>> (32 - n))
+    }
+}

+ 6 - 8
CryptoSwiftTests/HashTests.swift

@@ -59,14 +59,12 @@ class CryptoSwiftTests: XCTestCase {
         }
     }
     
-//    func testSHA1() {
-//        var data:NSData = NSData(bytes: [49, 50, 51] as [Byte], length: 3)
-//        var sha1:NSData = data.sha1()
-//        XCTAssertNotNil(sha1, "SHA1 calculation failed")
-//        
-//        var sha1String:String = sha1.toHexString()
-//        XCTAssertEqualObjects(sha1String, "40BD001563085FC35165329EA1FF5C5ECBDBBEEF", "SHA1 calculation failed");
-//    }
+    func testSHA1() {
+        var data:NSData = NSData(bytes: [0x31, 0x32, 0x33] as [Byte], length: 3)
+        if let hash = data.sha1() {
+            XCTAssertEqual(hash.hexString, "40BD001563085FC35165329EA1FF5C5ECBDBBEEF", "SHA1 calculation failed");
+        }
+    }
 //
 //    func testSHA512() {
 //        var data:NSData = NSData(bytes: [49, 50, 51] as [Byte], length: 3)