我有一个与Web服务器通信的iPhone应用程序。启动App时,用户必须使用用户名和密码进行身份验证。 应用程序和Web服务器之间的通信是安全的(HTTPS)但我不想向Web服务器发送清除密码,我只想发送密码的“签名”(签名将存储在Web服务器上的数据库)。
在IOS上创建此“签名”的最佳解决方案是什么?我应该使用MD5还是别的什么?
我是否需要获取外部库来构建此签名,还是可以使用IOS SDK中的SecKeyEncrypt来完成?
从长远来看,我将在Android上运行App,我必须能够为IOS和Android生成相同的签名。
感谢您的帮助,
塞巴斯蒂安。
答案 0 :(得分:18)
以明文形式传输密码很糟糕,所以做任何事情都是很好的第一步。如果你想付出努力,那么值得知道如何正确行事。
虽然MD5不再是强哈希算法,但在MD5和SHA256(甚至SHA512)之间进行选择并不如您使用它那么重要。让我们忽略散列算法的细节,看看如何先使用它。
使用散列的想法是字符串的散列总是相同的并且是单向操作。通过捕获字符串,不可能(或实际)确定密码。近年来,随着彩虹表的大量使用,这已成为不实。彩虹表包含每个可能的密码(最多给定长度)及其散列,以便攻击者可以使用反向查找来发现密码。对于16个字符以下的密码,所有哈希算法都可以使用彩虹表。
这个问题有一些常见的解决方案。一种是执行散列很多次(大约1,000次)。确切的次数必须由客户端和服务器知道并预先确定,以便他们可以这样做。这具有使哈希生成昂贵的优点和缺点。攻击者在计算上更难以暴力破解,但如果将彩虹表扩展到足够大,它们仍然有用。
更好但不常见的解决方案是在密码中添加一个已知的随机字符串(通常称为Salt),使其长(可能是64个字符)。客户端和服务器必须事先知道此盐。这种解决方案既便宜又简单,如果盐泄漏也无关紧要。
密码散列还有另一个常见问题。如果恶意用户知道用户密码的哈希值,那么就像设计不良的系统知道密码本身一样好。假设我们有一个需要用户名和密码哈希的RPC函数。知道密码哈希的恶意用户即使不知道密码也可以提交密码,并可以访问系统。这个已知的密码哈希将继续有效,直到用户更改密码,密码可能是数月或数年。所需要的是一种限制密码散列有用的持续时间的方法。这是通过使用动态盐来实现的。
然后,身份验证将成为一个多步骤过程。
这是(大致)MySQL使用的机制。它足够安全,可以在没有安全SSL的情况下使用,但我总是建议使用SSL,以便保护有效负载的其余部分。
如果您使用这样的安全机制,那么使用MD5或SHA变体并不重要。也就是说,没有使用SHA256的任何新开发都没有意义,除非MD5是一个非常好的理由是必要的。
答案 1 :(得分:1)
md5不是最好的主意 - 现在有很多非常快速的彩虹表可以解密它们。
我建议使用AES256 - 在iOS上你有NSData+CommonCrypto,这样你就可以轻松地做到这一点。
NSString* encryptionPass = @"myEncryptionPass";
NSData* passData = [userPassword dataUsingEncoding:NSStringEncodingConversionAllowLossy];
NSError* error = nil;
NSData* encryptedPassData = [passData AES256EncryptedDataUsingKey:encryptionPass error:&error];
if(!error)
{
NSString* encryptedString = [[NSString alloc] initWithData:encryptedPassData encoding:NSUTF8StringEncoding]
}