<?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>Forem: CipherStash</title>
    <description>The latest articles on Forem by CipherStash (@cipherstash).</description>
    <link>https://forem.com/cipherstash</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%2Forganization%2Fprofile_image%2F5898%2Fdb00e947-153a-4226-a9e0-25a1aa592470.png</url>
      <title>Forem: CipherStash</title>
      <link>https://forem.com/cipherstash</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/cipherstash"/>
    <language>en</language>
    <item>
      <title>Fixing a 1-in-256 bug in CLWW order-preserving encryption</title>
      <dc:creator>Dan Draper</dc:creator>
      <pubDate>Sat, 25 Apr 2026 04:32:10 +0000</pubDate>
      <link>https://forem.com/cipherstash/fixing-a-1-in-256-bug-in-clww-order-preserving-encryption-12ld</link>
      <guid>https://forem.com/cipherstash/fixing-a-1-in-256-bug-in-clww-order-preserving-encryption-12ld</guid>
      <description>&lt;p&gt;Many databases let you sort and range-query encrypted data using &lt;em&gt;order-preserving encryption&lt;/em&gt; (OPE): a scheme where ciphertext bytes compare in the same order as their plaintexts, so standard B-tree indexes and &lt;code&gt;ORDER BY&lt;/code&gt; clauses Just Work. A well-known construction is &lt;a href="https://cipherstash.com/papers/practical-ore-clww-2015.pdf" rel="noopener noreferrer"&gt;Chenette-Lewi-Weis-Wu (CLWW)&lt;/a&gt; from 2015 — small, fast, and widely deployed. The paper gives an order-&lt;em&gt;revealing&lt;/em&gt; scheme with a custom comparator, and notes in passing that the same ciphertext bytes can be compared &lt;em&gt;lexicographically&lt;/em&gt; to yield an order-&lt;em&gt;preserving&lt;/em&gt; scheme as a side benefit.&lt;/p&gt;

&lt;p&gt;But that reinterpretation is only almost right. Roughly 1 in 256 comparisons disagrees with the true plaintext order. In this post I'll walk through why, with a worked example, and show how two small changes to the encoding eliminate the residual — at the cost of one extra byte per ciphertext and a single arithmetic pass.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This post walks through the construction and the intuition. If you want the full derivation — triangular probability distributions, the signal/noise argument, empirical verification, and a discussion of what the scheme leaks — head over to the companion engineering note: &lt;a href="https://cipherstash.com/research/backward-carry-ope" rel="noopener noreferrer"&gt;Exact OPE from CLWW ORE via Backward Carry + MSB-Bit Placement&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why order-preserving encryption?
&lt;/h2&gt;

&lt;p&gt;When you encrypt a column in a database with a standard symmetric cipher — AES-GCM, ChaCha20, pick your favourite — you get great confidentiality. You also lose every other useful property of the column. The ciphertext byte order has nothing to do with the plaintext order, so your B-tree index, your &lt;code&gt;ORDER BY&lt;/code&gt; clauses, and your range queries (&lt;code&gt;WHERE price BETWEEN 100 AND 500&lt;/code&gt;) stop working entirely.&lt;/p&gt;

&lt;p&gt;Order-preserving encryption fixes this, at a cost. In an OPE scheme, if plaintext &lt;code&gt;x &amp;lt; y&lt;/code&gt;, then &lt;code&gt;enc(x) &amp;lt; enc(y)&lt;/code&gt; under the standard comparison your database already understands — usually byte-lexicographic compare, i.e. &lt;code&gt;memcmp&lt;/code&gt;. Drop these ciphertexts into any off-the-shelf sorted index and range scans work out of the box. No custom comparator. No query-rewriting middleware.&lt;/p&gt;

&lt;p&gt;To make that concrete, here's a handful of 8-bit integer plaintexts alongside illustrative ciphertexts — the bytes are made up rather than produced by running the scheme, but they follow its rules (9 bytes each, reserved leading byte, shared prefix where the high-order plaintext bits agree, first differing byte offset by ~128). Only the first 6 of 9 bytes are shown:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plaintext&lt;/th&gt;
&lt;th&gt;Ciphertext (hex)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;7&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;00 5e 38 12 9a 2c …&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;42&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;00 5e 38 92 3f c4 …&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;100&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;00 5e b8 4c 92 3f …&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;200&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;00 de 7a 23 51 8c …&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;250&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;00 de 7a a3 ff 22 …&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Plaintexts in ascending order produce ciphertexts in ascending byte-lexicographic order: &lt;code&gt;memcmp&lt;/code&gt; over any two rows returns the same verdict as comparing the plaintexts directly. Drop these into a B-tree index and &lt;code&gt;ORDER BY&lt;/code&gt; / range queries work out of the box. You can also see the scheme's leakage profile hiding in plain sight — the closer two plaintexts' high-order bits are, the more leading bytes their ciphertexts share. More on that in a minute.&lt;/p&gt;

&lt;p&gt;The cost is leakage. A scheme that preserves order also leaks order (tautologically), and typically a bit more — usually some information about the common prefix of two plaintexts. For many workloads that tradeoff is acceptable; for others you'd reach for a construction with a tighter leakage profile, like the Lewi–Wu &lt;a href="https://github.com/cipherstash/ore.rs" rel="noopener noreferrer"&gt;Block ORE scheme&lt;/a&gt; — which is what CipherStash uses for most production paths, exposed to Postgres through &lt;a href="https://github.com/cipherstash/encrypt-query-language" rel="noopener noreferrer"&gt;EQL&lt;/a&gt;. Block ORE needs a custom comparator, which in Postgres means registering a custom operator class via &lt;code&gt;CREATE OPERATOR CLASS&lt;/code&gt; / &lt;code&gt;CREATE OPERATOR FAMILY&lt;/code&gt;. Some managed platforms permit those statements without superuser (AWS RDS does, which is why EQL runs there today); others don't (Supabase, as of writing). When you're on a platform in the latter category, CLWW OPE is the next best thing — standard lex-compare on the ciphertext works with any stock B-tree index, no custom operator class required. I'll touch on what CLWW specifically leaks toward the end.&lt;/p&gt;

&lt;h2&gt;
  
  
  CLWW in 60 seconds
&lt;/h2&gt;

&lt;p&gt;CLWW is a bit-by-bit ORE scheme. For an n-bit plaintext &lt;code&gt;p = b₀ b₁ … bₙ₋₁&lt;/code&gt; (MSB-first), it produces an n-byte ciphertext. The construction feeds the plaintext bits through a keyed hash function one bit at a time — we'll model that keyed hash as a &lt;em&gt;pseudorandom function&lt;/em&gt; (PRF), a function whose output is indistinguishable from uniform random bytes to anyone who doesn't have the key. In practice that's HMAC-SHA256, BLAKE3 in keyed mode, or similar; our implementation uses BLAKE3. At each step we pull one PRF byte and add the plaintext bit to it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F578v1nj6giqubr7hfqep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F578v1nj6giqubr7hfqep.png" alt="CLWW ORE flow diagram cᵢ = (PRFᵢ + bᵢ) mod 256" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The arrows between the PRF boxes are the important part. &lt;code&gt;PRFᵢ&lt;/code&gt; depends on all the plaintext bits &lt;code&gt;b₀ … bᵢ₋₁&lt;/code&gt; that came before it. So for two plaintexts X and Y that first differ at bit k:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At positions 0 through k, the PRF inputs are identical in both plaintexts, so &lt;code&gt;PRFᵢ^X = PRFᵢ^Y&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;At positions k+1 onward, the chain has diverged (one side saw &lt;code&gt;bₖ = 0&lt;/code&gt;, the other saw &lt;code&gt;bₖ = 1&lt;/code&gt;), so the PRFs look independent-random.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the first differing byte itself, then, the ciphertexts differ by exactly &lt;code&gt;b_k^Y − b_k^X&lt;/code&gt;, which is &lt;code&gt;+1&lt;/code&gt; or &lt;code&gt;−1&lt;/code&gt;. The native CLWW comparator exploits this: find the first differing byte, check whether &lt;code&gt;c_Y ≡ c_X + 1 (mod 256)&lt;/code&gt;. If yes, X &amp;lt; Y; otherwise Y &amp;lt; X. Note the &lt;code&gt;mod 256&lt;/code&gt; in that check — we'll come back to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The paper's OPE reinterpretation — and the 1/256 bug
&lt;/h2&gt;

&lt;p&gt;Section 3.2 of the CLWW paper observes that the ciphertext bytes agree up to the first differing byte, and at that byte one side is exactly one more than the other. So if you forget about the custom comparator and just sort the ciphertexts lexicographically, you'll usually get the right answer.&lt;/p&gt;

&lt;p&gt;"Usually" is doing a lot of work there.&lt;/p&gt;

&lt;p&gt;Consider X = 0 and Y = 1 as 8-bit plaintexts. Bits of X are &lt;code&gt;0000 0000&lt;/code&gt;; bits of Y are &lt;code&gt;0000 0001&lt;/code&gt;. The PRF chain for Y sees only zeros up to bit 6, so &lt;code&gt;PRF₀ … PRF₇&lt;/code&gt; are identical in both plaintexts. Every ciphertext byte agrees, except byte 7 — which encodes the one differing bit.&lt;/p&gt;

&lt;p&gt;Now imagine &lt;code&gt;PRF₇ = 0xFF&lt;/code&gt;. A 1-in-256 event.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Byte&lt;/th&gt;
&lt;th&gt;PRF&lt;/th&gt;
&lt;th&gt;X's bit&lt;/th&gt;
&lt;th&gt;Y's bit&lt;/th&gt;
&lt;th&gt;&lt;code&gt;c^X&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;c^Y&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0–6&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PRFᵢ&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PRFᵢ&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PRFᵢ&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0xFF&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0xFF&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;(0xFF + 1) mod 256 = 0x00&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Lex compare: bytes 0 through 6 agree, byte 7 has &lt;code&gt;0x00&lt;/code&gt; on the Y side and &lt;code&gt;0xFF&lt;/code&gt; on the X side. The comparator says Y &amp;lt; X. The plaintext says Y &amp;gt; X. Wrong answer.&lt;/p&gt;

&lt;p&gt;The CLWW comparator handles this case because its check is &lt;code&gt;c_Y ≡ c_X + 1 (mod 256)&lt;/code&gt;, which is true for &lt;code&gt;(0xFF, 0x00)&lt;/code&gt; as well as for &lt;code&gt;(0x42, 0x43)&lt;/code&gt;. Lex compare doesn't have the mod-256 awareness — when the byte wraps around, the ordering flips.&lt;/p&gt;

&lt;p&gt;Per-comparison error rate: &lt;code&gt;1/256 ≈ 3.9 × 10⁻³&lt;/code&gt;. For a range scan touching a few thousand ciphertexts, that's multiple mis-orderings per query. Unacceptable.&lt;/p&gt;

&lt;h2&gt;
  
  
  First fix: backward carry
&lt;/h2&gt;

&lt;p&gt;Here's the key reframe: instead of thinking of the ciphertext as a byte stream, think of it as a big-endian integer. When &lt;code&gt;PRFₖ + bₖ&lt;/code&gt; wraps past 256, we don't lose the &lt;code&gt;+1&lt;/code&gt; — we propagate it as an arithmetic carry to the byte on the left, exactly like schoolbook long addition. We reserve a leading byte at the top of the ciphertext to absorb any carry that makes it all the way up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;encrypt_ope_v1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;hasher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;keyed_hasher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Pass 1: generate PRF bytes, record the plaintext bits.
&lt;/span&gt;    &lt;span class="n"&gt;prfs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;bit&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;bits_msb_first&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;prfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hasher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next_byte&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;hasher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Pass 2: compute P + B as an (n+1)-byte big-endian integer,
&lt;/span&gt;    &lt;span class="c1"&gt;# with a reserved leading byte that absorbs the final carry.
&lt;/span&gt;    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;prfs&lt;/span&gt;
    &lt;span class="n"&gt;carry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;carry&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;
        &lt;span class="n"&gt;carry&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;       &lt;span class="c1"&gt;# always 0 or 1
&lt;/span&gt;    &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;carry&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comparison is plain byte-lex compare — no custom comparator required.&lt;/p&gt;

&lt;p&gt;Let's replay the failing case. X = 0, Y = 1, &lt;code&gt;PRF₇ = 0xFF&lt;/code&gt;. The ciphertext is now 9 bytes (one reserved + eight content).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;X&lt;/strong&gt; (all bits zero): pass 2 adds nothing and no carry propagates.
&lt;code&gt;c^X = [0, PRF₀, …, PRF₆, 0xFF]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Y&lt;/strong&gt; (bit 7 = 1): at byte 8 we compute &lt;code&gt;0xFF + 1 + 0 = 0x100&lt;/code&gt; → byte 8 becomes &lt;code&gt;0x00&lt;/code&gt;, carry out = 1. At byte 7 we compute &lt;code&gt;PRF₆ + 0 + 1 = PRF₆ + 1&lt;/code&gt;, carry out = 0. Other bytes unchanged.
&lt;code&gt;c^Y = [0, PRF₀, …, PRF₅, PRF₆ + 1, 0x00]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lex compare: &lt;code&gt;c^X&lt;/code&gt; and &lt;code&gt;c^Y&lt;/code&gt; agree through byte 6. At byte 7, &lt;code&gt;c^X&lt;/code&gt; has &lt;code&gt;PRF₆&lt;/code&gt; and &lt;code&gt;c^Y&lt;/code&gt; has &lt;code&gt;PRF₆ + 1&lt;/code&gt;. Y is bigger — correctly. ✓&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;+1&lt;/code&gt; didn't disappear when the byte wrapped; it just moved one position to the left, where it reappears at the byte the lex comparator hits first.&lt;/p&gt;

&lt;h2&gt;
  
  
  But wait — this isn't exact
&lt;/h2&gt;

&lt;p&gt;A big improvement, but it turns out this scheme is only &lt;em&gt;almost&lt;/em&gt; right. The per-comparison error rate drops from &lt;code&gt;~1/256&lt;/code&gt; to around &lt;code&gt;7.7 × 10⁻⁶&lt;/code&gt; — about 500× better — but it's still not zero.&lt;/p&gt;

&lt;p&gt;The residual is a signal/noise mismatch. At the first differing byte, the plaintext injects a &lt;code&gt;+1&lt;/code&gt; signal — but the backward carry coming up from the byte to its right can also swing the result by &lt;code&gt;±1&lt;/code&gt;. Signal and noise are the same order of magnitude, so in rare PRF configurations they cancel exactly and the two ciphertexts tie where the plaintexts don't. The full derivation — triangular distributions, tail probabilities, the small correction for the &lt;code&gt;m = 2&lt;/code&gt; case — lives in the &lt;a href="https://cipherstash.com/research/backward-carry-ope" rel="noopener noreferrer"&gt;engineering note&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The question is: can we kill the residual without making the ciphertext larger?&lt;/p&gt;

&lt;h2&gt;
  
  
  Second fix: place the bit at the MSB
&lt;/h2&gt;

&lt;p&gt;The signal-vs-noise framing suggests the obvious move: make the signal bigger. We can't shrink the noise — &lt;code&gt;±1&lt;/code&gt; per byte is intrinsic to how the carry works — but we &lt;em&gt;can&lt;/em&gt; inject the plaintext bit at a higher-weight position within its byte.&lt;/p&gt;

&lt;p&gt;Concretely: instead of adding &lt;code&gt;+bit&lt;/code&gt; (which puts the signal at bit 0 of the byte, weight 1), add &lt;code&gt;+bit · 128&lt;/code&gt; (which puts it at bit 7, weight 128). Same ciphertext size. Same PRF chain. One line of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-    total = out[i + 1] + bits[i]       + carry
&lt;/span&gt;&lt;span class="gi"&gt;+    total = out[i + 1] + bits[i] * 128 + carry
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The signal is now &lt;code&gt;+128&lt;/code&gt; at the first differing byte. The carry noise is still &lt;code&gt;±1&lt;/code&gt;. They can't cancel — lex compare resolves at the first differing byte by a margin of at least 127 (or, if that byte happens to wrap and the carry propagates one position left, at the byte before it, which sits at 256× the integer weight and so dominates anyway). The &lt;a href="https://cipherstash.com/research/backward-carry-ope" rel="noopener noreferrer"&gt;engineering note&lt;/a&gt; has the full case analysis.&lt;/p&gt;

&lt;p&gt;Exact OPE. Verified empirically: 1 310 700 adjacent &lt;code&gt;u16&lt;/code&gt; pairs under 20 randomly sampled keys, zero ordering errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;Two small changes — a backward carry pass with a reserved byte, and placing the plaintext bit at the top bit of its byte rather than the bottom — turn CLWW's paper-suggested OPE reinterpretation from a ~1/256-wrong scheme into an exact one. Same number of PRF evaluations, one extra ciphertext byte, no custom comparator needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this gives you&lt;/strong&gt;: drop-in ciphertexts for any ordered index or sort operation, with ordering that matches plaintext ordering exactly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it doesn't give you&lt;/strong&gt;: strict-ORE-level leakage hiding (the scheme leaks first-differing-bit position, same as CLWW ORE), and no decryption — for round-trip you pair the OPE ciphertext with an authenticated symmetric cipher like AES-GCM.&lt;/p&gt;

&lt;p&gt;The implementation lives in our &lt;a href="https://crates.io/crates/cllw-ore" rel="noopener noreferrer"&gt;&lt;code&gt;cllw-ore&lt;/code&gt; crate&lt;/a&gt; on crates.io, with a fuller derivation of the error rate and the exactness argument in the &lt;a href="https://cipherstash.com/research/backward-carry-ope" rel="noopener noreferrer"&gt;engineering note&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you've got a production encrypted-database use case that needs order-preserving indexes — or you just enjoy small clean cryptographic primitives — I'd love to hear what you think.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>computerscience</category>
      <category>database</category>
      <category>security</category>
    </item>
    <item>
      <title>Show Dev: Introducing Protect.js</title>
      <dc:creator>Dan Draper</dc:creator>
      <pubDate>Fri, 14 Mar 2025 00:59:31 +0000</pubDate>
      <link>https://forem.com/cipherstash/show-dev-introducing-protectjs-53al</link>
      <guid>https://forem.com/cipherstash/show-dev-introducing-protectjs-53al</guid>
      <description>&lt;p&gt;&lt;strong&gt;Protecting data that’s sensitive — such as personal health or financial information — is crucial to building applications that users trust. But getting access control right is a tricky business. Complex requirements and a plethora of tools, as well as performance considerations, can kill dev team productivity.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is why we created &lt;a href="https://github.com/cipherstash/protectjs" rel="noopener noreferrer"&gt;Protect.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Protect turns data access control on its head by protecting data directly. Unlike complex, application-specific frameworks or hand-rolled tools, Protect.js makes building secure, data-driven applications simple so you can deliver services that users trust without slowing down delivery.&lt;/p&gt;

&lt;h2&gt;
  
  
  We rolled the crypto so you don’t have to
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Security experts say you shouldn't roll your own crypto but it's ok, we've done the hard work for you.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Protect’s power comes from the strongest form of access control: encryption. Encryption is rarely considered for the fine-grained protection of data because it's hard to implement, slow, and doesn’t play nicely with other tools in the stack like identity providers or the database. That is, until today.&lt;/p&gt;

&lt;p&gt;Based on the CipherStash encryption SDK and using our revolutionary key management service, &lt;a href="https://cipherstash.com/products/zerokms" rel="noopener noreferrer"&gt;ZeroKMS&lt;/a&gt;, Protect.js unlocks the power of encryption but without the hassle. Protect.js:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Works with any Node.js framework or ORM (like Next.js + Drizzle)&lt;/li&gt;
&lt;li&gt;Is based on AES-256 encryption and uses formally-verified cryptography&lt;/li&gt;
&lt;li&gt;Uses ZeroKMS key management that’s up to 14x faster than AWS KMS&lt;/li&gt;
&lt;li&gt;Supports queries and sorting over encrypted data&lt;/li&gt;
&lt;li&gt;Is so easy to use you can get started in ~under 15-minutes~&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Encryption in use
&lt;/h2&gt;

&lt;p&gt;You’ve probably heard of encryption &lt;em&gt;at rest&lt;/em&gt; or &lt;em&gt;in transit&lt;/em&gt; but these approaches are only part of the story when it comes to effective data protection.&lt;/p&gt;

&lt;p&gt;At-rest and in-transit encryption leave critical gaps in your data’s defenses which can lead to vulnerabilities or accidental leaks and make it harder to reason about whether data is secure, especially when trying to convince customers or an auditor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc8bks0vq0i36891s6u5k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc8bks0vq0i36891s6u5k.png" alt="Encryption in use" width="800" height="581"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Protect.js uses encryption &lt;em&gt;in use&lt;/em&gt; to protect data.&lt;br&gt;
Sensitive data items, like individual email addresses remain protected right up until an authorized end-user needs to read them.&lt;br&gt;
This limits the “surface area” of a potential attack and reduces risk as well as making it easier to demonstrate that data is secure.&lt;/p&gt;

&lt;p&gt;To protect a sensitive database field with Protect.js, you do so via a &lt;strong&gt;protected schema&lt;/strong&gt; definition. To specify that the &lt;code&gt;email&lt;/code&gt; column of the &lt;code&gt;users&lt;/code&gt; table should be encrypted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/protect/schema.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;csTable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;csColumn&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cipherstash/protect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;csTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;csColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, to encrypt a value, pass any schemas you've defined to &lt;code&gt;protect&lt;/code&gt; and call &lt;code&gt;encrypt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/protect/client.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;protect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cipherstash/protect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./schema&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Do this once when your app starts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;protectClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;protect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Encrypt an email address for a configured column and table&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;encryptResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;protectClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secret@squirrel.example&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;column&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out the &lt;a href="https://github.com/cipherstash/protectjs" rel="noopener noreferrer"&gt;Protect.js getting started guide&lt;/a&gt; if you want to jump right into the code. Or read on to learn about some of Protect.js's other capabilities!&lt;/p&gt;

&lt;h3&gt;
  
  
  Key management
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Encryption in use&lt;/em&gt; is similar to the idea of "field" or "row-level" encryption. One of the main differences is in how keys are managed: Encryption in use ensures each value is encrypted by a unique data key.&lt;/p&gt;

&lt;p&gt;I spoke about &lt;a href="https://youtu.be/zjI1qLakD-E?si=sEliLRNK6ZwiuCm_" rel="noopener noreferrer"&gt;why this is a good thing&lt;/a&gt; at BSides SF in 2024.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmejcayj5453bva3zc9v9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmejcayj5453bva3zc9v9.jpg" alt="You cant read the data if you dont have the encryption key" width="702" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even the best encryption tech is useless without good key management.&lt;br&gt;
When using traditional field-level encryption in a web-based application you have 2 options available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A local key (&lt;em&gt;fast but less secure&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;A cloud-based key-management service (&lt;em&gt;secure but slow&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A local key is a secret encryption key (usually stored as an environment variable). This approach uses the &lt;em&gt;same key&lt;/em&gt; to encrypt all data in the application and comes with some nasty security problems. For starters, if an adversary obtains the key, they can use it to access all of the data in your system.&lt;/p&gt;

&lt;p&gt;If you need to update ("rotate") the key you'll need to re-encrypt &lt;em&gt;everything&lt;/em&gt;. More subtle problems can arise too. AES keys are vulnerable to &lt;em&gt;key wear out&lt;/em&gt; which means that if a single key is used to encrypt more than about 4GB, previously encrypted values can be used to &lt;em&gt;recover the key itself&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Key Management Services (KMS) like &lt;a href="https://aws.amazon.com/kms/" rel="noopener noreferrer"&gt;AWS KMS&lt;/a&gt; or &lt;a href="https://learn.microsoft.com/en-us/azure/key-vault/general/overview" rel="noopener noreferrer"&gt;Azure KeyVault&lt;/a&gt; mitigate these problems with a technique called &lt;em&gt;envelope encryption&lt;/em&gt;. Instead of storing an encryption key in an application environment variable, a &lt;em&gt;root_key&lt;/em&gt; is stored within the cloud provider's infrastructure inside a device called a Hardware Security Module (HSM).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu8ee5ojpyrlaepsxvnq8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu8ee5ojpyrlaepsxvnq8.png" alt="Envelope encryption" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To perform an encryption operation, clients must make a request to the key service which returns a randomly generated &lt;em&gt;data key&lt;/em&gt; along with a copy that has itself been encrypted using the &lt;em&gt;root key&lt;/em&gt; (called a &lt;em&gt;wrapped data key&lt;/em&gt;). The &lt;em&gt;data key&lt;/em&gt; is used to encrypt the target value (such as an email address) and discarded with the result stored in the database with the &lt;em&gt;wrapped data key&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Envelope encryption is a big security improvement over a local key but has a major drawback. Because each data key requires a separate HTTP request, performance can be &lt;strong&gt;abysmal&lt;/strong&gt;. To get around this, cloud providers added support for &lt;em&gt;data key caching&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;However, when caching data-keys many of the same problems as using a local-key can arise. Use a single data key to encrypt too much data and you can run into wear-out issues. A compromise of the cache used to store data-keys could lead to a pretty significant data breach.&lt;/p&gt;

&lt;p&gt;Data key caching also means that there is no-longer a &lt;em&gt;1-to-1 mapping&lt;/em&gt; between a data-key and the specific value it was used to encrypt which means we miss out on powerful access-control and auditing capabilities. We'll cover these in a moment!&lt;/p&gt;

&lt;h3&gt;
  
  
  Security or performance: why not both?
&lt;/h3&gt;

&lt;p&gt;To address these problems, Protect.js uses ZeroKMS, which eliminates the performance-security tradeoffs common with traditional KMS. Instead of a single root key, ZeroKMS uses composable pairs of keys to generate data keys. One half of the pair, the &lt;em&gt;client key&lt;/em&gt; is stored by your application and the other, stored by ZeroKMS.&lt;/p&gt;

&lt;p&gt;This technique has a number of security benefits, but most relevant to this discussion is that it now makes it safe to do &lt;em&gt;bulk requests&lt;/em&gt; for data keys. ZeroKMS can generate up to &lt;strong&gt;10,000&lt;/strong&gt; data keys in a single operation.&lt;/p&gt;

&lt;p&gt;To demonstrate the impact on performance of this approach, we've shared some benchmarks below of Protect.js running in a Next.js application with Postgres and Drizzle. Each request fetches 10 user records from a table that have 2 fields encrypted (email and address).&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://app.artillery.io/share/sh_a2775fd02bf981207dd24e2e371b144f3e7792704948ac998ae34e83e28894b3" rel="noopener noreferrer"&gt;first report&lt;/a&gt; shows AWS KMS performance without data-key caching.&lt;br&gt;
It managed an average of 27 and a peak of 44 requests per second.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkj9ltvsxartnaip7limb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkj9ltvsxartnaip7limb.png" alt="Artillery graph of AWS KMS performance" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ZeroKMS managed &lt;a href="https://app.artillery.io/share/sh_75edb9d22a060633bfdce04777ffd60d1bcfc88989393dc38d3a4924b83fc6cd" rel="noopener noreferrer"&gt;7 times the average and 14 times the peak&lt;/a&gt; performance of AWS KMS, with a peak rate of 615 requests/second.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffz6o3inkp2k849nui4hc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffz6o3inkp2k849nui4hc.png" alt="Artillery graph of ZeroKMS performance" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Apdex scores are particularly telling:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frzbwtuvl8vq0tre3wkai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frzbwtuvl8vq0tre3wkai.png" alt="Image description" width="800" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a future post, we'll do a deep dive on how we ran these benchmarks as well as some surprising results.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rust you can trust
&lt;/h3&gt;

&lt;p&gt;Under the hood, Protect.js is &lt;a href="https://crates.io/crates/cipherstash-client" rel="noopener noreferrer"&gt;written in Rust&lt;/a&gt;.&lt;br&gt;
We chose Rust because it's incredibly fast, memory efficient, and has some unique security properties, particularly when it comes to cryptography. Rust is the &lt;em&gt;only&lt;/em&gt; mainstream compiled language that is also memory safe without the need for a garbage collector.&lt;br&gt;
This &lt;strong&gt;eliminates&lt;/strong&gt; the most common type of security vulnerabilities: memory bugs.&lt;/p&gt;

&lt;p&gt;Computerphile has a &lt;a href="https://youtu.be/pTMvh6VzDls?si=PIouKj8H_OIWn-8D" rel="noopener noreferrer"&gt;great video&lt;/a&gt; about Rust and memory safety if you'd like to learn more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quantum resistant, verified cryptography
&lt;/h3&gt;

&lt;p&gt;The low-level cryptographic components of Protect.js use &lt;a href="https://crates.io/crates/aws-lc-rs" rel="noopener noreferrer"&gt;aws-lc-rs&lt;/a&gt;, Amazon’s formally verified cryptography library. Used to mathematically &lt;em&gt;prove&lt;/em&gt; the correctness of software, formal verification is the gold-standard in high-assurance, secure-by-design systems. Protect.js is also designed to be resistant to attacks by a quantum computer should such devices ever become practical.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vitamins for your crypto
&lt;/h3&gt;

&lt;p&gt;At CipherStash, we’re also working on formal verification for other parts of our stack and have created an open source framework, called &lt;a href="https://github.com/cipherstash/vitaminc" rel="noopener noreferrer"&gt;Vitamin C&lt;/a&gt;. Vitamin C is like vitamins for cryptography. It simplifies the writing of high-assurance software by providing secure, highly-scrutinised and tested reusable building blocks.&lt;/p&gt;

&lt;h3&gt;
  
  
  SOC 2 compliant
&lt;/h3&gt;

&lt;p&gt;CipherStash, including the ZeroKMS key service is SOC 2 compliant.&lt;br&gt;
You can learn more in our &lt;a href="https://trust.cipherstash.com/" rel="noopener noreferrer"&gt;trust centre&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s coming next?
&lt;/h2&gt;

&lt;p&gt;We've barely scratched the surface in this post but over the coming weeks we'll share more about what Protect.js can do to make effective data protection easy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Granular control with identity-based context locking&lt;/li&gt;
&lt;li&gt;Searchable encryption with Protect.js and when to use it&lt;/li&gt;
&lt;li&gt;Deep dives on the internals of Protect.js and ZeroKMS&lt;/li&gt;
&lt;li&gt;More benchmarks, code samples, and tutorials for specific use-cases&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Protect sensitive data in just 15 minutes
&lt;/h2&gt;

&lt;p&gt;All there is to do now is give &lt;a href="https://github.com/cipherstash/protectjs" rel="noopener noreferrer"&gt;Protect.js&lt;/a&gt; a try!&lt;br&gt;
Don't forget to star us on Github, too :)&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>encryption</category>
      <category>database</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Verifying Rust Zeroize with Assembly...including portable SIMD</title>
      <dc:creator>Dan Draper</dc:creator>
      <pubDate>Wed, 10 Jan 2024 12:31:13 +0000</pubDate>
      <link>https://forem.com/cipherstash/verifying-rust-zeroize-with-assemblyincluding-portable-simd-2g65</link>
      <guid>https://forem.com/cipherstash/verifying-rust-zeroize-with-assemblyincluding-portable-simd-2g65</guid>
      <description>&lt;p&gt;When writing code that deals with sensitive information like passwords or payment data, it's important to &lt;em&gt;zeroize&lt;/em&gt; memory when you're done with it. Failing to do so can leave sensitive data in memory even after the program is terminated and even end up on disk when the computer uses swap.&lt;/p&gt;

&lt;p&gt;In this post, I'll explain what zeroizing is, why and when you should use it and how to implement it correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is &lt;em&gt;Zeroizing&lt;/em&gt;?
&lt;/h2&gt;

&lt;p&gt;When a sensitive value, say an encryption key, is used in a program it must be stored in memory: either on the stack or in the heap. In either case, even after memory is dropped (or freed, garbage collected etc), the contents may still lurk in the computer - even beyond the life of the program. It is therefore important that such data be cleared before the memory is dropped so that secrets are not leaked to unexpected places.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is Zeroizing important?
&lt;/h2&gt;

&lt;p&gt;The code below demonstrates that even after it has been dropped, data stored in a given memory location can still be read.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;SensitiveData&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  &lt;span class="c1"&gt;// Representing sensitive data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Some mock sensitive data&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sensitive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SensitiveData&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;data_location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sensitive&lt;/span&gt;&lt;span class="py"&gt;.data&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nn"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sensitive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Attempt to read the data back&lt;/span&gt;
    &lt;span class="c1"&gt;// after it has been dropped&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;recovered_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;copy_nonoverlapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="n"&gt;data_location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;recovered_data&lt;/span&gt;&lt;span class="nf"&gt;.as_mut_ptr&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="mi"&gt;16&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Recovered data: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recovered_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code calls creates a mock &lt;code&gt;SensitiveData&lt;/code&gt; value and then calls &lt;code&gt;mem::drop&lt;/code&gt; directly instead of letting Rust do it when the value goes out of scope. Before doing so, it stores the location of the memory that was used for the data as a raw pointer and then uses that location to read back the original contents of the memory.&lt;/p&gt;

&lt;p&gt;While this is a very simple example, it illustrates that just because memory is dropped, data still exists in the system even if the program doesn't care about it anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Zeroize
&lt;/h2&gt;

&lt;p&gt;Zeroizing memory is surprisingly very tricky. Even Rust, famous for memory safety has no formal built-in way to do this. The main challenge is stopping the compiler from optimizing away code that it &lt;em&gt;thinks&lt;/em&gt; is not necessary.&lt;/p&gt;

&lt;p&gt;Let's look at an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib.rs (simd_zeroize)&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nf"&gt;SafeArray&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;SafeArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;consume_and_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Careful! This could overflow!&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="nf"&gt;.into_iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, I have a type called &lt;code&gt;SafeArray&lt;/code&gt; which just wraps a 4-element array of &lt;code&gt;u32&lt;/code&gt;. I've created my own type so that I can implement the &lt;code&gt;Drop&lt;/code&gt; trait in a moment.&lt;/p&gt;

&lt;p&gt;My type has a single function which consumes &lt;code&gt;self&lt;/code&gt; and sums all elements as a u32. Because &lt;code&gt;self&lt;/code&gt; is consumed but not returned it will be dropped. (Be aware that this code could easily cause an addition overflow but I'm intentionally keeping it very simple to limit how much assembly code is generated).&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspecting the compiled code
&lt;/h2&gt;

&lt;p&gt;To really understand what's going on here we can look at the compiled assembly code. I'm working on a Mac and can do this using the &lt;code&gt;objdump&lt;/code&gt; tool. &lt;a href="https://godbolt.org/" rel="noopener noreferrer"&gt;Compiler Explorer&lt;/a&gt; is also a handy tool but doesn't seem to support Arm assembly which is what Rust will use when compiling on Apple Silicon.&lt;/p&gt;

&lt;p&gt;Before looking at the assembly, the code must be compiled in &lt;strong&gt;release&lt;/strong&gt; mode as this will ensure that all of the compiler's target optimizations are applied.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cargo build --release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I'll use &lt;code&gt;objdump&lt;/code&gt; to disassemble the machine code into Arm64 ASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;objdump -d target/debug/libsimd_zeroize.rlib &amp;gt; assembly.s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the &lt;code&gt;assembly.s&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0000000000000000 &amp;lt;ltmp0&amp;gt;:
       0: 00 00 c0 3d   ldr q0, [x0]
       4: 00 b8 b1 4e   addv.4s s0, v0
       8: 00 00 26 1e   fmov    w0, s0
       c: c0 03 5f d6   ret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't worry if you don't know or understand assembly code, we'll focus just on specific instructions for this exercise.&lt;/p&gt;

&lt;p&gt;The line starting with &lt;code&gt;0000000000000000&lt;/code&gt; is the label Rust has given to the &lt;code&gt;consume_and_sum&lt;/code&gt; method and the actual machine instructions are contained below it. These steps load the values from a memory address stored in &lt;code&gt;x0&lt;/code&gt; into a register called &lt;code&gt;q0&lt;/code&gt;, add all 4 values in one step (using the vectorized addv.4s instruction), move the result into an output register and return.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Registers are what the CPU uses to perform most operations so  this code loads data from memory into the register to that an operation can be performed.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Drop
&lt;/h2&gt;

&lt;p&gt;Let's see what happens when we try to implement zeroization when our &lt;code&gt;SafeArray&lt;/code&gt; is dropped.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nb"&gt;Drop&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;SafeArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Demonstration only: Don't do this&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the ASM for the whole program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight armasm"&gt;&lt;code&gt;&lt;span class="nl"&gt;0000000000000000&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;ltmp0&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;:&lt;/span&gt;
       &lt;span class="err"&gt;0:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;   &lt;span class="nv"&gt;ldr&lt;/span&gt; &lt;span class="nv"&gt;q0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
       &lt;span class="err"&gt;4:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;b8&lt;/span&gt; &lt;span class="nv"&gt;b1&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;   &lt;span class="nv"&gt;addv&lt;/span&gt;&lt;span class="mf"&gt;.4&lt;/span&gt;&lt;span class="nv"&gt;s&lt;/span&gt; &lt;span class="nv"&gt;s0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;v0&lt;/span&gt;
       &lt;span class="err"&gt;8:&lt;/span&gt; &lt;span class="mi"&gt;01&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;   &lt;span class="nv"&gt;fmov&lt;/span&gt;    &lt;span class="nv"&gt;w1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;s0&lt;/span&gt;
       &lt;span class="nb"&gt;c&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;a9&lt;/span&gt;   &lt;span class="nv"&gt;stp&lt;/span&gt; &lt;span class="nv"&gt;xzr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;xzr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;10:&lt;/span&gt; &lt;span class="nv"&gt;e0&lt;/span&gt; &lt;span class="mi"&gt;03&lt;/span&gt; &lt;span class="mi"&gt;01&lt;/span&gt; &lt;span class="nv"&gt;aa&lt;/span&gt;   &lt;span class="nv"&gt;mov&lt;/span&gt; &lt;span class="nv"&gt;x0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;x1&lt;/span&gt;
      &lt;span class="err"&gt;14:&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;03&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="nv"&gt;d6&lt;/span&gt;   &lt;span class="nv"&gt;ret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important line is shown below. It uses &lt;code&gt;stp&lt;/code&gt; which stores a pair of registers, in this case the special &lt;em&gt;zero&lt;/em&gt; register, &lt;code&gt;xzr&lt;/code&gt; in the memory pointed to by &lt;code&gt;x0&lt;/code&gt;. In other words, the memory was zeroed! It worked!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight armasm"&gt;&lt;code&gt;       &lt;span class="nb"&gt;c&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;a9&lt;/span&gt;   &lt;span class="nv"&gt;stp&lt;/span&gt; &lt;span class="nv"&gt;xzr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;xzr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But let's not get too excited, yet. We should check that it still works for other types. Changing the code to use &lt;code&gt;u8&lt;/code&gt; instead of &lt;code&gt;u32&lt;/code&gt; (and leaving the drop implementation the same), we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Changed to u8&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nf"&gt;SafeArray&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;SafeArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;consume_and_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Careful! This could overflow!&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="nf"&gt;.into_iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compiles to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight armasm"&gt;&lt;code&gt;&lt;span class="nl"&gt;0000000000000000&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;ltmp0&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;:&lt;/span&gt;
       &lt;span class="err"&gt;0:&lt;/span&gt; &lt;span class="mi"&gt;08&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt;   &lt;span class="nv"&gt;add&lt;/span&gt; &lt;span class="nv"&gt;w8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;lsr&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
       &lt;span class="err"&gt;4:&lt;/span&gt; &lt;span class="mi"&gt;08&lt;/span&gt; &lt;span class="mi"&gt;41&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt;   &lt;span class="nv"&gt;add&lt;/span&gt; &lt;span class="nv"&gt;w8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;lsr&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;
       &lt;span class="err"&gt;8:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;61&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt;   &lt;span class="nv"&gt;add&lt;/span&gt; &lt;span class="nv"&gt;w0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;lsr&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;
       &lt;span class="nb"&gt;c&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;03&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="nv"&gt;d6&lt;/span&gt;   &lt;span class="nv"&gt;ret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks quite different from the earlier version! The compiler is using a totally different approach. This code is doing is a series of additions involving the original value in &lt;code&gt;w0&lt;/code&gt; and its progressively right-shifted versions. After each shift, the shifted value is added to an accumulating sum. The shifts are by 8, 16, and then 24 bits, effectively breaking &lt;code&gt;w0&lt;/code&gt; into four bytes, adding these bytes together, and storing the final sum back into &lt;code&gt;w0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But where is the zeroizing code!?&lt;/em&gt; For some reason the compiler decided that our code to zeroize was irrelevant and optimized it away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoiding unsafe compiler operations
&lt;/h2&gt;

&lt;p&gt;Compilers are complicated pieces of software and are designed to generate code that is optimal for the target architecture. This means their behaviour can sometimes be hard to reason about and, like in the case above, remove code that is important to security in the interests of performance.&lt;/p&gt;

&lt;p&gt;We need a different approach to ensure our attempts to zeroize data don't get optimized away.&lt;/p&gt;

&lt;p&gt;Thankfully, there is already a crate to do this: &lt;a href="https://crates.io/crates/zeroize" rel="noopener noreferrer"&gt;Zeroize&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;I'll add it to my &lt;code&gt;Cargo.toml&lt;/code&gt; with the &lt;code&gt;derive&lt;/code&gt; feature enabled as we'll use that in a moment. I've also added &lt;code&gt;#[no_mangle]&lt;/code&gt; to the &lt;code&gt;drop&lt;/code&gt; which retains symbol names in the generated assembly code and will make things a bit easier to read.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# Cargo.toml&lt;/span&gt;

&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;zeroize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.7.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"derive"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can derive &lt;code&gt;Zeroize&lt;/code&gt; for &lt;code&gt;SafeArray&lt;/code&gt; and call &lt;code&gt;zeroize&lt;/code&gt; in the &lt;code&gt;Drop&lt;/code&gt; implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;zeroize&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Zeroize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Zeroize)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nf"&gt;SafeArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nb"&gt;Drop&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;SafeArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;#[no_mangle]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="nf"&gt;.zeroize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiled assembly is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight armasm"&gt;&lt;code&gt;&lt;span class="nl"&gt;0000000000000000&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;ltmp0&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;:&lt;/span&gt;
       &lt;span class="err"&gt;0:&lt;/span&gt; &lt;span class="nv"&gt;ff&lt;/span&gt; &lt;span class="mi"&gt;43&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;d1&lt;/span&gt;   &lt;span class="nv"&gt;sub&lt;/span&gt; &lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;
       &lt;span class="err"&gt;4:&lt;/span&gt; &lt;span class="mi"&gt;08&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="mi"&gt;08&lt;/span&gt; &lt;span class="mi"&gt;53&lt;/span&gt;   &lt;span class="nb"&gt;lsr&lt;/span&gt; &lt;span class="nv"&gt;w8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
       &lt;span class="err"&gt;8:&lt;/span&gt; &lt;span class="nv"&gt;e8&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;   &lt;span class="nv"&gt;strb&lt;/span&gt;    &lt;span class="nv"&gt;w8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
       &lt;span class="nb"&gt;c&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;09&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="mi"&gt;53&lt;/span&gt;   &lt;span class="nb"&gt;lsr&lt;/span&gt; &lt;span class="nv"&gt;w9&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;
      &lt;span class="err"&gt;10:&lt;/span&gt; &lt;span class="nv"&gt;e9&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;   &lt;span class="nv"&gt;strb&lt;/span&gt;    &lt;span class="nv"&gt;w9&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;14:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt; &lt;span class="mi"&gt;53&lt;/span&gt;   &lt;span class="nb"&gt;lsr&lt;/span&gt; &lt;span class="nv"&gt;w10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;
      &lt;span class="err"&gt;18:&lt;/span&gt; &lt;span class="nv"&gt;ea&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;   &lt;span class="nv"&gt;strb&lt;/span&gt;    &lt;span class="nv"&gt;w10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="nb"&gt;c&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;08&lt;/span&gt; &lt;span class="mi"&gt;01&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt;   &lt;span class="nv"&gt;add&lt;/span&gt; &lt;span class="nv"&gt;w8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w0&lt;/span&gt;
      &lt;span class="err"&gt;20:&lt;/span&gt; &lt;span class="mi"&gt;29&lt;/span&gt; &lt;span class="mi"&gt;01&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt;   &lt;span class="nv"&gt;add&lt;/span&gt; &lt;span class="nv"&gt;w9&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w9&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w10&lt;/span&gt;
      &lt;span class="err"&gt;24:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;01&lt;/span&gt; &lt;span class="mi"&gt;09&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt;   &lt;span class="nv"&gt;add&lt;/span&gt; &lt;span class="nv"&gt;w0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;w9&lt;/span&gt;
      &lt;span class="err"&gt;28:&lt;/span&gt; &lt;span class="nv"&gt;ff&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;   &lt;span class="nv"&gt;strb&lt;/span&gt;    &lt;span class="nv"&gt;wzr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;2&lt;/span&gt;&lt;span class="nb"&gt;c&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;ff&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;   &lt;span class="nv"&gt;strb&lt;/span&gt;    &lt;span class="nv"&gt;wzr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;30:&lt;/span&gt; &lt;span class="nv"&gt;ff&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;   &lt;span class="nv"&gt;strb&lt;/span&gt;    &lt;span class="nv"&gt;wzr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;34:&lt;/span&gt; &lt;span class="nv"&gt;ff&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;   &lt;span class="nv"&gt;strb&lt;/span&gt;    &lt;span class="nv"&gt;wzr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;38:&lt;/span&gt; &lt;span class="nv"&gt;ff&lt;/span&gt; &lt;span class="mi"&gt;43&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;91&lt;/span&gt;   &lt;span class="nv"&gt;add&lt;/span&gt; &lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;
      &lt;span class="err"&gt;3&lt;/span&gt;&lt;span class="nb"&gt;c&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;03&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="nv"&gt;d6&lt;/span&gt;   &lt;span class="nv"&gt;ret&lt;/span&gt;

&lt;span class="nl"&gt;0000000000000040&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;_drop&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;:&lt;/span&gt;
      &lt;span class="err"&gt;40:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;   &lt;span class="nv"&gt;strb&lt;/span&gt;    &lt;span class="nv"&gt;wzr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;44:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="mi"&gt;04&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;   &lt;span class="nv"&gt;strb&lt;/span&gt;    &lt;span class="nv"&gt;wzr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;48:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="mi"&gt;08&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;   &lt;span class="nv"&gt;strb&lt;/span&gt;    &lt;span class="nv"&gt;wzr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;4&lt;/span&gt;&lt;span class="nb"&gt;c&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;   &lt;span class="nv"&gt;strb&lt;/span&gt;    &lt;span class="nv"&gt;wzr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;50:&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;03&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="nv"&gt;d6&lt;/span&gt;   &lt;span class="nv"&gt;ret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a lot more code now but for the most part it is doing the same thing as before (the addition is done over several instructions this time though).&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;important part&lt;/strong&gt; is that we have a &lt;code&gt;Drop&lt;/code&gt; implementation that is correctly zeroizing memory 🎉. As you can see, there is the implementation of the &lt;code&gt;Drop&lt;/code&gt; trait, conveniently labeled &lt;code&gt;&amp;lt;_drop&amp;gt;&lt;/code&gt; (thanks to &lt;code&gt;#[no_mangle]&lt;/code&gt;) but that the zeroizing code has also been included (via &lt;em&gt;inlining&lt;/em&gt;) in the summation code above. In this case, the compiler has used the &lt;code&gt;strb&lt;/code&gt; instruction to store the zero register (&lt;code&gt;wzr&lt;/code&gt;) into each element of our array.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using &lt;code&gt;ZeroizeOnDrop&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The Zeroize crate comes with a marker trait called &lt;code&gt;ZeroizeOnDrop&lt;/code&gt; which works for any &lt;code&gt;Zeroize&lt;/code&gt; type and means I don't have to implement &lt;code&gt;Drop&lt;/code&gt; every time. I can derive &lt;code&gt;ZeroizeOnDrop&lt;/code&gt; instead of using my own &lt;code&gt;Drop&lt;/code&gt; implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;zeroize&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Zeroize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ZeroizeOnDrop&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Zeroize,&lt;/span&gt; &lt;span class="nd"&gt;ZeroizeOnDrop)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nf"&gt;SafeArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Caution!
&lt;/h2&gt;

&lt;p&gt;Implementing &lt;code&gt;Zeroize&lt;/code&gt; alone won't automatically zeroize memory on drop. &lt;code&gt;Zeroize&lt;/code&gt; just implements the &lt;code&gt;zeroize&lt;/code&gt; method to clear memory. The &lt;code&gt;ZeroizeOnDrop&lt;/code&gt; trait must be implemented as well to automatically zeroize when the value is dropped.&lt;/p&gt;

&lt;h2&gt;
  
  
  But...what about Portable SIMD?
&lt;/h2&gt;

&lt;p&gt;But you may also be asking, what is SIMD!?&lt;/p&gt;

&lt;h2&gt;
  
  
  ...um, what is SIMD?
&lt;/h2&gt;

&lt;p&gt;Single Instruction, Multiple Data (SIMD) is a parallel processing paradigm used in computer architecture to enhance performance by executing the same operation simultaneously on multiple data points. This approach is especially effective for tasks that require the same computation to be repeated over a large data set, such as in digital signal processing, image and video processing, and scientific simulations. In my case, I'm using SIMD for high-performance cryptography implementations.&lt;/p&gt;

&lt;p&gt;SIMD architectures achieve this by employing vector processors or SIMD extensions in CPUs, where a single instruction directs the simultaneous execution of operations on multiple data elements within wider registers. For instance, a SIMD instruction could add or multiply pairs of numbers in a single operation, significantly speeding up computations compared to processing each pair sequentially. This method leverages data-level parallelism, different from the traditional sequential execution model, and is a key feature in modern processors to boost computational efficiency and performance.&lt;/p&gt;

&lt;p&gt;For example, with SIMD I can sum 8 arrays of 4 integers in parallel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#![feature(portable_simd)]&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;simd&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Simd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Simd&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nn"&gt;Simd&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="nn"&gt;Simd&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="nn"&gt;Simd&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="nn"&gt;Simd&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sums&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="nf"&gt;.into_iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.reduce&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;dbg!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sums&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// 1 + 2 + 1 + 0&lt;/span&gt;
        &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// 1 + 2 + 2 + 0&lt;/span&gt;
        &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// etc&lt;/span&gt;
        &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neat, huh?!&lt;/p&gt;

&lt;h2&gt;
  
  
  OK, back to Zeroize for SIMD
&lt;/h2&gt;

&lt;p&gt;While the Zeroize crate is awesome, and you should absolutely use it, it doesn't currently have implementations for the forthcoming &lt;a href="https://rust-lang.github.io/portable-simd/core_simd/simd/struct.Simd.html#" rel="noopener noreferrer"&gt;portable SIMD&lt;/a&gt; modules for Rust. Unlike working with SIMD directly, which requires knowledge of the specific CPU architecture you're building for, Portable SIMD abstracts common CPU vectorizations into a universal interface that works on most architectures.&lt;/p&gt;

&lt;p&gt;I've created a type which wraps &lt;code&gt;Simd&amp;lt;u16, 8&amp;gt;&lt;/code&gt;, a vector of 8 &lt;code&gt;u16&lt;/code&gt; values and a simple method that adds 2 values, consuming both.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nf"&gt;MySimd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Simd&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;MySimd&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;#[no_mangle]&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;consume_and_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated assembly is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight armasm"&gt;&lt;code&gt;&lt;span class="nl"&gt;0000000000000000&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;ltmp0&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;:&lt;/span&gt;
       &lt;span class="err"&gt;0:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;   &lt;span class="nv"&gt;ldr&lt;/span&gt; &lt;span class="nv"&gt;q0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
       &lt;span class="err"&gt;4:&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;   &lt;span class="nv"&gt;ldr&lt;/span&gt; &lt;span class="nv"&gt;q1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
       &lt;span class="err"&gt;8:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="mi"&gt;84&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;   &lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="mf"&gt;.8&lt;/span&gt;&lt;span class="nv"&gt;h&lt;/span&gt;  &lt;span class="nv"&gt;v0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;v0&lt;/span&gt;
       &lt;span class="nb"&gt;c&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;01&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;   &lt;span class="nv"&gt;str&lt;/span&gt; &lt;span class="nv"&gt;q0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x8&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;10:&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;03&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="nv"&gt;d6&lt;/span&gt;   &lt;span class="nv"&gt;ret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We just added 8 pairs of numbers in only 5 instructions! Let's try adding a Drop implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nb"&gt;Drop&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;MySimd&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// splat is roughly equivalent to `[0u16; 8]&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="nn"&gt;Simd&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;splat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But oh no! The generated assembly is &lt;strong&gt;identical&lt;/strong&gt;! My drop code was completely ignored 😫.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight armasm"&gt;&lt;code&gt;&lt;span class="nl"&gt;0000000000000000&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;ltmp0&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;:&lt;/span&gt;
       &lt;span class="err"&gt;0:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;   &lt;span class="nv"&gt;ldr&lt;/span&gt; &lt;span class="nv"&gt;q0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
       &lt;span class="err"&gt;4:&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;   &lt;span class="nv"&gt;ldr&lt;/span&gt; &lt;span class="nv"&gt;q1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
       &lt;span class="err"&gt;8:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="mi"&gt;84&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;   &lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="mf"&gt;.8&lt;/span&gt;&lt;span class="nv"&gt;h&lt;/span&gt;  &lt;span class="nv"&gt;v0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;v0&lt;/span&gt;
       &lt;span class="nb"&gt;c&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;01&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;   &lt;span class="nv"&gt;str&lt;/span&gt; &lt;span class="nv"&gt;q0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x8&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;10:&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;03&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="nv"&gt;d6&lt;/span&gt;   &lt;span class="nv"&gt;ret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using &lt;code&gt;unsafe&lt;/code&gt; to be &lt;em&gt;safe&lt;/em&gt;!?
&lt;/h2&gt;

&lt;p&gt;Ironically, the only way we can make this code safely and correctly zero memory that may contain sensitive data is to use some &lt;code&gt;unsafe&lt;/code&gt; operations. The Zeroize crate itself uses two approaches to avoid compiler optimizations removing zeroizing code. I'll use them both here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;atomic&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nb"&gt;Drop&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;MySimd&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nn"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;write_volatile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;zeroed&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nn"&gt;atomic&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;compiler_fence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;atomic&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SeqCst&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before explaining what's going on, let's first see if it works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight armasm"&gt;&lt;code&gt;&lt;span class="nl"&gt;0000000000000000&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;ltmp0&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;:&lt;/span&gt;
       &lt;span class="err"&gt;0:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;e4&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt;   &lt;span class="nv"&gt;movi&lt;/span&gt;&lt;span class="mf"&gt;.2&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="nv"&gt;v0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;0000000000000000&lt;/span&gt;
       &lt;span class="err"&gt;4:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;   &lt;span class="nv"&gt;str&lt;/span&gt; &lt;span class="nv"&gt;q0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
       &lt;span class="err"&gt;8:&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;03&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="nv"&gt;d6&lt;/span&gt;   &lt;span class="nv"&gt;ret&lt;/span&gt;

&lt;span class="nl"&gt;000000000000000c&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;_consume_and_add&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;:&lt;/span&gt;
       &lt;span class="nb"&gt;c&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;   &lt;span class="nv"&gt;ldr&lt;/span&gt; &lt;span class="nv"&gt;q0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;10:&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;   &lt;span class="nv"&gt;ldr&lt;/span&gt; &lt;span class="nv"&gt;q1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;14:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="mi"&gt;84&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;   &lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="mf"&gt;.8&lt;/span&gt;&lt;span class="nv"&gt;h&lt;/span&gt;  &lt;span class="nv"&gt;v0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;v0&lt;/span&gt;
      &lt;span class="err"&gt;18:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;01&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;   &lt;span class="nv"&gt;str&lt;/span&gt; &lt;span class="nv"&gt;q0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x8&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="nb"&gt;c&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;e4&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt;   &lt;span class="nv"&gt;movi&lt;/span&gt;&lt;span class="mf"&gt;.2&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="nv"&gt;v0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;0000000000000000&lt;/span&gt;
      &lt;span class="err"&gt;20:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;   &lt;span class="nv"&gt;str&lt;/span&gt; &lt;span class="nv"&gt;q0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;24:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;   &lt;span class="nv"&gt;str&lt;/span&gt; &lt;span class="nv"&gt;q0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="err"&gt;28:&lt;/span&gt; &lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="mi"&gt;03&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="nv"&gt;d6&lt;/span&gt;   &lt;span class="nv"&gt;ret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two functions represent the &lt;code&gt;consume_and_add&lt;/code&gt; method on &lt;code&gt;MySimd&lt;/code&gt; and the &lt;code&gt;drop&lt;/code&gt; method in the &lt;code&gt;Drop&lt;/code&gt; trait. The top function confusingly denoted by &lt;code&gt;ltmp0&lt;/code&gt; (I'm still not sure why) is the Drop code and it contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight armasm"&gt;&lt;code&gt;       &lt;span class="err"&gt;0:&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="nv"&gt;e4&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt;   &lt;span class="nv"&gt;movi&lt;/span&gt;&lt;span class="mf"&gt;.2&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="nv"&gt;v0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;0000000000000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This moves the special zero value into the vector &lt;code&gt;v0&lt;/code&gt; which was dropped. Because the &lt;code&gt;consume_and_add&lt;/code&gt; method returns a vector, only one of the 2 arguments is actually dropped. You can also see that the same code has been inlined into the &lt;code&gt;consume_and_add&lt;/code&gt; function.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, what's going on here?
&lt;/h2&gt;

&lt;p&gt;Firstly, we're using &lt;a href="https://doc.rust-lang.org/std/ptr/fn.write_volatile.html" rel="noopener noreferrer"&gt;write_volatile&lt;/a&gt; to reliably zero the target memory. The Rust compiler guarantees not to mess with it! Unfortunately, the method is unsafe but its the only way to &lt;em&gt;safely&lt;/em&gt; zero the data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxo9knbjx5gqjap4ivu3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxo9knbjx5gqjap4ivu3.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Secondly, we're using what's called an atomic &lt;a href="https://doc.rust-lang.org/stable/core/sync/atomic/fn.compiler_fence.html" rel="noopener noreferrer"&gt;compiler fence&lt;/a&gt; which tells the compiler it is not allowed to reorganize the memory in question. It doesn't prevent the CPU from doing so in hardware though that is a post for another day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Zeroize
&lt;/h2&gt;

&lt;p&gt;Instead of implementing &lt;code&gt;Drop&lt;/code&gt; I can use my custom &lt;code&gt;Zeroize&lt;/code&gt; implementation and then just implement &lt;code&gt;ZeroizeOnDrop&lt;/code&gt; like we did earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Zeroize&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;MySimd&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;zeroize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nn"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;write_volatile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;zeroed&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nn"&gt;atomic&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;compiler_fence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;atomic&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SeqCst&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;ZeroizeOnDrop&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;MySimd&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Better, safer code
&lt;/h2&gt;

&lt;p&gt;While you may not have this exact problem in your day-to-day code, understanding what's happening under the hood can be instructive. And hopefully lead to better and safer code.&lt;/p&gt;

&lt;p&gt;:wq&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Encrypt(Syd) MeetUp</title>
      <dc:creator>Tia</dc:creator>
      <pubDate>Tue, 02 Aug 2022 05:55:46 +0000</pubDate>
      <link>https://forem.com/cipherstash/encryptsyd-meetup-319a</link>
      <guid>https://forem.com/cipherstash/encryptsyd-meetup-319a</guid>
      <description>&lt;p&gt;We'd love it if you were able to join our community_Encrypt(Syd)_and hope to see you at a meetup soon!&lt;br&gt;&lt;br&gt;
We've got some great talks this month, join online or come say hi IRL - &lt;a href="https://www.meetup.com/en-AU/encrypt-syd/events/dwnrssydclbpb/"&gt;https://www.meetup.com/en-AU/encrypt-syd/events/dwnrssydclbpb/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ekw6xKX6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8boxq55vdu5gqy3zkgwi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ekw6xKX6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8boxq55vdu5gqy3zkgwi.png" alt="Image description" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>encryption</category>
      <category>eventsinyourcity</category>
      <category>learning</category>
      <category>community</category>
    </item>
  </channel>
</rss>
