Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5747e62549 | |||
| d1b0bfe2a7 | |||
| 36e337b163 | |||
| ef3625cfd1 | |||
| e6ccf4371f | |||
| 0c84995793 | |||
| 53b0ff8665 | |||
| 6c786edae8 | |||
| 7acd623e0e | |||
| 87c222daa3 | |||
| 7547213dfc | |||
| 5404afa248 | |||
| e20fb9d9f9 |
@@ -1,8 +1,32 @@
|
||||
The `windowBits` parameter is the base two logarithm of the window size
|
||||
(the size of the history buffer). It should be in the range 8..15 for this
|
||||
version of the library. Larger values of this parameter result in better
|
||||
compression at the expense of memory usage.
|
||||
# GzipOutputStream
|
||||
Compress the data and write to a file
|
||||
```swift
|
||||
...
|
||||
let compressStream = GzipOutputStream(writingTo: fileOutputStream)
|
||||
try compressStream.open()
|
||||
try compressStream.write("Hello world", ofEncoding: .utf8)
|
||||
try! compressStream.close()
|
||||
...
|
||||
```
|
||||
|
||||
# GzipInputStream
|
||||
Decompress the data
|
||||
```swift
|
||||
...
|
||||
let decompressStream = GzipInputStream(readingFrom: fileInputStream)
|
||||
try decompressStream.open()
|
||||
|
||||
var result = Array<UInt8>()
|
||||
let tmpBufLen = 1<<16
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufLen)
|
||||
while decompressStream.hasBytesAvailable {
|
||||
let readLen = try decompressStream.read(&tmpBuffer, maxLength: tmpBufLen)
|
||||
result.append(contentsOf: tmpBuffer.prefix(readLen))
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
# Configuration parameters
|
||||
`windowBits` is used to control the compression level and the format of the
|
||||
compressed data. According to the zlib manual, the windowBits parameter can
|
||||
have the following values:
|
||||
@@ -1,10 +1,185 @@
|
||||
# StreamKit
|
||||
This open-source Swift library offers a comprehensive collection of cryptographic algorithms. These ciphers can be structured into chains, facilitating the seamless flow of output from one cipher stream to another. This architecture enables concurrent tasks, such as encrypting data while writing the encrypted result to a file. Integrate "StreamKit" into your projects to efficiently utilize these cryptographic functionalities.
|
||||
|
||||
# The available streams
|
||||
- [FileStream](FileStream.md)
|
||||
- [GzipStream](GzipStream.md)
|
||||
- [AesStream](AesStream.md)
|
||||
- [Salsa20Stream](Salsa20Stream.md)
|
||||
- [ChaCha20Stream](ChaCha20Stream.md)
|
||||
- [TwoFishStream](TwoFishStream.md)
|
||||
|
||||
# How to add the library to a project
|
||||
In the Xcode press `File` -> `Add Packages` -> In the search field insert `https://github.com/iharkatkavets/StreamKit.git`.
|
||||
It might require to setup `GitHub Account` in the Xcode
|
||||
|
||||
# How to use the library in the project
|
||||
First import the library
|
||||
```swift
|
||||
import StreamKit
|
||||
```
|
||||
|
||||
## How to read a file using `FileInputStream`
|
||||
```swift
|
||||
let fileURL: URL = ...
|
||||
guard let fileInputStream = FileInputStream(with: fileURL) else {
|
||||
return
|
||||
}
|
||||
try fileInputStream.open()
|
||||
|
||||
let fileContent: Data = try fileInputStream.readToEnd()
|
||||
|
||||
// or read chunk by chunk
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while fileInputStream.hasBytesAvailable {
|
||||
let readLen = fileInputStream.read(&tmpBuffer, maxLength: tmpBufferLen)
|
||||
// process tmpBuffer
|
||||
}
|
||||
|
||||
inputFileStream.close()
|
||||
```
|
||||
|
||||
## How to write to a file using `FileOutputStream`
|
||||
```swift
|
||||
let fileURL: URL = ...
|
||||
guard let fileOutputStream = FileOutputStream(with: fileURL) else {
|
||||
return
|
||||
}
|
||||
try fileOutputStream.open()
|
||||
|
||||
// write string to a file
|
||||
try fileOutputStream.write("Hello world", ofEncoding: .utf8)
|
||||
|
||||
// or write data to a file
|
||||
try fileOutputStream.write(Data([0,1,2,3]))
|
||||
|
||||
// or write some buffer to a file
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
try compressingStream.write(tmpBuffer, length: readLen)
|
||||
|
||||
try fileOutputStream.close()
|
||||
```
|
||||
|
||||
## How to perform encrypting using `AesOutputStream`
|
||||
```swift
|
||||
...
|
||||
let encryptingStream = AesOutputStream(writingTo: fileOutputStream,
|
||||
key: key,
|
||||
iv: iv)
|
||||
try encryptingStream.open()
|
||||
|
||||
try encryptingStream.write("Hello world", ofEncoding: .utf8)
|
||||
try encryptingStream.close()
|
||||
...
|
||||
```
|
||||
|
||||
## How to perform decrypting using `AesInputStream`
|
||||
```swift
|
||||
...
|
||||
let decryptingStream = AesInputStream(readingFrom: inputFileStream,
|
||||
key: key,
|
||||
iv: iv)
|
||||
try decryptingStream.open()
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while decryptingStream.hasBytesAvailable {
|
||||
let readLen = try decryptingStream.read(&tmpBuffer, maxLength: tmpBufferLen)
|
||||
// process buffer
|
||||
}
|
||||
|
||||
decryptingStream.close()
|
||||
...
|
||||
```
|
||||
|
||||
## How to perform encrypting using `Salsa20OutputStream`
|
||||
```swift
|
||||
...
|
||||
let encryptingStream = Salsa20OutputStream(writingTo: fileOutputStream,
|
||||
key: key,
|
||||
iv: iv)
|
||||
try encryptingStream.open()
|
||||
|
||||
try encryptingStream.write("Hello world", ofEncoding: .utf8)
|
||||
try encryptingStream.close()
|
||||
...
|
||||
```
|
||||
|
||||
## How to perform decrypting using `Salsa20InputStream`
|
||||
```swift
|
||||
...
|
||||
let decryptingStream = Salsa20InputStream(readingFrom: inputFileStream,
|
||||
key: key,
|
||||
iv: iv)
|
||||
try decryptingStream.open()
|
||||
|
||||
let decryptedData = try decryptingStream.readToEnd()
|
||||
|
||||
decryptingStream.close()
|
||||
...
|
||||
```
|
||||
|
||||
## How to perform encrypting using `ChaCha20OutputStream`
|
||||
```swift
|
||||
...
|
||||
let encryptingStream = ChaCha20OutputStream(writingTo: fileOutputStream,
|
||||
key: key,
|
||||
iv: iv)
|
||||
try encryptingStream.open()
|
||||
|
||||
try encryptingStream.write("Hello world", ofEncoding: .utf8)
|
||||
try encryptingStream.close()
|
||||
...
|
||||
```
|
||||
|
||||
## How to perform decrypting using `ChaCha20InputStream`
|
||||
```swift
|
||||
...
|
||||
let decryptingStream = ChaCha20InputStream(readingFrom: inputFileStream,
|
||||
key: key,
|
||||
iv: iv)
|
||||
try decryptingStream.open()
|
||||
|
||||
let decryptedData = try decryptingStream.readToEnd()
|
||||
|
||||
decryptingStream.close()
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
## How to perform encrypting using `TwoFishOutputStream`
|
||||
```swift
|
||||
...
|
||||
let encryptingStream = TwoFishOutputStream(writingTo: fileOutputStream,
|
||||
key: key,
|
||||
iv: iv)
|
||||
try encryptingStream.open()
|
||||
|
||||
try encryptingStream.write("Hello world", ofEncoding: .utf8)
|
||||
try encryptingStream.close()
|
||||
...
|
||||
```
|
||||
|
||||
## How to perform decrypting using `TwoFishInputStream`
|
||||
```swift
|
||||
...
|
||||
let decryptingStream = TwoFishInputStream(readingFrom: inputFileStream,
|
||||
key: key,
|
||||
iv: iv)
|
||||
try decryptingStream.open()
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while decryptingStream.hasBytesAvailable {
|
||||
let readLen = try decompressingStream.read(&tmpBuffer, maxLength: tmpBufferLen)
|
||||
// process or store bytes in `tmpBuffer`
|
||||
}
|
||||
|
||||
decryptingStream.close()
|
||||
...
|
||||
```
|
||||
|
||||
# How to use it
|
||||
For example it's possible to encrypt some data and simulteniously write the encrypted result to a file.
|
||||
@@ -56,5 +231,5 @@ inputFileStream.close()
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Sponsored by [KeePassium](https://github.com/keepassium)
|
||||
# Sponsorship
|
||||
### The library was developed in collaboration with [KeePassium](https://github.com/keepassium)
|
||||
|
||||
@@ -41,7 +41,6 @@ public final class AesInputStream: InputStream {
|
||||
private var decryptedBufferAvailableLen: Int
|
||||
private var status: Int32 = 0
|
||||
private let options: AesOptions
|
||||
private let blockSize = 16
|
||||
|
||||
public init(readingFrom nestedStream: InputStream,
|
||||
key: [UInt8],
|
||||
@@ -72,7 +71,7 @@ public final class AesInputStream: InputStream {
|
||||
guard !isOpen else { fatalError("The stream can be opened only once") }
|
||||
isOpen = true
|
||||
|
||||
guard iv.count == blockSize else {
|
||||
guard iv.count == AesIVSize else {
|
||||
throw AesStreamError(kind: .ivSizeError)
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ public final class AesOutputStream: OutputStream {
|
||||
private var isOpen = false
|
||||
private var status: Int32 = 0
|
||||
private let options: AesOptions
|
||||
private let blockSize = 16
|
||||
|
||||
public init(writingTo outputStream: OutputStream,
|
||||
key: [UInt8],
|
||||
@@ -66,7 +65,7 @@ public final class AesOutputStream: OutputStream {
|
||||
guard !isOpen else { fatalError("The stream can be opened only once") }
|
||||
isOpen = true
|
||||
|
||||
guard iv.count == blockSize else {
|
||||
guard iv.count == AesIVSize else {
|
||||
throw AesStreamError(kind: .ivSizeError)
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
import Foundation
|
||||
import CommonCrypto
|
||||
|
||||
public let AesIVSize = 16
|
||||
|
||||
public typealias AesOptions = Int
|
||||
public extension AesOptions {
|
||||
static let CBCMode = 0
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
let ChaCha20IVSize = 12
|
||||
let ChaCha20KeySize = 32
|
||||
public let ChaCha20KeySize = 32
|
||||
public let ChaCha20IVSize = 12
|
||||
|
||||
public struct ChaCha20StreamError: LocalizedError {
|
||||
public enum Kind {
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
let Salsa20IVSize = 8
|
||||
let Salsa20KeySize128 = 16
|
||||
let Salsa20KeySize256 = 32
|
||||
public let Salsa20KeySize128 = 16
|
||||
public let Salsa20KeySize256 = 32
|
||||
public let Salsa20IVSize = 8
|
||||
|
||||
public struct Salsa20StreamError: LocalizedError {
|
||||
public enum Kind {
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
let TwoFishIVSize = 16
|
||||
public let TwoFishIVSize = 16
|
||||
|
||||
public struct TwoFishStreamError: LocalizedError {
|
||||
public enum Kind {
|
||||
|
||||
@@ -108,11 +108,11 @@ extension GzipStreamTests {
|
||||
try decompressStream.open()
|
||||
|
||||
var result = Array<UInt8>()
|
||||
let bufLen = 1<<16
|
||||
var readBuffer = Array<UInt8>(repeating: 0, count: bufLen)
|
||||
let tmpBufLen = 1<<16
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufLen)
|
||||
while decompressStream.hasBytesAvailable {
|
||||
let readLen = try decompressStream.read(&readBuffer, maxLength: bufLen)
|
||||
result.append(contentsOf: readBuffer.prefix(readLen))
|
||||
let readLen = try decompressStream.read(&tmpBuffer, maxLength: tmpBufLen)
|
||||
result.append(contentsOf: tmpBuffer.prefix(readLen))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ final class StreamKitTests: XCTestCase {
|
||||
|
||||
func testEncryptingDecrypting1MBFileUsingSalsa20Streams() throws {
|
||||
let key = genBufferOfLen(32)
|
||||
let iv = genBufferOfLen(8)
|
||||
let iv = genBufferOfLen(Salsa20IVSize)
|
||||
|
||||
let originalFileURL = fileURL("1MB")!
|
||||
let encryptedFileURL = try encryptFileUsingSalsa20(originalFileURL, key, iv)
|
||||
@@ -53,7 +53,7 @@ final class StreamKitTests: XCTestCase {
|
||||
|
||||
func testCompressEncryptDecryptDecompress1MBFileUsingSalsa20Stream() throws {
|
||||
let key = genBufferOfLen(32)
|
||||
let iv = genBufferOfLen(8)
|
||||
let iv = genBufferOfLen(Salsa20IVSize)
|
||||
|
||||
let originalFileURL = fileURL("1MB")!
|
||||
let encryptedFileURL = try compressAndEncryptFileUsingSalsa20(originalFileURL, key, iv)
|
||||
@@ -63,9 +63,21 @@ final class StreamKitTests: XCTestCase {
|
||||
XCTAssertEqual(md5(originalFileURL), md5(decryptedFileURL))
|
||||
}
|
||||
|
||||
func testCompressEncryptDecryptDecompressPlainTextFileUsingSalsa20Stream() throws {
|
||||
let key = genBufferOfLen(32)
|
||||
let iv = genBufferOfLen(Salsa20IVSize)
|
||||
|
||||
let originalFileURL = fileURL("PlainText")!
|
||||
let encryptedFileURL = try compressAndEncryptFileUsingSalsa20(originalFileURL, key, iv)
|
||||
let decryptedFileURL = try decryptAndDecompressFileUsingSalsa20(encryptedFileURL, key, iv)
|
||||
|
||||
XCTAssertNotEqual(md5(originalFileURL), md5(encryptedFileURL))
|
||||
XCTAssertEqual(md5(originalFileURL), md5(decryptedFileURL))
|
||||
}
|
||||
|
||||
func testEncryptingDecrypting1MBFileUsingChaCha20Streams() throws {
|
||||
let key = genBufferOfLen(32)
|
||||
let iv = genBufferOfLen(12)
|
||||
let iv = genBufferOfLen(ChaCha20IVSize)
|
||||
|
||||
let originalFileURL = fileURL("1MB")!
|
||||
let encryptedFileURL = try encryptFileUsingChaCha20(originalFileURL, key, iv)
|
||||
@@ -77,7 +89,7 @@ final class StreamKitTests: XCTestCase {
|
||||
|
||||
func testCompressEncryptDecryptDecompress1MBFileUsingChaCha20Stream() throws {
|
||||
let key = genBufferOfLen(32)
|
||||
let iv = genBufferOfLen(12)
|
||||
let iv = genBufferOfLen(ChaCha20IVSize)
|
||||
|
||||
let originalFileURL = fileURL("1MB")!
|
||||
let encryptedFileURL = try compressAndEncryptFileUsingChaCha20(originalFileURL, key, iv)
|
||||
@@ -89,7 +101,7 @@ final class StreamKitTests: XCTestCase {
|
||||
|
||||
func testEncryptingDecrypting1MBFileUsingAesStream() throws {
|
||||
let key = genBufferOfLen(32)
|
||||
let iv = genBufferOfLen(16)
|
||||
let iv = genBufferOfLen(AesIVSize)
|
||||
|
||||
let originalFileURL = fileURL("1MB")!
|
||||
let encryptedFileURL = try encryptFileUsingAes(originalFileURL, key, iv)
|
||||
@@ -101,7 +113,7 @@ final class StreamKitTests: XCTestCase {
|
||||
|
||||
func testCompressEncryptDecryptDecompress1MBFileUsingAesStream() throws {
|
||||
let key = genBufferOfLen(32)
|
||||
let iv = genBufferOfLen(16)
|
||||
let iv = genBufferOfLen(AesIVSize)
|
||||
|
||||
let originalFileURL = fileURL("1MB")!
|
||||
let encryptedFileURL = try compressAndEncryptFileUsingAes(originalFileURL, key, iv)
|
||||
@@ -128,6 +140,31 @@ final class StreamKitTests: XCTestCase {
|
||||
XCTAssertNotEqual(md5(originalFileURL), md5(compressedFileURL))
|
||||
XCTAssertEqual(md5(originalFileURL), md5(decompressedFileURL))
|
||||
}
|
||||
|
||||
func testEncryptingDecrypting1MBFileUsingTwoFishStreams() throws {
|
||||
let key = genBufferOfLen(32)
|
||||
let iv = genBufferOfLen(TwoFishIVSize)
|
||||
|
||||
let originalFileURL = fileURL("1MB")!
|
||||
let encryptedFileURL = try encryptFileUsingTwoFish(originalFileURL, key, iv)
|
||||
let decryptedFileURL = try decryptFileUsingTwoFish(encryptedFileURL, key, iv)
|
||||
|
||||
XCTAssertNotEqual(md5(originalFileURL), md5(encryptedFileURL))
|
||||
XCTAssertEqual(md5(originalFileURL), md5(decryptedFileURL))
|
||||
}
|
||||
|
||||
func testCompressEncryptDecryptDecompress1MBFileUsingTwoFishStream() throws {
|
||||
let key = genBufferOfLen(32)
|
||||
let iv = genBufferOfLen(TwoFishIVSize)
|
||||
|
||||
let originalFileURL = fileURL("1MB")!
|
||||
let encryptedFileURL = try compressAndEncryptFileUsingTwoFish(originalFileURL, key, iv)
|
||||
let decryptedFileURL = try decryptAndDecompressFileUsingTwoFish(encryptedFileURL, key, iv)
|
||||
|
||||
XCTAssertNotEqual(md5(originalFileURL), md5(encryptedFileURL))
|
||||
XCTAssertEqual(md5(originalFileURL), md5(decryptedFileURL))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension StreamKitTests {
|
||||
@@ -143,7 +180,7 @@ extension StreamKitTests {
|
||||
key: key,
|
||||
iv: iv)
|
||||
try encryptingStream.open()
|
||||
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while inputFileStream.hasBytesAvailable {
|
||||
@@ -176,7 +213,7 @@ extension StreamKitTests {
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while decryptingStream.hasBytesAvailable {
|
||||
while decompressingStream.hasBytesAvailable {
|
||||
let readLen = try decompressingStream.read(&tmpBuffer, maxLength: tmpBufferLen)
|
||||
try outputFileStream.write(tmpBuffer, length: readLen)
|
||||
}
|
||||
@@ -204,7 +241,7 @@ extension StreamKitTests {
|
||||
|
||||
let compressingStream = GzipOutputStream(writingTo: encryptingStream)
|
||||
try compressingStream.open()
|
||||
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while inputFileStream.hasBytesAvailable {
|
||||
@@ -258,7 +295,7 @@ extension StreamKitTests {
|
||||
key: key,
|
||||
iv: iv)
|
||||
try encryptingStream.open()
|
||||
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while inputFileStream.hasBytesAvailable {
|
||||
@@ -315,7 +352,7 @@ extension StreamKitTests {
|
||||
|
||||
let compressingStream = GzipOutputStream(writingTo: encryptingStream)
|
||||
try compressingStream.open()
|
||||
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while inputFileStream.hasBytesAvailable {
|
||||
@@ -373,7 +410,7 @@ extension StreamKitTests {
|
||||
key: key,
|
||||
iv: iv)
|
||||
try encryptingStream.open()
|
||||
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while inputFileStream.hasBytesAvailable {
|
||||
@@ -404,7 +441,7 @@ extension StreamKitTests {
|
||||
|
||||
let compressingStream = GzipOutputStream(writingTo: encryptingStream)
|
||||
try compressingStream.open()
|
||||
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while inputFileStream.hasBytesAvailable {
|
||||
@@ -485,7 +522,7 @@ extension StreamKitTests {
|
||||
|
||||
let compressingStream = GzipOutputStream(writingTo: outputFileStream)
|
||||
try compressingStream.open()
|
||||
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while inputFileStream.hasBytesAvailable {
|
||||
@@ -523,4 +560,120 @@ extension StreamKitTests {
|
||||
inputFileStream.close()
|
||||
return decompressedFileURL
|
||||
}
|
||||
|
||||
func encryptFileUsingTwoFish(_ originalFileURL: URL, _ key: [UInt8], _ iv: [UInt8]) throws -> URL {
|
||||
let inputFileStream = FileInputStream(with: try! FileHandle(forReadingFrom: originalFileURL))
|
||||
try inputFileStream.open()
|
||||
|
||||
let encryptedFileURL = createTmpFileURL(Self.tmpDir)
|
||||
let outputFileStream = FileOutputStream(with: try! FileHandle(forWritingTo: encryptedFileURL))
|
||||
try outputFileStream.open()
|
||||
|
||||
let encryptingStream = TwoFishOutputStream(writingTo: outputFileStream,
|
||||
key: key,
|
||||
iv: iv)
|
||||
try encryptingStream.open()
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while inputFileStream.hasBytesAvailable {
|
||||
let readLen = inputFileStream.read(&tmpBuffer, maxLength: tmpBufferLen)
|
||||
try encryptingStream.write(tmpBuffer, length: readLen)
|
||||
}
|
||||
|
||||
try encryptingStream.close()
|
||||
try outputFileStream.close()
|
||||
inputFileStream.close()
|
||||
|
||||
return encryptedFileURL
|
||||
}
|
||||
|
||||
func decryptFileUsingTwoFish(_ encryptedFileURL: URL, _ key: [UInt8], _ iv: [UInt8]) throws -> URL {
|
||||
let inputFileStream = FileInputStream(with: try! FileHandle(forReadingFrom: encryptedFileURL))
|
||||
try inputFileStream.open()
|
||||
|
||||
let decryptedFileURL = createTmpFileURL(Self.tmpDir)
|
||||
let outputFileStream = FileOutputStream(with: try! FileHandle(forWritingTo: decryptedFileURL))
|
||||
try outputFileStream.open()
|
||||
|
||||
let decryptingStream = TwoFishInputStream(readingFrom: inputFileStream,
|
||||
key: key,
|
||||
iv: iv)
|
||||
try decryptingStream.open()
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while decryptingStream.hasBytesAvailable {
|
||||
let readLen = try decryptingStream.read(&tmpBuffer, maxLength: tmpBufferLen)
|
||||
try outputFileStream.write(tmpBuffer, length: readLen)
|
||||
}
|
||||
|
||||
decryptingStream.close()
|
||||
try outputFileStream.close()
|
||||
inputFileStream.close()
|
||||
return decryptedFileURL
|
||||
}
|
||||
|
||||
func compressAndEncryptFileUsingTwoFish(_ originalFileURL: URL, _ key: [UInt8], _ iv: [UInt8]) throws -> URL {
|
||||
let inputFileStream = FileInputStream(with: try! FileHandle(forReadingFrom: originalFileURL))
|
||||
try inputFileStream.open()
|
||||
inputFileStream.close()
|
||||
|
||||
let encryptedFileURL = createTmpFileURL(Self.tmpDir)
|
||||
let outputFileStream = FileOutputStream(with: try! FileHandle(forWritingTo: encryptedFileURL))
|
||||
try outputFileStream.open()
|
||||
|
||||
let encryptingStream = TwoFishOutputStream(writingTo: outputFileStream,
|
||||
key: key,
|
||||
iv: iv)
|
||||
try encryptingStream.open()
|
||||
|
||||
let compressingStream = GzipOutputStream(writingTo: encryptingStream)
|
||||
try compressingStream.open()
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while inputFileStream.hasBytesAvailable {
|
||||
let readLen = inputFileStream.read(&tmpBuffer, maxLength: tmpBufferLen)
|
||||
try compressingStream.write(tmpBuffer, length: readLen)
|
||||
}
|
||||
|
||||
try compressingStream.close()
|
||||
try encryptingStream.close()
|
||||
try outputFileStream.close()
|
||||
inputFileStream.close()
|
||||
|
||||
return encryptedFileURL
|
||||
}
|
||||
|
||||
func decryptAndDecompressFileUsingTwoFish(_ encryptedFileURL: URL, _ key: [UInt8], _ iv: [UInt8]) throws -> URL {
|
||||
let inputFileStream = FileInputStream(with: try! FileHandle(forReadingFrom: encryptedFileURL))
|
||||
try inputFileStream.open()
|
||||
|
||||
let decryptedFileURL = createTmpFileURL(Self.tmpDir)
|
||||
let outputFileStream = FileOutputStream(with: try! FileHandle(forWritingTo: decryptedFileURL))
|
||||
try outputFileStream.open()
|
||||
|
||||
let decryptingStream = TwoFishInputStream(readingFrom: inputFileStream,
|
||||
key: key,
|
||||
iv: iv)
|
||||
try decryptingStream.open()
|
||||
|
||||
let decompressingStream = GzipInputStream(readingFrom: decryptingStream)
|
||||
try decompressingStream.open()
|
||||
|
||||
let tmpBufferLen = 1<<16 // 65KB buffer
|
||||
var tmpBuffer = Array<UInt8>(repeating: 0, count: tmpBufferLen)
|
||||
while decryptingStream.hasBytesAvailable {
|
||||
let readLen = try decompressingStream.read(&tmpBuffer, maxLength: tmpBufferLen)
|
||||
try outputFileStream.write(tmpBuffer, length: readLen)
|
||||
}
|
||||
|
||||
decompressingStream.close()
|
||||
decryptingStream.close()
|
||||
try outputFileStream.close()
|
||||
inputFileStream.close()
|
||||
return decryptedFileURL
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user