Skip to content

Commit

Permalink
fix(crypto): Renaming CryptorModule with CryptoModule
Browse files Browse the repository at this point in the history
  • Loading branch information
jguz-pubnub committed Oct 20, 2023
1 parent 56c8687 commit f68cb9e
Show file tree
Hide file tree
Showing 18 changed files with 119 additions and 109 deletions.
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.cryptorModule?.description ?? "CryptorModule Not Found"
return config.cryptoModule?.description ?? "CryptoModule Not Found"
case .authKey:
return config.authKey
case .uuid:
Expand Down
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 cryptorModule = requestConfig.customConfiguration?.cryptorModule ?? configuration.cryptorModule
let cryptoModule = requestConfig.customConfiguration?.cryptoModule ?? configuration.cryptoModule
completion?(.success((
try URLRequest(from: response.payload, uploading: content, cryptorModule: cryptorModule),
try URLRequest(from: response.payload, uploading: content, cryptoModule: cryptoModule),
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: CryptorModule? = nil
_ taskType: FileDownloadTaskType, session: URLSessionReplaceable, downloadTo url: URL, decrypt: CryptoModule? = nil
) -> HTTPFileDownloadTask {
let downloadTask: URLSessionDownloadTask
switch taskType {
Expand All @@ -464,7 +464,7 @@ public extension PubNub {
task: downloadTask,
session: session.configuration.identifier,
downloadTo: url,
cryptorModule: decrypt ?? configuration.cryptorModule
cryptoModule: decrypt ?? configuration.cryptoModule
)

// Create task map inside Delegate
Expand Down
6 changes: 3 additions & 3 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,
cryptorModule: CryptorModule? = nil
cryptoModule: CryptoModule? = nil
) throws {
self.init(url: response.uploadRequestURL)
method = response.uploadMethod
Expand All @@ -73,8 +73,8 @@ public extension URLRequest {
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) {
if let cryptoModule = cryptoModule {
switch cryptoModule.encrypt(stream: contentStream, contentLength: content.contentLength) {
case .success(let encryptingResult):
finalStream = encryptingResult
contentLength = prefixData.count + ((encryptingResult as? MultipartInputStream)?.length ?? 0) + postfixData.count
Expand Down
2 changes: 1 addition & 1 deletion Sources/PubNub/Helpers/Crypto/Crypto.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import Foundation

/// Object capable of encryption/decryption
///
/// - Warning: This struct is deprecated. Use ``CryptorModule`` instead.
/// - Warning: This struct is deprecated. Use ``CryptoModule`` instead.
public struct Crypto: Hashable {
/// Key initially provided by the user
let key: String
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// CryptorModule.swift
// CryptoModule.swift
//
// PubNub Real-time Cloud-Hosted Push API and Push Notification Client Frameworks
// Copyright © 2023 PubNub Inc.
Expand Down Expand Up @@ -27,19 +27,29 @@

import Foundation

@available(*, unavailable, renamed: "CryptoModule")
public class CryptorModule {
public static func aesCbcCryptoModule(with key: String, withRandomIV: Bool = true) -> CryptoModule {
preconditionFailure("This method is no longer available")
}
public static func legacyCryptoModule(with key: String, withRandomIV: Bool = true) -> CryptoModule {
preconditionFailure("This method is no longer available")
}
}

/// Object capable of encryption/decryption
public struct CryptorModule {
public struct CryptoModule {
private let defaultCryptor: Cryptor
private let cryptors: [Cryptor]
private let legacyCryptorId: CryptorId = []

typealias Base64EncodedString = String

/// Initializes `CryptorModule` with custom ``Cryptor`` objects capable of encryption and decryption
/// Initializes `CryptoModule` with custom ``Cryptor`` objects capable of encryption and decryption
///
/// Use this constructor if you would like to provide **custom** objects for decryption and encryption and don't want to use PubNub's built-in `Cryptors`.
/// Otherwise, refer to convenience static factory methods such as ``aesCbcCryptoModule(with:withRandomIV:)``
/// and ``legacyCryptoModule(with:withRandomIV:)`` that return `CryptorModule` configured for you.
/// and ``legacyCryptoModule(with:withRandomIV:)`` that return `CryptoModule` configured for you.
///
/// - Parameters:
/// - default: Primary ``Cryptor`` instance used for encryption and decryption
Expand Down Expand Up @@ -251,10 +261,10 @@ public struct CryptorModule {
}
}

/// Convenience methods for creating `CryptorModule`
public extension CryptorModule {
/// Convenience methods for creating `CryptoModule`
public extension CryptoModule {

/// Returns **recommended** `CryptorModule` for encryption/decryption
/// Returns **recommended** `CryptoModule` for encryption/decryption
///
/// - Parameters:
/// - key: Key used for encryption/decryption
Expand All @@ -263,40 +273,40 @@ public extension CryptorModule {
/// This method sets ``AESCBCCryptor`` as the primary object for decryption and encryption. It also
/// instantiates ``LegacyCryptor``under the hood with `withRandomIV`. This way, you can interact with historical
/// messages or messages sent from older clients
static func aesCbcCryptoModule(with key: String, withRandomIV: Bool = true) -> CryptorModule {
CryptorModule(default: AESCBCCryptor(key: key), cryptors: [LegacyCryptor(key: key, withRandomIV: withRandomIV)])
static func aesCbcCryptoModule(with key: String, withRandomIV: Bool = true) -> CryptoModule {
CryptoModule(default: AESCBCCryptor(key: key), cryptors: [LegacyCryptor(key: key, withRandomIV: withRandomIV)])
}

/// Returns legacy `CryptorModule` for encryption/decryption
/// Returns legacy `CryptoModule` for encryption/decryption
///
/// - Parameters:
/// - key: Key used for encryption/decryption
/// - withRandomIV: A flag describing whether random initialization vector should be used
/// - Warning: It's highly recommended to always use ``aesCbcCryptoModule(with:withRandomIV:)``
static func legacyCryptoModule(with key: String, withRandomIV: Bool = true) -> CryptorModule {
CryptorModule(default: LegacyCryptor(key: key, withRandomIV: withRandomIV), cryptors: [AESCBCCryptor(key: key)])
static func legacyCryptoModule(with key: String, withRandomIV: Bool = true) -> CryptoModule {
CryptoModule(default: LegacyCryptor(key: key, withRandomIV: withRandomIV), cryptors: [AESCBCCryptor(key: key)])
}
}

extension CryptorModule: Equatable {
public static func ==(lhs: CryptorModule, rhs: CryptorModule) -> Bool {
extension CryptoModule: Equatable {
public static func ==(lhs: CryptoModule, rhs: CryptoModule) -> Bool {
lhs.cryptors.map { $0.id } == rhs.cryptors.map { $0.id }
}
}

extension CryptorModule: Hashable {
extension CryptoModule: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(cryptors.map { $0.id })
}
}

extension CryptorModule: CustomStringConvertible {
extension CryptoModule: CustomStringConvertible {
public var description: String {
"Default cryptor: \(defaultCryptor.id), others: \(cryptors.map { $0.id })"
}
}

internal extension CryptorModule {
internal extension CryptoModule {
func encrypt(string: String) -> Result<Base64EncodedString, PubNubError> {
guard let data = string.data(using: .utf8) else {
return .failure(PubNubError(
Expand Down
14 changes: 7 additions & 7 deletions Sources/PubNub/Networking/HTTPFileTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public class HTTPFileDownloadTask: HTTPFileTask {
/// The block that is called when the task completes
public var completionBlock: ((Result<URL, Error>) -> Void)?
/// The crypto object that will attempt to decrypt the file
public var cryptorModule: CryptorModule?
public var cryptoModule: CryptoModule?

/// The location where the temporary downloaded file should be copied
public private(set) var destinationURL: URL
Expand All @@ -250,21 +250,21 @@ public class HTTPFileDownloadTask: HTTPFileTask {
(urlSessionTask as? URLSessionDownloadTask)?.cancel(byProducingResumeData: byProducingResumeData)
}

init(task: URLSessionDownloadTask, session identifier: String?, downloadTo url: URL, cryptorModule: CryptorModule?) {
init(task: URLSessionDownloadTask, session identifier: String?, downloadTo url: URL, cryptoModule: CryptoModule?) {
self.destinationURL = url
self.cryptorModule = cryptorModule
self.cryptoModule = cryptoModule

super.init(task: task, session: identifier)
}

func decrypt(_ encryptedURL: URL, to outpuURL: URL, using cryptorModule: CryptorModule) throws {
func decrypt(_ encryptedURL: URL, to outpuURL: URL, using cryptoModule: CryptoModule) throws {
// If we were provided a Crypto object we should try and decrypt the file

guard let inputStream = InputStream(url: encryptedURL) else {
throw PubNubError(.streamCouldNotBeInitialized, additional: [encryptedURL.absoluteString])
}

cryptorModule.decrypt(
cryptoModule.decrypt(
stream: inputStream,
contentLength: encryptedURL.sizeOf,
to: outpuURL
Expand Down Expand Up @@ -324,15 +324,15 @@ public class HTTPFileDownloadTask: HTTPFileTask {
// Update destination to be a unique file
destinationURL = fileManager.makeUniqueFilename(destinationURL)

if let cryptorModule = cryptorModule {
if let cryptoModule = cryptoModule {
// Set the encrypted in case something goes wrong
encryptedURL = url

guard let stream = InputStream(url: url) else {
throw PubNubError(.streamCouldNotBeInitialized, additional: [url.absoluteString])
}

cryptorModule.decrypt(
cryptoModule.decrypt(
stream: stream,
contentLength: url.sizeOf,
to: destinationURL
Expand Down
2 changes: 1 addition & 1 deletion Sources/PubNub/Networking/HTTPRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public protocol RouterConfiguration {
/// If Access Manager (PAM) is enabled, client will use `authToken` instead of `authKey` on all requests
var authToken: String? { get }
/// If set, all communication will be encrypted with this module
var cryptorModule: CryptorModule? { get }
var cryptoModule: CryptoModule? { get }
/// Whether a request identifier should be included on outgoing requests
var useRequestId: Bool { get }
/// Ordered list of key-value pairs which identify various consumers.
Expand Down
4 changes: 2 additions & 2 deletions Sources/PubNub/Networking/Routers/HistoryRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ struct MessageHistoryResponseDecoder: ResponseDecoder {
response: EndpointResponse<MessageHistoryResponse>
) -> Result<EndpointResponse<MessageHistoryResponse>, Error> {
// End early if we don't have a cipher key
guard let cryptorModule = response.router.configuration.cryptorModule else {
guard let cryptoModule = response.router.configuration.cryptoModule else {
return .success(response)
}

Expand All @@ -200,7 +200,7 @@ struct MessageHistoryResponseDecoder: ResponseDecoder {
// Convert base64 string into Data
if let messageData = message.message.dataOptional {
// If a message fails we just return the original and move on
switch cryptorModule.decryptedString(from: messageData) {
switch cryptoModule.decryptedString(from: messageData) {
case .success(let decodedString):
messages[index] = MessageHistoryMessagePayload(
message: AnyJSON(reverse: decodedString),
Expand Down
8 changes: 4 additions & 4 deletions Sources/PubNub/Networking/Routers/PublishRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ struct PublishRouter: HTTPRouter {
}

func append(message: JSONCodable, to partialPath: String) -> Result<String, Error> {
if let cryptorModule = configuration.cryptorModule {
if let cryptoModule = configuration.cryptoModule {
return message.jsonDataResult.flatMap { jsonData in
cryptorModule.encrypt(data: jsonData).mapError { $0 as Error }
cryptoModule.encrypt(data: jsonData).mapError { $0 as Error }
.flatMap { .success("\(partialPath)\($0.base64EncodedString().urlEncodeSlash.jsonDescription)") }
}
}
Expand Down Expand Up @@ -145,9 +145,9 @@ struct PublishRouter: HTTPRouter {
var body: Result<Data?, Error> {
switch endpoint {
case let .compressedPublish(message, _, _, _, _):
if let cryptorModule = configuration.cryptorModule {
if let cryptoModule = configuration.cryptoModule {
return message.jsonStringifyResult.flatMap {
cryptorModule.encrypt(string: $0)
cryptoModule.encrypt(string: $0)
.map { $0.jsonDescription.data(using: .utf8) }
.mapError { $0 as Error }
}
Expand Down
12 changes: 6 additions & 6 deletions Sources/PubNub/Networking/Routers/SubscribeRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,11 @@ struct SubscribeDecoder: ResponseDecoder {
}
}

func decrypt(_ cryptorModule: CryptorModule, message: SubscribeMessagePayload) -> SubscribeMessagePayload {
func decrypt(_ cryptoModule: CryptoModule, message: SubscribeMessagePayload) -> SubscribeMessagePayload {
// Convert base64 string into Data
if let messageData = message.payload.dataOptional {
// If a message fails we just return the original and move on
switch cryptorModule.decryptedString(from: messageData) {
switch cryptoModule.decryptedString(from: messageData) {
case .success(let decodedString):
// Create mutable copy of payload
var message = message
Expand All @@ -157,19 +157,19 @@ struct SubscribeDecoder: ResponseDecoder {

func decrypt(response: SubscribeEndpointResponse) -> Result<SubscribeEndpointResponse, Error> {
// End early if we don't have a cipher key
guard let cryptorModule = response.router.configuration.cryptorModule else {
guard let cryptoModule = response.router.configuration.cryptoModule else {
return .success(response)
}

var messages = response.payload.messages
for (index, message) in messages.enumerated() {
switch message.messageType {
case .message:
messages[index] = decrypt(cryptorModule, message: message)
messages[index] = decrypt(cryptoModule, message: message)
case .signal:
messages[index] = decrypt(cryptorModule, message: message)
messages[index] = decrypt(cryptoModule, message: message)
case .file:
messages[index] = decrypt(cryptorModule, message: message)
messages[index] = decrypt(cryptoModule, message: message)
default:
messages[index] = message
}
Expand Down
12 changes: 6 additions & 6 deletions Sources/PubNub/PubNub.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1247,30 +1247,30 @@ public extension PubNub {
// MARK: - Crypto

extension PubNub {
/// Encrypt some `Data` using the configuration `CryptorModule` value
/// Encrypt some `Data` using the configuration `CryptoModule` value
/// - Parameter message: The plain text message to be encrypted
/// - Returns: A `Result` containing either the encryped Data (mapped to Base64-encoded data) or the Crypto Error
public func encrypt(message: String) -> Result<Data, Error> {
guard let cryptorModule = configuration.cryptorModule else {
guard let cryptoModule = configuration.cryptoModule else {
PubNub.log.error(ErrorDescription.missingCryptoKey)
return .failure(CryptoError.invalidKey)
}
guard let dataMessage = message.data(using: .utf8) else {
return .failure(CryptoError.decodeError)
}

return cryptorModule.encrypt(data: dataMessage).map {
return cryptoModule.encrypt(data: dataMessage).map {
$0.base64EncodedData()
}.mapError {
$0 as Error
}
}

/// Decrypt some `Data` using the configuration CryptorModule value
/// Decrypt some `Data` using the configuration CryptoModule value
/// - Parameter message: The encrypted `Data` to decrypt
/// - Returns: A `Result` containing either the decrypted plain text message or the Crypto Error
public func decrypt(data: Data) -> Result<String, Error> {
guard let cryptorModule = configuration.cryptorModule else {
guard let cryptoModule = configuration.cryptoModule else {
PubNub.log.error(ErrorDescription.missingCryptoKey)
return .failure(CryptoError.invalidKey)
}
Expand All @@ -1279,7 +1279,7 @@ extension PubNub {
return .failure(CryptoError.decodeError)
}

return cryptorModule.decrypt(data: base64EncodedData)
return cryptoModule.decrypt(data: base64EncodedData)
.flatMap {
guard let string = String(data: $0, encoding: .utf8) else {
return .failure(PubNubError(.decryptionFailure, additional: ["Cannot create String from received bytes"]))
Expand Down
Loading

0 comments on commit f68cb9e

Please sign in to comment.