<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lozi</title>
    <description>The latest articles on DEV Community by Lozi (@0xlozi).</description>
    <link>https://dev.to/0xlozi</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3968658%2Ffb8db326-4cec-4f7c-8d49-97e717f9936f.jpg</url>
      <title>DEV Community: Lozi</title>
      <link>https://dev.to/0xlozi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/0xlozi"/>
    <language>en</language>
    <item>
      <title>Why Rust allows many readers but only One Writer</title>
      <dc:creator>Lozi</dc:creator>
      <pubDate>Tue, 14 Jul 2026 16:53:23 +0000</pubDate>
      <link>https://dev.to/0xlozi/why-rust-allows-many-readers-but-only-one-writer-4b6p</link>
      <guid>https://dev.to/0xlozi/why-rust-allows-many-readers-but-only-one-writer-4b6p</guid>
      <description>&lt;p&gt;While programming in Rust, we stumble across many rules that, at first, are really unfamiliar to begin with.&lt;br&gt;
However, there's a certain rule that, while programming, I face the most: &lt;strong&gt;Multiple Mutable References&lt;/strong&gt;.&lt;br&gt;
It usually happens when you try to pass a variable into a function as a reader, and then pass that same variable as a writer. &lt;strong&gt;C&lt;/strong&gt; or &lt;strong&gt;C++&lt;/strong&gt; will happily compile and let you run the code, but &lt;strong&gt;Rust throws a massive red error in your face!!!.&lt;/strong&gt;&lt;br&gt;
In order to understand why this happens, we have to look at how C programmers dealt with it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pointers
&lt;/h3&gt;

&lt;p&gt;Back in the old days, programming in C was like having everything &lt;strong&gt;at your disposal&lt;/strong&gt;. A pointer was just an address in memory, nothing else. If you wanted to have ten different pointers all pointing at the same byte of &lt;strong&gt;RAM&lt;/strong&gt; (Aliasing) and you wanted three of them for example to simultaneously try to edit that &lt;strong&gt;byte&lt;/strong&gt; (Mutation), the C compiler would say, &lt;strong&gt;"Whatever you say, Boss".&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But this absolute freedom of memory management created &lt;strong&gt;LOTS&lt;/strong&gt; of bugs that kept devs awake for days!!!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Imagine processing bank transactions: Two Threads (workers), Alice and Bob are running at the exact same time:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Alice is reading your account balance in order to deposit $70&lt;/li&gt;
&lt;li&gt;Bob is reading your account balance because you just bought a $30 game&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because C places &lt;strong&gt;almost no restrictions on aliasing and mutation&lt;/strong&gt;, multiple parts of a program can read from and write to the same memory simultaneously. As a result, both workers read your balance and see &lt;strong&gt;$100&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Alice says:&lt;/strong&gt; "Alright: $100 + $70 = $170". And then Alice prepares to write $170&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bob says:&lt;/strong&gt; "$100 - $30 = $70". And then Bob prepares to write $70&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They both put their new numbers into the database. So whichever one writes a millisecond slower &lt;strong&gt;OVERWRITES&lt;/strong&gt; the other. It can make your $70 profit vanish into the void (This is called &lt;strong&gt;Data Race&lt;/strong&gt;)&lt;/p&gt;

&lt;h3&gt;
  
  
  The Single-Thread
&lt;/h3&gt;

&lt;p&gt;Even if you don't use multi threading. C would still shoot you at your own feet. Imagine like you are reading a list of names, right?. Then you have a pointer &lt;strong&gt;looking at the first name (Aliasing)&lt;/strong&gt;. But further down your code, you accidentally tell the program to &lt;strong&gt;add a hundred thousand new names to that list (Mutation).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The computer realizes the current memory array is &lt;strong&gt;too small&lt;/strong&gt; to hold a hundred thousand  new names, so what it does it silently pick up the entire list, moves it into a bigger space in &lt;strong&gt;RAM&lt;/strong&gt;, and &lt;strong&gt;DELETES&lt;/strong&gt; the old one. But your original reading pointer &lt;strong&gt;doesn't know that the program did that!!!!&lt;/strong&gt;. So then It tries to read the next name and reads literal &lt;strong&gt;deleted garbage&lt;/strong&gt;, causing the program to instantly crash. This behavior is called &lt;strong&gt;Iterator Invalidation&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;For decades, language researchers studied these crashes and behaviors. And eventually they realized something profound:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Aliasing by itself is literally &lt;strong&gt;harmless&lt;/strong&gt;: Like if you have a million threads reading a list simultaneously. If nobody changes throughout that time, then &lt;strong&gt;nothing breaks&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Mutation by itself is also &lt;strong&gt;harmless&lt;/strong&gt;: If only &lt;strong&gt;Bob&lt;/strong&gt; is allowed in the room to edit the bank account, then the math is always perfect.
The &lt;strong&gt;crashes&lt;/strong&gt; only happened when &lt;strong&gt;Aliasing&lt;/strong&gt; and &lt;strong&gt;Mutation&lt;/strong&gt; were combined.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The XOR Gate
&lt;/h3&gt;

&lt;p&gt;When Graydon Hoare started building Rust, one of his goals was to eliminate an entire class of memory safety bugs before a program could even run. Rust achieves this by enforcing a fundamental principle at compile time, commonly summarized as &lt;strong&gt;Aliasing XOR Mutation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Just like the XOR logic gate many of us encounter in our first digital logic course, a piece of data can have &lt;strong&gt;aliases&lt;/strong&gt; (multiple shared references) &lt;strong&gt;or&lt;/strong&gt; it can be &lt;strong&gt;mutated&lt;/strong&gt; (through one exclusive mutable reference), but never both at the same time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you didn't get it at first, I'll give you an analogy from a professor that I had at university:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"You can have your wife in the house, or your lover when she's not inside, but not at the same time or it'll be a disaster".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's essentially what Rust enforces. You can have many readers, or one writer—but never both at the same time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Option A (Aliasing):&lt;/strong&gt; You can have unlimited read-only references (&lt;code&gt;&amp;amp;name&lt;/code&gt;). But the moment you create one, the compiler locks the data and no one is allowed to mutate it until everyone is done READING.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Option B (Mutation):&lt;/strong&gt; You can have exactly one mutable reference (&lt;code&gt;&amp;amp;mut name&lt;/code&gt;). But in order to get it, you must be THE ONLY POINTER int he room!!.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rust</category>
    </item>
    <item>
      <title>Global Variables in Rust &amp; C/C++</title>
      <dc:creator>Lozi</dc:creator>
      <pubDate>Sun, 12 Jul 2026 20:30:44 +0000</pubDate>
      <link>https://dev.to/0xlozi/global-variables-in-rust-cc-3h4p</link>
      <guid>https://dev.to/0xlozi/global-variables-in-rust-cc-3h4p</guid>
      <description>&lt;p&gt;&lt;strong&gt;What's a global variable?&lt;/strong&gt;&lt;br&gt;
A global variable is a variable with global scope, meaning that it visible throughout the program, unless it's shadowed. In compiled languages, global variables are generally static, which means their lifetime is &lt;strong&gt;the entire runtime of the program&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which one's programming languages are actually compiled?&lt;/strong&gt;&lt;br&gt;
Is a &lt;strong&gt;programming language&lt;/strong&gt; that is usually implemented with a compiler &lt;strong&gt;rather than an interpreter&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we use them?&lt;/strong&gt;&lt;br&gt;
Global variables are used to pass information between sections of code that do not share a relation like concurrent threads and signal handlers. Languages (Including C) defines implicitly a namespace for earch global variable inside a certain file so that eliminates most of the problems seen with languages with a global namespace, though problems may persist without their proper encapsulation. Without a proper locking (like mutex) code, using global variables will not be thread-safe except for read only values in protected memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interesting, so using global variables in parallel programs is not the best idea UNLESS we use a proper locking (which is mutex)...&lt;/strong&gt;&lt;br&gt;
Rust is known as a safe programming language, therefore MAYBE this can be the cause of why I can't declare a global variable that can be edited at runtime: BECAUSE IT'S RISKY.&lt;br&gt;
But my program isn't parallel, then why I can't do it then?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's investigate&lt;/strong&gt;&lt;br&gt;
I stumble upon a thread from stack overflow from a person who had somewhat the same problem that I'm facing currently, and the answer to that manner was to use the "unsafe" type in order to stop fighting with the compiler, but at a certain cost: "Unless your program wouldn't be in te future concurrent, then is perfectly fine to use the unsafe keyword".&lt;/p&gt;

&lt;p&gt;But I want in the future make this decryption tool concurrent, so then I can learn more about concurrency in Rust. Thus, I think I might make the global variable "Safe".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But how do we make it "Safe"?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Let's investigate:&lt;/strong&gt;&lt;br&gt;
I stumble upon a really GOOD diagram explaining what to use depending on what do you wanna do with your global variable in Rust. You can find the diagram here: &lt;a href="https://www.sitepoint.com/rust-global-variables/" rel="noopener noreferrer"&gt;https://www.sitepoint.com/rust-global-variables/&lt;/a&gt; At Overview section.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frbk2hffo25davg6gj8yu.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frbk2hffo25davg6gj8yu.png" alt="Rust Concurrent Tree Decision Taking" width="799" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The thing that I need now is make my global variable "Safe", so then in the future I can use it without any problem.&lt;br&gt;
For single threading if I wanna store at runtime inside the const, I have to use Rc. But since I've told already that I want to make this in the future a concurrent program. Then I'll use Arc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's Arc btw&lt;/strong&gt;&lt;br&gt;
I made a summary before about this Arc thing, so I might just copy and paste in case someone is interested:&lt;/p&gt;
&lt;h4&gt;
  
  
  Rc and Arc note:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://app.notion.com/p/Rc-T-and-Arc-T-39bfcd22531880c1a6c0fb1446359574?source=copy_link" rel="noopener noreferrer"&gt;https://app.notion.com/p/Rc-T-and-Arc-T-39bfcd22531880c1a6c0fb1446359574?source=copy_link&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Solution to my problem
&lt;/h4&gt;

&lt;p&gt;This was my code before the refactoring:&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;// std::array&amp;lt;std::vector&amp;lt;char&amp;gt;, 13&amp;gt; g_tables;&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;G_TABLES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u8&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;13&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;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By combining Arc (Atomic Reference Counted) and Mutex (Mutual Exclusion), you create a single, shared source of truth that can be safely accessed and modified from anywhere in your program, even across multiple cores.&lt;/p&gt;

&lt;p&gt;In the Rust community, wrapping a type like this is so common it's often jokingly called "the Arc&amp;gt; sandwich."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After:&lt;/strong&gt;&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;static&lt;/span&gt; &lt;span class="n"&gt;g_tables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Arc&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u8&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;13&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahhhh I'm so close but the Rust compiler is telling me something:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;= note: the `Copy` trait is required because this value will be copied for each element of the array
help: create an inline `const` block
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I don't understand why in order to get the Copy trait I have to put the Vec::new() inside a const...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I found:&lt;/strong&gt;&lt;br&gt;
Copying vs. Re-running&lt;br&gt;
When I write [value; 13], Rust doesn't run the value code 13 times&lt;br&gt;
Instead, Rust does this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Evaluates &lt;code&gt;Vec::new()&lt;/code&gt; exactly one&lt;/li&gt;
&lt;li&gt;Takes that single vector and tries to copy it 13 TIMES in order to fill the array&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So this si where the Copy trait comes in. Simple types like u8 or booleans Implement Copy because copying them is just duplicating bits in memory.&lt;br&gt;
But a Vec is: A dynamic data structure that points to a chunk of memory on the heap. So if Rust blindly copied the vector 13 times, you would end up with 13 vectors &lt;strong&gt;all pointing to the exact same memory location&lt;/strong&gt;. So when you tried to add data to one, it would corrupt the others. And when the program ends, Rust would try to clean up the same memory 13 TIMES, causing a massive crash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution: const Block&lt;/strong&gt;&lt;br&gt;
When we add the const block like the compiler tells us to do: &lt;code&gt;[const { Vec::new() }; 13]&lt;/code&gt;, we are changing the rules of the array syntax itself!!!.&lt;br&gt;
I'm telling the compiler "Not evaluate this once, copy it instead, treat is as a constant expression, and run it 13 SEPARATE TIMES".&lt;/p&gt;

&lt;p&gt;Arc (Atomic Reference Counting) is used to share ownership of a variable when you don't know how long it needs to live. But a static variable lives forever, for the entire duration of the program, and is already globally accessible to every thread.&lt;/p&gt;

&lt;p&gt;If it's global, I only need the Mutex to safely mutate it!!!&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Result:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// std::array&amp;lt;std::vector&amp;lt;char&amp;gt;, 13&amp;gt; g_tables;&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;G_TABLES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u8&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;13&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Fat Pointers &amp; Smart Pointers in Rust</title>
      <dc:creator>Lozi</dc:creator>
      <pubDate>Sat, 27 Jun 2026 14:55:38 +0000</pubDate>
      <link>https://dev.to/0xlozi/fat-pointers-smart-pointers-in-rust-45mb</link>
      <guid>https://dev.to/0xlozi/fat-pointers-smart-pointers-in-rust-45mb</guid>
      <description>&lt;p&gt;When transitioning from C or C++ to Rust, the hardest habit to break is how you think about memory. In C/C++, pointers are mostly just memory addresses. Rust adds ownership and richer pointer types to make memory access safe without sacrificing performance.&lt;br&gt;
In order to understand Rust, you have to know 2 key concepts: &lt;strong&gt;Smart Pointers&lt;/strong&gt; and &lt;strong&gt;Fat Pointers&lt;/strong&gt;. The entire decision of which to use depends on one rule: &lt;strong&gt;Ownership&lt;/strong&gt; and &lt;strong&gt;Borrowing&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smart Pointer: Definition
&lt;/h3&gt;

&lt;p&gt;A data structure that acts like a normal pointer, but it comes with a "Property Manager" (Ownership Manager), let me explain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It owns some resource (commonly heap memory) and knows exactly &lt;strong&gt;when that resource is no longer needed.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;strong&gt;Rust&lt;/strong&gt;, common Smart Pointers have &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;Box&amp;lt;T&amp;gt;&lt;/code&gt;, or &lt;code&gt;String&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is it useful?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The CPU Stack is really fast but tiny. So if you try to create a 3000000 byte array on the stack, your program will crash instantly raising a &lt;code&gt;Stack Overflow&lt;/code&gt;. Smart pointers allocate their data on the &lt;strong&gt;heap&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Some smart pointers, like &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt; and &lt;code&gt;String&lt;/code&gt;, can dynamically grow or shrink.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No memory leaks:&lt;/strong&gt; Smart pointers automatically clean up the resources they own when they go out of scope, so you don't need to call &lt;code&gt;free()&lt;/code&gt; manually!!!.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Fat Pointer (Borrower &amp;amp; Viewer)
&lt;/h3&gt;

&lt;p&gt;A Fat Pointer is a "borrowed" reference to a contiguos sequence of memory. Conceptually, a fat pointer is like a &lt;strong&gt;small struct&lt;/strong&gt; containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Address:&lt;/strong&gt; Where the data starts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The length:&lt;/strong&gt; How many elements exist in the data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Rust, &lt;strong&gt;Fat Pointers&lt;/strong&gt; are represented as &lt;strong&gt;Slices&lt;/strong&gt; (e.d., &lt;code&gt;&amp;amp;[u8]&lt;/code&gt; or &lt;code&gt;&amp;amp;str&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is this useful?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Cost Windows:&lt;/strong&gt; If you have a 500MB file in RAM, you don't want to duplicate data just to look at the header. A Fat Pointer create a "window" into that existing file. It requieres zero memory allocation or zero copying. Which is very useful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bounds Safety:&lt;/strong&gt; Because the Fat Pointer has it's own length, the Because the fat pointer carries its length, Rust performs a bounds check before doing the indexing. If the index is out of range, the program safely panics instead of reading invalid memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Rust vs C/C++
&lt;/h3&gt;

&lt;p&gt;The reason why these concepts feel weird at first is because C &amp;amp; C++ rely almost entirely on Naked Pointers (const u8*)&lt;br&gt;
A naked Pointer is just a note with an address (&lt;code&gt;0x7FFF0042&lt;/code&gt;), so it has no conext, length and no context.&lt;/p&gt;

&lt;h3&gt;
  
  
  First difference: Bounds checking
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;In &lt;strong&gt;C/C++&lt;/strong&gt; when you write ptr[500], the CPU does the math (ptr+500) and walks blindly 500 steps past the address. So if your array was only 15 bytes long, you may read unrelated memory from your own process or trigger a segmentation fault.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rust:&lt;/strong&gt; When you write slice[500], Rust automatically checks whether 500 is within the slice's length. If it's out of bounds, the program safely stops itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Second Difference: Memory Leaks
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;C/C++:&lt;/strong&gt; Heap allocations are not automatically cleaned up. Even if a pointer variable goes out of scope, the allocated memory stays alive until you explicitly call free() or delete. If you forget, the program leaks memory.&lt;br&gt;
&lt;strong&gt;Rust:&lt;/strong&gt; By using a Smart Pointer (&lt;code&gt;Vec&lt;/code&gt;), Rust automatically inserts calls to drop when ownership ends. As a result, you can't accidentally forget to &lt;strong&gt;free memory&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Third Difference: Creating vs. Passing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;C/C++:&lt;/strong&gt; You pass naked pointers everywhere. You pass them in order to create data, and also to read it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In Rust:&lt;/strong&gt; You use Smart Pointers (Vec) only when you need to create and own data. So immediately after, you slice them into Fat Pointers in order to pass to your functions so they can efficiently borrow and read the data.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rust</category>
    </item>
    <item>
      <title>The Ilusion of Arrays: Pointer Casting, and the Danger of memory Reinterpretation</title>
      <dc:creator>Lozi</dc:creator>
      <pubDate>Wed, 24 Jun 2026 16:10:34 +0000</pubDate>
      <link>https://dev.to/0xlozi/the-ilusion-of-arrays-pointer-casting-and-the-danger-of-memory-reinterpretation-4ek7</link>
      <guid>https://dev.to/0xlozi/the-ilusion-of-arrays-pointer-casting-and-the-danger-of-memory-reinterpretation-4ek7</guid>
      <description>&lt;p&gt;When optimizing software to run as fast as possible, developers tend to hit a wall with high-level data structures. To squeeze every inch of performance out of a processor, we have to stop looking at arrays as safe little boxes, and start lookin at RAM for what it really is: a MASSIVE, contiguous strip of single bytes!!!&lt;br&gt;
One of the most powerful optimization tricks in C, C++, and algo unsafe Rust is Pointer Casting, reinterpreting an array of 1 byte-data (u8) as an array of 4 bytes (u32). But this raw pointer comes with a high risk of hardware crashes. Here’s why:&lt;/p&gt;
&lt;h3&gt;
  
  
  The Optimization: Why the bother of casting &lt;code&gt;u8&lt;/code&gt; to &lt;code&gt;u32&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;A processor executes instructions in CPU CYCLES. If you need to read 4 bytes of data, a naive approach processes it through &lt;code&gt;u8&lt;/code&gt; (1 byte) pointer.&lt;br&gt;
&lt;strong&gt;Cycles:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load Byte 0&lt;/li&gt;
&lt;li&gt;Load Byte 1&lt;/li&gt;
&lt;li&gt;Load Byte 2&lt;/li&gt;
&lt;li&gt;Load Byte 3&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To optimize this, we change the “glasses” (just to make an analogy) the CPU is currently wearing. By taking the starting address of that &lt;code&gt;u8&lt;/code&gt; array and telling the compiler “Hey, pretend this is actually 🤓 a pointer of &lt;code&gt;u32&lt;/code&gt; data”, we change the &lt;strong&gt;memory stride&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Wait, wtf is a memory stride?
&lt;/h3&gt;

&lt;p&gt;A memory stride is &lt;strong&gt;the distance in bytes between consecutive elements in memory along a particular dimension of an array.&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Let’s make an example:&lt;/strong&gt;&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="n"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;:&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;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;uint32&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Inside the memory will be:&lt;/strong&gt;&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="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;   &lt;span class="mi"&gt;1004&lt;/span&gt;   &lt;span class="mi"&gt;1008&lt;/span&gt;   &lt;span class="mi"&gt;1012&lt;/span&gt;
&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="mi"&gt;10&lt;/span&gt;     &lt;span class="mi"&gt;20&lt;/span&gt;     &lt;span class="mi"&gt;30&lt;/span&gt;     &lt;span class="mi"&gt;40&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;To go from 10 to 20, &lt;strong&gt;you have to move 4 bytes&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;To go from 20 to 30, &lt;strong&gt;you move another 4 bytes&lt;/strong&gt;
&lt;strong&gt;So:&lt;/strong&gt; &lt;code&gt;stride = 4&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffjfa5j2lsns6n33ju0zp.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffjfa5j2lsns6n33ju0zp.png" alt="memory stride" width="708" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Result when we “change the glasses”
&lt;/h3&gt;

&lt;p&gt;Now when we tell the CPU to read index 0, it uses a 32-bit hardware register in order to &lt;strong&gt;swallow&lt;/strong&gt; &lt;code&gt;Bytes 0, 1, 2, and 3&lt;/code&gt; simultaneously; which leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cycle 1: Load Bytes 0, 1, 2, and also 3!!!!!!!
We just made the memory read almost 400% faster. However, lying to the compiler about the shape of your memory could open two massive failures at a hardware level…&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Problem 1: Alignment Fault
&lt;/h3&gt;

&lt;p&gt;Processors are wired to expect certain data types to align with specific &lt;strong&gt;memory boundaries:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An u8 (1 byte) can start at any addres&lt;/li&gt;
&lt;li&gt;A u32 (4 bytes) is strictly expected to start at an addres that is perfectly dividisible by 4 (0, 4, 8…)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have an &lt;code&gt;u8&lt;/code&gt; array, and you decide to put on your &lt;code&gt;u32&lt;/code&gt; glasses starting at &lt;code&gt;Address 1&lt;/code&gt;, you just created an &lt;strong&gt;Unaligned Pointer&lt;/strong&gt;.&lt;br&gt;
So, when you ask the CPU to read a 4-byte chunk starting at A&lt;code&gt;ddress 1&lt;/code&gt;, the hardware struggles. Some processors (like modern intel x86) will silently fix the mistake behind the scenes. But processors liek ARM chips found in movile devices, consoles or embedded systems, physically can’t do it. So they will instantly panic and triggfer a Fatal Alignment Fault.&lt;/p&gt;
&lt;h3&gt;
  
  
  Problem 2: Modulo Trap
&lt;/h3&gt;

&lt;p&gt;Even if your starting Address is &lt;strong&gt;perfectly aligned&lt;/strong&gt;, the &lt;strong&gt;overall size&lt;/strong&gt; of your memory buffer can kill the program if it doesn’t divide perfectly into your &lt;strong&gt;new stride&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s imagine that you have a raw &lt;code&gt;u8&lt;/code&gt; buffer which is exactly 17 bytes long. Then you cast the pointer to &lt;code&gt;u32&lt;/code&gt; in order to read it faster&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="mi"&gt;17&lt;/span&gt; &lt;span class="n"&gt;modulo&lt;/span&gt; &lt;span class="mi"&gt;4&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that you have 4 perfect chunks , but 1 &lt;strong&gt;trailing byte&lt;/strong&gt; remaining…&lt;br&gt;
So... when you loop through the memory with your u32 glasses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Index [0]:&lt;/code&gt; Reads bytes 0-3 (Safe…)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Index [1]:&lt;/code&gt; Reads bytes 4-7 (Safe…)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Index [2]:&lt;/code&gt; Reads bytes 8-11 (Safe…)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Index [3]:&lt;/code&gt; Reads bytes 12-15 (Safe…)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Index [4]:&lt;/code&gt; Reads byte 16... and bytes 17, 18, and 19 💀💀💀&lt;/strong&gt;
Since you told the CPU it was reading a 4 byte structure.. It blindly reads past the end of your 17 byte buffer…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If bytes 17, 18, and 19 belong to the Operating System's restricted memory, the OS kills your program with a** Segmentation Fault** for trespassing.&lt;br&gt;
Worse, if those bytes belong to another variable inside your own program, the CPU reads or overwrites them silently. Your program keeps running but with corrupted data… This is the definition of &lt;strong&gt;Undefined Behavior (UB)&lt;/strong&gt;. Good luck with that.&lt;/p&gt;

&lt;h3&gt;
  
  
  C/C++ vs. Safe Rust
&lt;/h3&gt;

&lt;p&gt;In C and C++, the compiler implicitly trusts the developer. If you cast a &lt;code&gt;char*&lt;/code&gt; to an &lt;code&gt;int*&lt;/code&gt;, the compiler assumes you have &lt;strong&gt;manually verified&lt;/strong&gt; the alignment and &lt;strong&gt;modulo math&lt;/strong&gt;. When human error inevitably occurs, it results in security vulnerabilities.&lt;br&gt;
&lt;strong&gt;Rust solves this by splitting the logic:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;unsafe Rust:&lt;/strong&gt;
You can still perform raw pointer casting using &lt;code&gt;std::slice::from_raw_parts&lt;/code&gt; and pointer casting (as &lt;code&gt;*const u32&lt;/code&gt;). But you must wrap it in an &lt;code&gt;unsafe {}&lt;/code&gt; block, taking personal responsibility for the math. If it crashes, you know exactly which block of code to blame!!!.
&lt;strong&gt;2. Safe Rust (Zero-Cost Abstractions):&lt;/strong&gt;
Instead of manually casting pointers, safe Rust provides methods like &lt;code&gt;.copy_from_slice()&lt;/code&gt;, &lt;code&gt;.copy_within()&lt;/code&gt;, or &lt;code&gt;.try_into()&lt;/code&gt;.
When you use these, the Rust compiler checks the alignment and array lengths at compile time or safely handles them under the hood. It compiles down to the exact same hyper-efficient hardware instructions (like &lt;code&gt;memmove&lt;/code&gt; or &lt;code&gt;SIMD&lt;/code&gt; loads) that a manual C-pointer cast would achieve, but mathematically guarantees &lt;strong&gt;you cannot trigger an Alignment Fault or step out of bounds.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>From C++ to Rust: When Structure Layout Becomes Part of the Algorithm</title>
      <dc:creator>Lozi</dc:creator>
      <pubDate>Thu, 04 Jun 2026 17:49:17 +0000</pubDate>
      <link>https://dev.to/0xlozi/from-c-to-rust-when-structure-layout-becomes-part-of-the-algorithm-4poi</link>
      <guid>https://dev.to/0xlozi/from-c-to-rust-when-structure-layout-becomes-part-of-the-algorithm-4poi</guid>
      <description>&lt;p&gt;Have you ever stumbled upon code that works almost like a miracle, entirely because of how the compiler lays out data in memory?&lt;/p&gt;

&lt;p&gt;Recently, while I was working on a port of a decryption for executable files (specifically EBOOT.BIN) from the PSP that was originally written in C++, I found a design pattern that brought me different emotions such as "fascination" and "paranoia"...&lt;/p&gt;

&lt;p&gt;Today I want to document how a PSP decryption routine relies on contiguous structure layout to treat multiple adjacent fields as a single cryptographic workspace, the challenges of porting this design to Rust, and how I validated the implementation using an integration test with a real EBOOT.BIN file from Lego Batman.&lt;/p&gt;

&lt;h2&gt;
  
  
  First case: When The Structure Layout Becomes Part of the Algorithm
&lt;/h2&gt;

&lt;p&gt;Let's analyze the original C++ structure I used to map the encrypted executable layout of the &lt;code&gt;PRXType1&lt;/code&gt; format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;PRXType1&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;explicit&lt;/span&gt; &lt;span class="n"&gt;PRXType1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0xD0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sha1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0xD4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sha1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unused&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0xE8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unused&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kirkBlock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0x110&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x40&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
        &lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kirkBlock&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0x40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kirkBlock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;0x40&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prxHeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prxHeader&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// LOOK AT THIS NOW&lt;/span&gt;
        &lt;span class="n"&gt;kirk7&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sha1&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0xC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sha1&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0xC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xA0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;u8&lt;/span&gt; &lt;span class="n"&gt;tag&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;// 4 bytes&lt;/span&gt;
    &lt;span class="n"&gt;u8&lt;/span&gt; &lt;span class="n"&gt;sha1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x14&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;     &lt;span class="c1"&gt;// 20 bytes (0x14)&lt;/span&gt;
    &lt;span class="n"&gt;u8&lt;/span&gt; &lt;span class="n"&gt;unused&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x28&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;   &lt;span class="c1"&gt;// 40 bytes&lt;/span&gt;
    &lt;span class="n"&gt;u8&lt;/span&gt; &lt;span class="n"&gt;kirkBlock&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="c1"&gt;// 144 bytes&lt;/span&gt;
    &lt;span class="n"&gt;u8&lt;/span&gt; &lt;span class="n"&gt;prxHeader&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="c1"&gt;// 128 bytes&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;static_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PRXType1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mh"&gt;0x150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"inconsistent size of PRX Type 1"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Now u may ask: Where is the trick?
&lt;/h3&gt;

&lt;p&gt;Pay attention to the &lt;code&gt;decrypt&lt;/code&gt; fn. It calls the PSP's cryptographic engine (which is &lt;code&gt;kirk7&lt;/code&gt;), passing as a source &lt;code&gt;SHA1 + 0xC&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;sha1&lt;/code&gt; array is EXACTLY &lt;code&gt;0x14&lt;/code&gt; (20 bytes) long&lt;/li&gt;
&lt;li&gt;If we move &lt;code&gt;0xC&lt;/code&gt; (12 bytes) FORWARD, we only have 8 bytes left in that specific array&lt;/li&gt;
&lt;li&gt;HOWEVER, the third parameter says to process &lt;code&gt;0xA0&lt;/code&gt; (which is 160 BYTES)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we know that, Why the program didn't crash? Because the fields reside in a single contiguous structure object. (one after another). Although the pointer originates inside the sha1 field, the cryptographic routine processes 160 consecutive bytes. In practice, this means that the operation spans the remaining bytes of sha1, all of unused, and part of kirkBlock. The implementation therefore treats several adjacent fields as a single contiguous cryptographic workspace.&lt;/p&gt;

&lt;p&gt;Because the decryption routine depends on a very specific memory layout, changing the declaration order of the fields would alter the 160-byte region processed by kirk7. Such a change would likely corrupt the decrypted data and break the algorithm entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Does kirk7 Actually Do?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;kirk7&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;outbuff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;inbuff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;keyId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;AES_ctx&lt;/span&gt; &lt;span class="n"&gt;aesKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kirk_4_7_get_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;AES_set_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;aesKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;AES_cbc_decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;aesKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inbuff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;outbuff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&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;Since the pointer begins at sha1 + 0xC and the requested size is 0xA0 (160 bytes), the operation spans the remaining bytes of sha1, all of unused, and part of kirkBlock.&lt;br&gt;
In other words, the algorithm is not really interested in the sha1 field itself. It is operating on a 160-byte cryptographic workspace whose starting point happens to lie inside sha1.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Rust Philosophy: Explicit safety without sacrificing performance.
&lt;/h2&gt;

&lt;p&gt;When I decided to port this to Rust, I quickly realized that the original implementation relies on pointer arithmetic spanning multiple adjacent fields. While Rust can express the same behavior through raw pointers and unsafe code, I wanted a solution that made the memory region explicit and remained fully safe. Instead of relying on a pointer that implicitly goes to several fields, I represented the entire workspace as a single byte array and passed the exact range required by the decryption routine.&lt;/p&gt;

&lt;p&gt;To solve this, I decided to use a single flat byte array (which is &lt;code&gt;[u8; 0x150&lt;/code&gt;) and create read-only views (slices) based on fixed offsets. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is my implementation:&lt;/strong&gt;&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="n"&gt;PrxType1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&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;0x150&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;PrxType1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/// Constructs a new PrxType1 from raw file bytes.&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;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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="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;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;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;0x150&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="c1"&gt;// Reconstruct the layout respecting the original C++ offsets:&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.copy_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0xD0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0xD4&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;         &lt;span class="c1"&gt;// tag&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0x18&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.copy_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0xD4&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0xE8&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;      &lt;span class="c1"&gt;// sha1 (20 bytes)&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0x18&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0x40&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.copy_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0xE8&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0x110&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;  &lt;span class="c1"&gt;// unused (40 bytes)&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0x40&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.copy_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0x110&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0x150&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// kirkBlock part 1 (64 bytes)&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0x80&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0xD0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.copy_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0x80&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0xD0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;   &lt;span class="c1"&gt;// kirkBlock part 2&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0xD0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0x150&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.copy_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;prx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;     &lt;span class="c1"&gt;// prxHeader (128 bytes)&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;data&lt;/span&gt; &lt;span class="p"&gt;}&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;decrypt&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="n"&gt;key_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&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;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;KirkError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// In C++ the signature was: kirk7(sha1+0xC, sha1+0xC, 0xA0, key);&lt;/span&gt;
        &lt;span class="c1"&gt;// Our 'sha1' starts at offset 4.&lt;/span&gt;
        &lt;span class="c1"&gt;// 4 + 12 (0xC) = 16 (0x10).&lt;/span&gt;
        &lt;span class="c1"&gt;// If we want to decrypt 160 bytes (0xA0): 16 + 160 = 176 (0xB0).&lt;/span&gt;

        &lt;span class="c1"&gt;// Rust allows us to express the exact memory range explicitly and safely:&lt;/span&gt;
        &lt;span class="nf"&gt;kirk7&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="py"&gt;.data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0x10&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0xB0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;key_id&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="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// --- Safe Views (Read-only Slices) ---&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;tag&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;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="o"&gt;&amp;amp;&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="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&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="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;sha1&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;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="o"&gt;&amp;amp;&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="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0x18&lt;/span&gt;&lt;span class="p"&gt;]&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;unused&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;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="o"&gt;&amp;amp;&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="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0x18&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0x40&lt;/span&gt;&lt;span class="p"&gt;]&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;kirk_block&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;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="o"&gt;&amp;amp;&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="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0x40&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0xD0&lt;/span&gt;&lt;span class="p"&gt;]&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;prx_header&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;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="o"&gt;&amp;amp;&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="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0xD0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0x150&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;    

    &lt;span class="cd"&gt;/// This verifies integrity by recalculating the header hash (it does this in the original decrypt project but I prefer doing it here)&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;is_valid&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;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xorbuf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&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;hasher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Sha1&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;hasher&lt;/span&gt;&lt;span class="nf"&gt;.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;xorbuf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;0x14&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="n"&gt;hasher&lt;/span&gt;&lt;span class="nf"&gt;.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="nf"&gt;.unused&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;hasher&lt;/span&gt;&lt;span class="nf"&gt;.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="nf"&gt;.kirk_block&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;hasher&lt;/span&gt;&lt;span class="nf"&gt;.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="nf"&gt;.prx_header&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;hash_calculated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hasher&lt;/span&gt;&lt;span class="nf"&gt;.finalize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;hash_calculated&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="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="nf"&gt;.sha1&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why I think this solution is great?
&lt;/h3&gt;

&lt;p&gt;We keep the extreme performance of C++ because we are doing 0 dynamic allocations or array cloning. By passing the range &lt;code&gt;&amp;amp;mut self.data[0x10..0xB0]&lt;/code&gt; to kirk7, Rust guarantees via bounds checking that the cryptographic function operates strictly within those 160 bytes. So if we were to miscalculate the offsets, the program would trigger panic rather than silentyly corrupting other memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  The moment of Truth
&lt;/h3&gt;

&lt;p&gt;To ensure that this implementation was mathematically justified and the offset math was perfect, I wrote an integration test using the actual EBOOT.BIN file from the Lego Batman Game from the PSP.&lt;br&gt;
This test load the specified file, extract the TAG dinamically, looks up to the corresponding hardware key using a key service (allocated into keys_service.rs), it generates the XOR buffer, runs the decryption, and validates via SHA-1 if the resulting bytes match the game's original structure!!!.&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;#[cfg(test)]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;super&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="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="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;File&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="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;#[test]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test_lego_batman_type1_valido&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 1. Load the real PSP binary&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ruta_eboot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/home/snake/Downloads/lego_batman_game/PSP_GAME/SYSDIR/EBOOT.BIN"&lt;/span&gt;&lt;span class="p"&gt;;&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;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta_eboot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not open EBOOT!"&lt;/span&gt;&lt;span class="p"&gt;);&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;eboot_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="nf"&gt;.read_to_end&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="n"&gt;eboot_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// 2. Map data to our flat structure&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;type1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;PrxType1&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;eboot_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 3. Extract the crypto Tag (Should evaluate to 0xC0CB167C automatically)&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;tag_bytes&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;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;type1&lt;/span&gt;&lt;span class="nf"&gt;.tag&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.try_into&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tag doesn't have 4 bytes"&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;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_le_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag_bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

        &lt;span class="c1"&gt;// 4. Fetch the keys for this specific game&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;key_eboot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;keys_service&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get_tag_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This game's Tag is missing from the database!"&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;key_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;key_eboot&lt;/span&gt;&lt;span class="py"&gt;.code&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;;&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;xorbuf&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;144&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;key_eboot&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;KeyType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;U8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key_array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;xorbuf&lt;/span&gt;&lt;span class="nf"&gt;.copy_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;key_array&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nn"&gt;KeyType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;U32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key_array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;for&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;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;key_array&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.enumerate&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;start&lt;/span&gt; &lt;span class="o"&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;4&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;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;xorbuf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.copy_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="nf"&gt;.to_le_bytes&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="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// 5. Decrypt using our safe Rust memory range!&lt;/span&gt;
        &lt;span class="n"&gt;type1&lt;/span&gt;&lt;span class="nf"&gt;.decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AES engine failed..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 6. Final validation: Does the calculated hash match the EBOOT offset?&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;es_valido&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;type1&lt;/span&gt;&lt;span class="nf"&gt;.is_valid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;xorbuf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// If this passes, our contiguous memory emulation was an absolute success&lt;/span&gt;
        &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;es_valido&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"SHA-1 hash mismatch... Decryption failed!"&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;h3&gt;
  
  
  Result: &lt;code&gt;TEST PASSED (OK)&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;We managed to replicate the exact behavior of the original PSP implementation without inheriting it's dangerous security risks&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I am writing this article in order to prevent myself from forgetting this architectural headache as the project continues to scale...&lt;br&gt;
Mastering memory isn't just about programming retro consoles. It's about understanding how data layout, performance, and correctness interact in every system we build.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
