今天看啥
热点:

如何正确区分并使用加密与认证技术?(1)


在密码学专家之中,“加密并不是认证”是一个简单的共识。但很多不了解密码学的开发者,并不知道这句话的意义。如果这个知识更广为人知和深入理解,那么将会避免很多的设计错误。

这一概念本身并不困难,但在表面之下,还有更多丰富的细节和玄妙之处有待发现。本文就是讲述开发者对于加密和认证二者的混淆与误用,并附上了优秀的解决方案。

0x01 加密与认证之间有哪些区别?

加密是呈现信息,使其在没有正确的密钥情况下,变得难以卒读的过程。在简单的对称加密中,同一个密钥被用于加密和解密。在非对称加密中,可以使用用户的公钥对信息加密,使得只有对应私钥的拥有者才能读取它。

认证是呈现信息,使其抗篡改(通常在某一非常低的概率之内,小于1除以已知宇宙中粒子的数量),同时也证明它起源于预期发送者的过程。

注意:当本文提及真实性时,是专门指的信息真实性,而不是身份真实性。这是一个PKI和密钥管理问题,我们可能在未来的博客中详细说明。

就CIA triad而言:加密提供机密性,认证提供完整性。

加密不提供完整性;被篡改的信息(通常)还能解密,但结果通常会是垃圾。单独加密也不抑制恶意第三方发送加密信息。

认证不提供机密性;可以为明文信息提供抗篡改。

在程序员中,常见的错误是混淆这两个概念。你能很容易找到这样的一个库或者框架:加密cookie数据,然后在仅仅解密它之后就无条件地信任与使用之。

0x02 加密

我们之前定义了加密,并且详细说明了它是提供机密性,但不提供完整性和真实性的。你可以篡改加密信息,并将产生的垃圾给予接收者。而且你甚至可以利用这种垃圾产生机制,来绕过安全控制。

考虑在加密cookie的情况下,有如下代码:

  1. function setUnsafeCookie($name, $cookieData, $key)  
  2. {  
  3.     $iv = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);  
  4.     return setcookie(  
  5.         $name,   
  6.         base64_encode(  
  7.             $iv.  
  8.             mcrypt_encrypt(  
  9.                 MCRYPT_RIJNDAEL_128,  
  10.                 $key,  
  11.                 json_encode($cookieData),  
  12.                 MCRYPT_MODE_CBC,  
  13.                 $iv  
  14.             )  
  15.         )  
  16.     );  
  17. }  
  18. function getUnsafeCookie($name, $key)  
  19. {  
  20.     if (!isset($_COOKIE[$name])) {  
  21.         return null;  
  22.     }  
  23.     $decoded = base64_decode($_COOKIE[$name]);  
  24.     $iv = mb_substr($decoded, 0, 16, '8bit');  
  25.     $ciphertext = mb_substr($decoded, 16, null, '8bit');  
  26.    
  27.     $decrypted = rtrim(  
  28.         mcrypt_decrypt(  
  29.             MCRYPT_RIJNDAEL_128,  
  30.             $key,  
  31.             $ciphertext,  
  32.             MCRYPT_MODE_CBC,  
  33.             $iv  
  34.         ),  
  35.         "\0"  
  36.     );  
  37.    
  38.     return json_decode($decrypted, true);  

上面的代码提供了在密码段链接模块的AES加密,如果你传入32字节的字符串作为$key,你甚至可以声称,为你的cookie提供了256位的AES加密,然后人们可能被误导相信它是安全的。

0x03 如何攻击未经认证的加密

比方说,在登录到这个应用程序之后,你会发现你收到一个会话cookie,看起来就像

kHv9PAlStPZaZJHIYXzyCnuAhWdRRK7H0cNVUCwzCZ4M8fxH79xIIIbznxmiOxGQ7td8LwTzHFgwBmbqWuB+sQ==

让我们改变一个字节的第一块(初始化向量),并反复发送我们的新的cookie,直到出现一些变化。应该采取共4096次HTTP请求,以尝试变量IV所有可能的单字节变化。在上面的例子中,经过2405次请求后,我们得到一个看起来像这样的字符串:

kHv9PAlStPZaZZHIYXzyCnuAhWdRRK7H0cNVUCwzCZ4M8fxH79xIIIbznxmiOxGQ7td8LwTzHFgwBmbqWuB+sQ==

相比之下,在base64编码的cookie中只有一个字符不同(kHv9PAlStPZaZ J vs kHv9PAlStPZaZ Z):

- kHv9PAlStPZaZJHIYXzyCnuAhWdRRK7H0cNVUCwzCZ4M8fxH79xIIIbznxmiOxGQ7td8LwTzHFgwBmbqWuB+sQ==

+ kHv9PAlStPZaZZHIYXzyCnuAhWdRRK7H0cNVUCwzCZ4M8fxH79xIIIbznxmiOxGQ7td8LwTzHFgwBmbqWuB+sQ==

我们存储在这个cookie里的原始数据,是看起来像这样的数组:

  1. array(2) {  
  2.   ["admin"]=> 
  3.   int(0)  
  4.   ["user"]=> 
  5.   "aaaaaaaaaaaaa"  
  6.  } 

但在仅仅改变初始化向量的一个字节之后,我们就能够改写我们的阅读信息:

  1. array(2) {  
  2.   ["admin"]=> 
  3.   int(1)  
  4.   ["user"]=> 
  5.   "aaaaaaaaaaaaa"  

根据底层应用程序的设置方法,你或许可以翻转一位进而提升成为一名管理员。即使你的cookie是加密的。 如果你想再现我们的结果,我们的加密密钥是十六进制下的:000102030405060708090a0b0c0d0e0f




www.bkjia.comtruehttp://www.bkjia.com/jmjm/1002961.htmlTechArticle如何正确区分并使用加密与认证技术?(1) 在密码学专家之中,加密并不是认证是一个简单的共识。但很多不了解密码学的开发者,并不知道...

相关文章

相关搜索: 加密 密码

帮客评论

视觉看点