애플리케이션이 신뢰할 수 있는 소스에서 설치되었나요?
무결성관련 체크를 위해 빌드환경을 체크해야하는 상황이 생긴다.
이 앱이 앱스토어에서 빌드했는지, 테스트플라잇인지, 로컬인지를 확인할 수 있도록 말이다.
앱소스를 정확하게 식별하기 위해서는 몇단계의 검증을 거친다.
- 모바일 프로비저닝 프로파일의 존재여부
- App Store 영수증 데이터 파일 분석
- 샌드박스 영수증 데이터 파일 분석 – 앱이 TestFlight를 통해 배포되었을 때 표시됨
시뮬레이터인지 디바이스인지 체크하는 Bool값
private func isSimulator() -> Bool {
#if arch(i386) || arch(x86_64)
return true
#else
return false
#endif
}
- 앱스토어영수증이 있는지 체크하는 Bool값
- 사용자가 App Store에서 앱을 다운로드한 경우, 앱에는 영수증이 항상 존재한다.
- 샌드박스에서 앱이 Xcode 또는 Testflight를 사용하여 설치한 경우, 구매가 완료될 때까지 영수증이 없다.
- 테스트플라잇을 통해 배포되었을때 내용을 확인할 수 있다.
appStoreReceiptURL.lastPathComponent == "sandboxReceipt"
Step1. 시뮬레이터체크
Step2. Bundle.main의 appStoreReceiptURL
이 있는지 확인
Step3. 그 URL에 sandboxReceipt
가 있는지 확인
private func isAppStoreReceiptSandbox() -> Bool {
if isSimulator() {
return false
} else {
guard let url = Bundle.main.appStoreReceiptURL else {
return false
}
// 혹은 FileManager.default.fileExists(atPath: Bundle.main.appStoreReceiptURL.path)
guard url.lastPathComponent == "sandboxReceipt" else {
return false
}
return true
}
}
모바일 프로비저닝 파일이 nil이라면 true를 리턴하는 Bool값
- mobileProvision 파일은 Ad-Hoc 배포에 대한 명확한 지표이다.
- embedded.mobileprovision 파일이 있는 경우 .ipa 파일은 Apple App Store에서 가져온 것이 아님
- mobileProvision 파일을 통해 앱스토어가 아니라 개발자가 배포한 앱을 설치할 수 있다.
- MobileProvision에 대해 간단한 정리가 되어있는 naljin님 링크 [여기]
// Bundle.main.path(forResource: "embedded", ofType: "mobileprovision") != nil
private func hasEmbeddedMobileProvision() -> Bool {
guard Bundle.main.path(forResource: "embedded", ofType: "mobileprovision") == nil else {
return true
}
return false
}
extension UIApplication {
// MARK: Public
func isRunningInTestFlightEnvironment() -> Bool {
if isSimulator() {
return false
} else {
if isAppStoreReceiptSandbox() && !hasEmbeddedMobileProvision() {
return true
} else {
return false
}
}
}
func isRunningInAppStoreEnvironment() -> Bool {
if isSimulator(){
return false
} else {
if isAppStoreReceiptSandbox() || hasEmbeddedMobileProvision() {
return false
} else {
return true
}
}
}
// MARK: Private
private func hasEmbeddedMobileProvision() -> Bool {
guard Bundle.main.path(forResource: "embedded", ofType: "mobileprovision") == nil else {
return true
}
return false
}
private func isAppStoreReceiptSandbox() -> Bool {
if isSimulator() {
return false
} else {
guard let url = Bundle.main.appStoreReceiptURL else {
return false
}
guard url.lastPathComponent == "sandboxReceipt" else {
return false
}
return true
}
}
private func isSimulator() -> Bool {
#if arch(i386) || arch(x86_64)
return true
#else
return false
#endif
}
}
- https://iosdevblog.com/2021/01/13/is-the-application-installed-from-a-trusted-source/
- https://gist.github.com/SergLam/609e2dc76b9f321877f4fb7fe8e26fdf
mobileProvision