@@ -104,15 +104,17 @@ assert(hmacs5! == expectedRFC2202)
104104## Using ` Cryptor `
105105
106106``` swift
107+ let algorithm = Cryptor.Algorithm .aes
108+ var iv = try ! Random.generateBytes (byteCount : algorithm.blockSize ())
107109var key = arrayFrom (hexString : " 2b7e151628aed2a6abf7158809cf4f3c" )
108110var plainText = " The quick brown fox jumps over the lazy dog. The fox has more or less had it at this point."
109111
110- var cryptor = Cryptor (operation :.encrypt , algorithm :. aes , options :.PKCS7Padding , key :key, iv :Array < UInt8 > () )
112+ var cryptor = Cryptor (operation :.encrypt , algorithm :algorithm , options :.PKCS7Padding , key :key, iv :iv )
111113var cipherText = cryptor.update (plainText)? .final ()
112114
113- cryptor = Cryptor (operation :.decrypt , algorithm :. aes , options :.PKCS7Padding , key :key, iv :Array < UInt8 > () )
115+ cryptor = Cryptor (operation :.decrypt , algorithm :algorithm , options :.PKCS7Padding , key :key, iv :iv )
114116var decryptedPlainText = cryptor.update (cipherText! )? .final ()
115- var decryptedString = decryptedPlainText! . reduce ( " " ) { $0 + String ( UnicodeScalar ( $1 )) }
117+ var decryptedString = String ( bytes : decryptedPlainText! , encoding : . utf8 )
116118decryptedString
117119assert (decryptedString == plainText)
118120```
@@ -131,57 +133,105 @@ To encrypt a large file or a network stream use `StreamCryptor`. The `StreamCryp
131133
132134The example below shows how to use ` StreamCryptor ` to encrypt and decrypt an image file.
133135``` swift
134- func crypt (sc : StreamCryptor, inputStream : NSInputStream , outputStream : NSOutputStream , bufferSize : Int )
136+ func crypt (sc : StreamCryptor, inputStream : InputStream , outputStream : OutputStream , bufferSize : Int ) -> (bytesRead: Int , bytesWritten : Int )
135137{
136- var inputBuffer = Array < UInt8 > (count :1024 , repeatedValue :0 )
137- var outputBuffer = Array < UInt8 > (count :1024 , repeatedValue :0 )
138- inputStream.open ()
139- outputStream.open ()
138+ var inputBuffer = Array < UInt8 > (repeating :0 , count :1024 )
139+ var outputBuffer = Array < UInt8 > (repeating :0 , count :1024 )
140140
141- var cryptedBytes : UInt = 0
141+
142+ var cryptedBytes : Int = 0
143+ var totalBytesWritten = 0
144+ var totalBytesRead = 0
142145 while inputStream.hasBytesAvailable
143146 {
144147 let bytesRead = inputStream.read (& inputBuffer, maxLength : inputBuffer.count )
145- let status = sc.update (inputBuffer, byteCountIn : UInt (bytesRead), bufferOut : & outputBuffer, byteCapacityOut : UInt (outputBuffer.count ), byteCountOut : & cryptedBytes)
146- assert (status == Status.Success )
148+ totalBytesRead += bytesRead
149+ let status = sc.update (bufferIn : inputBuffer, byteCountIn : bytesRead, bufferOut : & outputBuffer, byteCapacityOut : outputBuffer.count , byteCountOut : & cryptedBytes)
150+ assert (status == Status.success )
147151 if (cryptedBytes > 0 )
148152 {
149153 let bytesWritten = outputStream.write (outputBuffer, maxLength : Int (cryptedBytes))
150154 assert (bytesWritten == Int (cryptedBytes))
155+ totalBytesWritten += bytesWritten
151156 }
152157 }
153- let status = sc.final (& outputBuffer, byteCapacityOut : UInt ( outputBuffer.count ) , byteCountOut : & cryptedBytes)
154- assert (status == Status.Success )
158+ let status = sc.final (bufferOut : & outputBuffer, byteCapacityOut : outputBuffer.count , byteCountOut : & cryptedBytes)
159+ assert (status == Status.success )
155160 if (cryptedBytes > 0 )
156161 {
157162 let bytesWritten = outputStream.write (outputBuffer, maxLength : Int (cryptedBytes))
158163 assert (bytesWritten == Int (cryptedBytes))
164+ totalBytesWritten += bytesWritten
159165 }
160- inputStream.close ()
161- outputStream.close ()
166+ return (totalBytesRead, totalBytesWritten)
162167}
163168
164- let imagePath = NSBundle.mainBundle ().pathForResource (" Riscal" , ofType :" jpg" )!
165- let tmp = NSTemporaryDirectory ()
166- let encryptedFilePath = tmp.stringByAppendingPathComponent (" Riscal.xjpgx" )
167- var decryptedFilePath = tmp.stringByAppendingPathComponent (" RiscalDecrypted.jpg" )
169+ let imagePath = Bundle.main .path (forResource : " Riscal" , ofType :" jpg" )!
170+ let tmp = NSTemporaryDirectory () as NSString
171+ let encryptedFilePath = " \( tmp ) /Riscal.xjpgx"
172+ var decryptedFilePath = " \( tmp ) /RiscalDecrypted.jpg"
173+
174+ // Prepare the input and output streams for the encryption operation
175+ guard let imageInputStream = InputStream (fileAtPath : imagePath) else {
176+ fatalError (" Failed to initialize the image input stream." )
177+ }
178+ imageInputStream.open ()
179+ guard let encryptedFileOutputStream = OutputStream (toFileAtPath : encryptedFilePath, append :false ) else
180+ {
181+ fatalError (" Failed to open output stream." )
182+ }
183+ encryptedFileOutputStream.open ()
168184
169- var imageInputStream = NSInputStream (fileAtPath : imagePath)
170- var encryptedFileOutputStream = NSOutputStream (toFileAtPath : encryptedFilePath, append :false )
171- var encryptedFileInputStream = NSInputStream (fileAtPath : encryptedFilePath)
172- var decryptedFileOutputStream = NSOutputStream (toFileAtPath : decryptedFilePath, append :false )
185+ // Generate a new, random initialization vector
186+ let initializationVector = try ! Random.generateBytes (byteCount : algorithm.blockSize ())
173187
174- var sc = StreamCryptor (operation :.encrypt , algorithm :.aes , options :.PKCS7Padding , key :key, iv :Array < UInt8 > ())
175- crypt (sc, imageInputStream, encryptedFileOutputStream, 1024 )
188+ // A common way to communicate the initialization vector is to write it at the beginning of the encrypted data.
189+ let bytesWritten = encryptedFileOutputStream.write (initializationVector, maxLength : initializationVector.count )
190+
191+ // Now write the encrypted data
192+ var sc = StreamCryptor (operation :.encrypt , algorithm :algorithm, options :.PKCS7Padding , key :key, iv :initializationVector)
193+ guard bytesWritten == initializationVector.count else
194+ {
195+ fatalError (" Failed to write initialization vector to encrypted output file." )
196+ }
197+ let outputResult = crypt (sc : sc, inputStream : imageInputStream, outputStream : encryptedFileOutputStream, bufferSize : 1024 )
198+ encryptedFileOutputStream.close ()
199+ outputResult
176200
177201// Uncomment this line to verify that the file is encrypted
178- // var encryptedImage = UIImage(contentsOfFile:encryptedFile)
202+ // var encryptedImage = NSImage(contentsOfFile:encryptedFile)
203+
204+ // Prepare the input and output streams for the decryption operation
205+ guard let encryptedFileInputStream = InputStream (fileAtPath : encryptedFilePath) else
206+ {
207+ fatalError (" Failed to open the encrypted file for input." )
208+ }
209+ encryptedFileInputStream.open ()
210+ guard let decryptedFileOutputStream = OutputStream (toFileAtPath : decryptedFilePath, append :false ) else {
211+ fatalError (" Failed to open the file for the decrypted output file." )
212+ }
213+ decryptedFileOutputStream.open ()
214+
215+ // Read back the initialization vector.
216+ var readbackInitializationVector = Array < UInt8 > (repeating : 0 , count : algorithm.blockSize ())
217+ let bytesRead = encryptedFileInputStream.read (& readbackInitializationVector, maxLength : readbackInitializationVector.count )
218+
219+ // Uncomment this to verify that we did indeed read back the initialization vector.
220+ // assert(readbackInitializationVector == initializationVector)
221+
222+ // Now use the read back initialization vector (along with the key) to
223+ sc = StreamCryptor (operation :.decrypt , algorithm :algorithm, options :.PKCS7Padding , key :key, iv :readbackInitializationVector)
224+ let inputResult = crypt (sc : sc, inputStream : encryptedFileInputStream, outputStream : decryptedFileOutputStream, bufferSize : 1024 )
225+
226+ // Uncomment this to verify that decrypt operation consumed all the encrypted data
227+ // and produced the correct output of plaintext output.
228+ // assert(inputResult.bytesRead == outputResult.bytesWritten && inputResult.bytesWritten == outputResult.bytesRead)
229+
230+ var image = NSImage (named :" Riscal.jpg" )
231+ var decryptedImage = NSImage (contentsOfFile :decryptedFilePath)
232+ decryptedImage
179233
180- sc = StreamCryptor (operation :.decrypt , algorithm :.aes , options :.PKCS7Padding , key :key, iv :Array < UInt8 > ())
181- crypt (sc, encryptedFileInputStream, decryptedFileOutputStream, 1024 )
182234
183- var image = UIImage (named :" Riscal.jpg" )
184- var decryptedImage = UIImage (contentsOfFile :decryptedFilePath)
185235```
186236
187237## Using ` PBKDF `
0 commit comments