浏览代码

Added reflection control to CRC-32 (calculation can now reflect or not the bytes and result).
Removed UInt32 reversing util function (reverseBytes(_:)) which produced wrong results and added a reverse function for UInt8 and UInt32.

Luís Silva 9 年之前
父节点
当前提交
e0056d9611

+ 0 - 0
CryptoSwift.xcodeproj/project.xcworkspace/xcshareddata/CryptoSwift.xcscmblueprint


+ 10 - 0
CryptoSwiftTests/HashTests.swift

@@ -126,6 +126,16 @@ final class CryptoSwiftTests: XCTestCase {
         XCTAssertEqual("".crc32(nil), "00000000", "CRC32 calculation failed");
     }
     
+    func testCRC32NotReflected() {
+        let bytes : [UInt8] = [0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39]
+        let data:NSData = NSData(bytes: bytes, length: bytes.count)
+        if let crc = data.crc32(nil, reflect: false) {
+            XCTAssertEqual(crc.toHexString(), "fc891918", "CRC32 (with reflection) calculation failed");
+        }
+        
+        XCTAssertEqual("".crc32(nil, reflect: false), "00000000", "CRC32 (with reflection) calculation failed");
+    }
+    
     func testCRC16() {
         let result = CRC().crc16([49,50,51,52,53,54,55,56,57] as [UInt8])
         XCTAssert(result == 0xBB3D, "CRC16 failed")

+ 3 - 4
Sources/CryptoSwift/CRC.swift

@@ -74,16 +74,15 @@ final class CRC {
         0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
         0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040]
     
-    func crc32(message:[UInt8], seed: UInt32? = nil) -> UInt32 {
+    func crc32(message:[UInt8], seed: UInt32? = nil, reflect : Bool = true) -> UInt32 {
         var crc:UInt32 = seed != nil ? seed! : 0xffffffff
-        
         for chunk in BytesSequence(chunkSize: 256, data: message) {
             for b in chunk {
-                let idx = Int((crc ^ UInt32(b)) & 0xff)
+                let idx = Int((crc ^ UInt32(reflect ? b : reverseUInt8(b))) & 0xff)
                 crc = (crc >> 8) ^ CRC.table32[idx]
             }
         }
-        return crc ^ 0xffffffff
+        return (reflect ? crc : reverseUInt32(crc)) ^ 0xffffffff
     }
     
     func crc16(message:[UInt8], seed: UInt16? = nil) -> UInt16 {

+ 2 - 2
Sources/CryptoSwift/CSArrayType+Extensions.swift

@@ -47,8 +47,8 @@ public extension CSArrayType where Generator.Element == UInt8 {
         return Hash.sha512(cs_arrayValue()).calculate()
     }
     
-    public func crc32(seed: UInt32? = nil) -> [Generator.Element] {
-        return Hash.crc32(cs_arrayValue(), seed: seed).calculate()
+    public func crc32(seed: UInt32? = nil, reflect : Bool = true) -> [Generator.Element] {
+        return Hash.crc32(cs_arrayValue(), seed: seed, reflect: reflect).calculate()
     }
     
     public func crc16(seed: UInt16? = nil) -> [Generator.Element] {

+ 2 - 2
Sources/CryptoSwift/Foundation/NSData+Extension.swift

@@ -60,8 +60,8 @@ extension NSData {
         return NSData.withBytes(result)
     }
 
-    public func crc32(seed: UInt32? = nil) -> NSData? {
-        let result = Hash.crc32(self.arrayOfBytes(), seed: seed).calculate()
+    public func crc32(seed: UInt32? = nil, reflect : Bool = true) -> NSData? {
+        let result = Hash.crc32(self.arrayOfBytes(), seed: seed, reflect: reflect).calculate()
         return NSData.withBytes(result)
     }
 

+ 2 - 2
Sources/CryptoSwift/Hash.swift

@@ -10,7 +10,7 @@ public enum Hash {
     case md5(Array<UInt8>)
     case sha1(Array<UInt8>)
     case sha224(Array<UInt8>), sha256(Array<UInt8>), sha384(Array<UInt8>), sha512(Array<UInt8>)
-    case crc32(Array<UInt8>, seed: UInt32?)
+    case crc32(Array<UInt8>, seed: UInt32?, reflect: Bool)
     case crc16(Array<UInt8>, seed: UInt16?)
     
     public func calculate() -> [UInt8] {
@@ -28,7 +28,7 @@ public enum Hash {
         case sha512(let bytes):
             return SHA2(bytes, variant: .sha512).calculate64()
         case crc32(let bytes):
-            return CRC().crc32(bytes.0, seed: bytes.seed).bytes()
+            return CRC().crc32(bytes.0, seed: bytes.seed, reflect: bytes.reflect).bytes()
         case crc16(let bytes):
             return UInt32(CRC().crc16(bytes.0, seed: bytes.seed)).bytes(2)
         }

+ 2 - 2
Sources/CryptoSwift/String+Extension.swift

@@ -33,8 +33,8 @@ extension String {
         return self.utf8.lazy.map({ $0 as UInt8 }).sha512().toHexString()
     }
 
-    public func crc32(seed: UInt32? = nil) -> String {
-        return self.utf8.lazy.map({ $0 as UInt8 }).crc32(seed).toHexString()
+    public func crc32(seed: UInt32? = nil, reflect : Bool = true) -> String {
+        return self.utf8.lazy.map({ $0 as UInt8 }).crc32(seed, reflect: reflect).toHexString()
     }
 
     public func crc16(seed: UInt16? = nil) -> String {

+ 16 - 2
Sources/CryptoSwift/Utils.swift

@@ -34,8 +34,22 @@ func rotateRight(x:UInt64, n:UInt64) -> UInt64 {
     return ((x >> n) | (x << (64 - n)))
 }
 
-func reverseBytes(value: UInt32) -> UInt32 {
-    return ((value & 0x000000FF) << 24) | ((value & 0x0000FF00) << 8) | ((value & 0x00FF0000) >> 8)  | ((value & 0xFF000000) >> 24);
+func reverseUInt8(uint8 : UInt8) -> UInt8 {
+    var v : UInt8 = uint8
+    v = (v & 0xF0) >> 4 | (v & 0x0F) << 4
+    v = (v & 0xCC) >> 2 | (v & 0x33) << 2
+    v = (v & 0xAA) >> 1 | (v & 0x55) << 1
+    return v
+}
+
+func reverseUInt32(uint32 : UInt32) -> UInt32 {
+    var v = uint32
+    v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1)
+    v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2)
+    v = ((v >> 4) & 0x0f0f0f0f) | ((v & 0x0f0f0f0f) << 4)
+    v = ((v >> 8) & 0x00ff00ff) | ((v & 0x00ff00ff) << 8)
+    v = ((v >> 16) & 0xffff) | ((v & 0xffff) << 16)
+    return v
 }
 
 func toUInt32Array(slice: ArraySlice<UInt8>) -> Array<UInt32> {