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

Decoupled Authorization and Authentication For Additional Lightning Services #70

Open
ZmnSCPxj-jr opened this issue Nov 23, 2023 · 6 comments

Comments

@ZmnSCPxj-jr
Copy link
Contributor

If we want LSPS to mean "Lightning SERVICE Provider Specification" rather than "LIQUIDITY Service Provider Specification" at some point, then an LSP would want to offer additional services, such as (but not limited to):

  • Lightning channel state backup
  • Watchtower
  • SPV-server for blockchain access
  • Rapid Gossip Sync

Such services obviously have some cost to operate.

An LSP might want to provide access to such additional services to clients that it has (e.g. already has open channels, or is promised a channel open via LSPS1 / LSPS2).

The naive way to implement this is to simply have some kind of "log in" where the client shows its client node ID. The server for the service then looks up the client via its node ID on the actual LSP node. This has the drawback that each use of the service is associated with a specific client node ID. This is dangerous information, as hackers may be able to specifically target vital money-guarding services (such as access to the blockchain or the Lightning channel state) of a specific client.

A better idea is to somehow decouple authorization ("LSP has this client, and allows client to use this additional service") from authentication ("this entity is a client (not know which) so let them use this additional service").

An initial idea would be to use something similar to PrivacyPass / Cashu, which is blinded diffie-helman key exchange (BDHKE). However, @nothingmuch proposes that a unified solution would be to instead base on homomorphic commitments (credential). The issue is that a BDHKE is basically just a value of "1". There may be cases where certain operations of a service are more expensive than others, and an LSP might want to be more restrictive of those expensive operations (e.g.: writing an encrypted blob is much more expensive than reading an already-stored blob). A credential would attach a value as well, not just a "1".

Credentials may also enable the implementation of #31 "Custodial Popcorn". A client could be paid tiny amounts that cannot pay for a JIT channel, with the LSP providing credentials for each payment. The client can then later sum them up and when the amount is big enough, can make a request to the LSP for a free channel open that is paid for by the already-summed-up amount. Alternatively the Custodial Popcorn can be extended so that the LSP gets little information about multiple payments to a client, then periodically the client drops down to non-custodial use of its channel, effectively informing the LSP only of the sum of its payments, not each individual payment and its timing.

@SeverinAlexB
Copy link
Collaborator

LSPSpec meeting 23rd of November 2023:
The group decided that LSPS6 (#68) is an interesting proposal that needs investigation. It is too early though and we are busy actually getting the LSPSpec out to people. We should revisit in the future. Maybe in 1 year?

This new issue should work as a discussion forum in the meantime.

@ZmnSCPxj-jr
Copy link
Contributor Author

ZmnSCPxj-jr commented Nov 23, 2023

Additional details on the crypto bits:

  • The LSP needs to rotate service keys periodically. This is because a "spent" token or credential needs to be recorded, leading to unbound state, so the LSP needs to be able to delete all old state by sunsetting an old service key. This also prevents a patient attacker that just collects credentials/tokens over a long time and then suddenly floods the service in a DoS.
  • Nevertheless, the LSP should still "credit" slightly-old tokens/credentials, possibly by reissuing a smaller amount using the latest service key.
  • For maximal privacy, on "claiming" a service the LSP must accept only the latest epoch / key-rotation, and "upgrade" from an older epoch / rotation is a separate operation that has to be done first.
  • For tokens that are used to symbolize boolean "access allowed" instead of "how many requests you can make", rather than upgrading, just always let a client to have at most one token for the latest epoch.

@ZmnSCPxj-jr
Copy link
Contributor Author

This is a nice summary of various stuff c/o @nothingmuch : civkit/staking-credentials-spec#3 (comment)

The initial #68 was based on PrivacyPass / Cashu (the substantive cryptographic difference from Cashu is the use of HMAC(s * T, m) during claim-time instead of just s * T; this difference comes from PrivacyPass). It is somewhat appropriate for one-time access to services, or to "make an account" that is pseudonymous relative to the client node ID. However, the use of a consistent account means that the LSP-server providing the service is able to track a consistent account that it might correlate with behavior from a specific client node ID.

@nothingmuch strongly suggests the use of homomorphic credentials. The substantive difference between this and Cashu-style tokens is that a Cashu-style token has N tokens to represent an amount N, whereas homomorphic credentials can contain the number N in a single token. This has implications for storage: a Cashu-style token requires 65 bytes (32 t, 33 s * T), but if I have N units I need N * 65-byte tokens. The homomorphic credentials take far more bytes for a single token (512 for an old form, have to go see for newer forms), but a token can contain N units for N < 2^bits where bits determines how large your rangeproofs are (I think? AIUI you are doing Sigma proofs of p * (1 - p) == 0 to prove that a bit is either 0 or 1).

@nothingmuch suggests the homomorphic credentials used in WabiSabi, which are basically a slightly-modified form of the Signal credentials.

Homomorphic credentials require a way to move value between two tokens as well. This is an important privacy operation, as the existence of such an operation makes it harder for the LSP to track the use of tokens.

Homomorphic credentials do look like you have to push more bytes on the network, at least for the case where a token is just a flag "yes, let them use it" instead of "let them use it for some time/number of ops/whatever constraint"; blinded DH keys are more efficient for the flag usage. Homomorphic credentials are much more powerful and let variables to be used.

@nothingmuch
Copy link

a Cashu-style token has N tokens to represent an amount N,

not exactly, multiple token pools are used, so log(N) tokens to represent an amount N.

whereas homomorphic credentials can contain the number N in a single token. This has implications for storage: a Cashu-style token requires 65 bytes (32 t, 33 s * T), but if I have N units I need N * 65-byte tokens. The homomorphic credentials take far more bytes for a single token (512 for an old form, have to go see for newer forms), but a token can contain N units for N < 2^bits where bits determines how large your rangeproofs are (I think? AIUI you are doing Sigma proofs of p * (1 - p) == 0 to prove that a bit is either 0 or 1).

The range proofs don't have to be stored, they are computed when requesting tokens and can be discarded after. Compressed sigma protocols (e.g. bulletproofs) can be used to make the range proofs O(1) sized.

For WabiSabi this was not done since there is no long term storage and the cryptographic code was much simpler (no inner product or ring signature/simulation type usage, just a generalization of Schnorr identification protocol)

@nothingmuch suggests the homomorphic credentials used in WabiSabi, which are basically a slightly-modified form of the Signal credentials.

More precisely, WabiSabi applies (a subset of) the Signal credential construction, instantiating it with a single group attribute which is a homomorphic value commitment, pretty much the same as in Confidential Transactions (just without the transaction part, only the homomorphic value commitments)

Homomorphic credentials do look like you have to push more bytes on the network, at least for the case where a token is just a flag "yes, let them use it" instead of "let them use it for some time/number of ops/whatever constraint"; blinded DH keys are more efficient for the flag usage. Homomorphic credentials are much more powerful and let variables to be used.

Asymptotically they cost the the same or KVAC credentials are less costly: log(N) tokens each with O(1) size vs. a single token with O(log(N)) size or, with compression, a single token with O(1) size (but still O(log(N)) prover & verifier time). Concretely, there's a constant factor of about 3 on those asymptotics IIRC?

Perhaps a useful intuition pump to compare the naive, bit decomposition / blind signature, and homomorphic value commitment approach:

  • with a single denomination and only unit valued tokens, you have perfect privacy but awful performance: time & communication complexity scales linearly in the amount.
  • splitting these into multiple denominations, e.g. powers of two reduces those bounds to logarithmic, but arguably defeats the unlinkability of blind signatures creating a tension between payment UX and privacy
  • with homomorphic values, this bit decomposition is still done, just in zero knowledge, and batched, thus eliminating the need to manage multiples of each bit value, working with batches, etc - unlinkability is cryptographically ensured at the level of a batch of "bits" instead of for a given bit

this is not very precise but the intuition of moving the overt bit decomposition into a zero knowledge proof is useful for understanding the properties of these credentials, and why it's better to think of one as a kind of private account balance that can get updated (by replacement), as opposed to a pool of tokens that can be redeemed individually

@ZmnSCPxj-jr
Copy link
Contributor Author

Thank you @nothingmuch ! I confess I am at the edge of my ability here.

instantiating it with a single group attribute which is a homomorphic value commitment, pretty much the same as in Confidential Transactions (just without the transaction part, only the homomorphic value commitments)

For WabiSabi so basically the Signal KVAC commits to a Pedersen commitment v * G + r * H where v is the committed value/amount and r is the salt, with the Pedersen commitment being a single point? The issuer then has to learn the Pedersen commitment, but the Pedersen commitment itself hides the actual value. Is that correct or...?

Looks like I need moar reading into WabiSabi and Signal!

@nothingmuch
Copy link

nothingmuch commented Nov 28, 2023

The issuer then has to learn the Pedersen commitment, but the Pedersen commitment itself hides the actual value. Is that correct or...

Yep that's right, then during credential presentation the client proves it has MAC on the commitment, but presents a further randomized version v * G + r * H + r' * H', and proves application specific things about the committed value (e.g. the balance proof)

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

No branches or pull requests

3 participants