Swift: RSA encrypt file or text : I use swift 3.
I encrypt message and save it to file. If when I decrypt file the same time of encrypt file, decrypt successful but if other time decrypt function return nil.

I use this class for encrypt and decrypt.

    class Crypt{
        
        // MARK: Public
        
        // MARK: Internal
        var publicKey, privateKey: SecKey?
        var publicKeyData, privateKeyData: Data?
        var statusCode: OSStatus?
        
        
        let publicKeyAttr: [NSObject: NSObject] = [
            kSecAttrIsPermanent:true as NSObject,
            kSecAttrApplicationTag:"com.aparnik.ios.books.public".data(using: String.Encoding.utf8)! as NSObject,
            kSecClass: kSecClassKey, // added this value
            kSecReturnData: kCFBooleanTrue] // added this value
        let privateKeyAttr: [NSObject: NSObject] = [
            kSecAttrIsPermanent:true as NSObject,
            kSecAttrApplicationTag:"com.aparnik.ios.books.private".data(using: String.Encoding.utf8)! as NSObject,
            kSecClass: kSecClassKey, // added this value
            kSecReturnData: kCFBooleanTrue] // added this value
        
        // MARK: Private
        
        // MARK: Initializer
        init() {
            self.generateRSAKey()
        }
        
        // MARK: Function
        fileprivate func generateRSAKey() {
            
            var keyPairAttr = [NSObject: NSObject]()
            keyPairAttr[kSecAttrKeyType] = kSecAttrKeyTypeRSA
            keyPairAttr[kSecAttrKeySizeInBits] = 1024 as NSObject
            keyPairAttr[kSecPublicKeyAttrs] = publicKeyAttr as NSObject
            keyPairAttr[kSecPrivateKeyAttrs] = privateKeyAttr as NSObject
            
            statusCode = SecKeyGeneratePair(keyPairAttr as CFDictionary, &publicKey, &privateKey)
            
            if statusCode == noErr && self.publicKey != nil && self.privateKey != nil {
                print("Key pair generated OK")
                var resultPublicKey: AnyObject?
                var resultPrivateKey: AnyObject?
                let statusPublicKey = SecItemCopyMatching(publicKeyAttr as CFDictionary, &resultPublicKey)
                let statusPrivateKey = SecItemCopyMatching(privateKeyAttr as CFDictionary, &resultPrivateKey)
                
                if statusPublicKey == noErr {
                    if let publicKeyData = resultPublicKey as? Data {
                        self.publicKeyData = publicKeyData
    //                    let publicKeyXor = xor(publicKeyData)
                        //print("Public Key: \((publicKeyData.base64EncodedString()))")
                        //print("Public Key xor: \(publicKeyXor.base64EncodedString())")
                        
                    }
                }
                
                if statusPrivateKey == noErr {
                    if let privateKey = resultPrivateKey as? Data {
                        self.privateKeyData = privateKey
                        //print("Private Key: \((privateKey.base64EncodedString()))"
                    }
                }
            } else {
                //print("Error generating key pair: \(String(describing: statusCode))")
            }
        }
        
        
        func xor() -> Data{
            
            var publicKeyXor: Data = Data()
            
                if (self.publicKeyData != nil) {
                    
                    //print("Public Key: \((publicKeyData.base64EncodedString()))")
                    //print("Public Key xor: \(publicKeyXor.base64EncodedString())")
                    publicKeyXor = self.publicKeyData!
    
                    let base: Int = 53
                    let length: Int = 40
                    let magic: Int = 95
                    
                    for i in 0..<length{
                        let index = i + base
                        publicKeyXor[index] = self.publicKeyData![magic] ^ self.publicKeyData![index]
                    }
                }
        
            
            return publicKeyXor
        }
        
        // decrypt
        func decryptWithRSAKey(_ encryptedData: Data, padding: SecPadding = .PKCS1, rsaKeyRef: SecKey? = nil) -> Data? {
            let rsaKeyRef = rsaKeyRef ?? self.privateKey!
            let blockSize = SecKeyGetBlockSize(rsaKeyRef)
            let dataSize = encryptedData.count / MemoryLayout<UInt8>.size
            
            var encryptedDataAsArray = [UInt8](repeating: 0, count: dataSize)
            (encryptedData as NSData).getBytes(&encryptedDataAsArray, length: dataSize)
            
            var decryptedData = [UInt8](repeating: 0, count: 0)
            var idx = 0
            while (idx < encryptedDataAsArray.count ) {
                var idxEnd = idx + blockSize
                if ( idxEnd > encryptedDataAsArray.count ) {
                    idxEnd = encryptedDataAsArray.count
                }
                var chunkData = [UInt8](repeating: 0, count: blockSize)
                for i in idx..<idxEnd {
                    chunkData[i-idx] = encryptedDataAsArray[i]
                }
                
                var decryptedDataBuffer = [UInt8](repeating: 0, count: blockSize)
                var decryptedDataLength = blockSize
                
                let status = SecKeyDecrypt(rsaKeyRef, padding, chunkData, idxEnd-idx, &decryptedDataBuffer, &decryptedDataLength)
                if ( status != noErr ) {
                    return nil
                }
                let finalData = removePadding(decryptedDataBuffer)
                decryptedData += finalData
                
                idx += blockSize
            }
            
            return Data(bytes: UnsafePointer<UInt8>(decryptedData), count: decryptedData.count)
        }
        
        // remove padding
        func removePadding(_ data: [UInt8]) -> [UInt8] {
            var idxFirstZero = -1
            var idxNextZero = data.count
            for i in 0..<data.count {
                if ( data[i] == 0 ) {
                    if ( idxFirstZero < 0 ) {
                        idxFirstZero = i
                    } else {
                        idxNextZero = i
                        break
                    }
                }
            }
            if ( idxNextZero-idxFirstZero-1 == 0 ) {
                idxNextZero = idxFirstZero
                idxFirstZero = -1
            }
            var newData = [UInt8](repeating: 0, count: idxNextZero-idxFirstZero-1)
            for i in idxFirstZero+1..<idxNextZero {
                newData[i-idxFirstZero-1] = data[i]
            }
            return newData
        }
        
        // encrypt
        func encryptWithRSAKey(_ data: Data, padding: SecPadding = .PKCS1, rsaKeyRef: SecKey? = nil) -> Data? {
            let rsaKeyRef = rsaKeyRef ?? self.publicKey!
            let blockSize = SecKeyGetBlockSize(rsaKeyRef)
            let dataSize = data.count / MemoryLayout<UInt8>.size
            let maxChunkSize = padding==SecPadding.OAEP ? (blockSize - 42) : (blockSize - 11)
            
            var dataAsArray = [UInt8](repeating: 0, count: dataSize)
            (data as NSData).getBytes(&dataAsArray, length: dataSize)
            
            var encryptedData = [UInt8](repeating: 0, count: 0)
            var idx = 0
            while (idx < dataAsArray.count ) {
                var idxEnd = idx + maxChunkSize
                if ( idxEnd > dataAsArray.count ) {
                    idxEnd = dataAsArray.count
                }
                var chunkData = [UInt8](repeating: 0, count: maxChunkSize)
                for i in idx..<idxEnd {
                    chunkData[i-idx] = dataAsArray[i]
                }
                
                var encryptedDataBuffer = [UInt8](repeating: 0, count: blockSize)
                var encryptedDataLength = blockSize
                
                let status = SecKeyEncrypt(rsaKeyRef, padding, chunkData, idxEnd-idx, &encryptedDataBuffer, &encryptedDataLength)
                if ( status != noErr ) {
                    NSLog("Error while encrypting: %i", status)
                    return nil
                }
                encryptedData += encryptedDataBuffer
                
                idx += maxChunkSize
            }
            
            return Data(bytes: UnsafePointer<UInt8>(encryptedData), count: encryptedData.count)
        }
        
    }

save this message to file:


    

        let message = "This is my message. asdfl;jas f;lkajsdf la;skfj asd;lkfj sa;dlkfjsad ;lkfj dsal;kfj daslk;fjds flkjas dfjkdfgjkhdfs gjklsdf lkgjhdfs klgj dfskljg fdslkjg dsfjklg dfskjlg dfskljg fdskljg fdskjlgn dfsjlknv sflkdjnv ldksfjnv dfsjnvdkfjsghlfsjkdgh fdskljgh dsfkljgh dfslkjghdljkfs sdfkljsadf dsaf;lkasdjf sad;lfjk as;ldkfjas d;flkjasd flk;asdf lkjha sdflhjka sdklgha fkljgh fsdkljg alkjfh aslkjdf asldkjfh asdljkfasdlkjfhas ldfh ash aslkj asdlkj aslkjchads lkjchadslkfjhsadlkfjhsad flkjasdh flkjashdf lkjadhsf lkjasdhf lkjashdf lkjasdhf lkadsjfhadslkfjhiuwlhoewiqufhopweif asjkbdsa kjfasdlkfja sdljkfhs alkjfh adsjkfhas ldfkjhas ldkfjhajlsfh alsjdfhadlsfhlasjdkfjhsad fljkls "
        
            let encryptData: Data? = self.crypt.encryptWithRSAKey(message.data(using: .utf8)!)
            
            let fileName = "file.enc"
            let dir = try? FileManager.default.url(for: .documentDirectory,
                                                   in: .userDomainMask, appropriateFor: nil, create: false)
    if let fileURL = dir?.appendingPathComponent(fileName).appendingPathExtension("dgk") {
                
                // Write to the file Test
                do {
                    //                try encry.write(to: fileURL, atomically: true, encoding: .utf8)
                    try encryptData?.write(to: fileURL)
                } catch {
                    print("Failed writing to URL: \(fileURL), Error: " + error.localizedDescription)
                }
                
            }

if I decrypt file at this time decrypt is success. but when I close the program and open it and decrypt file, decrypt method has been failed.

    if let fileURL = dir?.appendingPathComponent(fileName).appendingPathExtension("dgk") {
                var encryptDataFromFile: Data?
                do {
                    encryptDataFromFile = try Data(contentsOf: fileURL)
                    if let decryptData: Data = self.crypt.decryptWithRSAKey(encryptDataFromFile!){
                        let decryptString: String = String(data: decryptData, encoding: .utf8)!
                        print(decryptString)
                    }
                    exit(0)
                } catch {
                    print("Failed reading from URL: \(fileURL), Error: " + error.localizedDescription)
                }
            }