为什么无法读取收据数据以进行设备上验证

2024-04-09

我正在使用以下代码来读取收据数据。我可以使用 OpenSSL 静态库 1.1.1k 成功验证收据签名

 private func readReceipt(_ receiptPKCS7: UnsafeMutablePointer<PKCS7>?) {
        // Get a pointer to the start and end of the ASN.1 payload
        let receiptSign = receiptPKCS7?.pointee.d.sign
        let octets = receiptSign?.pointee.contents.pointee.d.data
        var ptr = UnsafePointer(octets?.pointee.data)
        let end = ptr!.advanced(by: Int(octets!.pointee.length))
      
        var type: Int32 = 0
        var xclass: Int32 = 0
        var length: Int = 0
      
        ASN1_get_object(&ptr, &length, &type, &xclass, ptr!.distance(to: end))
        guard type == V_ASN1_SET else {
            status = .unexpectedASN1Type
            return
        }

        // 1
        while ptr! < end {
            // 2
            ASN1_get_object(&ptr, &length, &type, &xclass, ptr!.distance(to: end))
            guard type == V_ASN1_SEQUENCE else {
                status = .unexpectedASN1Type
                return
            }
            
        
            // 3 type
            guard let attributeType = readASN1Integer(ptr: &ptr, maxLength: length) else {
              status = .unexpectedASN1Type
              return
            }
            print("shark-IAP, ", attributeType)
            
            // 4 version
            guard let _ = readASN1Integer(ptr: &ptr, maxLength: ptr!.distance(to: end)) else {
                print("shark-IAP, 3")
              status = .unexpectedASN1Type
              return
            }
            
            // 5 value
            ASN1_get_object(&ptr, &length, &type, &xclass, ptr!.distance(to: end))
            guard type == V_ASN1_OCTET_STRING else {
                print("shark-IAP, 4")
              status = .unexpectedASN1Type
              return
            }
            
            switch attributeType {
                case 2: // The bundle identifier
                    var stringStartPtr = ptr
                    bundleIdString = readASN1String(ptr: &stringStartPtr, maxLength: length)
                    bundleIdData = readASN1Data(ptr: ptr!, length: length)
              
                case 3: // Bundle version
                    var stringStartPtr = ptr
                    bundleVersionString = readASN1String(ptr: &stringStartPtr, maxLength: length)
              
                case 4: // Opaque value
                    let dataStartPtr = ptr!
                    opaqueData = readASN1Data(ptr: dataStartPtr, length: length)
              
                case 5: // Computed GUID (SHA-1 Hash)
                    let dataStartPtr = ptr!
                    hashData = readASN1Data(ptr: dataStartPtr, length: length)
              
                case 12: // Receipt Creation Date
                    var dateStartPtr = ptr
                    receiptCreationDate = readASN1Date(ptr: &dateStartPtr, maxLength: length)
              
                case 17: // IAP Receipt
                    var iapStartPtr = ptr
                    let parsedReceipt = IAPReceipt(with: &iapStartPtr, payloadLength: length)
                    if let newReceipt = parsedReceipt {
                        inAppReceipts.append(newReceipt)
                    }
              
                case 19: // Original App Version
                    var stringStartPtr = ptr
                    originalAppVersion = readASN1String(ptr: &stringStartPtr, maxLength: length)
              
                case 21: // Expiration Date
                    var dateStartPtr = ptr
                    expirationDate = readASN1Date(ptr: &dateStartPtr, maxLength: length)
              
                default: // Ignore other attributes in receipt
                    print("Not processing attribute type: \(attributeType)")
            }
            
            // Advance pointer to the next item
            ptr = ptr!.advanced(by: length)
        } // end while
    }



func readASN1Integer(ptr: inout UnsafePointer<UInt8>?, maxLength: Int) -> Int? {
    var type: Int32 = 0
    var xclass: Int32 = 0
    var length: Int = 0
  
    ASN1_get_object(&ptr, &length, &type, &xclass, maxLength)
    
    guard type == V_ASN1_INTEGER else {
        print("shark-IAP no!", type)
        return nil
    }
   
//     let integerObject = c2i_ASN1_INTEGER(nil, &ptr, length)
    let integerObject = d2i_ASN1_UINTEGER(nil, &ptr, length)
    let intValue = ASN1_INTEGER_get(integerObject)
    ASN1_INTEGER_free(integerObject)
  
    
    return intValue
}

我得到了这些打印输出。我怀疑函数 readASN1Integer 是错误的。也许 c2i_ASN1_INTEGER 会很好,但在 OpenSSL 1.1* 中已弃用,而是使用 d2i_ASN1_UINTEGER 。并且d2i_ASN1_UINTEGER需要传递(标识符+长度/八位字节+内容),而不仅仅是内容。在ASN1_get_object中,指针改变了位置。所以 d2i_ASN1_UINTEGER 读取错误。第一个 readASN1Integer 会导致第二个 readASN1Integer 引发错误。

shark-IAP,  0
shark-IAP no! 8
shark-IAP, 3
shark-IAP, bundleVersionString nil
shark-IAP, expirationData nil
shark-IAP,  0
shark-IAP no! 8
shark-IAP, 3
shark-IAP, bundleVersionString nil
shark-IAP, expirationData nil

但我不知道如何调整代码以适应 d2i_ASN1_UINTEGER。感谢您的帮助!


Stackoverflow是一个镇压魔鬼的地方。

我找到了解决方案。我将 readASN1Integer 修改为这个

func readASN1Integer(ptr: inout UnsafePointer<UInt8>?, maxLength: Int) -> Int? {
    var type: Int32 = 0
    var xclass: Int32 = 0
    var length: Int = 0
    let save_ptr = ptr
    ASN1_get_object(&ptr, &length, &type, &xclass, maxLength)

    guard type == V_ASN1_INTEGER else {
        return nil
    }
   
//     let integerObject = c2i_ASN1_INTEGER(nil, &ptr, length)
    ptr = save_ptr
    let integerObject = d2i_ASN1_UINTEGER(nil, &ptr, maxLength)
    let intValue = ASN1_INTEGER_get(integerObject)
    ASN1_INTEGER_free(integerObject)
  
    
    return intValue
}
  1. 由于指针位置改变了,需要将其设置回来,这就是为什么 save_ptr 来了(引用自Openssl 1.1.0 中的 c2i_ASN1_INTEGER 函数 https://stackoverflow.com/questions/56388735/c2i-asn1-integer-function-in-openssl-1-1-0)
  2. d2i_ASN1_UINTEGER(nil, &ptr, length) 更改为 d2i_ASN1_UINTEGER(nil, &ptr, maxLength)。对于每个位置,包括在 readReceipt 中,长度应为 maxLength 或 ptr!.distance(to: end)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么无法读取收据数据以进行设备上验证 的相关文章

  • 弱变量中间为零

    弱变量什么时候变为零 weak var backgroundNode SKSpriteNode texture SKTexture image initialBackgroundImage backgroundNode position C
  • Swift 中的 viewWillLayoutSubviews

    我正在尝试翻译SKScene scene GameScene sceneWithSize skView bounds size 进入 swift 但我收到错误 sceneWithSize 不可用 使用对象构造 SKScene size 我在
  • 来自索引范围 Swift 的新数组

    我怎样才能做这样的事情 从数组中取出前 n 个元素 newNumbers numbers 0 n 目前出现以下错误 error could not find an overload for subscript that accepts th
  • 进入后台时 Alamofire 请求卡住?

    我正在使用 Alamofire 调用 Web 服务 该服务需要相当长的时间才能加载 如果应用程序进入后台 当我返回应用程序时 我会被加载程序卡住 我想这是因为调用永远不会向我的完成处理程序返回任何内容 我该如何解决这个问题 您可以使用后台抓
  • iOS WKWebView 处理文件下载

    我面临以下问题 在 Web 界面中 文件下载是通过锚标记触发的 如下所示 a href bla blabla a 虽然 Safari 浏览器可以处理此请求并打开一个对话框来处理文件 但 WKWebView 将此视为普通链接并且不对其执行任何
  • 如何在 Swift 中使用 CoreBluetooth 更新 BLE 设备的电池电量?

    func peripheral peripheral CBPeripheral didDiscoverCharacteristicsFor service CBService error Error for c in service cha
  • 如何使用 SwiftUI 获取多个屏幕上的键盘高度并移动按钮

    以下代码获取键盘显示时的键盘高度 并将按钮移动键盘高度 在转换源 ContentView 和转换目标 SecibdContentView 处以相同的方式执行此移动 但按钮在转换目标处不移动 如何使按钮在多个屏幕上移动相同 import Sw
  • 如何使用 Swift 将“完成”按钮添加到 iOS 中的数字键盘?

    它在默认键盘上工作得很好 但我无法让它在数字键盘上工作 有任何想法吗 据我所知 你不能在键盘部分添加 完成 按钮 你应该添加一个inputAccessoryView to the UITextField or UITextView 如果这就
  • 如何在我的 Android 应用程序中实现应用内购买?

    如何在我的 Android 应用程序中实现应用内购买 我提到 http developer android com guide market billing billing integrate html billing service ht
  • NSURLCache 不缓存

    我正在使用 Xcode 6 1 6A1030 iOS7 和 iOS8 模拟器 NSURLCache 似乎没有缓存任何东西 我使用 Cache Control 标头 我的服务器返回带有 max age 6000 的 Cache Control
  • 使用 BGTaskScheduler 进行后台获取与调试模拟完美配合,但在实践中却不起作用

    我在 appDelegate 的 didFinishLaunchingWithOptions 中注册后台获取任务 BGTaskScheduler shared register forTaskWithIdentifier Backgroun
  • Swift:协议、结构、类

    我开始学习 Swift 语言 但在理解协议 结构和类方面遇到了困难 我来自 Android 方面的编程 所以我相信 Swift 协议基本上是 Java 接口 其中每一个的正确用例是什么 这些类比并不 完全 正确 但这就是我所理解的要点 是的
  • XCode 7 中的 AWSS3TransferManagerUploadRequest

    我今天升级到 Xcode 7 Swift 2 0 我的项目正在使用 CocoaPods 我正在 POD 文件中导入所有与 AWS 相关的文件 我已经设置了桥接标头 并导入了 Amazon 告诉我的所有文件 在升级到 Swift 2 0 之前
  • iOS Swift 和 reloadRowsAtIndexPaths 编译错误

    我与 xCode Swift 陷入僵局并刷新 UITableView 的单行 这条线有效 self tableView reloadData 而这条线没有 self tableView reloadRowsAtIndexPaths curr
  • 如何观察UserDefaults的变化?

    我有一个 ObservedObject在我看来 struct HomeView View ObservedObject var station Station var body some View Text self station sta
  • 具有动态警报正文的快速本地通知

    所以我可以创建一个像这样的本地通知 var localNotification UILocalNotification localNotification fireDate NSDate timeIntervalSinceNow 7 loc
  • 如何向 UIView 添加大小调整手柄?

    我试图根据用户请求在运行时动态创建视图 UIImageView 和 UITextView 然后允许用户移动它们并调整它们的大小 除了调整大小之外 我的一切都工作得很好 我尝试使用捏合手势识别器 但发现它对于我想要的东西来说太笨拙了 因此 我
  • 沙盒尝试恢复消耗性 IAP

    我一直在尝试在 iOS 上测试一些消耗性 IAP 但遇到了一个奇怪的错误 弹出一条警报 其中包含以下文本 此应用内购买已被购买 它将恢复为 自由的 环境 沙盒 我已经检查过 并且确定我的 IAP 可以在 iTunesConnect 中使用
  • iOS 防止计时器 UILabel 在数字变化时“晃动”

    我有一个UILabel它以以下格式显示计时器的输出MM ss SS 分 秒 厘秒 但是随着厘秒宽度的变化 它从左向右 摇动 例如 11 比 33 窄 有什么办法可以减轻这种情况吗 我尝试过将其居中 给它固定的宽度 但它们似乎没有帮助 从iO
  • AWS S3 公共对象与私有对象?

    回到 S3 我的存储桶中有图像的 URL 我将在我的应用程序中呈现这些图像 但它们被设置为私有 当我尝试单击该链接时 它显示 访问被拒绝 当我将链接的设置更改为公共时 它会通过 但是我读到公共访问并不是最安全的事情 所以这本质上是一个由两部

随机推荐