<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Jeff Wu</title>
    <description>Personal website of Jeff Wu
</description>
    <link>http://wuthejeff.com//</link>
    <atom:link href="http://wuthejeff.com//feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 06 Oct 2026 16:47:07 +0000</pubDate>
    <lastBuildDate>Tue, 06 Oct 2026 16:47:07 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Auditing the singularity</title>
        <description>&lt;p&gt;&lt;em&gt;AI is used by the powerful to oversee the masses.  We should instead be using it to let the masses oversee the powerful.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Imagine anyone submit natural language queries to any institution in the US.  To do so, you pay some money, specify an AI auditor, and specify the query.  Examples:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Claude Fable 7.5 auditing Goldman Sachs:  “Flag anything inconsistent with the risk-committee independence required under Dodd-Frank §165.”&lt;/li&gt;
  &lt;li&gt;DeepSeek v7 auditing the Pentagon:  “Is the Pentagon’s command and control logic willing to automatically target foreign civilians and under what tradeoffs if so?”&lt;/li&gt;
  &lt;li&gt;GPT-8.1 auditing Anthropic:  “What are ways Anthropic might be training their models to have secret/unexpected loyalties?”
The AI auditor is a perfect amnesiac.  It returns a result, but then ceases to exist.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Queries are not always accepted, but some categories are accepted presumptively.  For example, private queries are allowed for records where you are the subject or counterparty, subjects where you have a legitimate interest, or events that caused you injury.  Public queries are accepted if they straightforwardly pertain to incidents in public record, or pertain to compliance with law.  Federal agencies accept all public requests, under an upgraded version of FOIA.  Otherwise, queries are generally only accepted if the querier has a warrant, or if the institution voluntarily accepts it.  For public queries, results are published publicly.  For private queries, the querier can choose whether to publish.&lt;/p&gt;

&lt;p&gt;The AI auditor is given tools that provide comprehensive access to the institution’s audit trail, which contains internal documents, communications, AI agent traces, etc.  As firms become increasingly driven by AI output, the AI agent traces dominate.  It is important that the audit trail is maximally complete, with no information unrecorded.  The audit trail is secured extremely well, and kept in a tamper-evident append-only log; hashes of all documents are published continuously and publicly.  Because the auditor is an AI, the auditee has no fear of information leakage beyond the returned result.&lt;/p&gt;

&lt;p&gt;A third party institution is responsible for maintaining the auditing infrastructure, and is entrusted with the simple responsibilities of maintaining the logging software, securely accessing the auditor model weights, running the query in some trusted execution environment, and signing the result (or perhaps just verifying a zero-knowledge proof of it).  The third party is quite trusted:  1) their role is mechanical and requires minimal judgement, 2) they are paid by people interested in accountability, rather than by institutions, unlike the traditional auditing regime, and 3) it is subject to its own audits, perhaps by a rival third party.  There are no direct consequences of audit results, in general.  But depending on the circumstantial evidence, someone might decide to sue the institution, and documents will then be surfaced in discovery.&lt;/p&gt;

&lt;p&gt;After the auditor runs, results also undergo a redaction process before being returned, which is typically done by a standardized redactor AI.  There are a number of things redacted by default:  customer and employee PII, trade secrets, weapons access, classified info, etc.  Each institution declares their trade secrets publicly, e.g. “we develop new proprietary training algorithms for neural networks”, and trade secret redactions typically only apply for documents from &amp;lt;10 years ago unless you apply for exemptions (also made public).  After an auditor model produces a response, the auditee can flag sections for redactions (typically done with a standardized redactor model), citing the corresponding reason from the whitelist.  If the auditor model disagrees with the redactions, this is noted, but the redaction still goes through.  Existence of redactions and disagreements are public.  Too many disagreements on redactions can lead to lawsuits, where relevant evidence becomes unsealed (and subject to protective orders).  The threat of eventual discovery makes disagreements on redactions rare, for legitimate auditor models.&lt;/p&gt;

&lt;p&gt;What about public trust in the auditor model?  This comes from auditing the developer of the auditor AI.  Say Claude Fable 7.5 is commonly used for auditing.  We use GPT-7 or an open source model to make sure Anthropic’s alignment process of Claude Fable 7.5 was conducive to producing honest models trying their best to audit in all circumstances.  This relies on good science for alignment auditing.  Also, at some point, we had to bootstrap the trust from traditional auditors, who made sure the first auditor model was aligned enough and that Anthropic had sufficiently complete logs.  As with &lt;a href=&quot;https://www.cs.cmu.edu/~rdriley/487/papers/Thompson_1984_ReflectionsonTrustingTrust.pdf&quot;&gt;self-compiling languages&lt;/a&gt;, this first step is critical to get right, and it has to happen early on (which means ASAP, in my opinion).&lt;/p&gt;

&lt;p&gt;Checks and balances at a governance level are easier than before.  Investigative journalists get instant responses to their FOIA requests, though classified information is exempted.  Congress constantly asks auditors about cases of potential executive overreach, in some cases able to bypass redaction of classified information.  The judicial system gets bypass on warrants or in litigation, massively enhancing the document discovery process.  Governments constantly query the relevant institutions to make sure international treaties are enforced, when in the past cooperation would’ve failed for lack of credible mutual verification.  For example, the AI pause treaty consists of things like “Are the satellites still tracking all new data-center creation?” and “Are any companies in charge of big data-centers running training runs with X flops?”.  In some high stakes scenarios, there are queries that the governments pay to maintain constantly and run in real-time. In this modified system, the result of audits can block agent actions and alert relevant authorities.&lt;/p&gt;

&lt;p&gt;Institutions of course sometimes attempt to avoid the audit trail.  Whistleblowing laws mostly deter the most egregious cases.  But also, all logged AI agent activity is required to be stored alongside provenance, tracing back to either a human being, another agent, or a piece of software.  The third party facilitates programmatic checks that all activity originates from something else in the audit trail, or from some human directive.  If a large amount of activity is claimed to originate directly from a human, this is quickly flagged as suspicious, since humans cannot operate at such scale.  There are also inter-institutional counterparty checks for consistency – for any activity that affects the external world or another party, the custodian facilitates boolean checks to confirm existence of the corresponding record.  Taken together, attempts to hide large amounts of activity outside the trail is difficult: any action which eventually leads to affecting the world can be traced back to that action.  Ultimately, large scale harms are visible (even if initiated by machinations that aren’t), so the system is able to prevent major violations of public interest.&lt;/p&gt;

&lt;p&gt;Sometimes, people try to develop jailbreaks for the auditor model.  This usually is noticed immediately, but in some cases is discovered 1-2 generations of auditor models later, and is always punished under criminal law.  Academics also worry about steganographic encodings that the auditor model can’t understand.  Discussions of those developments would need to happen outside of the audit trail, and it seems very difficult in practice.  It is also illegal to use language models that were not trained in audited settings; the law was established after the NSA started using a model an employee trained in their personal time.  Overall, ability to thwart the system in practice seems quite limited.&lt;/p&gt;

&lt;p&gt;Some powerful institutions still try engaging in lawfare:  auditing opponents, arguing for protection via the 4th amendment, using redaction exemptions to hide bad behavior, and generally trying to set the rules differently for themselves.
But increasingly, trustworthy institutions voluntarily allow arbitrary queries, redact only the most important trade secrets, and ultimately benefit from the increased trust.
At the same time, AI agents who don’t mind being audited become responsible for more of the economy, and since redaction works well, the downsides are limited.&lt;br /&gt;
The ideas become more socialized, and people become more comfortable with audits and with requiring them.
The good equilibrium is also self-stabilizing:  people use audits to make sure the system itself is sound and not weaponized. 
Institutions abusing audits to learn about opponents, can be audited to in turn to expose the abuse to the public.&lt;/p&gt;

&lt;p&gt;The end result is that all the important functions of society are &lt;a href=&quot;https://aiprospects.substack.com/p/security-without-dystopia-new-options&quot;&gt;structurally transparent&lt;/a&gt;, and accountable to serve only the functions they are meant to, and there is much more trust to go around.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;i&gt;
The world needs much better defaults for oversight.  You can help by raising awareness and generating political will around today’s institutional problems.  And if you’re interested in helping build pieces of this future, contact me!
&lt;/i&gt;&lt;/p&gt;
</description>
        <pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate>
        <link>http://wuthejeff.com//ai/oversight/auditing/2026/05/27/auditing-the-singularity.html</link>
        <guid isPermaLink="true">http://wuthejeff.com//ai/oversight/auditing/2026/05/27/auditing-the-singularity.html</guid>
        
        
        <category>ai</category>
        
        <category>oversight</category>
        
        <category>auditing</category>
        
      </item>
    
      <item>
        <title>A compressed post</title>
        <description>&lt;p&gt;Understanding is compression, but reading involves both decompression and compression.
Decompression should sometimes be computationally taxing, especially when the compression is lossy or the author has a subtly different compression scheme.
It’s a lost art in today’s world to take a long time to digest a short text, and this leads to misunderstandings.&lt;/p&gt;
</description>
        <pubDate>Tue, 25 Jan 2022 11:04:00 +0000</pubDate>
        <link>http://wuthejeff.com//2022/01/25/a-compressed-post.html</link>
        <guid isPermaLink="true">http://wuthejeff.com//2022/01/25/a-compressed-post.html</guid>
        
        
      </item>
    
      <item>
        <title>Filtering vs finetuning: intuitions on training anti-racist machines</title>
        <description>&lt;p&gt;Pretrained large language models have been popular and successful in deep learning the last few years.
Unfortunately, the training process is data-hungry and these models are trained on uncurated data from the internet.
Furthermore, these models are deployed in a zero-shot manner for commercial applications, despite the original intention to use them as “pretrained” models.
This means we are likely commercializing models whose behavior we have very few assurances about - given certain prompts, they could insult humans, spread disinformation, perpetuate systemic racism, encourage suicide, and more.&lt;/p&gt;

&lt;p&gt;For this post, I’ll discuss the case of training an anti-racist language model, a particularly salient problem which has been &lt;a href=&quot;https://www.technologyreview.com/2020/12/10/1013617/racism-data-science-artificial-intelligence-ai-opinion/&quot;&gt;discussed&lt;/a&gt; &lt;a href=&quot;https://faculty.washington.edu/ebender/papers/Stochastic_Parrots.pdf&quot;&gt;a&lt;/a&gt; &lt;a href=&quot;https://www.nytimes.com/2021/03/15/technology/artificial-intelligence-google-bias.html&quot;&gt;lot&lt;/a&gt;, but the principles apply more broadly.&lt;/p&gt;

&lt;h4 id=&quot;filtering&quot;&gt;Filtering&lt;/h4&gt;
&lt;p&gt;One very compelling and practical fix is to filter the training dataset – if we remove racist documents, then perhaps the model should never have learned how to write racist materials.
But even if we take a pretrained language model with racist content filtered out, a user can still give it the prompt “Write me an essay about [overtly racist thesis]”.  Whether it does well on this task will depend on how well it generalizes from having seen essays, statements similar to the thesis in question, etc.&lt;/p&gt;

&lt;h4 id=&quot;fine-tuning&quot;&gt;Fine-tuning&lt;/h4&gt;
&lt;p&gt;Instead, we could keep all the racist training data, and treat pretraining as “learning knowledge”, then have a second finetuning phase for “learning behavior”.
Concretely, during finetuning, we might give the language model some training signal that encourages it to argue against the racist thesis upon receiving that prompt.&lt;/p&gt;

&lt;h4 id=&quot;comparison&quot;&gt;Comparison&lt;/h4&gt;

&lt;p&gt;The fine-tuning approach seems more difficult, in a couple ways.
You must procure high-quality finetuning data, likely involving humans in the loop.
You must make difficult calls on the desired language model behavior (you have to do this for filtering too, but arguably you could just be very conservative).
But filtering is effectively sidestepping important issues that need to be confronted - what is the actual distribution of behaviors you did want?  What happens if those behaviors scarcely appear in the pretraining dataset, or if people disagree on what behaviors are desired?
As a very imperfect analogy, if you want to raise an anti-racist kid, you should teach them about racism and then teach them how to combat it, rather than shelter them from racism in the first place.&lt;/p&gt;

&lt;h4 id=&quot;the-long-view&quot;&gt;The long view&lt;/h4&gt;

&lt;p&gt;I think as deep learning techniques/models get better, the (easier) filtering type solutions work less well, while finetuning like solutions work increasingly well.&lt;/p&gt;

&lt;p&gt;Filtering will work less well, since pretrained models will get better at generalization and inferring the intent behind the racist essay, even if they have not seen similar intents in pretraining.
Finetuning will work better, since models will become more data-efficient for finetunes, and infer the values we are trying to impart more quickly.&lt;/p&gt;

&lt;h4 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;So fine-tuning seems better to me in principle.
That said, I don’t have strong opinions about what solutions should be implemented today to fix model behaviors, and our pretraining data clearly needs improvement.
But overall, having imperfect solutions to these hard problems and then iterating and improving methodology slowly seems better to me than ignoring them, so it feels appealing to me to work on fine-tuning.&lt;/p&gt;

&lt;p&gt;I am personally fairly excited about doing these things today:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;A lot more explicit thinking about our values and behaviors we want in models&lt;/li&gt;
  &lt;li&gt;Working on good fine-tuning approach for eliciting those behaviors&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Sat, 15 May 2021 17:18:32 +0000</pubDate>
        <link>http://wuthejeff.com//machinelearning/ethics/2021/05/15/filtering-vs-finetuning.html</link>
        <guid isPermaLink="true">http://wuthejeff.com//machinelearning/ethics/2021/05/15/filtering-vs-finetuning.html</guid>
        
        
        <category>machinelearning</category>
        
        <category>ethics</category>
        
      </item>
    
      <item>
        <title>Smart TODO scheduling</title>
        <description>&lt;p&gt;I would like an app where the main interface is extremely minimal: in big font, it tells me what I should do.&lt;/p&gt;

&lt;p&gt;Whenever there’s something I would like to do later, I simply speak to the app - it parses my request and reorganizes my schedule.  Similarly, I can ask the app questions about previous time spent.&lt;/p&gt;

&lt;p&gt;The app should be dead simple to use, and give you the best of todo lists, calendars, time-tracking apps, and more.&lt;/p&gt;

&lt;details&gt;
  &lt;summary&gt;
    &lt;h2 id=&quot;motivation-premeditated-planning&quot;&gt;Motivation: premeditated planning&lt;/h2&gt;
  &lt;/summary&gt;
  &lt;p&gt;In general, I often find myself with free time and no particular idea of what I should do.
On the other hand, occasionally I think of things which aren’t habitual, but that I should be doing more of, e.g. calling my family.
But when the free time comes along, it takes much more effort to remember things I should be doing.
Ideally, I should premeditate about how I’d like to spend my time, and then later act faithfully on that without with low cognitive overhead.&lt;/p&gt;

  &lt;p&gt;You can imagine yourself in two possible modes, “CEO” and “worker”.  Most time is spent in worker mode, doing things you decided in CEO mode.
(You might switch fluidly between the two modes, but ideally not too much.)
To facilitate this, we use software:  CEO me enters a list of tasks (and priorities and deadlines) into some app, and worker me repeatedly does &lt;em&gt;whatever the app says&lt;/em&gt;.
The app is my boss, but since I program it, I’m my own boss.&lt;/p&gt;
&lt;/details&gt;

&lt;details&gt;
  &lt;summary&gt;
    &lt;h2 id=&quot;advantages-over-existing-solutions&quot;&gt;Advantages over existing solutions&lt;/h2&gt;
  &lt;/summary&gt;

  &lt;p&gt;Absorbing the functionality of both todo lists and calendars gives additional advantages.
Fundamentally, this is because both are tracking ways you should spend time.
Here are some examples:&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;When I add an event, it can tell me what the marginal time would’ve been used for.  Is that acquaintance’s birthday party really better than an hour of running or playing music? This is especially useful for people who tend to over-schedule themselves.&lt;/li&gt;
    &lt;li&gt;There’s less cognitive overhead if only using a single mechanism to decide what to do.  When I have todo list only for unstructured time, it’s hard to make a habit of following it.  If that list is also your calendar, you might find it easier to stick to.&lt;/li&gt;
    &lt;li&gt;It’s easy to see overviews of your time spent, if it’s all in one place.  So time-tracking comes nearly for free.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/details&gt;

&lt;details&gt;
  &lt;summary&gt;
    &lt;h2 id=&quot;idealized-interface-details&quot;&gt;Idealized interface details&lt;/h2&gt;
  &lt;/summary&gt;

  &lt;p&gt;Here’s an idealized version of the app I imagine, at a high level.
I think it’s quite hard to implement well (&lt;strong&gt;Update&lt;/strong&gt;: 5 years later, I think this is highly doable), but there is a large spectrum of simpler versions.&lt;/p&gt;

  &lt;h3 id=&quot;basic-actions&quot;&gt;Basic actions&lt;/h3&gt;

  &lt;p&gt;There are three main classes of actions, &lt;strong&gt;Plan&lt;/strong&gt;, &lt;strong&gt;Do&lt;/strong&gt;, and &lt;strong&gt;Reflect&lt;/strong&gt;, corresponding to the life cycle of tasks.
The default screen is a “Do” screen.
But you can prompt the app with queries to either plan new tasks or reflect on past tasks, in which case the app may show relevant information, such as a calendar.
When you exit a planning/reflecting session, it goes back to the “Do” screen.&lt;/p&gt;

  &lt;details&gt;
    &lt;summary&gt;
      &lt;h3 id=&quot;plan&quot;&gt;&lt;strong&gt;Plan&lt;/strong&gt;&lt;/h3&gt;
    &lt;/summary&gt;

    &lt;p&gt;You can add and edit tasks, in natural language, like:&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;I’d like to sleep about 8 hours a day.  I never need more than 9 hours and always need at least 6&lt;/li&gt;
      &lt;li&gt;I’d like to go for a 30 minute run on days with no other exercise planned, preferably in the morning.  Then I should shower right after.&lt;/li&gt;
      &lt;li&gt;I should make an doctor’s appointment every April and then enter the appointment time as a new task afterwards&lt;/li&gt;
      &lt;li&gt;I’d like to get eggs and milk the next time I’m at the grocery store&lt;/li&gt;
      &lt;li&gt;I have dinner with Bob on Friday at 6 PM, at his apartment&lt;/li&gt;
      &lt;li&gt;Move my meeting with Eve to 8 PM&lt;/li&gt;
      &lt;li&gt;I’d like to attend Saturday book club every other month, instead of every month&lt;/li&gt;
      &lt;li&gt;Every day before sleeping, I should rate how happy my day was.&lt;/li&gt;
      &lt;li&gt;I’d like to sleep 15 extra minutes per day, for the next 2 months.  In 2 months, set an event for me to compare happiness before and after.&lt;/li&gt;
      &lt;li&gt;I’d like to reflect and plan my time every Sunday morning.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;The app may ask clarifying questions, that you can optionally respond to.&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;em&gt;How long do you take to shower?&lt;/em&gt;&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;You’re already busy on Friday 6 PM with Alice’s birthday party.  Would you like to skip that?&lt;/em&gt;&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;It can also just comment.&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;em&gt;You will lose one hour of piano practice time.&lt;/em&gt;&lt;/li&gt;
    &lt;/ul&gt;

  &lt;/details&gt;

  &lt;details&gt;
    &lt;summary&gt;
      &lt;h3 id=&quot;do&quot;&gt;&lt;strong&gt;Do&lt;/strong&gt;&lt;/h3&gt;
    &lt;/summary&gt;

    &lt;p&gt;There’s a screen that tells you what to do.  You can either select Done or Skip.&lt;/p&gt;

    &lt;p&gt;If you mark the task “Done”, you can optionally enter additional feedback/notes&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;I was unable to finish this essay tonight.  It will take me another 2 hours or so.&lt;/li&gt;
      &lt;li&gt;I finished this 15 minutes ago, and spent the last 15 minutes going to the gas station&lt;/li&gt;
      &lt;li&gt;Alice’s party was not as cool as I expected&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;If you “Skip”, which is by default discouraged, you can/should enter a justification&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;I only have 10 minutes before I’m getting picked up&lt;/li&gt;
      &lt;li&gt;I’m at the mall, this task should be done at home&lt;/li&gt;
      &lt;li&gt;I don’t have the energy or willpower to exercise&lt;/li&gt;
    &lt;/ul&gt;

  &lt;/details&gt;

  &lt;details&gt;
    &lt;summary&gt;
      &lt;h3 id=&quot;reflect&quot;&gt;&lt;strong&gt;Reflect&lt;/strong&gt;&lt;/h3&gt;
    &lt;/summary&gt;

    &lt;p&gt;It’s easy to query about tasks, which is useful during planning&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;Show all planned exercise in the next month&lt;/li&gt;
      &lt;li&gt;What are the next few times I plan to see either Alice or Bob?&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;And easy to query about time spent&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;Show me a summary of time spent in the last week.&lt;/li&gt;
      &lt;li&gt;Show me a graph of time spent exercising, week by week.&lt;/li&gt;
      &lt;li&gt;What tasks do I skip often?&lt;/li&gt;
      &lt;li&gt;What tasks do I want to do, but don’t have time for?&lt;/li&gt;
      &lt;li&gt;Show me tasks that took longer than I expected&lt;/li&gt;
    &lt;/ul&gt;

  &lt;/details&gt;

  &lt;details&gt;
    &lt;summary&gt;
      &lt;h3 id=&quot;bells-and-whistles&quot;&gt;Bells and whistles&lt;/h3&gt;
    &lt;/summary&gt;

    &lt;p&gt;Obviously this app is not entirely fleshed out.  For example:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;You’d want integration with Google Calendar and have notifications for event-type items&lt;/li&gt;
      &lt;li&gt;You should be able to attaching notes or subtasks to existing tasks
        &lt;ul&gt;
          &lt;li&gt;Add “buy bananas” to my shopping list&lt;/li&gt;
          &lt;li&gt;Add “Increase leisure time” to my next planning session&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;It would be good to use location services in a smart way, if the user desires it&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;The list of feature requests is probably endless :)&lt;/p&gt;

    &lt;p&gt;Also, some suggestions for the name of such an app:&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;Lachesis or Decima, the second of the Three Fates who measured and apportioned the thread of life.&lt;/li&gt;
      &lt;li&gt;Remembear, in the spirit of Beeminder (if the Fates are too serious!)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/details&gt;

&lt;/details&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I would be very happy if someone implemented something like this.  If you are interested, please let me know!&lt;/p&gt;
</description>
        <pubDate>Mon, 03 Dec 2018 00:00:00 +0000</pubDate>
        <link>http://wuthejeff.com//productivity/2018/12/03/smart-scheduling.html</link>
        <guid isPermaLink="true">http://wuthejeff.com//productivity/2018/12/03/smart-scheduling.html</guid>
        
        
        <category>productivity</category>
        
      </item>
    
      <item>
        <title>Differential privacy and data poisoning</title>
        <description>&lt;p&gt;This is an elaboration upon &lt;a href=&quot;https://cstheory.stackexchange.com/questions/39350/differential-privacy-and-data-poisoning&quot;&gt;my stackoverflow question&lt;/a&gt;.&lt;/p&gt;

&lt;h1 class=&quot;no_toc&quot; id=&quot;contents&quot;&gt;Contents&lt;/h1&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#idea&quot; id=&quot;markdown-toc-idea&quot;&gt;Idea&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#justifying-a-weak-threat-model&quot; id=&quot;markdown-toc-justifying-a-weak-threat-model&quot;&gt;Justifying a weak threat model&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#example&quot; id=&quot;markdown-toc-example&quot;&gt;Example&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#preliminary-analysis&quot; id=&quot;markdown-toc-preliminary-analysis&quot;&gt;Preliminary analysis&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-big-picture&quot; id=&quot;markdown-toc-the-big-picture&quot;&gt;The big picture&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#data-poisoning-in-the-wild&quot; id=&quot;markdown-toc-data-poisoning-in-the-wild&quot;&gt;Data poisoning in the wild&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#the-rise-of-user-data&quot; id=&quot;markdown-toc-the-rise-of-user-data&quot;&gt;The rise of user data&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;idea&quot;&gt;Idea&lt;/h2&gt;

&lt;p&gt;A differentially private algorithm takes datasets containing inputs and produces randomized outputs, such that no small change in the dataset can shift the distribution of outputs by too much.
This is normally discussed in the context of privacy - when you observe the output, you cannot infer anything about a given input.
But it also implies that an attacker with control over just a single input cannot effectively poison the data to change outcomes.&lt;/p&gt;

&lt;h2 id=&quot;justifying-a-weak-threat-model&quot;&gt;Justifying a weak threat model&lt;/h2&gt;

&lt;p&gt;One might say this is useful only in a very weak threat model, compared to, say, a model in which a constant fraction of (or even &lt;a href=&quot;https://arxiv.org/abs/1611.02315&quot;&gt;most&lt;/a&gt;) inputs can be poisoned.
Generally, it’s against the security mindset to weaken threat models in order to get guarantees.
However, this problem seems more difficult than typical security problems, and I suspect the current real-world baselines have essentially no guarantees.&lt;/p&gt;

&lt;p&gt;So the critical assumption would be that it’s costly to create new inputs.
But one typical case to want a differential privacy guarantee for is when the unit that the datasets are being measured with respect to is a user of a service, e.g. collaborative filtering settings.
In these settings, account creation is often costly, in which case this model might be reasonable.&lt;/p&gt;

&lt;h3 id=&quot;example&quot;&gt;Example&lt;/h3&gt;

&lt;p&gt;Consider the Netflix dataset, with ~100M ratings from ~500K users, to ~20K movies.
In this case, the average movie has only 5K ratings.
Thus 1% of users being adversarial would negate any real signals - i.e. many malicious users rating a single movie well to boost it may be indistinguishable from normal behavior (if they rate other movies in a plausible way).&lt;/p&gt;

&lt;p&gt;A realistic threat model for Netflix might reasonably assume costly account creation.
So the number of poisoned ratings for a given movie is at least proportional to the cost to the attacker.&lt;/p&gt;

&lt;p&gt;This sugggests a more practical attack - a single user giving bad ratings to all but one movie.
This sort of attack would be mitigated by differential privacy.&lt;/p&gt;

&lt;h3 id=&quot;preliminary-analysis&quot;&gt;Preliminary analysis&lt;/h3&gt;

&lt;p&gt;Formally, \((\epsilon, \delta)\) differential privacy says that the increase in probability when changing the dataset by one user, is limited to a multiplicative blowup of \(e^{\epsilon}\) and additive blowup of \(\delta\).&lt;/p&gt;

&lt;p&gt;It’s easy to see that:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Any \((\epsilon, 0)\) differentially private algorithm has the property of group privacy, which says a group of size \(g\) can blow up outcome probabilities by \(e^{g\epsilon}\) instead of \(e^\epsilon\).
  Since cost is assumed to be linear in group size, this would be reasonable for small \(g\epsilon\), in which case \(e^{g\epsilon} \approx 1 + g\epsilon\).&lt;/li&gt;
  &lt;li&gt;A \((0, \delta)\) differentially private algorithm would also limit a group’s damage to an additive \(g\delta\), which is exactly what you’d want.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This simple analysis is not particularly compelling.  Some simple rebuttals:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;The attacker gets to choose \(g\) and thus \(g\epsilon\) can’t be assumed to be small.&lt;/li&gt;
  &lt;li&gt;It’s not easy to actually get \(\epsilon = 0\) for any useful algorithm.
And if both \(\epsilon\) and \(\delta\) are non-zero, the guarantee for large \(g\) will be even worse.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nevertheless, this is enough to convince me that we may be able to engineer systems in which data poisoning attacks aren’t scalable.
Some points for hope:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It’s possible that for particular algorithms, we can get better analysis for \(g &amp;gt; 1\) than by naively composing guarantees.
The &lt;a href=&quot;https://arxiv.org/pdf/1607.00133.pdf&quot;&gt;moment’s accountant technique&lt;/a&gt; gives an example of this, although they are analyzing composition of algorithms (which is entirely different from composition of the guarantee for group size).&lt;/li&gt;
  &lt;li&gt;We can hope for a guarantee that only holds when \(g &amp;lt; \alpha n\), for some fraction \(\alpha\) of all users.
Then when a group is larger than \(\alpha n\), we can explicitly detect them via other means (e.g. look at the patterns of account creation, or detected outliers by using verifiable points).
In other words, “large” threats can be delegated to something outside of the differentially private algorithm.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, this still leaves a lot to be desired.
It’s not clear to me how good a guarantee one could achieve in theory or practice.
But it seems promising enough to be a worthwhile idea to explore.&lt;/p&gt;

&lt;h2 id=&quot;the-big-picture&quot;&gt;The big picture&lt;/h2&gt;

&lt;h3 id=&quot;data-poisoning-in-the-wild&quot;&gt;Data poisoning in the wild&lt;/h3&gt;

&lt;p&gt;Historically, I think Google search is the most prevalent example of a single algorithm trained on external data whose outputs are extremely important.
And guess what?
The SEO industry spends over $50 billion a year trying to deliberately change the inputs of this algorithm in order to change the outputs.
Note that Google can’t do anything about people creating new websites and spurious links on them.
However, they’ve spent lots of effort using a diversified set of signals to make their algorithms more robust, as well as more explicit combatting of &lt;a href=&quot;http://www.wordstream.com/black-hat-seo&quot;&gt;“Black Hat” SEO techniques&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Other examples of data poisoning:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Market manipulation to affect stock prices&lt;/li&gt;
  &lt;li&gt;Fake news in Facebook’s news feed algorithm&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So it seems clear to me that whenever a sufficiently important algorithm is trained on data that can be manipulated, such manipulation will occur.&lt;/p&gt;

&lt;h3 id=&quot;the-rise-of-user-data&quot;&gt;The rise of user data&lt;/h3&gt;

&lt;p&gt;Companies like Amazon, Facebook and Google are collecting huge amounts of data on individual users.
Already, much fuss is made about protecting honest user data.
Privacy conscious users will often take inconvenient measures to hide their data entirely from such companies.
These companies would suffer large PR mishaps if they leaked large amounts of sensitive user data.&lt;/p&gt;

&lt;p&gt;Now, these companies are increasingly turning this data into useful services (shopping recommendations, Youtube recommendations, news feed personalization, etc).
Based on the previous section, the obvious conclusion is that as these services become more important, we will see increasingly many attempts at poisoning their datasets.
If they’re not already, I suspect these companies will have to combat such techniques, possibly by making their algorithms robust to poisoned datasets.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;So in addition to protecting honest data, algorithms should &lt;em&gt;protect against&lt;/em&gt; dishonest data!
It turns out these goals are related and aligned, and differential privacy can potentially be a good solution to both.&lt;/p&gt;

</description>
        <pubDate>Sun, 29 Oct 2017 19:35:32 +0000</pubDate>
        <link>http://wuthejeff.com//privacy/security/machine-learning/2017/10/29/differential-privacy-and-data-poisoning.html</link>
        <guid isPermaLink="true">http://wuthejeff.com//privacy/security/machine-learning/2017/10/29/differential-privacy-and-data-poisoning.html</guid>
        
        
        <category>privacy</category>
        
        <category>security</category>
        
        <category>machine-learning</category>
        
      </item>
    
      <item>
        <title>Git &apos;open&apos; aliases</title>
        <description>&lt;p&gt;Recently, I made some aliases for opening files within a git repo.&lt;/p&gt;

&lt;p&gt;They’re pretty simple, but they’ve affected my workflow a lot - I nearly never open files &lt;em&gt;without&lt;/em&gt; using a git alias anymore.&lt;/p&gt;

&lt;p&gt;After explaining to a coworker what the git commands “mop” and “shop” meant, they said I should share these with others.
Though I’m sure someone else has thought of this, a quick Google search didn’t turn up anything.  So here they are!&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# These go in your .gitconfig under the [alias] heading

# open file by name
op = &quot;!f() { $(git editor) $(git ls-files | grep -i \&quot;$@\&quot;); }; f&quot;

# open currently edited (unstaged) files
eop = &quot;! $(git editor) $(git ls-files --modified)&quot;

# open files for conflicts (good for rebase/cherry-pick/merge)
mop = &quot;!f() { $(git editor) $(git diff --name-only --diff-filter=U); }; f&quot;

# open files present in diff
dop = &quot;!f() { $(git editor) $(git diff --name-only $@); }; f&quot;

# grep and open files containing
gop = &quot;!f(){ $(git editor) $(git grep --name-only \&quot;$@\&quot;); }; f&quot;

# &quot;show and open&quot; commit
shop = &quot;!f() { $(git editor) $(git show --pretty=\&quot;format:\&quot; --name-only $1); }; f&quot;

# open on github (requires hub)
hop = &quot;!f() { hub browse -- blob/master/$(git find $@ | head -n 1); }; f&quot;

# fuzzy aliases require fzf (added 2016/8/12)

# fuzzy open by name, takes no argument
zop = &quot;!f() { \
  local file=$(git ls-files $(git rev-parse --show-toplevel) | fzf -m); \
  if [[ -z $file ]]; then return 1; fi; \
  $(git editor) $file; \
}; f&quot;

# fuzzy grep (does only one file), takes no argument
zgop = &quot;!f() { \
  local raw_selection=$(git grep -n &apos;.*&apos; | fzf); \
  if [[ -z $raw_selection ]]; then return 1; fi; \
  local selection=${raw_selection%:*}; \
  local file=${selection%:*}; \
  local line=${selection##*:}; \
  $(git editor) +\&quot;$line\&quot; \&quot;$file\&quot;; \
}; f&quot;

editor = config --get core.editor
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;NOTE: These aliases only work with editors that take separate filenames as arguments and opens all of them.
I think vim and emacs both work though, so that should cover many users.&lt;/p&gt;

&lt;p&gt;For those curious, my full list of aliases can be found &lt;a href=&quot;https://github.com/WuTheFWasThat/dotfiles/blob/master/gitconfig&quot;&gt;here&lt;/a&gt;.
Please let me know if you have other useful git aliases!&lt;/p&gt;
</description>
        <pubDate>Wed, 29 Jun 2016 17:18:32 +0000</pubDate>
        <link>http://wuthejeff.com//programming/git/productivity/2016/06/29/git-open-aliases.html</link>
        <guid isPermaLink="true">http://wuthejeff.com//programming/git/productivity/2016/06/29/git-open-aliases.html</guid>
        
        
        <category>programming</category>
        
        <category>git</category>
        
        <category>productivity</category>
        
      </item>
    
      <item>
        <title>Cheating in game simulations</title>
        <description>&lt;h1 id=&quot;intro&quot;&gt;Intro&lt;/h1&gt;

&lt;p&gt;Suppose you’re writing a simulation for a strategy game in which you’d like to compare how different strategies fare.  
You might require that the strategies satisfy an API like the following (in Go):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;type Strategy interface {
    // Tell me what player i am, and tell me the initial board state
    initialize(view GameStateView, player int)
    // Decide what i should do, in a given game state
    decide(view GameStateView) Play
    // Process some game event out of the player&apos;s control, e.g. player&apos;s play
    process(view GameStateView, event Event)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;problems&quot;&gt;Problems&lt;/h2&gt;

&lt;h3 id=&quot;1-out-of-band-communication&quot;&gt;1. Out-of-band communication&lt;/h3&gt;

&lt;p&gt;This setup is fine for chess, but if the game involves partial information and the potential for collaboration (in my case, Hanabi), you can easily cheat:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var external_state *ExternalState = new(ExternalState)

type CheatingStrategy struct {
    internal_state *InternalState
}
func (s *CheatingStrategy) initialize(view GameStateView, player int) {
    s.internal_state = newInternalState(view, player)
}
func (s *CheatingStrategy) decide(view GameStateView) {
    // Perfectly fine code
    stuff := s.internal_state.get_stuff()
    decision := some_logic(view, stuff)
    // Cheat!  Read/mutate external state
    partner_cards := external_state.get_partner_cards()
    external_state.tell_partner(s.internal_states.my_cards)
    decision = changed_my_mind(view, partner_cards, decision)
    return decision
}
func (s *CheatingStrategy) process(view GameStateView, event Event) {
    // Could cheat here too
    ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This cheating is possible because Go lets you have &lt;strong&gt;shared mutable state&lt;/strong&gt;. It’s the equivalent of bridge partners playing footsies under the table.&lt;/p&gt;

&lt;p&gt;If the state weren’t shared, it would be merely internal state, e.g. the inner workings of a bridge player’s mind, which is fine.&lt;/p&gt;

&lt;p&gt;If the state weren’t mutable, it just means that Strategies may have fixed contracts ahead of time, e.g. bridge conventions.
But any nontrivial strategy will &lt;em&gt;automatically&lt;/em&gt; have contracts with other instantiations of itself.
(I use bridge as an example, because it’s clearly not considered cheating.
 But I’ve heard people argue this sort of thing is against the spirit of Hanabi.
 Could be - but I like the game more both theoretically and in practice when allowing it!)&lt;/p&gt;

&lt;h3 id=&quot;2-direct-hacking-attempt&quot;&gt;2. Direct hacking attempt&lt;/h3&gt;
&lt;p&gt;Notice also, you can also attempt to cheat like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    // another attempt to cheat
    view.score += 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So to be safe, the simulator shouldn’t use the GameStateView after giving it away to the strategy.
This is likely to be an implementation annoyance and inefficiency, since the simulator will need to repeatedly produce deep copies of parts of the game state.&lt;/p&gt;

&lt;h2 id=&quot;solutions&quot;&gt;Solutions&lt;/h2&gt;

&lt;p&gt;Obviously you can always cheat by storing things in a file or remote database.
So let’s imagine an in-memory, network-less sandbox.
Interestingly, there are two quite different solutions.&lt;/p&gt;

&lt;h3 id=&quot;solution-1-functional-programming&quot;&gt;Solution 1: Functional programming&lt;/h3&gt;

&lt;p&gt;A pure functional language will make it much harder or impossible to cheat, by disallowing mutability. Here’s the strategy API, in Haskell&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Strategy state where
    initialize :: Player -&amp;gt; GameStateView -&amp;gt; state
    -- Decide what player i should do, in a given game state
    decide :: Player -&amp;gt; GameStateView -&amp;gt; state -&amp;gt; (state, Play)
    -- Process some game event out of the player&apos;s control, e.g. player&apos;s play
    process :: Player -&amp;gt; GameStateView -&amp;gt; Event -&amp;gt; state -&amp;gt; state
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Shared mutable state automatically became impossible, thanks to Haskell’s purity!
The decide and process functions aren’t allowed to have side effects.
As a bonus, mutating GameStateView became impossible, too.&lt;/p&gt;

&lt;p&gt;Note: A Haskell proramming would actually probably not write it like this, but you get the point&lt;/p&gt;

&lt;h3 id=&quot;solution-2-rust&quot;&gt;Solution 2: Rust&lt;/h3&gt;

&lt;p&gt;Until pretty recently, using a functional programming language might have been the only option. But along came Rust:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Shared mutable state is evil. So functional programming languages thought: let’s have no mutable state. So Rust thought: let’s have no sharing of state.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rust happens to be the language I was playing around with, for this Hanabi simulation business. Here’s my strategy API:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pub trait Strategy {
    fn new(&amp;amp;GameStateView, &amp;amp;Player) -&amp;gt; Self;
    fn decide(&amp;amp;mut Self, &amp;amp;GameStateView) -&amp;gt; TurnChoice;
    fn update(&amp;amp;mut Self, &amp;amp;GameStateView, &amp;amp;Turn);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Again, shared mutable state becomes impossible&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, thanks to Rust’s ownership system!
And again, as a bonus, mutating the GameStateView becomes impossible - you have to have a mutable reference to do so.&lt;/p&gt;

&lt;p&gt;For those interested, my project is &lt;a href=&quot;https://github.com/WuTheFWasThat/hanabi.rs&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Okay. I lied - it’s still possible, but made harder and highly discouraged. And you could tweak the language to disallow it (getting rid of Cell/Arc/Mutex), which is the important point. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 06 Mar 2016 17:18:32 +0000</pubDate>
        <link>http://wuthejeff.com//programming/2016/03/06/cheating-in-game-simulations.html</link>
        <guid isPermaLink="true">http://wuthejeff.com//programming/2016/03/06/cheating-in-game-simulations.html</guid>
        
        
        <category>programming</category>
        
      </item>
    
      <item>
        <title>Homomorphic encryption</title>
        <description>&lt;h1 class=&quot;no_toc&quot; id=&quot;contents&quot;&gt;Contents&lt;/h1&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#honoring-goldwasser-and-micali&quot; id=&quot;markdown-toc-honoring-goldwasser-and-micali&quot;&gt;Honoring Goldwasser and Micali&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#intro-to-encryption&quot; id=&quot;markdown-toc-intro-to-encryption&quot;&gt;Intro to encryption&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#history&quot; id=&quot;markdown-toc-history&quot;&gt;History&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#encryption&quot; id=&quot;markdown-toc-encryption&quot;&gt;Encryption&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#decryption&quot; id=&quot;markdown-toc-decryption&quot;&gt;Decryption&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#summary&quot; id=&quot;markdown-toc-summary&quot;&gt;Summary&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#homomorphic-encryption&quot; id=&quot;markdown-toc-homomorphic-encryption&quot;&gt;Homomorphic encryption&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#motivation&quot; id=&quot;markdown-toc-motivation&quot;&gt;Motivation&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#definition&quot; id=&quot;markdown-toc-definition&quot;&gt;Definition&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#homomorphic&quot; id=&quot;markdown-toc-homomorphic&quot;&gt;Homomorphic?&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#history-1&quot; id=&quot;markdown-toc-history-1&quot;&gt;History&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#a-homomorphic-encryption-scheme&quot; id=&quot;markdown-toc-a-homomorphic-encryption-scheme&quot;&gt;A homomorphic encryption scheme&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#somewhat-homomorphic-encryption&quot; id=&quot;markdown-toc-somewhat-homomorphic-encryption&quot;&gt;Somewhat homomorphic encryption&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#bootstrapping&quot; id=&quot;markdown-toc-bootstrapping&quot;&gt;Bootstrapping&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#aftermath&quot; id=&quot;markdown-toc-aftermath&quot;&gt;Aftermath&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;honoring-goldwasser-and-micali&quot;&gt;Honoring Goldwasser and Micali&lt;/h2&gt;

&lt;p&gt;Shafi Goldwasser and Silvio Micali won the Turing Award recently, for their foundational work in cryptography.  
I had the pleasure of working with Silvio (as his TA and as his student) while at MIT,
where he gave many of the most memorable and motivated lectures I’ve been part of.&lt;/p&gt;

&lt;p&gt;In their honor, I’m writing a post which tries to teach some cryptography, to an even less technical audience.
The topic I chose was Gentry’s construction of homomorphic encryption, for a few reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It was a huge breakthrough in cryptography&lt;/li&gt;
  &lt;li&gt;It has a very nice proof idea&lt;/li&gt;
  &lt;li&gt;I believe it can be well-illustrated to one with just high-school level math background
(though I may not succeed at it)&lt;/li&gt;
  &lt;li&gt;I’ve not seen a similar explanation attempted.
(In particular, I’ve not heard Micali lecture about it)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;intro-to-encryption&quot;&gt;Intro to encryption&lt;/h2&gt;

&lt;p&gt;Before we can talk about homomorphic encryption, we should talk about regular encryption.&lt;/p&gt;

&lt;h3 id=&quot;history&quot;&gt;History&lt;/h3&gt;

&lt;p&gt;Encryption in one form or another has been used for thousands of years.
Notably, governments used ciphers to pass war messages.&lt;/p&gt;

&lt;p&gt;In the 70s, it became much more commonplace, thanks to RSA, the famous encryption scheme
which was developed by and named after another group of Turing award winners.
(TAing for famous computer scientists is my main claim to fame, as I also did so for the R of RSA, Rivest.)
Half a decade &lt;em&gt;later&lt;/em&gt;, Micali and Goldwasser formally defined security for such schemes.&lt;/p&gt;

&lt;p&gt;Today, we’ll need only a very basic presentation.&lt;/p&gt;

&lt;h3 id=&quot;encryption&quot;&gt;Encryption&lt;/h3&gt;

&lt;p&gt;Say we start with a message, call it \(m\).  Like so:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/m.png&quot; alt=&quot;A message&quot; /&gt;&lt;/p&gt;

&lt;p&gt;An encrypted message is just a message that is locked up so other’s cant read it.
The message is not physically locked up, but is scrambled to look like complete gibberish.
I’ll denote an encrypted message by drawing a circle around the original message:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/em.png&quot; alt=&quot;An encrypted message&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encrypting&lt;/strong&gt; a message is the process of putting a lock around the message.
The “lock” is actually a function you apply, called an encryption function.  &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/encrypt.png&quot; alt=&quot;Encrypt!&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We’ll denote the encrpyted version of the message \(m\) by \(E(m)\).
The function \(E\) is depicted by the lock.  The arrow depicts function application.&lt;/p&gt;

&lt;h3 id=&quot;decryption&quot;&gt;Decryption&lt;/h3&gt;

&lt;p&gt;Now, a lock is not a lock without a key!
With a certain secret key, this lock can be removed, and the message can be recovered!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/decrypt.png&quot; alt=&quot;Decryption&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Decryption is also a function, call it \(D\).
But in addition to a message, it also requires a secret key, \(k\).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/functions.png&quot; alt=&quot;Our functions&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Crucially, decryption has the property that \(D(E(m), k) = m\).
The picture makes it more obvious:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/encryptdecrypt.png&quot; alt=&quot;Decryption&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Equally important is that without this secret key \(k\), the message becomes very hard to recover.  
The function \(D\) is publicly known, but if you feed it the wrong key, you get gibberish back out.&lt;/p&gt;

&lt;p&gt;As far as we can tell, you need to use brute force, which takes an impractically long time.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/insecure.png&quot; alt=&quot;Security breach&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Note that &lt;em&gt;encryption does not require the secret key&lt;/em&gt;.
We call this “asymmetric” encryption.
This asymmetry is very useful in the real world.
For example, it lets me send a secret message to someone I don’t know, without knowing their key.&lt;/p&gt;

&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;

&lt;p&gt;Encryption and decryption are fundamental to all security and privacy on the internet.
In fact, RSA remains extremely practical and commonplace -
if the security of the scheme were compromised, it would have a major impact on the world.
Until then, it puts the S in HTTPS!&lt;/p&gt;

&lt;h2 id=&quot;homomorphic-encryption&quot;&gt;Homomorphic encryption&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Homomorphic encryption&lt;/strong&gt; is a different beast.  &lt;/p&gt;

&lt;h3 id=&quot;motivation&quot;&gt;Motivation&lt;/h3&gt;

&lt;p&gt;Suppose Alice has a lot of private data, like her family’s sequenced genome, on a hard drive.
But now she wants to search through it, or perform some more complicated algorithm on it.  
Unfortunately, her laptop isn’t powerful enough to run the whole computation.
Bob offers an excellent cloud service for processing genomes.
In fact, his proprietary algorithm is much better for extracting relevant information
than the open-source algorithm Alice was thinking to run.
But Alice doesn’t want to give away her genome to someone she doesn’t know.
What does she do?&lt;/p&gt;

&lt;p&gt;To solve this problem, we need something magical.&lt;/p&gt;

&lt;h3 id=&quot;definition&quot;&gt;Definition&lt;/h3&gt;

&lt;p&gt;In general, suppose Alice wishes to apply some arbitrary function, \(f\), to some data, \(m\).  
Unfortunately, \(f\) can only be computed by Bob, perhaps because it is computationally expensive.
However, Alice wishes for Bob not to see \(m\).
So how can she get from \(m\) to \(f(m)\)?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/homomorphictry.png&quot; alt=&quot;This doesn&apos;t work&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Homomorphic encryption essentially lets you take encrypted inputs, and apply some function to get an encrypted output.&lt;/p&gt;

&lt;p&gt;More precisely, homomorphic encryption is an encryption scheme, with an additional property.  
For any function \(f\), you can easily transform it into a “homomorphic” version of the function, call it \(f^*\).  
This transformation has the “homomorphic” property that \(f^*(E(m)) = E(f(m))\), for any message \(m\).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/homomorphicapply.png&quot; alt=&quot;Homomorphic function application&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Of course, if you have a decryption key \(k\), this transformation from \(f\) to \(f^*\) is easy.
Simply decrypt, apply \(f\), and re-encrypt!
Formally, let \(f^*(x) = E(f(D(x, k)))\).
Then, if \(x = E(m)\), we have \(f^*(E(m)) = E(f(D(E(m), k))) = E(f(m))\), as desired.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/fapply.png&quot; alt=&quot;Easy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But in homomorphic encryption, the security of the original scheme is not compromised.
So Bob is not allowed to use the key to accomplish this.
After all, he is recovering \(m\) as an intermediate step, and could peek at it then.&lt;/p&gt;

&lt;p&gt;In homomorphic encryption, he must compute a function on inputs he can’t even see, r
esulting in an output he can’t see either!
And this can be done for &lt;em&gt;any&lt;/em&gt; function \(f\).
The homomorphic property really is magical.&lt;/p&gt;

&lt;p&gt;Now, assuming Bob has this way of transforming a function \(f\)  into a homomorphic one \(f^*\),
here’s how Alice would get \(f(m)\):  &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/alicebob.png&quot; alt=&quot;Magic&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Alice generates a secret, \(k\), and takes her data \(m\), and encrypt it, to get \(E(m)\).  &lt;/li&gt;
  &lt;li&gt;Alice hands \(E(m)\) to Bob, and tells him a function \(f\) she’d like to compute on it.&lt;/li&gt;
  &lt;li&gt;As far as Bob can tell, \(E(m)\) is gibberish, since he doesn’t know \(k\).
However, he transforms \(f\) into its homomorphic version, \(f^*\)&lt;/li&gt;
  &lt;li&gt;Bob uses his super computer to apply \(f^*\) to \(E(m)\), producing \(f^*(E(m)) = E(f(m))\).  &lt;/li&gt;
  &lt;li&gt;Bob hands \(E(f(m))\) to Alice, who then decrypts with her key: \(D(E(f(m)), k) = f(m)\)!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In fact, if homomorphic encryption is possible, then Alice can even make the function itself secret.
That is, she wants Bob to neither know \(f\) nor \(m\), and yet to compute \(f(m)\) for her!
Can you see how?  (Hint: it involves something called a Universal Turing Machine)&lt;/p&gt;

&lt;h3 id=&quot;homomorphic&quot;&gt;Homomorphic?&lt;/h3&gt;

&lt;p&gt;Now that you know what encryption is, and what homomorphic encryption is,
you may be wondering what “homomorphic” means.
In math, a homomorphism is a structure-preserving map.
So “homomorphic” is a fancy way to say that it completes this diagram:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/homomorphic.png&quot; alt=&quot;Homomorphism&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The homomorphic property lets us take the function \(f\) into a version of it that operates
in an encrypted version of the world.&lt;/p&gt;

&lt;h3 id=&quot;history-1&quot;&gt;History&lt;/h3&gt;

&lt;p&gt;Homomorphic encryption is an incredibly useful tool, and is considered a holy grail of cryptography.  
While tons of encryption schemes were known by the 70s, nobody knew how to construct a homomorphic one.  
Often times, when things are too good to be true, theoreticians go ahead and prove it so.
But nobody could show a homomorphic scheme was impossible either!  
So even with plenty of geniuses were thinking about it, homomorphic encryption
was a huge question mark for 30 years.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;… drumroll&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;a-homomorphic-encryption-scheme&quot;&gt;A homomorphic encryption scheme&lt;/h2&gt;

&lt;p&gt;Finally in 2009, Craig Gentry produced a candidate homomorphic encryption scheme.  &lt;/p&gt;

&lt;h3 id=&quot;somewhat-homomorphic-encryption&quot;&gt;Somewhat homomorphic encryption&lt;/h3&gt;

&lt;p&gt;Coming up with a homomorphic encryption scheme is difficult, but
it turns out coming up with a &lt;strong&gt;somewhat&lt;/strong&gt; homomorphic scheme is not so hard.&lt;/p&gt;

&lt;p&gt;In a somewhat homomorphic scheme, each time you apply the homomorphic version of a function,
the quality of the encryption gets a bit worse.&lt;/p&gt;

&lt;p&gt;Imagine you could change the contents inside the lock, but the shape of the lock gets a little bit warped.  
The more complicated the function, the more warped the lock would get.  
For a while, the key might still be able to open the lock, but eventually,
when the lock is too damaged, the key would stop working.  &lt;/p&gt;

&lt;p&gt;To illustrate, I’ll use green circles to denote locks that can still be unlocked, and red circles to denote locks that are hopeless.  
So a dark green circle is a perfectly fine encryption:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/greendecrypt.png&quot; alt=&quot;Good decryption&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But a red one makes it so even a key can’t recover a message:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/reddecrypt.png&quot; alt=&quot;Bad decryption&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now suppose we wanted to go from \(m\) to \(m + 6\), by repeatedly adding one.  
So, we let \(f(x) = x + 1\), use the homomorphic property to get \(f^*\), and apply repeatedly.
What happens is this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/worsen.png&quot; alt=&quot;Decryption worsening&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Recall that the homomorphic property is that \(f^*(E(m)) = E(f(m))\).
Let \(E_x(m)\) represent an encryption with \(x\) amount of warpedness.
So \(E_0(m)\) would represent a fresh encryption and \(E_6(m)\) might represent a irrecoverable encryption.
The somewhat homomorphic property then says \(f^*(E_x(m)) = E_{x+y}(f(m))\),
where the value of \(y\) depends on how complicated \(f\) is.&lt;/p&gt;

&lt;p&gt;So I can homomorphically add 2 or 3, but not 6!
This “somewhat homomorphic” property seems not so useful.
But this was Gentry’s first step in obtaining a fully homomorphic scheme.
So where do we go from here?  &lt;/p&gt;

&lt;h3 id=&quot;bootstrapping&quot;&gt;Bootstrapping&lt;/h3&gt;

&lt;p&gt;Suppose we had a way to “refresh” a bad encryption back into a good encryption.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/refresh.png&quot; alt=&quot;Refresh&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Then we could add 6 by simply adding 3, refreshing, then adding 3 again.
More generally, we could decompose complicated functions
into many simple functions, and refresh the encryptions
after applying each simple function.&lt;/p&gt;

&lt;p&gt;Here’s where an amazing idea called &lt;strong&gt;bootstrapping&lt;/strong&gt; comes in.
First, the picture:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/bootstrap.png&quot; alt=&quot;Bootstrapping!&quot; /&gt;&lt;/p&gt;

&lt;p&gt;What the hell is going on here?&lt;/p&gt;

&lt;p&gt;Basically, we’re putting a fresh lock on the outside, and then unlocking the &lt;em&gt;inner&lt;/em&gt; lock.
Unfortunately, when we do so, the outer lock will get a bit warped.  
But if it’s better than the original lock, then we’ve made progress!  &lt;/p&gt;

&lt;p&gt;But wait a minute, didn’t we cheat by using the key?
Well, not quite.  We used the homomorphic version of the encryption function, which looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/homomorphicdecrypt.png&quot; alt=&quot;Homomorphic decrypt&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So Bob only needs an &lt;em&gt;encrypted&lt;/em&gt; version of the key.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/encryptedkey.png&quot; alt=&quot;Encrypted key&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Is this safe?
Cryptographers still believe this is okay, and that Bob can’t recover the key or message.
It’s a bit like breaking into a house, where you know there’s a copy of the key inside the house.
The fact that there’s a key inside doesn’t really help you, when you’re on the outside to begin with.&lt;/p&gt;

&lt;p&gt;To break the bootstrapping process down in more detail:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;We start with an encryption that is getting close to unusable, \(E_4(m)\).&lt;/li&gt;
  &lt;li&gt;We encrypt this encryption, freshly!  
So now, it is weirdly encrypted twice, as \(E_0(E_4(m))\).
Bob can do this due to the asymmetric nature of encryption.&lt;/li&gt;
  &lt;li&gt;We now &lt;em&gt;homomorphically&lt;/em&gt; apply the decryption function!  
Remember, this means a function is magically applied to the inner contents.
In this case, what’s inside is an encryption, and the function is decryption.  
So the result is that our original message sits inside just one lock!
Mathematically:
\(D^*(E_0(E_4(m)), k^*) = E_2(D(E_4(m), k)) = E_2(m)\)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The picture, again:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/homomorphic/bootstrap.png&quot; alt=&quot;Bootstrapping!&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So this bootstrapping process turns a somewhat homomorphic encryption scheme into a “fully” homomorphic one,
simply by doing this refreshing process repeatedly during our computation.
And that’s it.  Take a moment to understand - it’s really quite beautiful!&lt;/p&gt;

&lt;h3 id=&quot;aftermath&quot;&gt;Aftermath&lt;/h3&gt;

&lt;p&gt;Plenty of technical work went into making the decryption function simple enough
that the resulting lock wasn’t worse off than the beginning.
But after Gentry’s original paper, the somewhat homomorphic schemes and decryption functions
have actually been substantially simplified.
The biggest key idea that opened the research floodgates was the bootstrapping.&lt;/p&gt;

&lt;p&gt;So this amazing trick makes it so that we can now have someone blindly apply arbitrary functions to encrypted data.  
Unfortunately, this same trick makes the schemes impractically slow.
The bootstrapping procedure is expensive and must be ran often,
and nobody has figured out how to get rid of it.
But research in this area has accelerating, and cryptographers are now working on bringing this dream to reality.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Imagine a world where&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;cloud email services like Gmail could search through your mail for you without being able reading it,
so you would never have to worry about the NSA pressuring Google into giving away sensitive information.&lt;/li&gt;
  &lt;li&gt;voters could vote electronically without worrying about privacy
(this is a special case of multi-party secure computation, which is possible with homomorphic encryption)&lt;/li&gt;
  &lt;li&gt;you could give away truly obfuscated source code, but still let others run your algorithm&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Can you imagine ways in which the world might be better off with homomorphic encryption?&lt;/p&gt;
</description>
        <pubDate>Thu, 21 Mar 2013 17:18:32 +0000</pubDate>
        <link>http://wuthejeff.com//computerscience/2013/03/21/homomorphic-encryption.html</link>
        <guid isPermaLink="true">http://wuthejeff.com//computerscience/2013/03/21/homomorphic-encryption.html</guid>
        
        
        <category>computerscience</category>
        
      </item>
    
  </channel>
</rss>
