Marcin Krzyżanowski 11 rokov pred
rodič
commit
39375d4cb7

+ 4 - 0
CryptoSwift/CryptoHash.swift

@@ -23,6 +23,10 @@ public enum CryptoHash {
             return data.sha224()
         case sha256:
             return data.sha256()
+        case sha384:
+            return data.sha384()
+        case sha512:
+            return data.sha512()
         default:
             return nil
         }

+ 3 - 3
CryptoSwift/CryptoHashBase.swift

@@ -17,14 +17,14 @@ class CryptoHashBase {
     }
     
     /** Common part for hash calculation. Prepare header data. */
-    func prepare() -> NSMutableData {
+    func prepare(_ len:Int = 64) -> NSMutableData {
         var tmpMessage: NSMutableData = NSMutableData(data: self.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 {
+        while tmpMessage.length % len != (len - 8) {
             tmpMessage.appendBytes([0x00])
         }
         
@@ -51,7 +51,7 @@ class CryptoHashBase {
     }
     
     func rotateRight(x:UInt32, _ n:UInt32) -> UInt32 {
-        return ((x &>> n) & 0xffffffff) | (x &<< (32 - n))
+        return (x >> n) | (x << (32 - n))
     }
 
     func rotateRight(x:UInt64, _ n:UInt64) -> UInt64 {

+ 10 - 2
CryptoSwift/NSDataExtension.swift

@@ -45,11 +45,19 @@ extension NSData {
     }
 
     public func sha224() -> NSData {
-        return SHA2(self).calculate(.sha224)
+        return SHA2(self).calculate32(.sha224)
     }
 
     public func sha256() -> NSData {
-        return SHA2(self).calculate(.sha256)
+        return SHA2(self).calculate32(.sha256)
+    }
+
+    public func sha384() -> NSData {
+        return SHA2(self).calculate64(.sha384)
+    }
+
+    public func sha512() -> NSData {
+        return SHA2(self).calculate64(.sha512)
     }
 
     internal func toHexString() -> String {

+ 98 - 10
CryptoSwift/SHA2.swift

@@ -63,6 +63,9 @@ class SHA2 : CryptoHashBase {
             case .sha224:
                 finalHH = Array(hh[0..<7])
                 break;
+            case .sha384:
+                finalHH = Array(hh[0..<6])
+                break;
             default:
                 break;
             }
@@ -70,7 +73,8 @@ class SHA2 : CryptoHashBase {
         }
     }
     
-    func calculate(variant: SHA2.variant) -> NSData {
+    //TODO: I can't do generict out of calculate32 and calculate64 (UInt32 vs UInt64), but if you can - please do pull request.
+    func calculate32(variant: SHA2.variant) -> NSData {
         var tmpMessage = self.prepare()
         
         // hash values
@@ -89,7 +93,7 @@ class SHA2 : CryptoHashBase {
             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 sixty-four 32-bit words:
-            var M:[UInt32] = [UInt32](count: 64, repeatedValue: 0)
+            var M:[UInt32] = [UInt32](count: variant.k().count, repeatedValue: 0)
             for x in 0..<M.count {
                 switch (x) {
                 case 0...15:
@@ -133,14 +137,14 @@ class SHA2 : CryptoHashBase {
                 A = t1 &+ t2
             }
             
-            hh[0] = (hh[0] &+ A) & 0xffffffff
-            hh[1] = (hh[1] &+ B) & 0xffffffff
-            hh[2] = (hh[2] &+ C) & 0xffffffff
-            hh[3] = (hh[3] &+ D) & 0xffffffff
-            hh[4] = (hh[4] &+ E) & 0xffffffff
-            hh[5] = (hh[5] &+ F) & 0xffffffff
-            hh[6] = (hh[6] &+ G) & 0xffffffff
-            hh[7] = (hh[7] &+ H) & 0xffffffff
+            hh[0] = (hh[0] &+ A)
+            hh[1] = (hh[1] &+ B)
+            hh[2] = (hh[2] &+ C)
+            hh[3] = (hh[3] &+ D)
+            hh[4] = (hh[4] &+ E)
+            hh[5] = (hh[5] &+ F)
+            hh[6] = (hh[6] &+ G)
+            hh[7] = (hh[7] &+ H)
         }
         
         // Produce the final hash value (big-endian) as a 160 bit number:
@@ -153,4 +157,88 @@ class SHA2 : CryptoHashBase {
         
         return buf.copy() as NSData;
     }
+    
+    func calculate64(variant: SHA2.variant) -> NSData {
+        var tmpMessage = self.prepare(128)
+        
+        // hash values
+        var hh = [UInt64]()
+        variant.h().map({(h) -> () in
+            hh.append(h)
+        })
+        
+        // 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 1024-bit chunks:
+        let chunkSizeBytes = 1024 / 8 // 128
+        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 64-bit words M[j], 0 ≤ j ≤ 15, big-endian
+            // Extend the sixteen 64-bit words into eighty 64-bit words:
+            var M = [UInt64](count: variant.k().count, repeatedValue: 0)
+            for x in 0..<M.count {
+                switch (x) {
+                case 0...15:
+                    var le:UInt64 = 0
+                    chunk.getBytes(&le, range:NSRange(location:x * sizeofValue(le), length: sizeofValue(le)));
+                    M[x] = le.bigEndian
+                    break
+                default:
+                    let s0 = rotateRight(M[x-15], 1) ^ rotateRight(M[x-15], 8) ^ (M[x-15] >> 7)
+                    let s1 = rotateRight(M[x-2], 19) ^ rotateRight(M[x-2], 61) ^ (M[x-2] >> 6)
+                    M[x] = M[x-16] &+ s0 &+ M[x-7] &+ s1
+                    break
+                }
+            }
+            
+            var A = hh[0]
+            var B = hh[1]
+            var C = hh[2]
+            var D = hh[3]
+            var E = hh[4]
+            var F = hh[5]
+            var G = hh[6]
+            var H = hh[7]
+            
+            // Main loop
+            for j in 0..<variant.k().count {
+                let s0 = rotateRight(A,28) ^ rotateRight(A,34) ^ rotateRight(A,39)
+                let maj = (A & B) ^ (A & C) ^ (B & C)
+                let t2 = s0 &+ maj
+                let s1 = rotateRight(E,14) ^ rotateRight(E,18) ^ rotateRight(E,41)
+                let ch = (E & F) ^ ((~E) & G)
+                let t1 = H &+ s1 &+ ch &+ variant.k()[j] &+ UInt64(M[j])
+                
+                H = G
+                G = F
+                F = E
+                E = D &+ t1
+                D = C
+                C = B
+                B = A
+                A = t1 &+ t2
+            }
+            
+            hh[0] = (hh[0] &+ A)
+            hh[1] = (hh[1] &+ B)
+            hh[2] = (hh[2] &+ C)
+            hh[3] = (hh[3] &+ D)
+            hh[4] = (hh[4] &+ E)
+            hh[5] = (hh[5] &+ F)
+            hh[6] = (hh[6] &+ G)
+            hh[7] = (hh[7] &+ H)
+        }
+        
+        // Produce the final hash value (big-endian)
+        var buf: NSMutableData = NSMutableData();
+        
+        variant.resultingArray(hh).map({ (item) -> () in
+            var i = item.bigEndian
+            buf.appendBytes(&i, length: sizeofValue(i))
+        })
+        
+        return buf.copy() as NSData;
+    }
 }

+ 8 - 0
CryptoSwift/StringExtension.swift

@@ -28,4 +28,12 @@ extension String {
         return self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)?.sha256().toHexString()
     }
 
+    public func sha384() -> String? {
+        return self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)?.sha384().toHexString()
+    }
+
+    public func sha512() -> String? {
+        return self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)?.sha512().toHexString()
+    }
+
 }

+ 24 - 12
CryptoSwiftTests/HashTests.swift

@@ -74,7 +74,7 @@ class CryptoSwiftTests: XCTestCase {
     func testSHA224() {
         var data:NSData = NSData(bytes: [0x31, 0x32, 0x33] as [Byte], length: 3)
         var hash:NSData = data.sha224();
-        XCTAssertEqual(hash.hexString, "78D8045D684ABD2EECE923758F3CD781489DF3A48E1278982466017F", "SHA256 calculation failed");
+        XCTAssertEqual(hash.hexString, "78D8045D684ABD2EECE923758F3CD781489DF3A48E1278982466017F", "SHA224 calculation failed");
     }
 
     func testSHA256() {
@@ -83,19 +83,31 @@ class CryptoSwiftTests: XCTestCase {
         XCTAssertEqual(hash.hexString, "A665A45920422F9D417E4867EFDC4FB8A04A1F3FFF1FA07E998E86F7F7A27AE3", "SHA256 calculation failed");
         
         if let hash = "Rosetta code".sha256() {
-            XCTAssertEqual(hash, "764FAF5C61AC315F1497F9DFA542713965B785E5CC2F707D6468D7D1124CDFCF", "SHA1 calculation failed")
+            XCTAssertEqual(hash, "764FAF5C61AC315F1497F9DFA542713965B785E5CC2F707D6468D7D1124CDFCF", "SHA256 calculation failed")
         }
     }
-    
-//    func testSHA512() {
-//        var data:NSData = NSData(bytes: [49, 50, 51] as [Byte], length: 3)
-//        var sha512:NSData = data.sha512()
-//        XCTAssertNotNil(sha512, "SHA512 calculation failed")
-//        
-//        var sha512String:String = sha512.toHexString()
-//        XCTAssertEqualObjects(sha512String, "3C9909AFEC25354D551DAE21590BB26E38D53F2173B8D3DC3EEE4C047E7AB1C1EB8B85103E3BE7BA613B31BB5C9C36214DC9F14A42FD7A2FDB84856BCA5C44C2", "SHA512 calculation failed");
-//    }
-//
+
+    func testSHA384() {
+        var data:NSData = NSData(bytes: [49, 50, 51] as [Byte], length: 3)
+        var hash = data.sha384()
+        XCTAssertEqual(hash.hexString, "9A0A82F0C0CF31470D7AFFEDE3406CC9AA8410671520B727044EDA15B4C25532A9B5CD8AAF9CEC4919D76255B6BFB00F", "SHA384 calculation failed");
+        
+        if let hash = "The quick brown fox jumps over the lazy dog.".sha384() {
+            XCTAssertEqual(hash, "ED892481D8272CA6DF370BF706E4D7BC1B5739FA2177AAE6C50E946678718FC67A7AF2819A021C2FC34E91BDB63409D7", "SHA384 calculation failed");
+        }
+    }
+
+    func testSHA512() {
+        var data:NSData = NSData(bytes: [49, 50, 51] as [Byte], length: 3)
+        var hash = data.sha512()
+        XCTAssertEqual(hash.hexString, "3C9909AFEC25354D551DAE21590BB26E38D53F2173B8D3DC3EEE4C047E7AB1C1EB8B85103E3BE7BA613B31BB5C9C36214DC9F14A42FD7A2FDB84856BCA5C44C2", "SHA512 calculation failed");
+        
+        if let hash = "The quick brown fox jumps over the lazy dog.".sha512() {
+            XCTAssertEqual(hash, "91EA1245F20D46AE9A037A989F54F1F790F0A47607EEB8A14D12890CEA77A1BBC6C7ED9CF205E67B7F2B8FD4C7DFD3A7A8617E45F3C463D481C7E586C39AC1ED", "SHA512 calculation failed");
+        }
+
+    }
+
 //    func testHashEnum() {
 //        var data:NSData = NSData(bytes: [49, 50, 51] as [Byte], length: 3)
 //        let md5 = CryptoHash.md5.hash(data);

+ 2 - 0
README.md

@@ -14,6 +14,8 @@ Good mood
 - SHA1
 - SHA224
 - SHA256
+- SHA384
+- SHA512
 
 ##Usage