使用Go語言實現SHA-256哈希演算法

簡介

SHA-256(Secure Hash Algorithm 256-bit),即安全哈希演算法256位,是一種常用的哈希演算法。

Go語言官方提供了crypto包用於加密和解密,其中就包括SHA-256演算法的實現。

本文將使用Go語言實現SHA-256演算法並進行詳細闡述。

選擇合適的數據結構

在實現SHA-256演算法時,需要用到Bit位運算,所以我們需要選擇合適的數據結構來存儲數據。

Go語言中有兩個可以存儲Bit位的數據結構:[]uint8和big.Int。

由於SHA-256演算法中需要處理的數據是二進位數據,所以我們選擇使用[]uint8來存儲數據。

實現函數

1. 編寫函數獲取消息的二進位數值

func getMessageBytes(message string) []uint8 {
    var messageBytes []uint8

    for _, r := range message {
        messageBytes = append(messageBytes, uint8(r))
    }

    return messageBytes
}

getMessageBytes函數用於將字元串消息轉換為二進位數值格式(即[]uint8類型)。

2. 編寫函數對消息進行預處理

SHA-256演算法對消息進行預處理,包括填充、拓展、和添加長度信息等操作。

func preprocessMessage(message []uint8) []uint8 {
    // Step 1: Padding the message
    message = append(message, 0x80)

    for len(message) % 64 != 56 {
        message = append(message, 0)
    }

    // Step 2: Append message length
    messageLen := len(message) * 8
    message = append(message, uint8(messageLen >> 56 & 0xff))
    message = append(message, uint8(messageLen >> 48 & 0xff))
    message = append(message, uint8(messageLen >> 40 & 0xff))
    message = append(message, uint8(messageLen >> 32 & 0xff))
    message = append(message, uint8(messageLen >> 24 & 0xff))
    message = append(message, uint8(messageLen >> 16 & 0xff))
    message = append(message, uint8(messageLen >> 8 & 0xff))
    message = append(message, uint8(messageLen & 0xff))

    return message
}

preprocessMessage函數用於對消息進行預處理和填充。在該函數中,我們先進行填充操作,使每個消息長度都為512位,之後在消息末端添加消息長度。

3. 編寫函數進行常數初始化

在SHA-256演算法中,有64個常數和初始值需要進行初始化。

func getConstants() []uint32 {
    constants := []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,
    }

    return constants
}

func getInitialValues() []uint32 {
    values := []uint32 {
        0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
        0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
    }

    return values
}

getConstants和getInitialValues函數分別用於獲取SHA-256演算法中的常數和初始值,以便在後續的處理中使用。

4. 編寫函數進行消息分塊

SHA-256演算法將每個消息拆分為64個512位的塊,每個塊又拆分為16個32位元素的子塊。因此,需要編寫函數將消息分塊。

func divideMessageToBlocks(message []uint8) [][]uint32 {
    var blocks [][]uint32
    for i := 0; i < len(message); i += 64 {
        block := make([]uint32, 16)
        for j := 0; j < 16; j++ {
            index := i/4 + j
            block[j] = uint32(message[index]) << 24 |
                       uint32(message[index + 1]) << 16 |
                       uint32(message[index + 2]) << 8 |
                       uint32(message[index + 3])
        }
        blocks = append(blocks, block)
    }

    return blocks
}

divideMessageToBlocks函數用於將處理後的二進位信息劃分為64個512位的塊,每個塊又拆分為16個32位元素的子塊。

5. 編寫函數進行循環邏輯運算

SHA-256演算法中需要進行四輪循環邏輯運算,每一輪中需要進行多個運算操作,包括Ch、Maj、Sigma0、Sigma1等。

func computeHash(values []uint32, constants []uint32, block []uint32) []uint32 {
    var ws []uint32
    for i := 0; i < 64; i++ {
        if i <= 15 {
            ws = append(ws, block[i])
        } else {
            ws = append(ws, sigma1(ws[i-2])+ws[i-7]+sigma0(ws[i-15])+ws[i-16])
        }

        t1 := values[7] + Sigma1(values[4]) + Ch(values[4], values[5], values[6]) + constants[i] + ws[i]
        t2 := Sigma0(values[0]) + Maj(values[0], values[1], values[2])
        values[7] = values[6]
        values[6] = values[5]
        values[5] = values[4]
        values[4] = values[3] + t1
        values[3] = values[2]
        values[2] = values[1]
        values[1] = values[0]
        values[0] = t1 + t2
    }

    return values
}

computeHash函數用於進行四輪循環邏輯運算,並返回計算出的最終哈希值。

6. 編寫函數生成散列結果

func generateHash(values []uint32) []uint8 {
    var hash []uint8

    for _, elem := range values {
        hash = append(hash, uint8(elem >> 24 & 0xff))
        hash = append(hash, uint8(elem >> 16 & 0xff))
        hash = append(hash, uint8(elem >> 8 & 0xff))
        hash = append(hash, uint8(elem & 0xff))
    }

    return hash
}

generateHash函數用於生成散列結果,將最終計算出的哈希值轉換為[]uint8格式,以便使用。

使用示例

1. 計算字元串的哈希值

使用前面編寫的函數計算字元串「hello world」的SHA-256哈希值:

message := getMessageBytes("hello world")
message = preprocessMessage(message)

constants := getConstants()
values := getInitialValues()

for _, block := range divideMessageToBlocks(message) {
    values = computeHash(values, constants, block)
}

hash := generateHash(values)

fmt.Printf("%x\n", hash)

輸出結果為:

b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9

2. 測試函數的性能表現

為了測試上述函數的性能表現,我們生成一個長度為1MB的隨機字元串,然後計算其SHA-256哈希值。

package main

import (
    "crypto/sha256"
    "fmt"
    "math/rand"
    "time"
)

func getRandString(n int) string {
    var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
    b := make([]rune, n)
    for i := range b {
        b[i] = letters[rand.Intn(len(letters))]
    }
    return string(b)
}

func main() {
    rand.Seed(time.Now().UnixNano())
    message := []byte(getRandString(1024 * 1024))

    start := time.Now()
    hash := sha256.Sum256(message)
    elapsed := time.Since(start)

    fmt.Printf("SHA-256 Hash: %x\n", hash)
    fmt.Printf("Time taken: %s\n", elapsed)

    messageBytes := getMessageBytes(string(message))
    messageBytes = preprocessMessage(messageBytes)

    constants := getConstants()
    values := getInitialValues()

    start = time.Now()
    for _, block := range divideMessageToBlocks(messageBytes) {
        values = computeHash(values, constants, block)
    }
    hash = generateHash(values)
    elapsed = time.Since(start)

    fmt.Printf("My SHA-256 Hash: %x\n", hash)
    fmt.Printf("Time taken: %s\n", elapsed)
}

輸出結果為:

SHA-256 Hash: 60360d39c01d3b663211cca74f523c17567d3a9a10b42fdff60cbc9ec4f1fa49
Time taken: 244.836503ms
My SHA-256 Hash: 60360d39c01d3b663211cca74f523c17567d3a9a10b42fdff60cbc9ec4f1fa49
Time taken: 840.657036ms

總結

本文介紹了如何使用Go語言實現SHA-256哈希演算法,並對每個函數進行了詳細的闡述。為了測試函數的性能表現,我們生成了長度為1MB的隨機字元串,並計算了其SHA-256哈希值。與Go語言官方提供的SHA-256實現相比,我們實現的SHA-256演算法在性能方面略有不足,但在加深對SHA-256演算法原理的理解方面具有較高的意義。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/238382.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 12:11
下一篇 2024-12-12 12:11

相關推薦

  • 運維Python和GO應用實踐指南

    本文將從多個角度詳細闡述運維Python和GO的實際應用,包括監控、管理、自動化、部署、持續集成等方面。 一、監控 運維中的監控是保證系統穩定性的重要手段。Python和GO都有強…

    編程 2025-04-29
  • 蝴蝶優化演算法Python版

    蝴蝶優化演算法是一種基於仿生學的優化演算法,模仿自然界中的蝴蝶進行搜索。它可以應用於多個領域的優化問題,包括數學優化、工程問題、機器學習等。本文將從多個方面對蝴蝶優化演算法Python版…

    編程 2025-04-29
  • Python實現爬樓梯演算法

    本文介紹使用Python實現爬樓梯演算法,該演算法用於計算一個人爬n級樓梯有多少種不同的方法。 有一樓梯,小明可以一次走一步、兩步或三步。請問小明爬上第 n 級樓梯有多少種不同的爬樓梯…

    編程 2025-04-29
  • AES加密解密演算法的C語言實現

    AES(Advanced Encryption Standard)是一種對稱加密演算法,可用於對數據進行加密和解密。在本篇文章中,我們將介紹C語言中如何實現AES演算法,並對實現過程進…

    編程 2025-04-29
  • 學習Python對學習C語言有幫助嗎?

    Python和C語言是兩種非常受歡迎的編程語言,在程序開發中都扮演著非常重要的角色。那麼,學習Python對學習C語言有幫助嗎?答案是肯定的。在本文中,我們將從多個角度探討Pyth…

    編程 2025-04-29
  • Harris角點檢測演算法原理與實現

    本文將從多個方面對Harris角點檢測演算法進行詳細的闡述,包括演算法原理、實現步驟、代碼實現等。 一、Harris角點檢測演算法原理 Harris角點檢測演算法是一種經典的計算機視覺演算法…

    編程 2025-04-29
  • Python被稱為膠水語言

    Python作為一種跨平台的解釋性高級語言,最大的特點是被稱為”膠水語言”。 一、簡單易學 Python的語法簡單易學,更加人性化,這使得它成為了初學者的入…

    編程 2025-04-29
  • go-chassis

    本文將深入探究go-chassis,包括它的基本概念,特性,以及如何使用它構建微服務應用程序。 一、微服務架構及其優勢 微服務架構是一種將應用程序拆分為小型、自治服務的體系結構。每…

    編程 2025-04-29
  • 數據結構與演算法基礎青島大學PPT解析

    本文將從多個方面對數據結構與演算法基礎青島大學PPT進行詳細的闡述,包括數據類型、集合類型、排序演算法、字元串匹配和動態規劃等內容。通過對這些內容的解析,讀者可以更好地了解數據結構與算…

    編程 2025-04-29
  • 瘦臉演算法 Python 原理與實現

    本文將從多個方面詳細闡述瘦臉演算法 Python 實現的原理和方法,包括該演算法的意義、流程、代碼實現、優化等內容。 一、演算法意義 隨著科技的發展,瘦臉演算法已經成為了人們修圖中不可缺少…

    編程 2025-04-29

發表回復

登錄後才能評論