<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Fhenix</title>
    <description>The latest articles on DEV Community by Fhenix (@fhenix_io).</description>
    <link>https://dev.to/fhenix_io</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3294376%2Fa560cdff-ad74-4e8a-931c-c775bc354e14.jpg</url>
      <title>DEV Community: Fhenix</title>
      <link>https://dev.to/fhenix_io</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fhenix_io"/>
    <language>en</language>
    <item>
      <title>Understanding Access Control in CoFHE</title>
      <dc:creator>Fhenix</dc:creator>
      <pubDate>Wed, 25 Jun 2025 15:56:53 +0000</pubDate>
      <link>https://dev.to/fhenix_io/privacy-isnt-private-by-default-understanding-access-control-in-cofhe-38l0</link>
      <guid>https://dev.to/fhenix_io/privacy-isnt-private-by-default-understanding-access-control-in-cofhe-38l0</guid>
      <description>&lt;p&gt;Ethereum devs are no strangers to public-by-default data. It’s one of the foundational features of blockchain: every transaction, every variable, every storage slot—transparent, inspectable, immutable.&lt;/p&gt;

&lt;p&gt;But what happens when you want to &lt;strong&gt;build applications that &lt;em&gt;don’t&lt;/em&gt; expose user data to the entire world?&lt;/strong&gt; Enter Fully Homomorphic Encryption (FHE) and the CoFHE coprocessor. For the first time, Ethereum contracts can &lt;em&gt;compute&lt;/em&gt; on encrypted values… but with this power comes a new responsibility:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Controlling who’s allowed to use or view encrypted data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s where &lt;strong&gt;access control&lt;/strong&gt; and &lt;strong&gt;permits&lt;/strong&gt; come in.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 Why does access control even matter in FHE?
&lt;/h2&gt;

&lt;p&gt;Let’s say a user encrypts a value (like a secret bid or their balance) and sends it to your contract. You store that encrypted value as an &lt;code&gt;euint32&lt;/code&gt;. Everything looks great!&lt;/p&gt;

&lt;p&gt;Now imagine someone else sees that encrypted handle on-chain and tries to use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function attack() public {
  FHE.decrypt(seenHandle); // 👀 tries to decrypt someone else’s data
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there were no protections, this would totally defeat the point of encryption. That’s why every encrypted handle in CoFHE is tied to an &lt;strong&gt;access control list (ACL)&lt;/strong&gt;. It enforces strict rules around &lt;strong&gt;who is allowed to operate on or decrypt a given ciphertext.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By default:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The contract that creates a value (via &lt;code&gt;FHE.asEuint32()&lt;/code&gt;) gets temporary access &lt;em&gt;for that transaction only&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;No one else can access that ciphertext unless &lt;strong&gt;explicitly granted&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 The mental model: ownership, scope, and sealing
&lt;/h2&gt;

&lt;p&gt;When working with encrypted values in Solidity using &lt;code&gt;FHE.sol&lt;/code&gt;, think in terms of &lt;strong&gt;who has permission to do what&lt;/strong&gt;, and for how long.&lt;/p&gt;

&lt;p&gt;There are &lt;strong&gt;two types of access&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Contract-level access&lt;/strong&gt; — via &lt;code&gt;FHE.allowThis()&lt;/code&gt; or &lt;code&gt;FHE.allow()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User-level access&lt;/strong&gt; — via &lt;code&gt;FHE.allow(ciphertext, address)&lt;/code&gt; + sealed output + permit in &lt;code&gt;cofhejs&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are also &lt;strong&gt;two time scopes&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transient&lt;/strong&gt;: access only lasts during the current tx&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent&lt;/strong&gt;: access survives across transactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And finally, to unseal &lt;strong&gt;data off-chain&lt;/strong&gt;, a user needs two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The contract must have called &lt;code&gt;FHE.allow(ciphertext, userAddress)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The user must hold a valid &lt;strong&gt;permit&lt;/strong&gt; that proves they are allowed to unseal that data.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ How to use it (conceptually)
&lt;/h2&gt;

&lt;p&gt;Here’s the basic lifecycle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Encryption&lt;/strong&gt;: User encrypts data client-side with &lt;code&gt;cofhejs.encrypt()&lt;/code&gt; and sends it to the contract.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access Granting (Contract)&lt;/strong&gt;: Your contract receives it with &lt;code&gt;InEuint32&lt;/code&gt; and does &lt;code&gt;FHE.asEuint32(input)&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;If you’ll use that value in &lt;em&gt;future transactions&lt;/em&gt;, you must call &lt;code&gt;FHE.allowThis(value)&lt;/code&gt; to persist access.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Off-chain Access (User)&lt;/strong&gt;: Before unsealing, the contract must call &lt;code&gt;FHE.allow(value, user)&lt;/code&gt; and the user must sign a &lt;strong&gt;permit&lt;/strong&gt; using &lt;code&gt;cofhejs.createPermit()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unsealing&lt;/strong&gt;: The user can now decrypt that value with &lt;code&gt;cofhejs.unseal()&lt;/code&gt;, proving they have a valid permit and access rights.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This access dance ensures that encrypted values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Aren’t globally usable by anyone&lt;/li&gt;
&lt;li&gt;Can only be decrypted by the intended party&lt;/li&gt;
&lt;li&gt;Can be safely passed between contracts or across chains (with careful permissioning)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧵 Example: encrypted balances
&lt;/h2&gt;

&lt;p&gt;Let’s say you’re building a private token or game where users have encrypted scores or balances.&lt;/p&gt;

&lt;p&gt;Here’s what you’d want to do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function transfer(InEuint32 _amount, address to) public {
    euint32 amount = FHE.asEuint32(_amount);

    balances[msg.sender] = FHE.sub(balances[msg.sender], amount);
    balances[to] = FHE.add(balances[to], amount);

    // 🔓 Let users unseal their updated balances offchain
    FHE.allow(balances[msg.sender], msg.sender);
    FHE.allow(balances[to], to);

    // ✅ Optional: Let the contract use these values again later
    FHE.allowThis(balances[msg.sender]);
    FHE.allowThis(balances[to]);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the frontend, a user would generate a permit like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const permit = await cofhejs.createPermit({
  type: 'self',
  issuer: wallet.address,
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then unseal their balance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const unsealed = await cofhejs.unseal(encryptedBalance, FheTypes.Uint32, permit.issuer, permit.getHash());

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it — no plaintext exposed, no extra trust assumptions.&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Things to remember
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FHE.asEuint32()&lt;/code&gt; gives you &lt;strong&gt;temporary&lt;/strong&gt; access. For reuse, call &lt;code&gt;FHE.allowThis()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;To decrypt off-chain, always call &lt;code&gt;FHE.allow(handle, user)&lt;/code&gt; on the contract side.&lt;/li&gt;
&lt;li&gt;Permits are signed proofs that the user owns their encryption keys — required to unseal.&lt;/li&gt;
&lt;li&gt;If you forget &lt;code&gt;allow()&lt;/code&gt;, &lt;code&gt;unseal()&lt;/code&gt; will silently fail with a &lt;code&gt;SEAL_OUTPUT_RETURNED_NULL&lt;/code&gt; error.&lt;/li&gt;
&lt;li&gt;Do not share encrypted handles between users or contracts without explicitly granting permission.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔎 What makes this unique?
&lt;/h2&gt;

&lt;p&gt;Unlike ZK or MPC systems, &lt;strong&gt;FHE data can live on-chain in encrypted form indefinitely&lt;/strong&gt; — but the only way to extract it is through controlled access.&lt;/p&gt;

&lt;p&gt;Rather than hiding inputs or proving secrets once, CoFHE builds a system where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Encrypted values are first-class citizens&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ownership is enforced at the encryption layer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Access is explicit, granular, and provable&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s closer to &lt;strong&gt;a permissions system for encrypted memory&lt;/strong&gt; than it is to a traditional "black box compute."&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 Want to see how to implement it?
&lt;/h2&gt;

&lt;p&gt;This post was a lot of  theory, but if you're ready to &lt;strong&gt;build something with CoFHE&lt;/strong&gt;, check out the official docs and step-by-step examples:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cofhe-docs.fhenix.zone/docs/devdocs/access-control" rel="noopener noreferrer"&gt;Read the CoFHE Access Control Docs&lt;/a&gt;&lt;/p&gt;




</description>
    </item>
  </channel>
</rss>
