一个开发人员,我们称他为“ Dave”,坚持使用自制脚本来保护密码。请参阅下面的Dave提案。

他的团队花了几个月的时间使用Bcrypt来采用行业标准协议。该协议中的软件和方法不是新的,并且基于支持数百万用户的经过实践检验的实现。该协议是一组规范,详细说明了当前的技术水平,所使用的软件组件以及应如何实现它们。该实现基于已知的良好实现。

Dave从一开始就反对该协议。他的理由是,像Bcrypt这样的算法已经发布,对黑客具有更大的可视性,并且更有可能成为攻击目标。他还认为该协议本身过于庞大且难以维护,但我认为Dave的主要困扰在于Bcrypt已发布。是要就以下问题达成共识:


为什么自家酿制不是一个好主意,
他的剧本到底有什么问题

/** Dave's Home-brew Hash */

// user data
$user = '';
$password = '';

// timestamp, random #
$time = date('mdYHis');
$rand = mt_rand().'\n';

// crypt
$crypt = crypt($user.$time.$rand);

// hash
function hash_it($string1, $string2) {
    $pass = md5($string1);
    $nt = substr($pass,0,8);
    $th = substr($pass,8,8);
    $ur = substr($pass,16,8);
    $ps = substr($pass,24,8);

    $hash = 'H'.sha1($string2.$ps.$ur.$nt.$th);
    return $hash
}

$hash = hash_it($password, $crypt);


评论

...现在Dave的协议发布了?

如果Dave最终采用了更好,更安全的方法,他也许会说一点。他没有。之所以使用已发布的算法,是为了使我们所有人都能从他人的集体智慧中受益,而不必依赖于我们对概念的个人和不断发展的理解。

Dave从根本上是错误的前提,即算法的安全性(甚至部分地)依赖于其模糊性-事实并非如此。哈希算法的安全性取决于我们对数学的理解的局限性,并且在较小程度上取决于对其进行暴力破解的硬件能力。一旦Dave接受了这个现实(这确实是现实,请阅读Wikipedia上有关散列的文章),那就是谁会更聪明的问题-Dave自己还是一群专门研究这个非常特殊问题的专家。

对于您的整个用户群,最糟糕的算法可能在几分钟之内就被强行使用。

问题不是戴夫傻了。从某种意义上说,我们都是愚蠢的。这是他成为邓宁-克鲁格效应的牺牲品,不仅不知道自己有多愚蠢,还完全相信他比该领域的专家更懂。这是真正的危险。愚蠢和意识到这很好,以及我们应该如何努力做到这一点。愚蠢和遗忘是不好的,但是比较容易补救。愚蠢而尴尬的过度自信既极度危险,又往往无法修复。

#1 楼

/** Dave's Home-brew Hash^H^H^H^H^Hkinda stupid algorithm */

// user data
$user = '';
$password = '';

// timestamp, "random" #
$time = date('mdYHis'); // known to attackers - totally pointless
// ^ also, as jdm pointed out in the comments, this changes daily. looks broken!

// different hashes for different days? huh? or is this stored as a salt?
$rand = mt_rand().'\n'; // mt_rand is not secure as a random number generator
// ^ it's even less secure if you only ask for a single 31-bit number. and why the \n?

// crypt is good if configured/salted correctly
// ... except you've used crypt on the username? WTF.
$crypt = crypt($user.$time.$rand); 

// hash
function hash_it($string1, $string2) {
    $pass = md5($string1); // why are we MD5'ing the same pass when crypt is available?
    $nt = substr($pass,0,8); // <--- BAD BAD BAD - why shuffle an MD5 hash?!?!?
    $th = substr($pass,8,8);
    $ur = substr($pass,16,8);
    $ps = substr($pass,24,8); // seriously. I have no idea. why?
    // ^ shuffling brings _zero_ extra security. it makes _zero_ sense to do this.
    // also, what's up with the variable names?

    // and now we SHA1 it with other junk too? wtf?
    $hash = 'H'.sha1($string2.$ps.$ur.$nt.$th); 
    return $hash
}

$hash = hash_it($password, $crypt); // ... please stop. it's hurting my head.

summon_cthulhu();


戴夫,你不是密码学家。阻止它。

这种自制方法无法真正抵抗暴力攻击,并给人一种“复杂”安全性的错误印象。实际上,您要做的仅是sha1(md5(pass) + salt),它可能会损坏并且过于复杂。您似乎在幻想复杂的代码可以提供更好的安全性,但事实并非如此。无论攻击者是否知道该算法,强大的密码系统都是强大的-这一事实被称为Kerckhoff原理。我意识到重新发明轮子并以自己的方式完成它很有趣,但是您正在编写将要用于业务关键型应用程序的代码,这将必须保护客户凭证。您有责任正确地做到这一点。

坚持尝试和测试过诸如PBKDF2或bcrypt之类的密钥派生算法,这些算法已经过多年的深入分析和审查,受到了众多专业和业余密码学家的审查。 。

如果您想对正确的密码存储进行良好的学习,请查看以下链接:


如何存储盐?
执行任何操作安全专家建议使用bcrypt进行密码存储?
如何安全地存储密码?


评论


您能解释一下为什么这是“ BAD BAD BAD”吗?我认为重复的哈希或处理哈希输入可以帮助阻止彩虹表或蛮力攻击。这如何引入漏洞?

– jdm
2012-12-18 15:35

@jdm“ BAD BAD BAD”部分是指MD5哈希的无意义改组,因为它提供了零额外的安全性,但是在这种情况下,“重复”哈希的设计很糟糕。它一次依赖于MD5,crypt(无论最终配置为什么)和SHA1,但实际上仅进行3次计算。距离击败基于GPU的蛮力还远远不够。整个过程除了含糊不清外什么都没有,并且可能不如带有适当盐的sha1(md5(pass + salt))安全。使用正确的密钥派生算法很重要(请参阅第一个链接)。

–多项式
2012-12-18 15:38



谢谢。相信我,我同样感到沮丧。戴夫(Dave)是一位出色的人,过去曾做过出色的工作。他对所有这些的反应令我感到惊讶。他缺少一些可以通过简单的Google搜索掌握的基本概念。我并不想变得斗气或残忍,但是我已经尽力向他解释了。这正是他需要的反馈...

–nallenscott
2012-12-18 15:44

@nallenscott公平地说,我在学习编码时经历了相同的阶段-我想自己做所有事情,并很快陷入编写自己的“加密”和哈希的陷阱。然后,我实际上了解了真正的安全性,并发现我以前编写的许多内容都被严重破坏了。大规模的叫醒电话!

–多项式
2012-12-18 15:48

@Casey:当然,总是发明自己的。制作自己的链表,自己的加密货币,自己的数据库,自己的mergesort。实施算法和数据结构以更好地理解它们。然后放弃实施-现有的几乎总是更好的。如果没有,继续该项目并进行改进!您的同伴将查看您的更改并提供反馈。如果您做错了,您将学到,如果您做对了,您的改变将惠及全人类;)

–科尼拉克
2014年1月24日,9:07

#2 楼

公共协议的优点:

可能是由比您更聪明的人编写的
经过了更多的人(也许其中有些人比您更聪明)进行了测试
有更多的人评论(可能有些人比您聪明),经常有数学证明
更多人(可能有些人比您聪明)改善了
目前,成千上万的人中只有一个发现缺陷,很多人开始修复它

公共协议的缺点:

如果确实发现了缺陷,就
将其公开
而不会修复得足够快

,然后攻击者将开始搜索易受攻击的站点/应用程序。但是:

他们可能会首先追赶更重要的目标
当缺陷暴露出来后,您就知道并且可以锁定
并非所有缺陷都是“关键”的(大多数就像“在某些情况下可能发生冲突”或“暴力破解的时间不是1012年,而是106年”)。

默默无闻的安全性被认为是绝对糟糕的。属于自己的发明属于该类别。

评论


对于众所周知的算法,如果您不是专业的密码学家,则可能绝对应该替换为。

–丹在火光中摆弄
2012-12-18 15:55

“大概是由比你更聪明的人写的”-您假设“戴夫”承认存在这种情况。

– AakashM
2012-12-18 18:33

任何密码都可以称为“默默无闻的安全性”。但是在一个好的系统中,已经证明密码是唯一必须保密的东西。未经测试的系统几乎肯定会存在其他缺陷,因此在保护密码的同时,有人会使用您没有想到的攻击。这就是为什么您想要一种被残酷地攻击并被认为是强大的算法的原因。

–内森·朗(Nathan Long)
2012年12月18日在21:01

@NathanLong:关于密码/密钥的重要一点:如果怀疑一个人的秘密已被泄露,则可以通过例如滚动25个透明骰子,并使用这些值生成密码或密钥(64位以上的熵);只要敌人不知道那是什么,任何掷骰就基本上和其他掷骰一样好。

–超级猫
2014年9月12日20:31

如果您聪明地说您的意思是人们对密码学更加了解...

–怪物
15年11月24日在14:53

#3 楼

如果Dave确实是“您的”开发人员,例如您有权解雇他,那么您有权指导他使用更有据可查的方案,您应该这样做。

在密码学中,需要保留的秘密越少越好。这尤其适用于“硬编码”机密,例如哈希函数本身,一旦包含机密的代码离开您的建筑物,这些机密就不再是机密。这就是为什么开放式密码标准成为好东西如果该方案已经存在了数十年甚至几十年,并且基本算法和各种实现都是众所周知的,但仍然没有人找到进入的方法,那它就是一个很好的方案。

例子,多项式提供了该方案出了什么问题的很好的细分,但是这是所提出的哈希算法的主要失败之处:


MD5被完全破坏了;虽然通过破坏MD5的主要方式并没有使原像攻击变得容易得多(它非常容易受到已知明文强烈冲突的影响;了解消息和摘要,但可以在2 ^ 24时间内产生冲突),但是该算法太快了,无法针对现代分布式破解硬件进行安全保护。永远不要在需要数据安全性的应用程序中使用它。
SHA-1被认为是脆弱的;再说一次,没有很好的向量来进行原像攻击,但是有很强的碰撞攻击(160位散列需要2 ^ 61次),并且散列算法足够快且密钥空间足够小,以至于当前硬件可以进行蛮力攻击强制。

更多的哈希值不一定意味着更好的哈希。哈希是确定性的过程;它们代表理论密码学中的“随机预言”,但是由于它们必须始终在给定相同输入的情况下产生相同的输出,因此它们不能对输入中已经固有的信息加任何熵。

简而言之,就像Dave一样使用多个哈希的秘密组合,即使这种组合是未知的,也不会给蛮力增加大量工作(三个哈希的相对顺序有6种可能性,增加了复杂性尝试用不到2的3的次方来尝试所有可能性,并且一旦攻击者可以反编译您的代码并发现哈希函数的相对顺序,这种额外的复杂性就会消失。

密码本质上是低熵的。最好的“用户可使用”(无垃圾)密码在大约50位熵的情况下最大程度地提高了复杂性,这意味着如果您对所要查找的内容有所了解,则可以在2 ^ 50或更短的时间内破解它们。这使得密码比通常要散列的其他内容(例如证书摘要)更容易破解,需要额外的“工作量证明”来提高其安全性。
该方案未添加任何重要的工作证明;在事物的宏伟方案中,用三个散列代替一个散列,在额外的工作中为方案增加了约1.25位的熵。您只需将密码延长一个字符就可以做的更好。

与上述所有方法相比,BCrypt具有一个非常慢的密钥派生功能或KDF作为其主要优点。 Blowfish是构成BCrypt基础的加密密码,它使用“ SBox”;预定的初始值的较大数组,可以通过密钥和/或IV进行修改,以产生密码的初始状态,通过该状态来馈送明文。在BCrypt中,通过使用较小的密码和盐值并将它们通过“无密钥”密码运行预定的次数,然后将其“预热”到理论上只能通过执行该操作来生成的状态,可使此SBox设置更加复杂使用相同的密码和盐,进行相同数量的设置迭代。然后,将此“预热”密码提供给常量明文以产生哈希值。用CS术语来说,散列形成“工作量证明”;一项难以执行(耗时和/或耗费资源)但易于检查正确性(产生的哈希值与我们已经拥有的哈希值相匹配的计算任务)。

“预定SBox设置的迭代次数”是可配置的;这是BCrypt的真正力量。散列时指定了许多“回合”键设置,对于n回合,执行2 ^ n次键设置迭代。这意味着增加轮数会使散列执行两倍的工作,并且在相同硬件上花费两倍的时间来产生必要的工作证明。因此,BCrypt可以轻松跟上摩尔定律,而摩尔定律一直是以前出现的许多哈希函数的祸根。

BCrypt的主要理论缺点是内存使用率低。尽管计算时间可以成倍增加,但所需的内存量实际上保持不变(随着迭代次数的增加,SBox不会变大,并且不需要保留“中间结果”)。因此,虽然BCrypt阻碍了GPU的纯流水线计算能力,但它仍然容易受到更复杂的“现场可编程门阵列”(基本上是大量的,高度模块化的“软接线”逻辑单元的集合)的破坏。高度分布式计算的最新技术),因为内存不足的限制意味着您可以将更多相对廉价的电路板投入该问题。

较新的算法SCrypt可与FPGA对抗通过以指数方式增加内存需求以及计算散列的计算开销来破解,因此每个FPGA可用的有限内存也很快使它们不可行(分布式破解基本上需要大量的CPU / FSB / RAM组合,实际上已满计算机,钩在一起)。唯一的问题是SCrypt只有2或3年的历史,因此它没有BCrypt(13年)的密码分析谱系。确实,如果您要担心FPGA配备的破解程序会在可行的时间内获取密码(例如,无论如何都无法更改所有密码),那么您会激怒一些非常有能力的人,并且已经暴露出另一个严重的问题。漏洞(允许攻击者首先获取您存储的密码哈希,以便他们可以破解一个“离线”)。

底线,使用BCrypt进行密码哈希处理。该密码器已有13年的历史,基于20年的密码算法,当时还没有发现有助于密码破解者的已知漏洞。它像糖蜜一样慢,并且可以配置为始终保持这种状态,前提是您将它​​与要求用户每90天左右更改一次密码的要求结合在一起,因此新密码会随着更昂贵的配置而不断散列。

评论


首先,SHA1是160位。其次,在碰撞哈希密码(2 ^(n / 2)蛮力)而被破解的过程中,破解散列密码(您担心(第一个)前映像攻击-2 ^ n至蛮力);请参阅:en.wikipedia.org/wiki/Preimage_attack。对于加密签名,不能使用冲突破折的哈希(并且SHA1在2 ^ 61时间内被破译)(因为签名的消息可以更改)。 (尽管MD5的简单性和速度以及大彩虹表的存在确实意味着它对密码不利。)不过,您还是同意bcrypt的说法。

– jimbob博士
2012-12-18 17:49

删除了关于原图像攻击,冲突,哈希强度等的冗长讨论

–Rory Alsop♦
2012-12-19 18:42

我使用MD5在图表脚本中创建漂亮的颜色-不是为了保护密码

– mplungjan
13年3月19日在7:19

@mplungjan好主意!

– Mark K Cowan
18年11月12日在13:36

噢,天哪,我非常讨厌公司需要每90天重置一次密码的公司,这真令人沮丧。不要这样做。您的公司并不特殊,除非您是Facebook或Google,否则您的用户访问该页面的可能性很小,您几乎要求用户每次访问您的网站时都要重置其密码,这是荒谬的。

–尼古拉斯·皮皮托尼
19年11月13日在7:48

#4 楼

公平地说,对于Dave而言,就自制密码安全而言,这是更好的情况之一,因为这只是掩盖了hash = SHA1(salt + MD5'(Password))(实际上不是很多),其中MD5'对MD5哈希的字节顺序进行可逆交换。现在,用户名/时间/随机/加密部分仅用于生成盐,而我们对盐的唯一要求是它们仅需要非常好的唯一性即可;因此,尽管它过于复杂,但实际上没有任何用处。
再次hash = sha1($salt+md5'($password))。重新排列MD5不会增加安全性(swap(00112233445566778899aabbccddeeff)变为ccddeeff8899aabb0011223344556677)交换并不会阻止您之后使用md5 Rainbow表(例如,查看代码并反转交换)。但是,唯一盐的存在使彩虹表变得不可行。
现在至关重要的是,这归结为一个简单的加密哈希函数被应用了两次;这比存储纯文本密码(请参阅纯文本违法者)要好,并且比存储未加盐的哈希(请参阅linkedin泄漏)要好。但是,在廉价的大规模并行GPU时代,这对于现代使用来说太弱了。任何具有某种通用GPU编程经验的人都以某种方式进入了实时服务器(用盐来获取哈希值),可能会看到他的源代码,尝试使用自己的密码作为测试用例,然后可以对任何每个GPU每秒可以尝试数十亿次尝试的特定密码。
因此,如果任何用户正在使用一百万个左右的先前泄露的密码(例如,从Linkedin中)的密码,则攻击者几乎可以立即破解它。如果某个用户的密码是字符集A-Za-z0-9中的随机8个字母;每个GPU平均中断大约需要60个小时(因此,如果您有60个GPU,则需要1个小时)。使用常见的破解技术,利用常见密码的形式可以大大加快其速度。还值得注意的是,由于$password通过128位MD5哈希函数,因此在密码短语中使用超过128位的熵绝对没有任何好处(尽管公平地说,这是一个非常安全的密码;例如10字骰子密码或22个字符的字母数字随机密码。)
真的,您应该使用迭代的加密哈希函数;类似于bcrypt或PBKDF之类的东西,它通过一个较大的常数因子(例如105)使攻击者的暴力破解速度变慢(因此,从60个小时内破解62个字符集的随机8个字符密码(A-Za -z0-9);使用单个GPU花费600万小时(可能会损坏700年左右),而使用更强大的密码(例如,一个10字符的密码将花费300万年左右)会更好。一百万个GPU需要花费3年的时间。因此,只需进行一点按键强化,就可以将相对较弱的密码(从62个字符集随机抽取8个字符)移出攻击者破解的可能性范围。有关更多信息,请使用简单的按键强化密码,请参阅此答案。
冲突攻击与图像前攻击(或为什么哈希函数的冲突攻击与密码哈希无关)
KeithS的答案虽然给出了很好的建议(使用bcrypt而不是简单的密码哈希函数来哈希您的密码),但最初批评MD5和SHA1的理由不正确(不要使用MD5容易受到冲突攻击)。映像前攻击和碰撞攻击之间有细微的差别,并且评论中的争论过于简洁,因此我在这里详细说明。我强烈建议您阅读维基百科有关图像前攻击的文章。
图像前攻击说,给定以十六进制形式编写的特定128位哈希值:h=ad2baf26a87795b3c8a8366a08b44112,特定的哈希函数H,请找到任何消息m,以便使h=H(m) ;请注意,有N = 2128个不同的不同哈希。现在,如果您的加密哈希函数没有中断,则哈希消息中的每一位都有50%的可能性,即随机消息m为0或1。然后我平均需要生成大约N = 2128个哈希值的哈希值,然后我很幸运地找到任何消息m,使得h=H(m)(此消息可能与最初生成哈希值的输入不同-但这仍然
碰撞攻击说找到我任意两个消息m1m2,例如H(m1) = H(m2)。请注意,m1m2(和H(m1))都可以自由更改。这种情况下的问题要容易得多,因为如果我为M条不同的消息生成M个散列,我不仅将M条消息与一个特定的哈希进行比较(因此有M条发现冲突的机会),现在我得到M *(M- 1)/ 2对哈希,因此大约有M ^ 2发生冲突的机会。因此,在这种情况下,我将需要大致生成sqrt(N)〜264个散列,然后它们中的一个可能在理想的128位哈希上与另一个散列冲突。
让我们看一下两种类型的生日问题。碰撞问题转化为共同的生日“悖论”。一个房间需要多少人,才能让两个人共同过生日,一年中N = 365天。答案很自相矛盾,因为您只需要大约sqrt(N)〜23个人就可以让两个人共享生日(例如,一个房间中有23个人,您就有253对可以配对的人)。 (我确实知道sqrt(365)!= 23:我使用的是近似数学,而不是关注无关紧要的常量因子。请先在房间中使用sqrt(365)〜19人再进行计算,然后再进行P(two share birthday) = 19! * comb(365,19)/365**n = 37.9%,但严格来说不是50%仍然表示其相当可能发生)。请注意碰撞生日问题,一个房间中不能有N + 1 = 366人,并且有可能没有碰撞(忽略leap日);最多365个人的生日不同,最后一个人发生了碰撞。
图像前问题是一个非常不同的问题,在一个房间中我可能需要多少人之前,很可能有人会特定的生日(例如B = 12月18日)。在这种情况下,大约需要N〜365个人才能实现。例如,房间中有365人,您有一个P(somebody has birthday B) = 1 - (1 - 1/365)^(# people),因此,对于# people = 365,您有63%的概率某人的生日将是某个固定的日期B。在这种情况下,您可以轻松想象有多少人在一个房间里没有人在某个特定的日期有生日。 (假设您没有在指定的生日那天才邀请人们进入房间;可以邀请的人数没有限制。)
当像MD5 / SHA1这样的哈希函数因碰撞攻击而被破坏时,这意味着您可以以比sqrt(N)〜2numbits / 2的蛮力时间少的工作量来产生碰撞。对于MD5,只需要大约2 ^ 24时间即可产生碰撞;对于SHA1,大约需要2 ^ 61的时间。这意味着对MD5进行碰撞攻击非常容易。但是对SHA1的实际攻击仍然很困难。但是,冲突攻击仅在您不关心要匹配的哈希值时才重要。这些冲突攻击与某些应用程序非常相关,例如对消息进行加密签名以确保消息的完整性,因此请注意在这种情况下使用MD5 / SHA1。但是,当您具有唯一的盐和要匹配的特定哈希来进行身份验证时,冲突攻击就没有关系。

#5 楼



请参阅相关的“安全性Meme”帖子

虽然这看起来很简单,但这些规则仍然适用-设计加密算法并正确/安全地实现它们非常困难。甚至是由专家设计并被数以千计的人挑选出来的,最终还是在其中发现了漏洞。阿德曼,波宁,沙米尔)

评论


有趣并且同意这种观点,但是与他没有写自己的密码无关。他将现有的加密哈希函数MD5和SHA1以及自定义的排列函数dumb_perm(dumb_perm('00112233445566778899aabbccddeeff')转到了'ccddeeff8899aabb0011223344556677'),因此hash = SHA1(salt ++ dumb_perm(MD5(pw)))并创建了它们的盐过于复杂。尽管他们增加了维护成本却没有获得安全性的好处,但是他们并没有创建自己的密码-缺点是如今简单的哈希值太快了,因此必须加强密钥。

– jimbob博士
2012-12-19 19:41

我认为更大的问题是,问题的例子更多地是关键削弱而不是关键加强。它可能不是一个新密码,但由于同样的陷阱而下降。

– Jeff Ferland♦
2012年12月19日在18:08

@drjimbob密码!=哈希

–bradley.ayers
2012年12月19日在21:09

@ bradley.ayers-我理解它们之间的区别(密码用于加密;散列不是加密的,因为它不可逆。)模因图像首先使用了“密码”一词,我也没有批评Rory是像MD5这样的加密散列函数和SHA1基于类似于分组密码的算法:en.wikipedia.org/wiki/…但是,Dave并未创建自己的密码/哈希函数或类似的东西。他只是在弱哈希方案(sha1(salt + md5(pw)))的一个步骤中对MD5进行了哑置换。

– jimbob博士
2012年12月19日在21:17

一个人不能简单地写出自己的密码听起来更好

– mplungjan
13年3月19日在7:21

#6 楼

尽管我们可以发现Dave算法存在很多缺陷,但它并不是可怕的,因为它不是100%的家庭酿造。他确实使用基于可靠原则的哈希协议(尽管很弱)。另一方面,他采取的步骤增加了开发人员的复杂性,但却无济于事提高他的算法的安全性。

但是我在这里添加另一个答案的原因是提出了一个古老的论点,即默默无闻是有价值的。第一道防线应始终是强大的,广为接受的哈希算法,但即使添加最少量的模糊度作为另一道防线,也没有任何危害。

不应该将那一层晦涩的事物本身视为防御,而只是减少妥协机会的附加因素。由于成功进行攻击通常需要考虑多种因素,因此即使是小的防御措施也可以对降低总体风险产生重大影响。

我无法告诉您多少次我试图破解哈希转储,但我却一无所获,因为有些Dave在某处想到了这种愚蠢的非标准算法无法进行大量的密码分析或侵入Web服务器以获得算法。您不能否认这些愚蠢的算法是一个有效的防御因素。

现在,如果Dave采用了他的愚蠢算法并将其作为一层添加到更强大的算法(如PBKDF2或bcrypt)中,那么他对可靠的安全实践的支持。另外,模糊性不必像Dave的代码那么复杂,您真正需要的只是一点点不同而变得模糊。请记住,这不是防御,只是一层晦涩。

更好地实现模糊性的方法是使用HMAC,连接服务器端盐常数和/或使用大量非标准迭代。这些措施都不能靠自己解决,但它们确实可以解决导致整体风险的特定攻击媒介。

tl:dr;通过隐蔽性实现安全性是不好的,但是可靠的安全性加上合理数量的隐蔽性是有效的策略。

评论


确实,Dave的算法本质上是盐化的HMAC,稍有扭曲。它似乎和HMAC一样强大。例如,攻击者将无法使用别人的彩虹桌。我对该系统最大的担忧是盐的存储位置。

–迪玛·蒂斯内克(Dima Tisnek)
2012年12月20日上午9:50

@qarma HMAC两次使用密码(即密码),此算法仅使用一次。

–PaŭloEbermann
13年4月6日在13:43

#7 楼

好,解雇戴夫。至少要用一个很大的提示棒打他。开放协议是好的,因为任何人都可以查找并尝试查找漏洞和结构性问题,并实施修补程序。可见性改善了协议。良好的安全性意味着每个人都可以知道系统的工作方式,并且仍然安全。

评论


您是否仍然相信在所有开放系统中发现并修复了所有漏洞,因此它们是最安全的系统,考虑到最近几年的泄漏,这些泄漏揭示了NSA和CIA之类的漏洞本身就存在漏洞并开发了漏洞利用程序出于种种勉强法律上的理由?如果他们能够做到(所谓的“好家伙”),那么所谓的“坏家伙”也不能做到(“中俄黑客”等等)吗?

–a20
17年5月14日下午5:27

您将设计与实现@ a20混淆了,在任何情况下,我都不认为封闭是没有帮助的,美国政府常坐的大多数漏洞都在封闭系统中,例如MS操作系统。

– GdD
17年5月15日在6:59

“美国政府所面临的大多数漏洞都处于封闭系统中”。您是什么使我混淆了设计和实现?

–a20
17年5月16日在8:01

@ a20我真的很晚才参加这个聚会,但是我猜测GdD指的是这样一个事实,即您所谈论的那些现实世界的漏洞很少是密码标准中的基本缺陷,而更多的是它们是软件产品使用或实施标准的方式。例如,如果我写了一个开放协议的实现,因为我使用时间戳而不是crypto-PRNG作为种子,所以该协议容易受到攻击,该漏洞表明我的实现存在缺陷,而不一定是开放协议的缺陷。封闭系统在这里更容易受到攻击。

– David Schwartz
7月1日23:22

#8 楼

用合理的理由说服他。不要指责他。

您必须考虑为什么我们对密码进行哈希处理:原因是通过使哈希处理过程花费大量CPU时间来执行保护原始密码。暴力破解是通常恢复密码的方式。

如果攻击者能够窃取您的密码数据库,则他们已经设法访问您的数据库。如果他们可以访问数据库,那么他们也可能也可以访问生成这些密码的代码。在检查了代码之后,由于哈希算法执行的时间太短,他们可以开始对密码进行暴力破解。

众所周知的哈希方法和实践(例如使用PBKDF2进行10,000次迭代)的思想是在当前的硬件上执行需要花费大量时间。

如果有时间,您还可以编写一个强制执行程序,并向他显示可以使用他的算法每秒执行多少攻击与现行标准。

评论


仅仅因为他们可以访问数据库,并不意味着他们可以访问他的代码。

– jmoreno
2012-12-18 18:48

@jmoreno仍然不能证明他的无用方案。

–托马斯
2012年12月18日20:39

@Thomas:是的,拒绝bcrypt的原因根本无法支持,但这并不意味着您的代码无法使用标准库和实践来增加(或删除)值。

– jmoreno
2012-12-18 22:02

@jmoreno通常,模糊的安全性通常被认为是不良加密实践的根源。这并不意味着它没有价值-它确实有其用途,但是在这种情况下,它不是必需的。

–托马斯
2012-12-18 22:13

@jmoreno,对,这就是为什么我说“可能”。要点是散列必须花费时间。

–萨拉·博塔(Sarel Botha)
2012-12-19 14:56

#9 楼

我已经写了几种哈希算法。如果您知道自己在做什么,那没有什么错。在某种程度上,他说得很对,即经过实践检验的算法可能更容易受到攻击。因此,如果您可以创建一个好的算法,那么您就是黄金。唯一的问题是,由于多种原因,他完全糟透了。




// timestamp, random # $time = date('mdYHis');

我什至感觉不需要解释这一点。当他试图创建一个种子化的“随机”数字没有任何意义时,他试图这样做。哈希值每天都会更改。我无法想象这种方法在任何合理的情况下都可以正常工作。 )的“ his”算法。他的方法只是普通ole MD5哈希的非常细微的派生。这使我想到了:
他正在重新整理他的MD5结果。嗯,为什么呢?作为一项有趣的小活动,请尝试让他解释一下他的推理。我会给您一个提示,以帮助您:无论他的回答是什么-都是错的。改组散列值就像改组一副全空白卡。它没有任何额外的好处。

还有很多问题出在这里,但是这些都是大问题。告诉他回到平常的工作,然后使用bcrypt(或scrypt,这样做实际上会占用大量CPU,甚至可能更安全)

评论


是的,您可以自己编写,但是大多数认为自己有资格自己编写的人不具备自己编写的资格。容易判断我们有多聪明,但很难判断我们有多愚蠢。

–马克·伯内特(Mark Burnett)
2012年12月21日19:44

我认为改组的原因是使算法不同于攻击者(不知道算法)的期望。使用特定于应用程序的秘密盐输入(也称为“胡椒粉”)具有相同的效果,并且更可靠。

–PaŭloEbermann
2012年12月22日在2:04

关于#3:不能在彩虹表中查找经过改组的MD5哈希。

–道格拉斯举行
19年7月3日在21:09



#10 楼

隐秘术比Dryptography更好地受益于Dave的操作保密性。这可能就是Dave直觉的目标。

密码学

每个密码解决方案都受益于最大的暴露范围,因为依靠除私钥以外的秘密可以使操作安全性提高。加密货币消费者要困难得多。密钥是一种易于管理,可移植,可预测,定义明确的安全风险,加密专家已集中精力进行了大量工作,以确保算法中的所有风险均被压缩为仅密钥。

可以使密钥变得难以猜测(高熵),从而需要蛮力或侧通道攻击。由于加密算法的任何其他方面都可以归纳为一类通用的(可能是较弱的)加密算法+一个恒定值,因此不能使算法其他方面的秘密难以言喻。该常数值表示算法结构或混淆中的所有残留不变熵。在自制算法中,该值永远不会特别大或熵,并且在任何非自我修改的计算机程序中,该值固有地是恒定的。攻击者可以获取源并直接删除该(较小的)熵,也可以通过通用算法类来运行密文。例如,美国国家安全局(NSA)会针对外国势力使用的常见算法的未知变体来精确地做到这一点。机密要求攻击者以对该受害者可能唯一的方式自定义搜索;并扩大到可能的藏身处和受害者掌握的藏身方法。

这很简单,例如拥有一个伪造的哈希密码列并在记录用户信息的各个表中隐藏真正的四分之一(64bit)time_t列。
这可能就像在BluRay电影中隐藏可移植Linux仿真一样复杂。一个人或一个组织可以通过隐藏次要语义来受益,其隐藏方式与任何谎言一样。是“我的袜子很无聊,并且不包含钻石”还是“这些是您要寻找的哈希,请忽略该蜜罐或与审计服务器的套接字连接”。
/>
,因此Dave应该使用经过审核的公共高级库(例如BouncyCastle),而不要使用低级的原始加密货币。但应该让黑客自由地浏览服务器生态系统,就像他们正在阅读缺少某些字符的“脑力激荡”程序一样。

假设完整的支持文档都保存在Dave继任者的安全脱机位置中...

#11 楼

我将尝试一种不同的方法来回答这个问题。我不会告诉你什么不好,也不会解释原因。我将逐步详细解释为什么它不好,并向您展示如何打破它,但是我不会对Rainbow Tables太过深入……假设您知道那是什么。

这就是为什么您的开发人员的哈希值不正确的原因:因为它只是引入了一些因素,一旦发现该方法,即使他随机分配改组,这些因素也可能被完全强行使用。

如何?因为如果我可以访问您的服务器,那么我也知道您的开发人员正在使用的用于散列密码的方法,因为我也已经窃取了该代码,因此我可以重新排列所有内容以适合我的小crackpot应用程序。 />比方说,我入侵了您的公司,并获得了对您数据库的访问权限,以便我可以获取这些哈希值。我知道用户何时注册,对吗?我知道他们最后一次更改密码的原因是,除非您是一个完整的新手,否则您应该将该信息记录到数据库中。

$time = date('mdYHis');


此时间戳可能在大约用户注册或更改密码的同时。我们可以知道这一点,因为上次更新应该存储在数据库中。您注册的时间应存储在数据库中。地穴的一部分已被击败。

$rand = mt_rand().'\n';


很酷,一个随机数生成器。您知道,计算机上没有什么是真正随机的。随机数生成器并非真正随机。这是Mersenne Twister。我需要的只是624不同的组合,以找出所有将来的数字。我也从数据库中盗走了您的“盐”,而且我知道您是如何计算的。

因为我知道您的用户注册的日期,所以我知道如何在特定时间为Mersenne Twister例程重新创建正确的数字。我可以写一些破解方法来提取当时可能发生的确切数字。您的食盐不再是随机的。但是你知道吗?没关系我知道您用于该盐的确切格式,无论如何我很可能从您的数据库中获取了它。然后,我可以使用Rainbow Tables在1秒钟内彻底消灭盐,因为仅mt_rand()会产生最多10^10散列,最少10^9,这意味着110亿种可能性,并且由于它们都是数字,所以我知道格式盐,它们将在不到一秒钟的时间内被破解。

所以现在我知道此用户名属于谁了,因为我劫持了您的数据库。我知道他们何时注册,我何时最后一次更改密码以及我的随机号码。我看见你了,戴夫,屋顶上的小偷。我的新卫星链接同时具有红外光谱和X射线光谱。我看到你的心跳。我看你很害怕。

现在$crypt已被击败,让我们看一下function hash_it()

function hash_it($string1, $string2) {
    $pass = md5($string1);
    $nt = substr($pass,0,8);
    $th = substr($pass,8,8);
    $ur = substr($pass,16,8);
    $ps = substr($pass,24,8);

    $hash = 'H'.sha1($string2.$ps.$ur.$nt.$th);
    return $hash
}


现在让我们看一下一些示例输入:hash_it(Dave, testpassword1);

结果:

$pass = "b7e055c6165da55c3e12c49ae5207455"
$nt = "b7e055c6";
$th = null;
$ur = "3e12c49a";
$ps = "e5207455";


$hash Input:“ H” +“用户名+” RegistrationDate“ +” 1604716014“ +” e5207455“ +” 3e12c49a “ +” b7e055c6“(tldr:"HDaveRegistrationDate1604716014e52074553e12c49ab7e055c6"

$hash = 'H'.sha1("DaveRegistrationDate1604716014e52074553e12c49ab7e055c6);


`$ hash输出:
” 6b347a1521b6b84501806268614abe1e7324c703“;(每次都相同)

这是一种攻击的工作方式:


经过624次观察后,打破梅森·特森(mt_rand()),或者只是彩虹表盐。
从数据库中抓取戴夫的REGISTRATION_DATEUSER_LAST_MODIFIED_DATE

Grab Dave的SHA1哈希
使用以下参数发起暴力攻击(在我们破坏了“安全性”后,它变成了静态sha1哈希):


"Username" + "RegistrationDate" + YourRandomNumber + DictionaryAttack[]



警告您的客户。

这就是为什么除非您真的知道自己在做什么,否则不应该推出自己的加密技术的故事。想象一下,如果我是一个真正的骗子,而不是一个刚浏览完您的代码的人。

评论


而且,如果您假设无法访问该代码怎么办?

–怪物
15年11月24日在9:51

@monster当然我可以访问代码。它是PHP,他正在尝试保护自己的数据库,而我已经偷了它。对密码进行哈希处理的目的是在您受到攻击后保护您的用户。如果我可以保留您的数据库,则保留Web服务器上其余的重要文件是一件容易的事。

–马克·布法罗(Mark Buffalo)
2015年11月24日11:56



让我们继续聊天中的讨论。

–马克·布法罗(Mark Buffalo)
15年11月24日在15:21

@MarkBuffalo当然我可以访问代码。它是PHP,他正试图保护自己的数据库。在许多情况下,SQLi可能允许在不获取PHP文件的情况下转储数据库。当然,这也意味着Dave应该只使用胡椒,因为它可以实现相同的威胁模型,但并不是那么……坏了。

–森林
17年12月12日下午6:51