我在这里尝试做的是创建一个函数,每次调用时都会将相同的输入加密为完全不同的输出。此函数的基础是xor,但是为了防止在字符串中轻易发现重复模式。我根据时间和字符串的一部分添加了随机散列,以便在解密时进行自我验证。
我要求的是,如果我在这里犯了任何错误,可以向有经验的人透露隐藏的文字而不对字符串施加暴力。 (我知道php有一个仅用于加密的模块,但如果加密模块不可用,这是一个糟糕的mans版本。) 第二:我不要求你重写这些功能或为我写一些东西,我要求的是一个简单的指导我做错了什么。 我知道一个可能的安全漏洞是我默认使用salsa,这对于空字符串都是零,但优点是这是php中可用的最长哈希,其次,傻瓜会使用空密码来保护他们的数据?
function crapt($str,$pass,$hmac = false,$meth = 'salsa20') {
$hash = pack('H*',($hmac===false) ? hash($meth,$pass) : hash_hmac($meth,$pass,$hmac));
$str = gzdeflate($str,9);
$tmphash = pack('H*',sha1(sin(microtime(1))));
$str = $tmphash.((string)$str ^ (string)str_repeat($tmphash,strlen($str)/strlen($tmphash)+1));
$str .= pack('H*',sha1($str));
return (string)$str ^ (string)str_repeat($hash,strlen($str)/strlen($hash)+1);
}
function decrapt($str,$pass,$hmac = false,$meth = 'salsa20') {
$hash = pack('H*',($hmac===false) ? hash($meth,$pass) : hash_hmac($meth,$pass,$hmac));
$str = (string)$str ^ (string)str_repeat($hash,strlen($str)/strlen($hash)+1);
$check = substr($str,-20);
$str = substr($str,0,strlen($str)-20);
if(pack('H*',sha1($str))!==$check) return false;
$tmphash = substr($str,0,20);
$str = substr($str,20);
return gzinflate((string)$str ^ (string)str_repeat($tmphash,strlen($str)/strlen($tmphash)+1));
}
var_dump(decrapt(crapt('sometext','secretpassword'),'secretpassword'));
答案 0 :(得分:13)
你自己发明的任何密码无疑都会有漏洞 - 如果我们这些Stack Overflow上的人无法检测到它,那并不意味着别人不会。密码学的第一条规则不是发明自己的密码:使用现有密码,并在可能的情况下,使用众所周知且经过测试的实现。如果您绝对无法使用标准库,请实现现有密码,例如TEA - 或者更好,以您选择的语言查找现有实现。
答案 1 :(得分:7)
您的算法以长度为strlen($hash)==strlen($tmphash)
的块运行。 编辑:错误,但请参见下文。
在密文中,第一个这样的块等于($tmphash XOR $hash)
。以下各项均等于(a_block_of_plaintext XOR $tmphash XOR $hash)
。
第一个密文块是数据的关键。只需重复密文的第一个块,然后得到明文即可。无需密码。
我不是PHP程序员,所以也许我错过了一些东西,但实际的攻击与此并没有太大的不同。
一般来说,只使用专业级加密模块。如果它们不可用,那么您的应用程序就不安全了。
编辑:通过重读问题,我注意到$hash
和$tmphash
的长度不同。
$hash
为512位,$tmphash
为160位。然而,这并没有改变基本思想;由于512和160的最小公倍数是2560,所以这些块每2560位同步一次。
因此,您只能解密每个2560位块的前160位。
答案 2 :(得分:3)
我的PHP不是很好,我是一个有一个学期的加密的家伙,所以绝不是专家。在评估加密系统的强度时,通常会假设攻击者可以完全访问您的算法和实现。
我看到了这句话:
$tmphash = pack('H*',sha1(sin(microtime(1))));
我认为这是你的关键。就像我说的,我的PHP非常糟糕,所以如果我错了请纠正我。
如果php sha1函数返回40位十六进制数,则为您提供WEP的密钥空间。我最后一次检查,WEP可以在大约3分钟内破解。我不完全确定这是基于通过信息泄漏的协议中的固有漏洞,还是因为这是因为超小密钥空间。但是,16 ^ 40似乎不是加密安全的足够大的密钥空间。
此外,基于此,我需要知道的是用户生成此请求的大致时间,您将大大减少搜索所需的密钥空间。如果php中的microtime()方法实际上给你自纪元以来的当前微秒,这会将我的关键搜索空间从16 ^ 40(php输出的sha1?)减少到时间范围内的微秒数我对你的用户充满信心收到你的这些数据。我可以写一个破解者,从我最有信心的时间(我嗅到数据包的时候)开始经过这个密钥空间,然后从那里回来,直到我达到某种阈值。
你总是可以玩“我的算法是一个秘密”的游戏,但我认识的大多数安全专业人员并不觉得这是一个非常有效的论点(或一个有趣的游戏)。这只是两个论点,一个非常基础教育的家伙遇到了只能解决你的密钥空间。
不要自己实施这样的事情。这是个坏主意。如果你正在为一个类编写玩具程序很酷,但是如果这适用于任何类型的生产系统,我强烈建议使用一个久经考验的密码系统。
-Brian J. Stinar -