         return Int(CCCalibratePBKDF(algorithm.rawValue, keyLength, saltLength, pseudoRandomAlgorithm.rawValue, derivedKeyLength, UInt32(msec)))
     }
     
-    public static func PBKDF(_ algorithm: PBKDFAlgorithm, _ pseudoRandomAlgorithm: PseudoRandomAlgorithm, _ key: Data, _ salt: Data, _ derivedKeyLength: Int, _ round: Int) throws -> Data {
+    public static func PBKDF<K : ContiguousBytes, S : ContiguousBytes>(_ algorithm: PBKDFAlgorithm, _ pseudoRandomAlgorithm: PseudoRandomAlgorithm, _ key: K, _ salt: S, _ derivedKeyLength: Int, _ round: Int) throws -> Data {
         
         var result = Data(count: derivedKeyLength)
         
-        let status = result.withUnsafeMutableBufferPointer { result in key.withUnsafeBufferPointer { key in key.withMemoryRebound(to: Int8.self) { key in salt.withUnsafeBufferPointer { salt in
-            
-            CCKeyDerivationPBKDF(algorithm.rawValue, key.baseAddress, key.count, salt.baseAddress, salt.count, pseudoRandomAlgorithm.rawValue, uint(round), result.baseAddress, result.count)
-            
-            } } } }
+        let status = result.withUnsafeMutableBufferPointer { result in key.withUnsafeBytes { key in salt.withUnsafeBytes { salt in
+            
+            CCKeyDerivationPBKDF(algorithm.rawValue, key.bindMemory(to: Int8.self).baseAddress, key.count, salt.bindMemory(to: UInt8.self).baseAddress, salt.count, pseudoRandomAlgorithm.rawValue, uint(round), result.baseAddress, result.count)
+            
+            } } }
         
         guard status == kCCSuccess else  { throw Error(status: status) }
         

        public var status: CCCryptorStatus
    }
    
    public static func encrypt(_ algorithm: CryptorAlgorithm, _ options: CryptorOptions, _ key: Data, _ data: Data, _ iv: Data? = nil) throws -> Data {
        
        var result = Data(count: data.count + algorithm.blockSize)
        var length = 0
        
        var status: CCCryptorStatus = 0
        
        result.withUnsafeMutableBytes { result in key.withUnsafeBytes { key in data.withUnsafeBytes { data in
            
            if let iv = iv {
                iv.withUnsafeBytes { iv in
                    status = CCCrypt(CCOperation(kCCEncrypt), algorithm.rawValue, CCOptions(options.rawValue), key.baseAddress, key.count, iv.baseAddress, data.baseAddress, data.count, result.baseAddress, result.count, &length)
                }
            } else {
                status = CCCrypt(CCOperation(kCCEncrypt), algorithm.rawValue, CCOptions(options.rawValue), key.baseAddress, key.count, nil, data.baseAddress, data.count, result.baseAddress, result.count, &length)
            }
            
            } } }
        
        guard status == kCCSuccess else  { throw Error(status: status) }
        
        return result.prefix(length)
    }
    
    public static func decrypt(_ algorithm: CryptorAlgorithm, _ options: CryptorOptions, _ key: Data, _ data: Data, _ iv: Data? = nil) throws -> Data {
        
        var result = Data(count: data.count + algorithm.blockSize)
        var length = 0
        
        var status: CCCryptorStatus = 0
        
        result.withUnsafeMutableBytes { result in key.withUnsafeBytes { key in data.withUnsafeBytes { data in
            
            if let iv = iv {
                iv.withUnsafeBytes { iv in
                    status = CCCrypt(CCOperation(kCCDecrypt), algorithm.rawValue, CCOptions(options.rawValue), key.baseAddress, key.count, iv.baseAddress, data.baseAddress, data.count, result.baseAddress, result.count, &length)
                }
            } else {
                status = CCCrypt(CCOperation(kCCDecrypt), algorithm.rawValue, CCOptions(options.rawValue), key.baseAddress, key.count, nil, data.baseAddress, data.count, result.baseAddress, result.count, &length)
            }
            
            } } }
        
        guard status == kCCSuccess else  { throw Error(status: status) }
        
        return result.prefix(length)
    }
}


        return Data(referencing: immutableReference)
    }()
    
    public static func symmetricKeyWrap<K : ContiguousBytes, E : ContiguousBytes>(_ algorithm: WrappingAlgorithm, _ key: K, _ encryptionKey: E) throws -> Data {
        return try symmetricKeyWrap(algorithm, key, encryptionKey, rfc3394)
    }
    
    public static func symmetricKeyWrap<K : ContiguousBytes, E : ContiguousBytes, I : ContiguousBytes>(_ algorithm: WrappingAlgorithm, _ key: K, _ encryptionKey: E, _ iv: I) throws -> Data {
        
        return try key.withUnsafeBytes { key in try encryptionKey.withUnsafeBytes { encryptionKey in try iv.withUnsafeBytes { iv in
            
            let outputSize = CCSymmetricWrappedSize(algorithm.rawValue, key.count)
            var result = Data(count: outputSize)
            
            var length = outputSize
            
            let status = result.withUnsafeMutableBufferPointer { CCSymmetricKeyWrap(algorithm.rawValue, iv.bindMemory(to: UInt8.self).baseAddress, iv.count, encryptionKey.bindMemory(to: UInt8.self).baseAddress, encryptionKey.count, key.bindMemory(to: UInt8.self).baseAddress, key.count, $0.baseAddress, &length) }
            
            guard status == kCCSuccess else  { throw Error(status: status) }
            
            return result.prefix(upTo: length)
            
            } } }
    }
    
    public static func symmetricKeyUnwrap<K : ContiguousBytes, E : ContiguousBytes>(_ algorithm: WrappingAlgorithm, _ key: K, _ encryptionKey: E) throws -> Data {
        return try symmetricKeyUnwrap(algorithm, key, encryptionKey, rfc3394)
    }
    
    public static func symmetricKeyUnwrap<K : ContiguousBytes, E : ContiguousBytes, I : ContiguousBytes>(_ algorithm: WrappingAlgorithm, _ key: K, _ encryptionKey: E, _ iv: I) throws -> Data {
        
        return try key.withUnsafeBytes { key in try encryptionKey.withUnsafeBytes { encryptionKey in try iv.withUnsafeBytes { iv in
            
            let outputSize = CCSymmetricUnwrappedSize(algorithm.rawValue, key.count)
            var result = Data(count: outputSize)
            
            var length = outputSize
            
            let status = result.withUnsafeMutableBufferPointer { CCSymmetricKeyUnwrap(algorithm.rawValue, iv.bindMemory(to: UInt8.self).baseAddress, iv.count, encryptionKey.bindMemory(to: UInt8.self).baseAddress, encryptionKey.count, key.bindMemory(to: UInt8.self).baseAddress, key.count, $0.baseAddress, &length) }
            
            guard status == kCCSuccess else  { throw Error(status: status) }
            
            return result.prefix(upTo: length)
            
            } } }
    }
}

