pscbonline-ios/PSCBOnline/Sources/Helpers/RSAHelper.swift

87 lines
2.5 KiB
Swift
Raw Permalink Normal View History

2024-07-08 15:20:00 +03:00
//
// 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<CFError>)
}
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<CFError>? = 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()
}
}