87 lines
2.5 KiB
Swift
87 lines
2.5 KiB
Swift
|
//
|
||
|
// 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()
|
||
|
}
|
||
|
|
||
|
}
|