Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CryptorModule #144

Merged
merged 16 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Examples/Sources/ConfigDetailTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class ConfigDetailTableViewController: UITableViewController {
case .subscribeKey:
return config.subscribeKey
case .cipherKey:
return config.cipherKey?.key.description ?? "Key Not Found"
return config.cryptorModule?.description ?? "CryptorModule Not Found"
case .authKey:
return config.authKey
case .uuid:
Expand Down
2 changes: 1 addition & 1 deletion Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 61a40240486621bb01f596fdd5bc632504940fab

COCOAPODS: 1.11.3
COCOAPODS: 1.12.1
216 changes: 200 additions & 16 deletions PubNub.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions Sources/PubNub/APIs/File+PubNub.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ public extension PubNub {
switch result {
case let .success(response):
do {
let autoCrypto = requestConfig.customConfiguration?.cipherKey ?? configuration.cipherKey
let cryptorModule = requestConfig.customConfiguration?.cryptorModule ?? configuration.cryptorModule
completion?(.success((
try URLRequest(from: response.payload, uploading: content, crypto: autoCrypto),
try URLRequest(from: response.payload, uploading: content, cryptorModule: cryptorModule),
response.payload.fileId,
response.payload.filename
)))
Expand Down Expand Up @@ -450,7 +450,7 @@ public extension PubNub {
/// - downloadTo: The async `Result` of the method call
/// - Returns: The new file download task. The `urlSessionTask` property can be used to access the underlying `URLSessionDownloadTask`
func createFileURLSessionDownloadTask(
_ taskType: FileDownloadTaskType, session: URLSessionReplaceable, downloadTo url: URL, decrypt: Crypto? = nil
_ taskType: FileDownloadTaskType, session: URLSessionReplaceable, downloadTo url: URL, decrypt: CryptorModule? = nil
) -> HTTPFileDownloadTask {
let downloadTask: URLSessionDownloadTask
switch taskType {
Expand All @@ -464,7 +464,7 @@ public extension PubNub {
task: downloadTask,
session: session.configuration.identifier,
downloadTo: url,
crypto: decrypt ?? configuration.cipherKey
cryptorModule: decrypt ?? configuration.cryptorModule
)

// Create task map inside Delegate
Expand Down
6 changes: 6 additions & 0 deletions Sources/PubNub/Errors/ErrorDescription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,12 @@ extension PubNubError.Reason: CustomStringConvertible, LocalizedError {
return "The Content-Length was incorrect for the content being uploaded"
case .serviceNotEnabled:
return "The PubNub Service that you're attempting to use has not be enabled for your keyset."
case .encryptionError:
return "Failure to perform encryption"
case .decryptionError:
return "Failure to perform decryption"
case .unknownCryptorError:
return "Unknown Cryptor error"
}
}

Expand Down
5 changes: 5 additions & 0 deletions Sources/PubNub/Errors/PubNubError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ public struct PubNubError: Error {

// Crypto
case missingCryptoKey
case encryptionError
case decryptionError
case unknownCryptorError
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jguz-pubnub Should we try to be consistent with other cases in class? The class itself already specifies that it will be errors, and the *Error suffix won't have much meaning. Other cases which report any troubles have *Failure suffix.


// Request Processing
case requestMutatorFailure
Expand Down Expand Up @@ -232,6 +235,8 @@ public struct PubNubError: Error {
return .streamFailure
case .fileTooLarge, .fileMissingAtPath, .fileAccessDenied, .fileContentLength:
return .fileManagement
case .encryptionError, .decryptionError, .unknownCryptorError:
return .crypto
}
}
}
Expand Down
42 changes: 22 additions & 20 deletions Sources/PubNub/Extensions/URLRequest+PubNub.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public extension URLRequest {
internal init(
from response: GenerateUploadURLResponse,
uploading content: PubNub.FileUploadContent,
crypto: Crypto? = nil
cryptorModule: CryptorModule? = nil
) throws {
self.init(url: response.uploadRequestURL)
method = response.uploadMethod
Expand All @@ -65,30 +65,32 @@ public extension URLRequest {
postfixData.append("\r\n--\(response.fileId)--")

// Get Content InputStream
guard var contentStream = content.inputStream else {
guard let contentStream = content.inputStream else {
throw PubNubError(.streamCouldNotBeInitialized, additional: [content.debugDescription])
}

// If we were given a Crypto payload we should convert the stream to a secure stream
if let crypto = crypto {
let cryptoStream = CryptoInputStream(
.encrypt, input: contentStream, contentLength: content.contentLength, with: crypto
)
setValue(
"\(prefixData.count + cryptoStream.estimatedCryptoCount + postfixData.count)",
forHTTPHeaderField: "Content-Length"
)
contentStream = cryptoStream

let finalStream: InputStream
let contentLength: Int

// If we were given a Crypto module we should convert the stream to a secure stream
if let cryptorModule = cryptorModule {
switch cryptorModule.encrypt(stream: contentStream, contentLength: content.contentLength) {
case .success(let encryptingResult):
finalStream = encryptingResult.stream
contentLength = prefixData.count + encryptingResult.contentLength + postfixData.count
case .failure(let encryptionError):
throw encryptionError
}
} else {
setValue("\(prefixData.count + content.contentLength + postfixData.count)", forHTTPHeaderField: "Content-Length")
finalStream = contentStream
contentLength = prefixData.count + content.contentLength + postfixData.count
}

let inputStream = MultipartInputStream(
inputStreams: [InputStream(data: prefixData), contentStream, InputStream(data: postfixData)]
)

httpBodyStream = inputStream

setValue("\(contentLength)", forHTTPHeaderField: "Content-Length")
setValue("multipart/form-data; boundary=\(response.fileId)", forHTTPHeaderField: "Content-Type")

httpBodyStream = MultipartInputStream(
inputStreams: [InputStream(data: prefixData), finalStream, InputStream(data: postfixData)]
)
}
}
Loading