1. 程式人生 > >ecc加密共識鎖demo

ecc加密共識鎖demo

之前版本的改進,增加了ecc加密,PoW機制等,並對一個使用者生成10對祕鑰實現匿名。

package main

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"math/big"
	"strconv"
	"time"
)

type Block struct {
	//PoW string
	timeStamp   string
	meetingTime string
	phoneNumber string
	lockNumber  string
	meetingName string
	roomNumber  string
	hashcode    string
	eccHashcode []byte
	prk         *ecdsa.PrivateKey
	puk         ecdsa.PublicKey
}

func calculateHashcode(b Block) string {
	data := b.meetingTime + b.phoneNumber + b.lockNumber + b.meetingName + b.roomNumber
	nonce := 1
	var str string
	var check string
	pass := false
	var dif int = 6
	for t := 0; ; t++ {
		str = ""
		check = ""
		check = data + strconv.Itoa(nonce)
		h := sha256.New()
		h.Write([]byte(check))
		hashed := h.Sum(nil)
		str = hex.EncodeToString(hashed)
		for i := 0; i < dif; i++ {
			if str[i] != '0' {
				nonce++
				break
			}
			if i == dif-1 {
				pass = true
			}
		}
		if pass == true {
			return str
		}
	}
}

func getKey() (*ecdsa.PrivateKey, error) {
	prk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	return prk, err
}

func eccSign(data []byte, prk *ecdsa.PrivateKey) ([]byte, error) {
	r, s, err := ecdsa.Sign(rand.Reader, prk, data)
	if err != nil {
		return nil, err
	}
	params := prk.Curve.Params()
	curveOrderByteSize := params.P.BitLen() / 8
	rBytes, sBytes := r.Bytes(), s.Bytes()
	signature := make([]byte, curveOrderByteSize*2)
	copy(signature[curveOrderByteSize-len(rBytes):], rBytes)
	copy(signature[curveOrderByteSize*2-len(sBytes):], sBytes)
	return signature, nil
}

func eccVerify(data, signature []byte, puk *ecdsa.PublicKey) bool {
	curveOrderByteSize := puk.Curve.Params().P.BitLen() / 8
	r, s := new(big.Int), new(big.Int)
	r.SetBytes(signature[:curveOrderByteSize])
	s.SetBytes(signature[curveOrderByteSize:])
	return ecdsa.Verify(puk, data, r, s)
}

func setBlock(mt, pn, ln, mn, rn string) Block {
	var newBlock Block
	t := time.Now()
	newBlock.timeStamp = t.String()
	//newBlock.PoW = proofOfWork(t.UnixNano())
	newBlock.meetingTime = mt
	newBlock.phoneNumber = pn
	newBlock.lockNumber = ln
	newBlock.meetingName = mn
	newBlock.roomNumber = rn
	newBlock.hashcode = calculateHashcode(newBlock)
	prk, err := getKey()
	if err != nil {
		panic(err)
	}
	newBlock.prk = prk
	newBlock.puk = prk.PublicKey
	eccHashcode, err := eccSign([]byte(newBlock.hashcode), newBlock.prk)
	if err != nil {
		panic(err)
	}
	newBlock.eccHashcode = eccHashcode
	return newBlock
}

func checkBlock(Block Block) bool {
	if calculateHashcode(Block) != Block.hashcode {
		fmt.Println("hash error")
		return false
	}
	if Block.timeStamp > "2018-10-17" {
		fmt.Println("	time error")
		return false
	}
	if eccVerify([]byte(Block.hashcode), Block.eccHashcode, &Block.puk) == false {
		fmt.Println("ecc error")
		return false
	}
	return true
}

func main() {
	var mt = "20181111"
	var pn = "18811881188"
	var ln = "001"
	var mn = "importantmeeting"
	var rn = "216"
	//var bc = setBlock(mt, pn, ln, mn, rn)
	var bc [10]Block
	for i := 0; i < 10; i++ {
		bc[i] = setBlock(mt, pn, ln, mn, rn)
		fmt.Println("{")
		fmt.Println("	user phonenumber:", bc[i].phoneNumber)
		fmt.Println("	lock number:", bc[i].lockNumber)
		fmt.Println("	meeting name:", bc[i].meetingName)
		fmt.Println("	room number:", bc[i].roomNumber)
		fmt.Println("	hash:", bc[i].hashcode)
		fmt.Println("	eccCrypto", hex.EncodeToString(bc[i].eccHashcode))
		fmt.Println("	check:", checkBlock(bc[i]))
		fmt.Println("}")
	}
	// fmt.Println(len(bc.hashcode))
	// fmt.Println(len(hex.EncodeToString(bc.eccHashcode)))
}