Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4dd74e61bb | |||
| cca79b7d2f | |||
| 171c84ec5c | |||
| 91e300cf49 | |||
| 192b0102cf |
@@ -7,10 +7,10 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
D1150C78274BA3AD007FA109 /* AppReceiptValidator in Frameworks */ = {isa = PBXBuildFile; productRef = D1150C77274BA3AD007FA109 /* AppReceiptValidator */; };
|
||||
D1150C79274BA3AD007FA109 /* AppReceiptValidator in Embed Frameworks */ = {isa = PBXBuildFile; productRef = D1150C77274BA3AD007FA109 /* AppReceiptValidator */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
D1150C7B274BA3B1007FA109 /* AppReceiptValidator in Frameworks */ = {isa = PBXBuildFile; productRef = D1150C7A274BA3B1007FA109 /* AppReceiptValidator */; };
|
||||
D1150C7C274BA3B1007FA109 /* AppReceiptValidator in Embed Frameworks */ = {isa = PBXBuildFile; productRef = D1150C7A274BA3B1007FA109 /* AppReceiptValidator */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
80AB3E2F276CA8E100C4AB61 /* AppReceiptValidator in Frameworks */ = {isa = PBXBuildFile; productRef = 80AB3E2E276CA8E100C4AB61 /* AppReceiptValidator */; };
|
||||
80AB3E30276CA8E100C4AB61 /* AppReceiptValidator in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 80AB3E2E276CA8E100C4AB61 /* AppReceiptValidator */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
80AB3E32276CA8E500C4AB61 /* AppReceiptValidator in Frameworks */ = {isa = PBXBuildFile; productRef = 80AB3E31276CA8E500C4AB61 /* AppReceiptValidator */; };
|
||||
80AB3E33276CA8E500C4AB61 /* AppReceiptValidator in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 80AB3E31276CA8E500C4AB61 /* AppReceiptValidator */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
D13E5B7D20331B9B001880F0 /* DropAcceptingTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D13E5B7C20331B9B001880F0 /* DropAcceptingTextView.swift */; };
|
||||
D19095841F6000A40095729B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D19095831F6000A40095729B /* AppDelegate.swift */; };
|
||||
D19095861F6000A40095729B /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D19095851F6000A40095729B /* ViewController.swift */; };
|
||||
@@ -30,7 +30,7 @@
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
D1150C7C274BA3B1007FA109 /* AppReceiptValidator in Embed Frameworks */,
|
||||
80AB3E33276CA8E500C4AB61 /* AppReceiptValidator in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -41,7 +41,7 @@
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
D1150C79274BA3AD007FA109 /* AppReceiptValidator in Embed Frameworks */,
|
||||
80AB3E30276CA8E100C4AB61 /* AppReceiptValidator in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -72,7 +72,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D1150C7B274BA3B1007FA109 /* AppReceiptValidator in Frameworks */,
|
||||
80AB3E32276CA8E500C4AB61 /* AppReceiptValidator in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -80,7 +80,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D1150C78274BA3AD007FA109 /* AppReceiptValidator in Frameworks */,
|
||||
80AB3E2F276CA8E100C4AB61 /* AppReceiptValidator in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -160,7 +160,7 @@
|
||||
);
|
||||
name = "AppReceiptValidator Demo macOS";
|
||||
packageProductDependencies = (
|
||||
D1150C7A274BA3B1007FA109 /* AppReceiptValidator */,
|
||||
80AB3E31276CA8E500C4AB61 /* AppReceiptValidator */,
|
||||
);
|
||||
productName = "AppReceiptValidator Demo macOS";
|
||||
productReference = D19095811F6000A40095729B /* AppReceiptValidator Demo macOS.app */;
|
||||
@@ -182,7 +182,7 @@
|
||||
);
|
||||
name = "AppReceiptValidator Demo iOS";
|
||||
packageProductDependencies = (
|
||||
D1150C77274BA3AD007FA109 /* AppReceiptValidator */,
|
||||
80AB3E2E276CA8E100C4AB61 /* AppReceiptValidator */,
|
||||
);
|
||||
productName = "Demo iOS";
|
||||
productReference = D1D6F4E41F5D691400E86FE1 /* AppReceiptValidator Demo iOS.app */;
|
||||
@@ -224,7 +224,6 @@
|
||||
);
|
||||
mainGroup = D1D6F4921F5D67E600E86FE1;
|
||||
packageReferences = (
|
||||
D1150C73274BA2C8007FA109 /* XCRemoteSwiftPackageReference "AppReceiptValidator" */,
|
||||
);
|
||||
productRefGroup = D1D6F49C1F5D67E600E86FE1 /* Products */;
|
||||
projectDirPath = "";
|
||||
@@ -584,26 +583,13 @@
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
D1150C73274BA2C8007FA109 /* XCRemoteSwiftPackageReference "AppReceiptValidator" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/IdeasOnCanvas/AppReceiptValidator";
|
||||
requirement = {
|
||||
branch = main;
|
||||
kind = branch;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
D1150C77274BA3AD007FA109 /* AppReceiptValidator */ = {
|
||||
80AB3E2E276CA8E100C4AB61 /* AppReceiptValidator */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D1150C73274BA2C8007FA109 /* XCRemoteSwiftPackageReference "AppReceiptValidator" */;
|
||||
productName = AppReceiptValidator;
|
||||
};
|
||||
D1150C7A274BA3B1007FA109 /* AppReceiptValidator */ = {
|
||||
80AB3E31276CA8E500C4AB61 /* AppReceiptValidator */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D1150C73274BA2C8007FA109 /* XCRemoteSwiftPackageReference "AppReceiptValidator" */;
|
||||
productName = AppReceiptValidator;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "6f36ef23becd7f9266ef6b026af4798996a1a8be",
|
||||
"version": null
|
||||
"version": "1.8.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -154,34 +154,8 @@ private extension AppReceiptValidator {
|
||||
guard let signatureData = signature.signatureData else { throw Error.receiptNotSigned }
|
||||
guard let receiptData = pkcs7.mainBlock.findOid(.pkcs7data)?.parent?.sub?.last?.sub(0)?.rawValue else { throw Error.receiptNotSigned }
|
||||
|
||||
let rootCert1 = pkcs7.certificates[0]
|
||||
let rootCert2: X509Certificate = try .init(data: appleRootCertificateData)
|
||||
|
||||
do {
|
||||
func validateChain() {
|
||||
let rootCert = SecCertificateCreateWithData(nil, appleRootCertificateData as CFData)
|
||||
let receiptCerts = pkcs7.certificatesData.compactMap { SecCertificateCreateWithData(nil, $0 as CFData) }
|
||||
|
||||
let policy = SecPolicyCreateBasicX509()
|
||||
var optionalTrust: SecTrust?
|
||||
let status = SecTrustCreateWithCertificates([rootCert] as AnyObject,
|
||||
policy,
|
||||
&optionalTrust)
|
||||
if status == errSecSuccess {
|
||||
let trust = optionalTrust! // Safe to force unwrap now
|
||||
SecTrustSetAnchorCertificates(trust, [receiptCerts] as CFArray)
|
||||
var error: CFError?
|
||||
print("Veryfing result: ", SecTrustEvaluateWithError(trust, &error))
|
||||
print(error)
|
||||
}
|
||||
else {
|
||||
print("error")
|
||||
}
|
||||
}
|
||||
validateChain()
|
||||
}
|
||||
|
||||
try self.verifyAuthenticity(x509Certificate: rootCert2, receiptData: receiptData, signatureData: signatureData)
|
||||
let rootCert = pkcs7.certificates[0]
|
||||
try self.verifyAuthenticity(x509Certificate: rootCert, receiptData: receiptData, signatureData: signatureData)
|
||||
}
|
||||
|
||||
func verifyAuthenticity(x509Certificate: X509Certificate, receiptData: Data, signatureData: Data) throws {
|
||||
@@ -190,10 +164,6 @@ private extension AppReceiptValidator {
|
||||
guard let key = x509Certificate.publicKey?.secKey,
|
||||
let algorithm = x509Certificate.publicKey?.secAlgorithm else { throw Error.receiptSignatureInvalid }
|
||||
|
||||
//
|
||||
//
|
||||
// guard SecTrustCreateWithCertificates(<#T##certificates: CFTypeRef##CFTypeRef#>, <#T##policies: CFTypeRef?##CFTypeRef?#>, <#T##trust: UnsafeMutablePointer<SecTrust?>##UnsafeMutablePointer<SecTrust?>#>)
|
||||
//
|
||||
var verifyError: Unmanaged<CFError>?
|
||||
guard SecKeyVerifySignature(key, algorithm, receiptData as CFData, signatureData as CFData, &verifyError),
|
||||
verifyError == nil else {
|
||||
@@ -242,7 +212,7 @@ private extension AppReceiptValidator {
|
||||
let items = receiptBlock.sub else { return .init(entries: []) }
|
||||
|
||||
let entries: [UnofficialReceipt.Entry] = items.compactMap { item in
|
||||
guard let fieldType = (item.sub(0)?.value as? Data)?.uint64Value,
|
||||
guard let fieldType = (item.sub(0)?.value as? Data)?.uint64ValueOrZero, // provisioning fieldtype pops up here as empty Data, so we use uint64ValueOrZero
|
||||
KnownReceiptAttribute(rawValue: fieldType) == nil else { return nil }
|
||||
|
||||
let fieldValueString = item.sub(2)?.asString
|
||||
@@ -428,3 +398,15 @@ extension X509PublicKey {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// MARK: - Data + Unofficial Receipt FieldTypes
|
||||
|
||||
private extension Data {
|
||||
|
||||
/// Decoded as by ASN1Decoder's Data.uint64Value extension, or as 0 if empty
|
||||
var uint64ValueOrZero: UInt64? {
|
||||
if self.isEmpty { return 0 }
|
||||
|
||||
return self.uint64Value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,6 +247,27 @@ class AppReceiptValidatorTests: XCTestCase {
|
||||
XCTAssertEqual(receipt, expected)
|
||||
}
|
||||
|
||||
func testUnofficialProvisioningTypes() throws {
|
||||
do {
|
||||
guard let data = assertB64TestAsset(filename: "mindnode_ios_michaelsandbox_receipt1.b64") else { return }
|
||||
|
||||
let result = try receiptValidator.parseUnofficialReceipt(origin: .data(data))
|
||||
XCTAssertEqual(result.unofficialReceipt.provisioningType, .known(value: .productionSandbox))
|
||||
}
|
||||
do {
|
||||
guard let data = assertB64TestAsset(filename: "mindnode_ios_michaelsandbox_receipt2.b64") else { return }
|
||||
|
||||
let result = try receiptValidator.parseUnofficialReceipt(origin: .data(data))
|
||||
XCTAssertEqual(result.unofficialReceipt.provisioningType, .known(value: .productionSandbox))
|
||||
}
|
||||
do {
|
||||
guard let data = assertB64TestAsset(filename: "hannes_mac_mindnode_receipt.b64") else { return }
|
||||
|
||||
let result = try receiptValidator.parseUnofficialReceipt(origin: .data(data))
|
||||
XCTAssertEqual(result.unofficialReceipt.provisioningType, .known(value: .production))
|
||||
}
|
||||
}
|
||||
|
||||
func testMindNodeiOSSandBoxReceipt2ParsingAndValidation() {
|
||||
guard let data = assertB64TestAsset(filename: "mindnode_ios_michaelsandbox_receipt2.b64") else { return }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user