Verifies downloaded app’s SHA-256 checksum (if specified)

This commit is contained in:
Riley Testut
2023-05-11 17:02:20 -05:00
committed by Magesh K
parent 7ad8db7bdc
commit 7dfbba9b00
6 changed files with 93 additions and 14 deletions

View File

@@ -7,6 +7,7 @@
//
import Foundation
import CryptoKit
import AltStoreCore
import AltSign
@@ -96,10 +97,10 @@ struct VerificationError: ALTLocalizedError {
@objc(VerifyAppOperation)
final class VerifyAppOperation: ResultOperation<Void>
{
let context: AppOperationContext
let context: InstallAppOperationContext
var verificationHandler: ((VerificationError) -> Bool)?
init(context: AppOperationContext)
init(context: InstallAppOperationContext)
{
self.context = context
@@ -133,7 +134,23 @@ final class VerifyAppOperation: ResultOperation<Void>
throw VerificationError.iOSVersionNotSupported(app: app, requiredOSVersion: app.minimumiOSVersion)
}
self.finish(.success(()))
guard let appVersion = self.context.appVersion else {
return self.finish(.success(()))
}
Task<Void, Never> {
do
{
guard let ipaURL = self.context.ipaURL else { throw OperationError.appNotFound(name: app.name) }
try await self.verifyHash(of: app, at: ipaURL, matches: appVersion)
self.finish(.success(()))
}
catch
{
self.finish(.failure(error))
}
}
}
catch
{
@@ -141,3 +158,20 @@ final class VerifyAppOperation: ResultOperation<Void>
}
}
}
private extension VerifyAppOperation
{
func verifyHash(of app: ALTApplication, at ipaURL: URL, @AsyncManaged matches appVersion: AppVersion) async throws
{
// Do nothing if source doesn't provide hash.
guard let expectedHash = await $appVersion.sha256 else { return }
let data = try Data(contentsOf: ipaURL)
let sha256Hash = SHA256.hash(data: data)
let hashString = sha256Hash.compactMap { String(format: "%02x", $0) }.joined()
print("[ALTLog] Comparing app hash (\(hashString)) against expected hash (\(expectedHash))...")
guard hashString == expectedHash else { throw VerificationError.mismatchedHash(hashString, expectedHash: expectedHash, app: app) }
}
}