         }
     }
     
-    private class func generateSymmetricKey(keySize: Int) -> NSData? {
-        var result = [UInt8](count: keySize, repeatedValue: 0)
-        SecRandomCopyBytes(kSecRandomDefault, keySize, &result)
-        
-        return NSData(bytes: result, length: keySize)
-    }
-    
-    
-    private class func encrypt(data: NSData, key: NSData, algorithm: CCAlgorithm) -> NSData? {
+    private class func generateRandomBytes(count: Int) -> NSData? {
+        var result = [UInt8](count: count, repeatedValue: 0)
+        SecRandomCopyBytes(kSecRandomDefault, count, &result)
+        
+        return NSData(bytes: result, length: count)
+    }
+    
+    private class func keySize(blockSize: Int) -> Int {
+        if blockSize >= Int(kCCKeySizeAES256) {
+            return kCCKeySizeAES256
+        } else if blockSize >= Int(kCCKeySizeAES192) {
+            return kCCKeySizeAES192
+        } else {
+            return kCCKeySizeAES128
+        }
+    }
+    
+    private class func blockSize(algorithm: CCAlgorithm) -> Int {
+        switch Int(algorithm) {
+        case kCCAlgorithmAES128, kCCAlgorithmAES:
+            return kCCBlockSizeAES128
+        case kCCAlgorithmDES:
+            return kCCBlockSizeDES
+        case kCCAlgorithm3DES:
+            return kCCBlockSize3DES
+        case kCCAlgorithmCAST:
+            return kCCBlockSizeCAST
+        case kCCAlgorithmRC2:
+            return kCCBlockSizeRC2
+        case kCCAlgorithmBlowfish:
+            return kCCBlockSizeBlowfish
+        default:
+            return 0
+        }
+    }
+    
+    
+    private class func encrypt(data: NSData, key: NSData, iv: NSData, algorithm: CCAlgorithm) -> NSData? {
         let dataBytes = UnsafePointer<UInt8>(data.bytes)
         let dataLength = data.length
         
-        if let result = NSMutableData(length: dataLength + key.length) {
+        if let result = NSMutableData(length: dataLength + key.length + iv.length) {
             let keyData = UnsafePointer<UInt8>(key.bytes)
             let keyLength = size_t(key.length)
+            let ivData = UnsafePointer<UInt8>(iv.bytes)
             
             let encryptedData = UnsafeMutablePointer<UInt8>(result.mutableBytes)
             let encryptedDataLength = size_t(result.length)
             
             var encryptedLength: size_t = 0
             
-            let status = CCCrypt(CCOperation(kCCEncrypt), algorithm, CCOptions(kCCOptionPKCS7Padding), keyData, keyLength, nil, dataBytes, dataLength, encryptedData, encryptedDataLength, &encryptedLength)
+            let status = CCCrypt(CCOperation(kCCEncrypt), algorithm, CCOptions(kCCOptionPKCS7Padding), keyData, keyLength, ivData, dataBytes, dataLength, encryptedData, encryptedDataLength, &encryptedLength)
             
             if UInt32(status) == UInt32(kCCSuccess) {
                 result.length = Int(encryptedLength)

    ///
    public func decrypt(encryptedData: NSData) -> NSData? {
        if let key = obtainKey(.Private) {
            // First block size should be the encrypted AES key
            let blockSize = SecKeyGetBlockSize(key)
            let keyData = encryptedData.subdataWithRange(NSRange(location: 0, length: blockSize))
            let messageData = encryptedData.subdataWithRange(NSRange(location: blockSize, length: encryptedData.length - blockSize))
            
            // Decrypt the key
            if let decryptedKey = NSMutableData(length: blockSize) {
                let encryptedKeyData = UnsafePointer<UInt8>(keyData.bytes)
                let decryptedKeyData = UnsafeMutablePointer<UInt8>(decryptedKey.mutableBytes)
                var decryptedLength = blockSize
                
                let keyStatus = SecKeyDecrypt(key, .PKCS1, encryptedKeyData, keyData.length, decryptedKeyData, &decryptedLength)
                
                if keyStatus == noErr {
                    decryptedKey.length = Int(decryptedLength)
                    
                    // Decrypt the message
                    if let message = Heimdall.decrypt(messageData, key: decryptedKey, algorithm: CCAlgorithm(kCCAlgorithmAES128)) {
                        return message
                    }
                }

        return nil
    }
    
    private class func decrypt(data: NSData, key: NSData, iv: NSData, algorithm: CCAlgorithm) -> NSData? {
        let encryptedData = UnsafePointer<UInt8>(data.bytes)
        let encryptedDataLength = data.length
        
        if let result = NSMutableData(length: encryptedDataLength) {
            let keyData = UnsafePointer<UInt8>(key.bytes)
            let keyLength = size_t(key.length)
            let ivData = UnsafePointer<UInt8>(iv.bytes)
            
            let decryptedData = UnsafeMutablePointer<UInt8>(result.mutableBytes)
            let decryptedDataLength = size_t(result.length)
            
            var decryptedLength: size_t = 0
            
            let status = CCCrypt(CCOperation(kCCDecrypt), algorithm, CCOptions(kCCOptionPKCS7Padding), keyData, keyLength, ivData, encryptedData, encryptedDataLength, decryptedData, decryptedDataLength, &decryptedLength)
            
            if UInt32(status) == UInt32(kCCSuccess) {
                result.length = Int(decryptedLength)
