implement the api for use.computeOTAPPKeys

This commit is contained in:
fnaticwang 2019-09-24 14:37:46 +08:00
parent e79ed13760
commit e9c09e759b
8 changed files with 147 additions and 0 deletions

View file

@ -152,6 +152,9 @@ type Wallet interface {
// GetUseAddress represents the wallet to retrieve corresponding wanchain public address for a specific ordinary account/address
GetUseAddress(account Account) (common.UAddress, error)
// ComputeOTAPPKeys returns one-time-address pair
ComputeOTAPPKeys(account Account, AX, AY, BX, BY string) ([]string, error)
}
// Backend is a "wallet provider" that may contain a batch of accounts they can

View file

@ -208,6 +208,11 @@ func (api *ExternalSigner) GetUseAddress(account accounts.Account) (common.UAddr
return common.UAddress{}, nil
}
// TODO: TBI
func (api *ExternalSigner) ComputeOTAPPKeys(account accounts.Account, AX, AY, BX, BY string) ([]string, error) {
return nil, nil
}
func (api *ExternalSigner) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) {
return []byte{}, fmt.Errorf("password-operations not supported on external signers")
}

View file

@ -35,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/event"
@ -286,6 +287,25 @@ func (ks *KeyStore) SignTx(a accounts.Account, tx *types.Transaction, chainID *b
return types.SignTx(tx, types.HomesteadSigner{}, unlockedKey.PrivateKey)
}
func (ks *KeyStore) ComputeOTAPPKeys(a accounts.Account, AX, AY, BX, BY string) ([]string, error) {
ks.mu.RLock()
defer ks.mu.RUnlock()
unlockedKey, found := ks.unlocked[a.Address]
if !found {
return nil, ErrLocked
}
pub1, priv1, priv2, err := crypto.GenerteOTAPrivateKey(unlockedKey.PrivateKey, unlockedKey.PrivateKey2, AX, AY, BX, BY)
pub1X := hexutil.Encode(common.LeftPadBytes(pub1.X.Bytes(), 32))
pub1Y := hexutil.Encode(common.LeftPadBytes(pub1.Y.Bytes(), 32))
priv1D := hexutil.Encode(common.LeftPadBytes(priv1.D.Bytes(), 32))
priv2D := hexutil.Encode(common.LeftPadBytes(priv2.D.Bytes(), 32))
return []string{pub1X, pub1Y, priv1D, priv2D}, err
}
// SignHashWithPassphrase signs hash if the private key matching the given address
// can be decrypted with the given passphrase. The produced signature is in the
// [R || S || V] format where V is 0 or 1.

View file

@ -138,6 +138,19 @@ func (w *keystoreWallet) SignTx(account accounts.Account, tx *types.Transaction,
return w.keystore.SignTx(account, tx, chainID)
}
func (w *keystoreWallet) ComputeOTAPPKeys(account accounts.Account, AX, AY, BX, BY string) ([]string, error) {
// Make sure the requested account is contained within
if account.Address != w.account.Address {
return nil, accounts.ErrUnknownAccount
}
if account.URL != (accounts.URL{}) && account.URL != w.account.URL {
return nil, accounts.ErrUnknownAccount
}
// Account seems valid, request the keystore to process
return w.keystore.ComputeOTAPPKeys(account, AX, AY, BX, BY)
}
// SignTxWithPassphrase implements accounts.Wallet, attempting to sign the given
// transaction with the given account using passphrase as extra authentication.
func (w *keystoreWallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {

View file

@ -793,6 +793,11 @@ func (w *Wallet) GetUseAddress(account accounts.Account) (common.UAddress, error
return common.UAddress{}, nil
}
// TODO: TBI
func (w *Wallet) ComputeOTAPPKeys(account accounts.Account, AX, AY, BX, BY string) ([]string, error) {
return nil, nil
}
// Session represents a secured communication session with the wallet.
type Session struct {
Wallet *Wallet // A handle to the wallet that opened the session

View file

@ -598,3 +598,8 @@ func (w *wallet) SignTxWithPassphrase(account accounts.Account, passphrase strin
func (w *wallet) GetUseAddress(account accounts.Account) (common.UAddress, error) {
return common.UAddress{}, nil
}
// TODO: TBI
func (w *wallet) ComputeOTAPPKeys(account accounts.Account, AX, AY, BX, BY string) ([]string, error) {
return nil, nil
}

View file

@ -295,3 +295,48 @@ func GenerateOneTimeKey(AX string, AY string, BX string, BY string) (ret []strin
generatedA1, generatedR, err := generateOneTimeKey2528(pa, pb)
return hexutil.PKPair2HexSlice(generatedA1, generatedR), nil
}
// 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) {
bytesAX, err := hexutil.Decode(AX)
if err != nil {
return
}
bytesAY, err := hexutil.Decode(AY)
if err != nil {
return
}
bytesBX, err := hexutil.Decode(BX)
if err != nil {
return
}
bytesBY, err := hexutil.Decode(BY)
if err != nil {
return
}
bnAX := new(big.Int).SetBytes(bytesAX)
bnAY := new(big.Int).SetBytes(bytesAY)
bnBX := new(big.Int).SetBytes(bytesBX)
bnBY := new(big.Int).SetBytes(bytesBY)
retPub = &ecdsa.PublicKey{X: bnAX, Y: bnAY}
pb := &ecdsa.PublicKey{X: bnBX, Y: bnBY}
retPriv1, retPriv2, err = GenerateOneTimePrivateKey2528(privateKey, privateKey2, retPub, pb)
return
}
func GenerateOneTimePrivateKey2528(privateKey *ecdsa.PrivateKey, privateKey2 *ecdsa.PrivateKey, destPubA *ecdsa.PublicKey, destPubB *ecdsa.PublicKey) (retPriv1 *ecdsa.PrivateKey, retPriv2 *ecdsa.PrivateKey, err error) {
pub := new(ecdsa.PublicKey)
pub.X, pub.Y = S256().ScalarMult(destPubB.X, destPubB.Y, privateKey2.D.Bytes()) //[b]R
k := new(big.Int).SetBytes(Keccak256(FromECDSAPub(pub))) //hash([b]R)
k.Add(k, privateKey.D) //hash([b]R)+a
k.Mod(k, S256().Params().N) //mod to feild N
retPriv1 = new(ecdsa.PrivateKey)
retPriv2 = new(ecdsa.PrivateKey)
retPriv1.D = k
retPriv2.D = new(big.Int).SetInt64(0)
return retPriv1, retPriv2, nil
}

View file

@ -1531,6 +1531,57 @@ func (s *PublicTransactionPoolAPI) FillTransaction(ctx context.Context, args Sen
return &SignTransactionResult{data, tx}, nil
}
// ComputeOTAPPKeys compute ota private key, public key and short address
// from account address and ota full address.
func (s *PublicTransactionPoolAPI) ComputeOTAPPKeys(ctx context.Context, address common.Address, inOtaAddr string) (string, error) {
account := accounts.Account{Address: address}
wallet, err := s.b.AccountManager().Find(account)
if err != nil {
return "", err
}
uanBytes, err := hexutil.Decode(inOtaAddr)
if err != nil {
return "", err
}
otaBytes, err := keystore.UaddrToUncompressedRawBytes(uanBytes)
if err != nil {
return "", err
}
otaAddr := hexutil.Encode(otaBytes)
//AX string, AY string, BX string, BY string
otaAddr = strings.Replace(otaAddr, "0x", "", -1)
AX := "0x" + otaAddr[0:64]
AY := "0x" + otaAddr[64:128]
BX := "0x" + otaAddr[128:192]
BY := "0x" + otaAddr[192:256]
sS, err := wallet.ComputeOTAPPKeys(account, AX, AY, BX, BY)
if err != nil {
return "", err
}
otaPub := sS[0] + sS[1][2:]
otaPriv := sS[2]
privateKey, err := crypto.HexToECDSA(otaPriv[2:])
if err != nil {
return "", err
}
var addr common.Address
pubkey := crypto.FromECDSAPub(&privateKey.PublicKey)
//caculate the address for replaced pub
copy(addr[:], crypto.Keccak256(pubkey[1:])[12:])
return otaPriv + "+" + otaPub + "+" + hexutil.Encode(addr[:]), nil
}
// SendRawTransaction will add the signed transaction to the transaction pool.
// The sender is responsible for signing the transaction and using the correct nonce.
func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) {