游戏协议加密(1)-消息摘要
消息摘要(Message Digest)又称为数字摘要(Digital Digest)。它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生。如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了。因此消息摘要保证了消息的完整性。消息摘要采用单向Hash函数将需加密的明文"摘要"成一串128bit的密文,这一串密文亦称为数字指纹(Finger Print),它有固定的长度,且不同的明文摘要成密文,其结果总是不同的,而同样的明文其摘要必定一致。这样这串摘要便可成为验证明文是否是"真身"的"指纹"了。
HASH函数的抗冲突性使得如果一段明文稍有变化,哪怕只更改该段落的一个字母,通过哈希算法作用后都将产生不同的值。而HASH算法的单向性使得要找到到哈希值相同的两个不同的输入消息,在计算上是不可能的。所以数据的哈希值,即消息摘要,可以检验数据的完整性。哈希函数的这种对不同的输入能够生成不同的值的特性使得无法找到两个具有相同哈希值的输入。因此,如果两个文档经哈希转换后成为相同的值,就可以肯定它们是同一文档。所以,当希望有效地比较两个数据块时,就可以比较它们的哈希值。例如,可以通过比较邮件发送前和发送后的哈希值来验证该邮件在传递时是否修改。
消息摘要算法
消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文。消息摘要算法不存在密钥的管理与分发问题,适合于分布式网络相同上使用。由于其加密计算的工作量相当可观,所以以前的这种算法通常只用于数据量有限的情况下的加密,例如计算机的口令就是用不可逆加密算法加密的。近年来,随着计算机相同性能的飞速改善,加密速度不再成为限制这种加密技术发展的桎梏,因而消息摘要算法应用的领域不断增加。
消息摘要算法的特点:
①无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。
②消息摘要看起来是“随机的”。这些比特看上去是胡乱的杂凑在一起的。
常用的摘要算法有MD5和SHA-1
在游戏通信协议中,如果使用消息摘要,我们可以添加一些混淆的数据,把正常的数据打乱,再加密。称为“加盐”。比如正常的数据包编码完成之后,我们对数据进行摘要加密,在加密的时候,在正常的数据包前几位和后几位添加一些其它的字节。然后进行摘要加密,并把加密的摘要放到正常的数据包中传给服务吕,服务器端接收到数据包之后,再做相同的加密算法,然后对比客户端和服务器端的摘要是否相同,如果相同,则包正确,如果不同,则包不合法,丢弃掉。
1、Java MD5实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | /** * * @param srcByteBuffer 正常的数据包 * @return * 2016年7月20日 下午10:53:17 */ public static byte [] md5MessageDigest(ByteBuffer srcByteBuffer){ try { //正常包的前置字符串 String str1 = "md1" ; byte [] strBytes1 = str1.getBytes( "utf8" ); //正常包的后置字符串 String str2 = "md2" ; byte [] strBytes2 = str2.getBytes( "utf8" ); int len = strBytes1.length + srcByteBuffer.remaining() + strBytes2.length; //把字符串和正常的包信息合到一起 ByteBuffer byteBuffer = ByteBuffer.allocate(len); byteBuffer.put(strBytes1); byteBuffer.put(srcByteBuffer); byteBuffer.put(strBytes2); //获取md5的数字摘名实例,对整合后的信息进行数字摘要计算 MessageDigest messageDigest = MessageDigest.getInstance( "MD5" ); byte [] digestBytes = messageDigest.digest(byteBuffer.array()); return digestBytes; } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null ; } |
2、JAVA SHA-1实现
只需要把上面的代码的MessageDigest实例换一下就可以了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | public static byte [] md5MessageDigest(ByteBuffer srcByteBuffer){ try { //正常包的前置字符串 String str1 = "md1" ; byte [] strBytes1 = str1.getBytes( "utf8" ); //正常包的后置字符串 String str2 = "md2" ; byte [] strBytes2 = str2.getBytes( "utf8" ); int len = strBytes1.length + srcByteBuffer.remaining() + strBytes2.length; //把字符串和正常的包信息合到一起 ByteBuffer byteBuffer = ByteBuffer.allocate(len); byteBuffer.put(strBytes1); byteBuffer.put(srcByteBuffer); byteBuffer.put(strBytes2); //获取SHA1的数字摘名实例,对整合后的信息进行数字摘要计算 MessageDigest messageDigest = MessageDigest.getInstance( "SHA-1" ); byte [] digestBytes = messageDigest.digest(byteBuffer.array()); return digestBytes; } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null ; } |
本文来自游戏技术网:http://www.youxijishu.com
MD5算法计算出来的消息摘要是128个比特位(bit),SHA-1算出来的摘要消息有160个比特位,由于生成的摘要信息更长,所以运算更复杂,在相同的硬件上,SHA-1比MD5慢一点。所以在游戏中,安全度高的,比如充值,购买操作可使用SHA-1进行加密,其它的相对不是很重要的,可以使用MD5加密。