关于安全性:哈希和加密算法之间的根本区别

Fundamental difference between Hashing and Encryption algorithms

我看到散列和加密算法之间有很多混淆,我想听听关于以下方面的专家建议:

  • 何时使用哈希与加密

  • 是什么使哈希或加密算法不同(从理论/数学层面)也就是说,是什么使得哈希不可逆(没有彩虹树的帮助)

  • 以下是一些类似的问题,没有像我所寻找的那样详细:

    混淆、散列和加密之间有什么区别?加密和哈希的区别


    嗯,你可以在维基百科上查到…但既然你想要解释,我会尽我所能:好的。哈希函数

    它们提供任意长度输入和(通常)固定长度(或更小长度)输出之间的映射。它可以是任何东西,从一个简单的CRC32,到一个完整的密码散列函数,如MD5或SHA1/2/256/512。关键是有一个单向映射正在进行。它总是一个多:1映射(意味着总是会有冲突),因为每个函数产生的输出都小于它能够输入的输出(如果将每个可能的1MB文件馈送到MD5中,就会产生大量的冲突)。好的。

    它们很难(或在实践中不可能)逆转的原因是它们内部的工作方式。大多数加密散列函数多次迭代输入集以生成输出。因此,如果我们查看每个固定长度的输入块(这取决于算法),散列函数将把它称为当前状态。然后,它将遍历状态并将其更改为新状态,并将其用作自身的反馈(MD5对每个512位数据块执行64次此操作)。然后它以某种方式将所有这些迭代的结果状态组合在一起,形成结果散列。好的。

    现在,如果您想对散列进行解码,首先需要弄清楚如何将给定的散列分解为其迭代状态(1对于小于数据块大小的输入,有可能是较大的输入)。然后您需要为每个状态反转迭代。现在,为了解释为什么这是非常困难的,想象一下从下面的公式中推导ab10 = a + bab共有10种有效的正组合。现在把它循环几次:tmp = a + b; a = b; b = tmp。对于64次迭代,您可以尝试10^64次以上的可能性。这只是一个简单的添加,在这个添加中,从迭代到迭代都会保留一些状态。真正的哈希函数执行的操作远不止一个(MD5对4个状态变量执行大约15个操作)。由于下一次迭代依赖于前一次的状态,而前一次在创建当前状态时会被破坏,所以几乎不可能确定导致给定输出状态的输入状态(对于每个迭代不少于)。结合这一点,再加上涉及到的大量可能性,即使是MD5的解码也将需要近乎无限(但不是无限)的资源量。这么多的资源,如果您知道输入的大小(对于较小的输入),那么强制散列实际上要比尝试解码散列便宜得多。好的。加密函数

    它们提供任意长度输入和输出之间的1:1映射。它们总是可逆的。需要注意的是,使用某种方法它是可逆的。对于一个给定的键,它总是1:1。现在,有多个输入:可能会生成相同输出的密钥对(事实上,通常会有,这取决于加密功能)。好的加密数据与随机噪声是不可区分的。这与良好的哈希输出不同,哈希输出的格式总是一致的。好的。用例

    当您想比较一个值,但无法存储纯表示形式(出于任何原因)时,请使用哈希函数。密码应该非常适合这个用例,因为出于安全原因,您不想将它们以纯文本的形式存储(也不应该)。但是,如果您想检查文件系统中是否有盗版音乐文件呢?每个音乐文件存储3 MB是不切实际的。因此,取文件的散列值并存储它(MD5将存储16个字节,而不是3MB)。这样,您只需散列每个文件,并将其与存储的散列数据库进行比较(由于重新编码、更改文件头等原因,这在实践中效果不佳,但它是一个示例用例)。好的。

    检查输入数据的有效性时使用哈希函数。这就是他们设计的目的。如果您有两个输入,并且想要检查它们是否相同,那么可以通过一个哈希函数来运行这两个输入。对于小的输入大小(假设有一个好的哈希函数),碰撞的概率在天文学上是很低的。这就是为什么推荐使用密码的原因。对于最多32个字符的密码,MD5有4倍的输出空间。sha1有6倍的输出空间(大约)。sha512的输出空间约为16倍。你真的不在乎密码是什么,你在乎它是否与存储的密码相同。这就是为什么你应该使用哈希作为密码。好的。

    每当需要将输入数据取出时,都要使用加密。注意单词need。如果您存储的是信用卡号码,您需要在某个时候将其取出,但不希望存储为纯文本。因此,存储加密版本并尽可能地保持密钥的安全性。好的。

    哈希函数也非常适合对数据进行签名。例如,如果您使用的是hmac,您可以通过获取与已知但未传输的值(一个秘密值)相连的数据散列来对一段数据进行签名。所以,您发送纯文本和HMAC哈希。然后,接收器简单地用已知值对提交的数据进行散列,并检查它是否与发送的HMAC匹配。如果它是相同的,你知道它没有被一个没有秘密价值的人篡改。这通常在HTTP框架的安全cookie系统中使用,也可以在HTTP上的数据消息传输中使用,在这种情况下,您需要保证数据的完整性。好的。有关密码哈希的说明:

    加密散列函数的一个关键特性是,它们应该创建得非常快,并且非常难/很慢地进行反转(如此之多以至于实际上不可能)。这会对密码造成问题。如果你储存了sha512(password),你就不会做任何事情来防御彩虹桌或蛮力攻击。记住,哈希函数是为速度而设计的。所以对于攻击者来说,仅仅通过散列函数运行字典并测试每个结果是很简单的。好的。

    添加salt有助于解决问题,因为它会向哈希添加一些未知数据。因此,他们不需要找到任何与md5(foo)匹配的东西,而是需要找到某种东西,当添加到已知的盐中时,就会产生md5(foo.salt),这很难做到。但它仍然不能解决速度问题,因为如果他们知道盐的含量,那只是查字典的问题。好的。

    所以,有很多方法可以解决这个问题。一种流行的方法被称为关键强化(或关键拉伸)。基本上,您可以多次迭代散列(通常是数千次)。这有两件事。首先,它显著降低了哈希算法的运行时间。其次,如果实现正确(在每次迭代中传递输入和salt),实际上会增加输出的熵(可用空间),从而减少发生冲突的机会。一个简单的实现是:好的。

    1
    2
    3
    4
    var hash = password + salt;
    for (var i = 0; i < 5000; i++) {
        hash = sha512(hash + password + salt);
    }

    还有其他更标准的实现,如pbkdf2、bcrypt。但这种技术被相当多的安全相关系统(如PGP、WPA、Apache和OpenSSL)使用。好的。

    底线是,hash(password)不够好。hash(password + salt)比较好,但还不够好…使用扩展哈希机制生成密码哈希…好的。关于小拉伸的另一个注记

    在任何情况下,都不要将一个哈希的输出直接送回哈希函数:好的。

    1
    2
    3
    4
    hash = sha512(password + salt);
    for (i = 0; i < 1000; i++) {
        hash = sha512(hash); // <-- Do NOT do this!
    }

    这与碰撞有关。请记住,所有哈希函数都有冲突,因为可能的输出空间(可能的输出数量)小于输入空间。为了了解原因,我们来看看会发生什么。首先,让我们假设有0.001%的几率与sha1()发生碰撞(实际上要低得多,但用于演示)。好的。

    1
    hash1 = sha1(password + salt);

    现在,hash1的碰撞概率为0.001%。但当我们进行下一个hash2 = sha1(hash1);时,hash1的所有碰撞都会自动变成hash2的碰撞。所以现在,hash1的比率是0.001%,第二个sha1()调用也增加了这个比率。所以现在,hash2的碰撞概率为0.002%。机会是原来的两倍!每次迭代都会给结果增加另一个0.001%碰撞的机会。因此,经过1000次迭代,碰撞的概率从0.001%跳到1%。现在,退化是线性的,实际概率要小得多,但效果是一样的(估计与md5发生单次碰撞的概率约为1/(2128)或1/(3x1038)。虽然这看起来很小,但由于生日攻击,它并不像看上去那么小)。好的。

    相反,通过每次重新附加salt和密码,您将把数据重新引入哈希函数。所以任何一个特定圆的碰撞都不再是下一个圆的碰撞。所以:好的。

    1
    2
    3
    4
    hash = sha512(password + salt);
    for (i = 0; i < 1000; i++) {
        hash = sha512(hash + password + salt);
    }

    与本机sha512函数具有相同的碰撞几率。这就是你想要的。用那个代替。好的。好啊。


    散列函数可以被认为与烤面包一样。你从输入(面粉、水、酵母等)开始,然后应用散列函数(混合+烘焙),你最终得到一个输出:一条面包。

    另一种方法是非常困难的-你不能真正地把面包分回到面粉,水,酵母-其中一些是在烘焙过程中丢失的,你永远不能确切地知道有多少水,面粉或酵母被用于一个特定的面包,因为信息被散列功能(也就是烤箱)破坏。

    理论上,许多不同的输入变量将产生相同的面包(例如,2杯水和1 tsbp的酵母产生与2.1杯水和0.9tsbp的酵母完全相同的面包),但如果有一个这样的面包,你就不能确切地知道是什么输入组合产生的。

    另一方面,加密可以被视为一个保险箱。无论你放在那里的是什么,只要你拥有锁在那里的钥匙,它就会回来。这是一个对称操作。给定一个键和一些输入,您将得到一个特定的输出。给定输出和相同的键,您将得到原始输入。这是一个1:1的映射。


    当您不想返回原始输入时,使用哈希,当您返回时使用加密。

    哈希取一些输入并将其转换为一些位(通常被认为是一个数字,如32位整数、64位整数等)。相同的输入总是会产生相同的哈希值,但是您在这个过程中主要会丢失信息,因此您不能可靠地复制原始输入(不过,有一些警告)。

    加密主要保留您输入到加密函数中的所有信息,只是使任何人在没有特定密钥的情况下都很难(理想情况下不可能)还原到原始输入。

    散列的简单示例

    下面是一个简单的例子,帮助您理解为什么哈希不能(在一般情况下)返回原始输入。假设我正在创建一个1位哈希。我的hash函数接受一个位字符串作为输入,如果在输入字符串中设置了偶数,则将hash设置为1;如果设置了奇数,则将hash设置为0。

    例子:

    1
    2
    3
    4
    5
    Input    Hash
    0010     0
    0011     1
    0110     1
    1000     0

    请注意,有许多输入值会导致散列值为0,还有许多输入值会导致散列值为1。如果知道散列值为0,则无法确定原始输入是什么。

    顺便说一下,这个1位散列不是完全人为的…看看奇偶校验位。

    加密的简单示例

    您可以使用简单的字母替换来加密文本,例如,如果输入是A,则写入B。如果输入是B,则写入C。一直到字母表的末尾,如果输入是Z,则再次写入A。

    1
    2
    3
    Input   Encrypted
    CAT     DBU
    ZOO     APP

    就像简单的哈希示例一样,这种类型的加密在历史上也曾被使用过。


    散列和加密/解密技术的基本概述如下。

    Hashing:

    If you hash any plain text again you can not get the same plain
    text from hashed text. Simply, It's a one-way process.

    hashing

    Encryption and Decryption:

    If you encrypt any plain text with a key again you can
    get same plain text by doing decryption on encrypted text with same(symetric)/diffrent(asymentric) key.

    encryption and decryption

    更新:解决编辑问题中提到的问题。

    1. When to use hashes vs encryptions

    如果你想给别人发送一个文件,散列是很有用的。但您担心其他人可能会截取并更改该文件。所以A收件人确保文件正确的方法是您将散列值公开发布。这样收件人就可以计算接收的文件的哈希值,并检查它是否与哈希匹配价值。

    如果你说有消息要发送给某人,那么加密是很好的。您用密钥加密邮件,收件人用相同的(甚至可能是不同的)键来返回原始消息。信用

    2. What makes a hash or encryption algorithm different (from a theoretical/mathematical level) i.e. what makes hashes irreversible
    (without aid of a rainbow tree)

    基本上,哈希是一个丢失信息但不加密的操作。让我们来看一看简单数学方法的差异,便于我们理解,当然,两者都有更复杂的数学运算它涉及的重复

    Encryption/Decryption (Reversible):

    Addition:

    1
    4 + 3 = 7

    This can be reversed by taking the sum and subtracting one of the
    addends

    1
    7 - 3 = 4

    Multiplication:

    1
    4 * 5 = 20

    This can be reversed by taking the product and dividing by one of the
    factors

    1
    20 / 4 = 5

    So, here we could assume one of the addends/factors is a decrpytion key and result(7,20) is an excrypted text.

    Hashing (Not Reversible):

    Modulo division:

    1
    22 % 7 = 1

    This can not be reversed because there is no operation that you can do to the quotient and the dividend to
    reconstitute the divisor (or vice versa).

    Can you find an operation to fill in where the '?' is?

    1
    2
    1  ?  7 = 22  
    1  ?  22 = 7

    So hash functions have the same mathematical quality as modulo division and looses the information.

    信用

    < /块引用>


    我的一行…一般来说,面试官想要下面的答案。

    散列是一种方法。无法从哈希代码转换数据/字符串。

    加密是双向的-如果你带着密钥,你可以再次解密加密的字符串。


    哈希函数将可变大小的文本转换为固定大小的文本。

    Hash

    来源:https://en.wikipedia.org/wiki/hash_函数

    让我们看看它的作用。我用了PHP。

    搞砸:

    1
    2
    3
    $str = 'My age is 29';
    $hash = hash('sha1', $str);
    echo $hash; // OUTPUT: 4d675d9fbefc74a38c89e005f9d776c75d92623e

    德哈什:

    sha1是单向散列。这就意味着你不能把土豆泥脱毛。但是,您可以暴力地强制散列。请参阅:https://hashkiller.co.uk/sha1-decrypter.aspx。

    MD5是另一个哈希。MD5脱氢器可在以下网址找到:https://www.md5online.org/。

    加密函数使用加密密钥将文本转换为无意义的密文,反之亦然。enter image description here

    来源:https://en.wikipedia.org/wiki/encryption

    让我们深入研究一些处理加密的PHP代码。

    ——mcrypt扩展---

    加密:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $cipher = MCRYPT_RIJNDAEL_128;
    $key = 'A_KEY';
    $data = 'My age is 29';
    $mode = MCRYPT_MODE_ECB;

    $encryptedData = mcrypt_encrypt($cipher, $key , $data , $mode);
    var_dump($encryptedData);

    //OUTPUT:
    string '?ùòyaq3?ì?üàp?' (length=16)

    解密:

    1
    2
    3
    4
    5
    6
    $decryptedData = mcrypt_decrypt($cipher, $key , $encryptedData, $mode);
    $decryptedData = rtrim($decryptedData,"\0\4"); // Remove the nulls and EOTs at the END
    var_dump($decryptedData);

    //OUTPUT:
    string 'My age is 29' (length=12)

    ——OpenSSL扩展---

    Mcrypt扩展在7.1中被弃用。并在php 7.2中删除。在php 7中应该使用openssl扩展。请参见下面的代码段:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $key = 'A_KEY';
    $data = 'My age is 29';

    // ENCRYPT
    $encryptedData = openssl_encrypt($data , 'AES-128-CBC', $key, 0, 'IV_init_vector01');
    var_dump($encryptedData);

    // DECRYPT    
    $decryptedData = openssl_decrypt($encryptedData, 'AES-128-CBC', $key, 0, 'IV_init_vector01');
    var_dump($decryptedData);

    //OUTPUT
    string '4RJ8+18YkEd7Xk+tAMLz5Q==' (length=24)
    string 'My age is 29' (length=12)


    对称加密:

    对称加密也可以称为共享密钥或共享秘密加密。在对称加密中,使用一个密钥来加密和解密通信。

    enter image description here

    非对称加密:

    非对称加密也称为公钥加密。非对称加密与对称加密的主要区别在于使用了两个密钥:一个用于加密,另一个用于解密。最常见的非对称加密算法是RSA

    与对称加密相比,非对称加密带来了很高的计算负担,而且往往要慢得多。因此,它通常不用于保护有效载荷数据。相反,它的主要优势在于能够在不安全的媒体(例如互联网)上建立安全通道。这是通过交换公钥来实现的,公钥只能用于加密数据。互补的私有密钥从不共享,用于解密。

    enter image description here

    散列:

    最后,哈希是一种不同于加密的加密安全形式。虽然加密是一个两步过程,用于先加密然后解密消息,但是散列将消息压缩为不可逆的固定长度值(hash)。网络中最常见的两种散列算法是MD5SHA-1

    enter image description here

    阅读更多信息:http://packetlife.net/blog/2010/nov/23/symmetric-asymmetric-encryption-hashing/


    加密和哈希算法的工作方式类似。在每种情况下,都需要在位之间创建混淆和扩散。归根结底,混淆是在密钥和密文之间建立一种复杂的关系,而扩散则是传播每一位的信息。

    许多哈希函数实际上使用加密算法(或加密算法的基元)。例如,sha-3候选skein使用threefish作为底层方法来处理每个块。区别在于,它们不是保留每一个密文块,而是以破坏性的、确定性的方式合并到一个固定的长度上。


    当涉及到传输数据的安全性,即双向通信时,使用加密。所有加密都需要密钥。

    当涉及到授权时,使用散列。散列中没有键

    散列获取任意数量的数据(二进制或文本),并创建一个表示数据校验和的等长散列。例如,哈希值可能是16个字节。不同的哈希算法产生不同大小的哈希。显然,您不能从散列重新创建原始数据,但是您可以再次散列数据以查看是否生成相同的散列值。基于Unix的密码单向工作。密码存储为散列值,为了登录到系统,您输入的密码将被散列,散列值将与实际密码的散列值进行比较。如果匹配,则必须键入正确的密码

    为什么散列是不可逆的:

    哈希不可逆,因为哈希映射的输入不是1到1。将两个输入映射到相同的哈希值通常被称为"哈希冲突"。为了安全起见,"好"散列函数的一个特性是在实际使用中很少发生冲突。


  • 当您只需要走一条路时,使用哈希。例如,对于系统中的密码,您使用散列,因为您将只验证用户在散列后输入的值是否与存储库中的值匹配。有了加密,你可以走两条路。

  • 哈希算法和加密算法只是数学算法。所以在这方面,它们并没有什么不同——只是数学公式而已。不过,从语义上讲,散列(单向)和加密(双向)之间有很大的区别。为什么哈希是不可逆的?因为它们被设计成那样,因为有时候你想要一个单向操作。


  • 密码术处理数字和字符串。基本上,整个宇宙中的所有数字事物都是数字。当我说数字时,它是0&1。你知道它们是什么,二进制的。你在屏幕上看到的图像,你通过耳机听的音乐,一切都是二进制的。但是我们的耳朵和眼睛不会理解双星对吗?只有大脑才能理解这一点,即使它能理解二进制文件,它也不能享受二进制文件。因此,我们将二进制文件转换为人类可理解的格式,如MP3、JPG等。让我们把这个过程称为编码。它是双向的过程,可以很容易地解码回原来的形式。好的。

    哈希好的。

    哈希是另一种加密技术,在这种技术中,一旦数据转换成其他形式,就永远无法恢复。在外行看来,没有所谓的去散列过程。有很多散列函数可以完成这项工作,如sha-512、md5等。好的。

    如果原始值无法恢复,那么我们在哪里使用它?密码!当您为手机或PC设置密码时,会创建密码散列并将其存储在安全的地方。下次尝试登录时,输入的字符串将再次使用相同的算法(散列函数)散列,并且输出与存储值匹配。如果相同,您将登录。否则你会被赶出去。好的。

    学分:维基媒体通过对密码应用hash,我们可以确保即使攻击者窃取了存储的密码文件,他也永远不会得到我们的密码。攻击者将拥有密码的散列值。他可能会找到一个最常用的密码列表,然后将sha-512应用于每个密码,并将其与手中的值进行比较。这叫做字典攻击。但他会这样做多久?如果您的密码足够随机,您认为这种破解方法会起作用吗?facebook、google和amazon数据库中的所有密码都是散列的,或者至少应该是散列的。好的。

    然后是加密好的。

    加密介于哈希和编码之间。编码是一个双向过程,不应用于提供安全性。加密也是一个双向过程,但只有在已知加密密钥的情况下才能检索原始数据。如果您不知道加密是如何工作的,不用担心,我们将在这里讨论基础知识。这足以理解SSL的基础知识。因此,有两种加密类型,即对称加密和非对称加密。好的。

    对称密钥加密好的。

    我尽量保持简单。所以,让我们用移位算法来理解对称加密。该算法通过将字母向左或向右移动来加密字母。让我们采用字符串加密并考虑一个数字+3。然后,加密的格式将是fubswr。这意味着每个字母向右移动3个位置。这里,单词crypto被称为明文,输出fubswr被称为密文,值+3被称为加密密钥(对称密钥),整个过程是一个密码。这是最古老的基本对称密钥加密算法之一,它的首次使用是在凯撒大帝时期报告的。所以,它是以他的名字命名的,是著名的凯撒密码。任何一个知道加密密钥的人,都可以应用凯撒算法的反向,并检索原始的明文。因此,它被称为对称加密。好的。

    非对称密钥加密好的。

    我们知道,在对称加密中,相同的密钥用于加密和解密。一旦那把钥匙被偷了,所有的数据都不见了。这是一个巨大的风险,我们需要更复杂的技术。1976年,Whitfield Diffie和Martin Hellman首次发布了非对称加密的概念,该算法被称为Diffie–Hellman密钥交换。1978年,麻省理工学院的罗恩·里维斯、阿迪·沙米尔和伦纳德·阿德尔曼发布了RSA算法。这些可以被认为是非对称密码学的基础。好的。

    与对称加密相比,在非对称加密中,有两个密钥而不是一个。一个称为公钥,另一个称为私钥。理论上,在启动期间,我们可以为我们的机器生成公钥-私钥对。私钥应该保存在一个安全的地方,不应该与任何人共享。如名称所示,公钥可以与任何希望向您发送加密文本的人共享。现在,拥有公共密钥的人可以用它加密秘密数据。如果密钥对是使用RSA算法生成的,那么它们在加密数据时应该使用相同的算法。通常算法将在公钥中指定。加密的数据只能用您拥有的私钥解密。好的。

    来源:ssl/tls for dummies第1部分:密码套件、哈希、加密wst(https://www.wst.space/ssl-part1-ciphersuite-hashing-encryption/)好的。好啊。


    EncryptionThe Purpose of encryption is to transform data in order to keep it secret E.g (Sending someone a secret text that they only should able to read,sending passwords through Internet).

    Instead of focusing the usability the goal is to ensure the data send can be send secretely and it can only seen by the user whom you sent.

    It Encrypts the data into another format of transforming it into unique pattern it can be encrypt with the secret key and those users who having the secret key can able to see the message by reversible the process.
    E.g(AES,BLOWFISH,RSA)

    The encryption may simply look like this FhQp6U4N28GITVGjdt37hZN

    Hashing In technically we can say it as takes a arbitary input and produced a fixed length string.

    Most important thing in these is you can't go from the output to the input.It prodeuce the strong ouptut that the given information has not been modified.
    The process is to takes a input and hash it and then send with the sender's private key once the receiver received they can validate it with sender's public key.

    If the hash is wrong and did't match with hash we can't see any of the information. E.g(MD5,SHA.....)