3

For doing a payment from a distribution account i'd like to use the destination account as a channel. Therefore i'd like to implement the functionality as follows:

  • there are 3 accounts involved:

    • distribution (weigth's 0,2,0)
    • tmpDistribution (weigth's 0,0,0)
    • user (weigth's 0,0,0)
    • distribution account has 2 signers (self(weight 1) and tmpDistribution (weight1)
  • server creates a transaction with the payment (source for seqnr is the users-account)

  • server signs the transaction with an tmpDistribution
  • server sends transaction-xdr to client
  • client signs transaction with user-seed
  • client sends back signed xdr
  • server uses the keypair.Verify function (https://godoc.org/github.com/stellar/go/keypair#Full.Verify) to check, that the user did not change the transactions.
  • server signs with distribution-seed (if check was ok)
  • server runs transaction

My first question is, if this is a secure way to check, that the transaction was not modified? Let's say the user adds some more operations to the transaction, keypair.Verify should return an error right?

Second question is on how to use the keypair.Verify? I tried prety much, but i don't get the validation done (signature verification failed). Here is some test go-code, that i thought should work:

kp, err := keypair.Parse(distSeed)
if err != nil {
    panic(errors.New("SigningKey is invalid"))
}

tx, err := b.Transaction(
    b.SourceAccount{AddressOrSeed: distAdd},
    b.AutoSequence{SequenceProvider: horizon.DefaultTestNetClient},
    b.TestNetwork,
    b.Payment(
        b.SourceAccount{AddressOrSeed: distAdd},
        b.Destination{AddressOrSeed: userAdd},
        b.CreditAmount{Code: "xxx", Issuer: issAdd, Amount: "10"},
    ),
)
if err != nil {
    panic(err)
}

txs, err := tx.Sign(distSeed)
if err != nil {
    panic(err)
}

tmpB64, err := xdr.MarshalBase64(tx.TX)
if err != nil {
    panic(err)
}

err = kp.Verify([]byte(tmpB64), txs.E.Signatures[0].Signature)
if err != nil {
    panic(err) // panics here with signature verification failed
}
1

try to validate the transaction hash

tx_hash_32, err := tx.Hash()
if err != nil {
    panic(err)
}
tx_hash := tx_hash_32[:]

err = destinationPair.Verify(tx_hash, txs.E.Signatures[0].Signature)
if err != nil {
    panic(err) // panics here with signature verification failed
}

fmt.Printf("success\n")
2

The easiest way is to compare the transaction hashes - if they are the same then it was not modified. Signatures are used to prove that a given user signed a transaction (and actually what is being signed is the transaction hash). You could do what you’re suggesting about using verify, but it’s a roundabout way of doing it.

Regarding your code - it doesn’t look like you’re modifying the transaction post-signing and before verifying it, so I would expect verify to work. I haven’t used the Go SDK but I’d make sure you’re passing the appropriate arguments to it.

  • Thanks Paul, Using the transaction hash would work of course. But I like to get the Verify running, because I‘d like to use the same function for doing authentication (later). Also this code is just a test. Therefore I did not modify the transaction but even this does not work. So I guess I have some error in here, but can‘t figure out where. – Udo Polder Sep 5 '18 at 11:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.