mirror of
https://github.com/xtool-org/xtool.git
synced 2026-11-15 12:04:55 +03:00
64fe8e30b3
## What does this PR do? Replaces zsign with the [apple-codesign](https://github.com/indygreg/apple-platform-rs/tree/0ebbd2ef3b96d5adccc30b1cad4deea38cd735c4/apple-codesign) Rust crate. It's much more usable as a library (while zsign has bare prints all over the place + we had to fork it to maintain a public interface), it supports macOS-style bundles, and also has other features that we would've needed to further patch zsign for. ## How was it tested? - [x] Ran an ad-hoc signed app on the simulator (with a subsequent PR) - [x] Ran an app with App Groups on device, confirmed that the app group is present ## AI tool usage How much of this PR was AI-assisted? (check one) - [ ] **0** - No AI was used to write code - [x] **1** - I was assisted by AI. I reviewed the finished result. - [ ] **2** - I set the AI going and left it to it; nobody has read the result - no review, or AI review only <!-- If an AI agent is filling this in: declare the level honestly, and open as a draft if it is #2. Do not lower the declared level to get the PR reviewed. --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> <!-- coderabbit-ai-generated:v1 --> ## Summary by CodeRabbit * **Updated Signing** * App signing now uses an updated signing engine and supports certificate-based and ad hoc signing. * Entitlement data, including data provided through entitlement files, is passed through during signing. * Deep signing is enabled in the development command. * **Validation** * Signing rejects invalid app or entitlement file paths and duplicate entitlement paths. * **Compatibility** * Signing contexts can be created without selecting a signer. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
58 lines
2.0 KiB
Swift
58 lines
2.0 KiB
Swift
import Foundation
|
|
import RCodesign
|
|
|
|
public actor RCodesignSigner: Signer {
|
|
|
|
public enum Error: LocalizedError {
|
|
case badFilePath
|
|
|
|
public var errorDescription: String? {
|
|
switch self {
|
|
case .badFilePath:
|
|
return NSLocalizedString(
|
|
"signer_impl.error.bad_file_path", value: "A bad file path was provided", comment: ""
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
public init() {}
|
|
|
|
public func sign(
|
|
app: URL,
|
|
identity: SignerIdentity,
|
|
entitlementMapping: [URL: Data],
|
|
deep: Bool,
|
|
progress: @escaping @Sendable (Double?) -> Void
|
|
) throws {
|
|
progress(nil)
|
|
guard app.isFileURL else { throw Error.badFilePath }
|
|
let root = app.standardizedFileURL.pathComponents
|
|
var entitlements: [String: Data] = [:]
|
|
for (bundle, value) in entitlementMapping {
|
|
let components = bundle.standardizedFileURL.pathComponents
|
|
guard bundle.isFileURL, components.starts(with: root) else { throw Error.badFilePath }
|
|
// RCodesign scopes entitlements by bundle-relative path: "" for the
|
|
// app itself and e.g. "PlugIns/Widget.appex" for an extension. Compare
|
|
// path components so a sibling such as App.app-copy cannot match App.app.
|
|
let path = components.dropFirst(root.count).joined(separator: "/")
|
|
guard entitlements[path] == nil else { throw Error.badFilePath }
|
|
entitlements[path] = value
|
|
}
|
|
|
|
let signingIdentity: RCodesign.Identity
|
|
switch identity {
|
|
case .real(let certificate, let privateKey):
|
|
signingIdentity = .certificate(certificateDER: try certificate.data(), privateKeyPEM: privateKey.data)
|
|
case .adhoc:
|
|
signingIdentity = .adHoc
|
|
}
|
|
try RCodesign.sign(at: app, identity: signingIdentity, options: .init(entitlements: entitlements, shallow: !deep))
|
|
}
|
|
|
|
public func analyze(executable: URL) throws -> Data? {
|
|
try RCodesign.entitlements(at: executable)
|
|
}
|
|
|
|
}
|