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

DKG Authorization Models #3050

Open
jMyles opened this issue Jan 23, 2023 · 21 comments · Fixed by #3213
Open

DKG Authorization Models #3050

jMyles opened this issue Jan 23, 2023 · 21 comments · Fixed by #3213
Assignees

Comments

@jMyles
Copy link
Contributor

jMyles commented Jan 23, 2023

As we determine whether Alice pays on a usage model, a subscription model, or both - ie:

#3057

...we also need to define how Enrico has standing to adhere conditions to a ciphertext of his making.

We don't want: a single Alice to make an "open" Strategy (meaning, without defined parameters for condition adherence), and for any Enrico to then be able to make ciphertexts with conditions of his choosing - because then, the whole world will simply use that Strategy-Cohort.

So, two types of relationship emerge:

  • Alice authors condition parameters and makes them broadly available. For example, Alice can author seven different conditions, hash them individually, and place them on-chain (perhaps using proto-danksharding or something).

  • Alice specifically authorizes, via an access token, label-derivation scheme, allowlist, or some other mechanism, particular Enrico configurations which have standing to author and adhere conditions under the auspices of her funding.

@arjunhassard
Copy link
Member

arjunhassard commented Apr 14, 2023

This seems like a subset of a bigger issue: #3080

I also think we can assume condition freeloading is a much more niche issue than DKG initialization ritual freeloading (i.e. with your own unique conditions but some other adopter's cohort).

@KPrasch
Copy link
Member

KPrasch commented Apr 24, 2023

Some thoughts on this...

DKG

Permissionless

Anyone can initialize a ritual and network nodes must comply. This may lead to #3102

Permissioned

We can build a simple payment-checking mechanism on Ursula by using the ritual ID/initiator address to check for payment or other authorization logic. A simple example: the initiator pays nodes directly or has paid for services via contract.

Threshold Decryption

Permissionless

It does not matter who uses the service to encrypt or decrypt as long as nodes are paid for the ritual by someone somehow.

Permissioned

Think "API Keys". Only authorized Enricos can encrypt. It is possible to authorize only particular enricos to encrypt by taking advantage of ferveo's AAD as a signed token and publishing authorized keys onchain for node evaluation.

  • Alice summons a ritual
  • Ursulas finalize the ritual
  • Alice publishes Enrico's public key onchain for this ritual
  • Enrico signs cipertexts before sending to Bob
  • Bob passes along the signed cipertext to Ursula in a tdec request
  • Ursula verifies the cipertext and recovers Enrico's public key
  • Ursula checks if Enrico's public is authorized for this ritual onchain
attack surface
  • If Bob sends a request to Ursula that is not signed by an authorized key the node refuses service (honesty assumption)
  • Bob cannot tamper with the request without invalidating his own access
drawbacks
  • doxxes Enricos
  • authorization is not cryptographically enforced until decryption-time

@cygnusv
Copy link
Member

cygnusv commented May 10, 2023

Approach 1. Signed tokens

  1. Initiator associates a public key to the ritual
  2. Initiator issues signed messages ("tokens") using their private key. This could be compliant to standards like e.g., JWT tokens. Each token serves as a sort of API Key that authorizes a particular Enrico (identified by hisPK) to create encrypted content that's acceptable by the cohort.
  3. Enrico attaches the signed token to the ciphertext, and signs everything with his PK
  4. Bob makes decryption request, which includes the token
  5. Node validates token message (which also ensure that the token was signed with the initiator PK) and Enrico's signature.

An alternative design doesn't designate an Enrico PK when producing the signed token, which on the one hand makes Enrico's life easier (doesn't need a keypair, doesn't need to sign the ciphertext), but on the other hand, makes possible for Bob to reuse the signed token.

Approach 2. Smart contract

I describe here a generic approach that generalizes @KPrasch's message above, but that could be used in different ways:

  1. Initiator associates a smart contract to the ritual, conforming to some interface, e.g.,:
function isEnricoAuthorized(uint256 ritualID, bytes evidence, bytes ciphertextHash) public view returns(bool);
  1. The way how initiator grants access on this smart contract is out of scope. For illustration, let's assume the initiator just adds Enrico's PK to a list in the smart contract
  2. Enrico attaches evidence to the ciphertext. In our example, Enrico's evidence is signature(ciphertext_hash).
  3. Bob makes decryption request, which includes the evidence.
  4. Node calls the function in the smart contract to check whether Enrico is authorized. In our example, the smart contract would take the signature as evidence, extract the public key from the signature, and check whether the public key is in the list.

@cygnusv
Copy link
Member

cygnusv commented May 10, 2023

So, two types of relationship emerge:

  • Alice authors condition parameters and makes them broadly available. For example, Alice can author seven different conditions, hash them individually, and place them on-chain (perhaps using proto-danksharding or something).
  • Alice specifically authorizes, via an access token, label-derivation scheme, allowlist, or some other mechanism, particular Enrico configurations which have standing to author and adhere conditions under the auspices of her funding.

After re-reading @jMyles's original post, and considering also #3080, I think this problem has two independent dimensions, which in the end boil down to two questions:

  1. Does Alice want to enforce what conditions can be used in her cohort? If so then we can call this scenario "Alice decides conditions" (@jMyles's first point above); otherwise, it's "Enrico decides conditions" (second point).
  2. Does Alice care if someone else uses her cohort? i.e. is free-riding a problem for Alice? I think in general this is the case, but want to hear your opinions here.

Wrt to my previous comment, just want to point out that both proposed approaches assume that Alice indeed cares about someone else using her cohort, and both approaches could be applied to either "Alice decides" or "Enrico decides".

If Alice doesn't care about free-riding, then there's no point in restricting Enricos.

@arjunhassard
Copy link
Member

On free-riding: A purist microeconomics viewpoint would rule out launching a non-excludable service, i.e. where there's no mechanism to prevent open and unpaid usage. An interesting example from the past; Prysm were concerned that Ursulas who received re-encryption requests after the threshold had already been met (i.e. via sequential node discovery), wouldn't bother to answer at all. We rejected that particular 'audit finding' because the effort and risk associated with client code modification outweighed any nano-benefit gainable by circumventing a cheap local operation. Is that similar to this problem? Will the world simply use paid-for Strategies to the detriment of 'honest' adopters? I'm not sure. At the very least, it could be premature optimization for v7.0.0.

The first few CBD versions will restrict the number of public keys that one can encrypt to. This means a whitelist of adopting projects will unilaterally control the parameters associated with a given cohort of nodes. Eventually, we hope they will cede some of that control to their users/DAO/SCs. Regardless, free-riding – i.e. encrypting real data to one of those available public keys, outside of the context of the app/DAO that controls it, carries highly unpredictable long-term risk:
(i) The cohort can be discontinued overnight. This doesn't even require the controlling app to Chapter 11, they could decide to strategically move all associated data to another public key (admittedly this would be an onerous and trustful orchestration, but you can't rule it out).
(ii) The cohort parameters could be modified so it becomes far more expensive to use the public key. For example, if any of the following actions are payment-gated – condition creation, verification (i.e. decryption requests) or updating – then even if the Strategy and DKG ritual has been paid for, free-riders may be unable to afford ongoing and future use.
(iii) The cohort parameters can be modified in such a way to impose unacceptable security/trust burdens on your end-users. For example, the controlling app could 'down-grade' the cohort to a set of professional stakers based in a jurisdiction, such that users of this hypothetical free-riding app may consider the regulatory risks to be unacceptable, leaving the data already encrypted to this key in no-mans-land.

On closer inspection, it is irrational for any project/application/system/adopter that handles 'real' user data to take on these risks. Certain use cases cannot accommodate, for logistical or trust reasons, underlying data being decrypted and encrypted again to a new public key. Any application which intends to grow their user base beyond testers, and understands the massive potential downside of (i-iii) above, is unlikely to free-ride. This is particularly true because the savings – i.e. the upsides of free-riding – are near-negligible.

For those just hacking on CBD – where there is no objective of heavy end-usage – free-riding may indeed occur. We could even encourage it along with some strongly-worded caveats re: risks (i-iii). But low throughput free-riding is non-rivalrous, inasmuch as the extra operations lumped on Ursulas aren't going to affect their computational overhead, and therefore will have no detrimental effect on the network, nor the 'honest' adopters who paid.

Free-riding protections may therefore be superfluous until we modify the coordinator contract to allow permissionless cohort generation – i.e. when operator replacement is economically sustainable for stakers. Although, even then, risks (i-iii) still apply!

@cygnusv
Copy link
Member

cygnusv commented May 16, 2023

The first few CBD versions will restrict the number of public keys that one can encrypt to. This means a whitelist of adopting projects will unilaterally control the parameters associated with a given cohort of nodes. Eventually, we hope they will cede some of that control to their users/DAO/SCs. Regardless, free-riding – i.e. encrypting real data to one of those available public keys, outside of the context of the app/DAO that controls it, carries highly unpredictable long-term risk: (i) The cohort can be discontinued overnight. This doesn't even require the controlling app to Chapter 11, they could decide to strategically move all associated data to another public key (admittedly this would be an onerous and trustful orchestration, but you can't rule it out).
(ii) The cohort parameters could be modified so it becomes far more expensive to use the public key. For example, if any of the following actions are payment-gated – condition creation, verification (i.e. decryption requests) or updating – then even if the Strategy and DKG ritual has been paid for, free-riders may be unable to afford ongoing and future use.

I think this is an argument for introducing Enrico-level authorization, as it can serve as a place to introduce a payment gate. It would be good then to, at least, future-proof this option (e.g., introducing free Enrico authorization from start).

On closer inspection, it is irrational for any project/application/system/adopter that handles 'real' user data to take on these risks. Certain use cases cannot accommodate, for logistical or trust reasons, underlying data being decrypted and encrypted again to a new public key. Any application which intends to grow their user base beyond testers, and understands the massive potential downside of (i-iii) above, is unlikely to free-ride. This is particularly true because the savings – i.e. the upsides of free-riding – are near-negligible.

This is true if we assume that cohort "owners" are willing to pull the plug at some point, but I don't think that's a good assumption because, ideally, adopters will be locked-in to their cohorts since their own service is tied to the set of public keys associated to these cohorts (as you mention in point (i) above). In other words, if CBD doesn't include a solution to dinamically and selectively (de)authorize Enricos from start, free-riders "only" need to choose cohorts that seem long-term, from likely-stable adopters, and if/when these adopters change their mind wrt to the free-riding problem, they wouldn't have any recourse going forward. Again, I see this more as a future-proofing thing, than anything else.

@cygnusv
Copy link
Member

cygnusv commented May 16, 2023

By the way, from a future-proofing perspective, I think Approach #2 here is superior, and would be relatively easy to implement.

@KPrasch
Copy link
Member

KPrasch commented Jun 20, 2023

Here's a take on a specification from @theref @cygnusv and I:

changes
  • Contracts

    • AccessController (one deployment per network)

      • is an access control contract (may be owned by DAOs or MultiSigs)
      • reference to the coordinator contract (can be updated by owner)
      • mapping of ritual IDs → authorized enrico addresses
      • function to auth enricos (append to array) only owner of ritual via Coordinator interface
      • function to deauth enricos (remove form array)
    • Coordinator (one deployment per network)

      • rename Ritual.initiatorRitual.owner
      • interface to expose ritual state to Authorization Contract
      • ability to transfer ownership of a ritual
  • Authorizer

    • The DKG ritual initiator is the default authority
    • The ritual authority can add addresses to the allow list
    • Ritual authority is transferable
User Stories
  • Enrico…

    • has an ethereum wallet
    • authors the conditions and encrypts the plaintext
    • hashes Ciphertext + Conditions and signs it with his wallet.
      • {"authorization": {"signature": ... }}
    • includes authorization in AccessControlPolicy
    • publishes Ciphertext and AccessControlPolicy in a side channel for Bob
  • Bob…

    • collects Ciphertext and AccessControlPolicy from a side channel
    • (optional) verifies Enrico’s signature against the AccessController
    • constructs a ThresholdDecryptionRequest containing the ciphertext and policy
    • submits the request to Ursula
      • Success: proceed to decrypt
      • Fail: error message from ursulas
  • Ursula…

    • receives ThresholdDecryptionRequest from Bob
    • hashes Ciphertext + Conditions and verifies the signature of AccessControlPolicy.authorization.signature matches AccessControlPolicy.authorization.address
    • reads AccessController.isAuthorized(enrico_addres)
      • true: proceed to produce one dFrag
      • false: refuse to perform work and respond with an error

@derekpierre
Copy link
Member

derekpierre commented Jun 20, 2023

Good stuff 🎸 :

Apologies if some of these questions were already previously addressed:

  • Is the use of the AccessController an add-on (additional payment) type facility that adopters opt-in to use or is it always used? i.e. if an adopter intends to use a ritual, do they have to add an Enrico to the allow list before anything can be done or can an adopter decide that they don't want the hassle of an Enrico allow list and don't care about others free-riding?
  • Do adopters pay to add/remove Enricos keys?
  • Does Enrico need an ethereum wallet specifically, as opposed to some crypto-scheme signing key? For example, could Alice simply generate/assign a signing key pair for Enrico to use? Thinking about a "lighter" Enrico.

@derekpierre
Copy link
Member

I guess I have some economic questions in there - not sure if there is a separate issue for that. The last point on Enrico is a question based on your earlier specification comment.

@theref
Copy link
Collaborator

theref commented Jun 20, 2023

Q1 - good question, and is up for debate
Q2 - they would pay a gas fee, but nothing to the network
Q3 - our thinking was that it allowed for use of the address type in solidity, but this is another detail that is absolutely available for discussion

@KPrasch
Copy link
Member

KPrasch commented Jun 20, 2023

Is the use of the AccessController an add-on (additional payment) type facility that adopters opt-in to use or is it always used?

I propose, always used. Not additionally, but primarily.

i.e. if an adopter intends to use a ritual, do they have to add an Enrico to the allow list before anything can be done or can an adopter decide that they don't want the hassle of an Enrico allow list and don't care about others free-riding?

Good question. At least the way I understand it, adopters are paying for the ability to authorize Enricos as they please. Perhaps they have their own business logic around authorizing their users but ultimately, yes. If the adopter wants to authorize one of their users "for free" (in their own domain) and have already paid for CBD usage - they can just add a new address to the ritual's allow list.

Do adopters pay to add/remove Enricos keys?

Yes, but only once. but I'd reframe this as "adopters pay for the ability to authorize/deauth enricos as they please". Of course, there will still be a transaction gas fee for adding new keys to a rituals allow list.

Does Enrico need an ethereum wallet specifically, as opposed to some crypto-scheme signing key? For example, could Alice simply generate/assign a signing key pair for Enrico to use? Thinking about a "lighter" Enrico.

@theref and I discussed using different cryptosystems for authorization artifacts - I assert that using an ethereum wallet is the lightest, most interoperable, and friendly UX. An enrico that runs in the browser can simply use metamask or another browser wallet. Otherwise we'd need some key management mechanisms for an alternate cryptosystem. Plus, we can use an ethereum signing standard, and there is native strong typing for addresses in solidity.

@arjunhassard
Copy link
Member

arjunhassard commented Jun 23, 2023

(1) The gas cost of a adding every single new end-user device/wallet to the Enrico allowlist may be an economic friction for certain use cases, to the point that some adopters may not bother to use the allowlist – especially given the previously discussed risks of free-riding for apps of any significance. Hence to @derekpierre’s point, it may be better as an opt-in facility (or at least comes with an easy opt-out). 



Of course it depends on (i) the GWEI cost per Enrico and (ii) how volatile MATICUSD is going forward. But eventually there will be an adopter for which this is a non-starter – like a Telegram clone with very large group chats or IOT network with thousands of new sensors frequently added and removed.

It would be a different matter if we controlled this price point completely (i.e. beyond contract optimization), because we could tune it to adopters’ budgets. For example, the total number of decryption requests covered by a sponsor would in most cases increase with an expanding user base, but there’s no unpredictable third-party cost.



(2)

adopters pay for the ability to authorize/deauth enricos as they please.

This is a good way of phrasing it, but it may be premature to configure a payment gate here during the invite-only era, since by controlling ritual initialization we are de facto controlling who can use the AccessController contract – and the duration-based fee easily covers nodes’ out-of-pocket expenses – see calculations in discord (Fees thread). Is this ultimately a question of trusting genesis adopters not to abuse the AccessController contract? 



(3) 
With an explicit mapping of a ritual ID to the Enrico address allowlist, is there a way to decouple ritual authority from sponsorship and associated powers? We don’t know ex ante the order of power devolution by adopters. Initially, the developers integrating TACo will be trusted by their users with: 

(i) power over parameters

(ii) power over payment 

(iii) power over who can encrypt

We don’t know the order in or graduations by which these authorities might be transferred to some other entity (e.g. a DAO or one of our adopters’ adopters).

@theref
Copy link
Collaborator

theref commented Jun 23, 2023

(1) For use cases with large numbers of enricos being added/removed, there are better storage solutions. Both Arweave and IPFS would both be cost efficient for this case. Obviously there is development work that would need to be done to allow that functionality, but this is perfectly feasable

(3) Sometimes I'm getting lost in terminology, we came up with some preliminary entities whilst brainstorming. I'll throw them here.

  • Sponsor - pays for the service
  • Initiator - calls the Coordinator smart contract function to kick off the ritual (in v7 this is only Nuycpher, but will change in v8)
  • Owner - owns the ritual, defaults to initiator, can set the Authoriser
  • Authoriser - defaults to Owner, has full control of Enrico authorisation logic (can set custom smart contract, can use AllowList and add/remove Enricos)

Authoriser and Initiator/Owner could be decoupled if we wanted. The Initiator sets the authoriser during the ritual initialisation process, but after that, only the Authoriser has the power to change the Authoriser (ie, send the power to another entity)
To relate these back to your power structure:

  • Initiator - power over parameter
  • Sponsor - power over payment (although, is there any problem with making payment completely open? such that anyone can "top-up" an existing ritual)
  • Authoriser - power over who can encrypt

@arjunhassard
Copy link
Member

@theref Thanks for the quick and useful answer.

On (1) – if I haven't misunderstood, this would be adopters bundling new Enricos, storing a list of their IDs on some persistent storage, and creating + posting an on-chain reference to that list (hash), that Ursulas go and check when pinged with ciphertexts – thereby reducing the gas cost per Enrico by some multiple. In some cases this would be very helpful, but not when new devices need to be able to encrypt immediately, so they can't be queued up until some threshold of Enricos is reached. Even for a few minutes would be unacceptable UX in many apps. Also new Enricos joining is unpredictable – although I suppose there could be a maximum queue time regardless of list length.

(3) Very clear and logical hierarchy. The only adjustment I would suggest is; although the Initiator is indeed NuCypher in v7, we need all three roles/powers (Initatior, Owner & Authorizer) to be transferred to the adopter right after each initialization, or we undermine our claim that v7 is decentralized from genesis. It needs to be 'day one decentralized' inasmuch as the first byte of data encrypted is being managed multilaterally, but maybe not 'minute one decentralized' inasmuch as the initialization is a trusted setup, with immediate power devolvement (i.e. before the first encryption event!)*.

Re: open payments, that's fine as long as random payments don't (unintentionally) confer Authorizer power to random payers.

*Acknowledging that this transfer moves power from NuCypher to another central authority, but (1) the core, user-facing component of the service – access – is fully decentralized and (2) symbolically and practically its carries a lower trust burden compared to NuCypher retaining any of these three powers, because we have more power over the DAO and the contracts than an adopter, so this transfer is a genuine spreading out of censoring power.

@theref
Copy link
Collaborator

theref commented Jun 23, 2023

(1) Nah you can do it way faster than that. Especially with arweave which allows tagging. So you store a tag onchain, then look for all transactions on arweave that a) contain the tag, b) were sent by the authoriser. Adding a new enrico is then super quick and cheap (potentially free because it's such a small amount of data, i think tx under 100kb are free on arweave). But we can definitely look into this further when adopters need it.

Also, as long as decryption isn't also happening immediately, there's nothing stopping Enrico just cracking on with encryption and the authorisation coming a little later (unless we plan to implement some timestamping at encryption time).

(3) Yes, totally agree that all power needs to be transferred immediately in v7. Ideally Initiation should be done with the adopter present I think :)

@arjunhassard
Copy link
Member

From Barcelona in-person discussions:

  • Instead of giving sponsors an inflexible ‘allowlist’, provide a choice of ‘allow logic’ contracts
  • Similar to before, Ursula would effectively check an extra condition for a given request, in this case that correct allow logic contract has the correct state (i.e. it's sufficiently funded and/or the encrypting party matches some criteria)
  • At genesis there will be be a limited number of allow logic contracts to choose from, including a simple one which functions like the previously envisaged simple allowlist of wallet addresses
  • Adopters can also propose custom allow logic, such as a ZK circuit based one to preserve encryptor anonymity. We can approve these at our discretion
  • A purely time-based allow logic contract would likely be open to free-riding
    • This is ok, because the network still gets paid, and in most cases the free rider will still have to pay at some other checkpoint in the flow. Also, it remains risky to channel a lot of usage via a cohort you don’t ultimately control
  • Allow list contracts could also enforce and collect payments, for example a fee on a per-encrypting device basis
    • These could also form part of a custom contract bundle along with other action-based fees
  • This could also way to restrict open/arbitrary API access from genesis – if not by adding a charge on top of the duration-based fee, then by adding some kind of usage caps – e.g. a maximum number of encrypting devices / users. This would reduce the challenge of weaning adopters off unrestricted and unlimited use of the API as we move to the multi-product era

@arjunhassard
Copy link
Member

Excellent example of a custom allow logic contract from @jdbertron (comment in fee + rollout RFC)

Could this be solved by enforcing condition inheritance ? i.e. the original sponsor creates the DKG with a 'parent condition', from which all encryptor conditions must derive, and of course the parent condition would enforce the membership, so that the membership may not be known prior to encryption, and may not even require maintaining a list, yet freeloaders can't make use of the setup to get a free encryption-decryption pipeline. I'm thinking one such parent condition could verify that encryptors can sign a known plaintext that shows they belong to a class of addresses all derived from the same point. Something like that.

@ghardin1314
Copy link

Approach 2. Smart contract

I describe here a generic approach that generalizes @KPrasch's message above, but that could be used in different ways:

  1. Initiator associates a smart contract to the ritual, conforming to some interface, e.g.,:
function isEnricoAuthorized(uint256 ritualID, bytes evidence, bytes ciphertextHash) public view returns(bool);
  1. The way how initiator grants access on this smart contract is out of scope. For illustration, let's assume the initiator just adds Enrico's PK to a list in the smart contract
  2. Enrico attaches evidence to the ciphertext. In our example, Enrico's evidence is signature(ciphertext_hash).
  3. Bob makes decryption request, which includes the evidence.
  4. Node calls the function in the smart contract to check whether Enrico is authorized. In our example, the smart contract would take the signature as evidence, extract the public key from the signature, and check whether the public key is in the list.

Personally I like this approach the best. For each ritual creation, the initiator would pass an accessControl address parameter which would have some standard interface. You could make address(0) a default which means "no access control, enable all enricos". This contract could then impose whatever logic it would like (holders of a NFT, merkle tree allowlist, etc).

For a higher throughput of Enricos where it is infeasible to store every address on chain (or Enricos dont have a key pair), potentially you could support something like this:

https://eips.ethereum.org/EIPS/eip-3668

Where the AccessControl contract tells the Ursula where to go to make an offchain data retrieval and then validates that response. Not sure if this EIP is worth implementing directly, or a modified version is warrented, but I think it would cover all your basis in a secure way

@cygnusv
Copy link
Member

cygnusv commented Jul 27, 2023

Continuing the iteration on Approach#2, currently being implemented nucypher/nucypher-contracts#89:

    function isAuthorized(
        uint32 ritualID,
        bytes memory evidence, // signature
        bytes memory digest   // signed message hash
    ) external view returns(bool);

Let's see how 3 different authorization mechanisms could be implemented pursuant to this interface (I'm being very loose with the code here, so please bear with me).

These 3 examples assume the creator has an ECDSA keypair, and in all of them they sign a digest of the Ferveo Ciphertext (specifically, of the "thin" format, see nucypher/ferveo#147 (comment)). In pseudo-code:

digest = keccak(thin_ferveo_ciphertext)
signature = sign(creator_private_key, digest)

On-chain allowlist

Let's assume that evidence = vrs_encoding(signature) and that the allowlist is implemented in the contract with a mapping keyed by ritualID and creator address:

function isAuthorized(
    uint32 ritualID,
    bytes memory evidence,
    bytes memory digest
) external view returns(bool){
    v, r, s = vrs_decode(evidence);
    address creator = ecrecover(digest, v, r, s);
    return allowlist[ritualID][creator];
}

Merkle Tree allowlist

Instead of adding individual creators to the contract, the authorizer creates a Merkle Tree (thanks @ghardin1314 for the idea). Let's assume that the Merkle tree is implemented with OpenZeppelin, where each leaf is an authorized address and the authorizer sets a global root, and that evidence = vrs_encoding(signature) || merkle_proof:

function isAuthorized(
    uint32 ritualID,
    bytes memory evidence,
    bytes memory digest
) external view returns(bool){
    signature, proof = parse_evidence(evidence)
    v, r, s = vrs_decode(signature);
    address leaf = ecrecover(digest, v, r, s);
    return MerkleProof.verify(proof, root, bytes32(leaf));
}

NFT Authorization

Let's assume that evidence = vrs_encoding(signature) and that the authorization is based in holding a certain NFT:

function isAuthorized(
    uint32 ritualID,
    bytes memory evidence,
    bytes memory digest
) external view returns(bool){
    v, r, s = vrs_decode(evidence);
    address creator = ecrecover(digest, v, r, s);
    return ERC721.balanceOf(creator) > 0;
}

It seems all of them can be accommodated to the interface. A question that you may have is why the creator always signs a hash of the thin ciphertext: there may be other approaches, but signing the ciphertext ensures that it's not possible to perform signature stripping, since we have to assume that MessageKits are public (at the very least, the consumer and the nodes will see it). We need to sign something unique to the request, and the ciphertext is the best representative of the request.

@derekpierre
Copy link
Member

Closed via #3226.

@arjunhassard arjunhassard reopened this Feb 19, 2024
@KPrasch KPrasch changed the title Alice authorizes condition adherence: by sharing a token with Enrico? Or by authoring a condition suite for public availability? DKG Authorization Models Feb 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Completed
Development

Successfully merging a pull request may close this issue.

7 participants