本文旨在深入探讨华为鸿蒙HarmonyOS Next系统(截止目前API12)的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。
在当今蓬勃发展的游戏产业中,游戏公平性成为了玩家体验的核心要素之一。然而,外挂和作弊行为却如影随形,严重破坏了游戏的公平竞争环境。华为鸿蒙HarmonyOS Next凭借其强大的安全特性,特别是Device Certificate Kit,为游戏开发者提供了有力的武器来构建高效的防作弊系统。
一、场景描述
在多人在线游戏中,作弊者常常使用外挂来获取不正当优势,如自动瞄准、加速、透视等功能,这不仅损害了普通玩家的利益,也影响了游戏的可玩性和寿命。同时,模拟器和云手机等非真实设备的使用也为作弊提供了便利,因为它们可以更容易地运行作弊程序且逃避一些常规的检测机制。因此,构建一个能够准确识别外挂并阻止非真实设备运行游戏的防作弊系统至关重要。
二、架构设计
为了实现游戏防作弊的目标,我们以Device Certificate Kit的真实性证明为基础,与Universal Keystore Kit紧密结合,构建了一个全面的验证体系。
- Device Certificate Kit
- 负责生成和管理设备证书链,其中包含设备的公钥和相关身份信息。在游戏启动时,设备向服务器发送证书链,用于验证设备的真实性和身份唯一性。
- 通过证书链中的密钥证明证书,确保设备公钥的来源可靠,并且可以追溯到可信的根证书。
- Universal Keystore Kit
- 安全地存储设备的私钥,确保私钥不被非法获取。在需要进行签名等操作时,为应用提供安全的私钥访问环境。
- 与Device Certificate Kit协同工作,保证密钥对的完整性和安全性,防止密钥被篡改或替换。
三、实现步骤
- 实现应用ID和设备公钥的绑定,并通过证书链进行验证
- 游戏应用在安装时,为每个应用实例生成唯一的应用ID。同时,通过Device Certificate Kit生成设备公私钥对,并将设备公钥与应用ID进行绑定。示例代码如下:
import {
huks } from '@kit.UniversalKeystoreKit';
import {
BusinessError } from '@kit.BasicServicesKit';
let appId = 'your_game_app_id';
let keyAlias = 'game_key';
function GetGenerateProperties() {
let properties: Array<huks.HuksParam> = new Array();
let index = 0;
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_ECC
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN |
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256
}
return properties;
}
async function GenerateKey(keyAlias: string) {
let genProperties = GetGenerateProperties();
let options: huks.HuksOptions = {
properties: genProperties
}
await huks.generateKeyItem(keyAlias, options)
.then(() => {
console.info(`promise: generate Key success.`);
}).catch((err: BusinessError) => {
console.error(`promise: generate Key failed, error: ` + err.message);
})
}
GenerateKey(keyAlias);
// 假设这里有将应用ID和设备公钥绑定的逻辑(实际应用中可能需要与游戏服务器交互来记录绑定关系)
bindAppIdAndPublicKey(appId, getPublicKeyFromKeyAlias(keyAlias));
- 当游戏启动并连接服务器时,设备将证书链发送给服务器。服务器首先验证证书链的完整性和有效性,检查证书是否过期、签名是否正确等。然后,服务器根据证书中的信息获取设备公钥,并验证其与应用ID的绑定关系是否正确。
- 针对不同攻击场景设计多层验证机制,阻止模拟器、云手机等非真实设备
- 模拟器检测:通过Device Certificate Kit的硬件级证书链验证,检查设备的硬件特征是否与真实设备一致。模拟器通常无法完全模拟真实设备的硬件环境,因此在证书链验证过程中可能会暴露其非真实设备的特征。例如,真实设备的证书链可能包含特定的硬件标识信息,而模拟器无法提供或伪造这些信息。
- 云手机识别:对于云手机等虚拟设备,除了证书链验证外,还可以结合网络特征分析等技术。云手机通常具有与真实移动设备不同的网络延迟、IP地址分配模式等特征。通过在服务器端对设备的网络连接进行分析,判断其是否为云手机环境。如果检测到疑似云手机的网络特征,服务器可以进一步要求设备提供额外的证明或直接拒绝其连接。
- 运行环境检测:在游戏运行过程中,持续监测游戏运行环境的完整性。例如,检查游戏进程是否被注入了外挂程序、内存中是否存在可疑的代码修改等。可以通过定期检查游戏关键模块的哈希值、监控系统调用等方式来实现。如果发现运行环境被篡改,立即采取相应措施,如暂停游戏、封禁账号等。
- 在服务器端进行证书链和挑战值的验证
- 证书链验证:服务器收到设备发送的证书链后,使用Device Certificate Kit的相关API进行详细验证。包括检查证书链的长度是否符合预期、证书的颁发机构是否可信、证书的有效期是否有效等。示例代码如下:
import {
cert } from '@kit.DeviceCertificateKit';
import {
BusinessError } from '@kit.BasicServicesKit';
import {
util } from '@kit.ArkTS';
// 假设这是设备证书链数据(实际应用中需从设备获取)
let deviceCertChainData = "-----BEGIN CERTIFICATE-----\n" +
"MIID6jCCAtKgAwIBAgIIIM2q/TmRoLcwDQYJKoZIhvcNAQELBQAwWjELMAkGA1\n" +
"UEBhMCRU4xEDAOBgNVBAgTB0VuZ2xhbmQxDzANBgNVBAcTBkxvbmRvbjEMMA\n" +
"oGA1UEChMDdHMyMQwwCgYDVQQLEwN0czIxDDAKBgNVBAMTA3RzMjAeFw0yMzEy\n" +
"MDUwNzM5MDBaFw0yNDEwMzEyMzU5MDBaMGExCzAJBgNVBAYTAkNOMRAwDgYDVQQI\n" +
"EwdKaWFuZ3N1MRAwDgYDVQQHEwdOYW5qaW5nMQwwCgYDVQQKEwN0czMxDDAKBg\n" +
"NVBAsTA3RzMzESMBAGA1UEAxMJMTI3LjAuMC4xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" +
"MIIBCgKCAQEAtt+2QxUevbolYLp51QGcUpageI4fwGLIqv4fj4aoVnHFOOBqVOVpfCLR\n" +
"p26LFV/F8ebwPyo8YEBKSwXzMD1573rMSbaH9BalscH5lZYAbetXoio6YRvzlcmc\n" +
"rVvLBNMeVnxY86xHpo0MTNyP7W024rZsxWO98xFQVdoiaBC+7+midlisx2Y+7u0\n" +
"zT9GjeUP6JLdLFUZJKUPSTK3jVzw9v1eZQZKYoNfU6vFMd6ndtwW6qEnwpzmmX\n" +
"/UT+p5ThAMH593zszlz330nTSXBjIsGkyvOz9gSB0Z0LAuJj06XUNhGL5xKJYKbdI3\n" +
"8MFQFJKvRHfgTAvVsvAvpBUM2DuBKwIDAQABo4GsMIGpMAkGA1UdEwQCMAA\n" +
"wHQYDVR0OBBYEFDfsHTMZwoA6eaDFlBUyDpka+sYtMAsGA1UdDwQEAwID+DAnBgN\n" +
"VHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMEMBQGA1UdEQQNM\n" +
"AuCCTEyNy4wLjAuMTARBglghkgBhvhCAQEEBAMCBkAwHgYJYIZIAYb4QgENBBEWD3hj\n" +
"YSBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAQEAp5vTvXrt8ZpgRJVtzv9ss0lJ\n" +
"izp1fJf+ft5cDXrs7TSD5oHrSW2vk/ZieIMhexU4LFwhs4OE7jK6pgI48Dseqxx7\n" +
"B/KktxhVMJUmVXd9Ayjp6f+BtZlIk0cArPuoXToXjsV8caTGBXHRdzxpAk/w9syc\n" +
"GYrbH9TrdNMuTizOb+k268oKXUageZNxHmd7YvOXkcNgrd29jzwXKDYYiUa1DI\n" +
"SzDnYaJOgPt0B/5izhoWNK7GhJDy9KEuLURcTSWFysbbnljwO9INPT9MmlS83PdAg\n" +
"NiS8VXF4pce1W9U5jH7d7k0JDVSXybebe1iPFphsZpYM/NE+jap+mPy1nTCbf9g==\n" +
"-----END CERTIFICATE-----\n" +
"-----BEGIN CERTIFICATE-----\n" +
"MIIC0zCCAoWgAwIBAgIIXpLoPpQVWnkwBQYDK2VwMFoxCzAJBgNVBAYTAkV\n" +
"OMRAwDgYDVQQIEwdFbmdsYW5kMQ8wDQYDVQQHEwZMb25kb24xDDAKBgNVBAoT\n" +
"A3RzMTEMMAoGA1UECxMDdHMxMQwwCgYDVQQDEwN0czEwHhcNMjMxMjA1MDczNzA\n" +
"wWhcNMjQwOTAxMjM1OTAwWjBaMQswCQYDVQQGEwJFTjEQMA4GA1UECBMHRW5nbGFu\n" +
"ZDEPMA0GA1UEBxMGTG9uZG9uMQwwCgYDVQQKEwN0czIxDDAKBgNVBAsTA3RzMjEMM\n" +
"AoGA1UEAxMDdHMyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtt+2QxUev\n" +
"bolYLp51QGcUpageI4fwGLIqv4fj4aoVnHFOOBqVOVpfCLRp26LFV/F8ebwPyo8YEBK\n" +
"SwXzMD1573rMSbaH9BalscH5lZYAbetXoio6YRvzlcmcrVvLBNMeVnxY86xHpo0\n" +
"MNTyP7W024rZsxWO98xFQVdoiaBC+7+midlisx2Y+7u0jzT9GjeUP6JLdLFUZJKUP\n" +
"STK3jVzw9v1eZQZKYoNfU6vFMd6ndtwW6qEnwpzmmX/UT+p5ThAMH593zszlz\n" +
"330nTSXBjIsGkyvOz9gSB0Z0LAuJj06XUNhGL5xKJYKbdI38MFQFJKvRHfgTAvVsvAv\n" +
"pBUM2DuBKwIDAQABo28wbTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBQ3\n" +
"7B0zGcKAOnmgxZQVMg6ZGvrGLTALBgNVHQ8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAg\n" +
"AHMB4GCGCGSAGG+EIBDQQRFg94Y2EgY2VydGlmaWNhdGUwBQYDK2VwA0EAuasLBe\n" +
"55YgvFb4wmHeohylc9r8cFGS1LNQ5UcSn3cGqMYf6ehnef16NLuCW6upHCs8Sui4iAMvs\n" +
"uKPWR9dKBA==\n" +
"-----END CERTIFICATE-----\n";
let textEncoder = new util.TextEncoder();
let encodingBlob: cert.EncodingBlob = {
data: textEncoder.encodeInto(deviceCertChainData),
encodingFormat: cert.EncodingFormat.FORMAT_PEM
};
let x509CertChain: cert.X509CertChain = {
} as cert.X509CertChain;
try {
x509CertChain = await cert.createX509CertChain(encodingBlob);
} catch (err) {
let e: BusinessError = err as BusinessError;
console.error(`createX509CertChain failed, errCode: ${
e.code}, errMsg: ${
e.message}`);
}
// 证书链校验数据(假设,实际需根据真实情况配置)
const param: cert.CertChainValidationParameters = {
date: '20231212080000Z',
trustAnchors: [{
CAPubKey: new Uint8Array([0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70,
0x03, 0x21, 0x00, 0xbb, 0x16, 0x9d

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



