Переглянути джерело

Added JSON extension for built-in Swift types.
Added RC4 cipher.
Added AES128 cipher.

Damian Kołakowski 10 роки тому
батько
коміт
e918b6866f

+ 260 - 0
Sources/Swifter/AES128.swift

@@ -0,0 +1,260 @@
+//
+//  AES128.swift
+//  Swifter
+//
+//  Copyright 2014-2016 Damian Kołakowski. All rights reserved.
+//
+
+#if os(Linux)
+    import Glibc
+#else
+    import Foundation
+#endif
+
+
+public struct AES128 {
+    
+    //
+    // Advanced Encryption Standard
+    //
+    // http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+    //
+    
+    // TODO Improvements:
+    //   - Use inout structs rather than copies.
+    //   - Introduce a util method for printing the content of Array<UInt8> as hex string.
+    //   - Avoid key expansion every encryptBlock(...) call.
+    //   - Add support for init with literals.
+
+    public struct Key: CustomStringConvertible {
+        
+        public init(k0: UInt8, k1: UInt8, k2: UInt8, k3: UInt8, k4: UInt8, k5: UInt8, k6: UInt8, k7: UInt8, k8: UInt8, k9: UInt8, k10: UInt8, k11: UInt8, k12: UInt8, k13: UInt8, k14: UInt8, k15: UInt8) {
+            self.k0 = k0
+            self.k1 = k1
+            self.k2 = k2
+            self.k3 = k3
+            self.k4 = k4
+            self.k5 = k5
+            self.k6 = k6
+            self.k7 = k7
+            self.k8 = k8
+            self.k9 = k9
+            self.k10 = k10
+            self.k11 = k11
+            self.k12 = k12
+            self.k13 = k13
+            self.k14 = k14
+            self.k15 = k15
+        }
+        
+        public var k0, k1, k2 , k3 : UInt8
+        public var k4, k5, k6 , k7 : UInt8
+        public var k8, k9, k10, k11 : UInt8
+        public var k12, k13, k14, k15 : UInt8
+        
+        public var description: String {
+            return "[" + [k0, k1, k2, k3, k4, k5, k6, k7, k8, k8, k10, k11, k12, k13, k14, k15].map({ String(format: "%02x", $0) }).joined(separator: ",") + "]"
+        }
+    }
+    
+    public struct Block: CustomStringConvertible {
+        
+        public init(s00: UInt8, s01: UInt8, s02: UInt8, s03: UInt8, s10: UInt8, s11: UInt8, s12: UInt8, s13: UInt8, s20: UInt8, s21: UInt8, s22: UInt8, s23: UInt8, s30: UInt8, s31: UInt8, s32: UInt8, s33: UInt8) {
+            self.s00 = s00
+            self.s01 = s01
+            self.s02 = s02
+            self.s03 = s03
+            self.s10 = s10
+            self.s11 = s11
+            self.s12 = s12
+            self.s13 = s13
+            self.s20 = s20
+            self.s21 = s21
+            self.s22 = s22
+            self.s23 = s23
+            self.s30 = s30
+            self.s31 = s31
+            self.s32 = s32
+            self.s33 = s33
+        }
+        
+        public var s00, s01, s02, s03 : UInt8
+        public var s10, s11, s12, s13 : UInt8
+        public var s20, s21, s22, s23 : UInt8
+        public var s30, s31, s32, s33 : UInt8
+        
+        public var description: String {
+            return
+                "[" + [self.s00, self.s01, self.s02, self.s03].map({ String(format: "%02x", $0) }).joined(separator: ",") + "]\n" +
+                "[" + [self.s10, self.s11, self.s12, self.s13].map({ String(format: "%02x", $0) }).joined(separator: ",") + "]\n" +
+                "[" + [self.s20, self.s21, self.s22, self.s23].map({ String(format: "%02x", $0) }).joined(separator: ",") + "]\n" +
+                "[" + [self.s30, self.s31, self.s32, self.s33].map({ String(format: "%02x", $0) }).joined(separator: ",") + "]"
+        }
+    }
+    
+    public static func encryptBlock(_ block: Block, _ key: Key) -> Block {
+        
+        let roundKeys = keyExpansion(key)
+        
+        var tmpBlock = block
+        
+        tmpBlock = addRoundKey(tmpBlock, roundKeys[0], roundKeys[1], roundKeys[2], roundKeys[3])
+        
+        for i in 1...10 {
+            
+            tmpBlock = subBytes(tmpBlock)
+            tmpBlock = shiftRows(tmpBlock)
+            
+            if i != 10 {
+                tmpBlock = mixColumns(tmpBlock)
+            }
+            
+            let index = i*4
+            tmpBlock = addRoundKey(tmpBlock, roundKeys[index], roundKeys[index+1], roundKeys[index+2], roundKeys[index+3])
+        }
+        
+        return tmpBlock
+    }
+    
+    private static func addRoundKey(_ block: Block, _ kw0: KeyWord, _ kw1: KeyWord, _ kw2: KeyWord, _ kw3: KeyWord) -> Block {
+        return Block(
+            s00: block.s00 ^ kw0.w0, s01: block.s01 ^ kw1.w0, s02: block.s02 ^ kw2.w0, s03: block.s03 ^ kw3.w0,
+            s10: block.s10 ^ kw0.w1, s11: block.s11 ^ kw1.w1, s12: block.s12 ^ kw2.w1, s13: block.s13 ^ kw3.w1,
+            s20: block.s20 ^ kw0.w2, s21: block.s21 ^ kw1.w2, s22: block.s22 ^ kw2.w2, s23: block.s23 ^ kw3.w2,
+            s30: block.s30 ^ kw0.w3, s31: block.s31 ^ kw1.w3, s32: block.s32 ^ kw2.w3, s33: block.s33 ^ kw3.w3
+        )
+    }
+    
+    public static func subBytes(_ state: Block) -> Block {
+        return Block(
+            s00: sboxLookup(state.s00), s01: sboxLookup(state.s01), s02: sboxLookup(state.s02), s03: sboxLookup(state.s03),
+            s10: sboxLookup(state.s10), s11: sboxLookup(state.s11), s12: sboxLookup(state.s12), s13: sboxLookup(state.s13),
+            s20: sboxLookup(state.s20), s21: sboxLookup(state.s21), s22: sboxLookup(state.s22), s23: sboxLookup(state.s23),
+            s30: sboxLookup(state.s30), s31: sboxLookup(state.s31), s32: sboxLookup(state.s32), s33: sboxLookup(state.s33)
+        )
+    }
+    
+    public static func shiftRows(_ state: Block) -> Block {
+        return Block(
+            s00: state.s00, s01: state.s01, s02: state.s02, s03: state.s03,
+            s10: state.s11, s11: state.s12, s12: state.s13, s13: state.s10,
+            s20: state.s22, s21: state.s23, s22: state.s20, s23: state.s21,
+            s30: state.s33, s31: state.s30, s32: state.s31, s33: state.s32
+        )
+    }
+    
+    private static func m2(_ value: UInt8) -> UInt8 {
+        let shifted = value << 1
+        return value & 0x80 > 0 ? ( shifted ^ 0x1B ) : shifted
+    }
+    
+    private static func m3(_ value: UInt8) -> UInt8 {
+        return value ^ m2(value)
+    }
+    
+    private static func mixColumns(_ state: Block) -> Block {
+        
+        return Block(
+            
+            s00: m2(state.s00) ^ m3(state.s10) ^ state.s20 ^ state.s30,
+            s01: m2(state.s01) ^ m3(state.s11) ^ state.s21 ^ state.s31,
+            s02: m2(state.s02) ^ m3(state.s12) ^ state.s22 ^ state.s32,
+            s03: m2(state.s03) ^ m3(state.s13) ^ state.s23 ^ state.s33,
+            
+            s10: state.s00 ^ m2(state.s10) ^ m3(state.s20) ^ state.s30,
+            s11: state.s01 ^ m2(state.s11) ^ m3(state.s21) ^ state.s31,
+            s12: state.s02 ^ m2(state.s12) ^ m3(state.s22) ^ state.s32,
+            s13: state.s03 ^ m2(state.s13) ^ m3(state.s23) ^ state.s33,
+            
+            s20: state.s00 ^ state.s10 ^ m2(state.s20) ^ m3(state.s30),
+            s21: state.s01 ^ state.s11 ^ m2(state.s21) ^ m3(state.s31),
+            s22: state.s02 ^ state.s12 ^ m2(state.s22) ^ m3(state.s32),
+            s23: state.s03 ^ state.s13 ^ m2(state.s23) ^ m3(state.s33),
+            
+            s30: m3(state.s00) ^ state.s10 ^ state.s20 ^ m2(state.s30),
+            s31: m3(state.s01) ^ state.s11 ^ state.s21 ^ m2(state.s31),
+            s32: m3(state.s02) ^ state.s12 ^ state.s22 ^ m2(state.s32),
+            s33: m3(state.s03) ^ state.s13 ^ state.s23 ^ m2(state.s33)
+        )
+    }
+    
+    public struct KeyWord: CustomStringConvertible {
+        
+        public var w0, w1, w2, w3: UInt8
+        
+        public var description: String {
+            return "[" + [w0, w1, w2, w3].map({ String(format: "%02x", $0) }).joined(separator: ",") + "]"
+        }
+    }
+    
+    private static func rotWord(_ word: KeyWord) -> KeyWord {
+        return KeyWord(w0: word.w1, w1: word.w2, w2: word.w3, w3: word.w0)
+    }
+    
+    private static func subWord(_ word: KeyWord) -> KeyWord {
+        return KeyWord(w0: sboxLookup(word.w0), w1: sboxLookup(word.w1), w2: sboxLookup(word.w2), w3: sboxLookup(word.w3))
+    }
+    
+    private static func addWord(_ word1: KeyWord, _ word2: KeyWord) -> KeyWord {
+        return KeyWord(w0: word1.w0 ^ word2.w0, w1: word1.w1 ^ word2.w1, w2: word1.w2 ^ word2.w2, w3: word1.w3 ^ word2.w3)
+    }
+    
+    private static func keyExpansion(_ key: Key) -> [KeyWord] {
+        
+        var words = [KeyWord]()
+        
+        words.append(KeyWord(w0: key.k0,  w1: key.k1,  w2: key.k2,  w3: key.k3))
+        words.append(KeyWord(w0: key.k4,  w1: key.k5,  w2: key.k6,  w3: key.k7))
+        words.append(KeyWord(w0: key.k8,  w1: key.k9,  w2: key.k10, w3: key.k11))
+        words.append(KeyWord(w0: key.k12, w1: key.k13, w2: key.k14, w3: key.k15))
+        
+        var rcon = [KeyWord]()
+        
+        rcon.append(KeyWord(w0: 0x01, w1: 0, w2: 0, w3: 0))
+        rcon.append(KeyWord(w0: 0x02, w1: 0, w2: 0, w3: 0))
+        rcon.append(KeyWord(w0: 0x04, w1: 0, w2: 0, w3: 0))
+        rcon.append(KeyWord(w0: 0x08, w1: 0, w2: 0, w3: 0))
+        rcon.append(KeyWord(w0: 0x10, w1: 0, w2: 0, w3: 0))
+        rcon.append(KeyWord(w0: 0x20, w1: 0, w2: 0, w3: 0))
+        rcon.append(KeyWord(w0: 0x40, w1: 0, w2: 0, w3: 0))
+        rcon.append(KeyWord(w0: 0x80, w1: 0, w2: 0, w3: 0))
+        rcon.append(KeyWord(w0: 0x1b, w1: 0, w2: 0, w3: 0))
+        rcon.append(KeyWord(w0: 0x36, w1: 0, w2: 0, w3: 0))
+        
+        for i in 4..<44 {
+            var temp = words[i-1]
+            if i % 4 == 0 {
+                temp = addWord(subWord(rotWord(temp)), rcon[(i-1)/4])
+            }
+            words.append(addWord(words[i-4], temp))
+        }
+        
+        return words
+    }
+    
+    private static var sbox: [UInt8] = [
+        0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+        0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+        0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+        0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+        0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+        0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+        0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+        0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+        0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+        0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+        0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+        0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+        0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+        0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+        0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+        0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
+    ]
+    
+    private static func sboxLookup(_ value: UInt8) -> UInt8 {
+        let rowIndex = value >> 4
+        let colIndex = value & 0x0F
+        return sbox[Int(rowIndex*16+colIndex)]
+    }
+}
+

+ 199 - 0
Sources/Swifter/JSON.swift

@@ -0,0 +1,199 @@
+//
+//  JSON.swift
+//  Swifter
+//
+//  Copyright © 2016 Damian Kołakowski. All rights reserved.
+//
+
+#if os(Linux)
+    import Glibc
+#else
+    import Foundation
+#endif
+
+// TODO 
+//  - Fix NSNumber extension decoding procedure.
+//  - Escape key string.
+
+public protocol JsonConvertable {
+    
+    func asJson(_ ident: UInt?) -> String
+}
+
+extension String: JsonConvertable {
+    
+    public func asJson(_ ident: UInt? = 0) -> String {
+        return self.unicodeScalars.reduce("\"") { (c, s) -> String in
+            switch s.value {
+            case 0 : return c + "\\0"
+            case 7 : return c + "\\a"
+            case 8 : return c + "\\b"
+            case 9 : return c + "\\t"
+            case 10: return c + "\\n"
+            case 11: return c + "\\v"
+            case 12: return c + "\\f"
+            case 13: return c + "\\r"
+            case 34: return c + "\\\""
+            case 39: return c + "\\'"
+            case 47: return c + "\\/"
+            case 92: return c + "\\\\"
+            case let n where n > 127: return c + "\\u" + String(format:"%04X", n)
+            default:
+                return c + String(s)
+            }
+        } + "\""
+    }
+}
+
+extension Bool: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return self ? "true" : "false"
+    }
+}
+
+extension Double: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return String(self)
+    }
+}
+
+extension Float: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return String(self)
+    }
+}
+
+extension Int: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return String(self)
+    }
+}
+
+extension UInt: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return String(self)
+    }
+}
+
+extension Int8: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return String(self)
+    }
+}
+
+extension UInt8: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return String(self)
+    }
+}
+
+extension Int16: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return String(self)
+    }
+}
+
+extension UInt16: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return String(self)
+    }
+}
+
+extension Int32: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return String(self)
+    }
+}
+
+extension UInt32: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return String(self)
+    }
+}
+
+extension Int64: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return String(self)
+    }
+}
+
+extension UInt64: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return String(self)
+    }
+}
+
+extension Dictionary where Key: ExpressibleByStringLiteral, Value: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return "{" + self.map({ "\"\($0.0)\":" + $0.1.asJson(ident) }).joined(separator: ",") + "}"
+    }
+}
+
+extension Collection where Iterator.Element: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return "[" + (self.map({ $0.asJson(ident) }).joined(separator: ",")) + "]"
+    }
+}
+
+extension Array where Element: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return "[" + (self.map({ $0.asJson(ident) }).joined(separator: ",")) + "]"
+    }
+}
+
+extension NSString: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return (self as String).asJson(ident)
+    }
+}
+
+extension NSArray: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return "[" + (self.map({ ($0 as? JsonConvertable)?.asJson(ident) ?? "null" }).joined(separator: ",")) + "]"
+    }
+}
+
+extension NSNumber: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        switch String(cString: objCType) {
+            case "c":
+                if self == kCFBooleanTrue || self == kCFBooleanFalse {
+                    return self.boolValue.asJson(ident)
+                }
+                return self.int8Value.asJson(ident)
+            case "s": return self.int16Value.asJson(ident)
+            case "i": return self.int32Value.asJson(ident)
+            case "q": return self.int64Value.asJson(ident)
+            case "f": return self.floatValue.asJson(ident)
+            case "d": return self.doubleValue.asJson(ident)
+        default:
+            return self.boolValue.asJson(ident)
+        }
+    }
+}
+
+extension NSDictionary: JsonConvertable {
+    
+    public func asJson(_ ident: UInt?) -> String {
+        return "{" + self.map({ "\"\($0.0)\":" + (($0.1 as? JsonConvertable)?.asJson(ident) ?? "null") }).joined(separator: ",") + "}"
+    }
+}

+ 79 - 0
Sources/Swifter/RC4.swift

@@ -0,0 +1,79 @@
+//
+//  RC4.swift
+//  Swifter
+//
+//  Copyright © 2016 Damian Kołakowski. All rights reserved.
+//
+
+#if os(Linux)
+    import Glibc
+#else
+    import Foundation
+#endif
+
+
+public struct RC4 {
+    
+    //
+    // Rivest Cipher 4
+    //
+    // https://en.wikipedia.org/wiki/RC4
+    //
+    
+    // TODO Improvements:
+    //   - Use inout structs rather than copies.
+    //   - Avoid key schedule every encrypt(...) call.
+    
+    public static func encrypt(_ data: [UInt8], _ key : [UInt8]) -> [UInt8] {
+        return generate(data, key)
+    }
+    
+    public static func decrypt(_ data: [UInt8], _ key : [UInt8]) -> [UInt8] {
+        return generate(data, key)
+    }
+    
+    private static func generate(_ data: [UInt8], _ key : [UInt8]) -> [UInt8] {
+        
+        var S = keySchedule(key)
+        var ouput = [UInt8]()
+        var i = 0, j = 0
+        
+        for byte in data {
+            
+            i = ( i + 1 ) % 256
+            j = ( j + Int(S[i]) ) % 256
+            
+            let tmp = S[i]
+            S[i] = S[j]
+            S[j] = tmp
+            
+            let t = (Int(S[i]) + Int(S[j])) % 256
+            let k = S[t]
+            
+            ouput.append(k ^ byte)
+        }
+        
+        return ouput
+    }
+    
+    private static func keySchedule(_ key: [UInt8]) -> [UInt8] {
+        
+        var S = [UInt8](repeating: 0, count: 256)
+        
+        for i in 0..<S.count {
+            S[i] = UInt8(i)
+        }
+        
+        var j : Int = 0
+        
+        for i in 0..<S.count {
+            j = ( j + Int(S[i]) + Int(key[i % key.count]) ) % 256
+            let tmp = S[i]
+            S[i] = S[j]
+            S[j] = tmp
+        }
+        
+        return S
+    }
+    
+}

+ 45 - 2
XCode/Swifter.xcodeproj/project.pbxproj

@@ -10,6 +10,9 @@
 		7AE893EA1C05127900A29F63 /* SwifteriOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AE893E91C05127900A29F63 /* SwifteriOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		7AE893EA1C05127900A29F63 /* SwifteriOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AE893E91C05127900A29F63 /* SwifteriOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		7AE893FE1C0512C400A29F63 /* SwifterMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AE893FD1C0512C400A29F63 /* SwifterMac.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		7AE893FE1C0512C400A29F63 /* SwifterMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AE893FD1C0512C400A29F63 /* SwifterMac.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		7AE8940D1C05151100A29F63 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7AE8940C1C05151100A29F63 /* Launch Screen.storyboard */; };
 		7AE8940D1C05151100A29F63 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7AE8940C1C05151100A29F63 /* Launch Screen.storyboard */; };
+		7C1145991D527545000DB965 /* AES128.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C1145981D527545000DB965 /* AES128.swift */; };
+		7C11459A1D527545000DB965 /* AES128.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C1145981D527545000DB965 /* AES128.swift */; };
+		7C11459B1D527545000DB965 /* AES128.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C1145981D527545000DB965 /* AES128.swift */; };
 		7C13B57C1C7B069500556443 /* SwifterTestsSQLite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C13B57B1C7B069500556443 /* SwifterTestsSQLite.swift */; };
 		7C13B57C1C7B069500556443 /* SwifterTestsSQLite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C13B57B1C7B069500556443 /* SwifterTestsSQLite.swift */; };
 		7C13B57D1C7B069500556443 /* SwifterTestsSQLite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C13B57B1C7B069500556443 /* SwifterTestsSQLite.swift */; };
 		7C13B57D1C7B069500556443 /* SwifterTestsSQLite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C13B57B1C7B069500556443 /* SwifterTestsSQLite.swift */; };
 		7C3195FB1CC2C68F00DF5406 /* sqlite.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C3195E31CC2C68F00DF5406 /* sqlite.h */; };
 		7C3195FB1CC2C68F00DF5406 /* sqlite.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C3195E31CC2C68F00DF5406 /* sqlite.h */; };
@@ -78,6 +81,13 @@
 		7C4785EA1C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C4785E81C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift */; };
 		7C4785EA1C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C4785E81C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift */; };
 		7C5915221C92A99300D884BC /* SwifterTestsReflection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5915211C92A99300D884BC /* SwifterTestsReflection.swift */; };
 		7C5915221C92A99300D884BC /* SwifterTestsReflection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5915211C92A99300D884BC /* SwifterTestsReflection.swift */; };
 		7C5915231C92A99300D884BC /* SwifterTestsReflection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5915211C92A99300D884BC /* SwifterTestsReflection.swift */; };
 		7C5915231C92A99300D884BC /* SwifterTestsReflection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5915211C92A99300D884BC /* SwifterTestsReflection.swift */; };
+		7C5F78EF1D54BB5600C514AA /* SwifterTestsAES128.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5F78EE1D54BB5600C514AA /* SwifterTestsAES128.swift */; };
+		7C5F78F01D54BB5600C514AA /* SwifterTestsAES128.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5F78EE1D54BB5600C514AA /* SwifterTestsAES128.swift */; };
+		7C5F78F21D54C99200C514AA /* RC4.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5F78F11D54C99200C514AA /* RC4.swift */; };
+		7C5F78F31D54C99200C514AA /* RC4.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5F78F11D54C99200C514AA /* RC4.swift */; };
+		7C5F78F41D54C99200C514AA /* RC4.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5F78F11D54C99200C514AA /* RC4.swift */; };
+		7C5F78F91D54D24B00C514AA /* SwifterTestsRC4.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5F78F51D54D21600C514AA /* SwifterTestsRC4.swift */; };
+		7C5F78FA1D54D24B00C514AA /* SwifterTestsRC4.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5F78F51D54D21600C514AA /* SwifterTestsRC4.swift */; };
 		7C6B57EB1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C6B57EA1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift */; };
 		7C6B57EB1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C6B57EA1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift */; };
 		7C6B57EC1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C6B57EA1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift */; };
 		7C6B57EC1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C6B57EA1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift */; };
 		7C71C5B01A1D52F800682BF0 /* login.html in CopyFiles */ = {isa = PBXBuildFile; fileRef = 98630C061A1C9A9D00478D08 /* login.html */; };
 		7C71C5B01A1D52F800682BF0 /* login.html in CopyFiles */ = {isa = PBXBuildFile; fileRef = 98630C061A1C9A9D00478D08 /* login.html */; };
@@ -90,6 +100,11 @@
 		7CA4815819A2EF2B0030B30D /* test.json in Resources */ = {isa = PBXBuildFile; fileRef = 7CA4815719A2EF2B0030B30D /* test.json */; };
 		7CA4815819A2EF2B0030B30D /* test.json in Resources */ = {isa = PBXBuildFile; fileRef = 7CA4815719A2EF2B0030B30D /* test.json */; };
 		7CA4815919A2EF560030B30D /* test.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7CA4815719A2EF2B0030B30D /* test.json */; };
 		7CA4815919A2EF560030B30D /* test.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7CA4815719A2EF2B0030B30D /* test.json */; };
 		7CB102E01A17381D00CBA3B4 /* logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 7CB102DF1A17381D00CBA3B4 /* logo.png */; };
 		7CB102E01A17381D00CBA3B4 /* logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 7CB102DF1A17381D00CBA3B4 /* logo.png */; };
+		7CB923CC1D50F11700899E2A /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2C85901D50D83D00B32145 /* JSON.swift */; };
+		7CB923CD1D50F11800899E2A /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2C85901D50D83D00B32145 /* JSON.swift */; };
+		7CB923CE1D50F11800899E2A /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2C85901D50D83D00B32145 /* JSON.swift */; };
+		7CB923D01D510D6400899E2A /* SwifterTestsJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CB923CF1D510D6400899E2A /* SwifterTestsJSON.swift */; };
+		7CB923D11D510D6400899E2A /* SwifterTestsJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CB923CF1D510D6400899E2A /* SwifterTestsJSON.swift */; };
 		7CCD1B681C8F7CEC0016D664 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CCD1B671C8F7CEC0016D664 /* AppDelegate.swift */; };
 		7CCD1B681C8F7CEC0016D664 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CCD1B671C8F7CEC0016D664 /* AppDelegate.swift */; };
 		7CCD1B6A1C8F7CEC0016D664 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CCD1B691C8F7CEC0016D664 /* ViewController.swift */; };
 		7CCD1B6A1C8F7CEC0016D664 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CCD1B691C8F7CEC0016D664 /* ViewController.swift */; };
 		7CCD1B6D1C8F7CEC0016D664 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7CCD1B6B1C8F7CEC0016D664 /* Main.storyboard */; };
 		7CCD1B6D1C8F7CEC0016D664 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7CCD1B6B1C8F7CEC0016D664 /* Main.storyboard */; };
@@ -173,7 +188,9 @@
 		7AE893FD1C0512C400A29F63 /* SwifterMac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwifterMac.h; sourceTree = "<group>"; };
 		7AE893FD1C0512C400A29F63 /* SwifterMac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwifterMac.h; sourceTree = "<group>"; };
 		7AE893FF1C0512C400A29F63 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		7AE893FF1C0512C400A29F63 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		7AE8940C1C05151100A29F63 /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
 		7AE8940C1C05151100A29F63 /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
+		7C1145981D527545000DB965 /* AES128.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AES128.swift; sourceTree = "<group>"; };
 		7C13B57B1C7B069500556443 /* SwifterTestsSQLite.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsSQLite.swift; sourceTree = "<group>"; };
 		7C13B57B1C7B069500556443 /* SwifterTestsSQLite.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsSQLite.swift; sourceTree = "<group>"; };
+		7C2C85901D50D83D00B32145 /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = "<group>"; };
 		7C3195E31CC2C68F00DF5406 /* sqlite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqlite.h; sourceTree = "<group>"; };
 		7C3195E31CC2C68F00DF5406 /* sqlite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqlite.h; sourceTree = "<group>"; };
 		7C3195E41CC2C68F00DF5406 /* module.map */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.map; sourceTree = "<group>"; };
 		7C3195E41CC2C68F00DF5406 /* module.map */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.map; sourceTree = "<group>"; };
 		7C3195E51CC2C68F00DF5406 /* sqlite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqlite.c; sourceTree = "<group>"; };
 		7C3195E51CC2C68F00DF5406 /* sqlite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqlite.c; sourceTree = "<group>"; };
@@ -198,6 +215,9 @@
 		7C3945631D256FDA003EEABA /* Scopes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scopes.swift; sourceTree = "<group>"; };
 		7C3945631D256FDA003EEABA /* Scopes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scopes.swift; sourceTree = "<group>"; };
 		7C4785E81C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsWebSocketSession.swift; sourceTree = "<group>"; };
 		7C4785E81C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsWebSocketSession.swift; sourceTree = "<group>"; };
 		7C5915211C92A99300D884BC /* SwifterTestsReflection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsReflection.swift; sourceTree = "<group>"; };
 		7C5915211C92A99300D884BC /* SwifterTestsReflection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsReflection.swift; sourceTree = "<group>"; };
+		7C5F78EE1D54BB5600C514AA /* SwifterTestsAES128.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsAES128.swift; sourceTree = "<group>"; };
+		7C5F78F11D54C99200C514AA /* RC4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RC4.swift; sourceTree = "<group>"; };
+		7C5F78F51D54D21600C514AA /* SwifterTestsRC4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsRC4.swift; sourceTree = "<group>"; };
 		7C6B57EA1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsHttpRouter.swift; sourceTree = "<group>"; };
 		7C6B57EA1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsHttpRouter.swift; sourceTree = "<group>"; };
 		7C7488771C1DA07300CBCD77 /* file.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = file.html; sourceTree = "<group>"; };
 		7C7488771C1DA07300CBCD77 /* file.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = file.html; sourceTree = "<group>"; };
 		7C839B6E19422CFF003A6950 /* SwifterSampleiOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwifterSampleiOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		7C839B6E19422CFF003A6950 /* SwifterSampleiOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwifterSampleiOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -205,6 +225,7 @@
 		7CA4813D19A2EA8D0030B30D /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
 		7CA4813D19A2EA8D0030B30D /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
 		7CA4815719A2EF2B0030B30D /* test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = test.json; sourceTree = "<group>"; };
 		7CA4815719A2EF2B0030B30D /* test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = test.json; sourceTree = "<group>"; };
 		7CB102DF1A17381D00CBA3B4 /* logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo.png; sourceTree = "<group>"; };
 		7CB102DF1A17381D00CBA3B4 /* logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo.png; sourceTree = "<group>"; };
+		7CB923CF1D510D6400899E2A /* SwifterTestsJSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsJSON.swift; sourceTree = "<group>"; };
 		7CCD1B651C8F7CEC0016D664 /* SwifterSampletvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwifterSampletvOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		7CCD1B651C8F7CEC0016D664 /* SwifterSampletvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwifterSampletvOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		7CCD1B671C8F7CEC0016D664 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		7CCD1B671C8F7CEC0016D664 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		7CCD1B691C8F7CEC0016D664 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
 		7CCD1B691C8F7CEC0016D664 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
@@ -359,6 +380,9 @@
 				7C3195F81CC2C68F00DF5406 /* String+BASE64.swift */,
 				7C3195F81CC2C68F00DF5406 /* String+BASE64.swift */,
 				7C3195F91CC2C68F00DF5406 /* String+Misc.swift */,
 				7C3195F91CC2C68F00DF5406 /* String+Misc.swift */,
 				7C3195FA1CC2C68F00DF5406 /* String+SHA1.swift */,
 				7C3195FA1CC2C68F00DF5406 /* String+SHA1.swift */,
+				7C2C85901D50D83D00B32145 /* JSON.swift */,
+				7C1145981D527545000DB965 /* AES128.swift */,
+				7C5F78F11D54C99200C514AA /* RC4.swift */,
 			);
 			);
 			path = Swifter;
 			path = Swifter;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -372,7 +396,6 @@
 				7AE893FC1C0512C400A29F63 /* SwifterMac */,
 				7AE893FC1C0512C400A29F63 /* SwifterMac */,
 				7CA4815619A2EF2B0030B30D /* Resources */,
 				7CA4815619A2EF2B0030B30D /* Resources */,
 				7CCD876C1C660B250068099B /* SwifterTestsCommon */,
 				7CCD876C1C660B250068099B /* SwifterTestsCommon */,
-				7CCD875D1C66099B0068099B /* SwifteriOSTests */,
 				7CCD877A1C660EA30068099B /* SwifterOSXTests */,
 				7CCD877A1C660EA30068099B /* SwifterOSXTests */,
 				7CDAB80B1BE2A1D400C8A977 /* SwifterSampleiOS */,
 				7CDAB80B1BE2A1D400C8A977 /* SwifterSampleiOS */,
 				7CA4813C19A2EA8D0030B30D /* SwifterSampleOSX */,
 				7CA4813C19A2EA8D0030B30D /* SwifterSampleOSX */,
@@ -442,7 +465,8 @@
 			children = (
 			children = (
 				7CCD87601C66099B0068099B /* Info.plist */,
 				7CCD87601C66099B0068099B /* Info.plist */,
 			);
 			);
-			path = SwifteriOSTests;
+			name = SwifteriOSTests;
+			path = ../SwifteriOSTests;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
 		7CCD876C1C660B250068099B /* SwifterTestsCommon */ = {
 		7CCD876C1C660B250068099B /* SwifterTestsCommon */ = {
@@ -454,6 +478,10 @@
 				7C4785E81C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift */,
 				7C4785E81C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift */,
 				7C13B57B1C7B069500556443 /* SwifterTestsSQLite.swift */,
 				7C13B57B1C7B069500556443 /* SwifterTestsSQLite.swift */,
 				7C6B57EA1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift */,
 				7C6B57EA1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift */,
+				7CB923CF1D510D6400899E2A /* SwifterTestsJSON.swift */,
+				7C5F78F51D54D21600C514AA /* SwifterTestsRC4.swift */,
+				7C5F78EE1D54BB5600C514AA /* SwifterTestsAES128.swift */,
+				7CCD875D1C66099B0068099B /* SwifteriOSTests */,
 			);
 			);
 			path = SwifterTestsCommon;
 			path = SwifterTestsCommon;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -788,6 +816,7 @@
 			isa = PBXSourcesBuildPhase;
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				7C5F78F21D54C99200C514AA /* RC4.swift in Sources */,
 				7C31962B1CC2C68F00DF5406 /* Socket.swift in Sources */,
 				7C31962B1CC2C68F00DF5406 /* Socket.swift in Sources */,
 				7C3196191CC2C68F00DF5406 /* HttpResponse.swift in Sources */,
 				7C3196191CC2C68F00DF5406 /* HttpResponse.swift in Sources */,
 				7C3196131CC2C68F00DF5406 /* HttpParser.swift in Sources */,
 				7C3196131CC2C68F00DF5406 /* HttpParser.swift in Sources */,
@@ -797,6 +826,7 @@
 				7C3195FE1CC2C68F00DF5406 /* sqlite.c in Sources */,
 				7C3195FE1CC2C68F00DF5406 /* sqlite.c in Sources */,
 				7C3196311CC2C68F00DF5406 /* SQLite.swift in Sources */,
 				7C3196311CC2C68F00DF5406 /* SQLite.swift in Sources */,
 				7C3196341CC2C68F00DF5406 /* String+BASE64.swift in Sources */,
 				7C3196341CC2C68F00DF5406 /* String+BASE64.swift in Sources */,
+				7C1145991D527545000DB965 /* AES128.swift in Sources */,
 				7C31961C1CC2C68F00DF5406 /* HttpRouter.swift in Sources */,
 				7C31961C1CC2C68F00DF5406 /* HttpRouter.swift in Sources */,
 				7C3196071CC2C68F00DF5406 /* File.swift in Sources */,
 				7C3196071CC2C68F00DF5406 /* File.swift in Sources */,
 				7C3196041CC2C68F00DF5406 /* DemoServer.swift in Sources */,
 				7C3196041CC2C68F00DF5406 /* DemoServer.swift in Sources */,
@@ -805,6 +835,7 @@
 				7C3196161CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C3196161CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C3196221CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
 				7C3196221CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
 				7C31960A1CC2C68F00DF5406 /* Files.swift in Sources */,
 				7C31960A1CC2C68F00DF5406 /* Files.swift in Sources */,
+				7CB923CC1D50F11700899E2A /* JSON.swift in Sources */,
 				7C3196011CC2C68F00DF5406 /* App.swift in Sources */,
 				7C3196011CC2C68F00DF5406 /* App.swift in Sources */,
 				7C3196251CC2C68F00DF5406 /* Process.swift in Sources */,
 				7C3196251CC2C68F00DF5406 /* Process.swift in Sources */,
 				7C3196371CC2C68F00DF5406 /* String+Misc.swift in Sources */,
 				7C3196371CC2C68F00DF5406 /* String+Misc.swift in Sources */,
@@ -815,6 +846,7 @@
 			isa = PBXSourcesBuildPhase;
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				7C5F78F31D54C99200C514AA /* RC4.swift in Sources */,
 				7C31962C1CC2C68F00DF5406 /* Socket.swift in Sources */,
 				7C31962C1CC2C68F00DF5406 /* Socket.swift in Sources */,
 				7C31961A1CC2C68F00DF5406 /* HttpResponse.swift in Sources */,
 				7C31961A1CC2C68F00DF5406 /* HttpResponse.swift in Sources */,
 				7C3196141CC2C68F00DF5406 /* HttpParser.swift in Sources */,
 				7C3196141CC2C68F00DF5406 /* HttpParser.swift in Sources */,
@@ -824,6 +856,7 @@
 				7C3195FF1CC2C68F00DF5406 /* sqlite.c in Sources */,
 				7C3195FF1CC2C68F00DF5406 /* sqlite.c in Sources */,
 				7C3196321CC2C68F00DF5406 /* SQLite.swift in Sources */,
 				7C3196321CC2C68F00DF5406 /* SQLite.swift in Sources */,
 				7C3196351CC2C68F00DF5406 /* String+BASE64.swift in Sources */,
 				7C3196351CC2C68F00DF5406 /* String+BASE64.swift in Sources */,
+				7C11459A1D527545000DB965 /* AES128.swift in Sources */,
 				7C31961D1CC2C68F00DF5406 /* HttpRouter.swift in Sources */,
 				7C31961D1CC2C68F00DF5406 /* HttpRouter.swift in Sources */,
 				7C3196081CC2C68F00DF5406 /* File.swift in Sources */,
 				7C3196081CC2C68F00DF5406 /* File.swift in Sources */,
 				7C3196051CC2C68F00DF5406 /* DemoServer.swift in Sources */,
 				7C3196051CC2C68F00DF5406 /* DemoServer.swift in Sources */,
@@ -832,6 +865,7 @@
 				7C3196171CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C3196171CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C3196231CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
 				7C3196231CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
 				7C31960B1CC2C68F00DF5406 /* Files.swift in Sources */,
 				7C31960B1CC2C68F00DF5406 /* Files.swift in Sources */,
+				7CB923CD1D50F11800899E2A /* JSON.swift in Sources */,
 				7C3196021CC2C68F00DF5406 /* App.swift in Sources */,
 				7C3196021CC2C68F00DF5406 /* App.swift in Sources */,
 				7C3196261CC2C68F00DF5406 /* Process.swift in Sources */,
 				7C3196261CC2C68F00DF5406 /* Process.swift in Sources */,
 				7C3196381CC2C68F00DF5406 /* String+Misc.swift in Sources */,
 				7C3196381CC2C68F00DF5406 /* String+Misc.swift in Sources */,
@@ -868,6 +902,7 @@
 			isa = PBXSourcesBuildPhase;
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				7C5F78F41D54C99200C514AA /* RC4.swift in Sources */,
 				7C31962D1CC2C68F00DF5406 /* Socket.swift in Sources */,
 				7C31962D1CC2C68F00DF5406 /* Socket.swift in Sources */,
 				7C31961B1CC2C68F00DF5406 /* HttpResponse.swift in Sources */,
 				7C31961B1CC2C68F00DF5406 /* HttpResponse.swift in Sources */,
 				7C3196151CC2C68F00DF5406 /* HttpParser.swift in Sources */,
 				7C3196151CC2C68F00DF5406 /* HttpParser.swift in Sources */,
@@ -877,6 +912,7 @@
 				7C31960F1CC2C68F00DF5406 /* WebSockets.swift in Sources */,
 				7C31960F1CC2C68F00DF5406 /* WebSockets.swift in Sources */,
 				7C3196001CC2C68F00DF5406 /* sqlite.c in Sources */,
 				7C3196001CC2C68F00DF5406 /* sqlite.c in Sources */,
 				7C3196331CC2C68F00DF5406 /* SQLite.swift in Sources */,
 				7C3196331CC2C68F00DF5406 /* SQLite.swift in Sources */,
+				7C11459B1D527545000DB965 /* AES128.swift in Sources */,
 				7C3196361CC2C68F00DF5406 /* String+BASE64.swift in Sources */,
 				7C3196361CC2C68F00DF5406 /* String+BASE64.swift in Sources */,
 				7C31961E1CC2C68F00DF5406 /* HttpRouter.swift in Sources */,
 				7C31961E1CC2C68F00DF5406 /* HttpRouter.swift in Sources */,
 				7C3196091CC2C68F00DF5406 /* File.swift in Sources */,
 				7C3196091CC2C68F00DF5406 /* File.swift in Sources */,
@@ -885,6 +921,7 @@
 				7C3196181CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C3196181CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C3196241CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
 				7C3196241CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
 				7C31960C1CC2C68F00DF5406 /* Files.swift in Sources */,
 				7C31960C1CC2C68F00DF5406 /* Files.swift in Sources */,
+				7CB923CE1D50F11800899E2A /* JSON.swift in Sources */,
 				7C3196031CC2C68F00DF5406 /* App.swift in Sources */,
 				7C3196031CC2C68F00DF5406 /* App.swift in Sources */,
 				7C3196271CC2C68F00DF5406 /* Process.swift in Sources */,
 				7C3196271CC2C68F00DF5406 /* Process.swift in Sources */,
 				7C3196391CC2C68F00DF5406 /* String+Misc.swift in Sources */,
 				7C3196391CC2C68F00DF5406 /* String+Misc.swift in Sources */,
@@ -895,11 +932,14 @@
 			isa = PBXSourcesBuildPhase;
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				7C5F78EF1D54BB5600C514AA /* SwifterTestsAES128.swift in Sources */,
 				7CCD87701C660B250068099B /* SwifterTestsHttpParser.swift in Sources */,
 				7CCD87701C660B250068099B /* SwifterTestsHttpParser.swift in Sources */,
 				7C6B57EB1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift in Sources */,
 				7C6B57EB1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift in Sources */,
 				7C5915221C92A99300D884BC /* SwifterTestsReflection.swift in Sources */,
 				7C5915221C92A99300D884BC /* SwifterTestsReflection.swift in Sources */,
 				7C13B57C1C7B069500556443 /* SwifterTestsSQLite.swift in Sources */,
 				7C13B57C1C7B069500556443 /* SwifterTestsSQLite.swift in Sources */,
+				7CB923D01D510D6400899E2A /* SwifterTestsJSON.swift in Sources */,
 				7C4785E91C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift in Sources */,
 				7C4785E91C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift in Sources */,
+				7C5F78F91D54D24B00C514AA /* SwifterTestsRC4.swift in Sources */,
 				7CCD87721C660B250068099B /* SwifterTestsStringExtensions.swift in Sources */,
 				7CCD87721C660B250068099B /* SwifterTestsStringExtensions.swift in Sources */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
@@ -908,11 +948,14 @@
 			isa = PBXSourcesBuildPhase;
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				7C5F78F01D54BB5600C514AA /* SwifterTestsAES128.swift in Sources */,
 				7CCD87841C660ED60068099B /* SwifterTestsHttpParser.swift in Sources */,
 				7CCD87841C660ED60068099B /* SwifterTestsHttpParser.swift in Sources */,
 				7C6B57EC1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift in Sources */,
 				7C6B57EC1CA6C3AA0042655C /* SwifterTestsHttpRouter.swift in Sources */,
 				7C5915231C92A99300D884BC /* SwifterTestsReflection.swift in Sources */,
 				7C5915231C92A99300D884BC /* SwifterTestsReflection.swift in Sources */,
 				7C13B57D1C7B069500556443 /* SwifterTestsSQLite.swift in Sources */,
 				7C13B57D1C7B069500556443 /* SwifterTestsSQLite.swift in Sources */,
+				7CB923D11D510D6400899E2A /* SwifterTestsJSON.swift in Sources */,
 				7C4785EA1C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift in Sources */,
 				7C4785EA1C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift in Sources */,
+				7C5F78FA1D54D24B00C514AA /* SwifterTestsRC4.swift in Sources */,
 				7CCD87851C660ED60068099B /* SwifterTestsStringExtensions.swift in Sources */,
 				7CCD87851C660ED60068099B /* SwifterTestsStringExtensions.swift in Sources */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;

+ 9 - 0
XCode/SwifterSampleOSX/main.swift

@@ -7,6 +7,15 @@
 import Foundation
 import Foundation
 import Swifter
 import Swifter
 
 
+
+let encyrpted = RC4.encrypt([UInt8]("Plaintext".utf8), [UInt8]("Key".utf8))
+
+print(encyrpted.map({ String(format: "%02x", $0) }).joined(separator: ","))
+
+let deencyrpted = RC4.encrypt(encyrpted, [UInt8]("Key".utf8))
+
+print(deencyrpted.map({ String(format: "%02x", $0) }).joined(separator: ","))
+
 do {
 do {
     let server: HttpServer = demoServer(try File.currentWorkingDirectory())
     let server: HttpServer = demoServer(try File.currentWorkingDirectory())
     server["/testAfterBaseRoute"] = { request in
     server["/testAfterBaseRoute"] = { request in

+ 66 - 0
XCode/SwifterTestsCommon/SwifterTestsAES128.swift

@@ -0,0 +1,66 @@
+//
+//  SwifterTestsAES128.swift
+//  Swifter
+//
+//  Copyright © 2016 Damian Kołakowski. All rights reserved.
+//
+//
+
+import XCTest
+import Swifter
+
+class SwifterTestsAES: XCTestCase {
+    
+    func testAES() {
+        
+        // Values from: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf ( Page 34 )
+
+        let key = AES128.Key(
+            k0: UInt8(0x2b),
+            k1: UInt8(0x7e),
+            k2: UInt8(0x15),
+            k3: UInt8(0x16),
+            k4: UInt8(0x28),
+            k5: UInt8(0xae),
+            k6: UInt8(0xd2),
+            k7: UInt8(0xa6),
+            k8: UInt8(0xab),
+            k9: UInt8(0xf7),
+            k10: UInt8(0x15),
+            k11: UInt8(0x88),
+            k12: UInt8(0x09),
+            k13: UInt8(0xcf),
+            k14: UInt8(0x4f),
+            k15: UInt8(0x3c))
+        
+        let text = AES128.Block(
+            s00: 0x32, s01: 0x88, s02: 0x31, s03: 0xe0,
+            s10: 0x43, s11: 0x5a, s12: 0x31, s13: 0x37,
+            s20: 0xf6, s21: 0x30, s22: 0x98, s23: 0x07,
+            s30: 0xa8, s31: 0x8d, s32: 0xa2, s33: 0x34
+        )
+        
+        let encrypted = AES128.encryptBlock(text, key)
+        
+        XCTAssert(encrypted.s00 == 0x39)
+        XCTAssert(encrypted.s10 == 0x25)
+        XCTAssert(encrypted.s20 == 0x84)
+        XCTAssert(encrypted.s30 == 0x1d)
+        
+        XCTAssert(encrypted.s01 == 0x02)
+        XCTAssert(encrypted.s11 == 0xdc)
+        XCTAssert(encrypted.s21 == 0x09)
+        XCTAssert(encrypted.s31 == 0xfb)
+        
+        XCTAssert(encrypted.s02 == 0xdc)
+        XCTAssert(encrypted.s12 == 0x11)
+        XCTAssert(encrypted.s22 == 0x85)
+        XCTAssert(encrypted.s32 == 0x97)
+        
+        XCTAssert(encrypted.s03 == 0x19)
+        XCTAssert(encrypted.s13 == 0x6a)
+        XCTAssert(encrypted.s23 == 0x0b)
+        XCTAssert(encrypted.s33 == 0x32)
+        
+    }
+}

+ 60 - 0
XCode/SwifterTestsCommon/SwifterTestsJSON.swift

@@ -0,0 +1,60 @@
+//
+//  SwifterTestsJSON.swift
+//  Swifter
+//
+//  Copyright © 2016 Damian Kołakowski. All rights reserved.
+//
+
+import XCTest
+import Swifter
+
+class SwifterTestsSwfitJSON: XCTestCase {
+    
+    func testJSONStringEscape() {
+        
+        XCTAssertEqual("".asJson(0), "\"\"")
+        XCTAssertEqual("\"".asJson(0), "\"\\\"\"")
+        XCTAssertEqual("\\".asJson(0), "\"\\\\\"")
+        XCTAssertEqual("/".asJson(0), "\"\\/\"")
+        
+        XCTAssertEqual("\u{8}".asJson(0), "\"\\b\"")
+        XCTAssertEqual("\u{0C}".asJson(0), "\"\\f\"")
+        XCTAssertEqual("\r".asJson(0), "\"\\r\"")
+        XCTAssertEqual("\n".asJson(0), "\"\\n\"")
+        XCTAssertEqual("\t".asJson(0), "\"\\t\"")
+        
+        XCTAssertEqual("ę".asJson(0), "\"\\u0119\"")
+        XCTAssertEqual("한".asJson(0), "\"\\uD55C\"")
+        XCTAssertEqual("💖".asJson(0), "\"\\u1F496\"")
+        XCTAssertEqual("🐪".asJson(0), "\"\\u1F42A\"")
+        
+        // From Ruby: https://github.com/ruby/ruby/blob/trunk/test/json/json_encoding_test.rb
+        
+        XCTAssertEqual("© ≠ €!".asJson(0), "\"\\u00A9 \\u2260 \\u20AC!\"")
+    }
+    
+    func testJSONNumber() {
+        XCTAssertEqual(0.asJson(0), "0")
+        XCTAssertEqual(1.asJson(0), "1")
+        XCTAssertEqual(99999.asJson(0), "99999")
+        
+        XCTAssertEqual((1.01).asJson(0), "1.01")
+        XCTAssertEqual((1.0).asJson(0), "1.0")
+        XCTAssertEqual(Double(1.01).asJson(0), "1.01")
+    }
+
+    
+    func testJSONBool() {
+        XCTAssertEqual(true.asJson(0), "true")
+        XCTAssertEqual(false.asJson(0), "false")
+    }
+
+    
+    func testJSONObject() {
+        XCTAssertEqual([1, 2].asJson(0), "[1,2]")
+        XCTAssertEqual(["key1" : [1, 2]].asJson(0), "{\"key1\":[1,2]}")
+        XCTAssertEqual(["key1" : ["key2": ["key3": false]]].asJson(0), "{\"key1\":{\"key2\":{\"key3\":false}}}")
+        XCTAssertEqual(["key1" : ["key2": ["key3": false, "key4": 1]]].asJson(0), "{\"key1\":{\"key2\":{\"key4\":1,\"key3\":false}}}")
+    }
+    
+}

+ 23 - 0
XCode/SwifterTestsCommon/SwifterTestsRC4.swift

@@ -0,0 +1,23 @@
+//
+//  SwifterTestsRC4.swift
+//  Swifter
+//
+//  Copyright © 2016 Damian Kołakowski. All rights reserved.
+//
+
+import XCTest
+import Swifter
+
+class SwifterTestsRC4: XCTestCase {
+    
+    func testRC4() {
+        
+        let encrypted = RC4.encrypt([UInt8]("Plaintext".utf8), [UInt8]("Key".utf8))
+        
+        XCTAssertTrue(encrypted == [0xbb, 0xf3, 0x16, 0xe8, 0xd9, 0x40, 0xaf, 0x0a, 0xd3])
+        
+        let decrypted = RC4.decrypt([0xbb, 0xf3, 0x16, 0xe8, 0xd9, 0x40, 0xaf, 0x0a, 0xd3], [UInt8]("Key".utf8))
+        
+        XCTAssertTrue(decrypted == [UInt8]("Plaintext".utf8))
+    }
+}