之前版本的改进,增加了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)))
}