可转链接:
勤奋的小牛–加密算法SHA
SHA 算法
安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。
SHA1(英语:Secure Hash Algorithm 1,中文名:安全散列算法1)是一种密码散列函数,美国国家安全局设计,并由美国国家标准技术研究所(NIST)发布为联邦数据处理标准(FIPS)。SHA-1可以生成一个被称为消息摘要的160位(20字节)散列值,散列值通常的呈现形式为40个十六进制数。
SHA256是SHA2的一种,可产生256位的哈希值,较SHA1更加的安全
SHA-1 算法
SHA-1(Secure Hash Algorithm 1)是一种广泛使用的密码散列函数,由美国国家安全局(NSA)设计,并由美国国家标准与技术研究院(NIST)发布。SHA-1 是 SHA 家族的一部分,旨在生成固定长度的摘要(哈希值),无论输入数据的长度如何。SHA-1 已广泛应用于各种安全协议和加密技术中,如 SSL/TLS 和数字签名,但由于其安全性问题,现在逐渐被更安全的算法取代,如 SHA-256 和 SHA-3。
SHA-1 的基本特点
- 摘要长度:160 位(20 字节)。
- 输入大小:最多可以处理 264−12^{64}-1264−1 比特的消息。
- 输出:固定长度的 160 位散列值。
- 结构:基于 Merkle-Damgård 构架,使用 Davies-Meyer 压缩函数。
SHA-1 工作原理
SHA-1 的工作原理可以分为以下几个步骤:
- 预处理:
- 填充:消息首先被填充,使其长度模 512 等于 448。填充方法是在消息末尾添加一个 1 位,然后添加足够多的 0 位,使得总长度(包括 64 位的消息长度)是 512 的倍数。
- 附加长度:在填充后的消息末尾附加 64 位的消息长度表示,这样填充后的消息长度总是 512 的倍数。
- 初始化哈希值:
- 处理消息块:
- 消息被分成 512 位的块,每个块进一步被分成 16 个 32 位的字。然后对每个块进行 80 轮的处理,每轮操作包括位运算、选择函数和常数相加。
- 更新哈希值:
- 每个 512 位块的处理结果用于更新前面的哈希值,通过一系列的逻辑运算和位移操作。
- 输出:
- 所有块处理完后,五个寄存器的值连接起来,形成 **160 位(20 字节)**的散列值。
我们以单词 China 为例,如何将其进行MD5加密呢?
第一步:首先将China单词转化为ASCII码的十六进制表示方式
China的十六进制为:43 68 69 6E 61
第二步:对得到的数据 4368696E61 进行填充和附加,使其能够被512整除。
对于任意长度的明文,SHA1的明文分组过程与MD5相类似,首先需要对明文添加位数,使明文总长度为448(mod512)位。在明文后添加位的方法是第一个添加位是 1,其余都是0。然后将真正明文的长度(没有添加位以前的明文长度)以64位表示,附加于前面已添加过位的明文后,此时的明文长度正好是512位的倍数。与MD5不同的是SHA1的原始报文长度不能超过2的64次方,另外SHA1的明文长度从低位开始填充。
第三步:将得到数据进行拆分,按照512位分块。SHA1有4轮运算,每一轮包括20个步骤(一共80步),最后产生160位摘要。
SHA-1 的局限性和安全性
尽管 SHA-1 在设计之初被认为是安全的,但随着计算能力的提升和密码分析技术的发展,SHA-1 已被证明不够安全,具体表现在:
- 碰撞攻击:在 2005 年,研究人员发现可以在比预期少得多的时间内找到两个不同的输入,它们的 SHA-1 散列值相同。这种攻击称为碰撞攻击。
- 实际碰撞实例:在 2017 年,谷歌和荷兰信息安全机构联合展示了第一个实际的 SHA-1 碰撞实例,进一步证明了 SHA-1 的不安全性。
由于这些安全问题,NIST 已经在 2011 年宣布从 2013 年起不再推荐使用 SHA-1。在现代应用中,SHA-1 已被更安全的散列算法取代,如 SHA-256 和 SHA-3。
替代算法
为了提高安全性,建议使用以下替代算法:
- SHA-256:生成 **256 位(32 字节)**的散列值,是 SHA-2 家族的一部分,广泛应用于安全敏感的场景。
- SHA-3:是 SHA 家族的最新成员,基于
Keccak
算法,提供了更高的安全性和不同的内部结构。
C - SHA1 算法
在 C 语言中,可以使用 OpenSSL 库提供的 SHA-1 函数来计算 SHA-1 散列值。OpenSSL 是一个功能强大且广泛使用的加密库,提供了各种加密和哈希算法。下面是一个使用 OpenSSL 库计算 SHA-1 散列值的示例代码。
安装 OpenSSL 库
在使用 OpenSSL 库之前,需要确保系统上已安装该库。可以使用包管理器进行安装,例如在 Debian/Ubuntu 系统上:
sudo apt-get install libssl-dev
示例代码
下面的示例代码展示了如何使用 OpenSSL 库中的 SHA-1 函数来计算一个字符串的 SHA-1 散列值:
#include <stdio.h>
#include <openssl/sha.h>
int main() {
// 要散列的消息
const char *message = "Hello, world!";
unsigned char hash[SHA_DIGEST_LENGTH];
// 计算 SHA-1 散列值
SHA1((unsigned char *)message, strlen(message), hash);
// 输出散列值
printf("SHA-1 hash of the message is: ");
for (int i = 0; i < SHA_DIGEST_LENGTH; i++) {
printf("%02x", hash[i]);
}
printf("\n");
return 0;
}
实际使用
在实际使用中,会将 SHA-1 生成的散列值转换成特定需求的特殊字符,比如我想要一组 6 位带有特殊 Log 的密码, 密码由 1-9,a-z 组成
#include <stdio.h>
#include <openssl/sha.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define PASSWD_LEN 6
#define LOG "Mantic"
#define SYMBOL_NUMBERS 26
static char symbol_table[SYMBOL_NUMBERS] = {'0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'a','b','c','d','e',
'f','h','i','j','k','m','l','n','o',
'p','q','r','s','t','u','v','w','x',
'y','z'};
int main() {
// 要散列的消息
const char *message = "Hello, world!";
unsigned char hash[SHA_DIGEST_LENGTH];
static char encode[SYMBOL_NUMBERS + 1] = "";
char *input = NULL;
int input_len = 0;
input_len = strlen(message) + strlen(LOG) + 1;
input = malloc(input_len);
if(input == NULL)
{
printf("malloc error\n");
exit(-1);
}
snprintf(input,input_len, "%s%s",message, LOG);
// 计算 SHA-1 散列值
SHA1((unsigned char *)message, strlen(message), hash);
encode[PASSWD_LEN] = '\0';
// 输出散列值
for (int i = 0; i < PASSWD_LEN; i++) {
hash[i] = symbol_table[hash[i] % SYMBOL_NUMBERS];
printf("%02x", hash[i]);
}
free(input);
printf("SHA-1 Generate Password is: %s", encode);
return 0;
}
输出结果:
SHA-1 Generate Password is: j68k69
编译和运行
要编译和运行上述代码,请确保链接 OpenSSL 库:
gcc -o sha1_example sha1_example.c -lssl -lcrypto
./sha1_example
详细说明
- 包含头文件:<openssl/sha.h> 包含了 SHA-1 函数的声明。
- 定义消息:const char *message = “Hello, world!”; 定义了要计算 SHA-1 散列值的消息。
- 存储散列值:
unsigned char hash[SHA_DIGEST_LENGTH];
定义了一个数组来存储生成的 SHA-1 散列值。SHA_DIGEST_LENGTH
是 SHA-1 散列值的长度,定义在 <openssl/sha.h> 中,值为 20。 - 计算散列值:
SHA1((unsigned char *)message, strlen(message), hash)
; 调用 SHA-1 函数计算散列值。第一个参数是消息的指针,第二个参数是消息的长度,第三个参数是存储散列值的数组。 - 输出散列值:通过循环输出 hash 数组中的每个字节,以十六进制格式显示散列值。
注意事项
- 安全性:由于 SHA-1 已被证明不再安全,不推荐在新的项目中使用 SHA-1。如果需要更高的安全性,建议使用 SHA-256 或其他更安全的哈希算法。
- 库依赖:OpenSSL 是一个强大但复杂的库,依赖于系统环境和安装配置。在使用前确保正确安装并配置了库。
- 编译选项:在编译时需要链接 ssl 和 crypto 库。
更安全的 SHA-256
如果需要使用 SHA-256,可以使用 OpenSSL 的 SHA256 函数。以下是使用 SHA-256 的示例代码:
#include <stdio.h>
#include <openssl/sha.h>
int main() {
const char *message = "Hello, world!";
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256((unsigned char *)message, strlen(message), hash);
printf("SHA-256 hash of the message is: ");
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
printf("%02x", hash[i]);
}
printf("\n");
return 0;
}
编译和运行命令与之前相同:
gcc -o sha256_example sha256_example.c -lssl -lcrypto
./sha256_example
通过这些示例代码,您可以在 C 语言中使用 OpenSSL 库来计算 SHA-1 和 SHA-256 散列值。
SHA-1和SHA-256区别
SHA-1 和 SHA-256 都是安全哈希算法(Secure Hash Algorithms),它们用于生成固定长度的散列值(哈希值)来代表输入数据。这些算法的设计目的是为了在确保数据完整性、密码学和数据安全方面提供可靠的散列值。虽然它们有一些相似之处,但也有显著的区别。以下是 SHA-1 和 SHA-256 的主要区别:
基本属性和结构
SHA-1 算法
- 摘要长度:160 位(20 字节)
- 安全性:已被证明不安全,存在碰撞攻击和预映射攻击
- 结构:基于 Merkle-Damgård 构架,使用 Davies-Meyer 压缩函数
- 速度:比 SHA-256 快,但安全性较低
- 发布时间:1993 年(作为 SHA-0 的改进),1995 年正式发布
SHA-256 算法
- 摘要长度:256 位(32 字节)
- 安全性:目前认为是安全的,抗碰撞和预映射攻击能力更强
- 结构:也是基于 Merkle-Damgård 构架,但使用不同的设计细节和更多的迭代
- 速度:比 SHA-1 慢,但安全性更高
- 发布时间:2001 年,作为 SHA-2 家族的一部分发布
安全性
SHA-1
- 碰撞攻击:在 2005 年,研究人员发现 SHA-1 存在实际的碰撞攻击方法。2017 年,谷歌和荷兰信息安全机构联合展示了第一个实际的 SHA-1 碰撞实例。
- 预映射攻击:SHA-1 也更容易受到预映射攻击,这使得它在密码学应用中不再安全。
- 强度:SHA-1 的安全性被认为约为 2^63.4 次操作,比理想情况下的 2^80 次操作(160/2)要弱得多。
SHA-256
- 碰撞攻击:目前没有已知的实际碰撞攻击。
- 预映射攻击:SHA-256 提供了更强的抗预映射攻击能力。
- 强度:SHA-256 的安全性被认为约为 2^128 次操作(256/2),提供了更高的安全性。
性能
- SHA-1:由于其较短的摘要长度和较少的迭代次数,SHA-1 的计算速度通常比 SHA-256 快。然而,随着现代计算机性能的提升,这种差异在许多应用中变得不那么明显。
- SHA-256:尽管速度稍慢,但由于其更高的安全性,SHA-256 更适合安全敏感的应用。
用途
SHA-1
- 过去:曾广泛用于 SSL/TLS 证书、数字签名、版本控制系统(如 Git)等。
- 现在:由于其安全性问题,SHA-1 已经被逐渐淘汰,不再推荐用于新的安全应用。许多标准和协议已经停止支持 SHA-1。
SHA-256
- 现在和未来:广泛应用于 SSL/TLS、数字签名、区块链(如比特币)、数据完整性校验等领域。SHA-256 被认为是当前推荐使用的安全哈希算法之一。
实现和示例
以下是使用 OpenSSL 库在 C 语言中分别计算 SHA-1 和 SHA-256 散列值的示例代码。
SHA-1 示例代码
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
int main() {
const char *message = "Hello, world!";
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1((unsigned char *)message, strlen(message), hash);
printf("SHA-1 hash: ");
for (int i = 0; i < SHA_DIGEST_LENGTH; i++) {
printf("%02x", hash[i]);
}
printf("\n");
return 0;
}
**SHA-256 示例代码 **
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
int main() {
const char *message = "Hello, world!";
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256((unsigned char *)message, strlen(message), hash);
printf("SHA-256 hash: ");
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
printf("%02x", hash[i]);
}
printf("\n");
return 0;
}
总结
在加密算法中,目前使用 SHA-1 的案例还是很多,相比于 SHA-256,其安全性会更低一些,容易发生碰撞.(即不同的消息,产生了相同的散列值). 建议都试用 SHA-256 算法.