Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Secret encrypted on metadata #344

Closed
andrevmatos opened this issue Jul 12, 2021 · 0 comments · Fixed by raiden-network/raiden#7296
Closed

Secret encrypted on metadata #344

andrevmatos opened this issue Jul 12, 2021 · 0 comments · Fixed by raiden-network/raiden#7296
Assignees

Comments

@andrevmatos
Copy link
Contributor

Abstract

Spec for raiden-network/raiden#7071
When making a transfer, after validations pass, we need to reveal the secret only to target. Usually (fallback case), this is done by target sending a message to initiator requesting the secret, initiator doing the validation on its side and then revealing the secret to target directly, which then is able to proceed with unlocking. There's a way to do that without requiring this slower messaging exchange, by using ECIES to encrypt the secret and the information needed for its validation with target's public key. The downside is that this puts the responsibility of validating these information on the target, and the initiator doesn't have the ability to cancel this transfer by forgetting the secret before revealing anymore. But we never implemented features which would require this anyway, and the optimisation is more important ATM.

Spec

  • This is only possible if all nodes in path support immutableMetadata capability #343 ; we should at least check partner and target for that capability.
  • In case it's possible, when creating a transfer, initiator can encrypt the secret to target:
    • It should fetch target's pubkey from its address_metadata (public key is recoverable from the displayname being the signature of the user_id).
    • With it, it uses ECIES (ecies/js, ecies/py) to encrypt an object containing secret and the metadata needed for validation
    • this object must be in the format: { "secret": HexString, "amount": NumericString, "payment_identifier": NumericString }
    • in pseudo-code: LockedTransfer.metadata.secret = hex(encrypt(target.pubkey, json.dumps({ secret, amount, payment_identifier })))
  • When receiving a transfer, target may check metadata.secret is present and try to decrypt and validate it:
    • metadata.secret should be an hex string, to be decrypted with its PrivateKey
      • The resulting string must be parseable as a JSON object in the above format
      • in pseudo-code: obj = json.loads(decrypt(privateKey, transfer.metadata.secret))
    • obj.secret must hash to the transfer's secrethash
    • obj.amount must be less than or equal received amount
    • obj.payment_identifier must be equal to transfer's payment_identifier
    • If the above validations pass, we use secret as this transfer's secret and skip requesting it to initiator and start the SecretReveal/unlock phase; otherwise, we proceed with the previous/fallback behavior
  • Target may skip creating an RTC channel with initiator if secret is present in the transfer.

Conclusion

This change depends on immutableMetadata capability, but it'll gracefully fall back to behavior compatible with 2.0/Bespin in case it isn't possible, so it's fully backwards compatible.

This is an optimisation to avoid target needing to message initiator, which usually doesn't have an RTC channel established, and would allow RTC channels to be established only between partners, reducing the attack surface and speeding the transfer times since first transfer to a new target.

This also fixes raiden-network/raiden#473

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants