是否可以在允许 Adobe AIR 客户端连接到服务器之前对其进行验证?
Is it possible to validate a Adobe AIR Client before allowing it to connect to a Server?
假设我在 AS3 中使用 Adobe AIR 创建客户端。我知道如果有人尝试反编译它,更改它的代码,重新编译它,扩展它的功能来做任何 he/she 喜欢的事情,然后用它连接到服务器,就好像它是原始文件。
在为客户端提供会话 ID 之前,服务器会将提交的客户端文件的字节与存储在服务器内存中的客户端文件的原始字节进行比较,会话 ID 是进行通信所必需且有效的与服务器
如果您想知道,这显然可以通过 TCP 完成。此外,客户端将安装在一台机器上并从那里 运行。
文件将在连接时提交。
服务器会测量发送的字节数,并将其与我之前谈到的内存中的服务器字节副本进行比较。显然,如果字节数大于或小于服务器内存中的原始客户端,连接将被忽略,什么也不会发生。
如果数量完全相同,那么它将比较字节序列是否完全相同。如果不是,同样,连接将被忽略等。
如果全部签出,服务器将为该特定客户端生成一个会话 ID,并将其发送出去供客户端捕获,并且必须与 any 消息一起发送到服务器。
如果服务器没有收到任何带有客户端消息的会话 ID,那么它将忽略该消息并取消连接。
但黑客可以直接进入客户端并让它写入包含在未修改文件中的相同字节序列,以欺骗服务器相信它是真实的。
所以我的问题是,我该怎么做才能确保用于连接到服务器的客户端的字节序列确实是用于连接到的客户端服务器?
不可能完全保护协议,但很有可能确保任何头脑正常的人都不会冒险解开保护层。要到达那里,您需要完成几个步骤:
步骤1:确保每条client->server消息绝对全局唯一。每条消息都应包含几个参数,例如:
- 用户id
- client session id(客户端握手时随机生成)
- server session id(由服务器随机生成)
- timestamp - 增加每个客户端->服务器消息的整数值,以服务器端 unix 时间戳
开头
- index - 增加每个客户端->服务器消息的整数值,从 0
开始
收到消息后,服务器必须验证这些参数以切断任何无效消息 - 它们不是来自最新握手的正版客户端。
第 2 步:签署消息。二进制消息数据的 MD5 或 SHA1 和 一些密钥。当然应该有一个不随消息一起发送的密钥。服务器(也知道该密钥)必须验证签名。您可以使用两个签名使其更安全:一个是根据标准参数(应包括上面列出的所有参数)和密钥计算的,另一个是根据消息的二进制表示(包括第一个签名)计算的,并且另一个密钥。
步骤 3:保护密钥和签名算法。当然,任何拥有反编译器的人都可以从您的应用程序中提取签名算法并重现它。你不会想要的。使用混淆器工具,例如 SecureSWF 来保护这些对您的消息进行签名的代码片段。不要以明显的形式保存密钥,在需要时构建它们,在不需要时立即销毁它们。使用 ByteArray class 可能是个好主意,因为它有 ByteArray.clear() 方法可以完全擦除内存中的内容。
第 4 步:加入一些偏执狂。在签署客户端-> 服务器消息之前进行一些额外的检查。您可以专门调用异常来检索 Error.getStackTrace() 以检查谁在调用。您可以检查环境中的某些 class 定义,并为此构建几个虚拟 classes。如果显示列表层次结构正确,您可以检查阶段。当然,不要以普通形式保留您在那里使用的任何字符串文字。当然还要严密保护以上所有内容。
假设我在 AS3 中使用 Adobe AIR 创建客户端。我知道如果有人尝试反编译它,更改它的代码,重新编译它,扩展它的功能来做任何 he/she 喜欢的事情,然后用它连接到服务器,就好像它是原始文件。
在为客户端提供会话 ID 之前,服务器会将提交的客户端文件的字节与存储在服务器内存中的客户端文件的原始字节进行比较,会话 ID 是进行通信所必需且有效的与服务器
如果您想知道,这显然可以通过 TCP 完成。此外,客户端将安装在一台机器上并从那里 运行。
文件将在连接时提交。
服务器会测量发送的字节数,并将其与我之前谈到的内存中的服务器字节副本进行比较。显然,如果字节数大于或小于服务器内存中的原始客户端,连接将被忽略,什么也不会发生。
如果数量完全相同,那么它将比较字节序列是否完全相同。如果不是,同样,连接将被忽略等。
如果全部签出,服务器将为该特定客户端生成一个会话 ID,并将其发送出去供客户端捕获,并且必须与 any 消息一起发送到服务器。
如果服务器没有收到任何带有客户端消息的会话 ID,那么它将忽略该消息并取消连接。
但黑客可以直接进入客户端并让它写入包含在未修改文件中的相同字节序列,以欺骗服务器相信它是真实的。
所以我的问题是,我该怎么做才能确保用于连接到服务器的客户端的字节序列确实是用于连接到的客户端服务器?
不可能完全保护协议,但很有可能确保任何头脑正常的人都不会冒险解开保护层。要到达那里,您需要完成几个步骤:
步骤1:确保每条client->server消息绝对全局唯一。每条消息都应包含几个参数,例如:
- 用户id
- client session id(客户端握手时随机生成)
- server session id(由服务器随机生成)
- timestamp - 增加每个客户端->服务器消息的整数值,以服务器端 unix 时间戳 开头
- index - 增加每个客户端->服务器消息的整数值,从 0 开始
收到消息后,服务器必须验证这些参数以切断任何无效消息 - 它们不是来自最新握手的正版客户端。
第 2 步:签署消息。二进制消息数据的 MD5 或 SHA1 和 一些密钥。当然应该有一个不随消息一起发送的密钥。服务器(也知道该密钥)必须验证签名。您可以使用两个签名使其更安全:一个是根据标准参数(应包括上面列出的所有参数)和密钥计算的,另一个是根据消息的二进制表示(包括第一个签名)计算的,并且另一个密钥。
步骤 3:保护密钥和签名算法。当然,任何拥有反编译器的人都可以从您的应用程序中提取签名算法并重现它。你不会想要的。使用混淆器工具,例如 SecureSWF 来保护这些对您的消息进行签名的代码片段。不要以明显的形式保存密钥,在需要时构建它们,在不需要时立即销毁它们。使用 ByteArray class 可能是个好主意,因为它有 ByteArray.clear() 方法可以完全擦除内存中的内容。
第 4 步:加入一些偏执狂。在签署客户端-> 服务器消息之前进行一些额外的检查。您可以专门调用异常来检索 Error.getStackTrace() 以检查谁在调用。您可以检查环境中的某些 class 定义,并为此构建几个虚拟 classes。如果显示列表层次结构正确,您可以检查阶段。当然,不要以普通形式保留您在那里使用的任何字符串文字。当然还要严密保护以上所有内容。