// // RSAHelper.swift // PSCB-OOS-iOS // // Created by Antonov Ilia on 26.10.2020. // import Foundation enum RSAKeyError: Error { /// Thrown when provided public key is invalid case invalidKey /// Thrown when encryption of message failed case encryption(OSStatus) /// Thrown when unable to initialize `SecKey` with given key string case unmanaged(Unmanaged) } public final class RSAHelper { internal static let key = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPQsWyHaynwoc2tuMbengf1SFase9tPnwtPh4o1tR+94xsWztADdhhUaUBk/68ipaoZE8uSnM9UgdEPmOotFXyUCAwEAAQ==" internal static var secKey: SecKey? = nil static func initPSCBOnlinePublicKey() throws { // Treat as assert guard let keyData = Data(base64Encoded: key) else { print("Invalid key string: \(key)") throw RSAKeyError.invalidKey } var attributes: CFDictionary { return [ kSecAttrKeyType: kSecAttrKeyTypeRSA, kSecAttrKeyClass: kSecAttrKeyClassPublic, kSecAttrKeySizeInBits: 2048, kSecReturnPersistentRef: true ] as CFDictionary } var error: Unmanaged? = nil guard let secKey = SecKeyCreateWithData(keyData as CFData, attributes, &error) else { print("Error creating a security key with \(String(describing: keyData))") print(error.debugDescription) throw RSAKeyError.unmanaged(error!) } Self.secKey = secKey } /// Encrypts given message with OOS public key. /// /// - Parameters: /// - message: A message to encrypt. /// /// - Returns: A base64 encoded string /// /// - Throws: `RSAKeyError` type error public static func encryptEncodeBase64(message: String) throws -> String { // Initialize OOS public key if Self.secKey == nil { try Self.initPSCBOnlinePublicKey() } // Initialize buffers let sKey = Self.secKey! let buff = [UInt8](message.utf8) // Mutable encryption refs var size = SecKeyGetBlockSize(sKey) var kBuf = [UInt8](repeating: 0, count: size) let status = SecKeyEncrypt(sKey, SecPadding.PKCS1, buff, buff.count, &kBuf, &size) // Sanity check guard status == errSecSuccess else { throw RSAKeyError.encryption(status) } return Data(bytes: kBuf, count: size).base64EncodedString() } }