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

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(使用前将#替换为@)

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

随机推荐