Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 反黑客系统:减少服务器开销并防止OCR_Node.js_Cryptography_Socket.io_Ocr - Fatal编程技术网

Node.js 反黑客系统:减少服务器开销并防止OCR

Node.js 反黑客系统:减少服务器开销并防止OCR,node.js,cryptography,socket.io,ocr,Node.js,Cryptography,Socket.io,Ocr,注意:我被否决了,因为这个帖子太模糊了。我在下面提供了大量的研究信息。向下滚动答案以查看精确的问题 我正在写一个实时多人纸牌游戏。游戏的所有逻辑都在服务器上。不过,我担心黑客会利用这个游戏。我希望有一个非常强大的保护,因为我希望这是一场付费的锦标赛 一点介绍 这是一个回合制游戏。目标是拿到所有的牌。每个玩家都有一副他们看不到的牌。依次,他们将一张牌放在棋盘的中心,以显示该牌。其中一条规则是,如果出现两张A-A、K-K、9-9类型相同的牌,任何人都可以点击,第一张点击的牌将赢得该组合 工作原理 客

注意:我被否决了,因为这个帖子太模糊了。我在下面提供了大量的研究信息。向下滚动答案以查看精确的问题


我正在写一个实时多人纸牌游戏。游戏的所有逻辑都在服务器上。不过,我担心黑客会利用这个游戏。我希望有一个非常强大的保护,因为我希望这是一场付费的锦标赛

一点介绍 这是一个回合制游戏。目标是拿到所有的牌。每个玩家都有一副他们看不到的牌。依次,他们将一张牌放在棋盘的中心,以显示该牌。其中一条规则是,如果出现两张A-A、K-K、9-9类型相同的牌,任何人都可以点击,第一张点击的牌将赢得该组合

工作原理 客户端接收socket.io卡事件。事件数据包含卡片种类、卡片等级和丢弃它的玩家的id

事件:{等级:王牌,种类:黑桃,玩家ID:3}

当客户端收到该信息时,Phaser将加载相应的sprite图像并将其显示在电路板上

也许你看到了问题所在。对于黑客来说,识别排名相同的两个连续事件很容易,例如:

{等级:A,种类:黑桃,玩家ID:3}

{等级:王牌,种类:红心,玩家ID:4}

看到艾斯了吗,艾斯?这太容易识别了

策略1:精灵的加密 然后,我想也许我会加密精灵本身,并将密钥和文件名与卡片事件一起发送以解密。现在的卡事件看起来像:

{sprite : "randomFileName", key : "aSecretKey", player : 3}
但是,我再次意识到,一旦文件被解密,它将几乎一样容易。在游戏进行了一段时间后,所有的牌都会至少出现一次,让黑客将每个精灵文件与相应的等级关联起来。e、 g:

randomFileName1 -> King
randomFileName2 -> Ace
randomFileName3 -> Jack
策略2:更新精灵 为了防止这种情况,我想,一旦玩家解密了一张卡,他就无法再次识别它,因为他的客户端会下载一些新的加密精灵。renewalRate是使用一张卡后从服务器下载的卡数

e、 g:

客户端的精灵

客户端接收到一个事件

用户现在可以识别Ace

用户更新Ace文件和一些其他文件以将其混合

客户端的精灵

策略3:延迟更新精灵 为了避免这种情况,我想我可以延迟更新这些卡,这意味着重新下载的卡肯定不会包含以前使用过的卡。这需要客户端下载同一卡的多个版本:

**客户端的精灵**

   randomFileName1 -> ? (King)
   randomFileName2 -> ? (Ace)
   randomFileName3 -> ? (Jack)
事件

客户端的精灵

用户下载新精灵

当用户下载新精灵时,Ace中消耗的卡不一定包含在新精灵中。它可能会在下次下载,或者在用户下次消费卡时第二次下载

Download

 x randomFileName1 -> ?   (King)
 x randomFileName2 -> Ace (Ace)
   randomFileName3 -> ?   (Jack)
 + randomFileName4 -> ?   (3)
 + randomFileName5 -> ?   (9)
下一轮

问题 服务器开销

卡精灵:5-10kB 通过移动更新的卡数:3 游戏中每秒消耗的卡数:2 游戏次数:30 总计:900kB/s-1800KB/s

大量的服务器开销。1800KB/s可能有点重。只有30场比赛在进行

光学字符识别

此外,在这个系统中,即使玩家不能通过文件名识别卡,一旦他收到钥匙,他可能会运行OCR来识别卡的等级,并赢得比赛

我的问题
在这种情况下,是否有加密策略或其他策略可以让我减少服务器开销,并防止用户在图像上运行OCR?

一种简单且不太复杂的方法是有一种加密数据的方法,并经常更改加密数据的方法。可以使用当前时间+20秒作为哈希的秘密。或者应用程序中的某些数据将在客户端和服务器之间同步。在文件名散列期间,服务器和客户端可以一起使用的移动变量,以便客户端和服务器之间的散列相同,但对于相同的卡名,2分钟后的散列将不同。 时间可能不是最好的选择,但它是获得全球理念的一个例子

这样一来,精灵的加密名称每次都会更改

我不确定我的观点是否清楚

crypto.createHash('sha256').update(filename+"(-)="+currentTime+20).digest('hex');

你发送这个散列,然后与客户端一起,对每个文件名进行散列,并用收到的散列进行测试,这样你就可以找到要加载的好精灵。

除非我遗漏了什么这是一个基于普通纸牌组的游戏

为什么客户端不下载整个卡片组作为图像,也可以缓存到服务器端,并且在请求/响应中只向客户端发送哪个卡片的元数据文本/json/xml表示,等等。处理来回发送的文字卡图像不是一个简单的问题 这样,您就可以集中精力保护数据

为了防止玩家作弊,不要让这个服务器端成为无状态。管理整个游戏服务器端,只处理来自用户操作/事件的请求。在那里,您可以检查操作是否有效,以及接收操作的顺序

假设一个玩家可以很容易地更改请求中的数据,你知道他们真正拥有什么牌,以及在玩什么牌,所以你可以很容易地缓解这种情况


为了防止其他玩家看到其他人的卡,请使用SSL。

我想要一个非常强大的保护,-SSL过时了吗?我不明白为什么黑客可以用第一种解决方案作弊?因为他可以通过嗅探socket.io事件在精灵加载之前点击?基本上是的。这些牌在一场比赛中出现多次。一旦精灵被解密,他只需嗅探socket.io事件中的文件名。如果他已经解密的两个精灵接收到两个socket.io连续的socket.io事件,他就会知道他是否可以点击。有人在他面前有10扇锁着的门。他不能打开任何一扇门。当他收到钥匙时,他可以打开一把。收到另一把钥匙会让他打开另一扇门。如果他能清楚地记得他收到的所有钥匙是什么样子的,以及它们打开了什么门,一旦他收到钥匙,他就会知道它打开了什么门。在这种情况下,如果玩家收到一个密钥来解密一个精灵,一旦他解密了它,任何时候他收到相同的密钥将意味着相同的卡被丢弃。服务器管理整个游戏,如前所述。客户端一次又一次地下载精灵并对其进行加密的原因是为了减少客户端精灵的身份。我不想让用户知道afwie2di29d.encrypted.jpeg是一张黑桃王牌。如果他知道这一点,如果他知道每张牌的身份,他就可以写一个触发机器人,每当出现两张相同等级的牌时,他都会轻敲。我的建议是,使用不同的密钥对所有卡进行加密,在需要时发送密钥,并在密钥使用后更新卡。客户端唯一收到的是中央包上的新卡通知,他发出的唯一一个信息是点击中央包或丢弃其上的一张卡的通知。在服务器用卡的身份做出响应之前,他不会看到这张卡。在服务器向客户端发送通知以及要显示的卡id之前,客户端不会看到他的卡,也不会看到其他人的卡。请提前知道,混淆文件名将花费您$$,因为您会丢失客户端缓存。请求1:为每个文件名生成UUID服务器端,并将其作为卡发送回。请求2:客户端是否通过该UUID获取图像?您可以根据需要经常循环此操作,并且不要对Ace使用UUID,而是对组中的特定Ace使用UUID。坦白地说,对于OCR来说,这是不值得的。如果有人能很好地进行OCR,那么这和一个真正的用户看着屏幕,保护屏幕不受影响没有作弊的99%用户没有什么不同。如果我给用户发送加密他自己文件名的密钥,我相信他能够跟踪它。这不能解决问题,除非我误解了你的建议。好的,我想我明白了。问题是,一旦用户知道加载哪个文件名,他就会知道该卡的身份。我想缓解文件名->卡之间的关系。
// User renews files randomFileName1 and randomFileName2 
// as specified in the event.
//
// This way, he doesn't know no more which of the new file is the "Ace"
// Ace has 50% chance of being randomFileName4 or randomFileName5
// In general, a card has 1/(renewalRate) chance of 
// being identified after renewal. 
//
// In this case, renewalRate = 2.
// So chances to identify the Ace is (½ = 50%) among randomFileName4 and 5
Download

 x randomFileName1 -> ?   (King)
 x randomFileName2 -> Ace (Ace)
   randomFileName3 -> ?   (Jack)
 + randomFileName4 -> ?   (Ace)  -> the consumed ace is redownloaded here
 + randomFileName5 -> ?   (King) -> Another card is renewed    
Sprites : 

   randomFileName3 -> ?           (Jack)
   randomFileName4 -> ? (Ace 50%) (Ace)
   randomFileName5 -> ? (Ace 50%) (King)
   randomFileName1 -> ? (King)
   randomFileName2 -> ? (Ace)
   randomFileName3 -> ? (Jack)
Event : 

   {
       fileName : "randomFileName2"

     , key : "randomFileName2Key"

     , playerId : 3

     , renew : [randomFileName1, randomFileName2] 
   }
   randomFileName1 -> ?   (King)
   randomFileName2 -> Ace (Ace)
   randomFileName3 -> ?   (Jack)
Download

 x randomFileName1 -> ?   (King)
 x randomFileName2 -> Ace (Ace)
   randomFileName3 -> ?   (Jack)
 + randomFileName4 -> ?   (3)
 + randomFileName5 -> ?   (9)
Download

 x randomFileName3 -> ?   (Jack)
 x randomFileName4 -> 3   (3)
   randomFileName5 -> ?   (9)
 + randomFileName6 -> ?   (Ace) //Ace is re-downloaded now
 + randomFileName7 -> ?   (10)
crypto.createHash('sha256').update(filename+"(-)="+currentTime+20).digest('hex');