亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Golang實現(xiàn)密碼加密的示例詳解

 更新時間:2023年07月19日 10:08:56   作者:uccs  
數(shù)據(jù)庫在存儲密碼時,不能明文存儲,需要加密后存儲,而Golang中的加密算法有很多種,下面小編就來通過簡單的示例和大家簡單聊聊吧

數(shù)據(jù)庫在存儲密碼時,不能明文存儲,需要加密后存儲

加密算法有很多種,比如:對稱加密,非對稱加密,哈希算法,密碼派生等

在加密之前,我們需要生成一些隨機(jī)數(shù),這些隨機(jī)數(shù)稱為鹽

什么是鹽?為什么需要鹽?

鹽是一種加密算法中的一種參數(shù),它是一個隨機(jī)數(shù),用于增加破解密碼的難度

把密碼想象成一盤菜,鹽就是調(diào)料,不加調(diào)料就是原汁原味的菜,調(diào)料加多加少,菜口味就不一樣了

也就是說,鹽的多少,會影響到加密后的結(jié)果,如果不使用鹽,那么相同的密碼,加密后的結(jié)果是一樣的,這樣就很容易被破解

鹽的生成方式有很多種,比如:隨機(jī)數(shù),時間戳等

這里用隨機(jī)數(shù)來舉例:

  • 定義一個字符串,里面包含了所有可能的字符
  • 根據(jù)傳入的長度,生成一個切片,并用隨機(jī)數(shù)填充
  • 遍歷這個切片,取出隨機(jī)數(shù),然后對字符串長度取余,得到一個索引,然后把這個索引對應(yīng)的字符,放到切片中
  • 返回這個切片(這個切片就是鹽)
func generateSalt(length int) []byte {
  const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  salt := make([]byte, length)
  rand.Read(salt)
  for key, val := range salt {
    salt[key] = alphanum[val%byte(len(alphanum))]
  }
  return salt
}

生成鹽之后,我們就可以對密碼進(jìn)行加密了

加密后的密碼要使用 hex.EncodeToString 轉(zhuǎn)換成字符串

salt := generateSalt(16)
encoded := pbkdf2.Key([]byte("uccs"), salt, 100, 32, sha256.New)
encodedPwd := hex.EncodeToString(encodedPwd)

因為這個加密算法是不可逆的,也就說你不能通過加密后的密碼,反推出原始密碼

那用戶輸入密碼時,如何知道密碼是否正確呢?

所以在存儲加密后的密碼時,還要存儲鹽和加密算法的參數(shù)

這里使用的是 pbkdf2 算法,它的參數(shù)有:原始密碼,鹽,迭代次數(shù),密鑰長度,哈希算法

所以最終存在數(shù)據(jù)的密碼是:

pwd := fmt.Sprintf("%s$%s$%d$%d$%s", encodedPwd, salt, 100, 32, "pbkdf2-sha256")

這樣在驗證密碼時,就可以通過這些參數(shù),把用戶輸入的密碼,加密后,再和數(shù)據(jù)庫中存儲的密碼進(jìn)行比較,如果相同,就說明密碼正確

知識補(bǔ)充

當(dāng)然除了上面的加密方式,Golang中還有很多加密算法的實現(xiàn),下面小編就來為大家簡單整理一下吧,希望對大家有所幫助

MD5加密

package main
import (
?? ?"crypto/md5"
?? ?"encoding/hex"
?? ?"fmt"
?? ?"io"
)
func main() {
?? ?h := md5.New()
?? ?io.WriteString(h, "123456")
?? ?sum := h.Sum(nil)
?? ?fmt.Println(hex.EncodeToString(sum[:]))
?? ?// e10adc3949ba59abbe56e057f20f883e
}

凱撒密碼加密

package main
import (
	"fmt"
	"strings"
)
func caesar(r rune, shift int) rune {
	// Shift character by specified number of places.
	// ... If beyond range, shift backward or forward.
	s := int(r) + shift
	if s > 'z' {
		return rune(s - 26)
	} else if s < 'a' {
		return rune(s + 26)
	}
	return rune(s)
}
func main() {
	value := "test"
	fmt.Println(value)
	// Test the caesar method in a func argument to strings.Map.
	value2 := strings.Map(func(r rune) rune {
		return caesar(r, 18)
	}, value)
	value3 := strings.Map(func(r rune) rune {
		return caesar(r, -18)
	}, value2)
	fmt.Println(value2, value3)
	value4 := strings.Map(func(r rune) rune {
		return caesar(r, 1)
	}, value)
	value5 := strings.Map(func(r rune) rune {
		return caesar(r, -1)
	}, value4)
	fmt.Println(value4, value5)
	value = "exxegoexsrgi"
	result := strings.Map(func(r rune) rune {
		return caesar(r, -4)
	}, value)
	fmt.Println(value, result)
}
//輸出結(jié)果
//test
//lwkl test
//uftu test
//exxegoexsrgi attackatonce

AES對稱加密

package main
import (
	"bytes"
	"crypto/aes"
	"fmt"
	"testing"
)
//ECB模式解密
func ECBDecrypt(crypted, key []byte) ([]byte, error) {
	if !validKey(key) {
		return nil, fmt.Errorf("秘鑰長度錯誤,當(dāng)前傳入長度為 %d",len(key))
	}
	if len(crypted) < 1 {
		return nil, fmt.Errorf("源數(shù)據(jù)長度不能為0")
	}
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	if len(crypted)%block.BlockSize() != 0 {
		return nil, fmt.Errorf("源數(shù)據(jù)長度必須是 %d 的整數(shù)倍,當(dāng)前長度為:%d",block.BlockSize(), len(crypted))
	}
	var dst []byte
	tmpData := make([]byte, block.BlockSize())
	for index := 0; index < len(crypted); index += block.BlockSize() {
		block.Decrypt(tmpData, crypted[index:index+block.BlockSize()])
		dst = append(dst, tmpData...)
	}
	dst, err = PKCS5UnPadding(dst)
	if err != nil {
		return nil, err
	}
	return dst, nil
}
//ECB模式加密
func ECBEncrypt(src, key []byte) ([]byte, error) {
	if !validKey(key) {
		return nil, fmt.Errorf("秘鑰長度錯誤, 當(dāng)前傳入長度為 %d",len(key))
	}
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	if len(src) < 1 {
		return nil, fmt.Errorf("源數(shù)據(jù)長度不能為0")
	}
	src = PKCS5Padding(src, block.BlockSize())
	if len(src)%block.BlockSize() != 0 {
		return nil, fmt.Errorf("源數(shù)據(jù)長度必須是 %d 的整數(shù)倍,當(dāng)前長度為:%d",block.BlockSize(), len(src))
	}
	var dst []byte
	tmpData := make([]byte, block.BlockSize())
	for index := 0; index < len(src); index += block.BlockSize() {
		block.Encrypt(tmpData, src[index:index+block.BlockSize()])
		dst = append(dst, tmpData...)
	}
	return dst, nil
}
// PKCS5填充
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}
// 去除PKCS5填充
func PKCS5UnPadding(origData []byte) ([]byte, error) {
	length := len(origData)
	unpadding := int(origData[length-1])
	if length < unpadding {
		return nil, fmt.Errorf("invalid unpadding length")
	}
	return origData[:(length - unpadding)], nil
}
// 秘鑰長度驗證
func validKey(key []byte) bool {
	k := len(key)
	switch k {
	default:
		return false
	case 16, 24, 32:
		return true
	}
}
func TestAes(t *testing.T){
	srcData := "hello world !"
	key := []byte("abcdabcdabcdabcdabcdabcdabcdabcd")
	//測試加密
	encData ,err := ECBEncrypt([]byte(srcData),(key))
	if err != nil {
		t.Errorf(err.Error())
		return
	}
	//測試解密
	decData ,err := ECBDecrypt(encData,key)
	if err != nil {
		t.Errorf(err.Error())
		return
	}
	t.Log(string(decData))
}

到此這篇關(guān)于Golang實現(xiàn)密碼加密的示例詳解的文章就介紹到這了,更多相關(guān)Golang密碼加密內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang+vue打造高效多語言博客系統(tǒng)的完整指南

    golang+vue打造高效多語言博客系統(tǒng)的完整指南

    這篇文章主要為大家詳細(xì)介紹了如何使用golang和vue打造一個高效多語言博客系統(tǒng),本文為大家附上了完整版指南,有需要的小伙伴可以參考一下
    2025-03-03
  • Golang利用compress/flate包來壓縮和解壓數(shù)據(jù)

    Golang利用compress/flate包來壓縮和解壓數(shù)據(jù)

    在處理需要高效存儲和快速傳輸?shù)臄?shù)據(jù)時,數(shù)據(jù)壓縮成為了一項不可或缺的技術(shù),Go語言的compress/flate包為我們提供了對DEFLATE壓縮格式的原生支持,本文將深入探討compress/flate包的使用方法,揭示如何利用它來壓縮和解壓數(shù)據(jù),并提供實際的代碼示例,需要的朋友可以參考下
    2024-08-08
  • go語言檢測文件是否存在的方法

    go語言檢測文件是否存在的方法

    這篇文章主要介紹了go語言檢測文件是否存在的方法,實例分析了Go語言文件操作的相關(guān)技巧,需要的朋友可以參考下
    2015-03-03
  • go語言中iota和左移右移的使用說明

    go語言中iota和左移右移的使用說明

    這篇文章主要介紹了go語言中iota和左移右移的使用說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • Golang標(biāo)準(zhǔn)庫之errors包應(yīng)用方式

    Golang標(biāo)準(zhǔn)庫之errors包應(yīng)用方式

    Go語言的errors包提供了基礎(chǔ)的錯誤處理能力,允許通過errors.New創(chuàng)建自定義error對象,error在Go中是一個接口,通過實現(xiàn)Error方法來定義錯誤文本,對錯誤的比較通常基于對象地址,而非文本內(nèi)容,因此即使兩個錯誤文本相同
    2024-10-10
  • go語言定時器Timer及Ticker的功能使用示例詳解

    go語言定時器Timer及Ticker的功能使用示例詳解

    這篇文章主要為大家介紹了go語言定時器的功能使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • Golang最大遞減數(shù)算法問題分析

    Golang最大遞減數(shù)算法問題分析

    這篇文章主要介紹了Golang最大遞減數(shù)算法問題分析,結(jié)合實例形式分析了Go語言數(shù)字遍歷與運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下
    2017-01-01
  • Go中的新增對模糊測試的支持

    Go中的新增對模糊測試的支持

    這篇文章主要為大家介紹了Go中的新增對模糊測試的支持,文中還包含了一些功能實驗性測試分析有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03
  • 詳解Go語言的計時器

    詳解Go語言的計時器

    Go語言的標(biāo)準(zhǔn)庫里提供兩種類型的計時器Timer和Ticker。這篇文章主要介紹了Go語言的計時器的相關(guān)知識,需要的朋友可以參考下
    2020-05-05
  • Golang信號處理及如何實現(xiàn)進(jìn)程的優(yōu)雅退出詳解

    Golang信號處理及如何實現(xiàn)進(jìn)程的優(yōu)雅退出詳解

    這篇文章主要給大家介紹了關(guān)于Golang信號處理及如何實現(xiàn)進(jìn)程的優(yōu)雅退出的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03

最新評論