如何为我的云函数服务器创建"challenge"



我正在尝试使用苹果的新DeviceCheckAPI来验证我的应用程序中的网络调用实际上来自我的应用程序的未妥协版本。

在成功验证密钥的认证后,您的服务器可以要求应用程序对任何或所有未来的服务器申明其合法性请求。应用程序通过签名请求来实现这一点。首先,在应用程序中从服务器获得唯一的一次性挑战。你用a这里的挑战,就像证明,以避免重放攻击。然后将挑战与服务器请求合并以创建散列:

let challenge = <# A string from your server #>
let request = [ "action": "getGameLevel",
"levelId": "1234",
"challenge": challenge ]
guard let clientData = try? JSONEncoder().encode(request) else { return }
let clientDataHash = Data(SHA256.hash(data: clientData))

使用这个散列和您之前生成的键标识符来方法创建断言对象generateAssertion (_: clientDataHash: completionHandler)方法:

service.generateAssertion(keyId, clientDataHash: clientDataHash) { assertion, error in
guard error == nil else { /* Handle the error. */ }
// Send the assertion and request to your server.
}

我正试图将此断言功能添加到我的Swift函数,这是一个调用Firebase Cloud Function的辅助函数。

我希望断言对象作为data传递给云函数,以验证云函数是从我的应用程序的未受损害的版本调用:

func callFunction(name: String, data: [String:Any?], completion: @escaping (HTTPSCallableResult?, Error?)->()){
var functions = Functions.functions()
functions.httpsCallable(name).call(data){ (result, error) in
completion(result, error)
}
}

(下面使用callFunction()的示例):

let data: [String:Any?] = [
"gameId": self.game?.id,
"answer": answer,
"answeredAt": Date().millisecondsSince1970
]
callFunction(name: "answerQuestion", data: data){ res, err in
print("Submitted answer: (res.debugDescription) | Error: (err)")
if let err = err {
self.game?.question?.state = .initial
}
}

要生成要发送到服务器的断言对象(云函数),需要生成上面所述的challenge。然而,我不确定如何产生这个挑战。

苹果说它应该是"来自你的服务器的字符串"。但我不确定字符串应该是什么。它是基于用户UID的动态字符串吗?一个base64编码的用户ID字符串和一个静态秘密字符串?当我试图从服务器检索这个字符串时,用户将能够读取它,因为他们可以看到传入的网络JSON(我假设我会检索字符串与云函数调用)-所以它似乎毫无意义,因为它不再是一个秘密字符串了吗?

知道我怎样才能使挑战安全地工作吗?

挑战的重点是避免重放攻击,所以它可以是任何随机字符串。UUID就可以了。不需要保密。

将挑战字符串与事务数据组合并生成散列。将哈希值发送给generateAssertion并接收断言对象。然后将其与请求数据一起发送到服务器。

现在,您的服务器可以将收到的请求数据与挑战(它知道,因为它最初将其发送给客户端)结合起来,生成相同的哈希并验证认证。

服务器端认证文章提供了有关挑战数据的详细信息:

提供挑战

每次你的应用程序需要向你的服务器传递认证数据时,应用程序首先向服务器请求一个唯一的、一次性的挑战。App test将这个挑战集成到它提供的对象中,你的应用程序将这些对象发送回服务器进行验证。这使得攻击者更难实现重放攻击。

当请求挑战时,为您的应用程序提供一个随机数据值,并记住在验证客户端发送的相应证明或断言对象时使用的值。如何使用挑战数据取决于需要验证的对象的类型。

最新更新