     ///
     public func decrypt(encryptedData: NSData) -> NSData? {
         if let key = obtainKey(.Private) {
-            // First block size should be the encrypted AES key
+            let algorithm = CCAlgorithm(kCCAlgorithmAES128)
+            
+            // First block contains the encrypted AES key and the IV
             let blockSize = SecKeyGetBlockSize(key)
-            let keyData = encryptedData.subdataWithRange(NSRange(location: 0, length: blockSize))
+            let ivSize = Heimdall.blockSize(algorithm)
+            let keySize = Heimdall.keySize(blockSize - ivSize)
+            
+            let metadata = 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 key and the IV
+            if let decryptedMetadata = NSMutableData(length: blockSize) {
+                let encryptedMetadata = UnsafePointer<UInt8>(metadata.bytes)
+                let decryptedMetadataBytes = UnsafeMutablePointer<UInt8>(decryptedMetadata.mutableBytes)
+                
+                var decryptedMetadataLength = blockSize
+                let decryptionStatus = SecKeyDecrypt(key, .PKCS1, encryptedMetadata, metadata.length, decryptedMetadataBytes, &decryptedMetadataLength)
+                
+                if decryptionStatus == noErr {
+                    decryptedMetadata.length = Int(decryptedMetadataLength)
                     
-                    // Decrypt the message
-                    if let message = Heimdall.decrypt(messageData, key: decryptedKey, algorithm: CCAlgorithm(kCCAlgorithmAES128)) {
+                    // We can now extract the key and the IV
+                    let decryptedKey = decryptedMetadata.subdataWithRange(NSRange(location: 0, length: keySize))
+                    let decryptedIv = decryptedMetadata.subdataWithRange(NSRange(location: keySize, length: ivSize))
+                    
+                    if let message = Heimdall.decrypt(messageData, key: decryptedKey, iv: decryptedIv, algorithm: algorithm) {
                         return message
                     }
                 }

    /// - parameters:
    ///     - publicTag: Tag to use for the public key
    ///     - privateTag: Tag to use for the private key
    ///     - keySize: Size of the RSA key pair
    ///
    /// - returns: Heimdall instance ready for both public and private key operations
    ///

        }
    }
    
    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 + 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, ivData, dataBytes, dataLength, encryptedData, encryptedDataLength, &encryptedLength)
            
            if UInt32(status) == UInt32(kCCSuccess) {
                result.length = Int(encryptedLength)
