7/19/2026 at 7:12:24 AM
I’m having a hard time wrapping my head around what guarantees this does and does not make.If you can run “select * where secret_col == 10”… why does it matter that the column is encrypted?
by maxrmk
7/19/2026 at 8:44:09 AM
CipherStash founder here.If a column is encrypted using standard encryption (like AES-GCM) then the values are non-deterministic and fully randomized. That means that if you encrypt the same value twice, you'll get 2 different ciphertexts.
So the query: select * where secret_col == 10
Would actualy be: select * where secret_col == encrypt_aes(10);
And values in secret_col will never match (because the output of encrypt_aes will be different every time, even for the same input).
A common way around this is to use deterministic encryption which eliminates the randomization at the cost of a slightly weaker security model. What leaks is the ability to see if any 2 plaintexts are equal (because they have the same ciphertext) - what you actually want in the case of search.
You have to be careful implementing deterministic encryption though: don't use AES-GCM with a fixed nonce because the scheme completely breaks. You can use CBC mode but then you lose authenticity. We use AES-GCM-SIV (synthetic IV which retains authentication but is secure under a fixed nonce) and HMAC (keyed hashing).
But there are approaches to solving queries like: -- range/order SELECT * FROM foo WHERE x > 10; SELECT * FROM foo ORDER BY x; -- fuzzy text SELECT * FROM foo WHERE name ~ "dan";
These capabilities are all based on public research: For example, order/range uses: https://eprint.iacr.org/2016/612.pdf
Our docs are quite limited at the moment (fixing as quickly as we can!) but you can see the current list of supported queries here: https://cipherstash.com/docs/stack/cipherstash/encryption/qu...
by dandraper
7/19/2026 at 1:45:45 PM
Don’t use deterministic encryption unless your data is already highly random.Any adversary who knows the distribution of the plaintext data can guess what your encrypted values are, with accuracy that improves as your sample size increases.
There were a bunch of papers on this 10-12 years ago. (Full disclosure: I was an author on some of them.)
by cvwright
7/19/2026 at 2:04:19 PM
Yep, we’ve read the papers. Naveed et al and Grubbs et al primarily.by dandraper
7/20/2026 at 8:01:21 PM
Thanks Dan, this is very interesting. From someone deeply involved in privacy I see the benefits of the auditability and risk mitigation in cases like SQL injection.What does the risk profile look like in a full leak of the encrypted database?
If you had a column of integers are you able to order them without decrypting? Check that values are the same? Identify null values?
by maxrmk
7/19/2026 at 9:15:00 AM
What does all this actually solve? Presumably SQL injection might still decrypt contents and order by/where clause enumeration would still be possible regardless. Keys must be stored in memory, on-disk or via a secret server meaning column encryption would not mitigate the impact of RCE/full shell compromise. Add in the cost of column level encryption when querying large volumes of data, this seems to be entirely angled at gold plated compliance security theatre rather than solving any actual problem.by hsbauauvhabzb
7/19/2026 at 10:30:14 AM
See above but some additional points:Keys are not stored in the database or in the application. Every data key is derived at query time via a 2-party system: 1. by the key server which manages root-key material (stored in an HSM or traditional KMS) 2. keys derived via a user credential at the time of the query
SQL Injection case: An adversary signs up to your app, pulls of a SQLi and you might think that the app will just decrypt the values. It won't because the adversary's auth cred can't derive keys to decrypt anything but the data they are explicitly allowed to access.
RCE/shell compromise: Because keys are derived on demand these kinds of attacks are largely inert. If the attacker could read memory from the running app on-demand then they could conceivably see credentials in flight but each key only ever decrypts one value so the blast radius is limited.
On the cost of decryption: Queries typically only return a subset of the values in a table and, importantly, don't need to decrypt anything at all. Querying and decryption are independent. If you DO need to decrypt a large volume of data, CipherStash can do it at 10,000 values per second.
Query performance is under 1ms for simple queries and no-more than 200-300ms for more complex queries.
Full benches here: https://github.com/cipherstash/benches
No security tool is perfect, nor "gold plated" but this tech meaningfully reduces blast area of attacks, makes many attacks inert and gives you an incredibly reliable audit trail.
by dandraper
7/19/2026 at 11:50:00 AM
If the keys are derived on demand and you have remote shell, you can derive them. If they’re salted with the users password, then it becomes impossible to decrypt them without the user being present which is problematic also.I’m not a cryptographer and I can see flaws in your proposed system, I imagine someone qualified could poke some pretty glorious holes in your snake oil.
by hsbauauvhabzb
7/19/2026 at 12:59:20 PM
No, to derive a key you need a client key (controlled by the app) and key-seeds for each value which can only be retrieved from the key server with a valid JWT. The JWT is time bound (15 mins).Now, if an attacker could gain access to the client key AND a valid JWT then they would be able to decrypt until the JWT expired. Blast radius reduced but we don't stop the attack entirely. An attacker with that much advantage is pretty hard to stop dead. But note that 2 things are required for the adversary to do this - where as in most systems, getting a JWT or a decryption key alone would be enough.
If you're not a cryptographer, then I'd suggest you reserve judgement about what flaws you think might be in the system. We have cryptographers on our team, have connections with universities in the US and Australia and our work is based on published, peer-reviewed papers. E.g. Lewi-Wu 2016 and Syalim et al 2011 and 2021.
by dandraper
7/19/2026 at 10:02:04 AM
Careful, they’ll take “gold plated compliance security” and use it in sales pitchesby repeekad
7/19/2026 at 10:30:58 AM
If we do, I'll be sure to attribute it to this thread :pby dandraper
7/19/2026 at 12:25:56 PM
[dead]by cipherjim
7/19/2026 at 10:14:32 AM
Searchable encryption means you can have encryption and queries (from apps etc) still work for authorized users.This is all started when I was the CTO of a health-tech and the engineers all had access to patient data. They needed DB access (data migrations, managing backups, reading non-sensitive fields) but not access to the sensitive values. 10m+ patient records - it made me nervous.
Row-level Security (RLS) was a nightmare, it was slow, easy to mess up and could be overridden by DBAs anyway. Plus the application connected to the DB using a service account so RLS was useless for end-user access control.
CipherStash solves the following:
* Hide sensitive data from direct database accessors (authorized or not!)
My original use-case. Direct access to the DB doesn't reveal sensitive data (unless the user also has permission to decrypt a specific record).
* Support or even replace application access controls
Decryption happens in the application layer and is based on end-user identity. That means a gap in application defenses is mitigated by the encryption. If the user can't decrypt the value then they can't access the data.
* Access auditing
Every sensitive data access is recorded (and by who) which is very useful for compliance and incident response. SQL query auditing is great for knowing what queries were run but it doesn't tell you what data was actually returned. Its also blind once data actually leaves the DB and can inadvertently leak sensitive data itself. Using key accesses with non-identifying value IDs to audit decryptions makes the auditing more reliable and super granular.
We have customers who use the tech to prove to their users (often large enterprise) that no internal staff can access the data.
* Agent access to data
The encryption shifts access control decisions down to the data layer on a per-value basis. This is incredibly useful for gating access to agents that need access to data. Every decryption requires authentication (e.g via Supabase Auth, Auth0 etc) and combining it with agent identities (creds issued to agents) means you can not only limit what agents can access, you can also audit exactly what _was_ accessed.
The searchable encryption is the enabler: value level encryption is what makes all of this possible. Searchable encryption means you can have encryption and queries (from apps etc) still work for authorized users.
Hope that helps! I'm so in the weeds I don't know if I explain things that well sometimes!
by dandraper
7/19/2026 at 10:30:37 AM
On auditing, is that CipherStash or the application doing the auditing? Seems like your logs would be huge if it contained values of queriesby catmanjan
7/19/2026 at 10:39:31 AM
CipherStash - specifically the key service. There is a lot of data for sure but we only record an identifier for each value and (optionally) the user ID. It compresses well.by dandraper
7/19/2026 at 10:49:29 AM
So an identifier is kept for each column returned by a query?If the value changes would you be able to get from the id you have audited back to the value that was returned at that point in time?
by catmanjan
7/19/2026 at 10:59:55 AM
Not just each column, each value.The answer to your question is yes.
Explanation: The identifier is actually for the key that encrypts the value (1 unique key per value).
1. When the value is encrypted for the first time, it gets an ID. 2. When its decrypted, the application requests the key for that ID from the key-server (key-server records that the data was accessed)* 3. When updating, the same data key is used so the ID is persistent*
* Technically the key server doesn't return a key, it generates partial key material that can be used to derive the data key in the app. It can do this at up to 10,000 keys per second. * You can also tag each value with the table/column name and the row-id to link everything together
The 3 values form the "descriptor" of a value: `table/column/id`.
by dandraper
7/19/2026 at 11:27:41 AM
So the audit log contains an ID for a key which could decrypt a value - does the audit log also contain the encrypted value itself? If not, how do you go from the audit log back to the original value in 1?by catmanjan
7/19/2026 at 11:42:54 AM
No, not by default. You could but as you said, that would be a A LOT of data.It depends on your setup. If you're using Supabase, one way is to send the logs to Clickhouse and use the Clickhouse partner integration to query the audit logs and join it to the actual data.
Keeping only the ids in the audit log means you need to stitch the data together later. This means you don't accidentally leak data via your audit trail!
by dandraper
7/20/2026 at 8:31:33 AM
Ok Im having trouble reconciling this comment> SQL query auditing is great for knowing what queries were run but it doesn't tell you what data was actually returned
With what you’re saying - sounds like cipher doesnt tell you what data was actually returned either - it will only tell you if the user could have received a decrypted version of the data right?
by catmanjan
7/19/2026 at 9:26:17 AM
the OP asked why, you more described the how.What is the benefit of all this?
by MikhailTal
7/19/2026 at 10:15:01 AM
I've replied aboveby dandraper
7/20/2026 at 11:52:43 AM
Because queries are encrypted, too. And you need to be authorized to encrypt a query term. That's the whole crux.TBH, I'm so close to this now I forget that part isn't obvious! You literally can't do:
select * from blah where secret_col == 10
And get meaningful results. You can only do something like:
select * from blah where secret_col == Encrypt(10);
And in order to generate that encrypted query, you must be authorized. So an adversary can't simply do trial and error queries to guess records.
by dandraper
7/19/2026 at 8:23:45 AM
It sounds like someone has discovered a side-channel, made a project around it, and forget/did not know what side-channel originally means. And then someone at Supabase who does not know crypto, is a victim of their marketing.by nicce
7/19/2026 at 2:07:52 PM
lol yeah. Just a side chain that I found on a weekend. 8 years and $10m later. Couldn’t possibly be real now could it?by dandraper
7/19/2026 at 9:12:43 AM
One would hope that only users who can already decrypt the data can perform the queries. In that case, it would give much faster query performance without allowing inference attacks on the data.If not, then a lot of the data could be easily reconstructed.
by MattPalmer1086
7/19/2026 at 12:21:45 PM
It is indeed the case.by dandraper
7/19/2026 at 7:36:10 AM
My thoughts as well. Seems like security theater.by nullbio
7/19/2026 at 7:41:13 AM
you're probably only allowed a subset of the query language to talk to an encrypted table. E.g. only range queries that target a sample size > 5% of rows, etc., with exceptions for searches that hit an exact index such as looking up by id.by aabhay
7/19/2026 at 8:25:00 AM
A lot is allowed: https://cipherstash.com/docs/stack/cipherstash/encryption/se...by nicce