Path: blob/main/SignalServiceKit/Cryptography/ECKeyPair.swift
1 views
//
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
public import LibSignalClient
@objc(ECKeyPair)
public final class ECKeyPair: NSObject, NSSecureCoding {
public let keyPair: IdentityKeyPair
public var identityKeyPair: IdentityKeyPair { keyPair }
init(_ keyPair: IdentityKeyPair) {
self.keyPair = keyPair
}
/**
* Build a keypair from existing key data.
* If you need a *new* keypair, user `ECKeyPair.generateKeyPair` instead.
*/
convenience init(publicKeyData: Data, privateKeyData: Data) throws {
let publicKey = try PublicKey(keyData: publicKeyData)
let privateKey = try PrivateKey(privateKeyData)
self.init(IdentityKeyPair(publicKey: publicKey, privateKey: privateKey))
}
private static let TSECKeyPairPublicKey = "TSECKeyPairPublicKey"
private static let TSECKeyPairPrivateKey = "TSECKeyPairPrivateKey"
public convenience init?(coder: NSCoder) {
var returnedLength = 0
let publicKeyBuffer = coder.decodeBytes(forKey: Self.TSECKeyPairPublicKey, returnedLength: &returnedLength)
guard let publicKeyBuffer else {
return nil
}
let publicKeyData = Data(bytes: publicKeyBuffer, count: returnedLength)
returnedLength = 0
let privateKeyBuffer = coder.decodeBytes(forKey: Self.TSECKeyPairPrivateKey, returnedLength: &returnedLength)
guard let privateKeyBuffer else {
return nil
}
let privateKeyData = Data(bytes: privateKeyBuffer, count: returnedLength)
do {
try self.init(publicKeyData: publicKeyData, privateKeyData: privateKeyData)
} catch {
Logger.warn("\(error)")
return nil
}
}
public func encode(with coder: NSCoder) {
self.identityKeyPair.publicKey.keyBytes.withUnsafeBytes {
coder.encodeBytes($0.baseAddress, length: $0.count, forKey: Self.TSECKeyPairPublicKey)
}
self.identityKeyPair.privateKey.serialize().withUnsafeBytes {
coder.encodeBytes($0.baseAddress, length: $0.count, forKey: Self.TSECKeyPairPrivateKey)
}
}
public class var supportsSecureCoding: Bool {
return true
}
public static func generateKeyPair() -> ECKeyPair {
return ECKeyPair(IdentityKeyPair.generate())
}
private func sign(_ data: Data) throws -> Data {
return identityKeyPair.privateKey.generateSignature(message: data)
}
public var publicKey: Data {
return identityKeyPair.publicKey.keyBytes
}
public var privateKey: Data {
return identityKeyPair.privateKey.serialize()
}
}
extension IdentityKeyPair {
public var asECKeyPair: ECKeyPair { return .init(self) }
}