TM-SGNL-iOS/SignalServiceKit/Curve25519/ECKeyPair.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

85 lines
2.7 KiB
Swift

//
// 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.withUnsafeBufferPointer {
coder.encodeBytes($0.baseAddress, length: $0.count, forKey: Self.TSECKeyPairPublicKey)
}
self.identityKeyPair.privateKey.serialize().withUnsafeBufferPointer {
coder.encodeBytes($0.baseAddress, length: $0.count, forKey: Self.TSECKeyPairPrivateKey)
}
}
public class var supportsSecureCoding: Bool {
return true
}
@objc
public static func generateKeyPair() -> ECKeyPair {
return ECKeyPair(IdentityKeyPair.generate())
}
private func sign(_ data: Data) throws -> Data {
return Data(identityKeyPair.privateKey.generateSignature(message: data))
}
@objc
public var publicKey: Data {
return Data(identityKeyPair.publicKey.keyBytes)
}
public var privateKey: Data {
return Data(identityKeyPair.privateKey.serialize())
}
}