HarmonyOS Next在游戏防作弊系统中的应用:利用Device Certificate Kit对外挂的智能识别与防护

news/2024/11/14 4:56:57/文章来源:https://www.cnblogs.com/samex/p/18541155

本文旨在深入探讨华为鸿蒙HarmonyOS Next系统(截止目前API12)的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。

在当今蓬勃发展的游戏产业中,游戏公平性成为了玩家体验的核心要素之一。然而,外挂和作弊行为却如影随形,严重破坏了游戏的公平竞争环境。华为鸿蒙HarmonyOS Next凭借其强大的安全特性,特别是Device Certificate Kit,为游戏开发者提供了有力的武器来构建高效的防作弊系统。

一、场景描述

在多人在线游戏中,作弊者常常使用外挂来获取不正当优势,如自动瞄准、加速、透视等功能,这不仅损害了普通玩家的利益,也影响了游戏的可玩性和寿命。同时,模拟器和云手机等非真实设备的使用也为作弊提供了便利,因为它们可以更容易地运行作弊程序且逃避一些常规的检测机制。因此,构建一个能够准确识别外挂并阻止非真实设备运行游戏的防作弊系统至关重要。

二、架构设计

为了实现游戏防作弊的目标,我们以Device Certificate Kit的真实性证明为基础,与Universal Keystore Kit紧密结合,构建了一个全面的验证体系。

  1. Device Certificate Kit
    • 负责生成和管理设备证书链,其中包含设备的公钥和相关身份信息。在游戏启动时,设备向服务器发送证书链,用于验证设备的真实性和身份唯一性。
    • 通过证书链中的密钥证明证书,确保设备公钥的来源可靠,并且可以追溯到可信的根证书。
  2. Universal Keystore Kit
    • 安全地存储设备的私钥,确保私钥不被非法获取。在需要进行签名等操作时,为应用提供安全的私钥访问环境。
    • 与Device Certificate Kit协同工作,保证密钥对的完整性和安全性,防止密钥被篡改或替换。

三、实现步骤

  1. 实现应用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的绑定关系是否正确。
  1. 针对不同攻击场景设计多层验证机制,阻止模拟器、云手机等非真实设备
    • 模拟器检测:通过Device Certificate Kit的硬件级证书链验证,检查设备的硬件特征是否与真实设备一致。模拟器通常无法完全模拟真实设备的硬件环境,因此在证书链验证过程中可能会暴露其非真实设备的特征。例如,真实设备的证书链可能包含特定的硬件标识信息,而模拟器无法提供或伪造这些信息。
    • 云手机识别:对于云手机等虚拟设备,除了证书链验证外,还可以结合网络特征分析等技术。云手机通常具有与真实移动设备不同的网络延迟、IP地址分配模式等特征。通过在服务器端对设备的网络连接进行分析,判断其是否为云手机环境。如果检测到疑似云手机的网络特征,服务器可以进一步要求设备提供额外的证明或直接拒绝其连接。
    • 运行环境检测:在游戏运行过程中,持续监测游戏运行环境的完整性。例如,检查游戏进程是否被注入了外挂程序、内存中是否存在可疑的代码修改等。可以通过定期检查游戏关键模块的哈希值、监控系统调用等方式来实现。如果发现运行环境被篡改,立即采取相应措施,如暂停游戏、封禁账号等。
  2. 在服务器端进行证书链和挑战值的验证
    • 证书链验证:服务器收到设备发送的证书链后,使用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, 0x8f, 0x5c, 0x30, 0xd0, 0xba, 0x8f, 0x37, 0x6e,0x33, 0xaf, 0x6f, 0x23, 0x71, 0x23, 0xa5, 0x49, 0x60, 0x1e, 0xd1, 0x07, 0x4b, 0xc9,0x11, 0x7e, 0x66, 0x01, 0xba, 0x92, 0x52]),CASubject: new Uint8Array([0x30, 0x5a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,0x04, 0x06, 0x13, 0x02, 0x45, 0x4e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04,0x08, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d,0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x06, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x31,0x6c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x74, 0x73, 0x31, 0x31,0x0c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x03, 0x74, 0x73, 0x31, 0x31,0x0c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x03, 0x74, 0x73, 0x31])}]
};try {const validationRes = await x509CertChain.validate(param);console.log('X509CertChain validate success');
} catch (err) {console.error('X509CertChain validate failed');
}
  • 挑战值验证:服务器向设备发送一个一次性的挑战值(challenge),设备使用私钥对挑战值进行签名,并将签名后的结果返回给服务器。服务器使用设备公钥验证签名是否正确。如果签名验证失败,说明设备可能存在作弊行为或者设备身份不真实。示例代码如下:
import { huks } from '@kit.UniversalKeystoreKit';
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { util } from '@kit.ArkTS';// 假设这是从服务器获取的挑战值
let challenge = 'random_challenge_string'; let keyAlias = 'game_key'; async function getPrivateKey() {let options: huks.HuksOptions = {properties: []}try {let key = await huks.getKeyItem(keyAlias, options);return key;} catch (err) {let e: BusinessError = err as BusinessError;console.error(`getPrivateKey failed, error: ` + err.message);}
}let privateKey = await getPrivateKey();async function signChallenge(challenge: string) {let dataToSign = new Uint8Array(textEncoder.encodeInto(challenge).data);let signature = await cryptoFramework.sign({key: privateKey,data: dataToSign});console.log('Signature:', signature.data);return signature;
}let signature = await signChallenge(challenge);// 将签名发送回服务器(这里只是示例,实际通信方式需根据具体情况实现)
sendSignatureToServer(signature);
  • 服务器端验证签名:
import { cert } from '@kit.DeviceCertificateKit';
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { util } from '@kit.ArkTS';// 接收到设备发送的签名后进行校验
async function verifyChallengeSignature(signature: Uint8Array, challenge: string, deviceCert: cert.X509Cert) {try {// 获取证书中的公钥let pubKey = deviceCert.getPublicKey();let dataToVerify = new Uint8Array(textEncoder.encodeInto(challenge).data);let result = await cryptoFramework.verify({key: pubKey,data: dataToVerify,signature: signature});if (result) {console.log('Challenge signature verification succeeded.');return true;} else {console.log('Challenge signature verification failed.');return false;}} catch (error) {let e: BusinessError = error as BusinessError;console.error(`verifyChallengeSignature failed, errCode: ${e.code}, errMsg:${e.message}`);return false;}
}

四、技术亮点

  1. 利用硬件级证书链验证确保设备身份唯一性
    • Device Certificate Kit基于硬件的证书链验证机制,使得每个设备的证书链都与设备的硬件特征紧密绑定。例如,证书链中的某些字段可能包含设备的硬件序列号、芯片标识等信息。在验证过程中,服务器可以通过检查这些硬件相关信息来确保设备身份的唯一性。即使作弊者试图克隆设备或在模拟器中伪造证书链,由于无法获取真实的硬件信息,其伪造的证书链在验证时将无法通过。这种硬件级别的绑定大大提高了设备身份验证的准确性和安全性,有效防止了设备伪造和身份冒用。
  2. 防止数据包抓取、伪造及重放的多重安全机制设计
    • 数据加密传输:利用Device Certificate Kit和Crypto Architecture Kit对游戏数据进行加密传输。在设备与服务器之间的通信中,使用证书中的公钥对数据进行加密,确保数据在传输过程中不被第三方抓取和窃取。只有拥有相应私钥的服务器才能解密并读取数据,这样即使数据包被拦截,攻击者也无法获取其中的内容。
    • 签名验证防止伪造:对于游戏中的关键操作(如角色移动、技能释放、道具使用等),设备使用私钥对操作数据进行签名,然后将签名和数据一起发送给服务器。服务器使用设备公钥验证签名的有效性,如果签名不正确,则认为数据被伪造,拒绝该操作。这种签名机制确保了数据的完整性和真实性,防止作弊者伪造游戏操作指令。
    • 挑战值和时间戳防止重放攻击:通过服务器发送挑战值和记录操作时间戳的方式来防止重放攻击。每次设备向服务器发送操作请求时,服务器会附带一个一次性的挑战值,设备必须对挑战值进行签名并返回。同时,服务器记录每个操作的时间戳,对于在短时间内重复收到的相同签名和操作数据(在合理时间范围外),视为重放攻击并拒绝处理。这样可以有效防止作弊者利用之前截获的合法数据包进行重放攻击,保证游戏操作的时效性和安全性。

五、示例代码

  1. 设备真实性验证核心代码(补充完整流程)
    • 设备端获取证书链并发送给服务器:
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}`);
}// 发送证书链到服务器(这里只是示例,实际通信方式需根据具体情况实现)
sendCertChainToServer(x509CertChain);
  • 服务器端验证证书链(上述已部分展示,补充完整错误处理等):
import { cert } from '@kit.DeviceCertificateKit';
import { BusinessError } from '@kit.BasicServicesKit';// 接收到设备发送的证书链后进行验证
async function verifyDeviceCertChain(certChain: cert.X509CertChain) {// 证书链校验数据(假设,实际需根据真实情况配置)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, 0x8f, 0x5c, 0x30, 0xd0, 0xba, 0x8f, 0x37, 0x6e,0x33, 0xaf, 0x6f, 0x23, 0x71, 0x23, 0xa5, 0x49, 0x60, 0x1e, 0xd1, 0x07, 0x4b, 0xc9,0x11, 0x7e, 0x66, 0x01, 0xba, 0x92, 0x52]),CASubject: new Uint8Array([0x30, 0x5a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,0x04, 0x06, 0x13, 0x02, 0x45, 0x4e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04,0x08, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d,0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x06, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x31,0x0c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x74, 0x73, 0x31, 0x31,0x0c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x03, 0x74, 0x73, 0x31, 0x31,0x0c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x03, 0x74, 0x73, 0x31])}]};try {const validationRes = await certChain.validate(param);if (validationRes) {console.log('X509CertChain validate success');return true;} else {console.log('X509CertChain validate failed');return false;}} catch (err) {console.error('X509CertChain validate failed with error:', err);return false;}
}
  1. 密钥签名核心代码(完整流程)
    • 设备端使用私钥对数据进行签名(补充完整错误处理和数据准备):
import { huks } from '@kit.UniversalKeystoreKit';
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
import { util } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';let keyAlias = 'game_key'; async function getPrivateKey() {let options: huks.HuksOptions = {properties: []}try {let key = await huks.getKeyItem(keyAlias, options);return key;} catch (err) {let e: BusinessError = err as BusinessError;console.error(`getPrivateKey failed, error: ` + err.message);}
}let privateKey = await getPrivateKey();// 假设这是要签名的数据,例如游戏操作数据
let gameOperationData = '{"operation":"move","parameters":{"x":10,"y":20}}'; async function signGameData(data: string) {let dataToSign = new Uint8Array(textEncoder.encodeInto(data).data);try {let signature = await cryptoFramework.sign({key: privateKey,data: dataToSign});console.log('Signature:', signature.data);return signature;} catch (error) {let e: BusinessError = error as BusinessError;console.error(`signGameData failed, errCode: ${e.code}, errMsg:${e.message}`);}
}let signature = await signGameData(gameOperationData);// 将签名和数据一起发送到服务器(这里只是示例,实际通信方式需根据具体情况实现)
sendSignatureAndDataToServer(signature, gameOperationData);
  • 服务器端验证签名(上述已部分展示,补充完整数据获取和处理):
import { cert } from '@kit.DeviceCertificateKit';
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { util } from '@kit.ArkTS';// 接收到设备发送的签名和数据后进行校验
async function verifySignature(signature: Uint8Array, data: string, deviceCert: cert.X509Cert) {try {// 获取证书中的公钥let pubKey = deviceCert.getPublicKey();let dataToVerify = new Uint8Array(textEncoder.encodeInto(data).data);let result = await cryptoFramework.verify({key: pubKey,data: dataToVerify,signature: signature});if (result) {console.log('Signature verification succeeded.');return true;} else {console.log('Signature verification failed.');return false;}} catch (error) {let e: BusinessError = error as BusinessError;console.error(`verifySignature failed, errCode: ${e.code}, errMsg:${e.message}`);return false;}
}
  1. 证书链校验核心代码(完整流程及错误处理优化)
    • 设备端获取并发送证书链(与上述设备真实性验证中获取证书链代码类似,可复用):
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" +
"AoGA1UEAxMDdHMyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" +
"MIIBCgKCAQEAtt+2QxUevbolYLp51QGcUpageI4fwGLIqv4fj4aoVnHFOOBqVOVpfCLRp26LFV/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}`);
}// 发送证书链到服务器(这里只是示例,实际通信方式需根据具体情况实现)
sendCertChainToServer(x509CertChain);
  • 服务器端验证证书链(优化错误处理和结果返回):
import { cert } from '@kit.DeviceCertificateKit';
import { BusinessError } from '@kit.BasicServicesKit';// 接收到设备发送的证书链后进行验证
async function verifyDeviceCertChain(certChain: cert.X509CertChain) {// 证书链校验数据(假设,实际需根据真实情况配置)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, 0x8f, 0x5c, 0x30, 0xd0, 0xba, 0x8f, 0x37, 0x6e,0x33, 0xaf, 0x6f, 0x23, 0x71, 0x23, 0xa5, 0x49, 0x60, 0x1e, 0xd1, 0x07, 0x4b, 0xc9,0x11, 0x7e, 0x66, 0x01, 0xba, 0x92, 0x52]),CASubject: new Uint8Array([0x30, 0x5a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,0x04, 0x06, 0x13, 0x02, 0x45, 0x4e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04,0x08, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d,0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x06, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x31,0x0c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x74, 0x73, 0x31, 0x31,0x0c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x03, 0x74, 0x73, 0x31, 0x31,0x0c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x03, 0x74, 0x73, 0x31])}]};try {const validationRes = await certChain.validate(param);if (validationRes) {console.log('X509CertChain validate success');return true;} else {console.log('X509CertChain validate failed');return false;}} catch (err) {console.error('X509CertChain validate failed with error:', err);return false;}
}

通过以上基于HarmonyOS Next和Device Certificate Kit的游戏防作弊系统设计,我们能够有效地识别和防止外挂及非真实设备的攻击,为游戏玩家提供一个公平、安全的游戏环境。在实际开发中,我们可以根据游戏的具体特点和需求,进一步优化和扩展该防作弊系统,确保游戏的长期健康发展。希望这篇文章能为游戏开发领域的小伙伴们提供一些有价值的参考和思路,让我们一起共同打造一个纯净的游戏世界!如果在实现过程中遇到问题,不要灰心,仔细分析,参考相关文档和示例代码,相信你一定能够攻克难题。加油!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/832136.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docx 生成word报告

# -*- coding: utf-8 -*- import base64 import os from io import BytesIO from docx import Document from docx.shared import Inches, Pt from bs4 import BeautifulSoup from matplotlib import pyplot as plt from wordcloud import WordCloud # 设置全局字体 plt.rcPara…

leetcode算法题-有效的括号(简单)

有效的括号(简单) leetcode:https://leetcode.cn/problems/valid-parentheses/description/ 前言 防止脑袋生锈,做一下leetcode的简单算法题,难得也做不来哈哈。 大佬绕道,小白可看。 题目描述 给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效。 有效字符…

30+企业高管齐聚!医疗器械企业渠道优化与健康增长主题沙龙成功举办

10月29日,深圳医疗器械行业协会携手纷享销客,共同举办了一场以“渠道优化与健康增长”为主题,探索医疗器械企业在新形势下渠道管理及落地实践的沙龙活动。此次活动吸引了33位医疗器械企业的管理层,共同探寻医疗器械企业营销增长的新思路、新渠道与新路径。<活动照片>…

AutoCAD Blockview .net在wpf项目中的问题

之前使用Blockview是遇到平移的问题, 这几天在学习使用CommunityToolkit.MVVM框架来创建用户界面, 当创建GsPreviewCtrl控件时会遇到错误, 导致整个窗体不能显示, 错误信息如下:************** 异常文本 ************** System.InvalidProgramException: 公共语言运行时检…

html`` - function html(str) { return str+111 } 调用方式 - solidjs文档里面发现的

html`` - function html(str) { return str+111 } 调用方式 标签模板字符串Tagged Template Literals 这里是自己实现这个字符串模板,等于函数调用的另一种方式 html(111) html`111`solidjs文档里面发现的 https://www.solidjs.com/guides/getting-started#不使用构建工具----…

模态内重叠优化,简单有效的CLIP微调方法 | BMVC24 Oral

来源:晓飞的算法工程笔记 公众号,转载请注明出处论文: CLIP Adaptation by Intra-modal Overlap Reduction论文地址:https://arxiv.org/abs/2409.11338创新点提出一种基于轻量级适配的新方法,直接在图像空间中减少CLIP中的模态内重叠(IMO)。新特征与任何利用缓存模型的无…

一文了解:如何多纬度阐述数据安全传输问题,部署及解决方案!

企业的业务正常开展依赖安全有序的数据流转,数据传输环节融合在企业生产办公、日常经营、技术研究、战略发展等活动的方方面面。数据是任何企业的命脉,但企业数据在传输过程中仍然面临着监管机制不健全、传输主体涉及面广、网络环境复杂、攻击手段多样、数据泄露引发多米诺骨…

Ftrans文件自动化传输方案:释放双手,让数据流动更自由!

随着企业业务不断扩大发展,数据传输和汇集逐渐成为其业务链中的一个重要环节。在企业内部,一般会存在多台文件存储服务器,基于业务开展需要,存在将不同服务器上的不同数据文件自动化传输到同一台文件存储服务器上的场景需求。当下企业选择较多的文件自动化传输方式如FTP、R…

项目UML图

1.用例图2.类图3.时序图

【Unity】UGUI中ScrollView的设置

UI实现横向滚动展示元素,并可以点击指定项增加元素。UI实现横向滚动展示元素,并可以点击指定项增加元素。 成果展示Scene部分ScrollView的设置此案例取消了纵向的滚动条,可以直接删除对应的Scrollbar,然后取消勾选Scroll Rect中的Vertical属性; MovementType属性选择了Cla…

基于surging的木舟平台如何构建起微服务

一、概述木舟平台分为微服务平台和物联网平台, 上面几篇都是介绍如何通过网络组件接入设备,那么此篇文章就细致介绍下在木舟平台下如何构建微服务。木舟 (Kayak) 是什么?木舟(Kayak)是基于.NET6.0软件环境下的surging微服务引擎进行开发的, 平台包含了微服务和物联网平台。支…

PYCHARM-pycharm工具激活

通过百度网盘分享的文件:pojie.zip 链接:https://pan.baidu.com/s/1FGafhVPF4TwL83u9_3sPUw 提取码:sky1