Created
August 8, 2020 19:53
-
-
Save debuggor/959727c5d357011f2463502cf81057d3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.nio.ByteBuffer; | |
/** | |
* @Author:yong.huang | |
* @Date:2020-08-08 17:49 | |
*/ | |
public class Sha256 { | |
private static int[] H0 = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; | |
private static int[] K = {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, | |
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, | |
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, | |
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, | |
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, | |
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, | |
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, | |
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; | |
private static int[] W = new int[64]; | |
private static int[] H = new int[8]; | |
/** | |
* @param mesage | |
* @return | |
*/ | |
public static byte[] hash(byte[] mesage) { | |
// let H = H0 | |
System.arraycopy(H0, 0, H, 0, H0.length); | |
// 预处理;补充长度 | |
byte[] padding = padding(mesage); | |
// 将bytes转为int处理 | |
int[] ints = bytesToInts(padding); | |
for (int i = 0; i < ints.length / 16; i++) { | |
// break chunk into sixteen 32-bit big-endian words w[0], …, w[15] | |
System.arraycopy(ints, i * 16, W, 0, 16); | |
// 剩余word Wt=σ1(Wt−2)+Wt−7+σ0(Wt−15)+Wt−16 | |
for (int t = 16; t < W.length; t++) { | |
W[t] = smallSigma1(W[t - 2]) + W[t - 7] + smallSigma0(W[t - 15]) + W[t - 16]; | |
} | |
// 64次 Hn——>Hn+1映射 | |
int[] tmp = new int[H.length]; | |
System.arraycopy(H, 0, tmp, 0, H.length); | |
for (int t = 0; t < 64; t++) { | |
int t1 = tmp[7] + bigSigma1(tmp[4]) + ch(tmp[4], tmp[5], tmp[6]) + K[t] + W[t]; | |
int t2 = bigSigma0(tmp[0]) + ma(tmp[0], tmp[1], tmp[2]); | |
System.arraycopy(tmp, 0, tmp, 1, tmp.length - 1); | |
tmp[0] = t1 + t2; | |
tmp[4] += t1; | |
} | |
for (int j = 0; j < H.length; j++) { | |
H[j] += tmp[j]; | |
} | |
} | |
// 将ints转为bytes | |
return intsToBytes(H); | |
} | |
private static byte[] intsToBytes(int[] ints) { | |
ByteBuffer buf = ByteBuffer.allocate(ints.length * Integer.BYTES); | |
for (int i = 0; i < ints.length; ++i) { | |
buf.putInt(ints[i]); | |
} | |
return buf.array(); | |
} | |
private static int[] bytesToInts(byte[] bytes) { | |
if (bytes.length % Integer.BYTES != 0) { | |
throw new IllegalArgumentException("byte array length error"); | |
} | |
ByteBuffer buf = ByteBuffer.wrap(bytes); | |
int[] result = new int[bytes.length / Integer.BYTES]; | |
for (int i = 0; i < result.length; ++i) { | |
result[i] = buf.getInt(); | |
} | |
return result; | |
} | |
/** | |
* 预处理:对message进行填充 %512==0 | |
* 在报文末尾进行填充1和0,使报文长度在对512取模以后的余数是448 | |
* 512-448=64 表示原始消息的长度 | |
* | |
* @param message | |
* @return | |
*/ | |
private static byte[] padding(byte[] message) { | |
int blockLen = 512; | |
int blockByteNum = blockLen / 8; | |
// new message length: original + 1-bit and padding + 8-byte length | |
int newMessageLen = message.length + 1 + 8; | |
int pad0Len = (blockByteNum - newMessageLen % blockByteNum) % blockByteNum; | |
newMessageLen += pad0Len; | |
// 原始消息的长度占位长度 | |
byte[] result = new byte[newMessageLen]; | |
// 1、message | |
System.arraycopy(message, 0, result, 0, message.length); | |
// 2、填充一个1byte | |
result[message.length] = (byte) 0b10000000; | |
// 3、省略填充0这一步 其默认就是0 | |
// 4、message的长度占位 | |
ByteBuffer.wrap(result, message.length + 1 + pad0Len, 8).putLong(message.length * 8); | |
return result; | |
} | |
/** | |
* Ch(x,y,z)=(x∧y)⊕(¬x∧z) | |
*/ | |
private static int ch(int x, int y, int z) { | |
return (x & y) | ((~x) & z); | |
} | |
/** | |
* Ma(x,y,z)=(x∧y)⊕(x∧z)⊕(y∧z) | |
*/ | |
private static int ma(int x, int y, int z) { | |
return (x & y) | (x & z) | (y & z); | |
} | |
/** | |
* Σ0(x)=S2(x)⊕S13(x)⊕S22(x) | |
*/ | |
private static int bigSigma0(int x) { | |
return Integer.rotateRight(x, 2) ^ Integer.rotateRight(x, 13) ^ Integer.rotateRight(x, 22); | |
} | |
/** | |
* Σ1(x)=S6(x)⊕S11(x)⊕S25(x) | |
*/ | |
private static int bigSigma1(int x) { | |
return Integer.rotateRight(x, 6) ^ Integer.rotateRight(x, 11) ^ Integer.rotateRight(x, 25); | |
} | |
/** | |
* σ0(x)=S7(x)⊕S18(x)⊕R3(x) | |
*/ | |
private static int smallSigma0(int x) { | |
return Integer.rotateRight(x, 7) ^ Integer.rotateRight(x, 18) ^ (x >>> 3); | |
} | |
/** | |
* σ1(x)=S17(x)⊕S19(x)⊕R10(x) | |
*/ | |
private static int smallSigma1(int x) { | |
return Integer.rotateRight(x, 17) ^ Integer.rotateRight(x, 19) ^ (x >>> 10); | |
} | |
public static String bytesToHex(byte[] raw) { | |
final StringBuilder hex = new StringBuilder(2 * raw.length); | |
for (final byte b : raw) { | |
hex.append(Character.forDigit((b & 0xF0) >> 4, 16)).append(Character.forDigit((b & 0x0F), 16)); | |
} | |
return hex.toString(); | |
} | |
public static void main(String[] args) { | |
byte[] message = "good".getBytes(); | |
byte[] hash = Sha256.hash(message); | |
System.out.println(bytesToHex(hash)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
sha256原理
sha256文档