Commit e0485ae2 authored by pengjun's avatar pengjun

add pre node

parents
# 对外重加密服务端口
bindAddr="localhost:11801"
# 区块链节点地址
nodeServer="http://127.0.0.1:8801"
# 节点外部IP
externalAddr="127.0.0.1"
# 节点操作私钥
preServerKey="0x85bf7aa29436bb186cac45ecd8ea9e63e56c5817e127ebb5e99cd5a9cbfe0f23"
# 节点收益地址
stakeAddr="16ui7XJ1VLM7YXcNhWwWsWS6CRC3ZA2sJ1"
# 数据存储路径
dbPath="preNode"
\ No newline at end of file
// Copyright Fuzamei Corp. 2020 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.13
package common
import (
"io/ioutil"
tml "github.com/BurntSushi/toml"
)
type Config struct {
BindAddr string
Nodeserver string
ExternalAddr string
PreServerKey string
StakeAddr string
DbPath string
}
func readFile(path string) string {
data, err := ioutil.ReadFile(path)
if err != nil {
panic(err)
}
return string(data)
}
func InitCfg(path string) (*Config, error) {
cfgstring := readFile(path)
var cfg Config
if _, err := tml.Decode(cfgstring, &cfg); err != nil {
return nil, err
}
return &cfg, nil
}
package common
import "errors"
var (
ErrEmpty = errors.New("ErrEmpty")
ErrPublicKeyInvalid = errors.New("ErrPublicKeyInvalid")
)
\ No newline at end of file
This diff is collapsed.
#!/bin/sh
protoc --go_out=plugins=grpc:../ ./*.proto --proto_path=.
syntax = "proto3";
package common;
// 发送秘钥分片请求
message ReqSendKeyFragment {
string pubOwner = 1; //数据所有者公钥
string pubRecipient = 2; //数据请求者公钥
string pubProofR = 3; //证明R公钥
string pubProofU = 4; //证明U公钥
string random = 5; //随机数
string value = 6; //处理秘钥数据
int64 expire = 7; //有效时间
string dhProof = 8; //发送证明,证明由pubOwner的地址发出
string precurPub = 9; //秘钥共享随机数
}
// 发送秘钥分片回复
message RepSendKeyFragment {
bool result = 1;
}
// 请求重加密
message ReqReeencryptParam {
string pubOwner = 1; //数据所有者公钥
string pubRecipient = 2; //数据请求者公钥
}
// 重加密返回
message RepReeencrypt {
string reKeyR = 1;
string reKeyU = 2;
string random = 3;
string precurPub = 4;
}
message keyFragment {
string pubProofR = 1; //证明R公钥
string pubProofU = 2; //证明U公钥
string ramdom = 3; //随机数
string value = 4; //处理秘钥数据
string precurPub = 5; //秘钥共享随机数
int64 expire = 6; //有效时间
}
module gitlab.33.cn/pengjun/reencrypt
go 1.12
require (
github.com/BurntSushi/toml v0.3.1
github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3
github.com/golang/protobuf v1.3.4
github.com/golang/snappy v0.0.1 // indirect
github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1
github.com/mattn/go-colorable v0.1.6 // indirect
github.com/mr-tron/base58 v1.1.3
github.com/onsi/ginkgo v1.12.0 // indirect
github.com/onsi/gomega v1.9.0 // indirect
github.com/rs/cors v1.7.0
github.com/spf13/cobra v0.0.7
github.com/stretchr/testify v1.5.1
github.com/syndtr/goleveldb v1.0.0
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392
)
This diff is collapsed.
package main
import (
"flag"
"fmt"
log "github.com/inconshreveable/log15"
"gitlab.33.cn/pengjun/reencrypt/common"
"gitlab.33.cn/pengjun/reencrypt/server"
"os"
"os/signal"
)
var (
configPath = flag.String("f", "chain33.pre.toml", "configfile")
)
func main() {
flag.Parse()
if *configPath == "" {
*configPath = "chain33.pre.toml"
}
log.Info("begin start pre server")
cfg, err := common.InitCfg(*configPath)
if err != nil {
panic(err)
}
routerServer, err := server.NewRpcServer(cfg)
if err != nil {
panic(err)
}
routerServer.Listen()
defer func() {
log.Info("begin close pre server")
routerServer.Close()
} ()
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
select {
case s := <-c:
fmt.Println("Got signal", s)
break
}
}
\ No newline at end of file
package sdk
import (
"gitlab.33.cn/pengjun/reencrypt/sdk/crypto"
)
type Account struct {
PrivateKey []byte
PublicKey []byte
Address string
SignType string
}
func NewAccount(signType string) (*Account, error) {
if signType == "" {
signType = crypto.SECP256k1
}
account := Account{}
account.SignType = signType
driver := crypto.NewSignDriver(signType)
account.PrivateKey = driver.GeneratePrivateKey()
account.PublicKey = driver.PubKeyFromPrivate(account.PrivateKey)
addr, err := crypto.PubKeyToAddress(account.PublicKey)
if err != nil {
return nil, err
}
account.Address = addr
return &account, nil
}
\ No newline at end of file
// Copyright Fuzamei Corp. 2020 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package jsonclient 实现JSON rpc客户端请求功能
package client
import (
"bytes"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"github.com/golang/protobuf/proto"
"io/ioutil"
"net/http"
"strings"
)
// JSONClient a object of jsonclient
type JSONClient struct {
url string
prefix string
tlsVerify bool
client *http.Client
}
func addPrefix(prefix, name string) string {
if strings.Contains(name, ".") {
return name
}
return prefix + "." + name
}
// NewJSONClient produce a json object
func NewJSONClient(prefix, url string) (*JSONClient, error) {
return new(prefix, url, false)
}
// New produce a jsonclient by perfix and url
func new(prefix, url string, tlsVerify bool) (*JSONClient, error) {
httpcli := http.DefaultClient
if strings.Contains(url, "https") { //暂不校验tls证书
httpcli = &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: !tlsVerify}}}
}
return &JSONClient{
url: url,
prefix: prefix,
tlsVerify: tlsVerify,
client: httpcli,
}, nil
}
type clientRequest struct {
Method string `json:"method"`
Params [1]interface{} `json:"params"`
ID uint64 `json:"id"`
}
type clientResponse struct {
ID uint64 `json:"id"`
Result *json.RawMessage `json:"result"`
Error interface{} `json:"error"`
}
func (client *JSONClient) Call(method string, params, resp interface{}) error {
method = addPrefix(client.prefix, method)
req := &clientRequest{}
req.Method = method
req.Params[0] = params
data, err := json.Marshal(req)
if err != nil {
return err
}
postresp, err := client.client.Post(client.url, "application/json", bytes.NewBuffer(data))
if err != nil {
return err
}
defer postresp.Body.Close()
b, err := ioutil.ReadAll(postresp.Body)
if err != nil {
return err
}
cresp := &clientResponse{}
err = json.Unmarshal(b, &cresp)
if err != nil {
return err
}
if cresp.Error != nil {
x, ok := cresp.Error.(string)
if !ok {
return fmt.Errorf("invalid error %v", cresp.Error)
}
if x == "" {
x = "unspecified error"
}
return fmt.Errorf(x)
}
if cresp.Result == nil {
return errors.New("Empty result")
}
if msg, ok := resp.(proto.Message); ok {
var str json.RawMessage
err = json.Unmarshal(*cresp.Result, &str)
if err != nil {
return err
}
b, err := str.MarshalJSON()
if err != nil {
return err
}
err = json.Unmarshal(b, msg)
if err != nil {
fmt.Println("err", err)
return err
}
return nil
}
return json.Unmarshal(*cresp.Result, resp)
}
// 发送交易
func (client *JSONClient) SendTransaction(signedTx string) (string, error) {
var res string
send := &RawParm{
Token: "BTY",
Data: signedTx,
}
err := client.Call("Chain33.SendTransaction", send, &res)
if err != nil {
return "", err
}
return res, nil
}
// 查询交易
func (client *JSONClient) QueryTransaction(hash string) (*TransactionDetail, error) {
query := QueryParm{
Hash: hash,
}
var detail TransactionDetail
err := client.Call("Chain33.QueryTransaction", query, &detail)
if err != nil {
return nil, err
}
return &detail, nil
}
\ No newline at end of file
package client
import "encoding/json"
// RawParm defines raw parameter command
type RawParm struct {
Token string `json:"token"`
Data string `json:"data"`
}
// CreateTxIn create tx input
type CreateTxIn struct {
Execer string `json:"execer"`
ActionName string `json:"actionName"`
Payload json.RawMessage `json:"payload"`
}
// QueryParm Query parameter
type QueryParm struct {
Hash string `json:"hash"`
}
// Signature parameter
type Signature struct {
Ty int32 `json:"ty"`
Pubkey string `json:"pubkey"`
Signature string `json:"signature"`
}
// Transaction parameter
type Transaction struct {
Execer string `json:"execer"`
Payload json.RawMessage `json:"payload"`
RawPayload string `json:"rawPayload"`
Signature *Signature `json:"signature"`
Fee int64 `json:"fee"`
FeeFmt string `json:"feefmt"`
Expire int64 `json:"expire"`
Nonce int64 `json:"nonce"`
From string `json:"from,omitempty"`
To string `json:"to"`
Amount int64 `json:"amount,omitempty"`
AmountFmt string `json:"amountfmt,omitempty"`
GroupCount int32 `json:"groupCount,omitempty"`
Header string `json:"header,omitempty"`
Next string `json:"next,omitempty"`
Hash string `json:"hash,omitempty"`
}
// ReceiptDataResult receipt data result
type ReceiptDataResult struct {
Ty int32 `json:"ty"`
TyName string `json:"tyName"`
Logs []*ReceiptLogResult `json:"logs"`
}
// ReceiptLogResult receipt log result
type ReceiptLogResult struct {
Ty int32 `json:"ty"`
TyName string `json:"tyName"`
Log json.RawMessage `json:"log"`
RawLog string `json:"rawLog"`
}
// Asset asset
type Asset struct {
Exec string `json:"exec"`
Symbol string `json:"symbol"`
Amount int64 `json:"amount"`
}
// TxProof :
type TxProof struct {
Proofs []string `json:"proofs"`
Index uint32 `json:"index"`
RootHash string `json:"rootHash"`
}
// TransactionDetail transaction detail
type TransactionDetail struct {
Tx *Transaction `json:"tx"`
Receipt *ReceiptDataResult `json:"receipt"`
Proofs []string `json:"proofs"`
Height int64 `json:"height"`
Index int64 `json:"index"`
Blocktime int64 `json:"blockTime"`
Amount int64 `json:"amount"`
Fromaddr string `json:"fromAddr"`
ActionName string `json:"actionName"`
Assets []*Asset `json:"assets"`
TxProofs []*TxProof `json:"txProofs"`
FullHash string `json:"fullHash"`
}
package crypto
import (
"crypto/sha256"
"fmt"
"github.com/mr-tron/base58/base58"
"golang.org/x/crypto/ripemd160"
)
//不同币种的前缀版本号
var coinPrefix = map[string][]byte{
"BTC": {0x00},
"BCH": {0x00},
"BTY": {0x00},
"LTC": {0x30},
"ZEC": {0x1c, 0xb8},
"USDT": {0x00},
}
func PubKeyToAddress(pub []byte) (addr string, err error) {
if len(pub) != 33 && len(pub) != 65 { //压缩格式 与 非压缩格式
return "", fmt.Errorf("invalid public key byte")
}
sha256h := sha256.New()
_, err = sha256h.Write(pub)
if err != nil {
return "", err
}
//160hash
ripemd160h := ripemd160.New()
_, err = ripemd160h.Write(sha256h.Sum([]byte("")))
if err != nil {
return "", err
}
//添加版本号
hash160res := append(coinPrefix["BTY"], ripemd160h.Sum([]byte(""))...)
//添加校验码
cksum := checksum(hash160res)
address := append(hash160res, cksum[:]...)
//地址进行base58编码
addr = base58.Encode(address)
return
}
//checksum: first four bytes of double-SHA256.
func checksum(input []byte) (cksum [4]byte) {
h := sha256.New()
_, err := h.Write(input)
if err != nil {
return
}
intermediateHash := h.Sum(nil)
h.Reset()
_, err = h.Write(intermediateHash)
if err != nil {
return
}
finalHash := h.Sum(nil)
copy(cksum[:], finalHash[:])
return
}
\ No newline at end of file
package crypto
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"errors"
"io"
)
func pkcs7Padding(src []byte) []byte {
padding := aes.BlockSize - len(src)%aes.BlockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(src, padtext...)
}
func aesCBCEncrypt(key, s []byte) ([]byte, error) {
return aesCBCEncryptWithRand(rand.Reader, key, s)
}
func aesCBCEncryptWithRand(prng io.Reader, key, s []byte) ([]byte, error) {
if len(s)%aes.BlockSize != 0 {
return nil, errors.New("Invalid plaintext. It must be a multiple of the block size")
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
ciphertext := make([]byte, aes.BlockSize+len(s))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(prng, iv); err != nil {
return nil, err
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext[aes.BlockSize:], s)
return ciphertext, nil
}
func aesCBCDecrypt(key, src []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
if len(src) < aes.BlockSize {
return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size")
}
iv := src[:aes.BlockSize]
src = src[aes.BlockSize:]
if len(src)%aes.BlockSize != 0 {
return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size")
}
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(src, src)
return src, nil
}
func pkcs7UnPadding(src []byte) ([]byte, error) {
length := len(src)
unpadding := int(src[length-1])
if unpadding > aes.BlockSize || unpadding == 0 {
return nil, errors.New("Invalid pkcs7 padding (unpadding > aes.BlockSize || unpadding == 0)")
}
pad := src[len(src)-unpadding:]
for i := 0; i < unpadding; i++ {
if pad[i] != byte(unpadding) {
return nil, errors.New("Invalid pkcs7 padding (pad[i] != unpadding)")
}
}
return src[:(length - unpadding)], nil
}
func AESCBCPKCS7Encrypt(key, src []byte) ([]byte, error) {
tmp := pkcs7Padding(src)
return aesCBCEncrypt(key, tmp)
}
func AESCBCPKCS7Decrypt(key, src []byte) ([]byte, error) {
pt, err := aesCBCDecrypt(key, src)
if err == nil {
return pkcs7UnPadding(pt)
}
return nil, err
}
\ No newline at end of file
package crypto
import (
"fmt"
"gitlab.33.cn/pengjun/reencrypt/sdk/types"
"math/big"
"testing"
)
func TestAES(t *testing.T) {
var text = "hello aes"
var key = GetRandBytes(32)
cipherText, err := AESCBCPKCS7Encrypt(key, []byte(text))
if err != nil {
fmt.Println(err)
return
}
cipher, err := AESCBCPKCS7Decrypt(key, cipherText)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(cipher))
}
func TestUtil(t *testing.T) {
var num = big.NewInt(123)
fmt.Println(num)
numstr := types.BigToString(num)
fmt.Println(numstr)
res := types.StringToBig(numstr)
fmt.Println(res)
}
\ No newline at end of file
package crypto
import (
"crypto/rand"
"crypto/sha256"
secp256k1 "github.com/btcsuite/btcd/btcec"
)
var (
SECP256k1 = "secp256k1"
SM2 = "sm2" //TODO
ED25519 = "ed25519" //TODO
)
type CryptoDriver interface {
GeneratePrivateKey() []byte
PubKeyFromPrivate(privKey []byte) []byte
Sign(msg []byte, privKey []byte) []byte
}
func NewSignDriver(signType string) CryptoDriver {
if signType == "secp256k1"{
return &Secp256k1Driver{}
} else {
// TODO
return nil
}
}
type Secp256k1Driver struct { }
func (driver *Secp256k1Driver) GeneratePrivateKey() []byte {
privKeyBytes := make([]byte, 32)
copy(privKeyBytes[:], GetRandBytes(32))
priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKeyBytes[:])
copy(privKeyBytes[:], priv.Serialize())
return privKeyBytes
}
func (driver *Secp256k1Driver) PubKeyFromPrivate(privKey []byte) []byte {
_, pub := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
pubSecp256k1 := make([]byte, 33)
copy(pubSecp256k1[:], pub.SerializeCompressed())
return pubSecp256k1
}
func (driver *Secp256k1Driver) Sign(msg []byte, privKey []byte) []byte {
priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
sig, err := priv.Sign(Sha256(msg))
if err != nil {
panic("Error signing secp256k1" + err.Error())
}
return sig.Serialize()
}
func PrivateECDSAFromByte(privKey []byte) *secp256k1.PrivateKey {
priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
return priv
}
func PublicECDSAFromByte(pubKey []byte) *secp256k1.PublicKey {
pub, _ := secp256k1.ParsePubKey(pubKey, secp256k1.S256())
return pub
}
func GetRandBytes(numBytes int) []byte {
b := make([]byte, numBytes)
_, err := rand.Read(b)
if err != nil {
panic("Panic on a Crisis" + err.Error())
}
return b
}
func Sha256(b []byte) []byte {
hasher := sha256.New()
hasher.Write(b)
return hasher.Sum(nil)
}
package sdk
import (
"crypto/rand"
"fmt"
secp256k1 "github.com/btcsuite/btcd/btcec"
"gitlab.33.cn/pengjun/reencrypt/sdk/crypto"
"gitlab.33.cn/pengjun/reencrypt/sdk/types"
"golang.org/x/crypto/blake2b"
"math/big"
)
var baseN = secp256k1.S256().Params().N
type KFrag struct {
Random string
Value string
PrecurPub string
}
type ReKeyFrag struct {
ReKeyR string
ReKeyU string
Random string
PrecurPub string
}
type EccPoit struct {
x *big.Int
y *big.Int
}
func NewEccPoint(pubStr string) (*EccPoit, error) {
reKeyRByte, err := types.FromHex(pubStr)
if err != nil {
fmt.Errorf("get reKeyRByte err", err)
return nil, err
}
reKeyR := crypto.PublicECDSAFromByte(reKeyRByte)
return &EccPoit{x: reKeyR.X, y: reKeyR.Y}, nil
}
func (p *EccPoit) Add(v *EccPoit) *EccPoit {
if v == nil {
return p
}
p.x, p.y = secp256k1.S256().Add(p.x, p.y, v.x, v.y)
return p
}
func (p *EccPoit) MulInt(i *big.Int) *EccPoit {
p.x, p.y = secp256k1.S256().ScalarMult(p.x, p.y, i.Bytes())
return p
}
func (p *EccPoit) ToPublicKey() *secp256k1.PublicKey {
return &secp256k1.PublicKey{
X: p.x,
Y: p.y,
Curve: secp256k1.S256(),
}
}
func hashToModInt(digest []byte) *big.Int {
sum := new(big.Int).SetBytes(digest)
one := big.NewInt(1)
order_minus_1 := big.NewInt(0)
order_minus_1.Sub(baseN, one)
bigNum := big.NewInt(0)
bigNum.Mod(sum, order_minus_1).Add(bigNum, one)
return bigNum
}
func makeShamirPolyCoeff(threshold int) []*big.Int {
driver := crypto.NewSignDriver(crypto.SECP256k1)
coeffs := make([]*big.Int, threshold-1)
for i,_ := range coeffs {
key := crypto.PrivateECDSAFromByte(driver.GeneratePrivateKey())
coeffs[i] = key.D
}
return coeffs
}
// p0*x^2 + p1 * x + p2
func hornerPolyEval(poly []*big.Int, x *big.Int) *big.Int {
result := big.NewInt(0)
result.Add(result, poly[0])
for i := 1; i < len(poly); i++ {
result = result.Mul(result, x).Add(result, poly[i])
}
return result.Mod(result, baseN)
}
func calcPart(a *big.Int, b *big.Int) *big.Int {
p := big.NewInt(0)
p.Sub(a, b).Mod(p, baseN)
res := big.NewInt(0)
res.Mul(a, p.ModInverse(p, baseN)).Mod(res, baseN)
return res
}
func calcLambdaCoeff(inId *big.Int, selectedIds []*big.Int) *big.Int {
var ids []*big.Int
for _, id := range selectedIds {
if inId.Cmp(id) == 0 {
continue
}
ids = append(ids, id)
}
if len(ids) == 0 {
return big.NewInt(1)
}
result := calcPart(ids[0], inId)
if len(ids) > 1 {
for _, id_j := range ids[1:] {
result.Mul(result, calcPart(id_j, inId)).Mod(result, baseN)
}
}
return result
}
func getRandomInt(order *big.Int) *big.Int {
randInt, err := rand.Int(rand.Reader, order)
if err != nil {
panic(err)
}
return randInt
}
func GenerateEncryptKey(pubOwner []byte) ([]byte, string, string) {
pubOwnerKey := crypto.PublicECDSAFromByte(pubOwner)
driver := crypto.NewSignDriver(crypto.SECP256k1)
priv_r := crypto.PrivateECDSAFromByte(driver.GeneratePrivateKey())
priv_u := crypto.PrivateECDSAFromByte(driver.GeneratePrivateKey())
result := &secp256k1.PublicKey{}
result.Curve = pubOwnerKey.Curve
sum := big.NewInt(0)
sum.Add(priv_u.D, priv_r.D).Mod(sum, baseN)
result.X, result.Y = secp256k1.S256().ScalarMult(pubOwnerKey.X, pubOwnerKey.Y, sum.Bytes())
pub_r := types.ToHex((*secp256k1.PublicKey)(&priv_r.PublicKey).SerializeCompressed())
pub_u := types.ToHex((*secp256k1.PublicKey)(&priv_u.PublicKey).SerializeCompressed())
return result.SerializeCompressed(), pub_r, pub_u
}
func GenerateKeyFragments(privOwner []byte, pubRecipient []byte, numSplit, threshold int) ([]*KFrag, error) {
driver := crypto.NewSignDriver(crypto.SECP256k1)
precursor := crypto.PrivateECDSAFromByte(driver.GeneratePrivateKey())
precurPub := types.ToHex((*secp256k1.PublicKey)(&precursor.PublicKey).SerializeCompressed())
privOwnerKey := crypto.PrivateECDSAFromByte(privOwner)
pubRecipientKey := crypto.PublicECDSAFromByte(pubRecipient)
dh_Alice_poit_x := types.ECDH(precursor, pubRecipientKey)
dAliceHash, err := blake2b.New256(precursor.X.Bytes())
if err != nil {
fmt.Errorf("Generate precursor Key err", err)
return nil, err
}
dAliceHash.Write(pubRecipientKey.X.Bytes())
dAliceHash.Write(dh_Alice_poit_x.Bytes())
dAlice := dAliceHash.Sum(nil)
dAliceBN := hashToModInt(dAlice)
// c0, c1, c2
f0 := big.NewInt(0)
f0.Mul(privOwnerKey.D, f0.ModInverse(dAliceBN, baseN)).Mod(f0, baseN)
kFrags := make([]*KFrag, numSplit)
if numSplit == 1 {
id := getRandomInt(baseN)
kFrags[0] = &KFrag{Random: types.BigToString(id), Value: types.BigToString(f0), PrecurPub: precurPub}
} else {
coeffs := makeShamirPolyCoeff(threshold)
coeffs = append(coeffs, f0)
// rk[i] = f2*id^2 + f1*id + f0
for i, _ := range kFrags {
id := getRandomInt(baseN)
dShareHash, err := blake2b.New256(precursor.X.Bytes())
if err != nil {
fmt.Errorf("Generate precursor Key err", err)
return nil, err
}
dShareHash.Write(pubRecipientKey.X.Bytes())
dShareHash.Write(dh_Alice_poit_x.Bytes())
dShareHash.Write(id.Bytes())
share := hashToModInt(dShareHash.Sum(nil))
rk := hornerPolyEval(coeffs, share)
kFrags[i] = &KFrag{Random: types.BigToString(id), Value: types.BigToString(rk), PrecurPub: precurPub}
}
}
return kFrags, nil
}
func AssembleReencryptFragment(privRecipient []byte, reKeyFrags []*ReKeyFrag) ([]byte, error) {
privRecipientKey := crypto.PrivateECDSAFromByte(privRecipient)
precursor, err := types.FromHex(reKeyFrags[0].PrecurPub)
if err != nil {
fmt.Errorf("FromHex", err)
return nil, err
}
precursorPubKey := crypto.PublicECDSAFromByte(precursor)
dh_Bob_poit_x := types.ECDH(privRecipientKey, precursorPubKey)
dBobHash, err := blake2b.New256(precursorPubKey.X.Bytes())
if err != nil {
fmt.Errorf("Generate precursor Key err", err)
return nil, err
}
dBobHash.Write(privRecipientKey.X.Bytes())
dBobHash.Write(dh_Bob_poit_x.Bytes())
dhBob := dBobHash.Sum(nil)
dhBobBN := hashToModInt(dhBob)
var share_key *EccPoit
if len(reKeyFrags) == 1 {
rPoint, err := NewEccPoint(reKeyFrags[0].ReKeyR)
if err != nil {
fmt.Errorf("get reKeyRByte err", err)
return nil, err
}
uPoint, err := NewEccPoint(reKeyFrags[0].ReKeyU)
if err != nil {
fmt.Errorf("get reKeyRByte err", err)
return nil, err
}
share_key = rPoint.Add(uPoint).MulInt(dhBobBN)
} else {
var eFinal, vFinal *EccPoit
ids := make([]*big.Int, len(reKeyFrags))
for x, _ := range ids {
xs, err := blake2b.New256(precursorPubKey.X.Bytes())
if err != nil {
fmt.Errorf("Generate precursor Key err", err)
return nil, err
}
xs.Write(privRecipientKey.X.Bytes())
xs.Write(dh_Bob_poit_x.Bytes())
randomByte, err := types.FromHex(reKeyFrags[x].Random)
if err != nil {
fmt.Errorf("get randomByte err", err)
return nil, err
}
xs.Write(randomByte)
ids[x] = hashToModInt(xs.Sum(nil))
}
for i, id := range ids {
lambda := calcLambdaCoeff(id, ids)
if lambda == nil {
continue
}
rPoint, err := NewEccPoint(reKeyFrags[i].ReKeyR)
if err != nil {
fmt.Errorf("get reKeyRByte err", err)
return nil, err
}
uPoint, err := NewEccPoint(reKeyFrags[i].ReKeyU)
if err != nil {
fmt.Errorf("get reKeyRByte err", err)
return nil, err
}
e := rPoint.MulInt(lambda)
v := uPoint.MulInt(lambda)
eFinal = e.Add(eFinal)
vFinal = v.Add(vFinal)
}
share_key = eFinal.Add(vFinal).MulInt(dhBobBN)
}
return share_key.ToPublicKey().SerializeCompressed(), nil
}
\ No newline at end of file
#!/bin/sh
protoc --go_out=plugins=grpc:../types/ ./*.proto --proto_path=.
syntax = "proto3";
package types;
message Transaction {
bytes execer = 1;
bytes payload = 2;
Signature signature = 3;
int64 fee = 4;
int64 expire = 5;
//随机ID,可以防止payload 相同的时候,交易重复
int64 nonce = 6;
//对方地址,如果没有对方地址,可以为空
string to = 7;
int32 groupCount = 8;
bytes header = 9;
bytes next = 10;
}
message Signature {
int32 ty = 1;
bytes pubkey = 2;
//当ty为5时,格式应该用RingSignature去解析
bytes signature = 3;
}
package sdk
import (
"encoding/hex"
"errors"
"gitlab.33.cn/pengjun/reencrypt/sdk/crypto"
"gitlab.33.cn/pengjun/reencrypt/sdk/types"
)
func SignRawTransaction(raw string, privateKey string, signType string) (string, error) {
var tx types.Transaction
txByteData, err := types.FromHex(raw)
if err != nil {
return "", err
}
err = types.Decode(txByteData, &tx)
if err != nil {
return "", err
}
tx.Signature = nil
if signType == "" {
signType = crypto.SECP256k1
}
signer := crypto.NewSignDriver(signType)
if signer == nil {
return "", errors.New("signType error")
}
key, err := types.FromHex(privateKey)
if err != nil {
return "", err
}
pub := signer.PubKeyFromPrivate(key)
data := types.Encode(&tx)
signature := signer.Sign(data, key)
tx.Signature = &types.Signature{
Ty: 1,
Pubkey: pub,
Signature: signature,
}
data = types.Encode(&tx)
return hex.EncodeToString(data), nil
}
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: sdk.proto
package types
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Transaction struct {
Execer []byte `protobuf:"bytes,1,opt,name=execer,proto3" json:"execer,omitempty"`
Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"`
Signature *Signature `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"`
Fee int64 `protobuf:"varint,4,opt,name=fee,proto3" json:"fee,omitempty"`
Expire int64 `protobuf:"varint,5,opt,name=expire,proto3" json:"expire,omitempty"`
//随机ID,可以防止payload 相同的时候,交易重复
Nonce int64 `protobuf:"varint,6,opt,name=nonce,proto3" json:"nonce,omitempty"`
//对方地址,如果没有对方地址,可以为空
To string `protobuf:"bytes,7,opt,name=to,proto3" json:"to,omitempty"`
GroupCount int32 `protobuf:"varint,8,opt,name=groupCount,proto3" json:"groupCount,omitempty"`
Header []byte `protobuf:"bytes,9,opt,name=header,proto3" json:"header,omitempty"`
Next []byte `protobuf:"bytes,10,opt,name=next,proto3" json:"next,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Transaction) Reset() { *m = Transaction{} }
func (m *Transaction) String() string { return proto.CompactTextString(m) }
func (*Transaction) ProtoMessage() {}
func (*Transaction) Descriptor() ([]byte, []int) {
return fileDescriptor_70decb0fb6f436df, []int{0}
}
func (m *Transaction) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Transaction.Unmarshal(m, b)
}
func (m *Transaction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Transaction.Marshal(b, m, deterministic)
}
func (m *Transaction) XXX_Merge(src proto.Message) {
xxx_messageInfo_Transaction.Merge(m, src)
}
func (m *Transaction) XXX_Size() int {
return xxx_messageInfo_Transaction.Size(m)
}
func (m *Transaction) XXX_DiscardUnknown() {
xxx_messageInfo_Transaction.DiscardUnknown(m)
}
var xxx_messageInfo_Transaction proto.InternalMessageInfo
func (m *Transaction) GetExecer() []byte {
if m != nil {
return m.Execer
}
return nil
}
func (m *Transaction) GetPayload() []byte {
if m != nil {
return m.Payload
}
return nil
}
func (m *Transaction) GetSignature() *Signature {
if m != nil {
return m.Signature
}
return nil
}
func (m *Transaction) GetFee() int64 {
if m != nil {
return m.Fee
}
return 0
}
func (m *Transaction) GetExpire() int64 {
if m != nil {
return m.Expire
}
return 0
}
func (m *Transaction) GetNonce() int64 {
if m != nil {
return m.Nonce
}
return 0
}
func (m *Transaction) GetTo() string {
if m != nil {
return m.To
}
return ""
}
func (m *Transaction) GetGroupCount() int32 {
if m != nil {
return m.GroupCount
}
return 0
}
func (m *Transaction) GetHeader() []byte {
if m != nil {
return m.Header
}
return nil
}
func (m *Transaction) GetNext() []byte {
if m != nil {
return m.Next
}
return nil
}
type Signature struct {
Ty int32 `protobuf:"varint,1,opt,name=ty,proto3" json:"ty,omitempty"`
Pubkey []byte `protobuf:"bytes,2,opt,name=pubkey,proto3" json:"pubkey,omitempty"`
//当ty为5时,格式应该用RingSignature去解析
Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Signature) Reset() { *m = Signature{} }
func (m *Signature) String() string { return proto.CompactTextString(m) }
func (*Signature) ProtoMessage() {}
func (*Signature) Descriptor() ([]byte, []int) {
return fileDescriptor_70decb0fb6f436df, []int{1}
}
func (m *Signature) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Signature.Unmarshal(m, b)
}
func (m *Signature) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Signature.Marshal(b, m, deterministic)
}
func (m *Signature) XXX_Merge(src proto.Message) {
xxx_messageInfo_Signature.Merge(m, src)
}
func (m *Signature) XXX_Size() int {
return xxx_messageInfo_Signature.Size(m)
}
func (m *Signature) XXX_DiscardUnknown() {
xxx_messageInfo_Signature.DiscardUnknown(m)
}
var xxx_messageInfo_Signature proto.InternalMessageInfo
func (m *Signature) GetTy() int32 {
if m != nil {
return m.Ty
}
return 0
}
func (m *Signature) GetPubkey() []byte {
if m != nil {
return m.Pubkey
}
return nil
}
func (m *Signature) GetSignature() []byte {
if m != nil {
return m.Signature
}
return nil
}
func init() {
proto.RegisterType((*Transaction)(nil), "types.Transaction")
proto.RegisterType((*Signature)(nil), "types.Signature")
}
func init() { proto.RegisterFile("sdk.proto", fileDescriptor_70decb0fb6f436df) }
var fileDescriptor_70decb0fb6f436df = []byte{
// 255 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x90, 0x41, 0x4e, 0xc3, 0x30,
0x10, 0x45, 0xe5, 0xa4, 0x49, 0xc9, 0xb4, 0x42, 0xd5, 0x08, 0xa1, 0x59, 0x20, 0x14, 0x75, 0xe5,
0x55, 0x16, 0x70, 0x04, 0x4e, 0x80, 0xe1, 0x02, 0x6e, 0x32, 0x94, 0xa8, 0xc8, 0xb6, 0x1c, 0x47,
0xaa, 0xcf, 0xc0, 0xa5, 0x51, 0x9c, 0x14, 0x2a, 0x76, 0xf3, 0x5e, 0xa2, 0x3f, 0x9e, 0x0f, 0xd5,
0xd0, 0x9d, 0x1a, 0xe7, 0x6d, 0xb0, 0x58, 0x84, 0xe8, 0x78, 0xd8, 0x7f, 0x67, 0xb0, 0x79, 0xf7,
0xda, 0x0c, 0xba, 0x0d, 0xbd, 0x35, 0x78, 0x0f, 0x25, 0x9f, 0xb9, 0x65, 0x4f, 0xa2, 0x16, 0x72,
0xab, 0x16, 0x42, 0x82, 0xb5, 0xd3, 0xf1, 0xcb, 0xea, 0x8e, 0xb2, 0xf4, 0xe1, 0x82, 0xd8, 0x40,
0x35, 0xf4, 0x47, 0xa3, 0xc3, 0xe8, 0x99, 0xf2, 0x5a, 0xc8, 0xcd, 0xd3, 0xae, 0x49, 0xe1, 0xcd,
0xdb, 0xc5, 0xab, 0xbf, 0x5f, 0x70, 0x07, 0xf9, 0x07, 0x33, 0xad, 0x6a, 0x21, 0x73, 0x35, 0x8d,
0xf3, 0x4e, 0xd7, 0x7b, 0xa6, 0x22, 0xc9, 0x85, 0xf0, 0x0e, 0x0a, 0x63, 0x4d, 0xcb, 0x54, 0x26,
0x3d, 0x03, 0xde, 0x42, 0x16, 0x2c, 0xad, 0x6b, 0x21, 0x2b, 0x95, 0x05, 0x8b, 0x8f, 0x00, 0x47,
0x6f, 0x47, 0xf7, 0x62, 0x47, 0x13, 0xe8, 0xa6, 0x16, 0xb2, 0x50, 0x57, 0x66, 0x4a, 0xff, 0x64,
0xdd, 0xb1, 0xa7, 0x6a, 0xbe, 0x68, 0x26, 0x44, 0x58, 0x19, 0x3e, 0x07, 0x82, 0x64, 0xd3, 0xbc,
0x7f, 0x85, 0xea, 0xf7, 0xcd, 0x69, 0x51, 0x4c, 0x35, 0x14, 0x2a, 0x0b, 0x71, 0x0a, 0x72, 0xe3,
0xe1, 0xc4, 0x71, 0x69, 0x60, 0x21, 0x7c, 0xf8, 0x5f, 0xc0, 0xf6, 0xea, 0xdc, 0x43, 0x99, 0xea,
0x7e, 0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, 0x21, 0x50, 0x6b, 0x04, 0x7b, 0x01, 0x00, 0x00,
}
package types
import (
"encoding/hex"
secp256k1 "github.com/btcsuite/btcd/btcec"
"github.com/golang/protobuf/proto"
"math/big"
)
//FromHex hex -> []byte
func FromHex(s string) ([]byte, error) {
if len(s) > 1 {
if s[0:2] == "0x" || s[0:2] == "0X" {
s = s[2:]
}
if len(s)%2 == 1 {
s = "0" + s
}
return hex.DecodeString(s)
}
return []byte{}, nil
}
//ToHex []byte -> hex
func ToHex(b []byte) string {
hex := hex.EncodeToString(b)
// Prefer output of "0x0" instead of "0x"
if len(hex) == 0 {
return ""
}
return "0x" + hex
}
//Encode 编码
func Encode(data proto.Message) []byte {
b, err := proto.Marshal(data)
if err != nil {
panic(err)
}
return b
}
//Decode 解码
func Decode(data []byte, msg proto.Message) error {
return proto.Unmarshal(data, msg)
}
// ECDH Calculate a shared secret using elliptic curve Diffie-Hellman
func ECDH(priv *secp256k1.PrivateKey, pub *secp256k1.PublicKey) *big.Int {
x, _ := secp256k1.S256().ScalarMult(pub.X, pub.Y, priv.D.Bytes())
return x
}
func BigToString(num *big.Int) string {
return ToHex(num.Bytes())
}
func StringToBig(num string) *big.Int {
numbyte, err := FromHex(num)
if err != nil {
panic(err)
}
return new(big.Int).SetBytes(numbyte)
}
\ No newline at end of file
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.13
package server
import (
"encoding/json"
"strings"
"net/http"
"io"
"compress/gzip"
)
type serverResponse struct {
ID uint64 `json:"id"`
Result interface{} `json:"result"`
Error interface{} `json:"error"`
}
func writeError(w http.ResponseWriter, r *http.Request, id uint64, errstr string) {
w.Header().Set("Content-type", "application/json")
//错误的请求也返回 200
w.WriteHeader(200)
resp, err := json.Marshal(&serverResponse{id, nil, errstr})
if err != nil {
rlog.Debug("json marshal error, nerver happen")
return
}
_, err = w.Write(resp)
if err != nil {
rlog.Debug("Write", "err", err)
return
}
}
// HTTPConn adapt HTTP connection to ReadWriteCloser
type HTTPConn struct {
r *http.Request
in io.Reader
out io.Writer
}
// Read rewrite the read of http
func (c *HTTPConn) Read(p []byte) (n int, err error) { return c.in.Read(p) }
// Write rewrite the write of http
func (c *HTTPConn) Write(d []byte) (n int, err error) { //添加支持gzip 发送
if strings.Contains(c.r.Header.Get("Accept-Encoding"), "gzip") {
gw := gzip.NewWriter(c.out)
defer gw.Close()
return gw.Write(d)
}
return c.out.Write(d)
}
// Close rewrite the close of http
func (c *HTTPConn) Close() error { return nil }
\ No newline at end of file
// Copyright Fuzamei Corp. 2020 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package server
import (
"errors"
"fmt"
"gitlab.33.cn/pengjun/reencrypt/sdk"
"gitlab.33.cn/pengjun/reencrypt/sdk/client"
"time"
)
// PreClient a object of jsonclient
type PreClient struct {
client *client.JSONClient
key string
}
// NewPreClient produce a json object
func NewPreClient(client *client.JSONClient, key string) *PreClient {
return &PreClient{
client: client,
key: key,
}
}
func (pre *PreClient) RegisterPreNode(url, statkeAddr string) (string, error) {
// 构造交易
params := &client.CreateTxIn{
Execer: "pre",
ActionName: "NodeRegister",
Payload: []byte(fmt.Sprintf("{\"url\":\"%s\", \"stakeAddr\":\"%s\"}",url, statkeAddr)),
}
var res string
err := pre.client.Call("Chain33.CreateTransaction", params, &res)
if err != nil {
return "", err
}
// 签名
signedTx, err := sdk.SignRawTransaction(res, pre.key, "")
if err != nil {
return "", err
}
// 发送
hash, err := pre.client.SendTransaction(signedTx)
if err != nil {
return "", err
}
// 查询交易
var tick int
for {
detail, err := pre.client.QueryTransaction(hash)
if err != nil {
tick++
if tick == 5 {
return "", err
}
time.Sleep(time.Second * 5)
continue
}
if detail.Receipt == nil || detail.Receipt.TyName != "ExecOk" {
return "", errors.New("Exec failed")
}
break
}
return res, nil
}
\ No newline at end of file
package server
import (
secp256k1 "github.com/btcsuite/btcd/btcec"
"github.com/syndtr/goleveldb/leveldb"
"gitlab.33.cn/pengjun/reencrypt/common"
"gitlab.33.cn/pengjun/reencrypt/sdk/crypto"
"gitlab.33.cn/pengjun/reencrypt/sdk/types"
"time"
)
type NodeService struct {
key string
db *leveldb.DB
}
func NewNodeService(db *leveldb.DB, key string) (*NodeService, error) {
//expire := &common.ExpireTime{
// Time: int64(math.MaxInt64),
//}
//err := db.Put(ExpireTimeKey, types.Encode(expire), nil)
//if err != nil {
// rlog.Error("NewNodeService.Put", "error", err)
// return nil, err
//}
return &NodeService{db:db, key:key}, nil
}
func getPubECDSA(pub string) (*secp256k1.PublicKey, error) {
pubByte, err := types.FromHex(pub)
if err != nil {
rlog.Error("FromHex", "error", err)
return nil, err
}
pubkey, err := secp256k1.ParsePubKey(pubByte[:], secp256k1.S256())
if err != nil {
rlog.Error("ParsePubKey", "error", err)
return nil, err
}
return pubkey, nil
}
func checkDhProof(key string, pub string, dh string) bool {
pubkey, err := getPubECDSA(pub)
if err != nil {
rlog.Error("get ecdsa pub key failed", "error", err)
return false
}
keybyte, err := types.FromHex(key)
if err != nil {
rlog.Error("get key byte from string failed", "error", err)
return false
}
proof := types.ECDH(crypto.PrivateECDSAFromByte(keybyte[:]), pubkey).String()
if proof != dh {
return false
}
return true
}
func generateDBKey(pubOwner string, pubRecipient string) []byte {
return crypto.Sha256([]byte("PRE-"+pubOwner+"-"+pubRecipient))
}
func (service *NodeService) CollectFragment(fragments *common.ReqSendKeyFragment, result *interface{}) error {
if !checkDhProof(service.key, fragments.PubOwner, fragments.DhProof) {
rlog.Error("CollectFragment. check data owmer public key failed")
*result = &common.RepSendKeyFragment{Result: false}
return common.ErrPublicKeyInvalid
}
dbKey := generateDBKey(fragments.PubOwner, fragments.PubRecipient)
dbVlaue := &common.KeyFragment{
PubProofR: fragments.PubProofR,
PubProofU: fragments.PubProofU,
Ramdom: fragments.Random,
Value: fragments.Value,
Expire: time.Now().Unix() + fragments.Expire * 3600,
PrecurPub: fragments.PrecurPub,
}
err := service.db.Put(dbKey, types.Encode(dbVlaue), nil)
if err != nil {
rlog.Error("CollectFragment. Put data to db failed", "error", err)
*result = &common.RepSendKeyFragment{Result: false}
return err
}
*result = &common.RepSendKeyFragment{Result: true}
return nil
}
func (service *NodeService) Reencrypt(req *common.ReqReeencryptParam, result *interface{}) error {
dbKey := generateDBKey(req.PubOwner, req.PubRecipient)
value, err := service.db.Get(dbKey, nil)
if err != nil {
rlog.Error("Reencrypt. get key fragment error", "error", err)
return err
}
var keyFragment common.KeyFragment
err = types.Decode(value, &keyFragment)
if err != nil {
rlog.Error("Reencrypt.decode", "error", err)
return err
}
pubkeyR, err := getPubECDSA(keyFragment.PubProofR)
if err != nil {
rlog.Error("Reencrypt.getECDSAPub", "key", keyFragment.PubProofR, "error", err)
return err
}
pubkeyU, err := getPubECDSA(keyFragment.PubProofU)
if err != nil {
rlog.Error("Reencrypt.getECDSAPub", "key", keyFragment.PubProofU, "error", err)
return err
}
rk := types.StringToBig(keyFragment.Value)
var reKeyR, reKeyU secp256k1.PublicKey
reKeyR.X, reKeyR.Y = secp256k1.S256().ScalarMult(pubkeyR.X, pubkeyR.Y, rk.Bytes())
reKeyU.X, reKeyU.Y = secp256k1.S256().ScalarMult(pubkeyU.X, pubkeyU.Y, rk.Bytes())
var rep common.RepReeencrypt
rep.ReKeyR = types.ToHex(reKeyR.SerializeCompressed())
rep.ReKeyU = types.ToHex(reKeyU.SerializeCompressed())
rep.Random = keyFragment.Ramdom
rep.PrecurPub = keyFragment.PrecurPub
*result = rep
return nil
}
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.13
package server
import (
"bytes"
"fmt"
"gitlab.33.cn/pengjun/reencrypt/sdk/client"
"gitlab.33.cn/pengjun/reencrypt/sdk/types"
log "github.com/inconshreveable/log15"
"github.com/rs/cors"
"github.com/syndtr/goleveldb/leveldb"
glError "github.com/syndtr/goleveldb/leveldb/errors"
"github.com/syndtr/goleveldb/leveldb/filter"
"github.com/syndtr/goleveldb/leveldb/opt"
"gitlab.33.cn/pengjun/reencrypt/common"
"io/ioutil"
"net"
"net/http"
"net/rpc"
"net/rpc/jsonrpc"
"path"
"strings"
"time"
)
var rlog = log.New("module", "router server")
type RpcServer struct {
service *NodeService
s *rpc.Server
l net.Listener
address string
pclient *PreClient
}
func NewRpcServer(cfg *common.Config) (*RpcServer, error) {
rpcServer := &RpcServer{}
url := cfg.BindAddr
_, port, err := net.SplitHostPort(url)
if err != nil {
rlog.Error("split url failed", "error", err)
return nil, err
}
jclient, err := client.NewJSONClient("Chain33", cfg.Nodeserver)
if err != nil {
rlog.Error("Create json client failed", "error", err)
return nil, err
}
pclient := NewPreClient(jclient, cfg.PreServerKey)
_, err = pclient.RegisterPreNode(cfg.ExternalAddr+":"+port, cfg.StakeAddr)
if err != nil {
rlog.Error("RegisterPreNode", "error", err)
return nil, err
}
rpcServer.pclient = pclient
db, err := newGoLevelDB("pre", cfg.DbPath, 16)
if err != nil {
rlog.Error("Create level db failed", "error", err)
return nil, err
}
service,err := NewNodeService(db, cfg.PreServerKey)
if err != nil {
rlog.Error(err.Error())
return nil, err
}
rpcServer.service = service
rpcServer.s = rpc.NewServer()
rpcServer.address = cfg.BindAddr
err = rpcServer.s.RegisterName("Pre", rpcServer.service)
if err != nil {
rlog.Error(err.Error())
return nil, err
}
go CheckExpireRoutine(db)
return rpcServer, nil
}
func newGoLevelDB(name string, dir string, cache int) (*leveldb.DB, error) {
dbPath := path.Join(dir, name+".db")
if cache == 0 {
cache = 64
}
handles := cache
if handles < 16 {
handles = 16
}
if cache < 4 {
cache = 4
}
// Open the db and recover any potential corruptions
db, err := leveldb.OpenFile(dbPath, &opt.Options{
OpenFilesCacheCapacity: handles,
BlockCacheCapacity: cache / 2 * opt.MiB,
WriteBuffer: cache / 4 * opt.MiB, // Two of these are used internally
Filter: filter.NewBloomFilter(10),
})
if _, corrupted := err.(*glError.ErrCorrupted); corrupted {
db, err = leveldb.RecoverFile(dbPath, nil)
}
if err != nil {
return nil, err
}
iter := db.NewIterator(nil, nil)
for iter.Next() {
var keyFragment common.KeyFragment
err := types.Decode(iter.Value(), &keyFragment)
if err != nil {
rlog.Error("CheckExpireRoutine.decode", "error", err)
continue
}
}
return db, nil
}
func (rr *RpcServer) Listen() {
var err error
for i := 0; i < 10; i++ {
_, err = rr.listen()
if err != nil {
time.Sleep(time.Second)
continue
}
break
}
//sleep for a while
time.Sleep(time.Millisecond)
}
func (rr *RpcServer) listen() (int, error) {
listener, err := net.Listen("tcp", rr.address)
if err != nil {
return 0, err
}
rr.l = listener
co := cors.New(cors.Options{})
var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rlog.Debug("RouterRPCServer", "RemoteAddr", r.RemoteAddr)
ip, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
writeError(w, r, 0, fmt.Sprintf(`The %s Address is not authorized!`, ip))
return
}
if r.URL.Path == "/" {
data, err := ioutil.ReadAll(r.Body)
if err != nil {
writeError(w, r, 0, "Can't get request body!")
return
}
serverCodec := jsonrpc.NewServerCodec(&HTTPConn{in: ioutil.NopCloser(bytes.NewReader(data)), out: w, r: r})
w.Header().Set("Content-type", "application/json")
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
w.Header().Set("Content-Encoding", "gzip")
}
w.WriteHeader(200)
err = rr.s.ServeRequest(serverCodec)
if err != nil {
rlog.Debug("Error while serving JSON request", "error", err)
return
}
}
})
handler = co.Handler(handler)
go http.Serve(listener, handler)
return listener.Addr().(*net.TCPAddr).Port, nil
}
// Close rpcserver close
func (rr *RpcServer) Close() {
if rr.l != nil {
err := rr.l.Close()
if err != nil {
rlog.Error("RouterRPCServer close", "err", err)
}
}
}
func CheckExpireRoutine(db *leveldb.DB) {
for {
var remove [][]byte
iter := db.NewIterator(nil, nil)
now := time.Now().Unix()
for iter.Next() {
var keyFragment common.KeyFragment
err := types.Decode(iter.Value(), &keyFragment)
if err != nil {
rlog.Error("CheckExpireRoutine.decode", "error", err)
continue
}
if keyFragment.Expire <= now {
remove = append(remove, iter.Key())
}
}
for _, key := range remove {
err := db.Delete(key, nil)
if err != nil {
rlog.Error("CheckExpireRoutine.Delete", "error", err)
continue
}
}
time.Sleep(time.Hour)
}
}
package server
import (
"github.com/stretchr/testify/assert"
"gitlab.33.cn/pengjun/reencrypt/common"
"gitlab.33.cn/pengjun/reencrypt/sdk"
"gitlab.33.cn/pengjun/reencrypt/sdk/crypto"
"gitlab.33.cn/pengjun/reencrypt/sdk/types"
"testing"
)
func TestReencrypt(t *testing.T) {
var msg = "hello proxy-re-encrypt"
alice, err := sdk.NewAccount("")
assert.Nil(t, err)
bob, err := sdk.NewAccount("")
assert.Nil(t, err)
enkey, pub_r, pub_u := sdk.GenerateEncryptKey(alice.PublicKey)
cipher, err := crypto.AESCBCPKCS7Encrypt(enkey[1:], []byte(msg))
assert.Nil(t, err)
keyFragments, err := sdk.GenerateKeyFragments(alice.PrivateKey, bob.PublicKey, 1, 1)
assert.Nil(t, err)
serviceAcc, err := sdk.NewAccount("")
assert.Nil(t, err)
db, err := newGoLevelDB("pre", "cfg.DbPath", 16)
assert.Nil(t, err)
service,err := NewNodeService(db, types.ToHex(serviceAcc.PrivateKey))
assert.Nil(t, err)
dhproof := types.ECDH(crypto.PrivateECDSAFromByte(alice.PrivateKey), crypto.PublicECDSAFromByte(serviceAcc.PublicKey))
param := &common.ReqSendKeyFragment{
PubOwner: types.ToHex(alice.PublicKey),
PubRecipient: types.ToHex(bob.PublicKey),
PubProofR: pub_r,
PubProofU: pub_u,
Random: keyFragments[0].Random,
Value: keyFragments[0].Value,
Expire: 1000000,
DhProof: dhproof.String(),
PrecurPub: keyFragments[0].PrecurPub,
}
var result interface{}
service.CollectFragment(param, &result)
assert.Equal(t, true, result.(*common.RepSendKeyFragment).Result)
param1 := &common.ReqReeencryptParam{
PubOwner: types.ToHex(alice.PublicKey),
PubRecipient: types.ToHex(bob.PublicKey),
}
var result1 interface{}
service.Reencrypt(param1, &result1)
var rekeys = make([]*sdk.ReKeyFrag, 1)
rekeys[0] = &sdk.ReKeyFrag{
ReKeyR: result1.(common.RepReeencrypt).ReKeyR,
ReKeyU: result1.(common.RepReeencrypt).ReKeyU,
Random: result1.(common.RepReeencrypt).Random,
PrecurPub: result1.(common.RepReeencrypt).PrecurPub,
}
aesKey, err := sdk.AssembleReencryptFragment(bob.PrivateKey, rekeys)
assert.Nil(t, err)
assert.Equal(t, aesKey, enkey)
msgDecrypt, err := crypto.AESCBCPKCS7Decrypt(aesKey[1:], cipher)
assert.Nil(t, err)
assert.Equal(t, msg, string(msgDecrypt))
}
package main
import (
"fmt"
"github.com/spf13/cobra"
"gitlab.33.cn/pengjun/reencrypt/common"
"gitlab.33.cn/pengjun/reencrypt/sdk"
client "gitlab.33.cn/pengjun/reencrypt/sdk/client"
"gitlab.33.cn/pengjun/reencrypt/sdk/crypto"
"gitlab.33.cn/pengjun/reencrypt/sdk/types"
"os"
)
func main() {
rootCmd := &cobra.Command{
Use: "proxy re-encrypt cli",
Short: "proxy re-enctypt client tools",
}
ownerCmd := &cobra.Command{
Use: "encrypt",
Short: "encrypt",
Run: ownerEncrypt,
}
addEncryptFlags(ownerCmd)
recipientCmd := &cobra.Command{
Use: "decrypt",
Short: "decrypt",
Run: recipientDecrypt,
}
addDecryptFlags(recipientCmd)
accountCmd := &cobra.Command{
Use: "account",
Short: "account",
Run: accountInfo,
}
addAccountInfoFlags(accountCmd)
rootCmd.AddCommand(
ownerCmd,
recipientCmd,
accountCmd,
)
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func addEncryptFlags(cmd *cobra.Command) {
cmd.Flags().StringP("msg", "m", "", "original message")
cmd.MarkFlagRequired("msg")
cmd.Flags().StringP("key", "k", "", "private key")
cmd.MarkFlagRequired("key")
cmd.Flags().StringP("pub", "p", "", "recipient public key")
cmd.MarkFlagRequired("pub")
cmd.Flags().StringP("server", "s", "", "pre server public key")
cmd.MarkFlagRequired("server")
}
func ownerEncrypt(cmd *cobra.Command, args []string) {
msg, _ := cmd.Flags().GetString("msg")
key, _ := cmd.Flags().GetString("key")
pub, _ := cmd.Flags().GetString("pub")
server, _ := cmd.Flags().GetString("server")
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
if rpcLaddr == "" {
rpcLaddr = "http://localhost:11801"
}
driver := crypto.NewSignDriver(crypto.SECP256k1)
keybyte, err := types.FromHex(key)
if err != nil {
panic(err)
}
pubOwner := driver.PubKeyFromPrivate(keybyte)
enKey, pub_r, pub_u := sdk.GenerateEncryptKey(pubOwner)
cipher, err := crypto.AESCBCPKCS7Encrypt(enKey[1:], []byte(msg))
if err != nil {
panic(err)
}
recipientPubu, err := types.FromHex(pub)
if err != nil {
panic(err)
}
keyFrags, err := sdk.GenerateKeyFragments(keybyte, recipientPubu, 1, 1)
if err != nil {
panic(err)
}
jclient, err := client.NewJSONClient("Pre", rpcLaddr)
if err != nil {
panic(err)
}
var result interface{}
serverPub, err := types.FromHex(server)
if err != nil {
panic(err)
}
dhproof := types.ECDH(crypto.PrivateECDSAFromByte(keybyte), crypto.PublicECDSAFromByte(serverPub))
param := &common.ReqSendKeyFragment{
PubOwner: types.ToHex(pubOwner),
PubRecipient: pub,
PubProofR: pub_r,
PubProofU: pub_u,
Random: keyFrags[0].Random,
Value: keyFrags[0].Value,
Expire: 1000000,
DhProof: dhproof.String(),
PrecurPub: keyFrags[0].PrecurPub,
}
jclient.Call("CollectFragment", param, &result)
fmt.Println("cipher text:", types.ToHex(cipher))
fmt.Println("result", result)
}
func addDecryptFlags(cmd *cobra.Command) {
cmd.Flags().StringP("msg", "m", "", "original message")
cmd.MarkFlagRequired("msg")
cmd.Flags().StringP("key", "k", "", "private key")
cmd.MarkFlagRequired("key")
cmd.Flags().StringP("pub", "p", "", "owner public key")
cmd.MarkFlagRequired("pub")
}
func recipientDecrypt(cmd *cobra.Command, args []string) {
msg, _ := cmd.Flags().GetString("msg")
key, _ := cmd.Flags().GetString("key")
pub, _ := cmd.Flags().GetString("pub")
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
if rpcLaddr == "" {
rpcLaddr = "http://localhost:11801"
}
msgByte, err := types.FromHex(msg)
if err != nil {
panic(err)
}
driver := crypto.NewSignDriver(crypto.SECP256k1)
keybyte, err := types.FromHex(key)
if err != nil {
panic(err)
}
pubRecipient := driver.PubKeyFromPrivate(keybyte)
param := &common.ReqReeencryptParam{
PubOwner: pub,
PubRecipient: types.ToHex(pubRecipient),
}
jclient, err := client.NewJSONClient("Pre", rpcLaddr)
if err != nil {
panic(err)
}
var result common.RepReeencrypt
jclient.Call("Reencrypt", param, &result)
var rekeys = make([]*sdk.ReKeyFrag, 1)
rekeys[0] = &sdk.ReKeyFrag{
ReKeyR: result.ReKeyR,
ReKeyU: result.ReKeyU,
Random: result.Random,
PrecurPub: result.PrecurPub,
}
encKey,err := sdk.AssembleReencryptFragment(keybyte, rekeys)
if err != nil {
panic(err)
}
msgDecrypt, err := crypto.AESCBCPKCS7Decrypt(encKey[1:], msgByte)
if err != nil {
panic(err)
}
fmt.Println(string(msgDecrypt))
}
func addAccountInfoFlags(cmd *cobra.Command) {
cmd.Flags().StringP("key", "k", "", "private key")
cmd.MarkFlagRequired("key")
}
func accountInfo(cmd *cobra.Command, args []string) {
key, _ := cmd.Flags().GetString("key")
driver := crypto.NewSignDriver(crypto.SECP256k1)
keybyte, err := types.FromHex(key)
if err != nil {
panic(err)
}
pubKey := driver.PubKeyFromPrivate(keybyte)
fmt.Println("public key:", types.ToHex(pubKey))
addr, err := crypto.PubKeyToAddress(pubKey)
if err != nil {
panic(err)
}
fmt.Println("address:", addr)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment