implement the api for use.genRingSignData

This commit is contained in:
fnaticwang 2019-09-25 15:49:13 +08:00
parent 5831801a22
commit a8cd67ecd0
4 changed files with 222 additions and 5 deletions

View file

@ -51,7 +51,7 @@ type Key struct {
PrivateKey *ecdsa.PrivateKey PrivateKey *ecdsa.PrivateKey
// add a second privkey for privary // add a second privkey for privary
PrivateKey2 *ecdsa.PrivateKey PrivateKey2 *ecdsa.PrivateKey
// compact wanchain address format // compact usechain address format
UAddress common.UAddress UAddress common.UAddress
} }

View file

@ -893,8 +893,7 @@ func (c *useCoinSC) ValidRefundReq(stateDB StateDB, payload []byte, from []byte)
func (c *useCoinSC) refund(all []byte, contract *Contract, evm *EVM) ([]byte, error) { func (c *useCoinSC) refund(all []byte, contract *Contract, evm *EVM) ([]byte, error) {
kix, value, err := c.ValidRefundReq(evm.StateDB, all, contract.CallerAddress.Bytes()) kix, value, err := c.ValidRefundReq(evm.StateDB, all, contract.CallerAddress.Bytes())
if err != nil { if err != nil {
fmt.Println("failed refund") fmt.Println("failed refund ", err)
fmt.Println(evm.BlockNumber)
return nil, err return nil, err
} }
@ -913,6 +912,7 @@ func (c *useCoinSC) refund(all []byte, contract *Contract, evm *EVM) ([]byte, er
func (c *useCoinSC) buyCoin(in []byte, contract *Contract, evm *EVM) ([]byte, error) { func (c *useCoinSC) buyCoin(in []byte, contract *Contract, evm *EVM) ([]byte, error) {
otaAddr, err := c.ValidBuyCoinReq(evm.StateDB, in, contract.value) otaAddr, err := c.ValidBuyCoinReq(evm.StateDB, in, contract.value)
if err != nil { if err != nil {
fmt.Println("failed buyCoin ", err)
return nil, err return nil, err
} }

View file

@ -245,6 +245,24 @@ func zeroBytes(bytes []byte) {
} }
} }
var one = new(big.Int).SetInt64(1)
// randFieldElement2528 returns a random element of the field
func randFieldElement2528(rand io.Reader) (k *big.Int, err error) {
params := S256().Params()
b := make([]byte, params.BitSize/8+8)
_, err = io.ReadFull(rand, b)
if err != nil {
return
}
k = new(big.Int).SetBytes(b)
n := new(big.Int).Sub(params.N, one)
k.Mod(k, n)
k.Add(k, one)
return
}
// calc [x]Hash(P) // calc [x]Hash(P)
func xScalarHashP(x []byte, pub *ecdsa.PublicKey) (I *ecdsa.PublicKey) { func xScalarHashP(x []byte, pub *ecdsa.PublicKey) (I *ecdsa.PublicKey) {
KeyImg := new(ecdsa.PublicKey) KeyImg := new(ecdsa.PublicKey)
@ -255,8 +273,116 @@ func xScalarHashP(x []byte, pub *ecdsa.PublicKey) (I *ecdsa.PublicKey) {
return return
} }
var (
ErrInvalidRingSignParams = errors.New("invalid ring sign params")
ErrRingSignFail = errors.New("ring sign fail")
)
// RingSign is the function of ring signature
func RingSign(M []byte, x *big.Int, PublicKeys []*ecdsa.PublicKey) ([]*ecdsa.PublicKey, *ecdsa.PublicKey, []*big.Int, []*big.Int, error) {
if M == nil || x == nil || len(PublicKeys) == 0 {
return nil, nil, nil, nil, ErrInvalidRingSignParams
}
for _, publicKey := range PublicKeys {
if publicKey == nil || publicKey.X == nil || publicKey.Y == nil {
return nil, nil, nil, nil, ErrInvalidRingSignParams
}
}
n := len(PublicKeys)
I := xScalarHashP(x.Bytes(), PublicKeys[0]) //Key Image
if I == nil || I.X == nil || I.Y == nil {
return nil, nil, nil, nil, ErrRingSignFail
}
rnd, rnderr := rand.Int(rand.Reader, big.NewInt(int64(n)))
if rnderr != nil {
return nil, nil, nil, nil, ErrRingSignFail
}
s := int(rnd.Int64()) //s is the random position for real key
if s > 0 {
PublicKeys[0], PublicKeys[s] = PublicKeys[s], PublicKeys[0] //exchange position
}
var (
q = make([]*big.Int, n)
w = make([]*big.Int, n)
)
SumC := new(big.Int).SetInt64(0)
Lpub := new(ecdsa.PublicKey)
d := sha3.NewLegacyKeccak256()
d.Write(M)
var err error
for i := 0; i < n; i++ {
q[i], err = randFieldElement2528(rand.Reader)
if err != nil {
return nil, nil, nil, nil, err
}
w[i], err = randFieldElement2528(rand.Reader)
if err != nil {
return nil, nil, nil, nil, err
}
Lpub.X, Lpub.Y = S256().ScalarBaseMult(q[i].Bytes()) //[qi]G
if Lpub.X == nil || Lpub.Y == nil {
return nil, nil, nil, nil, ErrRingSignFail
}
if i != s {
Ppub := new(ecdsa.PublicKey)
Ppub.X, Ppub.Y = S256().ScalarMult(PublicKeys[i].X, PublicKeys[i].Y, w[i].Bytes()) //[wi]Pi
if Ppub.X == nil || Ppub.Y == nil {
return nil, nil, nil, nil, ErrRingSignFail
}
Lpub.X, Lpub.Y = S256().Add(Lpub.X, Lpub.Y, Ppub.X, Ppub.Y) //[qi]G+[wi]Pi
SumC.Add(SumC, w[i])
SumC.Mod(SumC, secp256k1_N)
}
d.Write(FromECDSAPub(Lpub))
}
Rpub := new(ecdsa.PublicKey)
for i := 0; i < n; i++ {
Rpub = xScalarHashP(q[i].Bytes(), PublicKeys[i]) //[qi]HashPi
if Rpub == nil || Rpub.X == nil || Rpub.Y == nil {
return nil, nil, nil, nil, ErrRingSignFail
}
if i != s {
Ppub := new(ecdsa.PublicKey)
Ppub.X, Ppub.Y = S256().ScalarMult(I.X, I.Y, w[i].Bytes()) //[wi]I
if Ppub.X == nil || Ppub.Y == nil {
return nil, nil, nil, nil, ErrRingSignFail
}
Rpub.X, Rpub.Y = S256().Add(Rpub.X, Rpub.Y, Ppub.X, Ppub.Y) //[qi]HashPi+[wi]I
}
d.Write(FromECDSAPub(Rpub))
}
Cs := new(big.Int).SetBytes(d.Sum(nil)) //hash(m,Li,Ri)
Cs.Sub(Cs, SumC)
Cs.Mod(Cs, secp256k1_N)
tmp := new(big.Int).Mul(Cs, x)
Rs := new(big.Int).Sub(q[s], tmp)
Rs.Mod(Rs, secp256k1_N)
w[s] = Cs
q[s] = Rs
return PublicKeys, I, w, q, nil
}
// VerifyRingSign verifies the validity of ring signature // VerifyRingSign verifies the validity of ring signature
// Pengbo added, Shi,TeemoGuo revised
func VerifyRingSign(M []byte, PublicKeys []*ecdsa.PublicKey, I *ecdsa.PublicKey, c []*big.Int, r []*big.Int) bool { func VerifyRingSign(M []byte, PublicKeys []*ecdsa.PublicKey, I *ecdsa.PublicKey, c []*big.Int, r []*big.Int) bool {
if M == nil || PublicKeys == nil || I == nil || c == nil || r == nil { if M == nil || PublicKeys == nil || I == nil || c == nil || r == nil {
return false return false
@ -404,7 +530,6 @@ func GenerateOneTimeKey(AX string, AY string, BX string, BY string) (ret []strin
} }
// GenerteOTAPrivateKey generates the privatekey for an OTA account using receiver's main account's privatekey // GenerteOTAPrivateKey generates the privatekey for an OTA account using receiver's main account's privatekey
// Pengbo added, TeemoGuo revised
func GenerteOTAPrivateKey(privateKey *ecdsa.PrivateKey, privateKey2 *ecdsa.PrivateKey, AX string, AY string, BX string, BY string) (retPub *ecdsa.PublicKey, retPriv1 *ecdsa.PrivateKey, retPriv2 *ecdsa.PrivateKey, err error) { func GenerteOTAPrivateKey(privateKey *ecdsa.PrivateKey, privateKey2 *ecdsa.PrivateKey, AX string, AY string, BX string, BY string) (retPub *ecdsa.PublicKey, retPriv1 *ecdsa.PrivateKey, retPriv2 *ecdsa.PrivateKey, err error) {
bytesAX, err := hexutil.Decode(AX) bytesAX, err := hexutil.Decode(AX)
if err != nil { if err != nil {

View file

@ -19,6 +19,7 @@ package ethapi
import ( import (
"bytes" "bytes"
"context" "context"
"crypto/ecdsa"
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
@ -1531,6 +1532,97 @@ func (s *PublicTransactionPoolAPI) FillTransaction(ctx context.Context, args Sen
return &SignTransactionResult{data, tx}, nil return &SignTransactionResult{data, tx}, nil
} }
// GenRingSignData generate ring sign data
func (s *PublicTransactionPoolAPI) GenRingSignData(ctx context.Context, hashMsg string, privateKey string, mixUseAdresses string) (string, error) {
if !hexutil.Has0xPrefix(privateKey) {
return "", ErrInvalidPrivateKey
}
hmsg, err := hexutil.Decode(hashMsg)
if err != nil {
return "", err
}
ecdsaPrivateKey, err := crypto.HexToECDSA(privateKey[2:])
if err != nil {
return "", err
}
privKey, err := hexutil.Decode(privateKey)
if err != nil {
return "", err
}
if privKey == nil {
return "", ErrInvalidPrivateKey
}
useAddresses := strings.Split(mixUseAdresses, "+")
if len(useAddresses) == 0 {
return "", ErrInvalidOTAMixSet
}
return genRingSignData(hmsg, privKey, &ecdsaPrivateKey.PublicKey, useAddresses)
}
func genRingSignData(hashMsg []byte, privateKey []byte, actualPub *ecdsa.PublicKey, mixUseAdress []string) (string, error) {
otaPrivD := new(big.Int).SetBytes(privateKey)
publicKeys := make([]*ecdsa.PublicKey, 0)
publicKeys = append(publicKeys, actualPub)
for _, strUseAddr := range mixUseAdress {
pubBytes, err := hexutil.Decode(strUseAddr)
if err != nil {
return "", errors.New("fail to decode use address!")
}
if len(pubBytes) != common.UAddressLength {
return "", ErrInvalidUAddress
}
publicKeyA, _, err := keystore.GeneratePKPairFromUAddress(pubBytes)
if err != nil {
return "", errors.New("Fail to generate public key from use address!")
}
publicKeys = append(publicKeys, publicKeyA)
}
retPublicKeys, keyImage, w_random, q_random, err := crypto.RingSign(hashMsg, otaPrivD, publicKeys)
if err != nil {
return "", err
}
return encodeRingSignOut(retPublicKeys, keyImage, w_random, q_random)
}
// encode all ring sign out data to a string
func encodeRingSignOut(publicKeys []*ecdsa.PublicKey, keyimage *ecdsa.PublicKey, Ws []*big.Int, Qs []*big.Int) (string, error) {
tmp := make([]string, 0)
for _, pk := range publicKeys {
tmp = append(tmp, common.ToHex(crypto.FromECDSAPub(pk)))
}
pkStr := strings.Join(tmp, "&")
k := common.ToHex(crypto.FromECDSAPub(keyimage))
wa := make([]string, 0)
for _, wi := range Ws {
wa = append(wa, hexutil.EncodeBig(wi))
}
wStr := strings.Join(wa, "&")
qa := make([]string, 0)
for _, qi := range Qs {
qa = append(qa, hexutil.EncodeBig(qi))
}
qStr := strings.Join(qa, "&")
outs := strings.Join([]string{pkStr, k, wStr, qStr}, "+")
return outs, nil
}
func (s *PublicTransactionPoolAPI) GetOTAMixSet(ctx context.Context, otaAddr string, setLen int) ([]string, error) { func (s *PublicTransactionPoolAPI) GetOTAMixSet(ctx context.Context, otaAddr string, setLen int) ([]string, error) {
if setLen <= 0 { if setLen <= 0 {
return []string{}, ErrInvalidOTAMixNum return []string{}, ErrInvalidOTAMixNum