SHA算法(及示例)演变历史
安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。
家族成员
SHA家族的五个算法,分别是SHA-1、SHA-224、SHA-256、SHA-384,和SHA-512,由美国国家安全局(NSA)所设计,并由美国国家标准与技术研究院(NIST)发布;是美国的政府标准。后四者有时并称为SHA-2。SHA-1在许多安全协定中广为使用,包括TLS和SSL、PGP、SSH、S/MIME和IPsec,曾被视为是MD5(更早之前被广为使用的杂凑函数)的后继者。但SHA-1的安全性如今被密码学家严重质疑;虽然至今尚未出现对SHA-2有效的攻击,它的算法跟SHA-1基本上仍然相似;因此有些人开始发展其他替代的杂凑算法。 [1]
SHA-0和1
SHA-0破解
SHA-1破解
SHA-1算法
Initialize variables: h0 := 0x67452301 h1 := 0xEFCDAB89 h2 := 0x98BADCFE h3 := 0x10325476 h4 := 0xC3D2E1F0 Pre-processing: append the bit '1' to the message append k bits '0', where k is the minimum number >= 0 such that the resulting message length (in bits) is congruent to 448 (mod 512) append length of message (before pre-processing), in bits, as 64-bit big-endian integer Process the message in successive 512-bit chunks: break message into 512-bit chunks for each chunk break chunk into sixteen 32-bit big-endian words w[i], 0 ≤ i ≤ 15 Extend the sixteen 32-bit words into eighty 32-bit words: for i from 16 to 79 w[i] := (w[i-3] xor w[i-8] xor w[i-14] xor w[i-16]) leftrotate 1 Initialize hash value for this chunk: a := h0 b := h1 c := h2 d := h3 e := h4 Main loop: for i from 0 to 79 if 0 ≤ i ≤ 19 then f := (b and c) or ((not b) and d) k := 0x5A827999 else if 20 ≤ i ≤ 39 f := b xor c xor d k := 0x6ED9EBA1 else if 40 ≤ i ≤ 59 f := (b and c) or (b and d) or (c and d) k := 0x8F1BBCDC else if 60 ≤ i ≤ 79 f := b xor c xor d k := 0xCA62C1D6 temp := (a leftrotate 5) + f + e + k + w[i] e := d d := c c := b leftrotate 30 b := a a := temp Add this chunk's hash to result so far: h0 := h0 + a h1 := h1 + b h2 := h2 + c h3 := h3 + d h4 := h4 + e Produce the final hash value (big-endian): digest = hash = h0 append h1 append h2 append h3 append h4
SHA-2
应用
哈希表介绍
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
15 111 % 15
问题
有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,名字,住址..),当输入该员工的id时,要求查找到该员工的 所有信息.
要求:
不使用数据库,,速度越快越好=>哈希表(散列)
添加时,保证按照id从低到高插入 [课后思考:如果id不是从低到高插入,但要求各条链表仍是从低到高,怎么解决?]
使用链表来实现哈希表, 该链表不带表头[即: 链表的第一个结点就存放雇员信息]
思路分析并画出示意图
代码实现[增删改查(显示所有员工,按id查询)]
代码实现
1 package cn.smallmartial.hashTable; 2 3 import java.util.HashMap; 4 import java.util.Scanner; 5 6 /** 7 * @Author smallmartial 8 * @Date 2019/6/13 9 * @Email smallmarital@qq.com 10 */ 11 public class HashTableDemo { 12 13 public static void main(String[] args) { 14 //创建hash表 15 HashTab hashTab = new HashTab(7); 16 17 //写一个简单的菜单 18 String key = ""; 19 Scanner scanner = new Scanner(System.in); 20 while(true) { 21 System.out.println("add: 添加雇员"); 22 System.out.println("list: 显示雇员"); 23 System.out.println("find: 查找雇员"); 24 System.out.println("exit: 退出系统"); 25 26 key = scanner.next(); 27 switch (key) { 28 case "add": 29 System.out.println("输入id"); 30 int id = scanner.nextInt(); 31 System.out.println("输入名字"); 32 String name = scanner.next(); 33 //创建 雇员 34 Emp emp = new Emp(id, name); 35 hashTab.add(emp); 36 break; 37 case "list": 38 hashTab.list(); 39 break; 40 case "find": 41 System.out.println("请输入要查找的id"); 42 id = scanner.nextInt(); 43 hashTab.findEmpById(id); 44 break; 45 case "exit": 46 scanner.close(); 47 System.exit(0); 48 default: 49 break; 50 } 51 } 52 } 53 } 54 //创建hashTab 55 class HashTab{ 56 private int size; 57 private EmpLinkedList[] empLinkedListArray; 58 59 public HashTab(int size) { 60 this.size = size; 61 empLinkedListArray = new EmpLinkedList[size]; 62 63 for (int i = 0; i < size; i++) { 64 empLinkedListArray[i] = new EmpLinkedList(); 65 } 66 67 } 68 69 //添加雇员 70 public void add(Emp emp){ 71 //根据员工ID 添加到哪条联 72 int hashFun = hashFun(emp.id); 73 empLinkedListArray[hashFun].add(emp); 74 75 } 76 77 //遍历链表 78 public void list(){ 79 for (int i = 0; i < size; i++) { 80 empLinkedListArray[i].list(i); 81 } 82 } 83 84 //根据输入的id,查找雇员 85 public void findEmpById(int id) { 86 //使用散列函数确定到哪条链表查找 87 int empLinkedListNO = hashFun(id); 88 Emp emp = empLinkedListArray[empLinkedListNO].findEmpById(id); 89 if(emp != null) {//找到 90 System.out.printf("在第%d条链表中找到 雇员 id = %d\n", (empLinkedListNO + 1), id); 91 }else{ 92 System.out.println("在哈希表中,没有找到该雇员~"); 93 } 94 } 95 public int hashFun(int id){ 96 return id % size; 97 } 98 } 99 //表示雇员 100 class Emp { 101 public int id; 102 public String name; 103 public Emp next; 104 105 public Emp(int id, String name) { 106 this.id = id; 107 this.name = name; 108 } 109 } 110 //表示链表 111 class EmpLinkedList{ 112 private Emp head; 113 114 public void add(Emp emp){ 115 if (head == null){ 116 head = emp; 117 return; 118 } 119 120 Emp curEmp = head; 121 while (true){ 122 if (curEmp.next == null){ 123 break; 124 } 125 curEmp = curEmp.next; 126 } 127 curEmp.next = emp; 128 } 129 130 //遍历 131 public void list(int no){ 132 if (head == null){ 133 System.out.println("第"+no+"前链表为空"); 134 return; 135 } 136 System.out.print("第"+no+"链表信息为:"); 137 Emp curEmp = head; 138 while (true){ 139 System.out.print(curEmp.id+"=>"+curEmp.name); 140 if (curEmp.next == null){ 141 break; 142 } 143 curEmp = curEmp.next; 144 } 145 System.out.println(); 146 } 147 148 //根据id查找雇员 149 //如果查找到,就返回Emp, 如果没有找到,就返回null 150 public Emp findEmpById(int id) { 151 //判断链表是否为空 152 if(head == null) { 153 System.out.println("链表为空"); 154 return null; 155 } 156 //辅助指针 157 Emp curEmp = head; 158 while(true) { 159 if(curEmp.id == id) {//找到 160 break;//这时curEmp就指向要查找的雇员 161 } 162 //退出 163 if(curEmp.next == null) {//说明遍历当前链表没有找到该雇员 164 curEmp = null; 165 break; 166 } 167 curEmp = curEmp.next;//以后 168 } 169 170 return curEmp; 171 } 172 }