【问题标题】:How to generate iOS Application Certificate for Fairplay implementation如何为 Fairplay 实施生成 iOS 应用程序证书
【发布时间】:2017-10-07 08:23:57
【问题描述】:

我们正在开发一款 iOS 音乐应用。对于内容保护,我们将使用 Apple 的 fairplay DRM 系统。我正在关注苹果的 HDLCalog 示例以供参考。在实现时我注意到AssetLoaderDelegate 类中有两个方法需要实现。如果有人可以帮助我了解如何实现以下两种方法,我将不胜感激。提前致谢。

1.)

public func fetchApplicationCertificate() -> Data? {

    // MARK: ADAPT: YOU MUST IMPLEMENT THIS METHOD.
    let applicationCertificate: Data? = nil

    if applicationCertificate == nil {
        fatalError("No certificate being returned by \(#function)!")
    }        


    return applicationCertificate
}

2.)

public func contentKeyFromKeyServerModuleWithSPCData(spcData: Data, assetIDString: String) -> Data? {

    // MARK: ADAPT: YOU MUST IMPLEMENT THIS METHOD.
    let ckcData: Data? = nil

    if ckcData == nil {
        fatalError("No CKC being returned by \(#function)!")
    }


    return ckcData
}

我在这里更新我们设法实现了 fetchApplicationCertificate() 方法。现在我们面临着生成 ckc 数据的问题

【问题讨论】:

  • 你接受了吗?

标签: drm fairplay


【解决方案1】:

申请证书

应用程序证书是您在 Apple 注册 Fairplay 时创建的 DER 格式的公共证书。这应该放置在 Web 服务器上(AWS S3 是理想的)并在每个应用程序会话中检索一次。

CKC 数据

这仅适用于您使用 Fairplay 许可服务的任何人。他们将指定一个接口,用于将 SPC 数据从您的客户端发送到他们的许可证服务器。这可以是 JSON over REST、SOAP、MQ 或他们选择的任何东西。您必须向他们询问 API 规范。

【讨论】:

    【解决方案2】:

    第 1 步:

     let queue                       = DispatchQueue(label: "fairplay.resourcerequests", attributes: [])
    
        let url                         = URL(string: videoUrl)!   // Streaming the video from this URL
    
        let videoAsset                  = AVURLAsset(url: url, options: nil)
        videoAsset.resourceLoader.setDelegate(self, queue: queue)
    

    第 2 步:

    extension PlayerViewController : AVAssetResourceLoaderDelegate{
    
    func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
    
        let url = loadingRequest.request.url
        var error: NSError?
        print("Player Delegate Method")
        print("URL Schema Is  \(url?.scheme! ?? "")")
        if((url?.scheme ?? "") == "skd"),
            let assetString = url!.host, let assetID = assetString.data(using: String.Encoding.utf8) // Get the URI for the content key.{guard let fetchedCertificate = self.fetchedCertificate else { return false} // Get the application certificate from the server.
    
                let requestedBytes = try loadingRequest.streamingContentKeyRequestData(forApp: fetchedCertificate, contentIdentifier: assetID, options: nil)
    
    
                do{
    
                    print("Online Video Streaming Going On")
    
                    let responseData = try contentKeyFromKeyServerModuleWithRequestData(requestedBytes, assetString: assetString, expiryDuration: expiryDuration)
                    guard let dataRequest = loadingRequest.dataRequest else {
                        //                        print("Failed to get instance of AVAssetResourceLoadingDataRequest (loadingRequest.dataRequest).")
                        return false
                    }
    
                    dataRequest.respond(with: responseData)
    
                    if let infoRequest = loadingRequest.contentInformationRequest,
                        expiryDuration != 0.0
                    {
    
                        infoRequest.renewalDate = Date(timeIntervalSinceNow: expiryDuration)
    
                        infoRequest.contentType = "application/octet-stream"
                        infoRequest.contentLength = Int64(responseData.count)
                        infoRequest.isByteRangeAccessSupported = false
                    }
    
                    // Treat the processing of the requested resource as complete.
                    loadingRequest.finishLoading()
    
                    // The resource request has been handled regardless of whether the server returned an error.
                    return true
    
                }catch let e as NSError
                {
                    error = e
                    //                    print("content key  error\(error)")
                }
            }catch let e as NSError {
                error = e
                // Resource loading failed with an error.
                //                print("streamingContentKeyRequestDataForApp failure: \(error.localizedDescription)")
    
            }}}
    

    第 3 步:

    func contentKeyFromKeyServerModuleWithRequestData(_ requestBytes: Data, assetString: String, expiryDuration: TimeInterval?=0.0, persitent:Bool?=true) throws -> Data {
        // If the key server provided a CKC, return it.
        //        if let ckcData = ckcData {
        //            return ckcData
        //        }
        //        else
        //        {
        let base64Decoded = requestBytes.base64EncodedString(options: NSData.Base64EncodingOptions())
    
        //MARK: Get Fairplay license for the current user
        NSLog("using ticket: %@", streamTicket )
        if let returnData:Data = mediaMakerDRMLicenseCall(base64Decoded, ticket: streamTicket)
        {
            if returnData.count <= 0
            {
    
                //                 Otherwise, the CKC was not provided by key server. Fail with bogus error.
                //                 Generate an error describing the failure.
    
                throw NSError(domain: "com.example.apple-samplecode", code: 0, userInfo: [
                    NSLocalizedDescriptionKey: NSLocalizedString("Item cannot be played.", comment: "Item cannot be played."),
                    NSLocalizedFailureReasonErrorKey: NSLocalizedString("Could not get the content key from the Key Server.", comment: "Failure to successfully send the SPC to the Key Server and get the content key from the returned Content Key Context (CKC) message.")
                    ])
            }
            else
            {
                return returnData
            }
        }
        //}
    }
    

    第 4 步:

    func mediaMakerDRMLicenseCall(_ playerSPC : String, ticket : String) -> Data{// API Call to fetch license from client server}
    

    【讨论】:

    • 感谢您的解决方案。能否请您添加其他剩余代码?
    • @AmritTiwari 你还想要什么?
    • 我有很多困惑,所以我们可以谈谈其他聊天应用程序吗?或者您可以简单地在 tiwariammit@gmail.com 上给我发短信。这将非常感谢我。
    猜你喜欢
    • 2022-01-01
    • 2019-07-15
    • 1970-01-01
    • 1970-01-01
    • 2020-05-25
    • 1970-01-01
    • 2016-09-17
    • 2020-12-03
    • 2014-06-26
    相关资源
    最近更新 更多