Bläddra i källkod

More ChaCha20 performance improvements.

Marcin Krzyżanowski 10 år sedan
förälder
incheckning
4c5cb5e5c7

+ 22 - 0
CryptoSwift.xcodeproj/xcshareddata/xcbaselines/754BE45F19693E190098E6F3.xcbaseline/9396A4FE-F8F7-4542-8F75-DE77E1FEBEB9.plist

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>classNames</key>
+	<dict>
+		<key>ChaCha20Tests</key>
+		<dict>
+			<key>testChaCha20Performance()</key>
+			<dict>
+				<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
+				<dict>
+					<key>baselineAverage</key>
+					<real>0.15</real>
+					<key>baselineIntegrationDisplayName</key>
+					<string>Local Baseline</string>
+				</dict>
+			</dict>
+		</dict>
+	</dict>
+</dict>
+</plist>

+ 40 - 0
CryptoSwift.xcodeproj/xcshareddata/xcbaselines/754BE45F19693E190098E6F3.xcbaseline/Info.plist

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>runDestinationsByUUID</key>
+	<dict>
+		<key>9396A4FE-F8F7-4542-8F75-DE77E1FEBEB9</key>
+		<dict>
+			<key>localComputer</key>
+			<dict>
+				<key>busSpeedInMHz</key>
+				<integer>100</integer>
+				<key>cpuCount</key>
+				<integer>1</integer>
+				<key>cpuKind</key>
+				<string>Intel Core i7</string>
+				<key>cpuSpeedInMHz</key>
+				<integer>1700</integer>
+				<key>logicalCPUCoresPerPackage</key>
+				<integer>4</integer>
+				<key>modelCode</key>
+				<string>MacBookAir6,2</string>
+				<key>physicalCPUCoresPerPackage</key>
+				<integer>2</integer>
+				<key>platformIdentifier</key>
+				<string>com.apple.platform.macosx</string>
+			</dict>
+			<key>targetArchitecture</key>
+			<string>x86_64</string>
+			<key>targetDevice</key>
+			<dict>
+				<key>modelCode</key>
+				<string>iPhone7,2</string>
+				<key>platformIdentifier</key>
+				<string>com.apple.platform.iphonesimulator</string>
+			</dict>
+		</dict>
+	</dict>
+</dict>
+</plist>

+ 22 - 5
CryptoSwift/ChaCha20.swift

@@ -79,7 +79,10 @@ public class ChaCha20 {
 
 
         for i in 0..<16 {
         for i in 0..<16 {
             x[i] = x[i] &+ input[i]
             x[i] = x[i] &+ input[i]
-            output.extend(x[i].bigEndian.bytes())
+            output += [UInt8((x[i] & 0xFFFFFFFF) >> 24),
+                       UInt8((x[i] & 0xFFFFFF) >> 16),
+                       UInt8((x[i] & 0xFFFF) >> 8),
+                       UInt8((x[i] & 0xFF) >> 0)]
         }
         }
 
 
         return output;
         return output;
@@ -96,7 +99,7 @@ public class ChaCha20 {
         // 4 - 8
         // 4 - 8
         for (var i = 0; i < 4; i++) {
         for (var i = 0; i < 4; i++) {
             let start = i * 4
             let start = i * 4
-            ctx.input[i + 4] = UInt32.withBytes(key[start..<(start + 4)]).bigEndian
+            ctx.input[i + 4] = wordNumber(key[start..<(start + 4)])
         }
         }
         
         
         var addPos = 0;
         var addPos = 0;
@@ -120,14 +123,16 @@ public class ChaCha20 {
         // 8 - 11
         // 8 - 11
         for (var i = 0; i < 4; i++) {
         for (var i = 0; i < 4; i++) {
             let start = addPos + (i*4)
             let start = addPos + (i*4)
-            ctx.input[i + 8] = UInt32.withBytes(key[start..<(start + 4)]).bigEndian
+            
+            let bytes = key[start..<(start + 4)]
+            ctx.input[i + 8] = wordNumber(bytes)
         }
         }
 
 
         // iv
         // iv
         ctx.input[12] = 0
         ctx.input[12] = 0
         ctx.input[13] = 0
         ctx.input[13] = 0
-        ctx.input[14] = UInt32.withBytes(iv[0..<4]).bigEndian
-        ctx.input[15] = UInt32.withBytes(iv[4..<8]).bigEndian
+        ctx.input[14] = wordNumber(iv[0..<4])
+        ctx.input[15] = wordNumber(iv[4..<8])
         
         
         return ctx
         return ctx
     }
     }
@@ -180,3 +185,15 @@ public class ChaCha20 {
         b = rotateLeft((b ^ c), 7);
         b = rotateLeft((b ^ c), 7);
     }
     }
 }
 }
+
+// MARK: Helpers
+
+/// Change array to number. It's here because arrayOfBytes is too slow
+private func wordNumber(bytes:ArraySlice<UInt8>) -> UInt32 {
+    var value:UInt32 = 0
+    for (var i:UInt32 = 0, j = 0; i < 4; i++, j++) {
+        value = value | UInt32(bytes[j]) << (8 * i)
+    }
+    return value
+}
+

+ 5 - 2
CryptoSwift/Generics.swift

@@ -34,7 +34,9 @@ func integerFromBitsArray<T: UnsignedIntegerType>(bits: [Bit]) -> T
     return bitPattern
     return bitPattern
 }
 }
 
 
-/** initialize integer from array of bytes */
+/// Initialize integer from array of bytes.
+/// I found this method slow
+@availability(*, deprecated=0.8)
 func integerWithBytes<T: IntegerType>(bytes: [UInt8]) -> T {
 func integerWithBytes<T: IntegerType>(bytes: [UInt8]) -> T {
     var totalBytes = Swift.min(bytes.count, sizeof(T))
     var totalBytes = Swift.min(bytes.count, sizeof(T))
     // get slice of Int
     // get slice of Int
@@ -53,7 +55,8 @@ func integerWithBytes<T: IntegerType>(bytes: [UInt8]) -> T {
     return i
     return i
 }
 }
 
 
-/** array of bytes, little-endian representation */
+/// Array of bytes, little-endian representation. Don't use if not necessary.
+/// I found this method slow
 func arrayOfBytes<T>(value:T, length:Int? = nil) -> [UInt8] {
 func arrayOfBytes<T>(value:T, length:Int? = nil) -> [UInt8] {
     let totalBytes = length ?? sizeof(T)
     let totalBytes = length ?? sizeof(T)
     var v = value
     var v = value

+ 1 - 1
CryptoSwiftTests/ChaCha20Tests.swift

@@ -74,7 +74,7 @@ class ChaCha20Tests: XCTestCase {
     func testChaCha20Performance() {
     func testChaCha20Performance() {
         let key:[UInt8] = [0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c];
         let key:[UInt8] = [0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c];
         let iv:[UInt8] = [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F]
         let iv:[UInt8] = [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F]
-        let message = [UInt8](count: 1024 * 1024, repeatedValue: 7)
+        let message = [UInt8](count: (1024 * 1024) * 1, repeatedValue: 7)
         self.measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false, forBlock: { () -> Void in
         self.measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false, forBlock: { () -> Void in
             self.startMeasuring()
             self.startMeasuring()
             let encrypted = ChaCha20(key: key, iv: iv)?.encrypt(message)
             let encrypted = ChaCha20(key: key, iv: iv)?.encrypt(message)