golang笔记-区块链密码学01

golang笔记-区块链密码学01

# pbkdf2.Key() 生成秘钥函数 PBKDF2(Password-Based Key Derivation Function) > 是一个用来导出密钥的函数,常用于生成加密的密码。 它的基本原理是通过一个伪随机函数(例如HMAC函数、sha512等),把明文(password)和一个盐值(salt)作为一个输入参数,然后重复进行运算,并最终产生秘钥。 如果重复的次数足够大,破解的成本就会变得很高。而盐值的添加也会增加“彩虹表”攻击的难度。 用户密码采用PBKDF2算法存储,比较安全。 **PBKDF2函数的语法定义** ``` DK = PBKDF2(PRF, Password, Salt, c, dkLen ,Hash algorithm) ``` - PRF是一个伪随机函数,例如HASH_HMAC函数,它会输出长度为hLen的结果。 - Password是用来生成密钥的原文密码。 - Salt是一个加密用的盐值。 - c是进行重复计算的次数。 - dkLen是期望得到的密钥的长度。 - DK是最后产生的密钥。 **以下为使用助记词生成私钥的代码** ``` package pbkdf2 import ( "crypto/rand" "crypto/sha512" "golang.org/x/crypto/pbkdf2" ) const ( Mnemonic = "search crime conversation tag directory joke leaf express interest password = "" ) func encryptPwdWithSalt(password string) (*ecdsa.PrivateKey, *ecdsa.PublicKey) { seed := pbkdf2.Key([]byte(Mnemonic), []byte("mnemonic"+password), 2048, 64, sha512.New) } // []byte(Mnemonic):助记词 // []byte("mnemonic"+password) :salt盐值 // 2048:重复计算的次数 // 64:返回的秘钥长度 // sha512.New:哈希算法 ``` # HMAC 生成摘要算法 HMAC算法中文名称叫哈希消息认证码,英文全称是Hash-based Message Authentication Code。**它的算法是基于某个哈希散列函数(主要是SHA系列和MD系列),以一个密钥和一个消息为输入,生成一个消息摘要作为输出**。HMAC算法与其他哈希散列算法最大区别就是需要有密钥。它的算法函数是利用分组密码来建立的一个单向Hash函数。 下表显示具体的算法对应输出摘要的长度。 算法 | 摘要长度(位)|备注 ---|---|---|--- HmacMD5 |128| BouncyCastle实现 HmacSHA1| 160|(20个字节) BouncyCastle实现 HmacSHA256| 256 |BouncyCastle实现 HmacSHA384| 384| BouncyCastle实现 HmacSHA512| 512| JAVA6实现 HmacMD2 |128| BouncyCastle实现 HmacMD4 |128| BouncyCastle实现 HmacSHA224| 224| BouncyCastle实现 HMAC的密钥可以是任何长度,如果密钥的长度超过了摘要算法信息分组的长度,则首先使用摘要算法计算密钥的摘要作为新的密钥。一般不建议使用太短的密钥,因为密钥的长度与安全强度是相关的。通常选取密钥长度不小于所选用摘要算法输出的信息摘要的长度。 **HMAC算法golang封装的代码详细解析** ``` //创建运算对象,HMAC需要两个参数:hash函数和key hmac := hmac.New(sha512.New, []byte(BitcoinSeed)) //将明文写入到hmac中 _, err := hmac.Write([]byte(seed)) if err != nil { return nil, nil } //hmac对象对写入数据的运算,生成的参数为字节 intermediary := hmac.Sum(nil) ``` **用golang使用HMAC算法的距举例** ``` package main import ( "crypto/hmac" "crypto/md5" "crypto/sha1" "encoding/hex" "fmt" ) func Md5(data string) string { md5 := md5.New() md5.Write([]byte(data)) md5Data := md5.Sum([]byte("")) return hex.EncodeToString(md5Data) } func Hmac(key, data string) string { hmac := hmac.New(md5.New, []byte(key)) hmac.Write([]byte(data)) return hex.EncodeToString(hmac.Sum(nil) } func Sha1(data string) string { sha1 := sha1.New() sha1.Write([]byte(data)) return hex.EncodeToString(sha1.Sum(nil)) } func main() { fmt.Println(Md5("hello")) fmt.Println(Hmac("key2", "hello")) fmt.Println(Sha1("hello")) } ``` # PrivKeyFromBytes 创建私钥、公钥对 根据作为参数作为字节切片传递的私钥返回“曲线”的私钥和公钥。 我们应该知道,可以从私钥生成公钥。所以拥有私钥相当于拥有整个密钥对。 以下为生成密钥对的代码: ``` func PrivKeyFromBytes(curve elliptic.Curve, pk []byte) (*PrivateKey, *PublicKey) { x, y := curve.ScalarBaseMult(pk) priv := &PrivateKey{ PublicKey: e.PublicKey{ Curve: curve, X: x, Y: y, }, D: new(big.Int).SetBytes(pk), } return priv, (*PublicKey)(&priv.PublicKey) } ``` *ecdsa.PrivateKey 是 PublicKey 和 PrivateKey 的结构。这也是从原始字节 PrivateKey 检索密钥对的函数。 **参考文档** - PBKDF2算法:https://segmentfault.com/a/1190000004261009 - 比特币btcd源码:https://github.com/btcsuite/btcd/blob/master/btcec/privkey.go - btcd包:https://pkg.go.dev/github.com/btcsuite/btcd/btcec#PrivKeyFromBytes - 理解btcd:https://hlongvu.com/post/z2hvvdr6wb-Understanding-btcd-Part-2-Key-and-Address - 区块链密码学:https://www.chaindesk.cn/witbook/15/230 --- 以上,就是今天分享的全部内容了,希望大家通过以上笔记可以解决自己的实际需求,解决自己目前所遇到的问题。 如果文章中如果有不太正确的地方,欢迎指正,可以添加我的个人微信,备注:地区-职业方向-昵称,欢迎来撩,加入golang技术交流群,与更多的golang开发者、技术大佬学习交流。

pbkdf2.Key() 生成秘钥函数

PBKDF2(Password-Based Key Derivation Function)

是一个用来导出密钥的函数,常用于生成加密的密码。

它的基本原理是通过一个伪随机函数(例如HMAC函数、sha512等),把明文(password)和一个盐值(salt)作为一个输入参数,然后重复进行运算,并最终产生秘钥。

如果重复的次数足够大,破解的成本就会变得很高。而盐值的添加也会增加“彩虹表”攻击的难度。

用户密码采用PBKDF2算法存储,比较安全。

PBKDF2函数的语法定义

DK = PBKDF2(PRF, Password, Salt, c, dkLen ,Hash algorithm)
  • PRF是一个伪随机函数,例如HASH_HMAC函数,它会输出长度为hLen的结果。
  • Password是用来生成密钥的原文密码。
  • Salt是一个加密用的盐值。
  • c是进行重复计算的次数。
  • dkLen是期望得到的密钥的长度。
  • DK是最后产生的密钥。

以下为使用助记词生成私钥的代码

package pbkdf2

import (
    "crypto/rand"
    "crypto/sha512"
    "golang.org/x/crypto/pbkdf2"
)

const (
    Mnemonic =  "search crime conversation tag directory joke leaf express interest password = ""
)
func encryptPwdWithSalt(password string) (*ecdsa.PrivateKey, *ecdsa.PublicKey) {
        seed := pbkdf2.Key([]byte(Mnemonic), []byte("mnemonic"+password), 2048, 64, sha512.New)
}

// []byte(Mnemonic):助记词
// []byte("mnemonic"+password) :salt盐值
// 2048:重复计算的次数
// 64:返回的秘钥长度
// sha512.New:哈希算法

HMAC 生成摘要算法

HMAC算法中文名称叫哈希消息认证码,英文全称是Hash-based Message Authentication Code。它的算法是基于某个哈希散列函数(主要是SHA系列和MD系列),以一个密钥和一个消息为输入,生成一个消息摘要作为输出。HMAC算法与其他哈希散列算法最大区别就是需要有密钥。它的算法函数是利用分组密码来建立的一个单向Hash函数。 下表显示具体的算法对应输出摘要的长度。

算法 摘要长度(位) 备注
HmacMD5 128 BouncyCastle实现
HmacSHA1 160 (20个字节) BouncyCastle实现
HmacSHA256 256 BouncyCastle实现
HmacSHA384 384 BouncyCastle实现
HmacSHA512 512 JAVA6实现
HmacMD2 128 BouncyCastle实现
HmacMD4 128 BouncyCastle实现
HmacSHA224 224 BouncyCastle实现

HMAC的密钥可以是任何长度,如果密钥的长度超过了摘要算法信息分组的长度,则首先使用摘要算法计算密钥的摘要作为新的密钥。一般不建议使用太短的密钥,因为密钥的长度与安全强度是相关的。通常选取密钥长度不小于所选用摘要算法输出的信息摘要的长度。

HMAC算法golang封装的代码详细解析

//创建运算对象,HMAC需要两个参数:hash函数和key
hmac := hmac.New(sha512.New, []byte(BitcoinSeed))
//将明文写入到hmac中
    _, err := hmac.Write([]byte(seed))
    if err != nil {
        return nil, nil
    }
//hmac对象对写入数据的运算,生成的参数为字节   
intermediary := hmac.Sum(nil)

用golang使用HMAC算法的距举例

package main

import (
    "crypto/hmac"
    "crypto/md5"
    "crypto/sha1"
    "encoding/hex"
    "fmt"
)

func Md5(data string) string {
    md5 := md5.New()
    md5.Write([]byte(data))
    md5Data := md5.Sum([]byte(""))
    return hex.EncodeToString(md5Data)
}

func Hmac(key, data string) string {
    hmac := hmac.New(md5.New, []byte(key))
    hmac.Write([]byte(data))
    return hex.EncodeToString(hmac.Sum(nil)
}

func Sha1(data string) string {
    sha1 := sha1.New()
    sha1.Write([]byte(data))
    return hex.EncodeToString(sha1.Sum(nil))
}

func main() {
    fmt.Println(Md5("hello"))
    fmt.Println(Hmac("key2", "hello"))
    fmt.Println(Sha1("hello"))
}

PrivKeyFromBytes 创建私钥、公钥对

根据作为参数作为字节切片传递的私钥返回“曲线”的私钥和公钥。

我们应该知道,可以从私钥生成公钥。所以拥有私钥相当于拥有整个密钥对。

以下为生成密钥对的代码:

func PrivKeyFromBytes(curve elliptic.Curve, pk []byte) (*PrivateKey, *PublicKey) {
    x, y := curve.ScalarBaseMult(pk)
    priv := &PrivateKey{
        PublicKey: e.PublicKey{
            Curve: curve,
            X:     x,
            Y:     y,
        },
        D: new(big.Int).SetBytes(pk),
    }
    return priv, (*PublicKey)(&priv.PublicKey)
}

*ecdsa.PrivateKey 是 PublicKey 和 PrivateKey 的结构。这也是从原始字节 PrivateKey 检索密钥对的函数。

参考文档

  • PBKDF2算法:https://segmentfault.com/a/1190000004261009
  • 比特币btcd源码:https://github.com/btcsuite/btcd/blob/master/btcec/privkey.go
  • btcd包:https://pkg.go.dev/github.com/btcsuite/btcd/btcec#PrivKeyFromBytes
  • 理解btcd:https://hlongvu.com/post/z2hvvdr6wb-Understanding-btcd-Part-2-Key-and-Address
  • 区块链密码学:https://www.chaindesk.cn/witbook/15/230

以上,就是今天分享的全部内容了,希望大家通过以上笔记可以解决自己的实际需求,解决自己目前所遇到的问题。

如果文章中如果有不太正确的地方,欢迎指正,可以添加我的个人微信,备注:地区-职业方向-昵称,欢迎来撩,加入golang技术交流群,与更多的golang开发者、技术大佬学习交流。

本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

  • 发表于 22小时前
  • 阅读 ( 70 )
  • 学分 ( 0 )
  • 分类:钱包

评论