go 调用 sha256 加密
字符串哈希值
package main
import(
"fmt"
"crypto/sha256"
"io"
"log"
"os"
)
func main() {
// 第一种调用方法
sum := sha256.Sum256([]byte("hello world\n"))
fmt.Printf("%x\n", sum)
// 第二种调用方法
h := sha256.New()
h.Write([]byte("hello world\n"))
fmt.Printf("%x\n", h.Sum(nil))
}
文件哈希值
// 对文件加密
f, err := os.Open("test.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
h = sha256.New()
if _, err := io.Copy(h, f); err != nil {
log.Fatal(err)
}
fmt.Printf("%x\n", h.Sum(nil))
源码下载:https://github.com/didianV5/blockchain/tree/master/encryption/sha256
sha256 实现原理
SHA-256 算法输入报文的最大长度不超过2^64 bit,输入按512-bit 分组进行处理,产生的输出是一个256-bit 的报文摘要。
附加填充比特:对报文进行填充使报文长度与448 模512 同余(长度=448 mod 512),填充的比特数范围是1 到512,填充比特串的最高位为1,其余位为0。就是先在报文后面加一个 1,再加很多个0,直到长度 满足 mod 512=448.为什么是448,因为448+64=512. 第二步会加上一个 64bit的 原始报文的 长度信息。
附加长度值 将用64-bit 表示的初始报文(填充前)的位长度附加在步骤1 的结果后(低位字节优先)。
-
初始化缓存:使用一个256-bit 的缓存来存放该散列函数的中间及最终结果。 该缓存表示为
const ( init0 = 0x6A09E667 init1 = 0xBB67AE85 init2 = 0x3C6EF372 init3 = 0xA54FF53A init4 = 0x510E527F init5 = 0x9B05688C init6 = 0x1F83D9AB init7 = 0x5BE0CD19 )
-
处理512-bit(16 个字)报文分组序列:该算法使用了六种基本逻辑函数,由64步迭代运算组成。每步都以256-bit 缓存值ABCDEFGH 为输入,然后更新缓存内容。 每步使用一个32-bit 常数值Kt 和一个32-bit Wt。
- 常数K为
var _K = []uint32{ 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, }
- Wt 是 分组之后的报文
for i := 0; i < 16; i++ { j := i * 4 w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3]) } for i := 16; i < 64; i++ { v1 := w[i-2] t1 := (v1>>17 | v1<<(32-17)) ^ (v1>>19 | v1<<(32-19)) ^ (v1 >> 10) v2 := w[i-15] t2 := (v2>>7 | v2<<(32-7)) ^ (v2>>18 | v2<<(32-18)) ^ (v2 >> 3) w[i] = t1 + w[i-7] + t2 + w[i-16] }
- 64步迭代运算
for i := 0; i < 64; i++ { t1 := h + ((e>>6 | e<<(32-6)) ^ (e>>11 | e<<(32-11)) ^ (e>>25 | e<<(32-25))) + ((e & f) ^ (^e & g)) + _K[i] + w[i] t2 := ((a>>2 | a<<(32-2)) ^ (a>>13 | a<<(32-13)) ^ (a>>22 | a<<(32-22))) + ((a & b) ^ (a & c) ^ (b & c)) h = g g = f f = e e = d + t1 d = c c = b b = a a = t1 + t2 } h0 += a h1 += b h2 += c h3 += d h4 += e h5 += f h6 += g h7 += h
-
生成256-bit的报文摘要 所有的512-bit分组处理完毕后,对于SHA-256算法最后一个分组产生的输出便是256-bit的报文摘要。
dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
源码下载
源码地址: https://github.com/didianV5/blockchain/tree/master/encryption/sha256/source