com.qcloud.cos.common_utils.CommonSha1Utils Maven / Gradle / Ivy
package com.qcloud.cos.common_utils;
/**
* 求sha1, 未使用JAVA自带类,是为了获取分片的中间状态(state数组)
* @author chengwu
*
*/
public final class CommonSha1Utils {
private int state[] = new int[5];
private long count;
public byte[] digestBits;
public boolean digestValid;
public CommonSha1Utils() {
state = new int[5];
count = 0;
if (block == null)
block = new int[16];
digestBits = new byte[20];
digestValid = false;
}
/**
* Add specific bytes to the digest.
*/
public synchronized void update(byte input[], int offset, int len) {
for (int i = 0; i < len; i++) {
update(input[i + offset]);
}
}
/**
* Add an array of bytes to the digest.
*/
public synchronized void update(byte input[]) {
update(input, 0, input.length);
}
/**
* Treat the string as a sequence of ISO-Latin1 (8 bit) characters.
*/
public void updateASCII(String input) {
int i, len;
byte x;
len = input.length();
for (i = 0; i < len; i++) {
x = (byte) (input.charAt(i) & 0xff);
update(x);
}
}
/*
* The following array forms the basis for the transform buffer. Update puts bytes into this
* buffer and then transform adds it into the state of the digest.
*/
private int block[] = new int[16];
private int blockIndex;
/*
* These functions are taken out of #defines in Steve's code. Java doesn't have a preprocessor
* so the first step is to just promote them to real methods. Later we can optimize them out
* into inline code, note that by making them final some compilers will inline them when given
* the -O flag.
*/
final int rol(int value, int bits) {
int q = (value << bits) | (value >>> (32 - bits));
return q;
}
final int blk0(int i) {
block[i] = (rol(block[i], 24) & 0xFF00FF00) | (rol(block[i], 8) & 0x00FF00FF);
return block[i];
}
final int blk(int i) {
block[i & 15] = rol(block[(i + 13) & 15] ^ block[(i + 8) & 15] ^ block[(i + 2) & 15]
^ block[i & 15], 1);
return (block[i & 15]);
}
final void R0(int data[], int v, int w, int x, int y, int z, int i) {
data[z] += ((data[w] & (data[x] ^ data[y])) ^ data[y]) + blk0(i) + 0x5A827999
+ rol(data[v], 5);
data[w] = rol(data[w], 30);
}
final void R1(int data[], int v, int w, int x, int y, int z, int i) {
data[z] +=
((data[w] & (data[x] ^ data[y])) ^ data[y]) + blk(i) + 0x5A827999 + rol(data[v], 5);
data[w] = rol(data[w], 30);
}
final void R2(int data[], int v, int w, int x, int y, int z, int i) {
data[z] += (data[w] ^ data[x] ^ data[y]) + blk(i) + 0x6ED9EBA1 + rol(data[v], 5);
data[w] = rol(data[w], 30);
}
final void R3(int data[], int v, int w, int x, int y, int z, int i) {
data[z] += (((data[w] | data[x]) & data[y]) | (data[w] & data[x])) + blk(i) + 0x8F1BBCDC
+ rol(data[v], 5);
data[w] = rol(data[w], 30);
}
final void R4(int data[], int v, int w, int x, int y, int z, int i) {
data[z] += (data[w] ^ data[x] ^ data[y]) + blk(i) + 0xCA62C1D6 + rol(data[v], 5);
data[w] = rol(data[w], 30);
}
int dd[] = new int[5];
/**
* Hash a single 512-bit block. This is the core of the algorithm.
*
* Note that working with arrays is very inefficent in Java as it does a class cast check each
* time you store into the array.
*
*/
void transform() {
/* Copy context->state[] to working vars */
dd[0] = state[0];
dd[1] = state[1];
dd[2] = state[2];
dd[3] = state[3];
dd[4] = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(dd, 0, 1, 2, 3, 4, 0);
R0(dd, 4, 0, 1, 2, 3, 1);
R0(dd, 3, 4, 0, 1, 2, 2);
R0(dd, 2, 3, 4, 0, 1, 3);
R0(dd, 1, 2, 3, 4, 0, 4);
R0(dd, 0, 1, 2, 3, 4, 5);
R0(dd, 4, 0, 1, 2, 3, 6);
R0(dd, 3, 4, 0, 1, 2, 7);
R0(dd, 2, 3, 4, 0, 1, 8);
R0(dd, 1, 2, 3, 4, 0, 9);
R0(dd, 0, 1, 2, 3, 4, 10);
R0(dd, 4, 0, 1, 2, 3, 11);
R0(dd, 3, 4, 0, 1, 2, 12);
R0(dd, 2, 3, 4, 0, 1, 13);
R0(dd, 1, 2, 3, 4, 0, 14);
R0(dd, 0, 1, 2, 3, 4, 15);
R1(dd, 4, 0, 1, 2, 3, 16);
R1(dd, 3, 4, 0, 1, 2, 17);
R1(dd, 2, 3, 4, 0, 1, 18);
R1(dd, 1, 2, 3, 4, 0, 19);
R2(dd, 0, 1, 2, 3, 4, 20);
R2(dd, 4, 0, 1, 2, 3, 21);
R2(dd, 3, 4, 0, 1, 2, 22);
R2(dd, 2, 3, 4, 0, 1, 23);
R2(dd, 1, 2, 3, 4, 0, 24);
R2(dd, 0, 1, 2, 3, 4, 25);
R2(dd, 4, 0, 1, 2, 3, 26);
R2(dd, 3, 4, 0, 1, 2, 27);
R2(dd, 2, 3, 4, 0, 1, 28);
R2(dd, 1, 2, 3, 4, 0, 29);
R2(dd, 0, 1, 2, 3, 4, 30);
R2(dd, 4, 0, 1, 2, 3, 31);
R2(dd, 3, 4, 0, 1, 2, 32);
R2(dd, 2, 3, 4, 0, 1, 33);
R2(dd, 1, 2, 3, 4, 0, 34);
R2(dd, 0, 1, 2, 3, 4, 35);
R2(dd, 4, 0, 1, 2, 3, 36);
R2(dd, 3, 4, 0, 1, 2, 37);
R2(dd, 2, 3, 4, 0, 1, 38);
R2(dd, 1, 2, 3, 4, 0, 39);
R3(dd, 0, 1, 2, 3, 4, 40);
R3(dd, 4, 0, 1, 2, 3, 41);
R3(dd, 3, 4, 0, 1, 2, 42);
R3(dd, 2, 3, 4, 0, 1, 43);
R3(dd, 1, 2, 3, 4, 0, 44);
R3(dd, 0, 1, 2, 3, 4, 45);
R3(dd, 4, 0, 1, 2, 3, 46);
R3(dd, 3, 4, 0, 1, 2, 47);
R3(dd, 2, 3, 4, 0, 1, 48);
R3(dd, 1, 2, 3, 4, 0, 49);
R3(dd, 0, 1, 2, 3, 4, 50);
R3(dd, 4, 0, 1, 2, 3, 51);
R3(dd, 3, 4, 0, 1, 2, 52);
R3(dd, 2, 3, 4, 0, 1, 53);
R3(dd, 1, 2, 3, 4, 0, 54);
R3(dd, 0, 1, 2, 3, 4, 55);
R3(dd, 4, 0, 1, 2, 3, 56);
R3(dd, 3, 4, 0, 1, 2, 57);
R3(dd, 2, 3, 4, 0, 1, 58);
R3(dd, 1, 2, 3, 4, 0, 59);
R4(dd, 0, 1, 2, 3, 4, 60);
R4(dd, 4, 0, 1, 2, 3, 61);
R4(dd, 3, 4, 0, 1, 2, 62);
R4(dd, 2, 3, 4, 0, 1, 63);
R4(dd, 1, 2, 3, 4, 0, 64);
R4(dd, 0, 1, 2, 3, 4, 65);
R4(dd, 4, 0, 1, 2, 3, 66);
R4(dd, 3, 4, 0, 1, 2, 67);
R4(dd, 2, 3, 4, 0, 1, 68);
R4(dd, 1, 2, 3, 4, 0, 69);
R4(dd, 0, 1, 2, 3, 4, 70);
R4(dd, 4, 0, 1, 2, 3, 71);
R4(dd, 3, 4, 0, 1, 2, 72);
R4(dd, 2, 3, 4, 0, 1, 73);
R4(dd, 1, 2, 3, 4, 0, 74);
R4(dd, 0, 1, 2, 3, 4, 75);
R4(dd, 4, 0, 1, 2, 3, 76);
R4(dd, 3, 4, 0, 1, 2, 77);
R4(dd, 2, 3, 4, 0, 1, 78);
R4(dd, 1, 2, 3, 4, 0, 79);
/* Add the working vars back into context.state[] */
state[0] += dd[0];
state[1] += dd[1];
state[2] += dd[2];
state[3] += dd[3];
state[4] += dd[4];
}
/**
*
* SHA1Init - Initialize new context
*/
public void init() {
/* SHA1 initialization constants */
state[0] = 0x67452301;
state[1] = 0xEFCDAB89;
state[2] = 0x98BADCFE;
state[3] = 0x10325476;
state[4] = 0xC3D2E1F0;
count = 0;
digestBits = new byte[20];
digestValid = false;
blockIndex = 0;
}
/**
* Add one byte to the digest. When this is implemented all of the abstract class methods end up
* calling this method for types other than bytes.
*/
public synchronized void update(byte b) {
int mask = (8 * (blockIndex & 3));
count += 8;
block[blockIndex >> 2] &= ~(0xff << mask);
block[blockIndex >> 2] |= (b & 0xff) << mask;
blockIndex++;
if (blockIndex == 64) {
transform();
blockIndex = 0;
}
}
/**
* Complete processing on the message digest.
*/
public void finish() {
byte bits[] = new byte[8];
int i;
for (i = 0; i < 8; i++) {
bits[i] = (byte) ((count >>> (((7 - i) * 8))) & 0xff);
}
update((byte) 128);
while (blockIndex != 56)
update((byte) 0);
// This should cause a transform to happen.
update(bits);
for (i = 0; i < 20; i++) {
digestBits[i] = (byte) ((state[i >> 2] >> ((3 - (i & 3)) * 8)) & 0xff);
}
digestValid = true;
}
/** Return a string that identifies this algorithm */
public String getAlg() {
return "SHA1";
}
/**
* Print out the digest in a form that can be easily compared to the test vectors.
*/
public String digout() {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 20; i++) {
char c1, c2;
c1 = (char) ((digestBits[i] >>> 4) & 0xf);
c2 = (char) (digestBits[i] & 0xf);
c1 = (char) ((c1 > 9) ? 'a' + (c1 - 10) : '0' + c1);
c2 = (char) ((c2 > 9) ? 'a' + (c2 - 10) : '0' + c2);
sb.append(c1);
sb.append(c2);
/*
* if (((i+1) % 4) == 0) sb.append(' ');
*/
}
return sb.toString();
}
// 输出中间状态
public String dumpTempState() {
StringBuilder sb = new StringBuilder();
final int count = 5;
for (int index = 0; index < count; ++index) {
for (int i = 0; i < 4; ++i) {
sb.append(String.format("%02x", (byte)(state[index] >>> (i * 8))));
}
}
return sb.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy