WIF(wallet import format)钱包导入格式,是一种私有的ESCDSA(椭圆曲线签名算法)秘钥,通过此种格式可以更方便的进行复制及存储。
其中,通过椭圆曲线签名算法生成的公钥一般来说是椭圆曲线上的x,y坐标拼接在一起的。压缩的公钥其实就是x的坐标,因为有了椭圆曲线还有x,顺理成章就可以求出y。
1:通过根据椭圆曲线算法生成私钥privateKey
2 : 如果是 Mainnet 的地址则在前面添加一个 0x80 的前缀,如果是 testnet 地址则在前面添加一个 0xef 前缀。如果私钥对应于压缩的公钥,则在末尾添加一个 0x01 的后缀。
3 : 对其生成的私钥privateKey连续两次sha256之后再取其前4个字节作为校验码checksum
4: 再对转换过的privateKey的后面拼接上checksum得到字节数组result
5: 最后再对字节数组result进行base58编码。

代码如下:

package main

import (
"blockTest/tool"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
)

//根据随机key及楕圆曲线生成私钥和公钥
func newKeyPair() (*ecdsa.PrivateKey, []byte) {
curve := elliptic.P256() //楕圆曲线
privateKey, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
fmt.Println(err)
}
publicKey := append(privateKey.PublicKey.X.Bytes(), privateKey.PublicKey.Y.Bytes()...)
return privateKey, publicKey
}

// 生成WIF私钥
// hexprivatekey 椭圆曲线16进制数据
//compressed 是否为压缩的公钥

func generatePrivateKey(hexprivatekey string,compressed bool) []byte{
versionstr :=""
//判断是否对应的是压缩的公钥,如果是,需要在后面加上0x01这个字节。同时任何的私钥,我们需要在前方0x80的字节
if compressed{
versionstr = "80" + hexprivatekey + "01"
}else{
versionstr = "80" + hexprivatekey
}
//字符串转化为16进制的字节
privatekey,_:=hex.DecodeString(versionstr)
//通过 double hash 计算checksum.checksum他是两次hash256以后的前4个字节。
firsthash:=sha256.Sum256(privatekey)

secondhash:= sha256.Sum256(firsthash[:])

checksum := secondhash[:4]
//拼接
result := append(privatekey,checksum...)

//最后进行base58的编码
base58result :=tool.Base58Encode(result)
return base58result

}

//检查checkWIF是否有效,实质是通过转换后的WIF私钥得到校验码及从WIF私钥串解析得到的校验码做匹配,匹配一致,则表示为合法的WIF私钥,不一致,则为非法的。
func checkWIF(wifprivate string) bool{
rawdata := []byte(wifprivate)
//包含了80、私钥、checksum
base58decodedata:= tool.Base58Decode(rawdata)
length :=len(base58decodedata)
//如果不是压缩的公钥,其长度为 "80"+32位私钥+4个字节校验码,为37个字节
//如果是压缩的公钥,其长度为(80,一个字节)+32个字节私钥(64位)+(01,一个字节)+4个字节校验码,总共为1+32+1+4=38个字节,故压缩后的私钥长度至少大于等于37个字节
if(length <37){
fmt.Printf("长度小于37,一定有问题")
return false
}
private := base58decodedata[:(length-4)]
//得到检查码
//fmt.Printf("private:%x\n",private)
firstsha := sha256.Sum256(private)

secondsha := sha256.Sum256(firstsha[:])

checksum := secondsha[:4]
//fmt.Printf("%x\n",checksum)
//得到原始的检查码
orignchecksum:= base58decodedata[(length-4):]
//  fmt.Printf("%x\n",orignchecksum)

//[]byte对比
if bytes.Compare(checksum,orignchecksum)==0{
    return true
}

return false

}

func main(){
privateKey,_:=newKeyPair()
fmt.Printf("私钥:%x\n", privateKey.D.Bytes())
wifprivatekey:=generatePrivateKey(hex.EncodeToString(privateKey.D.Bytes()),true)
fmt.Printf("WIF格式私钥为:%s\n",wifprivatekey)
privateKey2:=getPrivateKeyfromWIF(string(wifprivatekey))
fmt.Printf("通过WIF私钥获取原来的私钥,值为:%x\n", privateKey2)

}

运行结果如下所示:
私钥:0b0f26365fc38d502e650f1e6c73fcee9c071492968a00d4b68c053ea5cb9089
30623066323633363566633338643530326536353066316536633733666365653963303731343932393638613030643462363863303533656135636239303839
800b0f26365fc38d502e650f1e6c73fcee9c071492968a00d4b68c053ea5cb908901
WIF格式私钥为:KwbD3ZoRCLcoFab6xk5RRUK7no2DwWDc8NPoGaDZgNkTFqYJEovq
base58decodedata:800b0f26365fc38d502e650f1e6c73fcee9c071492968a00d4b68c053ea5cb908901a9003c22
通过WIF私钥获取原来的私钥,值为:0b0f26365fc38d502e650f1e6c73fcee9c071492968a00d4b68c053ea5cb9089