安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准 (Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。 SHA1有如下特性:不可以从消息摘要中复原信息;两个不同的消息不会产生同样的消息摘要,(但会有1x10 ^ 48分之一的机率出现相同的消息摘要,一般使用时忽略)。
(注:最后有案例代码)
术语和概念
位,字节和字
运算符和符号
SHA1算法描述
补位
补长度
使用的常量
使用的函数
计算消息摘要
public class SHA1 {
private final int[] abcde = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
// 摘要数据存储数组
private int[] digestInt = new int[5];
// 计算过程中的临时数据存储数组
private int[] tmpData = new int[80]; // 计算sha-1摘要
private int process_input_bytes(byte[] bytedata) {
// 初试化常量
System.arraycopy(abcde, 0, digestInt, 0, abcde.length);
// 格式化输入字节数组,补10及长度数据
byte[] newbyte = byteArrayFormatData(bytedata);
// 获取数据摘要计算的数据单元个数
int MCount = newbyte.length / 64;
// 循环对每个数据单元进行摘要计算
for (int pos = 0; pos < MCount; pos++) {
// 将每个单元的数据转换成16个整型数据,并保存到tmpData的前16个数组元素中
for (int j = 0; j < 16; j++) {
tmpData[j] = byteArrayToInt(newbyte, (pos * 64) + (j * 4));
}
// 摘要计算函数
encrypt();
}
return 20;
} // 格式化输入字节数组格式
private byte[] byteArrayFormatData(byte[] bytedata) {
// 补0数量
int zeros = 0;
// 补位后总位数
int size = 0;
// 原始数据长度
int n = bytedata.length;
// 模64后的剩余位数
int m = n % 64;
// 计算添加0的个数以及添加10后的总长度
if (m < 56) {
zeros = 55 - m;
size = n - m + 64;
} else if (m == 56) {
zeros = 63;
size = n + 8 + 64;
} else {
zeros = 63 - m + 56;
size = (n + 64) - m + 64;
}
// 补位后生成的新数组内容
byte[] newbyte = new byte[size];
// 复制数组的前面部分
System.arraycopy(bytedata, 0, newbyte, 0, n);
// 获得数组Append数据元素的位置
int l = n;
// 补1操作
newbyte[l++] = (byte) 0x80;
// 补0操作
for (int i = 0; i < zeros; i++) {
newbyte[l++] = (byte) 0x00;
}
// 计算数据长度,补数据长度位共8字节,长整型
long N = (long) n * 8;
byte h8 = (byte) (N & 0xFF);
byte h7 = (byte) ((N >> 8) & 0xFF);
byte h6 = (byte) ((N >> 16) & 0xFF);
byte h5 = (byte) ((N >> 24) & 0xFF);
byte h4 = (byte) ((N >> 32) & 0xFF);
byte h3 = (byte) ((N >> 40) & 0xFF);
byte h2 = (byte) ((N >> 48) & 0xFF);
byte h1 = (byte) (N >> 56);
newbyte[l++] = h1;
newbyte[l++] = h2;
newbyte[l++] = h3;
newbyte[l++] = h4;
newbyte[l++] = h5;
newbyte[l++] = h6;
newbyte[l++] = h7;
newbyte[l++] = h8;
return newbyte;
} private int f1(int x, int y, int z) {
return (x & y) | (~x & z);
} private int f2(int x, int y, int z) {
return x ^ y ^ z;
} private int f3(int x, int y, int z) {
return (x & y) | (x & z) | (y & z);
} private int f4(int x, int y) {
return (x << y) | x >>> (32 - y);
} // 单元摘要计算函数
private void encrypt() {
for (int i = 16; i <= 79; i++) {
tmpData[i] = f4(tmpData[i - 3] ^ tmpData[i - 8] ^ tmpData[i - 14] ^ tmpData[i - 16], 1);
}
int[] tmpabcde = new int[5];
for (int i1 = 0; i1 < tmpabcde.length; i1++) {
tmpabcde[i1] = digestInt[i1];
}
for (int j = 0; j <= 19; j++) {
int tmp = f4(tmpabcde[0], 5) + f1(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + tmpData[j]
+ 0x5a827999;
tmpabcde[4] = tmpabcde[3];
tmpabcde[3] = tmpabcde[2];
tmpabcde[2] = f4(tmpabcde[1], 30);
tmpabcde[1] = tmpabcde[0];
tmpabcde[0] = tmp;
}
for (int k = 20; k <= 39; k++) {
int tmp = f4(tmpabcde[0], 5) + f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + tmpData[k]
+ 0x6ed9eba1;
tmpabcde[4] = tmpabcde[3];
tmpabcde[3] = tmpabcde[2];
tmpabcde[2] = f4(tmpabcde[1], 30);
tmpabcde[1] = tmpabcde[0];
tmpabcde[0] = tmp;
}
for (int l = 40; l <= 59; l++) {
int tmp = f4(tmpabcde[0], 5) + f3(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + tmpData[l]
+ 0x8f1bbcdc;
tmpabcde[4] = tmpabcde[3];
tmpabcde[3] = tmpabcde[2];
tmpabcde[2] = f4(tmpabcde[1], 30);
tmpabcde[1] = tmpabcde[0];
tmpabcde[0] = tmp;
}
for (int m = 60; m <= 79; m++) {
int tmp = f4(tmpabcde[0], 5) + f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + tmpData[m]
+ 0xca62c1d6;
tmpabcde[4] = tmpabcde[3];
tmpabcde[3] = tmpabcde[2];
tmpabcde[2] = f4(tmpabcde[1], 30);
tmpabcde[1] = tmpabcde[0];
tmpabcde[0] = tmp;
}
for (int i2 = 0; i2 < tmpabcde.length; i2++) {
digestInt[i2] = digestInt[i2] + tmpabcde[i2];
}
for (int n = 0; n < tmpData.length; n++) {
tmpData[n] = 0;
}
} // 4字节数组转换为整数
private int byteArrayToInt(byte[] bytedata, int i) {
return ((bytedata[i] & 0xff) << 24) | ((bytedata[i + 1] & 0xff) << 16) | ((bytedata[i + 2] & 0xff) << 8)
| (bytedata[i + 3] & 0xff);
} // 整数转换为4字节数组
private void intToByteArray(int intValue, byte[] byteData, int i) {
byteData[i] = (byte) (intValue >>> 24);
byteData[i + 1] = (byte) (intValue >>> 16);
byteData[i + 2] = (byte) (intValue >>> 8);
byteData[i + 3] = (byte) intValue;
} // 将字节转换为十六进制字符串
private static String byteToHexString(byte ib) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char[] ob = new char[2];
ob[0] = Digit[(ib >>> 4) & 0X0F];
ob[1] = Digit[ib & 0X0F];
String s = new String(ob);
return s;
} // 将字节数组转换为十六进制字符串
private static String byteArrayToHexString(byte[] bytearray) {
String strDigest = "";
for (int i = 0; i < bytearray.length; i++) {
strDigest += byteToHexString(bytearray[i]);
}
return strDigest;
} // 计算sha-1摘要,返回相应的字节数组
public byte[] getDigestOfBytes(byte[] byteData) {
process_input_bytes(byteData);
byte[] digest = new byte[20];
for (int i = 0; i < digestInt.length; i++) {
intToByteArray(digestInt[i], digest, i * 4);
}
return digest;
} // 计算sha-1摘要,返回相应的十六进制字符串
public String getDigestOfString(byte[] byteData) {
return byteArrayToHexString(getDigestOfBytes(byteData));
} public static void main(String[] args) {
String data = "123456";
String digest = new SHA1().getDigestOfString(data.getBytes());
}
}
SHA1 安全哈希算法(Secure Hash Algorithm)的更多相关文章
-
一致性哈希算法(Consistent Hashing Algorithm)
一致性哈希算法(Consistent Hashing Algorithm) 浅谈一致性Hash原理及应用 在讲一致性Hash之前我们先来讨论一个问题. 问题:现在有亿级用户,每日产生千万级订单,如 ...
-
感知哈希算法的java实现
一.原理讲解 实现这种功能的关键技术叫做"感知哈希算法"(Perceptual Hash Algorithm), 意思是为图片生成一个指纹(字符串格式), 两张图片的指纹 ...
-
SHA-1(安全哈希算法实现)
如题,不知道sha-1的自己百度吧. #include <iostream> #include <vector> //定义vector数组 #include <strin ...
-
一致性哈希算法以及其PHP实现
在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括: 轮循算法(Round Robin).哈希算法(HASH).最少连接算法(Least Connection).响应速度算法(Respons ...
-
Notes:一致性哈希算法
业务场景: 存在三个专门提供缓存服务的服务器,前端所需要的图片等静态资源被缓存于这三个服务器其中之一. 但是如何提高查找图片的速度呢? 可以采用哈希算法. 常规意义上的哈希算法: 通过hash(图片名 ...
-
一致性哈希算法介绍,及java实现
应用场景 在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括: 轮循算法(Round Robin).哈希算法(HASH).最少连接算法(Least Connection).响应速度算法(Res ...
-
转:MD5(Message-Digest Algorithm 一种哈希算法)
什么是MD5算法 MD5讯息摘要演算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码杂凑函数,可以产生出一个128位元(16位元组)的散列值(hash val ...
-
[Algorithm] 局部敏感哈希算法(Locality Sensitive Hashing)
局部敏感哈希(Locality Sensitive Hashing,LSH)算法是我在前一段时间找工作时接触到的一种衡量文本相似度的算法.局部敏感哈希是近似最近邻搜索算法中最流行的一种,它有坚实的理论 ...
-
openssl evp 哈希算法(md5,sha1,sha256)
1. 简述 openssl提供了丰富密码学工具,一些常用的哈希算法 比如md5,sha 可以直接用提供的md5.h ,sha.h 接口使用: 为了方便开发者使用,openssl 又提供了一个EVP, ...
随机推荐
-
LeetCode(43. Multiply Strings)
题目: Given two numbers represented as strings, return multiplication of the numbers as a string. Note ...
-
前端构建工具gulp入门
本文假设你之前没有用过任何任务脚本(task runner)和命令行工具,一步步教你上手Gulp.不要怕,它其实很简单,我会分为五步向你介绍gulp并帮助你完成一些惊人的事情.那就直接开始吧. 第一步 ...
-
解析activity之间数据传递方法的详解
转自:http://www.jb51.net/article/37227.htm 本篇文章是对activity之间数据传递的方法进行了详细的分析介绍,需要的朋友参考下 1 基于消息的通信机制 ...
-
HDU 5949 Relative atomic mass 【模拟】 (2016ACM/ICPC亚洲区沈阳站)
Relative atomic mass Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Oth ...
-
[T]各种字符串Hash函数比较
常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些函数使用位运算使得每一个字符都对最后的函数值产生影响.另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎 ...
-
linux 私房菜 CH7 Linux 档案与目录管理
路径 ``` . 此层目录 .. 上一级目录 前一个工作目录 ~ 当前用户的家的目录 ``` 变换目录 cd 显示目录 pwd [-P] -P 显示出确实的路径,而非使用链接 (link) 路径. 创 ...
-
用PetaPoco为ASP.NET已有数据库建模
序:最近一直在抓紧重构公司的网站,没有很多时间去写博客,积累了很多的问题,几乎是一天一个,折腾死了,尤其是在模型方面几经周折. 以前,多半从事PHP开发,很少接触到模型(thinkphp中模型),但是 ...
-
Django2.0中文文档
title: Django2.0中文文档 tags: Python,Django,入沐三分 grammar_cjkRuby: true --- Django2.0版本已经发布了,我们先来看一个图片 从 ...
-
WD与地图 解题报告
WD与地图 哎,我好傻啊,看了题解还弄错了一遍,靠着lbw指点才董 题意:给一个带点权有向图,要求支持删边,查询一个scc前\(k\)大权值,修改点权,不强制在线. 显然倒序处理变成加边 考虑求出每条 ...
-
超详细Gitlab Runner环境配置中文教程
配置GitlabRunner环境 GitLab Runner 是一个开源项目, 它用来运行你定制的任务(jobs)并把结果返回给 GitLab. GitLab Runner 配合GitLab CI(G ...