<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>TheBestTvarynka</title>
    <subtitle>My personal blog with articles, thoughts, guides&#x2F;tips</subtitle>
    <link rel="self" type="application/atom+xml" href="https://tbt.qkation.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://tbt.qkation.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-02-02T00:00:00+00:00</updated>
    <id>https://tbt.qkation.com/atom.xml</id>
    <entry xml:lang="en">
        <title>Drawing Genealogy Graphs. Part 1: Tree Drawing Using Reingold-Tilford Algorithm</title>
        <published>2026-02-02T00:00:00+00:00</published>
        <updated>2026-02-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/draw-tree-using-reingold-tilford-algorithm/"/>
        <id>https://tbt.qkation.com/posts/draw-tree-using-reingold-tilford-algorithm/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/draw-tree-using-reingold-tilford-algorithm/">&lt;h1 id=&quot;motivation&quot;&gt;Motivation&lt;&#x2F;h1&gt;
&lt;p&gt;Last year, I started my own genealogy research. Honestly, I planned to start it many years ago.
One day in 2025, I realized that if I did not start, then it may never happen, and I would lose a huge part of my family history.&lt;&#x2F;p&gt;
&lt;p&gt;I spent a lot of time visiting my old relatives and asking them many questions, and scanning old photos and documents.
At some point, I questioned myself about how it&#x27;s better to store all this data.
Some day, I will write a detailed post about the approaches considered, the pros and cons of each, and why I chose what I did.
But today, in this post, I am going right to the solution.&lt;&#x2F;p&gt;
&lt;p&gt;I chose &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;obsidian.md&#x2F;&quot;&gt;Obsidian&lt;&#x2F;a&gt; as a main app for storing all genealogy data, including photos, conversation recordings, text, people&#x27;s information, scanned documents, etc.
I wanted to have full control over my data. I did not want to trust any websites.
Obsidian is very flexible, convenient, and extendable. For me, it&#x27;s a perfect choice.
Additionally, I periodically back up genealogy data to an external SSD and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;products&#x2F;storage&quot;&gt;Google Cloud Storage&lt;&#x2F;a&gt; bucket.
I do not know about you, but I feel pretty comfortable and reliable with this approach.&lt;&#x2F;p&gt;
&lt;p&gt;Let me answer one question before we go further. Yes, I know about &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.myheritage.com&#x2F;&quot;&gt;myheritage&lt;&#x2F;a&gt;.
I still fill in all the basic info for my family and ancestors, like names, birth, marriage, and death dates.
I consider MyHeritage a great tool for research.
But again, I do not trust it, and I do not want to entrust it with all my family&#x27;s personal photos, stories, some documents, and other sensitive information.&lt;&#x2F;p&gt;
&lt;p&gt;So, where did I stop? Oh, yes, Obsidian. Obviously, I would want to visualize the family graph.
The Obsidian has a built-in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;help.obsidian.md&#x2F;plugins&#x2F;graph&quot;&gt;Graph View&lt;&#x2F;a&gt;.
It looks funny, but it doesn&#x27;t even look close to what I want.
I browsed the community plugins and did not find anything helpful.
So, I decided to write my own Obsidian plugin that will render family members as a pretty graph.
Plugin details are out of the scope of this article. I will definitely write a separate post about it in the future.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;This article is focused only on the nodes positioning algorithm.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;All tree diagrams were made using &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tldraw&#x2F;tldraw&quot;&gt;&lt;mark&gt;tldraw&lt;&#x2F;mark&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;intro&quot;&gt;Intro&lt;&#x2F;h1&gt;
&lt;p&gt;I knew that calculating node positions during graph or tree drawing is not a trivial task, and it would definitely be hard.
But I still decided to try to solve this task by myself. I spent a few days on it without achieving any results.
Then I googled for existing algorithms (yes, I should have done it before spending a few days on nothing).&lt;&#x2F;p&gt;
&lt;p&gt;I did not find the exact algorithm, but I found a similar (and much simpler) one: the Reingold-Tilford Algorithm for rendering pretty trees.
This algorithm is not suitable for me because it is for tree node positioning. But all family relationships are a (complex) graph.
This fact introduces a lot of complexity to the task, but I decided to implement the simpler version first and then improve it to meet my requirements.&lt;&#x2F;p&gt;
&lt;p&gt;But why write one more post when other explanations exist?
The problem with existing explanations is that they explain every step of the algorithm as it is, but do not explain &lt;strong&gt;&lt;em&gt;WHY it works&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; and &lt;strong&gt;&lt;em&gt;WHAT THE PURPOSE&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; of each step of the algorithm is.
Many posts feel like the code, but converted to English words 😔.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;UDP.&lt;&#x2F;strong&gt; During writing this post, I found another post with a great explanation and even animations: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;williamyaoh.com&#x2F;posts&#x2F;2023-04-22-drawing-trees-functionally.html&quot;&gt;Drawing Trees Functionally: Reingold and Tilford, 1981&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-reingold-tilford-algorithm&quot;&gt;The Reingold-Tilford Algorithm&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s go straight to the point. Our task is to calculate &lt;code&gt;x&lt;&#x2F;code&gt; and &lt;code&gt;y&lt;&#x2F;code&gt; coordinates of each node in our tree.
Every node in the tree can have any number of children.
Different implementations use similar (maybe a bit different) &lt;em&gt;Aesthetic Rules&lt;&#x2F;em&gt; for tree rendering. Usually, they look like this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Nodes at the same level of the tree should be on the same horizontal line.&lt;&#x2F;li&gt;
&lt;li&gt;A parent should be centered over its children.&lt;&#x2F;li&gt;
&lt;li&gt;A tree and its mirror image should produce drawings that are reflections of one another;
Moreover, a sub-tree should be drawn the same way regardless of where it occurs in the tree.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;Note 1.&lt;&#x2F;strong&gt; Someone also requires the distance between children of the node to be the same, but it&#x27;s not the case for me.
I do not care about this distance 🙃.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Note 2.&lt;&#x2F;strong&gt; There is a special rule for binary trees:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;A left child should be positioned to the left of its parent node and a right child to the right (only applicable to binary trees)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The family tree of direct ancestors is, in fact, a binary tree; the explanation below assumes that any node can have any number of children.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s easy to satisfy the first condition: the &lt;code&gt;y&lt;&#x2F;code&gt; coordinate is a recursion depth (node level in the tree) multiplied by (node height + gap between nodes).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; level&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;NODE_HEIGHT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; NODES_GAP&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The real problem is the &lt;code&gt;x&lt;&#x2F;code&gt; coordinate assignment.
Because any node in the tree can have any number of children, we cannot know in advance the exact tree layout and node positions.
In other words, we cannot assign &lt;code&gt;x&lt;&#x2F;code&gt; coordinates with just one tree traversal.
Fortunately, we can do it in two traversals 😉. I call them the first walk and the second walk.&lt;&#x2F;p&gt;
&lt;p&gt;During the first walk, we calculate intermediate (preliminary) &lt;code&gt;preX&lt;&#x2F;code&gt;, &lt;code&gt;mod&lt;&#x2F;code&gt;, and &lt;code&gt;shift&lt;&#x2F;code&gt; values.
During the second walk, we use these values to calculate the final &lt;code&gt;x&lt;&#x2F;code&gt; coordinate.&lt;&#x2F;p&gt;
&lt;p&gt;Because it is just two tree traversals, the overall algorithm complexity is &lt;code&gt;O(n)&lt;&#x2F;code&gt; where &lt;code&gt;n&lt;&#x2F;code&gt; is the number of nodes in the tree.&lt;&#x2F;p&gt;
&lt;p&gt;Suppose we have the following tree:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;tree.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Let me clarify a few things.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;mark&gt;Siblings&lt;&#x2F;mark&gt; are all nodes that share the same parent node.
I do not often see this term used, so I decided to clarify it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;mark&gt;Sub-tree&lt;&#x2F;mark&gt; of the node is all descendants, including the node itself.
For example, the subtree of node 10 consists of nodes 10, 7, 8, and 9.&lt;&#x2F;li&gt;
&lt;li&gt;The Reingold-Tilford Algorithm uses a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Depth-first_search&quot;&gt;depth-first tree traversal&lt;&#x2F;a&gt;.
In the picture above, you can see in what order the coordinates will be assigned.
It is important to determine the siblings&#x27; order.
Each time we traverse the tree, we should visit nodes in the same order.
In the picture below, I drew arrows that show the nodes visiting order:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;tree-dfs.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;first-walk&quot;&gt;First walk&lt;&#x2F;h2&gt;
&lt;p&gt;As I wrote above, during the first walk, we determine &lt;code&gt;preX&lt;&#x2F;code&gt;, &lt;code&gt;mod&lt;&#x2F;code&gt;, and &lt;code&gt;shift&lt;&#x2F;code&gt; values for each node in the tree.
Let me explain what these parameters mean.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;preX&lt;&#x2F;code&gt; or &lt;mark&gt;preliminary x&lt;&#x2F;mark&gt;.
The initial node &lt;code&gt;x&lt;&#x2F;code&gt; coordinate was given based on its position among siblings.
This &lt;code&gt;preX&lt;&#x2F;code&gt; value does not take into account siblings&#x27; sub-trees or children&#x27;s sub-trees.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;mod&lt;&#x2F;code&gt; or &lt;mark&gt;modifier&lt;&#x2F;mark&gt;.
Denotes how much we need to shift node descendants (&lt;strong&gt;but not the node itself&lt;&#x2F;strong&gt;) to the right to make descendants centered with respect to the node.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;mod.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;shift&lt;&#x2F;code&gt; or &lt;mark&gt;shift&lt;&#x2F;mark&gt; 🤣.
Denotes how much we need to shift the node &lt;strong&gt;and&lt;&#x2F;strong&gt; its descendants to the right to avoid overlapping with the previous sibling sub-tree.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;shift.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Worth mentioning that the original paper does not have the &lt;code&gt;shift&lt;&#x2F;code&gt; parameter, only &lt;code&gt;preX&lt;&#x2F;code&gt; and &lt;code&gt;mod&lt;&#x2F;code&gt;.
The &lt;code&gt;shift&lt;&#x2F;code&gt; parameter was introduced in this post &lt;em&gt;for better clarity&lt;&#x2F;em&gt;: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;towardsdatascience.com&#x2F;reingold-tilford-algorithm-explained-with-walkthrough-be5810e8ed93&#x2F;&quot;&gt;Reingold Tilford Algorithm Explained With Walkthrough. Sep 12, 2023&lt;&#x2F;a&gt;.
I also follow this approach because I&#x27;ve gotten used to this parameter, and it&#x27;s easier to understand that way.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;preliminary-x&quot;&gt;Preliminary x&lt;&#x2F;h3&gt;
&lt;p&gt;As I wrote above, &lt;code&gt;preX&lt;&#x2F;code&gt; is the initial node &lt;code&gt;x&lt;&#x2F;code&gt; coordinate we gave it based on its position among siblings.
The distance between nodes must be at least NODE_WIDTH + NODES_GAP. Let&#x27;s call it a &lt;mark&gt;sibling distance&lt;&#x2F;mark&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For the example&#x27;s simplicity, I assume that the &lt;em&gt;sibling distance&lt;&#x2F;em&gt; is equal to &lt;code&gt;1&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;sinling_distance.svg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;sup&gt;&lt;sub&gt;Almost at the end of writing this article, I realized it would be easier to set sibling distance to 2.
But I did not want to recalculate all numbers, so I left it as it is.&lt;&#x2F;sup&gt;&lt;&#x2F;sub&gt;&lt;&#x2F;p&gt;
&lt;p&gt;For every node, we set the &lt;code&gt;preX&lt;&#x2F;code&gt; to one of the following values:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If the node is the leftmost node among siblings, then its &lt;code&gt;preX&lt;&#x2F;code&gt; is equal to the midpoint of its children:&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; leftmostX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; leftmostNode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;preX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; leftmostNode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;shift&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rightmostX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rightmostNode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;preX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rightmostNode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;shift&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; midpoint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;leftmostX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rightmostX&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;If the node does not have children but is the leftmost sibling, then its &lt;code&gt;prex&lt;&#x2F;code&gt; is equal to &lt;code&gt;0&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;If the node is &lt;strong&gt;not&lt;&#x2F;strong&gt; the leftmost node among siblings, then its &lt;code&gt;preX&lt;&#x2F;code&gt; is equal to the previous sibling &lt;code&gt;preX&lt;&#x2F;code&gt; plus sibling distance.&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; preX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; prevSibling&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;preX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; SIBLING_DISTANCE&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Wait!!! What? &lt;code&gt;.shift&lt;&#x2F;code&gt;? Here? Why?&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Calm down! 😇&lt;&#x2F;p&gt;
&lt;p&gt;Yes, &lt;code&gt;shift&lt;&#x2F;code&gt;. Do you remember the &lt;code&gt;shift&lt;&#x2F;code&gt; definition?&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Denotes how much we need to shift the &lt;strong&gt;node and its descendants&lt;&#x2F;strong&gt; to the right to avoid overlapping with the previous sibling sub-tree.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The &lt;code&gt;shift&lt;&#x2F;code&gt; value also affects the node &lt;code&gt;x&lt;&#x2F;code&gt; value.
We need to take it into account when calculating &lt;code&gt;preX&lt;&#x2F;code&gt;.
But we do not use the children&#x27;s &lt;code&gt;mod&lt;&#x2F;code&gt; value because it does not affect the children &lt;code&gt;x&lt;&#x2F;code&gt; value (only children&#x27;s descendants).&lt;&#x2F;p&gt;
&lt;p&gt;Yes, you do not know how the &lt;code&gt;shift&lt;&#x2F;code&gt; is calculated, but I assure you, I will explain it below.
As noted above, the Reingold-Tilford algorithm is a depth-first recursive algorithm.
It means that when we calculate node &lt;code&gt;preX&lt;&#x2F;code&gt;, &lt;code&gt;mod&lt;&#x2F;code&gt;, and &lt;code&gt;shift&lt;&#x2F;code&gt; values, these values &lt;strong&gt;are already calculated for all child nodes&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;modifier&quot;&gt;Modifier&lt;&#x2F;h3&gt;
&lt;p&gt;At this step, our goal is to center children with respect to their parent node.
Currently, only children of leftmost siblings are centered with respect to their parent node.
We need to do the same for all other nodes.&lt;&#x2F;p&gt;
&lt;p&gt;For every node, we calculate the &lt;code&gt;mod&lt;&#x2F;code&gt; value: the distance between the children&#x27;s midpoint and &lt;code&gt;preX&lt;&#x2F;code&gt;.
Or, in other words, how much we need to shift descendants to the right, so they are centered with respect to their parent node.
The general formula looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; leftmostX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; leftmostNode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;preX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; leftmostNode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;shift&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rightmostX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rightmostNode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;preX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rightmostNode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;shift&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; midpoint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;leftmostX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rightmostX&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; mod&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; node&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;preX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; midpoint&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here is an example of how it will look on a real tree:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;mod-example.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Do not think about the child&#x27;s shift value. I will explain it below.&lt;&#x2F;p&gt;
&lt;p&gt;Good. Now all children are centered with respect to their parent node.
Obviously, that&#x27;s not enough.
All previous manipulations do not prevent overlaps. We do not want sub-trees to overlap.
We are going to fix it using the &lt;code&gt;shift&lt;&#x2F;code&gt; parameter.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;shift&quot;&gt;Shift&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;mod&lt;&#x2F;code&gt; parameter is responsible for parent-children alignment.
Whereas the &lt;code&gt;shift&lt;&#x2F;code&gt; parameter is responsible for eliminating overlaps.&lt;&#x2F;p&gt;
&lt;p&gt;If the current node is the leftmost node among its siblings, then its &lt;code&gt;shift&lt;&#x2F;code&gt; value is 0.
It&#x27;s pointless to search for overlaps because there are no sub-trees to the left (in the scope of sibling sub-trees, of course).&lt;&#x2F;p&gt;
&lt;p&gt;If the current node is not the leftmost node among its siblings, then there is a possibility that its sub-tree overlaps with one of the sub-trees of siblings to the left.
We need to check for overlaps and increase the &lt;code&gt;shift&lt;&#x2F;code&gt; value if needed.&lt;&#x2F;p&gt;
&lt;p&gt;For every sibling&#x27;s sub-tree to the left, we do the following: we compare &lt;code&gt;x&lt;&#x2F;code&gt; coordinates of the rightmost node of the left sub-tree and leftmost node of the right sub-tree (current node sub-tree) on each level.
If we detect that nodes overlap, we calculate how much we need to shift the right sub-tree. We do that on each level and, as a result, we take the maximum &lt;code&gt;shift&lt;&#x2F;code&gt; value. The shift calculation algorithm is pretty simple:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Pseudocode.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; leftNode - rightmost node from the left sub-tree.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; rightNode - leftmost node from the current (right) sub-tree.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; leftShift - the sum of parents&amp;#39; mod and shift parameters for leftNode.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; rightShift - the sum of parents&amp;#39; mod and shift parameters for rightNode.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; leftX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; leftNode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;preX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; leftShift&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; leftNode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;shift&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; NODE_WIDTH&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rightX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rightNode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;preX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rightShift&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rightNode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;shift&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; shift&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; If the distance between sub-trees is not big enough.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;rightX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; leftX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; NODES_GAP&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Calculate needed shift.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    shift&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; NODES_GAP&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;rightX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; leftX&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;See the example:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;shift-example.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I highlighted the rightmost nodes of the left sub-tree with purple and the leftmost nodes of the current sub-tree with orange.
All purple nodes are called the &lt;mark&gt;right contour&lt;&#x2F;mark&gt; and all orange nodes are called &lt;mark&gt;left contour&lt;&#x2F;mark&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We do shift calculation for each not-leftmost node in the tree.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Important moment #1.&lt;&#x2F;strong&gt; Pay attention that we compare the leftmost and rightmost nodes &lt;em&gt;on each level&lt;&#x2F;em&gt;.
It does not mean that it&#x27;s enough, for example, for the left contour to &lt;em&gt;just&lt;&#x2F;em&gt; take the leftmost child of the leftmost sibling and so on.
Look at the picture below:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;contour.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The path to some leftmost&#x2F;rightmost nodes can lead through intermediate nodes. You need to take it into account when implementing the algorithm.
Unfortunately, I forgot about that, and my implementation is incomplete.
I remembered about it only while writing this post 😅. And that&#x27;s another reason to write 🤓.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Important moment #2.&lt;&#x2F;strong&gt; Do not forget to apply &lt;code&gt;mod&lt;&#x2F;code&gt; and &lt;code&gt;shift&lt;&#x2F;code&gt; values to child nodes during shift calculation.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;example&quot;&gt;Example&lt;&#x2F;h3&gt;
&lt;p&gt;Do you remember the big tree from the beginning of the post?
Let&#x27;s calculate the &lt;code&gt;preX&lt;&#x2F;code&gt;, &lt;code&gt;mod&lt;&#x2F;code&gt;, and &lt;code&gt;shift&lt;&#x2F;code&gt; values for each node.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;tree-final-x.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I added verbose explanations on purpose.
The good, verbose, and comprehensive example was exactly what I wanted when I first encountered this algorithm.&lt;&#x2F;p&gt;
&lt;p&gt;Did you notice that node11 is not exactly between node10 and node15?
That&#x27;s what I told you at the beginning of the article: I did not care about distances between siblings.
The only thing that matters to me is parent-children alignment.
But if you want to fix that and get even more ✨aesthetic✨ tree, you can improve the math behind shift calculation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;second-walk&quot;&gt;Second walk&lt;&#x2F;h2&gt;
&lt;p&gt;Congratulations! You have gotten through the hardest part. The second walk is much easier and intuitively understandable.&lt;&#x2F;p&gt;
&lt;p&gt;At this point, we have &lt;code&gt;preX&lt;&#x2F;code&gt;, &lt;code&gt;mod&lt;&#x2F;code&gt;, and &lt;code&gt;shift&lt;&#x2F;code&gt; parameters for every node in the tree.
Using the depth-first left-to-right walk, we determine the final &lt;code&gt;x&lt;&#x2F;code&gt; and &lt;code&gt;y&lt;&#x2F;code&gt; coordinates for every node.&lt;&#x2F;p&gt;
&lt;p&gt;For every node, the final &lt;code&gt;x&lt;&#x2F;code&gt; coordinate is the sum of all parent nodes &lt;code&gt;mod&lt;&#x2F;code&gt; and &lt;code&gt;shift&lt;&#x2F;code&gt; values plus its own &lt;code&gt;preX&lt;&#x2F;code&gt; and &lt;code&gt;shift&lt;&#x2F;code&gt; values.
In other words, we need to sum the &lt;code&gt;mod&lt;&#x2F;code&gt; and &lt;code&gt;shift&lt;&#x2F;code&gt; values of every parent node on our way to the node.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; shift&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* the sum of parent nodes mod and shift parameters *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; node&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;preX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; node&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;shift&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; shift&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For example, the final &lt;code&gt;x&lt;&#x2F;code&gt; coordinate for node13 is a sum of mod + shift values of nodes22,16,15 and its own x + shift values:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;tree-final-node13.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The best part is that we do not even need to create separate arrays&#x2F;lists to track parent nodes. We can calculate this sum recursively:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Pseudocode.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; secondWalk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;font-style: italic;&quot;&gt;node&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;font-style: italic;&quot;&gt; shift&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;font-style: italic;&quot;&gt; level&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; `shift` - sum of all parent nodes mod and shift values.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; child&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; node&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;getChildNodes&lt;&#x2F;span&gt;&lt;span&gt;()) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        secondWalk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;child&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; shift&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; node&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;mod&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; node&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;shift&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; level&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; node&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;preX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; node&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;shift&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; shift&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; level&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;NODE_HEIGHT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; NODES_GAP&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; At this point, (x, y) are final node coordinates.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Do whatever you need to do with them.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;secondWalk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;root&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s apply this to our example and see what we will get:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;tree-final.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;demo-grafily&quot;&gt;Demo: Grafily&lt;&#x2F;h1&gt;
&lt;p&gt;I hope the reader does not forget that my primary goal is to render family graphs.
Obviously, we cannot render all family members but &lt;strong&gt;only direct ancestors&lt;&#x2F;strong&gt;: parents, parents of parents, etc.&lt;&#x2F;p&gt;
&lt;p&gt;I adjusted the Reingold-Tilford Algorithm to family tree rendering and implemented it in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;grafily&#x2F;blob&#x2F;b9d281d35fe5def9a3b0b260c82375d44f4755b1&#x2F;src&#x2F;layout.ts&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;grafily&#x2F;b9d281d3&#x2F;src&#x2F;layout.ts&lt;&#x2F;a&gt;.
The whole implementation took me ~500 LoC.
This implementation is far from perfection and code can be cleaned a lot.
But I do not need any perfectionism here, and I know that I will rewrite it soon.&lt;&#x2F;p&gt;
&lt;p&gt;This is the example of the Reingold-Tilford algorithm in action:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;demo.jpg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;sup&gt;&lt;sub&gt;I was too lazy to create a separate vault with non-existent persons, so I just took a small subset of my real ancestors and blurred alive ones 🙃&lt;&#x2F;sup&gt;&lt;&#x2F;sub&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As you can see from the screenshot above, the algorithm successfully positioned marriages; there are no overlaps and all marriages are aligned.
At this point, I can call it a success 🤩 😎.&lt;&#x2F;p&gt;
&lt;p&gt;The main limitation of this approach: &lt;strong&gt;only direct ancestors are allowed&lt;&#x2F;strong&gt;. I also call it a school-level family tree.
It&#x27;s impossible to render siblings, their spouses, and their spouses&#x27; families (I call them parallel families).&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I adjusted the Reingold-Tilford Algorithm to family tree rendering...&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I did not change the algorithm itself, but added small tricks to the nodes&#x27; representation.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Every tree note is actually 3 nodes combined together: parent1 node + marriage node + parent2 node.
It was done to simplify the implementation of the algorithm and improve edge rendering.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;grafily&#x2F;blob&#x2F;b9d281d35fe5def9a3b0b260c82375d44f4755b1&#x2F;src&#x2F;layout.ts#L13-L19&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; +------------+                             +------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; |  parent1   |--------------o--------------|  parent2   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; +------------+                             +------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; | NODE_WIDTH | MARRIAGE_GAP | MARRIAGE_GAP | NODE_WIDTH |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; |                    MARRIAGE_WIDTH                     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; MARRIAGE_WIDTH&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;NODE_WIDTH&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; MARRIAGE_GAP&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I draw a tree with the root at the bottom and leaves on the top of the page.
In family trees, it is conventional to draw older generations on top.
On the other hand, that&#x27;s even better because now the tree looks actually like a real tree:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;real-tree.webp&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;conclusions&quot;&gt;Conclusions&lt;&#x2F;h1&gt;
&lt;p&gt;I hope my explanation is pretty clear to you, my dear reader. I did my best to make it easier to understand 😊.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, I would like to mention that implementing such an algorithm is a great exercise to boost your programming skills.
I have not had such algorithmic tasks in years. And when I started writing the Reingold-Tilford Algorithm for my plugin, I felt a small numbness.
Most of the time, I looked like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;draw-tree-using-reingold-tilford-algorithm&#x2F;.&#x2F;meme.jpg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The progress was super slow, and I spent a lot of time thinking about how to represent different parts of the algorithm in the code.
But in the end, I managed to get it done and am even a bit proud of myself.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;references&quot;&gt;References&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.cs.unc.edu&#x2F;techreports&#x2F;89-034.pdf&quot;&gt;A Node-Positioning Algorithm for General Trees. John Q. Walker II. September, 1989&lt;&#x2F;a&gt;.
This paper is awful. It was useless for me. I understand a bit more than nothing from it. I mentioned it just for curiosity.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;reingold.co&#x2F;tidier-drawings.pdf&quot;&gt;Tidier Drawings of Trees Edward M. Reingold and John S. Tilford.  March 1981&lt;&#x2F;a&gt;.
Another related paper just for curiosity and general intellectual development 🤣.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;towardsdatascience.com&#x2F;reingold-tilford-algorithm-explained-with-walkthrough-be5810e8ed93&#x2F;&quot;&gt;Reingold Tilford Algorithm Explained With Walkthrough. Sep 12, 2023&lt;&#x2F;a&gt;.
Excellent blog post 🤩 — good explanations, nice images, and illustrations. I recommend reading it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;williamyaoh.com&#x2F;posts&#x2F;2023-04-22-drawing-trees-functionally.html&quot;&gt;Drawing Trees Functionally: Reingold and Tilford, 1981. April 22, 2023&lt;&#x2F;a&gt;.
Another post with great explanation and even animations 🤩.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rachel53461.wordpress.com&#x2F;2014&#x2F;04&#x2F;20&#x2F;algorithm-for-drawing-trees&#x2F;&quot;&gt;Algorithm for Drawing Trees. April 20, 2014&lt;&#x2F;a&gt;.
Another blog post I found, but it was confusing for me and raised more questions than it answered.&lt;&#x2F;li&gt;
&lt;li&gt;My Reingold-Tilford Algorithm implementation: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;grafily&#x2F;blob&#x2F;b9d281d35fe5def9a3b0b260c82375d44f4755b1&#x2F;src&#x2F;layout.ts&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;grafily&#x2F;b9d281d3&#x2F;src&#x2F;layout.ts&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;obsidian.md&#x2F;&quot;&gt;Obsidian&lt;&#x2F;a&gt; official website.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.myheritage.com&#x2F;&quot;&gt;myheritage&lt;&#x2F;a&gt; official website.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tldraw&#x2F;tldraw&quot;&gt;tldraw&lt;&#x2F;a&gt; GitHub repository.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Announcing crypto-helper v.0.16.0</title>
        <published>2025-12-11T00:00:00+00:00</published>
        <updated>2025-12-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/announcing-crypto-helper-0-16/"/>
        <id>https://tbt.qkation.com/posts/announcing-crypto-helper-0-16/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/announcing-crypto-helper-0-16/">&lt;p&gt;Visit this tool at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crypto.qkation.com&quot;&gt;crypto.qkation.com&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Short release notes can be found here: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;releases&#x2F;tag&#x2F;v.0.16.0&quot;&gt;crypto-helper&#x2F;v.0.16.0&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;intro&quot;&gt;Intro&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;releases&#x2F;tag&#x2F;v.0.15.0&quot;&gt;The previous release&lt;&#x2F;a&gt; was around 1.5 years ago.
I&#x27;ve made many improvements and fixes since then. It&#x27;s time to publish a new release.&lt;&#x2F;p&gt;
&lt;p&gt;Note:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Actually, releases are just checkpoints during the &lt;code&gt;crypto-helper&lt;&#x2F;code&gt; development and do not mean anything special.&lt;&#x2F;em&gt;
&lt;em&gt;All features and fixes are deployed and available right after merging into the &lt;code&gt;main&lt;&#x2F;code&gt; branch.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This post contains a comprehensive list of new changes, along with additional explanations on how to use the new functionality.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;asn1-major-features&quot;&gt;ASN1 major features&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;asn1-tree-editing&quot;&gt;ASN1 tree editing&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;announcing-crypto-helper-0-16&#x2F;.&#x2F;asn1-tree-editing-pr-stats.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;105&quot;&gt;feat(asn1): implement asn1 tree editing (#105)&lt;&#x2F;a&gt; + &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;108&quot;&gt;fix: asn1: create&#x2F;delete pop-up shake on &lt;code&gt;ctrl&lt;&#x2F;code&gt; press&lt;&#x2F;a&gt; + &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;109&quot;&gt;fix(crypto-helper): asn1: remove node pop-up positioning&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is the most prominent and most wanted feature of this release.&lt;&#x2F;p&gt;
&lt;p&gt;I always wanted the ability to edit the ASN1 tree. It &lt;em&gt;just&lt;&#x2F;em&gt; feels right. If I can view, then I&#x27;m most likely going to edit...
But for the past few years, I have not had enough time and&#x2F;or motivation to implement it.
It was just an interesting idea (as many other ideas in my head). But it changed this summer, when I needed &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;pull&#x2F;483&#x2F;commits&#x2F;46d04e5b1cccf9aa7e9da704ddf063df6e049081#diff-5c9de79f33bbce03789d71e8b4c0fbd409a4bdcb4c746cedfe4cbfc428036ebf&quot;&gt;to generate different certificates&lt;&#x2F;a&gt; to test information extraction.&lt;&#x2F;p&gt;
&lt;p&gt;It was a nightmare. How can I generate the same cert with a few differences, such as extension&#x2F;enhanced key usage or alternate subject name properties?
I did not care if the cert is trusted or about the cert&#x27;s private key. I only needed certificate files. The task can be summarized as &lt;em&gt;how to edit the ASN1 tree&lt;&#x2F;em&gt;: add, change, or remove ASN1 nodes.&lt;&#x2F;p&gt;
&lt;p&gt;That time I decided to use my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;tree&#x2F;main&#x2F;crates&#x2F;asn1-parser&quot;&gt;&lt;code&gt;asn1-parser&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate and &lt;em&gt;just&lt;&#x2F;em&gt; wrote some tests that parse the original certificate, make the necessary changes, and encode it again in base64.
It wasn&#x27;t a pleasure to write such tests. After that, I decided to implement ASN1 tree editing no matter what.&lt;&#x2F;p&gt;
&lt;p&gt;After...&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- many hours of designing,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- a few PoCs,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- `asn1-parser` complete refactoring,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- 2.8k lines of code,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- ??? hours of development,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I finally came up with a working, very cool (IMHO) implementation. It works just as I wanted. I am even a bit proud of it 🥰.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;user-guide&quot;&gt;User guide&lt;&#x2F;h3&gt;
&lt;p&gt;So, how to edit the ASN1 tree? The page looks exactly the same as before ASN1 tree editing was implemented:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;announcing-crypto-helper-0-16&#x2F;.&#x2F;asn1-tree-example.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;editing&quot;&gt;Editing&lt;&#x2F;h4&gt;
&lt;p&gt;To &lt;strong&gt;edit&lt;&#x2F;strong&gt; an ASN1 node, hold &lt;code&gt;ctrl&lt;&#x2F;code&gt; + click on the node title. For example, let&#x27;s click on the &lt;code&gt;Integer&lt;&#x2F;code&gt; node:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;announcing-crypto-helper-0-16&#x2F;.&#x2F;inteter-editing.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You will see a pop-up menu. Here you can enter any value you want. Multiple formats supported: raw hex&#x2F;base64 bytes or decimal value (the value will be converted into bytes).&lt;&#x2F;p&gt;
&lt;p&gt;The changes take effect automatically when you type:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;announcing-crypto-helper-0-16&#x2F;.&#x2F;integer-editing.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;These editing rules apply to &lt;strong&gt;every node you see on the screen.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;deletion&quot;&gt;Deletion&lt;&#x2F;h4&gt;
&lt;p&gt;To &lt;strong&gt;delete&lt;&#x2F;strong&gt; an ASN1 node, hold &lt;code&gt;ctrl&lt;&#x2F;code&gt; and move the cursor to the start of the node title. You will see a trash icon. Click it and confirm deletion. It will automatically update the entire tree.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;announcing-crypto-helper-0-16&#x2F;.&#x2F;deletion-example.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;creation&quot;&gt;Creation&lt;&#x2F;h4&gt;
&lt;p&gt;To &lt;strong&gt;create&lt;&#x2F;strong&gt; an ASN1 node, hold &lt;code&gt;ctrl&lt;&#x2F;code&gt; and move the cursor between the other two notes where you want to insert a new node. You will see the plus icon.
Click on it. You will see a pop-up menu. Type the desired node type. The app will automatically select the suitable editor type for the entered node type.
Type in the data you want, then submit. Demo:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;announcing-crypto-helper-0-16&#x2F;.&#x2F;creation-example.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes you need to create more than one node at a time. For example, when you want to move one sub-tree from one place to another inside the tree.
The current implementation allows it, but with the help of a small workaround. Still, you can achieve the result by copying the sub-tree, deleting it, and then inserting it in the needed place by creating a new sub-tree from raw (hex&#x2F;base64) data.
Example:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;announcing-crypto-helper-0-16&#x2F;.&#x2F;sub-tree-moving-example.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;raw&lt;&#x2F;code&gt; data type is added on purpose: to allow multiple node creations at a time. I bet it will be helpful in many cases.
This technique allows the user to paste any kind of asn1 data at once.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wide-strings-auto-decoding&quot;&gt;Wide strings auto-decoding&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;103&quot;&gt;feat(crypto-helper): asn1: autodecode wide strings; (#103)&lt;&#x2F;a&gt;.
I often see that in some cases, strings can be encoded as UTF-16 inside the &lt;code&gt;OctetString&lt;&#x2F;code&gt; node. For example, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-cssp&#x2F;34ee27b3-5791-43bb-9201-076054b58123&quot;&gt;CredSSP&lt;&#x2F;a&gt; smart card credentials are encoded this way:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;announcing-crypto-helper-0-16&#x2F;.&#x2F;credssp-scard-credentials.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As you can see in the screenshot above, such buffers are now parsed as UTF-16 and printed as a standard string.&lt;&#x2F;p&gt;
&lt;p&gt;But I forgot that many other buffers can be a valid UTF-16. For example, in the screenshot below, you can see the highlighted encryption key, which was automatically decoded as UTF-16:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;announcing-crypto-helper-0-16&#x2F;.&#x2F;encryption-key-as-wide-string.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I still decided to keep this feature because it looks fun 😆. If I need to look at buffer bytes, I can always use the hex viewer to the right.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;crypto-helper-major-features&quot;&gt;crypto-helper major features&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;hmac-sha-support&quot;&gt;HMAC-SHA support&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;HMAC-SHA&lt;&#x2F;code&gt; algorithm support: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;commit&#x2F;dcc4e41f73e84e5e6f49d1d24e3abac128368e53&quot;&gt;crypto-helper&#x2F;commit&#x2F;dcc4e41f&lt;&#x2F;a&gt;. Including the following SHA variations: &lt;code&gt;SHA256&lt;&#x2F;code&gt;, &lt;code&gt;SHA384&lt;&#x2F;code&gt;, and &lt;code&gt;SHA512&lt;&#x2F;code&gt;. Demo:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;announcing-crypto-helper-0-16&#x2F;.&#x2F;hmac-sha-example.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;redirect-to-asn1&quot;&gt;Redirect to ASN1&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;95&quot;&gt;Add button to redirect output to ans1 page (#95)&lt;&#x2F;a&gt;. &lt;em&gt;&lt;strong&gt;Many thanks &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;grok-rs&quot;&gt;@grok-rs&lt;&#x2F;a&gt; for his contribution!&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;
The idea is simple: redirect to the ASN1 page and try to decode the result of the cryptographic operation as an ASN1 DER structure.&lt;&#x2F;p&gt;
&lt;p&gt;This feature is very useful for me when I want to decrypt and parse the encrypted part of the Kerberos message. For example:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;announcing-crypto-helper-0-16&#x2F;.&#x2F;asn1-redirect-example.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;other-changes&quot;&gt;Other changes&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;More OIDs: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;81&quot;&gt;#81&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;102&quot;&gt;#102&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Fix incorrect diff calculation: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;94&quot;&gt;#94&lt;&#x2F;a&gt;. &lt;em&gt;&lt;strong&gt;Many thanks &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;grok-rs&quot;&gt;@grok-rs&lt;&#x2F;a&gt; for his contribution!&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Allow empty &lt;code&gt;BitString&lt;&#x2F;code&gt; decoding: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;93&quot;&gt;#93&lt;&#x2F;a&gt;. &lt;em&gt;&lt;strong&gt;Many thanks &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;grok-rs&quot;&gt;@grok-rs&lt;&#x2F;a&gt; for his contribution!&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;CI: add build WASM step: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;commit&#x2F;814d16755e95d4f4e69b736c7917d578beb6d881&quot;&gt;crypto-helper&#x2F;commit&#x2F;814d1675&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Update dependencies and refactoring: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;83&quot;&gt;#83&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;87&quot;&gt;#87&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;101&quot;&gt;Rust 2024 edition (#101)&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;106&quot;&gt;#106&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;README.md&lt;&#x2F;code&gt; and typos fixes: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;79&quot;&gt;#79&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;pull&#x2F;80&quot;&gt;#80&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;commit&#x2F;15785bfecb6d23c7aea0c19f7953af07fa2e08c4&quot;&gt;crypto-helper&#x2F;commit&#x2F;15785bfe&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;commit&#x2F;dd47d963e8f56c3d65e80f4da059db094e474dfb&quot;&gt;crypto-helper&#x2F;commit&#x2F;dd47d963&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;references&quot;&gt;References&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;GitHub release: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;releases&#x2F;tag&#x2F;v.0.16.0&quot;&gt;crypto-helper&#x2F;v.0.16.0&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Official website: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crypto.qkation.com&quot;&gt;crypto.qkation.com&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Source code: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;&quot;&gt;TheBestTvarynka&#x2F;crypto-helper&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How RDP smart card logon works</title>
        <published>2025-11-24T00:00:00+00:00</published>
        <updated>2025-11-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/how-rdp-scard-logon-works/"/>
        <id>https://tbt.qkation.com/posts/how-rdp-scard-logon-works/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/how-rdp-scard-logon-works/">&lt;h1 id=&quot;intro&quot;&gt;Intro&lt;&#x2F;h1&gt;
&lt;p&gt;Around two years ago, FreeRDP got smart card logon support: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.hardening-consulting.com&#x2F;en&#x2F;posts&#x2F;20231004-smartcard-logon.html&quot;&gt;Smartcard logon with FreeRDP&lt;&#x2F;a&gt;.
Theoretically (and sometimes practically), it is possible to use a smart card (scard) for RDP logon in FreeRDP. In this post, I will explain how RDP scard logon works and how to set it up.&lt;&#x2F;p&gt;
&lt;p&gt;This post has two main parts: theoretical and practical. I was thinking about two separate posts, but then I decided that I don&#x27;t want to split theory and practice.&lt;&#x2F;p&gt;
&lt;p&gt;After reading this article, you should have enough understanding and skills to set up and troubleshoot your own RDP smart card logon.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; It is much easier to do smart card logon on Windows, so I assume we run FreeRDP on macOS and our target machine runs Windows.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You may be surprised (sarcasm), but it is not easy to do scard logon on macOS when connecting to the Windows machine.
It became easier with &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;pull&#x2F;492&quot;&gt;recent improvement&lt;&#x2F;a&gt; in &lt;code&gt;sspi-rs&lt;&#x2F;code&gt;. I have a lot to say, let&#x27;s dive in.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;how-it-works&quot;&gt;How it works&lt;&#x2F;h1&gt;
&lt;p&gt;Each section explains the theoretical aspects of RDP smart card logon and the software component we will use for it.
Sometimes it is not trivial because not all Microsoft components have exact replacements on macOS.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rdp-nla&quot;&gt;RDP NLA&lt;&#x2F;h2&gt;
&lt;p&gt;Now we need to understand how the scard authorization works. Without this knowledge, we can&#x27;t move further. The RDP is very complicated. So, I&#x27;ll focus my attention only on scard-related things.&lt;&#x2F;p&gt;
&lt;p&gt;So, the first thing you need to know is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Remote_Desktop_Services#Network_Level_Authentication&quot;&gt;Network Level Authentication&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Network Level Authentication (NLA) is a feature of RDP Server or Remote Desktop Connection (RDP Client) that requires the connecting user to authenticate themselves before a session is established with the server.&lt;&#x2F;p&gt;
&lt;p&gt;...&lt;&#x2F;p&gt;
&lt;p&gt;Network Level Authentication delegates the user&#x27;s credentials from the client through a client-side Security Support Provider and prompts the user to authenticate before establishing a session on the server.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Basically, NLA says: &quot;&lt;em&gt;Let&#x27;s authenticate the user (and the server, if the Kerberos protocol is used) before opening any GUI windows at the beginning of the RDP connection&lt;&#x2F;em&gt;&quot;.
And only when the user passes the authentication, the NLA will transfer credentials to the target server.
In turn, the RDP server will use these credentials to open the session.&lt;&#x2F;p&gt;
&lt;p&gt;NLA is not a concrete protocol but a general principle. In RDP, the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-cssp&#x2F;85f57821-40bb-46aa-bfcb-ba9590b8fc30&quot;&gt;CredSSP&lt;&#x2F;a&gt; protocol is responsible for the NLA.&lt;&#x2F;p&gt;
&lt;div class=&quot;mermaid&quot;&gt;
flowchart LR
    subgraph CREDSSP[&amp;quot;CredSSP&amp;quot;]
        subgraph SPNEGO[&amp;quot;SPNEGO&amp;quot;]
            subgraph ApplicationProtocol[&amp;quot;Negotiated Application Protocol (NTLM, Kerberos, etc)&amp;quot;]
            end
        end
    end
&lt;&#x2F;div&gt;
&lt;p&gt;The CredSSP protocol performs the user authentication (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-cssp&#x2F;78e0d50f-5a99-45e8-9f8b-d8a2bd67d4eb&quot;&gt;using NTLM&#x2F;Kerberos&#x2F;SPNEGO protocols inside&lt;&#x2F;a&gt;) and transfers the user&#x27;s credentials to the target server.
The CredSSP protocol is responsible only for credential delegation. It doesn&#x27;t authenticate clients or servers. An actual authentication is performed by the inner application protocol, like NTLM or Kerberos (preferably).&lt;&#x2F;p&gt;
&lt;p&gt;But Microsoft would not be Microsoft if it did not add another layer of abstraction. The CredSSP uses &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-spng&#x2F;b16309d8-4a93-4fa6-9ee2-7d84b2451c84&quot;&gt;the SPNEGO framework&lt;&#x2F;a&gt;: (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-cssp&#x2F;e36b36f6-edf4-4df1-9905-9e53b7d7c7b7&quot;&gt;quote src&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;SPNEGO provides a framework for two parties that are engaged in authentication to select from a set of possible authentication mechanisms.&lt;&#x2F;p&gt;
&lt;p&gt;...The CredSSP Protocol uses SPNEGO to mutually authenticate the CredSSP client and CredSSP server. It then uses the encryption key that is established under SPNEGO to securely bind to the TLS session.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Let&#x27;s summarize it.&lt;&#x2F;p&gt;
&lt;p&gt;The SPNEGO selects (negotiates) an appropriate authentication protocol and performs authentication using it.
As a result, we&#x27;ll have an established security context with a secure encryption key.
In turn, the CredSSP will use this key to encrypt the credentials and pass (delegate) them to the target CredSSP (RDP) server.&lt;&#x2F;p&gt;
&lt;p&gt;FreeRDP implements the CredSSP protocol, so there are no pitfalls.
Its CredSSP implementation can rely on either the built-in NTLM implementation, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;web.mit.edu&#x2F;kerberos&#x2F;krb5-latest&#x2F;doc&#x2F;&quot;&gt;the MIT KRB5 implementation&lt;&#x2F;a&gt;, or an external &lt;code&gt;&#x2F;sspi-module:&lt;&#x2F;code&gt; — a dynamic library that implements &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;sspi-introduction&#x2F;&quot;&gt;the SSPI interface&lt;&#x2F;a&gt;.
Spoiler: We will use an external library.&lt;&#x2F;p&gt;
&lt;p&gt;Good. Now you have a brief overview of the NLA. Now it&#x27;s time to move forward.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;kerberos&quot;&gt;Kerberos&lt;&#x2F;h2&gt;
&lt;p&gt;To log on with a smart card, we need SPNEGO to select Kerberos as the authentication protocol.
&lt;strong&gt;Kerberos is the only authentication protocol that can be used for scard logon.&lt;&#x2F;strong&gt;
To support password-less logon, Kerberos includes the PKINIT extension: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc4556&quot;&gt;Public Key Cryptography for Initial Authentication in Kerberos (PKINIT)&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The only difference between password-based Kerberos and scard-based is in the AS exchange (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc4120#section-3.1&quot;&gt;The Authentication Service Exchange&lt;&#x2F;a&gt;). During password-based logon, the AS exchange session key is derived from the user&#x27;s password:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;picky-rs&#x2F;blob&#x2F;628bbcab3100a782971261022f0ec91b4f4549f5&#x2F;picky-krb&#x2F;src&#x2F;crypto&#x2F;aes&#x2F;key_derivation.rs#L39-L51&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; derive_key_from_password&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; AsRef&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; S&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; AsRef&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    password&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; P&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    salt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    aes_size&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;AesSize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; KerberosCryptoResult&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; tmp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; aes_size&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;key_length&lt;&#x2F;span&gt;&lt;span&gt;()];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    pbkdf2_hmac&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Sha1&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; salt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; AES_ITERATION_COUNT&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; tmp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; For AES encryption (https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc3962.html#section-6):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; &amp;gt; random-to-key function    ``    identity function&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; temp_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; random_to_key&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;tmp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; A Key Derivation Function (https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc3961.html#section-5.1).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    derive_key&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;temp_key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; KERBEROS&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; aes_size&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Essentially, it means that if someone knows the user&#x27;s password, they can decrypt the &lt;code&gt;AsRep&lt;&#x2F;code&gt; encrypted part, extract a session key, and decrypt-and-extract all other sequential keys in the Kerberos authentication (e.g., TGS exchange session key).&lt;&#x2F;p&gt;
&lt;p&gt;Thus, always enforce a strong password policy 🙃. However, I am not here to talk about Kerberos attack vectors and vulnerabilities.
So, what is different in the scard-based logon?&lt;&#x2F;p&gt;
&lt;p&gt;During the scard-based logon, the AS exchange session key is derived using the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc4556#section-3.2.3.1&quot;&gt;the Diffie-Hellman Key Exchange&lt;&#x2F;a&gt;.
PKINIT also defines the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc4556#section-3.2.3.2&quot;&gt;Public Key Encryption&lt;&#x2F;a&gt;, but I haven&#x27;t seen it in action ever.
I always see the Diffie-Hellman Key Exchange in the Wireshark capture of the &lt;code&gt;mstsc&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Diffie%E2%80%93Hellman_key_exchange&quot;&gt;Diffie–Hellman (DH) key exchange&lt;&#x2F;a&gt; is a mathematical method of securely generating a symmetric cryptographic key over a public channel.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It means that two parties can &lt;strong&gt;&lt;em&gt;securely&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; establish an encryption key over a public network.
There are tons of articles explaining how the Diffie-Hellman Key Agreement works.
Let me paste only a small description and move on.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The client generates DH parameters and a private key.&lt;&#x2F;li&gt;
&lt;li&gt;Using the DH parameters and private key, the client generates the public key.&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;picky-rs&#x2F;blob&#x2F;628bbcab3100a782971261022f0ec91b4f4549f5&#x2F;picky-krb&#x2F;src&#x2F;crypto&#x2F;diffie_hellman.rs#L145-L149&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; [Key and Parameter Requirements](https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc2631#section-2.2)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; y is then computed by calculating g^x mod p.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; compute_public_key&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;private_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; modulus&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; base&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; DiffieHellmanResult&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    generate_dh_shared_secret&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;base&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; private_key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; modulus&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The client sends DH parameters and public key to the server (KDC in our case).&lt;&#x2F;li&gt;
&lt;li&gt;The server generates its own private and public keys.&lt;&#x2F;li&gt;
&lt;li&gt;Both parties can generate the shared secret (symmetric encryption key) using the DH algorithm:&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;picky-rs&#x2F;blob&#x2F;628bbcab3100a782971261022f0ec91b4f4549f5&#x2F;picky-krb&#x2F;src&#x2F;crypto&#x2F;diffie_hellman.rs#L94-L112&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; [Using Diffie-Hellman Key Exchange](https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc4556.html#section-3.2.3.1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; let DHSharedSecret be the shared secret value. DHSharedSecret is the value ZZ&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; [Generation of ZZ](https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc2631#section-2.1.1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; ZZ = g ^ (xb * xa) mod p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; ZZ = (yb ^ xa)  mod p  = (ya ^ xb)  mod p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; where ^ denotes exponentiation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; generate_dh_shared_secret&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;public_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; private_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; DiffieHellmanResult&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; public_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; BoxedUint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from_be_slice_vartime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;public_key&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; private_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; BoxedUint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from_be_slice_vartime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;private_key&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Odd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;BoxedUint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from_be_slice_vartime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;into_option&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;ok_or&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;DiffieHellmanError&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;ModulusIsNotOdd&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; BoxedMontyParams&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new_vartime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; ZZ = (public_key ^ private_key) mod p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; pow_mod_params&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;public_key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;private_key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;out&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_be_bytes&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_vec&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Using the derived encryption key, the server encrypts all needed data and sends it to the client alongside the DH public key.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Of course, I&#x27;ve omitted many technical details, but I&#x27;m here to convey the overall idea, not to teach you cryptography.
The astute reader may notice that the smart card is not required for the Diffie-Hellman exchange.&lt;&#x2F;p&gt;
&lt;p&gt;The smart card is needed &lt;strong&gt;&lt;em&gt;ONLY&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; for signing the digest of all these public authentication parameters: DH parameters, DH public key, nonce, etc (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;ffd920b7b396739b60a6e1bae701f31e735deeef&#x2F;src&#x2F;pk_init.rs#L75-L239&quot;&gt;source code&lt;&#x2F;a&gt;).
The KDC will verify the signature using the client&#x27;s certificate.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s all 🙃. Someday I will write a detailed post about Kerberos scard auth, but today is not that day 😬.&lt;&#x2F;p&gt;
&lt;p&gt;The FreeRDP itself does not implement the Kerberos protocol. It uses the external library for that instead.
FreeRDP&#x27;s CredSSP implementation uses &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;sspi-introduction&#x2F;&quot;&gt;the SSPI interface&lt;&#x2F;a&gt; to perform the authentication.
Here we have a few options:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Enable the &lt;code&gt;WITH_KRB5&lt;&#x2F;code&gt; and &lt;code&gt;WITH_KRB5_MIT&lt;&#x2F;code&gt; flags and provide &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;web.mit.edu&#x2F;kerberos&#x2F;krb5-latest&#x2F;doc&#x2F;&quot;&gt;MIT KRB5&lt;&#x2F;a&gt; library for FreeRDP (see &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;FreeRDP&#x2F;FreeRDP&#x2F;wiki&#x2F;Compilation&quot;&gt;FreeRDP&#x2F;wiki&#x2F;Compilation&lt;&#x2F;a&gt;).
FreeRDP has a wrapper over MIT KRB5 to export its functionality via the SSPI interface: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;FreeRDP&#x2F;FreeRDP&#x2F;blob&#x2F;2eb88390f94071c0d46974381a3953e0d382f114&#x2F;winpr&#x2F;libwinpr&#x2F;sspi&#x2F;Kerberos&#x2F;krb5glue_mit.c&quot;&gt;FreeRDP&#x2F;winpr&#x2F;libwinpr&#x2F;sspi&#x2F;Kerberos&#x2F;krb5glue_mit.c&lt;&#x2F;a&gt; + &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;FreeRDP&#x2F;FreeRDP&#x2F;blob&#x2F;2eb88390f94071c0d46974381a3953e0d382f114&#x2F;winpr&#x2F;libwinpr&#x2F;sspi&#x2F;Kerberos&#x2F;kerberos.c&quot;&gt;FreeRDP&#x2F;winpr&#x2F;libwinpr&#x2F;sspi&#x2F;Kerberos&#x2F;kerberos.c&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Provide our own SSPI implementation using the &lt;code&gt;&#x2F;sspi-module&lt;&#x2F;code&gt; arg. It can be any library that implements the SSPI interface.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Surprisingly, we will follow the second path. We will use the following open-source SSPI implementation: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&quot;&gt;github&#x2F;Devolutions&#x2F;sspi-rs&lt;&#x2F;a&gt;. It supports both Kerberos password-based and scard-based logon and has various other pros:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Easier to set up and configure.&lt;&#x2F;li&gt;
&lt;li&gt;Easier logs reading and configuring.&lt;&#x2F;li&gt;
&lt;li&gt;Do not need to install new packages (e.g., &lt;code&gt;libkrb5-dev&lt;&#x2F;code&gt;) and link them with FreeRDP.&lt;&#x2F;li&gt;
&lt;li&gt;Implemented in Rust 🙃.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;scard-credentials&quot;&gt;Scard credentials&lt;&#x2F;h2&gt;
&lt;p&gt;During password-based logon, the CredSSP client transfers the user&#x27;s username, password, and domain to the target server.
In turn, the target server tries to log in the user using these credentials.
But we cannot send the smart card to the target server 🙃. According to the specification, smart card credentials are defined as follows:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; https&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-cssp&#x2F;94a1ab00-5500-42fd-8d3d-7a84e6c2cf03&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;TSCredentials&lt;&#x2F;span&gt;&lt;span&gt; ::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; SEQUENCE&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        credType&lt;&#x2F;span&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; INTEGER&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        credentials&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; OCTET STRING&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; credType&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt; 2.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; Credentials contains a TSSmartCardCreds structure that defines the user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;#39;s smart card credentials. &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; https&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-cssp&#x2F;4251d165-cf01-4513-a5d8-39ee4a98b7a4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;TSSmartCardCreds&lt;&#x2F;span&gt;&lt;span&gt; ::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; SEQUENCE&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        pin&lt;&#x2F;span&gt;&lt;span&gt;         [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; OCTET STRING&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        cspData&lt;&#x2F;span&gt;&lt;span&gt;     [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; TSCspDataDetail&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        userHint&lt;&#x2F;span&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; OCTET STRING OPTIONAL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        domainHint&lt;&#x2F;span&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; OCTET STRING OPTIONAL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; https&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-cssp&#x2F;34ee27b3-5791-43bb-9201-076054b58123&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;TSCspDataDetail&lt;&#x2F;span&gt;&lt;span&gt; ::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; SEQUENCE&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        keySpec&lt;&#x2F;span&gt;&lt;span&gt;       [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; INTEGER&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        cardName&lt;&#x2F;span&gt;&lt;span&gt;      [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; OCTET STRING OPTIONAL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        readerName&lt;&#x2F;span&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; OCTET STRING OPTIONAL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        containerName&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; OCTET STRING OPTIONAL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        cspName&lt;&#x2F;span&gt;&lt;span&gt;       [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; OCTET STRING OPTIONAL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I want to go through every field and explain its meaning:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;credType&lt;&#x2F;code&gt; = &lt;code&gt;2&lt;&#x2F;code&gt; (according to the specification).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pin&lt;&#x2F;code&gt; - smart card PIN code.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;userHint&lt;&#x2F;code&gt; - username. &lt;strong&gt;Important&lt;&#x2F;strong&gt;: the username must be &lt;strong&gt;only&lt;&#x2F;strong&gt; username. The target server &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;pull&#x2F;494&quot;&gt;may reject&lt;&#x2F;a&gt; the FQDN. &lt;code&gt;t2@example.com&lt;&#x2F;code&gt; ❌ -&amp;gt; &lt;code&gt;t2&lt;&#x2F;code&gt; ✅.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;domainHint&lt;&#x2F;code&gt; - domain.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;keySpec&lt;&#x2F;code&gt; = &lt;code&gt;AT_KEYEXCHANGE&lt;&#x2F;code&gt; = &lt;code&gt;1&lt;&#x2F;code&gt;. (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-server&#x2F;identity&#x2F;ad-fs&#x2F;technical-reference&#x2F;ad-fs-and-keyspec-property&quot;&gt;AD FS and certificate KeySpec property information&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The KeySpec property identifies how a key, that is generated or retrieved using the Microsoft CryptoAPI (CAPI) from a Microsoft legacy Cryptographic Storage Provider (CSP), can be used.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Typically, this value equals &lt;code&gt;AT_KEYEXCHANGE&lt;&#x2F;code&gt;. Since this value is not encoded in the certificate or smart card, we can set it manually in the credentials.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;cardName&lt;&#x2F;code&gt; - smart card name. It can be any name.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;cspName&lt;&#x2F;code&gt;. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secgloss&#x2F;c-gly&quot;&gt;Cryptographic Service Provider&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;An independent software module that actually performs cryptography algorithms for authentication, encoding, and encryption.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In our case, it is always equal to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;seccertenroll&#x2F;cryptoapi-cryptographic-service-providers#microsoft-base-smart-card-crypto-provider&quot;&gt;&lt;code&gt;Microsoft Base Smart Card Crypto Provider&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
It supports smart cards and implements algorithms for hashing, signing, and encrypting data. We do not need to know internals, but only that it uses smart cards for crypto operations.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;readerName&lt;&#x2F;code&gt;. (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-rdpesc&#x2F;d361b24c-611e-46c5-9ac6-93cb6490a472&quot;&gt;quote src&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;smart card reader name&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;: The friendly, human-readable name of the &lt;em&gt;smart card reader&lt;&#x2F;em&gt;. Also referred to as a &lt;em&gt;Reader Name&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;smart card reader&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;: A device used as a communication medium between the smart card and a Host; for example, a computer. Also referred to as a Reader.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The system automatically generates the Reader Name on Windows. But we need to take it from somewhere on macOS. In short, the PKCS11 slot description is used as the reader name.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;containerName&lt;&#x2F;code&gt;. (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secgloss&#x2F;k-gly&quot;&gt;quote src&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;key container - A part of the key database that contains all the key pairs (exchange and signature key pairs) belonging to a specific user. Each container has a unique name used when calling &lt;code&gt;CryptAcquireContext&lt;&#x2F;code&gt; to obtain a handle to the container.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Therefore, the container name is a &lt;em&gt;unique&lt;&#x2F;em&gt; string that represents the smart card certificate and its private key.
And, of course, it is internally generated during scard certificate enrollment on Windows.
We cannot precalculate or extract it from somewhere. A small trick is used to generate this value:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;dea60b5ef60932efdbf22e0806954d8c236fbb78&#x2F;ffi&#x2F;src&#x2F;winscard&#x2F;piv.rs#L134C1-L212&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; chuid_to_container_name&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;chuid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; tag&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; ... (some lines are omitted) ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; `chuid` - smart card Card Holder Unique Identifier.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; guid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;chuid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;BYTES_TO_SKIP&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;BYTES_TO_SKIP&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* GUID length *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Construct the value Windows would use for a PIV key&amp;#39;s container name.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; container_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;        &amp;quot;{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        guid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        guid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        guid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        guid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        guid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        guid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        guid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        guid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        guid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        guid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;9&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        guid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        guid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;11&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        guid&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        tag&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        tag&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        tag&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;container_name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is how &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;FreeRDP&#x2F;FreeRDP&#x2F;blob&#x2F;3fc1c3ce31b5af1098d15603d7b3fe1c93cf77a5&#x2F;winpr&#x2F;libwinpr&#x2F;ncrypt&#x2F;ncrypt_pkcs11.c#L865-L964&quot;&gt;FreeRDP constructs&lt;&#x2F;a&gt; a container name for the certificate.
It takes a smart card CHUID, extracts a GUID value, and combines it with the certificate PIV tag to construct a unique container name.
Since every smart card CHUID is unique and there is only one certificate per slot, the constructed value is guaranteed to be unique.
Moreover, the uniqueness is not the critical part. The crucial part is that the container name format must meet Windows expectations.
Last year, in one of my posts, I explained and provided an example of how a bad container name can cause issues in smart card logon: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;#what&quot;&gt;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;#what&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;scard-driver&quot;&gt;Scard driver&lt;&#x2F;h2&gt;
&lt;p&gt;As explained above, the Kerberos protocol does client and server authentication. And, as we can logically assume, it relies on some APIs to communicate with the smart card.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s first discuss how it works on Windows, then move on to macOS. Look at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;security&#x2F;identity-protection&#x2F;smart-cards&#x2F;smart-card-architecture&quot;&gt;this diagram from the MSDN&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;how-rdp-scard-logon-works&#x2F;sc-image203.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The Kerberos implementation uses the Windows high-level cryptographic API to communicate with the smart card. Using &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;wincred&#x2F;ns-wincred-cert_credential_info&quot;&gt;the certificate hash&lt;&#x2F;a&gt;, it can get the user&#x27;s certificate, container name, and all other smart card credentials.
Windows allows using vendor-specific CSPs, but the default &lt;code&gt;basecsp.dll&lt;&#x2F;code&gt; is used during RDP smart card auth.&lt;&#x2F;p&gt;
&lt;p&gt;In turn, the &lt;code&gt;basecsp.dll&lt;&#x2F;code&gt; uses the smart card minidriver to perform cryptographic operations.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;smartcard&#x2F;smart-card-minidrivers&quot;&gt;Smart Card Minidrivers&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The smart card minidriver provides a simpler alternative to developing a legacy cryptographic service provider (CSP) by encapsulating most of the complex cryptographic operations from the card minidriver developer.&lt;&#x2F;p&gt;
&lt;p&gt;Applications use CAPI for smart card–based cryptographic services. CAPI, in turn, routes these requests to the appropriate CSP to handle the cryptographic requirements.
Although Base CSP can use the RSA capabilities of a smart card only by using the minidriver...&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;smartcard&#x2F;smart-card-minidriver-overview&quot;&gt;Smart Card Minidriver Overview&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The card-specific minidriver is the lowest logical interface layer in the Base CSP&#x2F;KSP. This minidriver lets the Base CSP&#x2F;KSP and applications interact directly with a specific type of card by using SCRM.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In simple words, the smart card minidriver is a small dll provided by the card vendor that implements &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;previous-versions&#x2F;windows&#x2F;hardware&#x2F;design&#x2F;dn631754(v=vs.85)&quot;&gt;the Smart Card Minidriver specification&lt;&#x2F;a&gt;.
This dll is used by BaseCSP to perform basic cryptography operations. This allows card vendors to reuse Microsoft&#x27;s cryptography stack and not implement their own CSP:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;how-rdp-scard-logon-works&#x2F;capiinterface.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I have the &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;how-rdp-scard-logon-works&#x2F;www.yubico.com&#x2F;ua&#x2F;product&#x2F;yubikey-5-nano&#x2F;&quot;&gt;YubiKey 5 Nano&lt;&#x2F;a&gt; smart card and will use it in this article.
Of course, YubiKey has its own &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.yubico.com&#x2F;support&#x2F;download&#x2F;smart-card-drivers-tools&#x2F;&quot;&gt;smart card minidriver implementation&lt;&#x2F;a&gt;, which must be installed on the target machine: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;support.yubico.com&#x2F;hc&#x2F;en-us&#x2F;articles&#x2F;360015654560-Deploying-the-YubiKey-Smart-Card-Minidriver-to-workstations-and-servers&quot;&gt;Deploying the YubiKey Smart Card Minidriver to workstations and servers&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But what about macOS? We do not have minidrivers here... FreeRDP (and &lt;code&gt;sspi-rs&lt;&#x2F;code&gt;) relies on the PKCS11 module (a dynamic library) for executing cryptographic operations.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;In cryptography, &lt;strong&gt;PKCS #11&lt;&#x2F;strong&gt; is a Public-Key Cryptography Standard that defines a C programming interface to create and manipulate cryptographic tokens that may contain secret cryptographic keys. It is often used to communicate with a Hardware Security Module or smart cards. (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;PKCS_11&quot;&gt;Wiki&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Fortunately, YubiKey also distributes its own PKCS11 library: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developers.yubico.com&#x2F;yubico-piv-tool&#x2F;YKCS11&#x2F;&quot;&gt;&lt;code&gt;libykcs11.2.7.2.dylib&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;However, that&#x27;s not the end: each smart card minidriver communicates with the smart card through a unified API: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winscard&#x2F;&quot;&gt;WinSCard API&lt;&#x2F;a&gt;. ⬇️&lt;&#x2F;p&gt;
&lt;h2 id=&quot;winscard&quot;&gt;WinSCard&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;The basic parts of the smart card subsystem are based on PC&#x2F;SC standards (see the specifications at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pcscworkgroup.com&quot;&gt;https:&#x2F;&#x2F;pcscworkgroup.com&lt;&#x2F;a&gt;). (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;smart-card-authentication&quot;&gt;src&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The WinSCard API enables communications with smart card hardware. It is the lowest API from the software perspective.&lt;&#x2F;p&gt;
&lt;p&gt;The WinSCard API is based on the PC&#x2F;SC (Personal Computer&#x2F;Smart Card) specification - a globally implemented standard for cards and readers (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.smartcardbasics.com&#x2F;pc-sc&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.smartcardbasics.com&#x2F;pc-sc&#x2F;&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The advantage of PC&#x2F;SC is that applications do not have to acknowledge the details corresponding to the smart card reader when communicating with the smart card. This application can function with any reader that complies with the PC&#x2F;SC standard. (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.cardlogix.com&#x2F;glossary&#x2F;pc-sc&#x2F;&quot;&gt;src&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;On Windows, we have WinSCard API, but on macOS, we have &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pcsclite.apdu.fr&#x2F;&quot;&gt;pcsc-lite&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;PC&#x2F;SC is the de facto cross-platform API for accessing smart card readers. It is published by &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;www.pcscworkgroup.com&#x2F;&quot;&gt;PC&#x2F;SC Workgroup&lt;&#x2F;a&gt;, but the &lt;em&gt;&quot;reference implementation&quot;&lt;&#x2F;em&gt; is Windows. Linux and Mac OS X use the open source &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pcsclite.apdu.fr&#x2F;&quot;&gt;pcsc-lite&lt;&#x2F;a&gt; package. (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;OpenSC&#x2F;OpenSC&#x2F;wiki&#x2F;PCSC-and-pcsc-lite&quot;&gt;src&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Everything looks good at first sight: &lt;code&gt;libykcs11&lt;&#x2F;code&gt; uses &lt;code&gt;pcsc-lite&lt;&#x2F;code&gt;, both of them are available on macOS. Seems like nothing stops us from scard logon.
Unfortunately, there is one thing.&lt;&#x2F;p&gt;
&lt;p&gt;The target machine tries to open a new session using the transferred smart card credentials. Internally, the same high-level APIs are used except for the WinSCard API.
All WinSCard API calls are redirected to the client machine (via &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-rdpesc&#x2F;0428ca28-b4dc-46a3-97c3-01887fa44a90&quot;&gt;[MS-RDPESC]: Remote Desktop Protocol: Smart Card Virtual Channel Extension&lt;&#x2F;a&gt;). Soooo?
Obviously, we will call the &lt;code&gt;pcsc-lite&lt;&#x2F;code&gt; API on macOS instead of WinSCard because we do not have WinSCard here. The problem is that the &lt;code&gt;pcsc-lite&lt;&#x2F;code&gt; API does not match the WinSCard API identically.
There are differences:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Most of them are listed in the documentation: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pcsclite.apdu.fr&#x2F;api&#x2F;group__API.html#differences&quot;&gt;https:&#x2F;&#x2F;pcsclite.apdu.fr&#x2F;api&#x2F;group__API.html#differences&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;pcsc-lite&lt;&#x2F;code&gt; API does not contain some functions as WinSCard. For example: &lt;code&gt;SCardReadCache&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Some function has &lt;code&gt;-A&lt;&#x2F;code&gt; and &lt;code&gt;-W&lt;&#x2F;code&gt; variations. For example: &lt;code&gt;SCardConnectA&lt;&#x2F;code&gt; and &lt;code&gt;SCardConnectW&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A &lt;code&gt;pcsc-lite&lt;&#x2F;code&gt; wrapper needed to be implemented to match the original WinSCard API. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;FreeRDP&#x2F;FreeRDP&#x2F;blob&#x2F;3fc1c3ce31b5af1098d15603d7b3fe1c93cf77a5&#x2F;winpr&#x2F;libwinpr&#x2F;smartcard&#x2F;smartcard_pcsc.c#L3185-L3265&quot;&gt;FreeRDP&#x27;s  implementation&lt;&#x2F;a&gt; is not complete.
It lacks a proper WinSCard cache implementation. The target machine expects the client-side to have the required WinSCard smart card cache items.&lt;&#x2F;p&gt;
&lt;p&gt;It is a real problem: the target machine will not authenticate the client without a properly working smart card cache. Otherwise, the target machine will display a message such as &lt;em&gt;&quot;This smart card could not be used. Additional detail may be available in the system log. Please report this error to your administrator.&quot;&lt;&#x2F;em&gt; or &lt;em&gt;&quot;The requested key container does not exist on the smart card.&quot;&lt;&#x2F;em&gt;. If you are interested in smart card cache items, then check my old post: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;win-scard-cache&#x2F;&quot;&gt;tbt.qkation.com&#x2F;posts&#x2F;win-scard-cache&#x2F;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To my knowledge, the &lt;code&gt;sspi-rs&lt;&#x2F;code&gt;&#x27;s FFI module is the only open-source library that implements proper smart card cache items: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;dea60b5ef60932efdbf22e0806954d8c236fbb78&#x2F;ffi&#x2F;src&#x2F;winscard&#x2F;system_scard&#x2F;context.rs#L283-L564&quot;&gt;github&#x2F;Devolutions&#x2F;sspi-rs&#x2F;dea60b5e&#x2F;ffi&#x2F;src&#x2F;winscard&#x2F;system_scard&#x2F;context.rs#L283-L564&lt;&#x2F;a&gt;.
Now, with this final software component, we can finally set up FreeRDP scard logon 🤩 🥵.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;let-s-put-it-all-together&quot;&gt;Let&#x27;s put it all together&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;software component&lt;&#x2F;th&gt;&lt;th&gt;meaning&lt;&#x2F;th&gt;&lt;th&gt;Windows&lt;&#x2F;th&gt;&lt;th&gt;macOS&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;RDP client&lt;&#x2F;td&gt;&lt;td&gt;&lt;em&gt;no comments&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;mstsc.exe&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;FreeRDP&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;CredSSP protocol&lt;&#x2F;td&gt;&lt;td&gt;Performs NLA. Transfers user credentials to the target server&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;credssp.dll&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;FreeRDP&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Kerberos protocol&lt;&#x2F;td&gt;&lt;td&gt;Authenticates the user and the server. Established the security context&lt;&#x2F;td&gt;&lt;td&gt;Implemented inside Windows&lt;&#x2F;td&gt;&lt;td&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;tree&#x2F;master&#x2F;ffi&#x2F;src&#x2F;sspi&quot;&gt;&lt;code&gt;libsspi.dylib&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; - Kerberos client implementation with scard logon support&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Smart card (mini)driver&lt;&#x2F;td&gt;&lt;td&gt;Transforms high-level crypto operations into low-level PCSC commands&lt;&#x2F;td&gt;&lt;td&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.yubico.com&#x2F;support&#x2F;download&#x2F;smart-card-drivers-tools&#x2F;&quot;&gt;YubiKey Smart Card Minidriver&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developers.yubico.com&#x2F;yubico-piv-tool&#x2F;YKCS11&#x2F;&quot;&gt;&lt;code&gt;libykcs11.2.7.2.dylib&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; - a PKCS#11 module&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;PC&#x2F;SC&lt;&#x2F;td&gt;&lt;td&gt;Enables communications with smart card hardware&lt;&#x2F;td&gt;&lt;td&gt;WinSCard&lt;&#x2F;td&gt;&lt;td&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;tree&#x2F;master&#x2F;ffi&#x2F;src&#x2F;winscard&quot;&gt;&lt;code&gt;libsspi.dylib&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; - WinSCard-compatible &lt;code&gt;pcsc-lite&lt;&#x2F;code&gt; wrapper with proper smart card cache implementation&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;At this point, I hope it all makes sense to you 🤞.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;setting-up&quot;&gt;Setting up&lt;&#x2F;h1&gt;
&lt;p&gt;Finally! We&#x27;ve lived enough to start configuring this machinery 🤩.&lt;&#x2F;p&gt;
&lt;p&gt;If you would like to replicate the configuration below in your own environment, I have some prerequisites for you:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You know how to configure, and even more, you have them configured:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Windows Server Active Directory and Certificate Authority.&lt;&#x2F;li&gt;
&lt;li&gt;Domain joined-machines to make the RDP connection.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;You possess a YubiKey, a PIV-compatible smart card device. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.yubico.com&#x2F;authentication-standards&#x2F;smart-card&#x2F;&quot;&gt;The list of suitable devices&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;YubiKey 5 NFC, YubiKey 5 Nano, YubiKey 5C, and YubiKey 5C Nano provide Smart Card functionality based on the Personal Identity Verification (PIV) interface specified in NIST SP 800-73, “Cryptographic Algorithms and Key Sizes for PIV.”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;For example, I own a YubiKey 5 Nano.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;You enrolled in the smart card certificate.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;smart-card&quot;&gt;Smart card&lt;&#x2F;h2&gt;
&lt;p&gt;I already have a ready-to-go smart card. The user certificate is enrolled and valid:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;ykman&lt;&#x2F;span&gt;&lt;span&gt; piv info&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You should have something like that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;PIV&lt;&#x2F;span&gt;&lt;span&gt; version:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;              5.4.3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;PIN&lt;&#x2F;span&gt;&lt;span&gt; tries remaining:      3&#x2F;3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;PUK&lt;&#x2F;span&gt;&lt;span&gt; tries remaining:      0&#x2F;3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Management&lt;&#x2F;span&gt;&lt;span&gt; key algorithm: TDES&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;WARNING:&lt;&#x2F;span&gt;&lt;span&gt; Using default PIN!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;PUK&lt;&#x2F;span&gt;&lt;span&gt; is blocked&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Management&lt;&#x2F;span&gt;&lt;span&gt; key is stored on the YubiKey, protected by PIN.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;CHUID:&lt;&#x2F;span&gt;&lt;span&gt; 3019d4e739da739ced39ce739d836858210842108421c84210c3eb34101df30c281471d9a216caed2291f8e494350832303330303130313e00fe00&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;CCC:&lt;&#x2F;span&gt;&lt;span&gt;   No data available&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Slot&lt;&#x2F;span&gt;&lt;span&gt; 9A (AUTHENTICATION):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;  Private&lt;&#x2F;span&gt;&lt;span&gt; key type: RSA2048&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;  Public&lt;&#x2F;span&gt;&lt;span&gt; key type:  RSA2048&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;  Subject&lt;&#x2F;span&gt;&lt;span&gt; DN:       &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;  Issuer&lt;&#x2F;span&gt;&lt;span&gt; DN:        CN=tbt-WIN-956CQOSSJTF-CA,DC=tbt,DC=com&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;  Serial:&lt;&#x2F;span&gt;&lt;span&gt;           00:1c:00:00:00:11:a3:a9:8c:0c:7d:22:25:df:00:00:00:00:00:11&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;  Fingerprint:&lt;&#x2F;span&gt;&lt;span&gt;      bbb2ff52231e831d4d7b3c575c8f7bb8c50c941ac2121a0000d68d4d540255e5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;  Not&lt;&#x2F;span&gt;&lt;span&gt; before:       2025-10-23T17:17:44+00:00&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;  Not&lt;&#x2F;span&gt;&lt;span&gt; after:        2027-10-23T17:27:44+00:00&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Slot&lt;&#x2F;span&gt;&lt;span&gt; 9D (KEY_MANAGEMENT):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;  Private&lt;&#x2F;span&gt;&lt;span&gt; key type: RSA2048&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And here is the certificate itself: &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;how-rdp-scard-logon-works&#x2F;.&#x2F;t2@tbt.com.cer&quot;&gt;&lt;code&gt;t2@tbt.com.cer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. You can export it from your smart card using the following command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;ykman&lt;&#x2F;span&gt;&lt;span&gt; piv certificates export ${&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;SLOT_ID&lt;&#x2F;span&gt;&lt;span&gt;} ${&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;PATH_TO_FILE&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Example:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;ykman&lt;&#x2F;span&gt;&lt;span&gt; piv certificates export 9a ~&#x2F;delete_it&#x2F;t2@tbt.com.cer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And the last step in configuring the smart card is installing &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developers.yubico.com&#x2F;yubico-piv-tool&#x2F;YKCS11&#x2F;&quot;&gt;&lt;code&gt;libykcs11.2.7.2.dylib&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;YKCS11 is automatically built as part of yubico-piv-tool&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; clone https:&#x2F;&#x2F;github.com&#x2F;Yubico&#x2F;yubico-piv-tool.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span&gt; yubico-piv-tool&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span&gt; build;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; cd&lt;&#x2F;span&gt;&lt;span&gt; build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;cmake&lt;&#x2F;span&gt;&lt;span&gt; ..&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;make&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; make install&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When working with smart cards, I like to check if the smart scard works well using the following command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;TheBestTvarynka&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; pkcs11-tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --module&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;&#x2F;usr&#x2F;local&#x2F;lib&#x2F;libykcs11.2.7.2.dylib&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; -m&lt;&#x2F;span&gt;&lt;span&gt; RSA-PKCS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; -p 123456 -s --id 01&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; base64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# You should get the base64-encoded signature:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# SRA+CTXAYJRO3Wz42K9W&#x2F;4qeHlV2WmY&#x2F;t6bDumdSOf7+KL1&#x2F;32E7Cuq55GIdkDnZnCfHZp89Eyq&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# TEcV2GAnbyiMiUqlZb1iBEYyYOf5ovaJ7xy4dPIuEvkJLMVJPpCCJ7Cr9zolpTEmfZ7FMZVbtprS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# 04ho4P2lz60eJ00Bykrerwc4FcmIPs7tNX&#x2F;&#x2F;1EJVNLrlXdEBYlxH8ZOFnYtMUggf80EJJlWxTHjT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# ZTz8&#x2F;+KNZRSFwHR+lZikzxMDaVx4Kiq+2w5NMrSA0MQlFA7fvHOBRh4LBAdHPHzXmgCMWNM1cAbm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# h9PrXdMlo24Xdj+EHZRRLsD7HfeVYPWYNhCvoC0tW1RCVF0tPjogR2V0RnVuY3Rpb25MaXN0IHN0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# YXJ0IQotLVtUQlRdLT46IEdldEZ1bmN0aW9uTGlzdCBzdWNjZXNzIQo=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;winscard-1&quot;&gt;WinSCard&lt;&#x2F;h2&gt;
&lt;p&gt;As I said above, we will use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&quot;&gt;&lt;code&gt;sspi-rs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to provide FreeRDP with the custom WinSCard API implementation.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# The `sspi-rs` was in commit `ffd920b7b396739b60a6e1bae701f31e735deeef` at the time of writing this article.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; clone https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span&gt; sspi-rs&#x2F;ffi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span&gt; build&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --features&lt;&#x2F;span&gt;&lt;span&gt; scard&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;file&lt;&#x2F;span&gt;&lt;span&gt; ..&#x2F;target&#x2F;debug&#x2F;libsspi.dylib&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# You should see something like this:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# ..&#x2F;target&#x2F;debug&#x2F;libsspi.dylib: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=eb4b2d386823f59cbd4bd7ed08055f887db6c45b, with debug_info, not stripped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can confirm that the &lt;code&gt;libsspi.dylib&lt;&#x2F;code&gt; library exports the WinSCard API by running:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;readelf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; -Ws --dyn-syms&lt;&#x2F;span&gt;&lt;span&gt; ..&#x2F;target&#x2F;debug&#x2F;libsspi.dylib&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; -E&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot; SCard&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To configure the WinSCard API implementation, we need to set the following environment variables:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;name&lt;&#x2F;th&gt;&lt;th&gt;meaning&lt;&#x2F;th&gt;&lt;th&gt;example&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;WINSCARD_USE_SYSTEM_SCARD&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Tells the &lt;code&gt;sspi-rs&lt;&#x2F;code&gt; to use the system-provided (real) smart card instead of an emulated one&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;true&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The last step in this section is to ensure that the &lt;code&gt;pcsc-lite&lt;&#x2F;code&gt; is installed on your system and running:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# I use Arch bwt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; pacman&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; -S&lt;&#x2F;span&gt;&lt;span&gt; pcsclite&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; systemctl enable pcscd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; systemctl start pcscd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; systemctl status pcscd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# ● pcscd.service - PC&#x2F;SC Smart Card Daemon&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#      Loaded: loaded (&#x2F;usr&#x2F;lib&#x2F;systemd&#x2F;system&#x2F;pcscd.service; indirect; preset: disabled)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#      Active: active (running) since Sat 2025-11-08 12:28:03 EET; 5s ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#  Invocation: e7d44e3ded3c4a19a388887891599d6b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# TriggeredBy: ● pcscd.socket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#        Docs: man:pcscd(8)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#    Main PID: 265031 (pcscd)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#       Tasks: 5 (limit: 18705)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#      Memory: 1.4M (peak: 2.7M)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#         CPU: 65ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#      CGroup: &#x2F;system.slice&#x2F;pcscd.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#              └─265031 &#x2F;usr&#x2F;bin&#x2F;pcscd --foreground --auto-exit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Nov 08 12:28:03 tbt systemd[1]: Started PC&#x2F;SC Smart Card Daemon.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;kerberos-1&quot;&gt;Kerberos&lt;&#x2F;h2&gt;
&lt;p&gt;As I mentioned above, we will use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&quot;&gt;&lt;code&gt;sspi-rs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to provide FreeRDP with a Kerberos implementation.
&lt;code&gt;sspi-rs&lt;&#x2F;code&gt; exports both SSPI and WinSCard APIs from the same library file.
Thus, at this point, we already have the Kerberos implementation exported via the SSPI interface inside &lt;code&gt;libsspi.dylib&lt;&#x2F;code&gt; from the previous step.
You can confirm that by checking the exported functions. For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;readelf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; -Ws --dyn-syms&lt;&#x2F;span&gt;&lt;span&gt; ..&#x2F;target&#x2F;debug&#x2F;libsspi.dylib&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; -E&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;SecurityContext(A|W)?$&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# You should see simething like this:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#    153: 00000000003066f0  2841 FUNC    GLOBAL DEFAULT   12 AcceptSecurityContext&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#    197: 00000000003bfe30  2900 FUNC    GLOBAL DEFAULT   12 InitializeSecurityContextA&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#    223: 0000000000308f60  2248 FUNC    GLOBAL DEFAULT   12 ImpersonateSecurityContext&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#    233: 00000000003c2850  2272 FUNC    GLOBAL DEFAULT   12 ImportSecurityContextA&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#    234: 00000000003c0990  2900 FUNC    GLOBAL DEFAULT   12 InitializeSecurityContextW&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#    235: 000000000030bb40  2271 FUNC    GLOBAL DEFAULT   12 ExportSecurityContext&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#    257: 00000000003c3130  2272 FUNC    GLOBAL DEFAULT   12 ImportSecurityContextW&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#    269: 0000000000309830  2248 FUNC    GLOBAL DEFAULT   12 RevertSecurityContext&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#    273: 0000000000307c60  2595 FUNC    GLOBAL DEFAULT   12 DeleteSecurityContext&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# 105839: 00000000003c2850  2272 FUNC    GLOBAL DEFAULT   12 ImportSecurityContextA&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# 105866: 00000000003c0990  2900 FUNC    GLOBAL DEFAULT   12 InitializeSecurityContextW&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# 105872: 0000000000307c60  2595 FUNC    GLOBAL DEFAULT   12 DeleteSecurityContext&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# 105878: 00000000003bfe30  2900 FUNC    GLOBAL DEFAULT   12 InitializeSecurityContextA&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# 105887: 00000000003c3130  2272 FUNC    GLOBAL DEFAULT   12 ImportSecurityContextW&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# 105896: 0000000000308f60  2248 FUNC    GLOBAL DEFAULT   12 ImpersonateSecurityContext&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# 105929: 00000000003066f0  2841 FUNC    GLOBAL DEFAULT   12 AcceptSecurityContext&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# 105957: 000000000030bb40  2271 FUNC    GLOBAL DEFAULT   12 ExportSecurityContext&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# 105978: 0000000000309830  2248 FUNC    GLOBAL DEFAULT   12 RevertSecurityContext&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We need to set the following environment variables to configure Kerberos properly:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;name&lt;&#x2F;th&gt;&lt;th&gt;meaning&lt;&#x2F;th&gt;&lt;th&gt;example&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SSPI_LOG_PATH&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Path to the logfile&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;~&#x2F;delete_it&#x2F;sspi.log&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SSPI_LOG_LEVEL&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Logging level&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;trace&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SSPI_KDC_URL&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Url to the KDC server or KDC Proxy server. You can omit this value if the DNS is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;i.imgflip.com&#x2F;7h0kjh.png&quot;&gt;properly configured&lt;&#x2F;a&gt;.&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;tcp:&#x2F;&#x2F;192.168.1.104:88&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SSPI_SCARD_TYPE&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;sspi-rs&lt;&#x2F;code&gt; also implements the emulated smart card. We need to specify it to use the system-provided (real) smart card&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;system&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SSPI_PKCS11_MODULE_PATH&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Path to the PKCS11 module&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;&#x2F;usr&#x2F;local&#x2F;lib&#x2F;libykcs11.2.7.2.dylib&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;freerdp&quot;&gt;FreeRDP&lt;&#x2F;h2&gt;
&lt;p&gt;Now to the hard part. Compiling the C&#x2F;C++ project was always a nightmare for me. Time passes, and I become more skilled in it, but it remains unpleasant.&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately, FreeRDP has an excellent compilation guide: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;FreeRDP&#x2F;FreeRDP&#x2F;wiki&#x2F;Compilation&quot;&gt;FreeRDP&#x2F;wiki&#x2F;Compilation&lt;&#x2F;a&gt;.
Unfortunately, versions of some dependencies are outdated (at the moment), so I used the macOS bundling script (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;FreeRDP&#x2F;FreeRDP&#x2F;blob&#x2F;2eb88390f94071c0d46974381a3953e0d382f114&#x2F;scripts&#x2F;bundle-mac-os.sh&quot;&gt;FreeRDP&#x2F;scripts&#x2F;bundle-mac-os.sh&lt;&#x2F;a&gt;) to help me with compilation.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;demo&quot;&gt;Demo&lt;&#x2F;h1&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; SSPI_LOG_PATH&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sspi&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; SSPI_LOG_LEVEL&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;trace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; SSPI_KDC_URL&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;tcp:&#x2F;&#x2F;192.168.1.104:88&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; SSPI_SCARD_TYPE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;system&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; SSPI_PKCS11_MODULE_PATH&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;usr&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;local&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;lib&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;libykcs11&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;dylib&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; WINSCARD_USE_SYSTEM_SCARD&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;sdl-freerdp&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;v:DESKTOP-QELPR32.tbt.com &#x2F;u:t2 &#x2F;d:tbt.com &#x2F;p:123456 &#x2F;smartcard-logon &#x2F;sec:nla&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;cert:ignore &#x2F;log-level:TRACE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;sspi-module:&#x2F;Users&#x2F;user&#x2F;delete_it&#x2F;sspi-rs&#x2F;target&#x2F;debug&#x2F;libsspi.dylib&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;kerberos:pkcs11-module:&#x2F;usr&#x2F;local&#x2F;lib&#x2F;libykcs11.2.7.2.dylib&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;winscard-module:&#x2F;Users&#x2F;user&#x2F;delete_it&#x2F;sspi-rs&#x2F;target&#x2F;debug&#x2F;libsspi.dylib &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;how-rdp-scard-logon-works&#x2F;.&#x2F;rdp_success.jpg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It was quite a short demo 😅. But it works!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;doc-references-code&quot;&gt;Doc, references, code&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.hardening-consulting.com&#x2F;en&#x2F;posts&#x2F;20231004-smartcard-logon.html&quot;&gt;Smartcard logon with FreeRDP&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Remote_Desktop_Services#Network_Level_Authentication&quot;&gt;Network Level Authentication&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-cssp&#x2F;85f57821-40bb-46aa-bfcb-ba9590b8fc30&quot;&gt;CredSSP&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc4556&quot;&gt;Public Key Cryptography for Initial Authentication in Kerberos (PKINIT)&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;smartcard&#x2F;smart-card-minidrivers&quot;&gt;Smart Card Minidrivers&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;security&#x2F;identity-protection&#x2F;smart-cards&#x2F;smart-card-architecture&quot;&gt;Smart Card Architecture&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winscard&#x2F;&quot;&gt;WinSCard API&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Announcing Dataans v.0.3.0</title>
        <published>2025-08-03T00:00:00+00:00</published>
        <updated>2025-08-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/dataans-0-3/"/>
        <id>https://tbt.qkation.com/posts/dataans-0-3/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/dataans-0-3/">&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;releases&#x2F;tag&#x2F;v.0.3.0&quot;&gt;GitHub&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;releases&#x2F;v.0.3.0&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;intro&quot;&gt;Intro&lt;&#x2F;h1&gt;
&lt;p&gt;The Dataans app has adopted a local-first approach since the very beginning of its existence.
After some time, I started to use the app on many devices and inside my Windows&#x2F;Linux VMs.
I caught myself thinking that it would be good to be able to transfer data from one device to another.
Fast forward two months, and suddenly I realized that it is a critical feature for me.
After some considerations and small research, I understood that I wanted the multi-device synchronization feature.&lt;&#x2F;p&gt;
&lt;p&gt;Decentralized Internet, P2P networks, etc, are good. But the current implementation of the data synchronization feature relies on the central sync (backup) server. The data synchronization using the P2P communication may be implemented in the future. It depends on my needs.&lt;&#x2F;p&gt;
&lt;p&gt;This post turned out to be quite large. Alternatively, you can read the shorter version: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;6c898a01afc0942cb94b5dbc822349d8afa924ee&#x2F;doc&#x2F;sync_server.md&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;6c898a01&#x2F;doc&#x2F;sync_server.md&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;demo&quot;&gt;Demo&lt;&#x2F;h1&gt;
&lt;p&gt;Before explaining how it works and how I implemented it, I want to show you the demo.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Better to see something once than hear about it a thousand times.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;skeptics.stackexchange.com&#x2F;q&#x2F;28487&quot;&gt;Asian Proverb&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;So, first, the user needs to log in. Open the &lt;code&gt;App-info&lt;&#x2F;code&gt; window by clicking on the app version number in the bottom left corner of the main window. Then, type the sync server address and click log in:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;dataans-0-3&#x2F;.&#x2F;log-in-1.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now the user needs to authorize:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;dataans-0-3&#x2F;.&#x2F;log-in-2.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And yes, as you can see, I decided to delegate all authentication-related tasks to Cloudflare. I did not want to implement it manually, and, honestly, it was one of the best decisions I made.
Thanks to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.cloudflare.com&#x2F;zero-trust&#x2F;products&#x2F;access&#x2F;&quot;&gt;Cloudflare Zero Trust Access&lt;&#x2F;a&gt;, I only need to enter email and the code from email.&lt;&#x2F;p&gt;
&lt;p&gt;After the successful sign in, the user needs to enter the password and secret passphrase.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;dataans-0-3&#x2F;.&#x2F;log-in-3.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;At this point, two cases are possible:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;If it is the first sign-in among all users&#x27; devices (sync server&#x27;s database is empty), then the user needs to fill in ONLY the password input.
The passphrase will be automatically generated by the app. But if the user wants to use a custom passphrase, then they can type it.&lt;&#x2F;li&gt;
&lt;li&gt;If it is a new sign-in on another device and the sync server&#x27;s database is not empty (there was a sync from other devices), then the user must type both password AND passphrase.
The user can read the passphrase on any signed-in device in the &lt;code&gt;profile.json&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Why does the app require the user to have a password if all auth has been delegated to Cloudflare?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It is explained in detail in the &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;dataans-0-3&#x2F;#auth&quot;&gt;Auth&lt;&#x2F;a&gt; section. But, in short, the data encryption key is derived from the user&#x27;s password and passphrase.&lt;&#x2F;p&gt;
&lt;p&gt;This is what the user sees after successful sign-in:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;dataans-0-3&#x2F;.&#x2F;logged-in.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;From the screenshot above:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Button that triggers data synchronization.&lt;&#x2F;li&gt;
&lt;li&gt;Synchronization mode. Currently, only manual mode is implemented.
It means that whenever the user wants to sync the data, they need to press the button 🙃.&lt;&#x2F;li&gt;
&lt;li&gt;Sign out button.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Now, the user is able to sync app data. The synchronization process happens in the background.
So, the user can freely use the app without any limitations during synchronization. Once the sync is complete, a small pop-up message will appear.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;dataans-0-3&#x2F;.&#x2F;successful-sync.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;how-it-works&quot;&gt;How it works&lt;&#x2F;h1&gt;
&lt;p&gt;Now let&#x27;s talk about interesting things: how it works 😊. Below are detailed technical explanations.
You can jump right to the interesting part. There is no need to read it in order.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;infrastructure&quot;&gt;Infrastructure&lt;&#x2F;h2&gt;
&lt;p&gt;This section is boring, because I don&#x27;t like to describe infrastructure in detail. So, if you are not interested in such things, then skip it 😉.&lt;&#x2F;p&gt;
&lt;div class=&quot;mermaid&quot;&gt;
graph TD
    subgraph Internet
        Client[Dataans App]
    end

    subgraph Cloudflare
        Client --&amp;gt;|HTTPS Request| CloudflareZeroTrust[Cloudflare Zero Trust Access]
        CloudflareZeroTrust --&amp;gt;|cf-access-jwt-assertion Injected| FlyApp[Sync Server]

        subgraph Fly.io
            FlyApp --&amp;gt;|User files| ObjectStorage[(Tigris Object Storage)]
        end

        FlyApp --&amp;gt;|Verifies JWT| CF_PubKey[Cloudflare Public Key Endpoint]
    end

    subgraph Neon.com
        FlyApp --&amp;gt;|User data| Postgres[(PostgreSQL Database)]
    end
&lt;&#x2F;div&gt;
&lt;p&gt;The overall infrastructure is straightforward.&lt;&#x2F;p&gt;
&lt;p&gt;I use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.cloudflare.com&#x2F;&quot;&gt;Cloudflare&lt;&#x2F;a&gt; for endpoint protection, auth, DDoS protection, and domain hosting.&lt;&#x2F;p&gt;
&lt;p&gt;I use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fly.io&#x2F;&quot;&gt;Fly.io&lt;&#x2F;a&gt; as a main cloud provider. I like the microVM approach that they use. It is my first app deployed on fly.io.
The deployment process was simple and fast. It reminded me of the old, almost forgotten feeling &lt;em&gt;&quot;it just works&quot;&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;neon.com&#x2F;&quot;&gt;Neon.com&lt;&#x2F;a&gt; PostgreSQL provider to store user data. I did not like fly.io&#x27;s Postgres integration because it does not shut down automatically when it is not in use.
So, I decided to try Neon. They have a very limited free tier, but it is ok for me (at least for now).
I am very satisfied with the database start time. I think it is a great choice for small personal projects.&lt;&#x2F;p&gt;
&lt;p&gt;I use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.tigrisdata.com&#x2F;&quot;&gt;Tigris&lt;&#x2F;a&gt; object storage to store user files. Mainly because it is integrated into the fly.io, so I decided to use it. Its free tier is more than enough for me.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;auth&quot;&gt;Auth&lt;&#x2F;h2&gt;
&lt;p&gt;Initially, I implemented the authentication manually.
It was a simple password-based authentication with a primitive session-based authorization implementation.&lt;&#x2F;p&gt;
&lt;p&gt;However, I then decided &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;pull&#x2F;97&#x2F;commits&quot;&gt;to throw it out&lt;&#x2F;a&gt;.
I pondered on it and decided that I do not want to maintain a ton of code dedicated to auth.
I wanted to delegate it to some external service. I explored the most popular solutions and chose &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.cloudflare.com&#x2F;zero-trust&#x2F;products&#x2F;access&#x2F;&quot;&gt;Cloudflare Zero Trust Access&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It works very simply (as I wanted). Cloudflare works as a proxy and intercepts requests to my web service.
If the request does not have an authentication token inside, then Cloudflare does the auth.
I configured the allowed emails list, and Cloudflare sends a code to the entered email during sign-in.
Cloudflare injects a token into the request after successful sign-in and sends the request to my web server.&lt;&#x2F;p&gt;
&lt;div class=&quot;mermaid&quot;&gt;
sequenceDiagram
    participant Client as Client
    participant Cloudflare as Cloudflare
    participant Server as Web-Service

    Client-&amp;gt;&amp;gt;Cloudflare: HTTP Request
    Cloudflare-&amp;gt;&amp;gt;Client: Redirect to Zero Trust login page
    Client-&amp;gt;&amp;gt;Cloudflare: Sign in
    Cloudflare-&amp;gt;&amp;gt;Client: Redirect back with session cookie (CF_Authorization cookie)

    Client-&amp;gt;&amp;gt;Cloudflare: HTTP Request (with CF_Authorization cookie)
    Cloudflare-&amp;gt;&amp;gt;Server: Proxies request with cf-access-jwt-assertion header
    Server--&amp;gt;&amp;gt;Cloudflare: Response
    Cloudflare--&amp;gt;&amp;gt;Client: Web server response
&lt;&#x2F;div&gt;
&lt;p&gt;The only thing I need to do on my web server&#x27;s side is to validate Cloudflare&#x27;s JWT token.
The validation algorithm is pretty straightforward:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Extract the &lt;code&gt;cf-access-jwt-assertion&lt;&#x2F;code&gt; header.&lt;&#x2F;li&gt;
&lt;li&gt;Get Cloudflare&#x27;s signing keys.&lt;&#x2F;li&gt;
&lt;li&gt;Validate JWT using any common library.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;You can read the full code here: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;6c898a01afc0942cb94b5dbc822349d8afa924ee&#x2F;crates&#x2F;web-server&#x2F;src&#x2F;routes&#x2F;mod.rs&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;6c898a01&#x2F;crates&#x2F;web-server&#x2F;src&#x2F;routes&#x2F;mod.rs&lt;&#x2F;a&gt;. There is an important moment:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;By default, &lt;strong&gt;Access rotates the signing key every 6 weeks&lt;&#x2F;strong&gt;. This means you will need to programmatically or manually update your keys as they rotate. (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developers.cloudflare.com&#x2F;cloudflare-one&#x2F;identity&#x2F;authorization-cookie&#x2F;validating-json&#x2F;#access-signing-keys&quot;&gt;src&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Therefore, if you decide to hardcode signing keys, ensure that you rotate them regularly.
I decided to follow another path: the web server requests the signing keys every time it needs to verify the JWT token.
Yes, it is not the best option, but it is enough for me (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.dreamsongs.com&#x2F;RiseOfWorseIsBetter.html&quot;&gt;Worse Is Better&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Great. Simple, secure, easy to set up 🚀. I asked ChatGPT for the step-by-step guide, which worked from the first try.
I tried to access the protected route from the browser, and it worked perfectly.&lt;&#x2F;p&gt;
&lt;p&gt;However, there is a small, tiny problem: I am not writing a website, I am writing a desktop app using Tauri.
I cannot rely on cookies themselves because I want to make requests from the app backend using the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;reqwest&#x2F;latest&#x2F;reqwest&#x2F;&quot;&gt;&lt;code&gt;request&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; HTTP client.&lt;&#x2F;p&gt;
&lt;p&gt;Therefore, I need to extract the &lt;code&gt;CF_Authorization&lt;&#x2F;code&gt; token somehow and save it somewhere in the app backend.
Additionally, the app needs to ask the user password and passphrase. I was thinking for some time about the easiest way to implement.
I came up with the idea of sending the cookie token, password, and passphrase in one Tauri command to the app backend.&lt;&#x2F;p&gt;
&lt;p&gt;When the user passes the Cloudflare, the web server responds with the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;6c898a01afc0942cb94b5dbc822349d8afa924ee&#x2F;crates&#x2F;web-server&#x2F;authorize.html&quot;&gt;&lt;code&gt;authorize.html&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; page.
It is a simple form with an embedded script. When the user submits the form, the script extracts the &lt;code&gt;CF_Authorization&lt;&#x2F;code&gt; token, reads the typed password and passphrase, and sends all this data to the app backend:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;async function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; extractAndSendToken&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; cookie&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;cookie&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;#39;; &amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;find&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;font-style: italic;&quot;&gt;row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; row&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;startsWith&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;#39;CF_Authorization=&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;cookie&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;CF_Authorization cookie not found.&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; token&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; cookie&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;#39;=&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; password&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;password&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; salt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;salt&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; token&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; url&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B6B1B1;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; window&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;origin&lt;&#x2F;span&gt;&lt;span&gt; };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; password&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    args&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; password&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;salt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; salt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    args&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #2EE2FA;&quot;&gt;salt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; salt&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  try&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    await&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; window&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;__TAURI__&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;core&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;invoke&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;plugin:dataans|sign_in&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; args&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Token sent successfully:&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; token&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; catch&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Failed to send token:&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; e&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Fortunately, Tauri injects the &lt;code&gt;window.__TAURI__&lt;&#x2F;code&gt; object into every spawned webview. Thus, even when the webview is created from &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tauri&#x2F;2.7.0&#x2F;tauri&#x2F;enum.WebviewUrl.html#variant.External&quot;&gt;an external URL&lt;&#x2F;a&gt; (not &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tauri&#x2F;2.7.0&#x2F;tauri&#x2F;enum.WebviewUrl.html#variant.App&quot;&gt;the direct app frontend&lt;&#x2F;a&gt;), it can still send Tauri commands.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s all. The rest is easy to implement. When the app backend receives the data, it generates an encryption key (from the password and passphrase), tests the auth token, and saves it... There is a corresponding piece of &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;6c898a01afc0942cb94b5dbc822349d8afa924ee&#x2F;dataans&#x2F;src-tauri&#x2F;src&#x2F;dataans&#x2F;command&#x2F;auth.rs#L35&quot;&gt;code&lt;&#x2F;a&gt;, if you want to see it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;data-encryption&quot;&gt;Data encryption&lt;&#x2F;h2&gt;
&lt;p&gt;The local state is unencrypted and saved in a SQLite database. But the app encrypts the data before sending it to the sync server.
Dataans follows one rule regarding user data: &lt;strong&gt;&lt;em&gt;we trust the user&#x27;s computer and the user is responsible for keeping the local state safe, but we do not trust any remote servers and always encrypt data before sending it&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We need to derive a key to encrypt the data. The app uses the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;PBKDF2&quot;&gt;&lt;code&gt;PBKDF2&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function and needs the user&#x27;s password and passphrase to derive the key.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Pseudocode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; password&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; sha256&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; salt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; sha256&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;passphrase&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; pbkdf2_hmac&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; salt&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1_200_000&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* iterations *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The derived key is stored in plaintext in the &lt;code&gt;profile.json&lt;&#x2F;code&gt; file. There is no need to hide this key, because all data is local and unencrypted.&lt;&#x2F;p&gt;
&lt;p&gt;As I wrote above, all data is encrypted before sending to the sync server.
The app uses the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Advanced_Encryption_Standard&quot;&gt;AES256&lt;&#x2F;a&gt;-&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Galois&#x2F;Counter_Mode&quot;&gt;GCM&lt;&#x2F;a&gt; algorithm and appends an &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;HMAC&quot;&gt;HMAC&lt;&#x2F;a&gt;-&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;SHA-2&quot;&gt;SHA256&lt;&#x2F;a&gt; checksum.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Pseudocode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; nonce&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; random&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; cipher_text&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; aes_gcm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;encrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; nonce&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; plaintext&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; checksum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; hmac_sha256&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; nonce&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; plaintext&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; nonce&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; plaintext&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; checksum&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;AES256-GCM&lt;&#x2F;code&gt; provides strong encryption, and &lt;code&gt;HMAC-SHA256&lt;&#x2F;code&gt; provides data integrity. The same for decryption, but in reverse:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Pseudocode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;nonce&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; cipher&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;split_at&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;NONCE_LEN&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;cipher_text&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; checksum&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; cipher&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;split_at&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;cipher&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; HMAC_LEN&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; plaintext&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; aes_gcm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;decrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; nonce&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; cipher_text&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; calculated_checksum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; hmac_sha256&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; nonce&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; plaintext&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; checksum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; calculated_checksum&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;   return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;data is altered&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;plaintext&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That is all for the encryption part. The overall encryption process is simple, secure, and, most importantly, boring.
I like the fact that it took a bit more than 100 lines of code to implement all the needed cryptography functions in Rust: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;6c898a01afc0942cb94b5dbc822349d8afa924ee&#x2F;dataans&#x2F;src-tauri&#x2F;src&#x2F;dataans&#x2F;crypto.rs&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;6c898a01&#x2F;dataans&#x2F;src-tauri&#x2F;src&#x2F;dataans&#x2F;crypto.rs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;synchronization&quot;&gt;Synchronization&lt;&#x2F;h2&gt;
&lt;p&gt;(If you do not want to read the whole section, then you can read the code: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;6c898a01afc0942cb94b5dbc822349d8afa924ee&#x2F;dataans&#x2F;src-tauri&#x2F;src&#x2F;dataans&#x2F;sync&#x2F;mod.rs&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;6c898a01&#x2F;dataans&#x2F;src-tauri&#x2F;src&#x2F;dataans&#x2F;sync&#x2F;mod.rs&lt;&#x2F;a&gt;.
It is well-documented.&lt;&#x2F;p&gt;
&lt;p&gt;I spent around half of the year trying different approaches in synchronization. It was hard to choose a suitable sync algorithm.
I had never implemented such features and had been overthinking it for months. First, I read &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rsync.samba.org&#x2F;tech_report&#x2F;tech_report.html&quot;&gt;the rsync algorithm&lt;&#x2F;a&gt; documentation and tried to apply it.
Then, I tried to store the hash of every object in the database and compare these hashes to determine the state diff.
At some point, I went even further and tried to apply &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Merkle_tree&quot;&gt;Merkle trees&lt;&#x2F;a&gt; 🤪.&lt;&#x2F;p&gt;
&lt;p&gt;Everything looked overcomplicated. But I did not give up and decided to make things even more complicated: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Conflict-free_replicated_data_type&quot;&gt;CRDT&lt;&#x2F;a&gt;s. I was disappointed again because it wasn&#x27;t what I needed.&lt;&#x2F;p&gt;
&lt;p&gt;At some point, I paid attention to the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Conflict-free_replicated_data_type#Operation-based_CRDTs&quot;&gt;Operation-Based CRDTs&lt;&#x2F;a&gt;.
Synchronizing the operations log instead of the full app state looks simple.
I elaborated this idea further and finally decided to use it for the synchronization.&lt;&#x2F;p&gt;
&lt;p&gt;Every time a user does any action that alters the local state, the app logs this action. It is called &lt;em&gt;a user operation&lt;&#x2F;em&gt;, or &lt;em&gt;an operation&lt;&#x2F;em&gt;.
When the user starts the sync, &lt;strong&gt;&lt;em&gt;the app and the sync server synchronize the operation lists&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;. Now the task is a bit simpler: there are two lists and the app needs to synchronize their content.&lt;&#x2F;p&gt;
&lt;p&gt;The naive solution is to take local (app state) and remote (sync server state) operation lists and compare them operation by operation.
But it can be slow, operations number can be large, and I still want to overengineer things. Thus, I introduced blocks and block hashes.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;em&gt;block&lt;&#x2F;em&gt; is a collection of &lt;code&gt;N&lt;&#x2F;code&gt; sequential operations sorted by timestamp.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; `operations` are sorted by timestamp.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; block_1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; operations&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;N&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; block_2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; operations&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; block_n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; operations&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I am sure you got the idea. All operations are divided into chunks by &lt;code&gt;N&lt;&#x2F;code&gt;, which I call blocks. Nothing more, nothing less.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;em&gt;block hash&lt;&#x2F;em&gt; is a hash of sequential hashes of block operations.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; block_hash&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; hash&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;hash&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; hash&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; hash&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;block&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;]));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the core of my small, simple optimization. During the first synchronization step, the app requests the server&#x27;s block hashes.
And calculates the same block hashes on local operations. Blocks with the same hashes contain the same operations.
Thus, the app can safely discard such blocks.&lt;&#x2F;p&gt;
&lt;p&gt;Conflicts? The last write wins. Every object in the local database has an &lt;code&gt;updated_at&lt;&#x2F;code&gt; timestamp.
When the app detects conflict during synchronization, it compares two timestamps and last (latest) write wins.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s summarize the synchronization algorithm. I prepared a scheme for you to make it easier to understand:&lt;&#x2F;p&gt;
&lt;div class=&quot;mermaid&quot;&gt;
sequenceDiagram
    participant App as Dataans
    participant Server as Sync Server

    Note over App,Server: Step 1: Request server&amp;#x27;s blocks and calculate local ones
    App-&amp;gt;&amp;gt;Server: GET &amp;#x2F;data&amp;#x2F;blocks
    Server--&amp;gt;&amp;gt;App: [hash_1, hash_2, ...]

    Note over App: Step 2: Compare block hashes
    App-&amp;gt;&amp;gt;App: Find distinct blocks by comparing hashes

    Note over App,Server: Step 3: Request server&amp;#x27;s operations from distinct blocks
    App-&amp;gt;&amp;gt;Server: GET &amp;#x2F;data&amp;#x2F;operation?operations_to_skip=&amp;lt;&amp;gt;
    Server--&amp;gt;&amp;gt;App: [operation_1, operation_2, ...]

    Note over App: Step 4: Determine operations differences
    App-&amp;gt;&amp;gt;App: Form operations_to_upload and operations_to_apply sets

    Note over App,Server: Step 5: Sync operations
    App-&amp;gt;&amp;gt;Server: POST &amp;#x2F;data&amp;#x2F;operation (operations_to_upload)
    App-&amp;gt;&amp;gt;App: Apply operations_to_apply to local state
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;strong&gt;Step 1.&lt;&#x2F;strong&gt; The app requests the server&#x27;s block hashes and calculates local block hashes concurrently.
The app will have two lists of hashes as the result.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Step 2.&lt;&#x2F;strong&gt; The app compares block hashes from two lists one by one.
It stops on the first pair of unequal hashes (or until one of the lists ends) and discards all hashes before this pair. The app will have two lists of block hashes that have different hashes.
It does not need to compare hashes after the first unequal pair.
All operations are sorted by timestamp before calculating block hashes. So, all the next consecutive blocks will also have different hashes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Step 3.&lt;&#x2F;strong&gt; At this point, the app knows how many blocks are equal on the local and remote sides.
So, the app requests all operations &lt;em&gt;after&lt;&#x2F;em&gt; equal blocks and queries local operations (also &lt;em&gt;after&lt;&#x2F;em&gt; equal blocks).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Step 4.&lt;&#x2F;strong&gt; The app compares local and remote operation lists (both of which are sorted by timestamp).
The best thing is that the app does not need to do a Cartesian product over these two lists.
The app compared operations one by one until the pair of operations with different ids (or until one of the lists ends).&lt;&#x2F;p&gt;
&lt;p&gt;We can be sure that all operations after that point also have different ids.
Because it is impossible otherwise. If the app is aware of some operation, then it is also aware of all operations before.
The app cannot synchronize only later operations and skip earlier ones. The same is true for the server&#x27;s side.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Step 4: Find the difference between local and remote operations.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; operations_to_upload&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; operations_to_apply&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;local_operations&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; remote_operations&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;()) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;local_operation&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;remote_operation&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; local_operation&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;!=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; remote_operation&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;id {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;                operations_to_upload&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;local_operation&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;                operations_to_apply&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;remote_operation&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;                for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; local_operation&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; local_operations&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;                    operations_to_upload&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;local_operation&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;                for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; remote_operation&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; remote_operations&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;                    operations_to_apply&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;remote_operation&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;                break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;local_operation&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            operations_to_upload&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;local_operation&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;remote_operation&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            operations_to_apply&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;remote_operation&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; =&amp;gt; break&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The app will have &lt;code&gt;operations_to_upload&lt;&#x2F;code&gt; and &lt;code&gt;operations_to_apply&lt;&#x2F;code&gt; lists as the result.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Step 5.&lt;&#x2F;strong&gt; The last step is simple. The app uploads the &lt;code&gt;operations_to_upload&lt;&#x2F;code&gt; operations to the sync server and applies &lt;code&gt;operations_to_apply&lt;&#x2F;code&gt; operations on the local database.&lt;&#x2F;p&gt;
&lt;p&gt;If everything succeeds, we can be sure that local and remote states are the same ☺️.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;files-sync&quot;&gt;Files sync&lt;&#x2F;h2&gt;
&lt;p&gt;Aren&#x27;t you forgetting something important? 🙃&lt;&#x2F;p&gt;
&lt;p&gt;Let me remind you. The Dataans supports attaching files to notes. Only file metadata is saved in the local SQLite database.
The file contents are saved locally in the file system as files. It means that we also need to synchronize files alongside the SQLite DB state.&lt;&#x2F;p&gt;
&lt;p&gt;A registered file is the file that is recorded in the local SQLite database. Every file has an &lt;code&gt;is_uploaded&lt;&#x2F;code&gt; property.
The app iterates over all registered files in the local database. Based on this property and the file existence in FS, the app does one of the following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;is_uploaded&lt;&#x2F;code&gt; is &lt;code&gt;true&lt;&#x2F;code&gt; and the file exists in FS - then the app does nothing. Everything is good.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;is_uploaded&lt;&#x2F;code&gt; is &lt;code&gt;true&lt;&#x2F;code&gt; and the file does not exist in FS - then the app downloads the file from the sync server.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;is_uploaded&lt;&#x2F;code&gt; is &lt;code&gt;false&lt;&#x2F;code&gt; and file exists in FS - then the app uploads the file and sets &lt;code&gt;is_uploaded&lt;&#x2F;code&gt; to &lt;code&gt;true&lt;&#x2F;code&gt;.
The file is encrypted before uploading.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;is_uploaded&lt;&#x2F;code&gt; is &lt;code&gt;false&lt;&#x2F;code&gt; and the file does exist in FS - then the app logs a problem. Ideally, such a situation should not even exist.
If it happens, then it means that someone&#x2F;something has modified the app data directory (or a bug, but come on, it is definitely something else 🙃).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Files synchronization task runs concurrently with the main synchronization task. The synchronization process ends when both tasks finish.&lt;&#x2F;p&gt;
&lt;p&gt;The app can discover new files during database sync. For example, when you add a new file on the first device, synchronize the data, and then try to sync the data on the second device.&lt;&#x2F;p&gt;
&lt;p&gt;When this happens, the main synchronization task notifies the files synchronization task that there is a new file to download.
These two tasks communicate over the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tauri&#x2F;2.7.0&#x2F;tauri&#x2F;async_runtime&#x2F;fn.channel.html&quot;&gt;channel&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;6c898a01afc0942cb94b5dbc822349d8afa924ee&#x2F;dataans&#x2F;src-tauri&#x2F;src&#x2F;dataans&#x2F;sync&#x2F;mod.rs#L133-L138&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sender&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; receiver&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; channel&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;FileId&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;CHANNEL_BUFFER_SIZE&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; main_sync_fut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; synchronizer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;synchronize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;emitter&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sender&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; file_sync_fut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; synchronizer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;synchronize_files&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;emitter&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; receiver&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;main_result&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; file_result&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; futures&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;join!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;main_sync_fut&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; file_sync_fut&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;what-is-next&quot;&gt;What is next?&lt;&#x2F;h1&gt;
&lt;p&gt;I am happy I managed to implement it. I was a bit frustrated about it because the path to the final solution was very rough.
Such an intuitive and simple feature turned out to be quite complex and hard to implement.&lt;&#x2F;p&gt;
&lt;p&gt;Currently, I have implemented most of the major app backend features I needed. I am continuing to develop the Dataans.
But I will focus more on the app frontend features. I think the next major releases will contain a lot of UI and UX improvements.
I have a long list of amazing features ✨.&lt;&#x2F;p&gt;
&lt;p&gt;If you are interested in contributing to or using the Dataans, feel free to ask any questions ☺️.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;references&quot;&gt;References&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;releases&#x2F;tag&#x2F;v.0.3.0&quot;&gt;GitHub&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;releases&#x2F;v.0.3.0&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&quot;&gt;GitHub&#x2F;TheBestTvarynka&#x2F;Dataans&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.cloudflare.com&#x2F;zero-trust&#x2F;products&#x2F;access&#x2F;&quot;&gt;Cloudflare Zero Trust Access&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neondatabase&#x2F;neon&quot;&gt;Neon&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fly.io&#x2F;&quot;&gt;Fly.io&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.tigrisdata.com&#x2F;&quot;&gt;Tigris&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Conflict-free_replicated_data_type#Operation-based_CRDTs&quot;&gt;Operation-based_CRDTs&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;6c898a01afc0942cb94b5dbc822349d8afa924ee&#x2F;doc&#x2F;sync_server.md&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;6c898a01&#x2F;doc&#x2F;sync_server.md&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Safety Comments Matter</title>
        <published>2025-05-31T00:00:00+00:00</published>
        <updated>2025-05-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/safety-comments-matter/"/>
        <id>https://tbt.qkation.com/posts/safety-comments-matter/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/safety-comments-matter/">&lt;p&gt;TL;DR: This article is highly inspired by &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;pull&#x2F;430#pullrequestreview-2850078587&quot;&gt;this GitHub comment&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;safety-comments-matter&quot;&gt;Safety Comments Matter&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;SAFETY&lt;&#x2F;code&gt; comments are always welcome when dealing with &lt;code&gt;unsafe&lt;&#x2F;code&gt; code in Rust. The clippy even has a lint to enforce writing them: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rust-clippy&#x2F;master&#x2F;#undocumented_unsafe_blocks&quot;&gt;rust-lang.github.io&#x2F;rust-clippy&#x2F;#undocumented_unsafe_blocks&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#![warn(clippy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;undocumented_unsafe_blocks)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can find such comments in many crates and std. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;blob&#x2F;7a7bcbbcdbf2845164a94377d0e0efebb737ffd3&#x2F;library&#x2F;core&#x2F;src&#x2F;ptr&#x2F;non_null.rs#L391-L394&quot;&gt;Example&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; SAFETY: `NonNull` is `transparent` over a `*const T`, and `*const T`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; and `*mut T` have the same layout, so transitively we can transmute&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; our `NonNull` to a `*mut T` directly.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; mem&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;transmute&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Such comments help us to understand safety preconditions and invariants of the unsafe operation, and how they are upheld. Devs usually tend to treat them as one another boring thing in the development process. I kinda feel the same, but the benefits of properly written &lt;code&gt;unsafe&lt;&#x2F;code&gt; blocks are almost immeasurable.&lt;&#x2F;p&gt;
&lt;p&gt;But what is &lt;em&gt;&quot;a properly written &lt;code&gt;unsafe&lt;&#x2F;code&gt; block&quot;&lt;&#x2F;em&gt;? A properly written &lt;code&gt;unsafe&lt;&#x2F;code&gt; block has the following characteristics:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Has a single unsafe operation.&lt;&#x2F;li&gt;
&lt;li&gt;Documented using &lt;code&gt;SAFETY:&lt;&#x2F;code&gt; comment. In turn, to write a proper &lt;code&gt;SAFETY:&lt;&#x2F;code&gt; comment, you must follow the following requirements (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;pull&#x2F;430#pullrequestreview-2850078587&quot;&gt;src&lt;&#x2F;a&gt; of the quote below):&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Explain why the code is &quot;sound&quot;, detailing the invariants and preconditions that are maintained.&lt;&#x2F;li&gt;
&lt;li&gt;Avoid assumptions without justifications.
&lt;ul&gt;
&lt;li&gt;Do not use phrases like &lt;em&gt;&quot;we assume this is safe because…&quot;&lt;&#x2F;em&gt; or &lt;em&gt;&quot;this should be safe&quot;&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Provide concrete evidence or reasoning that justifies the safety of the operation.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Explicitly reference type invariants and prior checks when safety relies on it.&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; SAFETY: index is guaranteed to be within bounds due to the prior check.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; array&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;get_unchecked&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span&gt;) };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Address each safety requirement individually, using a bullet list.&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; SAFETY:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; - ptr is non-null and properly aligned.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; - The memory region ptr points to is valid for reads of len elements.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;slice&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from_raw_parts&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;ptr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;) };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Document FFI boundaries clearly, but if the only safety requirements are standard (e.g.: non-dangling pointers), for consistency, use the following concise comment verbatim:&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; SAFETY: FFI call with no outstanding preconditions.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; straightforward_ffi_function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;ptr&lt;&#x2F;span&gt;&lt;span&gt;) };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Do not document how the resulting value is safely used later.
&lt;ul&gt;
&lt;li&gt;Really focus only on why the current unsafe operation is sound.&lt;&#x2F;li&gt;
&lt;li&gt;Subsequent operations should be documented as appropriate in the code.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;It’s welcomed to document how and why the function is used, but this should not be part of the &lt;code&gt;SAFETY:&lt;&#x2F;code&gt; comment.
&lt;ul&gt;
&lt;li&gt;Write a separate paragraph out of the safety comment, typically above the safety comment.&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Passing None to GetModuleHandleW requests the handle to the&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; current process main executable module&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; SAFETY: FFI call with no outstanding preconditions.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; h_module&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; HMODULE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; GetModuleHandleW&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt; };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;To keep the comment concise, do not use phrases like &lt;em&gt;&quot;this is safe because…&quot;&lt;&#x2F;em&gt;. Go straight to the point (e.g.: &lt;em&gt;&quot;pointer is guaranteed not null due to the prior check&quot;&lt;&#x2F;em&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;For readability and clarity, keep the &lt;code&gt;unsafe&lt;&#x2F;code&gt; block as small as possible, and untangled from other safe code.  If needed, use intermediate variables.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; SAFETY: …&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; intermediate_variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; transform_credentials_handle&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;credentials_handle&lt;&#x2F;span&gt;&lt;span&gt;) };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; intermediate_variable&lt;&#x2F;span&gt;&lt;span&gt; { … }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;If a precondition must be upheld by the caller, mark the function as unsafe and document it with a &lt;code&gt;# Safety&lt;&#x2F;code&gt; section listing the invariants.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Returns the length in characters of the C-string.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; # Safety&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; - `s` must be a valid, null-terminated C-string.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; strlen&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt; { … }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;blockquote&gt;
&lt;p&gt;😮‍💨. I hope you didn&#x27;t get tired at this point. It is true that writing a good &lt;code&gt;SAFETY:&lt;&#x2F;code&gt; comment can be hard and exhausting. But it is worth it.&lt;&#x2F;p&gt;
&lt;p&gt;For me, the most important point in &lt;code&gt;SAFETY:&lt;&#x2F;code&gt; comments is that writing them requires thinking about preconditions and invariants. Devs seldom think about invariants and what can go wrong. When explaining why the &lt;code&gt;unsafe&lt;&#x2F;code&gt; operation is safe, you check the corresponding unsafe function preconditions and how to uphold them.&lt;&#x2F;p&gt;
&lt;p&gt;You can use AI to help you write &lt;code&gt;SAFETY:&lt;&#x2F;code&gt; comments, but remember that &lt;strong&gt;it is your responsibility&lt;&#x2F;strong&gt; to check that the generated ones list all needed preconditions and invariants.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Do not neglect &lt;code&gt;SAFETY:&lt;&#x2F;code&gt; comments.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;example&quot;&gt;Example&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lkml.org&#x2F;lkml&#x2F;2000&#x2F;8&#x2F;25&#x2F;132&quot;&gt;As Linus Torvalds said&lt;&#x2F;a&gt;,&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Talk is cheap. Show me the code.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So, let&#x27;s show some code. Suppose we have the following &lt;code&gt;unsafe&lt;&#x2F;code&gt; code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; do_some_job&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; PCtxtHandle&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; buf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; attrs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; buf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;is_null&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;is_null&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; attrs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;is_null&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* do the job *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_attrs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* Attributes::... *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        from_raw_parts_mut&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;copy_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;out_data&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;try_into&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;attrs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_attrs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;    0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The function above is pretty simple. It does some job and saves the resulting buffers and attributes into the out parameters. Now let&#x27;s make it better. I know we can.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Does some job.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; # SAFETY:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; - The `context` pointer must be a valid non-null pointer to the application context and obtained using the [init_context] function.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; - The `len` and `attrs` pointers must be non-null.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; - The `buf` pointer must be non-null. The entire memory range behind it must be contained within a single allocated object,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F;   be properly initialized and aligned.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; do_some_job&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; PCtxtHandle&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; buf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; attrs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; buf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;is_null&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;is_null&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; attrs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;is_null&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* do the job *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_attrs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* Attributes::... *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; SAFETY:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; - The `buf` pointer is not null due to the prior check.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; - We create only one slice at a time, so slice do not alias any other references.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; - The caller must ensure that the memory is properly initialized and aligned.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; buf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; from_raw_parts_mut&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;()) };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    buf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;copy_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;out_data&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;try_into&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; SAFETY:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; The `len` pointer is not null due to the prior check.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_len&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_attrs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_attrs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; SAFETY:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; The `attrs` pointer is not null due to the prior check.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;attrs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; out_attrs&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;    0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Much better, right? Let&#x27;s recall what has changed:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Added function doc comment with &lt;code&gt;# Safety&lt;&#x2F;code&gt; requirements.&lt;&#x2F;li&gt;
&lt;li&gt;Split unsafe operations into many &lt;code&gt;unsafe&lt;&#x2F;code&gt; blocks containing exactly one unsafe operation.&lt;&#x2F;li&gt;
&lt;li&gt;Every &lt;code&gt;unsafe&lt;&#x2F;code&gt; block now has the &lt;code&gt;SAFETY:&lt;&#x2F;code&gt; comment.&lt;&#x2F;li&gt;
&lt;li&gt;Moved safe operation out of the unsafe block (I&#x27;m talking about the &lt;code&gt;.copy_from_slice&lt;&#x2F;code&gt; method call).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now the caller knows that it is not enough to just allocate the memory. The memory needs to be initialized. Now the caller knows that &lt;code&gt;len&lt;&#x2F;code&gt; and &lt;code&gt;attrs&lt;&#x2F;code&gt; pointers cannot be NULL. And more... It sounds obvious, but the unsafe code becomes very dangerous in the blink of an eye.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;put-a-finger-down&quot;&gt;Put A Finger Down&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s play the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;officialgamerules.org&#x2F;game-rules&#x2F;put-a-finger-down&#x2F;&quot;&gt;Put A Finger Down&lt;&#x2F;a&gt; game. &lt;em&gt;(This section is optional and written mostly for fun)&lt;&#x2F;em&gt;. The rule is simple: you put one finger down for every true statement about your unsafe Rust code.&lt;&#x2F;p&gt;
&lt;p&gt;If you put down zero fingers, my congratulations 🎊. You are probably aware of what you are doing, and you can sleep peacefully. If you put down all your fingers, then, please, reconsider your life choices 🙂&lt;&#x2F;p&gt;
&lt;p&gt;☑️ Rust 2018 edition or older.&lt;&#x2F;p&gt;
&lt;p&gt;☑️ &lt;code&gt;unsafe&lt;&#x2F;code&gt; blocks without &lt;code&gt;SAFETY&lt;&#x2F;code&gt; comments.&lt;&#x2F;p&gt;
&lt;p&gt;☑️ Many unsafe operations per one unsafe block.&lt;&#x2F;p&gt;
&lt;p&gt;☑️ Your unsafe code has never been run using &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;miri&#x2F;&quot;&gt;Miri&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;☑️ Raw pointer &amp;lt;-&amp;gt; &lt;code&gt;int&lt;&#x2F;code&gt; cast is a usual thing.&lt;&#x2F;p&gt;
&lt;p&gt;The reader understands that these statements mean something bad for your unsafe code. Let&#x27;s discuss each of them. I want to make sure that we are on the same page.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rust-2018-edition-or-older&quot;&gt;Rust 2018 edition or older&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Why is the Rust edition important in our case?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;(I already described it &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;t.me&#x2F;tbtpm&#x2F;348&quot;&gt;here&lt;&#x2F;a&gt;.)&lt;&#x2F;p&gt;
&lt;p&gt;The 2024 edition brought many important features related to &lt;code&gt;unsafe&lt;&#x2F;code&gt; code and FFI.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;edition-guide&#x2F;rust-2024&#x2F;unsafe-op-in-unsafe-fn.html&quot;&gt;&lt;code&gt;unsafe_op_in_unsafe_fn&lt;&#x2F;code&gt; warning&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; set_id&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; dest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; warning[E0133]: dereference of raw pointer is unsafe and requires unsafe block&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;dest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Solution:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;dest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I like it a lot. Because in huge &lt;code&gt;unsafe&lt;&#x2F;code&gt; functions, it&#x27;s not clear which operations are unsafe and which are not.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;edition-guide&#x2F;rust-2024&#x2F;unsafe-attributes.html&quot;&gt;Unsafe attributes&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Before Rust 2024 the following code was accepted:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[no_mangle]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; tbt&lt;&#x2F;span&gt;&lt;span&gt;() {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; In Rust 2024 you need to add the unsafe attribute:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;unsafe&lt;&#x2F;span&gt;&lt;span&gt;(no_mangle)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; tbt&lt;&#x2F;span&gt;&lt;span&gt;() {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Starting with the 2024 Edition, it is now required to mark these attributes as unsafe. This one applies to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;reference&#x2F;abi.html#the-export_name-attribute&quot;&gt;export_name&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;reference&#x2F;abi.html#the-link_section-attribute&quot;&gt;link_section&lt;&#x2F;a&gt;, and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;reference&#x2F;abi.html#the-no_mangle-attribute&quot;&gt;no_mangle&lt;&#x2F;a&gt;.
It is crucial because previously the app could crash even if it contained only safe code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Hello, world!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[export_name &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;malloc&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;edition-guide&#x2F;rust-2024&#x2F;static-mut-references.html&quot;&gt;Disallow references to static mut&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;static mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; X&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 23&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; ERROR: shared reference to mutable static&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;X&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Merely taking such a reference in violation of Rust&#x27;s mutability XOR aliasing requirement has always been instantaneous undefined behavior,
even if the reference is never read from or written to.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;edition-guide&#x2F;rust-2024&#x2F;unsafe-extern.html&quot;&gt;Unsafe extern blocks&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Adding the unsafe keyword helps to emphasize that it is the responsibility of the author of the extern block to ensure that the signatures are correct.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It produces a warning in Rust 2021, but in Rust 2024 it results in error.&lt;&#x2F;p&gt;
&lt;p&gt;Now you understand why the 2024 edition is preferred in unsafe code 😃.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;unsafe-blocks-without-safety-comments&quot;&gt;&lt;code&gt;unsafe&lt;&#x2F;code&gt; blocks without &lt;code&gt;SAFETY&lt;&#x2F;code&gt; comments&lt;&#x2F;h3&gt;
&lt;p&gt;The whole &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;safety-comments-matter&#x2F;#safety-comments-matter&quot;&gt;first part&lt;&#x2F;a&gt; of the article is about it. You should already understand the importance of such comments in the code.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;many-unsafe-operations-per-one-unsafe-block&quot;&gt;Many unsafe operations per one unsafe block&lt;&#x2F;h3&gt;
&lt;p&gt;It is partially covered by the 2024 edition, but still can violated:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Compiles without any warnings.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;unsafe fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; tbt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *mut *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; null_mut&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It is not recommended (by me and some other dudes 😉) to have multiple unsafe operations in one &lt;code&gt;unsafe&lt;&#x2F;code&gt; block.
Because it becomes much harder to keep the code safe and follow all safety preconditions.
Every unsafe operation should have its own &lt;code&gt;unsafe&lt;&#x2F;code&gt; block and &lt;code&gt;SAFETY&lt;&#x2F;code&gt; comment above it (you can see an example in &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;safety-comments-matter&#x2F;#example&quot;&gt;the first part&lt;&#x2F;a&gt; of the article).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;miri&quot;&gt;Miri&lt;&#x2F;h3&gt;
&lt;p&gt;I already described all pros and cons of Miri here: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;miri&#x2F;&quot;&gt;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;miri&#x2F;&lt;&#x2F;a&gt;. Please, read this article so I don&#x27;t need to repeat myself.&lt;&#x2F;p&gt;
&lt;p&gt;TL;DR: if you have many unsafe operations, then consider using Miri. Miri is awesome and will help you to prevent a lot of bugs.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pointer-integer-cast&quot;&gt;Pointer &amp;lt;-&amp;gt; integer cast&lt;&#x2F;h3&gt;
&lt;p&gt;Oh, this one deserves a separate article, but I will try to fit it in a few sentences.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m still convinced that the Rust documentation is the best place to learn about unsafe. To your attention, quotes from the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;ptr&#x2F;#provenance&quot;&gt;&lt;code&gt;std::ptr&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; module level documentation:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pointers are not simply an “integer” or “address”.&lt;&#x2F;strong&gt; ...pointers need to somehow be more than just their addresses: they must have provenance. Provenance can affect whether a program has undefined behavior:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It is undefined behavior to access memory through a pointer that does not have provenance over that memory.&lt;&#x2F;li&gt;
&lt;li&gt;It is undefined behavior to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.pointer.html#method.offset&quot;&gt;&lt;code&gt;offset&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; a pointer across a memory range that is not contained in the allocated object it is derived from, or to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.pointer.html#method.offset_from&quot;&gt;&lt;code&gt;offset_from&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; two pointers not derived from the same allocated object. Provenance is used to say what exactly “derived from” even means: the lineage of a pointer is traced back to the Original Pointer it descends from, and that identifies the relevant allocated object. In particular, it’s always UB to offset a pointer derived from something that is now deallocated, except if the offset is 0.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;ptr&#x2F;#pointers-vs-integers&quot;&gt;and&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;From this discussion, it becomes very clear that a &lt;code&gt;usize&lt;&#x2F;code&gt; cannot accurately represent a pointer, and converting from a pointer to a &lt;code&gt;usize&lt;&#x2F;code&gt; is generally an operation which only extracts the address. Converting this address back into pointer requires somehow answering the question: which provenance should the resulting pointer have?&lt;&#x2F;p&gt;
&lt;p&gt;Rust provides two ways of dealing with this situation: &lt;em&gt;Strict Provenance&lt;&#x2F;em&gt; and &lt;em&gt;Exposed Provenance&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;There is a lot more to say. But I think you can read the Rust doc by yourself. My point is that you should never cast a pointer to an integer and vice versa. Or if you even dare to do it, then at least use an appropriate API: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.pointer.html#method.expose_provenance&quot;&gt;&lt;code&gt;expose_provenance&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;ptr&#x2F;fn.with_exposed_provenance.html&quot;&gt;&lt;code&gt;with_exposed_provenance&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Pointers are not simply an &quot;integer&quot; or &quot;address&quot; 🙂.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Implementing Kerberos RPC encryption over SSPI</title>
        <published>2025-04-05T00:00:00+00:00</published>
        <updated>2025-04-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/rpc-encryption-sspi-kerberos/"/>
        <id>https://tbt.qkation.com/posts/rpc-encryption-sspi-kerberos/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/rpc-encryption-sspi-kerberos/">&lt;h1 id=&quot;intro&quot;&gt;Intro&lt;&#x2F;h1&gt;
&lt;p&gt;Today&#x27;s world has many unknown and magical things. Proprietary protocols and libraries are among them 🤪. In this blog post, I will explain how RPC encryption works under the hood and how to implement it over the SSPI interface.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;goals&quot;&gt;Goals&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Provide a detailed explanation of how RPC PDUs are encrypted.&lt;&#x2F;li&gt;
&lt;li&gt;Explain how it is related to SSPI.&lt;&#x2F;li&gt;
&lt;li&gt;Implement RPC PDUs encryption&#x2F;decryption and test it against &lt;strong&gt;real RPC traffic&lt;&#x2F;strong&gt; 🤭.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;non-goals&quot;&gt;Non-goals&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;I&#x27;m not explaining RPC use cases or how to set it up.&lt;&#x2F;li&gt;
&lt;li&gt;Do not expect RPC internals explanations.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This blog post is only about encrypting and decrypting RPC PDUs.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;getting-started&quot;&gt;Getting started&lt;&#x2F;h1&gt;
&lt;p&gt;I assume the reader has enough knowledge and experience with RPC and SSPI to read this article. If not, I highly recommend reading the following articles (they should give enough context to understand what I am going to do):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.bloggingforlogging.com&#x2F;2023&#x2F;04&#x2F;28&#x2F;rpc-encryption-an-exercise-in-frustration&#x2F;&quot;&gt;RPC Encryption - An Exercise in Frustration&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;sspi-introduction&#x2F;&quot;&gt;SSPI introduction&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Microsoft frequently uses RPC for local and remote calls. Of course, many remote RPC calls are encrypted, and the caller needs to pass the authentication to communicate with the server.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s take, for example, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-gkdi&#x2F;943dd4f6-6b80-4a66-8594-80df6d2aad0a&quot;&gt;[MS-GKDI]: Group Key Distribution Protocol&lt;&#x2F;a&gt;,&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;...which enables clients to obtain cryptographic keys associated with Active Directory security principals.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It specifies only one &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-gkdi&#x2F;4cac87a3-521e-4918-a272-240f8fabed39&quot;&gt;&lt;code&gt;GetKey&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; RPC method. I hope it&#x27;s obvious that the key is encrypted and cannot be sent over the network as plaintext.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;rpc-encryption-sspi-kerberos&#x2F;.&#x2F;encrypted-rpc-request.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;(If you want to open and analyze this packet with me, then here is a Wireshark recording: &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;rpc-encryption-sspi-kerberos&#x2F;.&#x2F;rpc.pcapng&quot;&gt;rpc.pcapng&lt;&#x2F;a&gt;.)&lt;&#x2F;p&gt;
&lt;p&gt;Captured RPC communication shows us all authentication steps and encrypted &lt;code&gt;GetKey&lt;&#x2F;code&gt; RPC method call. And we will decrypt it at the end of this article 😎.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;rpc-pdu-structure&quot;&gt;RPC PDU structure&lt;&#x2F;h1&gt;
&lt;p&gt;(Alternatively, you can read the &lt;em&gt;RPC Payload&lt;&#x2F;em&gt; section from the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.bloggingforlogging.com&#x2F;2023&#x2F;04&#x2F;28&#x2F;rpc-encryption-an-exercise-in-frustration&#x2F;&quot;&gt;RPC Encryption - An Exercise in Frustration&lt;&#x2F;a&gt; article).&lt;&#x2F;p&gt;
&lt;p&gt;RPC PDU is usually split into three parts (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9629399&#x2F;chap12.htm&quot;&gt;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9629399&#x2F;chap12.htm&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;name&lt;&#x2F;th&gt;&lt;th&gt;purpose&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;header&lt;&#x2F;td&gt;&lt;td&gt;contains protocol control information&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;body&lt;&#x2F;td&gt;&lt;td&gt;the body of a request or response PDU contains data representing the input or output parameters for an operation&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;security trailer&lt;&#x2F;td&gt;&lt;td&gt;contains data specific to an authentication protocol. For example, an authentication protocol may ensure the integrity of a packet via inclusion of an encrypted checksum in the authentication verifier&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;But for now, we need to dig a bit deeply. PDU body consists of its header and data. In turn, the PDU security trailer also has its header and auth value. Look at the screenshot below:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;rpc-encryption-sspi-kerberos&#x2F;.&#x2F;rpc-pdu-structure.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I think you&#x27;ve got the idea. In our case, the PDU body data and security trailer auth value are encrypted.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;rpc-encryption-over-sspi&quot;&gt;RPC encryption over SSPI&lt;&#x2F;h1&gt;
&lt;p&gt;Why SSPI? There are several reasons why:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;This is how it is originally done in Windows.&lt;&#x2F;li&gt;
&lt;li&gt;Some aspects of the encryption process make sense only with SSPI in mind.&lt;&#x2F;li&gt;
&lt;li&gt;RPC and SSPI are interconnected in many places, so why not explain the SSPI part?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;RPC PDUs are encrypted by calling the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;nf-sspi-encryptmessage&quot;&gt;SSPI::EncryptMessage&lt;&#x2F;a&gt; function (and, correspondingly, decryption is done by calling the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;nf-sspi-decryptmessage&quot;&gt;SSPI::DecryptMessage&lt;&#x2F;a&gt; function). Let&#x27;s see its interface.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;nf-sspi-encryptmessage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;SECURITY_STATUS SEC_ENTRY&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; EncryptMessage&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;font-style: italic;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt;]      PCtxtHandle    phContext,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [in]      unsigned long  fQOP,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [in, out] PSecBufferDesc pMessage,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [in]      unsigned long  MessageSeqNo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;nf-sspi-decryptmessage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;SECURITY_STATUS SEC_ENTRY&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; DecryptMessage&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;font-style: italic;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt;]      PCtxtHandle    phContext,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [in, out] PSecBufferDesc pMessage,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [in]      unsigned long  MessageSeqNo,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [out]     unsigned long  *pfQOP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;ns-sspi-secbufferdesc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;typedef struct _SecBufferDesc {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  unsigned long&lt;&#x2F;span&gt;&lt;span&gt; ulVersion;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  unsigned long&lt;&#x2F;span&gt;&lt;span&gt; cBuffers;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  PSecBuffer    pBuffers;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} SecBufferDesc,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;PSecBufferDesc;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;ns-sspi-secbuffer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;typedef struct _SecBuffer {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  unsigned long&lt;&#x2F;span&gt;&lt;span&gt; cbBuffer;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  unsigned long&lt;&#x2F;span&gt;&lt;span&gt; BufferType;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  char          *&lt;&#x2F;span&gt;&lt;span&gt;pvBuffer;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} SecBuffer,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;PSecBuffer;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are a lot of security buffer types and two security buffer flags defined in SSPI (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;ns-sspi-secbuffer&quot;&gt;SecBuffer structure (&lt;code&gt;sspi.h&lt;&#x2F;code&gt;): &lt;code&gt;BufferType&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;). But for now, we need only a few of them:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;buffer type&lt;&#x2F;th&gt;&lt;th&gt;meaning&#x2F;purpose&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SECBUFFER_TOKEN&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;in the general case, it contains the security token portion of the message. In our case, it contains a signature generated by the security package.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SECBUFFER_DATA&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;contains input data to be processed by the security package. In our case, it&#x27;s just data we want to encrypt or decrypt.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Also, we have two possible buffer flags:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;buffer flag&lt;&#x2F;th&gt;&lt;th&gt;meaning&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SECBUFFER_READONLY&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;the data in this buffer is read-only and is never can be overwritten by the security package. Usually, this flag is used to inform the security package about something.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SECBUFFER_READONLY_WITH_CHECKSUM&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;The data in this buffer is included in the checksum calculation but not in the encryption&#x2F;decryption process.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;As you can see, the message we want to encrypt is an array of buffers. The whole PDU is split into SSPI security buffers and passed to the &lt;code&gt;SSPI::EncryptMessage&lt;&#x2F;code&gt; function. This process is described in the &lt;em&gt;&quot;Message Protection&quot;&lt;&#x2F;em&gt; section of the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.bloggingforlogging.com&#x2F;2023&#x2F;04&#x2F;28&#x2F;rpc-encryption-an-exercise-in-frustration&#x2F;&quot;&gt;RPC Encryption - An Exercise in Frustration&lt;&#x2F;a&gt; article. In short, it happens as follows:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;security buffer type + flags&lt;&#x2F;th&gt;&lt;th&gt;security buffer value&lt;&#x2F;th&gt;&lt;th&gt;made-up name&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;SECBUFFER_DATA&lt;&#x2F;code&gt; + &lt;code&gt;SECBUFFER_READONLY_WITH_CHECKSUM&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;contains PDU header + PDU body header&lt;&#x2F;td&gt;&lt;td&gt;Sign1&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;SECBUFFER_DATA&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;contains PDU body data to be encrypted (in-place)&lt;&#x2F;td&gt;&lt;td&gt;Enc&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;SECBUFFER_DATA&lt;&#x2F;code&gt; + &lt;code&gt;SECBUFFER_READONLY_WITH_CHECKSUM&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;contains PDU security trailer header&lt;&#x2F;td&gt;&lt;td&gt;Sign2&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;4&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;SECBUFFER_TOKEN&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;will contain PDU security trailer auth value&lt;&#x2F;td&gt;&lt;td&gt;Token&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;We will refer to these buffers a lot, so I added made-up names to each of them. This can be illustrated in the previous RPC request that we used as the example:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;rpc-encryption-sspi-kerberos&#x2F;.&#x2F;pdu-to-sspi-buffers.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;All encryption is always &lt;strong&gt;in-place&lt;&#x2F;strong&gt;. The security package overwrites the original data with encrypted data. This also means that the caller must allocate the last security buffer (4th which has the &lt;code&gt;SECBUFFER_TOKEN&lt;&#x2F;code&gt; type), and the security package will overwrite it. The caller can get the token buffer length by calling the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;querycontextattributes--general&quot;&gt;&lt;code&gt;QueryContextAttributes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function with the &lt;code&gt;SECPKG_ATTR_SIZES&lt;&#x2F;code&gt; parameter. The &lt;code&gt;cbSecurityTrailer&lt;&#x2F;code&gt; field of the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;ns-sspi-secpkgcontext_sizes&quot;&gt;&lt;code&gt;SecPkgContext_Sizes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; structure contains a desired value.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;sspi-encryptmessage&quot;&gt;SSPI::EncryptMessage&lt;&#x2F;h1&gt;
&lt;p&gt;Before implementing it, I want to clarify some general function behavior. As I wrote above, it encrypts the input message in-place. Some security packages, besides encryption, also calculate checksum over the provided data. Even more, some security packages can only calculate a checksum over the provided data. Here is a citation from the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;nf-sspi-encryptmessage&quot;&gt;MSDN&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Some packages do not have messages to be encrypted or decrypted but rather provide an integrity hash that can be checked.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In our case, both encryption and integrity hash (hmac) calculations happen. We have 4 buffers as an input message. The general encryption process looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; pseudo code&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Sign1: message[0] is PDU header + PDU body header. SECBUFFER_DATA + SECBUFFER_READONLY_WITH_CHECKSUM.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Enc: message[1] is PDU body data. we need to encrypt it. SECBUFFER_DATA.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Sign2: message[2] is PDU security trailer header. SECBUFFER_DATA + SECBUFFER_READONLY_WITH_CHECKSUM.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Token: message[3] is PDU security trailer auth value. Currently, this buffer is blank (memory is allocated). SECBUFFER_TOKEN.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; encrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; checksum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;kerberos-encryptmessage&quot;&gt;Kerberos::EncryptMessage&lt;&#x2F;h1&gt;
&lt;p&gt;Now that we have enough knowledge about the encryption process, we can talk about concrete encryption algorithms. The client can authenticate using one of the available protocols (security packages) like NTLM or Kerberos. The most secure these days is, of course, Kerberos. Our task is to understand how it works and implement it.&lt;&#x2F;p&gt;
&lt;p&gt;First, I should mention that the &lt;code&gt;Kerberos::EncryptMessage&lt;&#x2F;code&gt; function behaves as the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-kile&#x2F;e94b3acd-8415-4d0d-9786-749d0c39d550&quot;&gt;&lt;code&gt;GSS_WrapEx&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function. It encrypts the data, constructs a Wrap Token, and writes it in the input message. The wrap token construction and encryption process are defined in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc4121.html&quot;&gt;RPC 4121&lt;&#x2F;a&gt;. Let&#x27;s recall &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc4121.html#section-4.2.6.2&quot;&gt;the token structure&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Octet no   Name        Description&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--------------------------------------------------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 0..1     TOK_ID    Identification field.  Tokens emitted by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    GSS_Wrap() contain the hex value 05 04&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    expressed in big-endian order in this&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    field.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 2        Flags     Attributes field, as described in section&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    4.2.2.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 3        Filler    Contains the hex value FF.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 4..5     EC        Contains the &amp;quot;extra count&amp;quot; field, in big-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    endian order as described in section 4.2.3.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 6..7     RRC       Contains the &amp;quot;right rotation count&amp;quot; in big-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    endian order, as described in section&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    4.2.5.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 8..15    SND_SEQ   Sequence number field in clear text,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    expressed in big-endian order.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 16..last Data      Encrypted data for Wrap tokens with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    confidentiality, or plaintext data followed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    by the checksum for Wrap tokens without&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    confidentiality, as described in section&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    4.2.4.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This can look familiar to you because we already saw this structure in the Wireshark:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;rpc-encryption-sspi-kerberos&#x2F;.&#x2F;krb-wrap-token.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If we want to decrypt the RPC request, then we need to know the meaning of each field:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;name&lt;&#x2F;th&gt;&lt;th&gt;meaning&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;TOK_ID&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;0x0504&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Flags&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;They depend on the authentication process.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Filler&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;0xff&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;EC&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc4121.html#section-4.2.3&quot;&gt;RFC 4121: EC Field&lt;&#x2F;a&gt;. It represents how many filler bytes we must insert after the plaintext data before encryption. In our case, it is equal to &lt;strong&gt;16&lt;&#x2F;strong&gt; (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-kile&#x2F;e94b3acd-8415-4d0d-9786-749d0c39d550&quot;&gt;The sender should set extra count (EC) to 1 block - 16 bytes.&lt;&#x2F;a&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;RRC&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;In our case, it is equal to &lt;strong&gt;28&lt;&#x2F;strong&gt;. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-kile&#x2F;e94b3acd-8415-4d0d-9786-749d0c39d550&quot;&gt;The RRC field is 28 if encryption is requested.&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SND_SEQ&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;This value is set by the Kerberos implementation.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;It might not make much sense to you so far, but soon enough, you will have one picture.&lt;&#x2F;p&gt;
&lt;p&gt;RFC 4121 also defines &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc4121.html#section-4.2.4&quot;&gt;the encryption process&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The resulting Wrap token is &lt;code&gt;{&quot;header&quot; | encrypt(plaintext-data | filler | &quot;header&quot;)}&lt;&#x2F;code&gt;, where &lt;code&gt;encrypt()&lt;&#x2F;code&gt; is the encryption operation.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It looks simple, and I think you got the idea. But there is a tricky moment. The negotiated Kerberos encryption algorithm is &lt;code&gt;AES256-CTS-HMAC-SHA1-96&lt;&#x2F;code&gt;. This algorithm has two specific features:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It appends a checksum (hmac) over the plaintext to the ciphertext.&lt;&#x2F;li&gt;
&lt;li&gt;It prepends one block of random bytes (named &lt;em&gt;confounder&lt;&#x2F;em&gt;) to the plaintext data before encryption (it is a non-deterministic encryption).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So, the actual encryption scheme is a bit more complex and looks something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; pseudocode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; I hope you didn&amp;#39;t forget the `message` array from the previous pseudo code block.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; ec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; filler&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; ec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0x00&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; confounder&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; rand&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data_to_encrypt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; filler&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token_header&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; ciphertext&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; encrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;confounder&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data_to_encrypt&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data_to_hmac&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; filler&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token_header&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; checksum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; hmac&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;confounder&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data_to_hmac&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; ciphertext&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; checksum&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Cool. Can we finally write the resulting Wrap Token to input buffers?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Not yet 🤭. The RFC also defined the right rotation operation after the encryption. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc4121.html#section-4.2.5&quot;&gt;RFC 4121: RRC Field&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &quot;RRC&quot; (Right Rotation Count) field in Wrap tokens is added &lt;strong&gt;to allow the data to be encrypted in-place by existing SSPI applications&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Excluding the first 16 octets of the token header, the resulting Wrap token in the previous section is rotated to the right by &quot;RRC&quot; octets. The net result is that &quot;RRC&quot; octets of trailing octets are moved toward the header.&lt;&#x2F;p&gt;
&lt;p&gt;Consider the following as an example of this rotation operation: Assume that the RRC value is 3 and the token before the rotation is &lt;code&gt;{&quot;header&quot; | aa | bb | cc | dd | ee | ff | gg | hh}&lt;&#x2F;code&gt;.  The token after rotation would be &lt;code&gt;{&quot;header&quot; | ff | gg | hh | aa | bb | cc | dd | ee }&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It means, that we need to do the right-rotation operation on &lt;code&gt;ciphertext | checksum&lt;&#x2F;code&gt;. But pay attention here: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-kile&#x2F;e94b3acd-8415-4d0d-9786-749d0c39d550&quot;&gt;we must rotate it by &lt;strong&gt;RRC + RC&lt;&#x2F;strong&gt; bytes&lt;&#x2F;a&gt;. The final Wrap Token looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; pseudocode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rrc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 28&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; ec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; rotate_right&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;ciphertext&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; checksum&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rrc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; ec&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The very last step is to split the resulting Wrap Token into buffers and write them into corresponding input buffers (input message). Let&#x27;s recall the task. We have 4 input buffers:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Sign1: &lt;code&gt;Data&lt;&#x2F;code&gt; buffer with &lt;code&gt;SECBUFFER_READONLY_WITH_CHECKSUM&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Enc: &lt;code&gt;Data&lt;&#x2F;code&gt; buffer.&lt;&#x2F;li&gt;
&lt;li&gt;Sign2: &lt;code&gt;Data&lt;&#x2F;code&gt; buffer with &lt;code&gt;SECBUFFER_READONLY_WITH_CHECKSUM&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Token: &lt;code&gt;Token&lt;&#x2F;code&gt; buffer.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And now we need to write the Wrap Token buffer into the second and fourth buffers. To do it correctly, we write first &lt;code&gt;cbSecurityTrailer&lt;&#x2F;code&gt; bytes of the Wrap Token into the Token buffer, and the rest of the Wrap Token should be written into the Enc buffer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; pseudocode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; cb_security_trailer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 76&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;token&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;split_at&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;cb_security_trailer&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Write into the Enc buffer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;copy_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Write into the Token buffer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;copy_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;token&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Some curious readers may ask me:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Why can&#x27;t we fill the Enc buffer first and then just write the rest of the Wrap Token into the Token buffer? Most likely because the RPC server expects the same buffers, as you just explained.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;But the question is why it works this way and not another.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Some things are done on purpose, while others are simply historical heritage (legacy). If you write down all these data manipulations, you can notice that, in the end, the Enc buffer ciphertext matches the original data. The checksum, encrypted confounder, and Wrap Token header will be in the Token buffer. Look at the scheme below:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;rpc-encryption-sspi-kerberos&#x2F;.&#x2F;rpc-encryption-full-diagram.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I tried to show the whole encryption process in the diagram above. As you can see, the encrypted Enc buffer data is written directly into the Enc buffer. But the Wrap Token Header, encrypted confounder, filler, etc., are written exclusively in the Token buffer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;assumptions&quot;&gt;Assumptions&lt;&#x2F;h2&gt;
&lt;p&gt;Now we know all the details of the encryption process. Of course, we can&#x27;t know all the reasons behind Microsoft&#x27;s decisions regarding their protocols and implementations. But for now, I can make a few &lt;strong&gt;&lt;em&gt;assumptions&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Why do we need to rotate &lt;code&gt;ciphertext | checksum&lt;&#x2F;code&gt;?&lt;&#x2F;strong&gt;. To make the encrypted Enc buffer data match the unencrypted one. This way, the encryption will be &lt;em&gt;in-place&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Why is the EC value equal to 16?&lt;&#x2F;strong&gt;. Just to extend the ciphertext (to make it longer on purpose). &lt;strong&gt;Why do we need to make it longer?&lt;&#x2F;strong&gt; Kerberos AES256-CTS-HMAC-SHA1-96 encryption algorithm uses AES256 in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Ciphertext_stealing&quot;&gt;CTS mode&lt;&#x2F;a&gt;. In short, it changes the last two blocks of ciphertext, so the padding is unnecessary. To ensure that the encrypted Enc buffer data is not affected during CTS (cipher text stealing) (otherwise, it would be impossible for the encrypted Enc buffer data to match the unencrypted one), we need to be sure that the last two blocks of the ciphertext do not contain the Enc buffer data. Thus, we have two additional blocks: the first block is the filler bytes (&lt;code&gt;0x00 * 16&lt;&#x2F;code&gt;) and the second block is the Wrap Token header (16 bytes long).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Why is the &lt;code&gt;cbSecurityTrailer&lt;&#x2F;code&gt; value equal to 76?&lt;&#x2F;strong&gt; wrap token header len + confounder len + filler len + wrap token header (encrypted) len + checksum len = 16 + 16 + 16 + 16 + 12 = 76.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Alternatively, you can read Microsoft&#x27;s example of the message encryption. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-kile&#x2F;ade7594d-5934-42e0-994e-93fa0fd1f359&quot;&gt;[MS-KILE]: &lt;code&gt;GSS_WrapEx&lt;&#x2F;code&gt; with &lt;code&gt;AES128-CTS-HMAC-SHA1-96&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-kile&#x2F;ms-kile_files&#x2F;image004.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The picture above shows the same process but with two buffers to encrypt instead of one. &lt;code&gt;clearhdr&lt;&#x2F;code&gt; - Wrap Token header. &lt;code&gt;padding&lt;&#x2F;code&gt; = &lt;code&gt;ec * 0x00&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Phew 😮‍💨 I hope you are not tired because we are going to implement it 🤗.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;code-encryptor&quot;&gt;Code: Encryptor&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note 1&lt;&#x2F;strong&gt;. The full code is available here: RPC decryptor &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;feat&#x2F;rpc-kerberos-encryption&#x2F;rpc-decryptor&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;rpc-decryptor&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note 2&lt;&#x2F;strong&gt;. The code in this article is not production-ready! &lt;strong&gt;The only purpose of the code below is to show the algorithm&#x27;s correctness.&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start with simple things. Here is a small &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;ns-sspi-secbuffer&quot;&gt;&lt;code&gt;SecBuffer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; implementation. We don&#x27;t need anything more complex.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; DATA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; TOKEN&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; READONLY_WITH_CHECKSUM_FLAG&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0x10000000&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; buffer_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;buffer_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;        Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; buffer_type&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we need a Wrap Token implementation. I don&#x27;t want to overengineer it. I wrote a simple Wrap Token header encoding&#x2F;decoding. Again, we don&#x27;t need anything more complex.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; WrapTokenHeader&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; flags&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; ec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rrc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; send_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; WrapTokenHeader&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; encoded&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span&gt;] {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; header_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        header_data&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;copy_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0x05&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0x04&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        header_data&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;flags;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        header_data&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0xff&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        header_data&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;copy_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_be_bytes&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        header_data&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;copy_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rrc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_be_bytes&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        header_data&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;copy_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;send_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_be_bytes&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        header_data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; from_bytes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Read&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;read_u16&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;BigEndian&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0x0504&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Invalid Wrap Token ID&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; flags&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;read_u8&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; filler&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;read_u8&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; filler&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0xff&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Invalid filler&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; ec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;read_u16&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;BigEndian&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rrc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;read_u16&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;BigEndian&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; send_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;read_u64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;BigEndian&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;        Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            flags&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            ec&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            rrc&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            send_seq&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Great! Now the fun part: encryption implementation. First of all, we should define the constants we are going to use.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; &amp;quot;Extra count&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; EC&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; &amp;quot;Right Rotation Count&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; RRC&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 28&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc4121.html#section-2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; CLIENT_ENCRYPTION_KEY_USAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; CLIENT_DECRYPTION_KEY_USAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 22&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; SERVER_ENCRYPTION_KEY_USAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; CLIENT_DECRYPTION_KEY_USAGE&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; SERVER_DECRYPTION_KEY_USAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; CLIENT_ENCRYPTION_KEY_USAGE&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; CB_SECURITY_TRAILER&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* wrap token header len *&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* confounder len *&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; EC&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* wrap token header (encrypted) len *&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 12&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* checksum (hmac) len *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You may be surprised by key usage numbers. Don&#x27;t worry.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc4120#section-7.5.1&quot;&gt;7.5.1.  Key Usage Numbers&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The encryption and checksum specifications in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc3961&quot;&gt;RFC3961&lt;&#x2F;a&gt; require as input a &lt;em&gt;&quot;key usage number&quot;&lt;&#x2F;em&gt;, to alter the encryption key used in any specific message to make certain types of cryptographic attack more difficult.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In other words, a key usage number is a &lt;em&gt;public&lt;&#x2F;em&gt; known value used to derive the encryption key from a base key (session key). You should not care about it. We always use key usage numbers specified in the RFC&#x2F;specification.&lt;&#x2F;p&gt;
&lt;p&gt;Now we can start implementing RPC encryption. Finally! We start with the Wrap Token and filler generation.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; encrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key_usage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; send_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; WrapTokenHeader&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        flags&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0x06&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        ec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; EC&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        rrc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        send_seq&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; encoded_wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;encoded&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; filler&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;EC&lt;&#x2F;span&gt;&lt;span&gt;)];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    todo!&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, we encrypt the data. Let&#x27;s do it in two steps:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Collect the data to encrypt in one buffer: DATA sec buffer + filler + wrap token header.&lt;&#x2F;li&gt;
&lt;li&gt;Encrypt it with the correct key usage number. There are not many Kerberos encryption algorithm implementations. The only actively used and well-maintained one is &lt;code&gt;picky-krb&lt;&#x2F;code&gt;: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;picky-krb&#x2F;latest&#x2F;picky_krb&#x2F;crypto&#x2F;aes&#x2F;index.html&quot;&gt;docs.rs&#x2F;picky-krb&#x2F;crypto&#x2F;aes&#x2F;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; encrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key_usage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; send_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Find the Enc buffer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data_to_encrypt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;fold&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; acc&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer_type &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; DATA&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        acc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; + Filler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    data_to_encrypt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;filler&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; + Wrap token header&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    data_to_encrypt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;encoded_wrap_token_header&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; cipher&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Aes256CtsHmacSha196&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; EncryptWithoutChecksum&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; encrypted&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        confounder&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        ki&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; cipher&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;encrypt_no_checksum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key_usage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;data_to_encrypt&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    todo!&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I hope you didn&#x27;t forget about the confounder. In the code above, it is autogenerated and returned from the &lt;code&gt;encrypt_no_checksum&lt;&#x2F;code&gt; function. We need it to correctly calculate HMAC. What is next? Right, checksum calculation.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; encrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key_usage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; send_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data_to_sign&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;fold&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;confounder&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; acc&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer_type &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; DATA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; READONLY_WITH_CHECKSUM_FLAG&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; else if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer_type &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; DATA&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        acc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; + Filler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    data_to_sign&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;filler&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; + Wrap token header&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    data_to_sign&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;encoded_wrap_token_header&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; checksum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; cipher&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;encryption_checksum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key_usage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;data_to_sign&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    encrypted&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;checksum&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    todo!&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see, we calculate checksum separately from the encryption because we may have &lt;code&gt;READONLY_WITH_CHECKSUM_FLAG&lt;&#x2F;code&gt; buffers which we don&#x27;t need to encrypt.&lt;&#x2F;p&gt;
&lt;p&gt;😮‍💨 What&#x27;s left? Right rotation, final Wrap Token construction, copying the data to the input &lt;code&gt;message&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; encrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key_usage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; send_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    encrypted&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;rotate_right&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;RRC&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; EC&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rrc &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; RRC&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; final Wrap Token&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; raw_wrap_token&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;encoded&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_vec&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    raw_wrap_token&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;encrypted&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;token&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; raw_wrap_token&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;split_at&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;CB_SECURITY_TRAILER&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; token_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;iter_mut&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;find&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer_type &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; TOKEN&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;TOKEN buffer not found&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    token_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;copy_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;token&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;iter_mut&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;find&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer_type &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; DATA&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;DATA buffer not found&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    data_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;copy_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s all! We just implemented RPC Kerberos encryption! 😎 🥳&lt;&#x2F;p&gt;
&lt;h1 id=&quot;code-decryptor&quot;&gt;Code: Decryptor&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;&#x2F;strong&gt;. The full code is available here: RPC decryptor &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;feat&#x2F;rpc-kerberos-encryption&#x2F;rpc-decryptor&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;rpc-decryptor&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I didn&#x27;t explain the decryption process in detail, but it is completely the reverse of encryption. Look at the scheme below (you may need to zoom in or open it in a new tab):&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;rpc-encryption-sspi-kerberos&#x2F;.&#x2F;rpc-decryption-full-diagram.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As you can see, the decryption process is a reversed encryption process (obviously, makes sense). Time to start implementing it. We start with the Wrap Token construction and split it into the header and encrypted parts.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; decrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key_usage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;iter_mut&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;find&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer_type &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; TOKEN&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;TOKEN buffer not found&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_vec&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer_type &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; DATA&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            wrap_token&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;wrap_token_header&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; encrypted&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;split_at_mut&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* Wrap Token header length *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; WrapTokenHeader&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from_bytes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    encrypted&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;rotate_left&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rrc &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ec));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    todo!&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, we do the left rotation and data decryption:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; decrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key_usage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    encrypted&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;rotate_left&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rrc &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ec));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; cipher&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Aes256CtsHmacSha196&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; DecryptWithoutChecksum&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        plaintext&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        confounder&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        checksum&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        ki&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; cipher&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;decrypt_no_checksum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key_usage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; encrypted&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; plaintext_len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; plaintext&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;wrap_token_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ec &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* Wrap Token header length *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; plaintext - decrypted data.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; data - filler + wrap token.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;plaintext&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; plaintext&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;split_at&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;plaintext_len&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    todo!&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Nice! And, of course, we need to calculate the checksum and compare it with the provided one.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; decrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key_usage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; decrypted&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; plaintext&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data_to_sign&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;fold&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;confounder&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; acc&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer_type &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; DATA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; READONLY_WITH_CHECKSUM_FLAG&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; else if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer_type &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; DATA&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;decrypted&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;()]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            decrypted&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;decrypted&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        acc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; + Filler + Wrap token header&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    data_to_sign&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;extend_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; calculated_checksum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; cipher&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;encryption_checksum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key_usage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;data_to_sign&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; calculated_checksum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; checksum&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Checksum mismatch: message is altered&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    todo!&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;😮‍💨 And the last one: copying the plaintext to the input &lt;code&gt;message&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; decrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key_usage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; decrypted&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; plaintext&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    message&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;iter_mut&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buffer_type &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; DATA&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;copy_from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;decrypted&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;()]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            decrypted&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;decrypted&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sec_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;🎊 🥳 That&#x27;s all! Now we have encryptor and decryptor implemented.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;code-testing&quot;&gt;Code: testing&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s add a simple test to ensure that it works at least against itself (encrypt-decrypt test). I wrote small wrappers for the encryption&#x2F;decryption functions to make testing easier:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; KerberosClient&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    send_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; KerberosClient&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; TOKEN_LEN&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; CB_SECURITY_TRAILER&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; send_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;        Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; send_seq&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; encrypt_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        encrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;key,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; CLIENT_ENCRYPTION_KEY_USAGE&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;send_seq,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; decrypt_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        decrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;key,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; CLIENT_DECRYPTION_KEY_USAGE&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; KerberosServer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    send_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; KerberosServer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; TOKEN_LEN&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; CB_SECURITY_TRAILER&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; send_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;        Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; send_seq&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; encrypt_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        encrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;key,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; SERVER_ENCRYPTION_KEY_USAGE&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;send_seq,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; decrypt_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SecBuffer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        decrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;key,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; SERVER_DECRYPTION_KEY_USAGE&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pretty straightforward and understandable. And most importantly, we don&#x27;t need more. Here is a simple test:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[test]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; encrypt_decrypt&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; tbt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; b&amp;quot;TheBestTvarynka&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; session_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        91&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 11&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 188&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 227&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 91&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 180&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 246&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 129&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 251&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 200&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 118&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 82&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 109&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 65&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 241&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 177&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 109&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 124&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 39&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 127&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 171&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        222&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 132&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 199&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 199&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 126&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 110&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 166&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; kerberos_client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; KerberosClient&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;session_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_vec&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 681238048&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; kerberos_server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; KerberosServer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;session_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_vec&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 681238048&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data_buf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; tbt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_vec&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; token_buf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; KerberosClient&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;TOKEN_LEN&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;        SecBuffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;DATA&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; data_buf&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;        SecBuffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;TOKEN&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; token_buf&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    kerberos_client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;encrypt_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    kerberos_server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;decrypt_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; tbt&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;rpc-encryption-sspi-kerberos&#x2F;.&#x2F;encrypt_decrypt_test.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Good results so far! But do you remember our main goal? We wanted to decrypt the captured encrypted RPC request. Let&#x27;s do it! Now nothing can stop us 😉 😆.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[test]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; decrypt_rpc_request&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; session_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        19&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 28&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 59&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 181&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 202&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 41&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 22&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 25&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 122&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 144&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 217&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 87&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 170&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 209&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 72&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 223&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 145&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 41&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 12&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 252&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 229&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 45&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        218&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 206&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 161&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 199&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 216&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 243&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 53&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; kerberos_server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; KerberosServer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;session_key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 41895117&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; PDU header + PDU body header&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 60&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 76&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 208&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; PDU body: encrypted part&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; enc_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        12&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 202&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 158&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 245&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 73&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 200&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 196&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 158&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 187&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 135&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 112&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 187&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 78&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 253&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 225&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 60&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 114&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 70&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 163&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 77&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 66&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 75&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        203&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 192&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 184&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 167&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 222&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 182&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 217&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 253&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 203&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 107&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 132&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 172&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 128&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 70&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 81&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 210&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 183&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 199&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 117&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 14&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 7&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        215&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 161&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 70&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 44&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 155&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 123&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 215&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 95&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 187&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 68&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 145&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 45&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 106&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 53&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 92&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 218&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 167&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 113&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 41&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 179&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 199&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 93&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        184&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 19&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 95&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 44&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 40&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 91&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 135&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 207&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 72&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 105&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 99&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 217&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 231&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 167&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 98&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 66&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 15&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 121&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 183&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 134&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 103&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 196&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 161&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 76&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        117&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 188&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 160&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 178&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 41&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 63&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 253&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 98&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 127&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 97&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 67&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 66&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 175&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 212&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 255&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 232&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 212&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 49&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 154&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 253&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 229&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 120&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 25&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 195&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        157&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 167&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 14&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 203&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 124&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 241&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 195&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 102&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 98&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 45&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 123&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 75&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 181&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 38&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 240&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 116&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 19&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 47&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 14&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 200&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 210&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 153&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 60&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        194&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 102&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 179&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 76&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 65&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 224&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 161&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 248&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 169&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 152&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 208&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 222&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 177&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 167&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 43&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 19&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 130&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 168&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 105&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 173&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 44&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 97&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 84&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        13&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 191&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 57&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 214&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 26&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 41&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 205&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 106&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 74&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 58&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 194&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 114&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 107&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 110&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 175&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 90&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 183&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 185&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 21&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 126&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 197&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        127&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 205&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 114&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 220&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 254&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 60&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 27&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 170&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 191&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 139&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 219&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 136&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 73&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; PDU security trailer header&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_trailer_header&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; PDU security trailer auth value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_trailer_auth_value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 255&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 28&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 127&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 68&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 205&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 187&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 173&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 74&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 166&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 160&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 153&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 40&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 89&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 22&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 35&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 47&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 177&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        219&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 87&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 47&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 250&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 226&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 224&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 221&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 190&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 242&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 117&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 26&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 246&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 227&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 66&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 83&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 51&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 25&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 251&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 201&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 147&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 221&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 150&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 156&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        38&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 106&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 201&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 152&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 57&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 242&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 145&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 76&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 83&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 52&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 239&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 115&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 245&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 174&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 74&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 173&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 95&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 157&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 251&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 98&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 108&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 134&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 71&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;        SecBuffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;DATA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; READONLY_WITH_CHECKSUM_FLAG&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; header&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;        SecBuffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;DATA&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; enc_data&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;        SecBuffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;DATA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; READONLY_WITH_CHECKSUM_FLAG&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_trailer_header&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;        SecBuffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;TOKEN&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sec_trailer_auth_value&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    kerberos_server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;decrypt_message&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Plaintext: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All these buffers were extracted from the RPC Request PDU, which you already saw at the start of this article. And yes, I already expect the question from you:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Wait! Wait! Wait! Where the hell did you get the correct (I suppose correct) session key?&lt;&#x2F;em&gt; 🤨&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;😅 I know the user&#x27;s password, so I can decrypt the previous Kerberos messages and extract the session key 🤭 🤫. Maybe I&#x27;ll write an article about it someday. Ping me if you need to know how to do it 🙃.&lt;&#x2F;p&gt;
&lt;p&gt;Enough talking. Let&#x27;s run this test. We&#x27;ve been waiting for this for so long.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;rpc-encryption-sspi-kerberos&#x2F;.&#x2F;decrypt_rpc_request_test.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Yeeeeeey. We have successfully decrypted the RPC request! It proves that the implementation is correct! The plaintext buffer on the screenshot is decrypted &lt;code&gt;GetKey&lt;&#x2F;code&gt; RPC request.&lt;&#x2F;p&gt;
&lt;p&gt;Hope you find this article informative and useful. Cheers! 😉&lt;&#x2F;p&gt;
&lt;h1 id=&quot;unaddressed-topics&quot;&gt;Unaddressed topics&lt;&#x2F;h1&gt;
&lt;p&gt;If you want to get any of the following topics explained, feel free to contact me.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;NTLM RPC encryption. But if you are really interested, you can read how it is implemented in &lt;code&gt;sspi-rs&lt;&#x2F;code&gt;: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;193f92a0fd73e43d672e3f9ac5775c894c02b200&#x2F;src&#x2F;ntlm&#x2F;mod.rs#L419-L455&quot;&gt;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;193f92a0fd73e43d672e3f9ac5775c894c02b200&#x2F;src&#x2F;ntlm&#x2F;mod.rs#L419-L455&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Kerberos auth process. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-kile&#x2F;190ab8de-dc42-49cf-bf1b-ea5705b7a087&quot;&gt;Three-Leg DCE-Style Mutual Authentication&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;How I decrypted Kerberos traffic and extracted the session key.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;doc-references-code&quot;&gt;Doc, references, code&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;Code: RPC decryptor &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;feat&#x2F;rpc-kerberos-encryption&#x2F;rpc-decryptor&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;rpc-decryptor&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.bloggingforlogging.com&#x2F;2023&#x2F;04&#x2F;28&#x2F;rpc-encryption-an-exercise-in-frustration&#x2F;&quot;&gt;RPC Encryption - An Exercise in Frustration&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-kile&#x2F;e94b3acd-8415-4d0d-9786-749d0c39d550&quot;&gt;[MS-KILE]: Kerberos Binding of &lt;code&gt;GSS_WrapEx()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.rfc-editor.org&#x2F;rfc&#x2F;rfc4121.html&quot;&gt;RPC 4121: The Kerberos Version 5 GSS-API&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;encryptmessage--kerberos&quot;&gt;&lt;code&gt;EncryptMessage&lt;&#x2F;code&gt; (Kerberos) function&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;ns-sspi-secbuffer&quot;&gt;SecBuffer structure (&lt;code&gt;sspi.h&lt;&#x2F;code&gt;)&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;openspecs&#x2F;windows_protocols&#x2F;ms-rpce&#x2F;290c38b1-92fe-4229-91e6-4fc376610c15&quot;&gt;[MS-RPCE]&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Tauri error handling recipes</title>
        <published>2024-12-26T00:00:00+00:00</published>
        <updated>2024-12-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/tauri-error-handling/"/>
        <id>https://tbt.qkation.com/posts/tauri-error-handling/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/tauri-error-handling/">&lt;h1 id=&quot;intro&quot;&gt;Intro&lt;&#x2F;h1&gt;
&lt;p&gt;I&#x27;m developing the desktop app to meet my own needs: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&quot;&gt;Dataans&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Take notes in the form of markdown snippets grouped into spaces.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tauri.app&#x2F;&quot;&gt;Tauri&lt;&#x2F;a&gt; as the main framework and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;leptos.dev&#x2F;&quot;&gt;Leptos&lt;&#x2F;a&gt; as the frontend. I am satisfied with the developing experience and the result I got.&lt;&#x2F;p&gt;
&lt;p&gt;During the initial implementation (PoC phase), I didn&#x27;t implement any error handling and called &lt;code&gt;.unwrap()&lt;&#x2F;code&gt; every time. However, after the first release, I needed to add proper error handling and make the app more fault-tolerant. The refactoring process wasn&#x27;t easy and I spent more time than expected. I learned some important lessons and decided to write this article to summarize my knowledge.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Disclaimer&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;: I have experience using &lt;code&gt;Tauri&lt;&#x2F;code&gt; only with &lt;code&gt;Leptos&lt;&#x2F;code&gt; and other Rust-based frontend frameworks. Error handling approaches may be different when using JS-based frontend frameworks.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;set-up&quot;&gt;Set up&lt;&#x2F;h1&gt;
&lt;p&gt;I set up a simple project (basically it is a &lt;code&gt;cargo create-tauri-app&lt;&#x2F;code&gt; with minimal changes) to demonstrate the approach and the progress: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;265f39bfde2aa9fb10055bfee5031714498f7b28&#x2F;tauri-error-handling&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;265f39bfde2aa9fb10055bfee5031714498f7b28&#x2F;tauri-error-handling&lt;&#x2F;a&gt;. I left a corresponding commit link for each section in this article. So, you can follow this process and even reproduce it with me.&lt;&#x2F;p&gt;
&lt;p&gt;So, what do we have? We have one simple Tauri command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Backend: src-tauri&#x2F;src&#x2F;lib.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[tauri&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;command]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; greet&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Hello, {}! You&amp;#39;ve been greeted from Rust!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Frontend: src&#x2F;backend.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; greet&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; to_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;GreetArgs&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt; })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    invoke&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;greet&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; args&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.await.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;as_string&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;let-s-handle-the-error&quot;&gt;Let&#x27;s handle the error&lt;&#x2F;h1&gt;
&lt;p&gt;Usually, most of the commands may fail. We may want to return a &lt;code&gt;Result&lt;&#x2F;code&gt; and handle the error on the frontend side. Let&#x27;s try it. Suppose we need to validate the name. I came up with the following implementation (let&#x27;s keep it simple):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; thiserror&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[error(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;invalid name: {0}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    InvalidName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; validate_name&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;InvalidName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Tbt&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;()))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[tauri&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;command]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; greet&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    validate_name&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Hello, {}! You&amp;#39;ve been greeted from Rust!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unfortunately, now we have a compilation error:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;error[E0599]: the method `blocking_kind` exists for reference `&amp;amp;Result&amp;lt;String, Error&amp;gt;`, but its trait bounds were not satisfied&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   --&amp;gt; src-tauri&#x2F;src&#x2F;lib.rs:14:1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5   | enum Error {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    | ---------- doesn&amp;#39;t satisfy `Error: Into&amp;lt;InvokeError&amp;gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;14  | #[tauri::command]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    | ^^^^^^^^^^^^^^^^^ method cannot be called on `&amp;amp;Result&amp;lt;String, Error&amp;gt;` due to unsatisfied trait bounds&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;25  |         .invoke_handler(tauri::generate_handler![greet])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                         ------------------------------- in this macro invocation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ::: &#x2F;home&#x2F;pavlo-myroniuk&#x2F;.rustup&#x2F;toolchains&#x2F;stable-x86_64-unknown-linux-gnu&#x2F;lib&#x2F;rustlib&#x2F;src&#x2F;rust&#x2F;library&#x2F;core&#x2F;src&#x2F;result.rs:527:1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;527 | pub enum Result&amp;lt;T, E&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    | --------------------- doesn&amp;#39;t satisfy `Result&amp;lt;std::string::String, Error&amp;gt;: IpcResponse` or `_: ResultKind`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    = note: the following trait bounds were not satisfied:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            `Error: Into&amp;lt;InvokeError&amp;gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            which is required by `Result&amp;lt;std::string::String, Error&amp;gt;: tauri::ipc::private::ResultKind`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            `Result&amp;lt;std::string::String, Error&amp;gt;: IpcResponse`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            which is required by `&amp;amp;Result&amp;lt;std::string::String, Error&amp;gt;: tauri::ipc::private::ResponseKind`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;🤔. Our &lt;code&gt;Result&amp;lt;String, Error&amp;gt;&lt;&#x2F;code&gt; type must implement the &lt;code&gt;IpcResponse&lt;&#x2F;code&gt; trait. Implementing &lt;code&gt;serde::Serialize&lt;&#x2F;code&gt; should be enough (because of the &lt;code&gt;impl&amp;lt;T: Serialize&amp;gt; IpcResponse for T&lt;&#x2F;code&gt; trait bound. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tauri&#x2F;latest&#x2F;tauri&#x2F;ipc&#x2F;trait.IpcResponse.html#impl-IpcResponse-for-T&quot;&gt;docs&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Deserialize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Serialize&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[error(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;invalid name: {0}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    InvalidName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Great. Compilation successful. Alternatively, you can read another explanation and example: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;jonaskruckenberg.github.io&#x2F;tauri-docs-wip&#x2F;development&#x2F;inter-process-communication.html#error-handling&quot;&gt;The Tauri Documentation WIP&#x2F;Inter-Process Communication#error-handling&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Lesson 1&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;. &lt;em&gt;All &lt;code&gt;Error&lt;&#x2F;code&gt;s must implement the &lt;code&gt;serde::Serialize&lt;&#x2F;code&gt; trait&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;What about frontend? How are we going to handle the error? Let&#x27;s start with the simplest solution:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Move the &lt;code&gt;Error&lt;&#x2F;code&gt; type to a separate &lt;code&gt;common&lt;&#x2F;code&gt; crate which can be used by frontend and backend.&lt;&#x2F;li&gt;
&lt;li&gt;Expect &lt;code&gt;JsValue&lt;&#x2F;code&gt; to be parsed into &lt;code&gt;Result&amp;lt;String, Error&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; greet&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; to_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;GreetArgs&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt; })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;GreetArgs to JsValue should not fail&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; js_value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; invoke&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;greet&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; args&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.await&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    from_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;js_value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;JsValue to Result should not fail&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Oops, we have a problem in runtime:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;tauri-error-handling&#x2F;.&#x2F;err-exception.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;But why 😭? According to the documentation (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;v2.tauri.app&#x2F;develop&#x2F;calling-rust&#x2F;#error-handling&quot;&gt;v2.tauri.app&#x2F;calling-rust&#x2F;#error-handling&lt;&#x2F;a&gt;), Tauri command error will be an exception on frontend 😕. So, we should not expect the &lt;code&gt;Result&amp;lt;String, Error&amp;gt;&lt;&#x2F;code&gt;, but handle a JS exception instead.&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately, we can ask &lt;code&gt;wasm_bindgen&lt;&#x2F;code&gt; to handle this exception. Tauri docs say nothing about it, but if we open the wasm-bindgen documentation instead, we will find this treasure (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rustwasm.github.io&#x2F;wasm-bindgen&#x2F;reference&#x2F;attributes&#x2F;on-js-imports&#x2F;catch.html&quot;&gt;wasm-bindgen&#x2F;attributes&#x2F;on-js-imports&#x2F;catch&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;catch&lt;&#x2F;code&gt; attribute allows catching a JavaScript exception. This can be attached to any imported function or method, and the function must return a &lt;code&gt;Result&lt;&#x2F;code&gt; where the &lt;code&gt;Err&lt;&#x2F;code&gt; payload is a &lt;code&gt;JsValue&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;😲. Let&#x27;s use it. Now I&#x27;m going to change the binding generated by &lt;code&gt;cargo create-tauri-app&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[wasm_bindgen]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;C&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[wasm_bindgen(js_namespace &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;window&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;__TAURI__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;core&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; catch&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; invoke&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; JsValue&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;JsValue&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; JsValue&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And now we can handle the exception as an error:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; greet&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; to_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;GreetArgs&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt; })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;GreetArgs to JsValue should not fail&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; invoke&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;greet&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; args&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.await&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;()),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;        Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;()),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And finally, it works 🎉. Here is the resulting code: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;9f6437fe7799e87439430e483c92c0ed590b12f3&#x2F;tauri-error-handling&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;9f6437fe7799e87439430e483c92c0ed590b12f3&#x2F;tauri-error-handling&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Lesson 2&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;. &lt;em&gt;Tauri command error is an exception on frontend. The exception can be caught by using the &lt;code&gt;catch&lt;&#x2F;code&gt; attribute of the &lt;code&gt;#[wasm_bindgen]&lt;&#x2F;code&gt; macro.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;bonus-unexpected-none&quot;&gt;Bonus: unexpected None&lt;&#x2F;h1&gt;
&lt;p&gt;As you can see from the &lt;code&gt;invoke&lt;&#x2F;code&gt; function declaration, command input&#x2F;output values are serialized into&#x2F;deserialized from JsValue using the &lt;code&gt;serde_wasm_bindgen&lt;&#x2F;code&gt; crate. But we are also aware that the JS type-system and Rust type-system are different. Thus, not all Rust objects can be represented in a JS type-system. Theoretically, we can find a Rust object, that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;obj&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; serde_wasm_bindgen&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;serde_wasm_bindgen&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;to_value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;obj&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I mean, objects before and after the serialization + deserialization process are not the same. It was theoretical until yesterday when I faced it in practice 🤪. Suppose we have the following Tauri command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[tauri&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;command]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; greet&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;()&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; do the work here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Some&lt;&#x2F;span&gt;&lt;span&gt;(())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And the corresponding code on frontend side:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub async fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; greet&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;()&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; to_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;GreetArgs&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt; })&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;GreetArgs to JsValue should not fail&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; js_value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; invoke&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;greet&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; args&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.await.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;should not fail&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;()&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; from_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;js_value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;deserialization should not fail&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    info!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Result: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; result&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s try it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;tauri-error-handling&#x2F;.&#x2F;none-value.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Oppps 😯. We have &lt;code&gt;None&lt;&#x2F;code&gt; instead of &lt;code&gt;Some(())&lt;&#x2F;code&gt;. &lt;code&gt;Some(())&lt;&#x2F;code&gt; is serialized in &lt;code&gt;undefined&lt;&#x2F;code&gt; and &lt;code&gt;undefined&lt;&#x2F;code&gt; is deserialized in &lt;code&gt;None&lt;&#x2F;code&gt;. You should be very careful with &lt;code&gt;()&lt;&#x2F;code&gt; and &lt;code&gt;enum&lt;&#x2F;code&gt;s. You can reproduce it by yourself: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;4a4f62d1d55687cc02538408ceb9eb6fee93187f&#x2F;tauri-error-handling&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;4a4f62d1d55687cc02538408ceb9eb6fee93187f&#x2F;tauri-error-handling&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Lesson 3&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;. &lt;em&gt;Objects before and after the serialization + deserialization process may be different. Be careful when using types like &lt;code&gt;()&lt;&#x2F;code&gt;, &lt;code&gt;enum&lt;&#x2F;code&gt;s, etc.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you say that no one uses the &lt;code&gt;Option&amp;lt;()&amp;gt;&lt;&#x2F;code&gt; type, then I will disagree. Try to search for &lt;code&gt;Option&amp;lt;()&amp;gt;&lt;&#x2F;code&gt; on GitHub and you will find many uses of this type: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;search?q=Option%3C%28%29%3E+lang%3ARust+&amp;amp;type=code&quot;&gt;github&#x2F;search?q=Option%3C%28%29%3E+lang%3ARust+&amp;amp;type=code&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;tauri-error-handling&#x2F;.&#x2F;github-search.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;learned-lessons&quot;&gt;Learned lessons&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;All &lt;code&gt;Error&lt;&#x2F;code&gt;s must implement the &lt;code&gt;serde::Serialize&lt;&#x2F;code&gt; trait.&lt;&#x2F;li&gt;
&lt;li&gt;Tauri command error (&lt;code&gt;Result::Err(E)&lt;&#x2F;code&gt;) is an exception on frontend. The exception can be caught by using the &lt;code&gt;catch&lt;&#x2F;code&gt; attribute of the &lt;code&gt;#[wasm_bindgen]&lt;&#x2F;code&gt; macro.&lt;&#x2F;li&gt;
&lt;li&gt;The JS type-system and Rust type-system are different. Objects before and after the serialization + deserialization process may be different.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;Fun fact.&lt;&#x2F;strong&gt; This article looks nothing like the one I planned. I didn&#x27;t know about the &lt;code&gt;catch&lt;&#x2F;code&gt; attribute before writing the article. I discovered it accidentally 🤪. I even wrote my own &lt;code&gt;Result&lt;&#x2F;code&gt; and &lt;code&gt;Unit&lt;&#x2F;code&gt; types to implement proper error handling: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;3f2b97e81cbe8b6c4cd0fffc6d0b44c0a8c4e748&#x2F;dataans&#x2F;common&#x2F;src&#x2F;error.rs&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;3f2b97e81cbe8b6c4cd0fffc6d0b44c0a8c4e748&#x2F;dataans&#x2F;common&#x2F;src&#x2F;error.rs&lt;&#x2F;a&gt; (but now I plan to delete them).&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;gt; refactored error handling in my Tauri project&lt;&#x2F;p&gt;
&lt;p&gt;&amp;gt; it turned out harder than I thought&lt;&#x2F;p&gt;
&lt;p&gt;&amp;gt; decided to write a blog post about error handling in Tauri&lt;&#x2F;p&gt;
&lt;p&gt;&amp;gt; while writing the blog post I found out that I could have done it much easier&lt;&#x2F;p&gt;
&lt;p&gt;&amp;gt; now I am going to refactor the error handling again&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I like this side effect of writing articles. Most likely, you will do some research, investigation, and code examples to better explain your idea. Almost every time I write a blog post I discover something new for me.&lt;&#x2F;p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Writing blog posts is a good way to learn something more deeply 🤩.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;doc-references-code&quot;&gt;Doc, references, code&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;jonaskruckenberg.github.io&#x2F;tauri-docs-wip&#x2F;development&#x2F;inter-process-communication.html#error-handling&quot;&gt;The Tauri Documentation WIP&#x2F;Inter-Process Communication#error-handling&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;v2.tauri.app&#x2F;develop&#x2F;calling-rust&#x2F;#error-handling&quot;&gt;v2.tauri.app&#x2F;calling-rust&#x2F;#error-handling&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rustwasm.github.io&#x2F;wasm-bindgen&#x2F;reference&#x2F;attributes&#x2F;on-js-imports&#x2F;catch.html&quot;&gt;wasm-bindgen&#x2F;attributes&#x2F;on-js-imports&#x2F;catch&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Announcing Dataans v.0.1.0</title>
        <published>2024-10-19T00:00:00+00:00</published>
        <updated>2024-10-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/announcing-dataans/"/>
        <id>https://tbt.qkation.com/posts/announcing-dataans/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/announcing-dataans/">&lt;h1 id=&quot;intro&quot;&gt;Intro&lt;&#x2F;h1&gt;
&lt;p&gt;Around half a year ago, I started my new side project: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&quot;&gt;&lt;code&gt;Dataans&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. It already has plenty of good features and I think I&#x27;m ready to present it to you.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d say that it&#x27;s not ready and missing a lot of functionality, but I remembered the following quote (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dev.jimgrey.net&#x2F;2024&#x2F;07&#x2F;03&#x2F;lessons-learned-in-35-years-of-making-software&#x2F;&quot;&gt;Lessons learned in 35 years of making software&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;When you deliver work you’re really proud of, you’ve almost certainly done too much and taken too long.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I&#x27;ve been thinking about it for a while and decided to finally publish a first release. Otherwise, it might never happen. I always have something in mind to implement&#x2F;fix&#x2F;improve. It is an infinite process.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;dataans&quot;&gt;Dataans&lt;&#x2F;h1&gt;
&lt;p&gt;The Dataans is a desktop app that allows you to take notes in the form of markdown snippets grouped into spaces. Yes, it&#x27;s another note-taking app, but it has unique features that I miss in all other note-taking apps.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;&#x2F;h2&gt;
&lt;p&gt;I already have &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;projects&#x2F;dataans&#x2F;&quot;&gt;a post&lt;&#x2F;a&gt; about the motivation and features I lack in other existing note-taking apps. Please, read the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;projects&#x2F;dataans&#x2F;#motivation&quot;&gt;Motivation&lt;&#x2F;a&gt; section of the article to understand why I decided to write my own app.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;announcing-dataans&#x2F;.&#x2F;md-note.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Quake (drop-down) mode. The keybinding can be configured.&lt;&#x2F;li&gt;
&lt;li&gt;Cross-platform.&lt;&#x2F;li&gt;
&lt;li&gt;All notes are markdown snippets grouped into spaces. The following MD features are supported:
&lt;ul&gt;
&lt;li&gt;Italic, bold, strike-through text.&lt;&#x2F;li&gt;
&lt;li&gt;Quotes.&lt;&#x2F;li&gt;
&lt;li&gt;Links.&lt;&#x2F;li&gt;
&lt;li&gt;Headers.&lt;&#x2F;li&gt;
&lt;li&gt;Tables.&lt;&#x2F;li&gt;
&lt;li&gt;In-line code and code blocks.&lt;&#x2F;li&gt;
&lt;li&gt;Pasting images from clipboard.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Files can be attached to the note.&lt;&#x2F;li&gt;
&lt;li&gt;Common keybindings for text editing (like &lt;code&gt;ctrl+k&lt;&#x2F;code&gt; for creating links).&lt;&#x2F;li&gt;
&lt;li&gt;The app can be configured using the config file. Color scheme also can be configured.&lt;&#x2F;li&gt;
&lt;li&gt;Simple note search.&lt;&#x2F;li&gt;
&lt;li&gt;Many different keybindings to control the application.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Read more detailed in the project Wiki: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;wiki&quot;&gt;Dataans: Wiki&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-try-it&quot;&gt;How to try it&lt;&#x2F;h2&gt;
&lt;p&gt;Follow this instructions: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;main&#x2F;dataans&#x2F;README.md&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;dataans&#x2F;README.md&lt;&#x2F;a&gt; 😜 🤪&lt;&#x2F;p&gt;
&lt;h1 id=&quot;references-final-note&quot;&gt;References &amp;amp; final note&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;&quot;&gt;Dataans: Source code&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;main&#x2F;doc&#x2F;CONTRIBUTING.md&quot;&gt;Dataans: Contributing guide&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;main&#x2F;doc&#x2F;tech_stack.md&quot;&gt;Dataans: Technical decisions explained&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;wiki&quot;&gt;Dataans: Wiki&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dev.jimgrey.net&#x2F;2024&#x2F;07&#x2F;03&#x2F;lessons-learned-in-35-years-of-making-software&#x2F;&quot;&gt;Lessons learned in 35 years of making software&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I want to add one thing: &lt;strong&gt;write programs for yourself in your favorite languages&lt;&#x2F;strong&gt;. I&#x27;m feeling happy every time I use my app for my needs. Even if your future app will do only one task, then still create it. &lt;em&gt;No better software than software that does useful work.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>dataans</title>
        <published>2024-10-19T00:00:00+00:00</published>
        <updated>2024-10-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/projects/dataans/"/>
        <id>https://tbt.qkation.com/projects/dataans/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/projects/dataans/">&lt;p&gt;Source code: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;&quot;&gt;github&#x2F;TheBestTvarynka&#x2F;Dataans&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The Dataans is a desktop app that allows you to take notes in the form of markdown snippets grouped into spaces. Yes, it&#x27;s another note-taking app, but it has unique features that I miss in all other note-taking apps.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;motivation&quot;&gt;Motivation&lt;&#x2F;h1&gt;
&lt;p&gt;I write notes almost every time I use my computer. Usually, it&#x27;s small pieces of data&#x2F;code&#x2F;docs&#x2F;links I found during the research or bug fixing. So, I need some place to store them and the ability to find needed pieces of information easily. I used to use a single text file and open it in &lt;code&gt;Notepad&lt;&#x2F;code&gt; or &lt;code&gt;VS Code&lt;&#x2F;code&gt;. After the research, I got the file with almost random symbols:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;projects&#x2F;dataans&#x2F;.&#x2F;notes-example.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Do I need to explain that it is inconvenient and hard to find anything? I needed a better solution. I tried other note-taking apps, but every one of them had flaws I didn&#x27;t like a lot.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-wrong-with-existing-note-taking-apps&quot;&gt;What&#x27;s wrong with existing note-taking apps?&lt;&#x2F;h2&gt;
&lt;p&gt;I relate a lot to this blog post (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;monoline.io&#x2F;posts&#x2F;2021&#x2F;11&#x2F;11&#x2F;why-build-a-messenger-app-only-for-sending-to-yourself&#x2F;&quot;&gt;Why build a messenger app only for sending to yourself?&lt;&#x2F;a&gt;). I quote some key points from it but explain them in my own way and how they relate to me.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Too many options&lt;&#x2F;strong&gt;. I don&#x27;t need so much test editing functionality. I just want to take notes and have simple markup (styling) functionality. Something like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.markdownguide.org&#x2F;&quot;&gt;markdown&lt;&#x2F;a&gt; or &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.asciidoctor.org&#x2F;&quot;&gt;asciidoc&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Unwanted features&lt;&#x2F;strong&gt;. This echoes the previous point, but I want to draw your attention specifically to the &lt;em&gt;UNWANTED&lt;&#x2F;em&gt; features. For example, I don&#x27;t need AI to search for info in my notes. I only need a typical search engine. I don&#x27;t want AI to write notes for me. I can write down my thoughts by myself.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Article-oriented mindset&lt;&#x2F;strong&gt;. People don&#x27;t think in articles. Many note-taking apps look like you are going to write an article instead of just writing down the idea, thought, or a random piece of data. When I see a blank screen with the cursor, I feel I need to write a document with a defined structure, style, and line of thought. It throws off the thoughts I wanted to write at the beginning.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;missing-features&quot;&gt;Missing features&lt;&#x2F;h2&gt;
&lt;p&gt;Despite the listed flaws above, I also have missing features I would like to have in my note-taking app. Some of them may feel weird and illogical to you, but I know what I want 😝.&lt;&#x2F;p&gt;
&lt;p&gt;All note-taking apps I tried lack one or more features listed below. No one contains all of them at once (but if you find such an app, please, tell me about it).&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Desktop app&lt;&#x2F;strong&gt;. Yes, you heard it right. In the era of the web, I want a desktop app. Usually, the browser has dozens of opened tabs across multiple windows. It becomes hard to find the tab with notes (even when it&#x27;s pinned).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Quake (drop-down) mode&lt;&#x2F;strong&gt;. I have used the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Guake&#x2F;guake&#x2F;&quot;&gt;Quake&lt;&#x2F;a&gt; terminal since 2019. I like it a lot and the most pleasant feature is a drop-down mode. I set a keybinding to the &lt;code&gt;F1&lt;&#x2F;code&gt; key and always have my terminal with me. I would like to have the same ability for my note-taking app because I use it often.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Cross platform&lt;&#x2F;strong&gt;. It should behave the same on &lt;em&gt;Windows&lt;&#x2F;em&gt; and &lt;em&gt;Linux&lt;&#x2F;em&gt;. Other platforms may may be supported too, but it&#x27;s not a requirement for me.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Markdown&lt;&#x2F;strong&gt;. It is simple, easy to learn, and looks good. It contains a perfect set of styling and markup functionality for me.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Grouping&lt;&#x2F;strong&gt; into channels&#x2F;spaces&#x2F;folders&#x2F;or anything like that.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;solution&quot;&gt;Solution&lt;&#x2F;h1&gt;
&lt;p&gt;These are the two closest apps to what I want:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;telegram.org&#x2F;&quot;&gt;Telegram&lt;&#x2F;a&gt;. I have plenty of Telegram channels with one subscriber (me) where I save important, useful, and just interesting information. Despite rich Telegram features, I think you can understand why it isn&#x27;t a solution.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;monoline.io&#x2F;&quot;&gt;Monoline&lt;&#x2F;a&gt;. It supports MD and has pretty UI, but I would like to organize my notes into groups (like messages are organized in channels in Telegram).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I decided to write my note-taking app after many tries and thoughts. The best part of being a programmer is the ability to do everything I want with the software. It&#x27;s like a limitless power in the virtual world (unfortunately, &lt;em&gt;everything has a limit&lt;&#x2F;em&gt;, but we aren&#x27;t about that).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tech-stack&quot;&gt;Tech stack&lt;&#x2F;h2&gt;
&lt;p&gt;We can debate a lot about the best technologies for such a project, but I already made my decision:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Main programming language: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;&quot;&gt;&lt;code&gt;Rust&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;App framework: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;v2.tauri.app&#x2F;&quot;&gt;&lt;code&gt;Tauri&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Frontend framework: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;leptos.dev&#x2F;&quot;&gt;&lt;code&gt;Leptos&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I wrote a comprehensive explanation of the chosen tech stack. You can read it here: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;main&#x2F;doc&#x2F;tech_stack.md&quot;&gt;&lt;code&gt;tech_stack.md&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;projects&#x2F;dataans&#x2F;.&#x2F;md-note.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Quake (drop-down) mode. The keybinding can be configured.&lt;&#x2F;li&gt;
&lt;li&gt;Cross-platform.&lt;&#x2F;li&gt;
&lt;li&gt;All notes are markdown text. The following MD features are supported:
&lt;ul&gt;
&lt;li&gt;Italic, bold, strike-through text.&lt;&#x2F;li&gt;
&lt;li&gt;Quotes.&lt;&#x2F;li&gt;
&lt;li&gt;Links.&lt;&#x2F;li&gt;
&lt;li&gt;Headers.&lt;&#x2F;li&gt;
&lt;li&gt;Tables.&lt;&#x2F;li&gt;
&lt;li&gt;In-line code and code blocks.&lt;&#x2F;li&gt;
&lt;li&gt;Pasting images from clipboard.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Files can be attached to the note.&lt;&#x2F;li&gt;
&lt;li&gt;All notes are grouped into spaces. So, space is a collection of notes. It has a name and avatar picture.&lt;&#x2F;li&gt;
&lt;li&gt;Common keybindings for text editing (like &lt;code&gt;ctrl+k&lt;&#x2F;code&gt; for creating links).&lt;&#x2F;li&gt;
&lt;li&gt;The app can be configured using the config file.&lt;&#x2F;li&gt;
&lt;li&gt;Color scheme also can be configured.&lt;&#x2F;li&gt;
&lt;li&gt;Simple note search.&lt;&#x2F;li&gt;
&lt;li&gt;Many different keybindings to control the application.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;...And more. This is a short list of main futures. The full features list and user manual can be found here: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;wiki&#x2F;User-manual&quot;&gt;Dataans&#x2F;wiki&#x2F;User-manual&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;moving-further&quot;&gt;Moving further&lt;&#x2F;h1&gt;
&lt;p&gt;I&#x27;m going to continue to improve &lt;code&gt;Dataans&lt;&#x2F;code&gt; according to my needs. If someone wants some missing functionality, then create an &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;issues&#x2F;new&quot;&gt;issue&lt;&#x2F;a&gt; or a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;discussions&quot;&gt;discussion&lt;&#x2F;a&gt;, and most likely I&#x27;ll implement it. Or if you are interested in contributing to this project, then read the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;main&#x2F;doc&#x2F;CONTRIBUTING.md&quot;&gt;&lt;code&gt;CONTRIBUTING.md&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; document.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;references-final-note&quot;&gt;References &amp;amp; final note&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;&quot;&gt;Dataans: Source code&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;main&#x2F;doc&#x2F;CONTRIBUTING.md&quot;&gt;Dataans: Contributing guide&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;blob&#x2F;main&#x2F;doc&#x2F;tech_stack.md&quot;&gt;Dataans: Technical decisions explained&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;Dataans&#x2F;wiki&quot;&gt;Dataans: Wiki&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;monoline.io&#x2F;posts&#x2F;2021&#x2F;11&#x2F;11&#x2F;why-build-a-messenger-app-only-for-sending-to-yourself&#x2F;&quot;&gt;Why build a messenger app only for sending to yourself?&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I want to add only one thing: &lt;strong&gt;write programs for yourself in your favorite languages&lt;&#x2F;strong&gt;. I&#x27;m feeling happy every time I use my app for my needs. Even if your app will do only one task, then still create it. &lt;em&gt;No better software than software that does useful work.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>crypto-helper</title>
        <published>2024-08-24T00:00:00+00:00</published>
        <updated>2024-08-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/projects/crypto-helper/"/>
        <id>https://tbt.qkation.com/projects/crypto-helper/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/projects/crypto-helper/">&lt;p&gt;Visit this tool at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crypto.qkation.com&quot;&gt;crypto.qkation.com&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The crypto-helper is an online app that helps to work with the different crypto algorithms. This app can hash&#x2F;hmac, encrypt&#x2F;decrypt, and sign&#x2F;verify the data, debug JWT tokens, parse ASN1 structures, compute diffs, and more. All computations are performed on the client side. &lt;em&gt;This tool never sends the data the any servers.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;crypto-helper&quot;&gt;Crypto helper&lt;&#x2F;h3&gt;
&lt;p&gt;During my work, I often need to work with bytes sequences that I need to encrypt or decrypt, hash or verify. For example, I might intercept the traffic, extract encrypted Kerberos cipher data, and try to decrypt it using the user&#x27;s password. Or take payload + signature from the message and try to recalculate it. Such small tasks are very annoying and I decided to optimize this proccess.&lt;&#x2F;p&gt;
&lt;p&gt;Basically, it just takes the input bytes in some format and applies the selected algorithm to it.&lt;&#x2F;p&gt;
 &lt;img src=&quot;crypto-helper-demo-krb.png&quot; alt=&quot;crypto helper krb encryption demo&quot; width=&quot;1920&quot; height=&quot;953&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;p&gt;The list of supported algorithms:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Argon2&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;BCrypt&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;MD5&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;SHA1&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;SHA256&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;SHA384&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;SHA512&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Kerberos ciphers: &lt;code&gt;AES128-CTS-HMAC-SHA1-96&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;AES256-CTS-HMAC-SHA1-96&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Kerberos HMAC: &lt;code&gt;HMAC-SHA1-96-AES128&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;HMAC-SHA1-96-AES256&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;RSA&lt;&#x2F;li&gt;
&lt;li&gt;Compression: &lt;code&gt;ZLIB&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;jwt-debugger&quot;&gt;JWT debugger&lt;&#x2F;h3&gt;
&lt;p&gt;Another interesting feature is the JWT debugger. I had some time working with Azure AD authorization and its JWT tokens. Why did I decide to implement my own if &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;jwt.io&quot;&gt;jwt.io&lt;&#x2F;a&gt; already exists? The answer is pretty obvious: the existing one is very inconvenient.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I really don&#x27;t like its big header. AzureAD tokens are pretty big. Such a massive header is just a waste of space.&lt;&#x2F;li&gt;
&lt;li&gt;Problems with scrolling. Did you ever try to scroll the header or payload section that contains more than five fields? If not then try.&lt;&#x2F;li&gt;
&lt;li&gt;Header and payload fields are not resizable.&lt;&#x2F;li&gt;
&lt;li&gt;Every header&#x2F;payload&#x2F;key change immediately overwrites the original JWT token. I often want to see the original one, compare it to a new one, or create a few different tokens based on the initial token.&lt;&#x2F;li&gt;
&lt;li&gt;Ads. Ads. Ads.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here is my JWT debugger in action:&lt;&#x2F;p&gt;
 &lt;img src=&quot;jwt-demo.png&quot; alt=&quot;JWT demo&quot; width=&quot;1920&quot; height=&quot;1080&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;p&gt;Supported signature algorithms:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;none&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;HS256&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;HS384&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;HS512&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;RS256&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;RS384&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;RS512&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ES256&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ES384&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ES512&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;asn1-debugger&quot;&gt;ASN1 debugger&lt;&#x2F;h3&gt;
&lt;p&gt;Did you hear anything about &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;luca.ntop.org&#x2F;Teaching&#x2F;Appunti&#x2F;asn1.html&quot;&gt;ASN1 der&lt;&#x2F;a&gt;? If not, then this tool is not for you 😅 If yes and you work with asn1 structures encoding&#x2F;decoding a lot, then you are at the right place 😉.&lt;&#x2F;p&gt;
&lt;p&gt;The purpose of this tool is to parse input bytes as the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;luca.ntop.org&#x2F;Teaching&#x2F;Appunti&#x2F;asn1.html&quot;&gt;asn1 der&lt;&#x2F;a&gt; structure and render the structural representation of it alongside the hex view of its fields and data. A list of supported asn1 types can be found &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;tree&#x2F;main&#x2F;crates&#x2F;asn1-parser#supported-asn1-types&quot;&gt;here&lt;&#x2F;a&gt;. Long story short, here is a demo:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;projects&#x2F;crypto-helper&#x2F;.&#x2F;asn1-demo.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I think you got it. Basically, it&#x27;s a reimplementation of &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lapo.it&#x2F;asn1js&quot;&gt;lapo.it&#x2F;asn1js&lt;&#x2F;a&gt; but with my features and my design. There are some of them:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Ability to copy asn1 node or node inner value.&lt;&#x2F;li&gt;
&lt;li&gt;Decode on &lt;code&gt;ctrl + enter&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Different hex view. I compare parsed structure with its hex representation very often, so I need more explicit and highlighted bytes rendering.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;To implement it, the custom asn1 parser crate has been written: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;tree&#x2F;main&#x2F;crates&#x2F;asn1-parser&quot;&gt;asn1-parser&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Yet another &lt;code&gt;asn1&lt;&#x2F;code&gt; parser? (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;users.rust-lang.org&#x2F;t&#x2F;comparison-of-way-too-many-rust-asn-1-der-libraries&quot;&gt;https:&#x2F;&#x2F;users.rust-lang.org&#x2F;t&#x2F;comparison-of-way-too-many-rust-asn-1-der-libraries&lt;&#x2F;a&gt;)&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;i.imgflip.com&#x2F;8789zm.jpg&quot; alt=&quot;well yes, but actually no&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It parses the asn1 types and remembers their position in the input data stream. It is a useful feature for pretty rendering.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;diff-checker&quot;&gt;Diff checker&lt;&#x2F;h3&gt;
&lt;p&gt;The purpose of the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crypto.qkation.com&#x2F;diff&quot;&gt;diff-checker&lt;&#x2F;a&gt; is to just show the diff using selected diff algorithms. It lacks many modern diff-tool features. Most likely it will never have them implemented. The purpose of this tool is only to cover a few specific edge cases.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;projects&#x2F;crypto-helper&#x2F;.&#x2F;diff-demo.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I use it from time to time for raw data diff computation using different diff algorithms. Most likely you will never need this feature but at least it is needed by me and doesn&#x27;t contain any ads.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-journey&quot;&gt;The journey&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Written in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&quot;&gt;Rust&lt;&#x2F;a&gt; 🦀 using &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yewstack&#x2F;yew&quot;&gt;yew&lt;&#x2F;a&gt; ✨&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It&#x27;s a fun story because I rewrote this tool two times. Firstly, I planned to make it very simple and started implementing using plain &lt;code&gt;html&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;css&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;js&lt;&#x2F;code&gt;. Then I realized that it&#x27;s hard to improve, and maintain, and can cause a lot of stupid bugs. The second choice was &lt;code&gt;React&lt;&#x2F;code&gt;. In the middle of the rewriting, I thought: why do not write it in &lt;code&gt;Rust&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;After some research, I decided to use the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yewstack&#x2F;yew&quot;&gt;Yew&lt;&#x2F;a&gt; framework. Basically, it&#x27;s like &lt;code&gt;React&lt;&#x2F;code&gt; but for &lt;code&gt;Rust&lt;&#x2F;code&gt;. From my experience, I can tell that &lt;em&gt;yew&lt;&#x2F;em&gt; is a great framework to write web applications (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Single-page_application&quot;&gt;SPA&lt;&#x2F;a&gt;s) in &lt;code&gt;Rust&lt;&#x2F;code&gt;. It works well, has great documentation, and is easy to work with. I have faced only one problem: styling. We don&#x27;t have (so far) such convenient libraries for stlyling as we have for &lt;code&gt;React&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m happy that I wrote this tool. I use it very often and learned a lot during the implementation. I have had to deal with the web frontend in Rust, web assembly, web workers, application designing and implementation, writing custom asn1 parser, deploying, and much more.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;&#x2F;h2&gt;
&lt;p&gt;Just follow &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crypto.qkation.com&#x2F;&quot;&gt;the link&lt;&#x2F;a&gt; and paste your data. As you can see, the interface is pretty intuitive.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;moving-further&quot;&gt;Moving further&lt;&#x2F;h2&gt;
&lt;p&gt;At this point, this tool has the all needed functionality for me. I plan to improve it continuously according to my needs and goals. If you have any feature requests, then create an &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;issues&#x2F;new&quot;&gt;issue&lt;&#x2F;a&gt; with the description. It&#x27;ll be a priority for me.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;doc-references-code&quot;&gt;Doc, references, code&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Visit this tool at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crypto.qkation.com&quot;&gt;crypto.qkation.com&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Source code: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&quot;&gt;TheBestTvarynka&#x2F;crypto-helper&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Writing unsafe Rust code? Please, consider Miri</title>
        <published>2024-06-30T00:00:00+00:00</published>
        <updated>2024-06-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/miri/"/>
        <id>https://tbt.qkation.com/posts/miri/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/miri/">&lt;p&gt;For ones who don&#x27;t know (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&quot;&gt;quote src&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&quot;&gt;Miri&lt;&#x2F;a&gt; is an &lt;strong&gt;interpreter&lt;&#x2F;strong&gt; for Rust&#x27;s mid-level intermediate representation.
Miri is an &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;behavior-considered-undefined.html&quot;&gt;Undefined Behavior&lt;&#x2F;a&gt; detection tool for Rust. It can run binaries and test suites of cargo projects and detect unsafe code that fails to uphold its safety requirements.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;👍&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The description is pretty clear. So, why did you write an entire blog post about it?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I have a few reasons to do it.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Recently I decided to try it on my work project and was excited with the result.&lt;&#x2F;li&gt;
&lt;li&gt;I thought &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&quot;&gt;Miri&lt;&#x2F;a&gt; was complicated in usage&#x2F;configuring like other similar checkers, but it turned out very easy and convenient (like all tools in the Rust ecosystem).&lt;&#x2F;li&gt;
&lt;li&gt;Show you some of the bugs Miri has found in the project.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Convince you to try it&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;getting-started&quot;&gt;Getting started&lt;&#x2F;h1&gt;
&lt;p&gt;First of all, you need to install Miri:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;rustup&lt;&#x2F;span&gt;&lt;span&gt; +nightly component add miri&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Why &lt;em&gt;nightly&lt;&#x2F;em&gt;? The Miri can be run only with the nightly Rust. So, you should be able to compile your project with nightly Rust.
Miri can run project binaries, tests, examples, and so on.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span&gt; +nightly miri run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span&gt; +nightly miri run&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --example&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;example name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span&gt; +nightly miri test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span&gt; +nightly miri test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;test_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --features=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;feature&lt;&#x2F;span&gt;&lt;span&gt; list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;who-should-use-miri&quot;&gt;Who should use Miri&lt;&#x2F;h1&gt;
&lt;p&gt;In my opinion, everyone who writes an &lt;em&gt;unsafe&lt;&#x2F;em&gt; Rust code should use Miri and test their code with this tool. It can be any kind of &lt;em&gt;unsafe&lt;&#x2F;em&gt; code:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;FFI (except fully generated ones).&lt;&#x2F;li&gt;
&lt;li&gt;Unsafe transmutations.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Box::from_raw&#x2F;into_raw&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;slice::from_raw_parts&#x2F;_mut&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Interaction with OS API.&lt;&#x2F;li&gt;
&lt;li&gt;Magic tricks with references and raw pointers.&lt;&#x2F;li&gt;
&lt;li&gt;...and many other cases.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you are writing any unsafe Rust code, you should consider using Miri.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;We have tested our code and it works well in production&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;miri&#x2F;.&#x2F;well_yes_but_actually_no.jpg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can be just lucky. Fortune and the compiler are on your side then. But one day you can change your code a little bit, just reorder some functions and boom 💥. Now you have an unexplainable magic error&#x2F;behavior. This and other arguments are well explained in this talk: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;svR0p6fSUYY&quot;&gt;Unsafe Rust and Miri by Ralf Jung&lt;&#x2F;a&gt;. I highly recommend watching it!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;let-s-find-some-ub&quot;&gt;Let&#x27;s find some UB&lt;&#x2F;h1&gt;
&lt;p&gt;The first run:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;miri&#x2F;.&#x2F;compilation_errors.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Uuups, I can&#x27;t compile the project with nightly Rust. I have warned you about it above. In my case, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;pull&#x2F;255&quot;&gt;updating the &lt;code&gt;Cargo.lock&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is enough. But it&#x27;s just a case and we can be forced to spend more time on it.&lt;&#x2F;p&gt;
&lt;p&gt;The second run was more &lt;em&gt;&quot;successful&quot;&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;miri&#x2F;.&#x2F;miri_ub_slice_from_null.png&quot; alt=&quot;&quot; &#x2F;&gt; &lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;miri&#x2F;.&#x2F;miri_ub_failed_memory_access.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;...and more. But I&#x27;m not showing you this to ask you to fix my code. I want you to pay attention to the following: look at the second screenshot and tell me what Miri has printed.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Comprehensive problem description: &lt;em&gt;Undefined Behavior: memory access failed: alloc872852 has size 250, so pointer to 22 bytes starting at offset 236 is out-of-bounds&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The exact place in the code where the error happened: &lt;code&gt;ffi&#x2F;src&#x2F;sspi&#x2F;sec_pkg_info.rs:189:13&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;An approximate stack trace.&lt;&#x2F;li&gt;
&lt;li&gt;A place in the code where the memory was allocated: &lt;code&gt;ffi&#x2F;src&#x2F;sspi&#x2F;sec_pkg_info.rs:167:28&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Isn&#x27;t this cool? It&#x27;s very cool! Now I have so much info to fix this UB. I can&#x27;t ask for more info 😄.&lt;&#x2F;p&gt;
&lt;p&gt;Miri has found more bugs than I expected. The UB was in such places I can&#x27;t even think of. In this PR you can see what UB and memory leaks I have fixed thanks to Miri: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;pull&#x2F;256&quot;&gt;Fix UB and memory leaks found by Miri&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;limitations&quot;&gt;Limitations&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Miri can execute only Rust code.&lt;&#x2F;strong&gt; It means you don&#x27;t have access to all functions from &lt;code&gt;libc&lt;&#x2F;code&gt; or any other foreign functions (system API, FFI). Miri can open the file or read the environment variable. But you can not establish a TCP connection, for example. It&#x27;s another reason to write &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;q&#x2F;14000762&#x2F;9123725&quot;&gt;low-coupled code with high cohesion&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Miri can not ensure that your program is sound.&lt;&#x2F;strong&gt; From Miri &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri?tab=readme-ov-file#miri&quot;&gt;README.md&lt;&#x2F;a&gt;:
&lt;blockquote&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;unsafe-code-guidelines&#x2F;glossary.html#soundness-of-code--of-a-library&quot;&gt;Soundness&lt;&#x2F;a&gt; is the property of never causing undefined behavior when invoked from arbitrary safe code, even in combination with other sound code. In contrast, Miri can just tell you if &lt;em&gt;a particular way of interacting with your code&lt;&#x2F;em&gt; (e.g., a test suite) causes any undefined behavior. It is up to you to ensure sufficient coverage.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Miri can be slow on big&#x2F;heavy tests.&lt;&#x2F;strong&gt; It&#x27;s because Miri is &lt;em&gt;an interpreter&lt;&#x2F;em&gt; for Rust&#x27;s mid-level intermediate representation. It means that the code is not compiled to ASM and is not executed directly on the CPU.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;configuration&quot;&gt;Configuration&lt;&#x2F;h1&gt;
&lt;p&gt;Miri can be configured by &lt;code&gt;-Z&lt;&#x2F;code&gt; flags and environment variables. And yes, we don&#x27;t have any &lt;code&gt;.toml&lt;&#x2F;code&gt; file here. For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;MIRIFLAGS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;-Zmiri-disable-isolation -Zmiri-ignore-leak&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; cargo&lt;&#x2F;span&gt;&lt;span&gt; +nightly miri test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The full list of flags is listed in the Miri &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri#miri--z-flags-and-environment-variables&quot;&gt;README.md&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;conclusions&quot;&gt;Conclusions&lt;&#x2F;h1&gt;
&lt;p&gt;If you&#x27;re writing &lt;code&gt;unsafe&lt;&#x2F;code&gt; Rust code, don&#x27;t forget to test it.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re writing &lt;code&gt;unsafe&lt;&#x2F;code&gt; Rust code, don&#x27;t forget to run it with &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&quot;&gt;Miri&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s all. Bye bye 👋.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;doc-references-code&quot;&gt;Doc, references, code&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&quot;&gt;Miri&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri?tab=readme-ov-file#miri--z-flags-and-environment-variables&quot;&gt;Miri flags&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;behavior-considered-undefined.html&quot;&gt;Behavior considered undefined&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.ralfj.de&#x2F;blog&#x2F;2023&#x2F;06&#x2F;13&#x2F;undefined-behavior-talk.html&quot;&gt;Talk about Undefined Behavior, unsafe Rust, and Miri&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Git recipes</title>
        <published>2024-06-22T00:00:00+00:00</published>
        <updated>2024-06-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/git-recipes/"/>
        <id>https://tbt.qkation.com/posts/git-recipes/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/git-recipes/">&lt;p&gt;Recently I lectured in my company about &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.git-scm.com&#x2F;&quot;&gt;&lt;code&gt;git&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and resolving specific situations with it. It inspired me to write this article. I know that there is tons of info about &lt;code&gt;git&lt;&#x2F;code&gt; and related stuff. I wanted to make this one as a comprehensive set of instructions about resolving concrete git situations.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note.&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; This page can be changed and improved in the future (I&#x27;ll try to save the backward compatibility)!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;how-to-read-this-page&quot;&gt;How to read this page&lt;&#x2F;h1&gt;
&lt;p&gt;You can read it in any order. If you are interested only in some particular scenario, then read only the corresponding section. All sections are independent from each other and you can start reading anywhere.&lt;&#x2F;p&gt;
&lt;p&gt;The required &lt;code&gt;git&lt;&#x2F;code&gt; knowledge level to read this article is pretty low. If you know what are &lt;em&gt;commit&lt;&#x2F;em&gt;, &lt;em&gt;branch&lt;&#x2F;em&gt;, and &lt;em&gt;index&lt;&#x2F;em&gt; (&lt;em&gt;stage&lt;&#x2F;em&gt;), then everything is good.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;goals&quot;&gt;Goals&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Explain how to resolve common &lt;code&gt;git&lt;&#x2F;code&gt; tasks I face at work every time.&lt;&#x2F;li&gt;
&lt;li&gt;Improve your &lt;code&gt;git&lt;&#x2F;code&gt; knowledge.&lt;&#x2F;li&gt;
&lt;li&gt;Dispel the fear of working with &lt;code&gt;git&lt;&#x2F;code&gt; in uncommon cases (if you have one).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;non-goals&quot;&gt;Non-goals&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Explain how &lt;code&gt;git&lt;&#x2F;code&gt; works inside.&lt;&#x2F;strong&gt; There is a great section in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.git-scm.com&#x2F;book&#x2F;en&#x2F;v2&quot;&gt;the book&lt;&#x2F;a&gt; about git internals: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.git-scm.com&#x2F;book&#x2F;en&#x2F;v2&#x2F;Git-Internals-Plumbing-and-Porcelain&quot;&gt;Git Internals&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Propagate to work with &lt;code&gt;git&lt;&#x2F;code&gt; only from the terminal.&lt;&#x2F;strong&gt; If the GUI is enough for you to perform all needed tasks, then it&#x27;s great! The less we interact with &lt;code&gt;git&lt;&#x2F;code&gt;, the lower the probability of having problems with it 🙃.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Write zero to pro guide.&lt;&#x2F;strong&gt; It&#x27;s just impossible 😄.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Replace the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ohshitgit.com&#x2F;&quot;&gt;Oh Shit, Git!?!&lt;&#x2F;a&gt; page&lt;&#x2F;strong&gt;. The &lt;em&gt;Oh-Shit-Git&lt;&#x2F;em&gt; purpose is to quickly resolve common problems. But my purpose is to offer guides for common tasks.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;recipes&quot;&gt;Recipes&lt;&#x2F;h1&gt;
&lt;p&gt;I want to leave a few clarifications before I write recipes.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;HEAD&lt;&#x2F;code&gt;. How does Git know what branch you’re currently on? It keeps a special pointer called &lt;code&gt;HEAD&lt;&#x2F;code&gt;. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;book&#x2F;en&#x2F;v2&#x2F;Git-Branching-Branches-in-a-Nutshell&quot;&gt;3.1 Git Branching - Branches in a Nutshell&lt;&#x2F;a&gt;. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;2304106&#x2F;9123725&quot;&gt;What is HEAD in Git?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;~&amp;lt;number&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;^&amp;lt;number&amp;gt;&lt;&#x2F;code&gt; is the same in many cases, but not always. Read this SO answer for more details: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;2222920&#x2F;9123725&quot;&gt;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;2222920&#x2F;9123725&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;last-commit-to-index&quot;&gt;Last commit to index&lt;&#x2F;h2&gt;
&lt;p&gt;So, you want to &lt;em&gt;&quot;undo&quot;&lt;&#x2F;em&gt; the last commit but save changes. The &lt;code&gt;git&lt;&#x2F;code&gt; has a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-reset&quot;&gt;&lt;code&gt;git reset&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; command for that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; reset&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --soft&lt;&#x2F;span&gt;&lt;span&gt; HEAD~1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As a result, you&#x27;ll not have the last commit and all changes will be in the stage. And yes, you can enter any number of commits instead of &lt;code&gt;1&lt;&#x2F;code&gt;. If you want changes to be untracked, then use the save command but with the &lt;code&gt;--mixed&lt;&#x2F;code&gt; parameter:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; reset&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --mixed&lt;&#x2F;span&gt;&lt;span&gt; HEAD~1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;discard-last-commit&quot;&gt;Discard last commit&lt;&#x2F;h2&gt;
&lt;p&gt;I know that it&#x27;s a bad idea, but if you really want, then this is how you can &lt;strong&gt;discard&lt;&#x2F;strong&gt; the last commit:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; reset&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --hard&lt;&#x2F;span&gt;&lt;span&gt; HEAD~1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Note.&lt;&#x2F;strong&gt; If you regret your decision, then you can restore lost commit with its hash:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; cherry-pick&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;commit-hash&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you don&#x27;t know its hash, then try to find it with &lt;code&gt;git reflog&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;edit-last-commit&quot;&gt;Edit last commit&lt;&#x2F;h2&gt;
&lt;p&gt;Actually, you only need the &lt;code&gt;git commit --amend&lt;&#x2F;code&gt; to do it. &lt;code&gt;git commit&lt;&#x2F;code&gt; has a lot of flags and possible use cases, but I list here only common ones so you can copy and use them.&lt;&#x2F;p&gt;
&lt;p&gt;If you have any changes in the stage, then they will be added to commit after running &lt;code&gt;git commit --amend&lt;&#x2F;code&gt;. For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt; README.md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; commit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --amend --no-edit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now the last commit contains changes we made in &lt;code&gt;README.md&lt;&#x2F;code&gt; file. The &lt;code&gt;--no-edit&lt;&#x2F;code&gt; arg means do not edit the commit message. If you want to edit the commit message, then use the &lt;code&gt;-m&lt;&#x2F;code&gt; arg and just nothing (&lt;code&gt;git&lt;&#x2F;code&gt; will ask you for the message). It&#x27;s also possible to alter the commit author, date, and so on:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Reset commit author saving commit date. This command is helpful when you&amp;#39;ve changed the `.gitconfig` file.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; commit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --amend&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; commit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --amend -m&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;new commit message&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; commit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --amend --reset-author --no-edit --date=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;$(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; log&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; -n 1 --format=%aD&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; commit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --amend --author=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;author&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Run &lt;code&gt;git commit --help&lt;&#x2F;code&gt; for more flags.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;edit-any-commit-in-branch&quot;&gt;Edit any commit in branch&lt;&#x2F;h2&gt;
&lt;p&gt;Lets say you want to edit 5th commit starting from the current one (5th parent). You can use the &lt;code&gt;git rebase&lt;&#x2F;code&gt; with its interactive mode to do it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; rebase&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span&gt; HEAD~5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;git&lt;&#x2F;code&gt; will open a text file with a list of 5 commits (parent commits). Now you need to write &lt;code&gt;edit&lt;&#x2F;code&gt; instead of &lt;code&gt;pick&lt;&#x2F;code&gt; for commit you want to edit. Safe this file and clone the editor. The rebasing will stop in the specified commit.&lt;&#x2F;p&gt;
&lt;p&gt;Now all you need is to edit selected commit and continue rebasing:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Check this recipe to know how to edit the commit: &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;git-recipes&#x2F;#edit-last-commit&quot;&gt;Edit last commit&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Continue rebasing:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; rebase&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;example&quot;&gt;Example&lt;&#x2F;h3&gt;
&lt;p&gt;I want to edit the the parent commit:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;git-recipes&#x2F;.&#x2F;git_log.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So, I type &lt;code&gt;git rebase -i HEAD~2&lt;&#x2F;code&gt; and edit the opened text file:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;git-recipes&#x2F;.&#x2F;git_rebase_edit.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When I save the file and close the editor, I see (&lt;code&gt;git status&lt;&#x2F;code&gt;) that rebasing has stopped in the needed commit (&lt;code&gt;1&lt;&#x2F;code&gt; on the screenshot) and git even shows me helpful commands (&lt;code&gt;2&lt;&#x2F;code&gt; on the screenshot):&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;git-recipes&#x2F;.&#x2F;git_rebase_status.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I edit files as I want, commit changes, and continue rebasing:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;git-recipes&#x2F;.&#x2F;git_rebase_finish.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s all! Nothing complicated 😄.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;split-commit-into-two&quot;&gt;Split commit into two&lt;&#x2F;h2&gt;
&lt;p&gt;Oh, it is an easy one. Usually, I do it in two steps:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&quot;Undo&quot; the last commit but save changes. &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;git-recipes&#x2F;#last-commit-to-index&quot;&gt;Last commit to index&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Create two different commits with &lt;code&gt;git add&lt;&#x2F;code&gt; and &lt;code&gt;git commit&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &amp;quot;Undo&amp;quot; last commit and save its changes. Changes will not be indexed after this command.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; reset&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --mixed&lt;&#x2F;span&gt;&lt;span&gt; HEAD~1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# First commit:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; add&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;files for first commit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; commit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; -m&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;first commit message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Second commit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; add&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;files for second commit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; commit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; -m&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;second commit message&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can split one commit into multiple ones with this approach. If you need to split another commit in your branch (one of the parent commits), use the &lt;code&gt;git rebase -i&lt;&#x2F;code&gt; and &lt;code&gt;git reset&lt;&#x2F;code&gt; commands. More info: &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;git-recipes&#x2F;#edit-any-commit-in-branch&quot;&gt;Edit any commit in branch&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;split-branch-into-a-few-pull-requests&quot;&gt;Split branch into a few pull requests&lt;&#x2F;h2&gt;
&lt;p&gt;😑 😟 😵‍💫&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;git-recipes&#x2F;.&#x2F;post_merge_request.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;(&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;xanf_ua&#x2F;status&#x2F;1688486956202643456&quot;&gt;post source&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;p&gt;The algorithm is simple:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Decide how to split. How many branched you&#x27;ll have and what commits you&#x27;ll move to what branches.&lt;&#x2F;li&gt;
&lt;li&gt;If you need to split some commits in order to move them to separate branches, then read the &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;git-recipes&#x2F;#split-commit-into-two&quot;&gt;Split commit into two&lt;&#x2F;a&gt; recipe, and go to the step 1. Otherwise, go to step 2.&lt;&#x2F;li&gt;
&lt;li&gt;Create needed branches in the base commit of the current branch.&lt;&#x2F;li&gt;
&lt;li&gt;Use &lt;code&gt;git checkout&lt;&#x2F;code&gt; and &lt;code&gt;git cherry-pick&lt;&#x2F;code&gt; commands to apply commits to corresponding branches.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;untrack-file&quot;&gt;Untrack file&lt;&#x2F;h2&gt;
&lt;p&gt;If you want &lt;code&gt;git&lt;&#x2F;code&gt; to ignore some file, then just add it to the &lt;code&gt;.gitignore&lt;&#x2F;code&gt; file. For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;credentials.json&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; .gitignore&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But if this file was tracked by the &lt;code&gt;git&lt;&#x2F;code&gt; before, then this is not enough. You also need to run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; rm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --cached&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;More info you can read in this SO answer: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;936290&#x2F;9123725&quot;&gt;How to stop tracking and ignore changes to a file in Git?&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;just-my-notes&quot;&gt;Just my notes&lt;&#x2F;h2&gt;
&lt;p&gt;Commands below are my notes for quick access:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# last commit with date&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; log&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --pretty=format:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;%h%x09%an%x09%ad%x09%s&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; head&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; -n 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# one commit changes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; show ff10697de4f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# move last 10 commits from HEAD to another_branch.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# note. this command will not move the another_branch itself. just adds commits on top of it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; rebase&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span&gt; HEAD~10&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --onto&lt;&#x2F;span&gt;&lt;span&gt; another_branch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# author and commiter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; cat-file commit HEAD&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# print any file in any commit. more info: https:&#x2F;&#x2F;juplo.de&#x2F;cat-any-file-in-any-commit-with-git&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; show&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;hash&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;filepath&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h1&gt;
&lt;p&gt;There are no any &lt;em&gt;smart&lt;&#x2F;em&gt; conclusions. But I have stupid ones 😁:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Make small atomic commits. The smaller your commits are, the better. It&#x27;s easier to work with such commits. Moreover, everything committed in &lt;code&gt;git&lt;&#x2F;code&gt; always stays inside of it and can always be restored.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There are a lot of other &lt;code&gt;git&lt;&#x2F;code&gt; commands. I just listed the most common situations for me.
I just leave it here: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=16807206&quot;&gt;HN: Nobody really understands git&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;doc-references-code&quot;&gt;Doc, references, code&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.git-scm.com&#x2F;book&#x2F;en&#x2F;v2&quot;&gt;Pro GIT&lt;&#x2F;a&gt; book.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ohshitgit.com&#x2F;&quot;&gt;Oh Shit, Git!?!&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Smart card container name</title>
        <published>2024-04-22T00:00:00+00:00</published>
        <updated>2024-04-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/scard-container-name/"/>
        <id>https://tbt.qkation.com/posts/scard-container-name/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/scard-container-name/">&lt;h1 id=&quot;before-i-start&quot;&gt;Before I start&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;goals&quot;&gt;Goals&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Explain how the Windows &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;smartcard&#x2F;smart-card-minidriver-overview&quot;&gt;minidriver&lt;&#x2F;a&gt; treats the smart card container name.&lt;&#x2F;li&gt;
&lt;li&gt;Tell how a bad container name can break scard auth.&lt;&#x2F;li&gt;
&lt;li&gt;Fun 🥳.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;non-goals&quot;&gt;Non-goals&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Explain every piece of smart card architecture in Windows.&lt;&#x2F;li&gt;
&lt;li&gt;Explain every smart card minidriver function.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;getting-started&quot;&gt;Getting Started&lt;&#x2F;h1&gt;
&lt;p&gt;In my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;win-scard-cache&quot;&gt;previous article&lt;&#x2F;a&gt;, I explained the different smart card cache items (files), their format, and purpose. The current one is some continuation of talking about PIV smart cards in Windows. The setup is the same: Windows smart card minidriver + PIV smartcard. But in this case, we&#x27;ll use a fully emulated smart card 🔥.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note.&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; The current article is full of technical things related to debugging (WinDbg) and reversing (IDA). Depending on your purpose, choose one of the following paths:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If you want to reproduce each step with me, then perform all actions from the &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;#debugging-environment&quot;&gt;Debugging environment&lt;&#x2F;a&gt; section and continue reading the article.&lt;&#x2F;li&gt;
&lt;li&gt;If you don&#x27;t want to set up the whole environment but want to reproduce each step on your machine, then download my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;drive.google.com&#x2F;drive&#x2F;folders&#x2F;1eaQld0SC94sMgzQUMvIZ1Lm7vUo1PoSr?usp=sharing&quot;&gt;TTD recoding and log files&lt;&#x2F;a&gt;. But I still recommend reading the &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;#debugging-environment&quot;&gt;Debugging environment&lt;&#x2F;a&gt; section (at least to know how I came up with it).&lt;&#x2F;li&gt;
&lt;li&gt;If you only want to read my findings and smart card container name structure, then jump to the &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;#what&quot;&gt;What?&lt;&#x2F;a&gt; section.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;else&lt;&#x2F;code&gt;: read it fully.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Happy reading 😊. Enjoy 😌.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;debugging-environment&quot;&gt;Debugging environment&lt;&#x2F;h1&gt;
&lt;p&gt;My goal is to simulate the data signing using an emulated smart card. To achieve this I need two key things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Some program signs the data using the smart card.&lt;&#x2F;li&gt;
&lt;li&gt;Hook somehow the &lt;code&gt;winscard.dll&lt;&#x2F;code&gt; to use an emulated smart card.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A brief explanation of our debugging environment:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Test VM + certificate with private key suitable for the data signing.&lt;&#x2F;li&gt;
&lt;li&gt;We&#x27;ll have a small program written in C#. The only thing this program does is sign the hardcoded data using the smart card.&lt;&#x2F;li&gt;
&lt;li&gt;We&#x27;ll have a &lt;code&gt;bad.dll&lt;&#x2F;code&gt; that hooks the original &lt;code&gt;winscard.dll&lt;&#x2F;code&gt; with our one.&lt;&#x2F;li&gt;
&lt;li&gt;And the last but not least thing is a &lt;em&gt;&quot;launcher&quot;&lt;&#x2F;em&gt;: another program that creates a signing process, then loads the &lt;code&gt;bad.dll&lt;&#x2F;code&gt; into it to hook the &lt;code&gt;winscard.dll&lt;&#x2F;code&gt;, and then continues the execution.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Pheww, it starts looking like some kind of Frankenstein&lt;&#x2F;em&gt; 🤪&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Yes. You are right 🙃.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compile-the-data-signer&quot;&gt;Compile the data signer&lt;&#x2F;h2&gt;
&lt;p&gt;The code is very simple. It uses some high level C# API for the data signing. The full code can be found &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;scard-container-name&#x2F;scard-container-name&#x2F;SignDataTmp&quot;&gt;here&lt;&#x2F;a&gt;. Just clone the project and build it with &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;visualstudio.microsoft.com&#x2F;vs&#x2F;community&#x2F;&quot;&gt;Visual Studio&lt;&#x2F;a&gt;. &lt;em&gt;Note:&lt;&#x2F;em&gt; it required &lt;strong&gt;net6.0&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The overall algorithm is pretty simple: we create a CSP that matches our smart card and then sign the data using the RSA crypto provider. The simplified code looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Create needed CSP.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;CspParameters&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; csp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; CspParameters&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;    &amp;quot;Microsoft Base Smart Card Crypto Provider&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    containerName&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;&#x2F; smart card container name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;csp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;KeyPassword&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; pwd&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Sign the data.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;RSACryptoServiceProvider&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rsaCsp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; RSACryptoServiceProvider&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;csp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span&gt;[]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; signature&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; rsaCsp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;SignData&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;dataToSign&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; HashAlgorithmName&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;SHA1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; RSASignaturePadding&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;Pkcs1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As a result, you should get &lt;code&gt;SignDataTmp.exe&lt;&#x2F;code&gt; + &lt;code&gt;SignDataTmp.dll&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compile-your-own-version-of-winscard-dll&quot;&gt;Compile your own version of &lt;code&gt;winscard.dll&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; clone https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span&gt; sspi-rs&#x2F;ffi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; checkout 4cd21349311b8edad03cc0dc8edf56407ccc22b9&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span&gt; build&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --all-features&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Of course, during my first debugging, I had a dev version of the &lt;code&gt;sspi-rs&lt;&#x2F;code&gt;. But now all developed functionality has been &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;pull&#x2F;210&quot;&gt;merged&lt;&#x2F;a&gt;, so we need to pick a specific commit. After that you will have &lt;code&gt;sspi.dll&lt;&#x2F;code&gt; in the &lt;code&gt;target&#x2F;debug&lt;&#x2F;code&gt; directory. You can rename it to &lt;code&gt;winscard.dll&lt;&#x2F;code&gt; if you want (but it&#x27;s not required).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compile-bad-dll&quot;&gt;Compile &lt;code&gt;bad.dll&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This &lt;code&gt;bad.dll&lt;&#x2F;code&gt; represents how I do the hooking. There are many hooking techniques. My choice criteria were that it should work and not be hard to implement. So, I chose the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TsudaKageyu&#x2F;minhook&quot;&gt;MinHook&lt;&#x2F;a&gt; library. It is easy to use and does its job well. Project source code can be found &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;scard-container-name&#x2F;scard-container-name&#x2F;bad&quot;&gt;here&lt;&#x2F;a&gt;. Just clone the project and build it with &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;visualstudio.microsoft.com&#x2F;vs&#x2F;community&#x2F;&quot;&gt;Visual Studio&lt;&#x2F;a&gt;. &lt;em&gt;Note:&lt;&#x2F;em&gt; do not forget to properly link it with &lt;code&gt;MinHook&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But here is a surprise. When you try to read the code you&#x27;ll find out that I hook some weird functions instead of the &lt;code&gt;winscard.dll&lt;&#x2F;code&gt;. The reason for that is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;cpp&#x2F;build&#x2F;reference&#x2F;understanding-the-helper-function&quot;&gt;delayed loading&lt;&#x2F;a&gt;. We can not simply hook the &lt;code&gt;winscard.dll&lt;&#x2F;code&gt; because the &lt;code&gt;basecsp.dll&lt;&#x2F;code&gt; loads it via delayed loading 😕.&lt;&#x2F;p&gt;
&lt;p&gt;But it is still possible to hook. Thanks to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;awakecoding&quot;&gt;@awakecoding&lt;&#x2F;a&gt; I know how to do it. He had &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;awakecoding&#x2F;status&#x2F;1725249330435518736&quot;&gt;researched&lt;&#x2F;a&gt; and implemented it in the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;MsRdpEx&quot;&gt;MsRdpEx&lt;&#x2F;a&gt;: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;MsRdpEx&#x2F;pull&#x2F;84&quot;&gt;fix winscard.dll delay-loading interception from basecsp.dll&lt;&#x2F;a&gt;. I reused some code and make it work for my debugging program 😅.&lt;&#x2F;p&gt;
&lt;p&gt;So, as a result, you should get &lt;code&gt;bad.dll&lt;&#x2F;code&gt;. Do not forget to set your own paths in the code!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compile-the-launcher&quot;&gt;Compile the launcher&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;em&gt;&quot;launcher&quot;&lt;&#x2F;em&gt; is named as &lt;em&gt;&quot;HookLibrary&quot;&lt;&#x2F;em&gt; due to my own historical reasons 🤪. The full source code can be found &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;scard-container-name&#x2F;scard-container-name&#x2F;HookLoadLibrary&quot;&gt;here&lt;&#x2F;a&gt;. &lt;em&gt;Important&lt;&#x2F;em&gt;: do not forget to change hardcoded paths to your ones. It works as follows:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Runs the data signer executable in a separate process, but does not run it.&lt;&#x2F;li&gt;
&lt;li&gt;Injects the &lt;code&gt;bad.dll&lt;&#x2F;code&gt; into the process memory forcing it to load this dll. In turn, the &lt;code&gt;bad.dll&lt;&#x2F;code&gt; will hook all needed methods.&lt;&#x2F;li&gt;
&lt;li&gt;Continues the execution.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;So, as a result, you should get &lt;code&gt;HookLoadLibrary.exe&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;run-it&quot;&gt;Run it&lt;&#x2F;h2&gt;
&lt;p&gt;Before trying to run this machinery we need to configure the emulated smart card. To do this set up the following environment variables:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Name&lt;&#x2F;th&gt;&lt;th&gt;Value&lt;&#x2F;th&gt;&lt;th&gt;Example&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SSPI_LOG_PATH&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Path to the log file&lt;&#x2F;td&gt;&lt;td&gt;D:\test_data\sspi.log&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SSPI_LOG_LEVEL&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Log level&lt;&#x2F;td&gt;&lt;td&gt;trace&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;WINSCARD_PIN&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Smart card PIN code&lt;&#x2F;td&gt;&lt;td&gt;214653&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;WINSCARD_CERT_PATH&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Path to the &lt;em&gt;.cer&lt;&#x2F;em&gt; file containing the smart card certificate&lt;&#x2F;td&gt;&lt;td&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;blob&#x2F;scard-container-name&#x2F;scard-container-name&#x2F;t2%40tbt.com.cer&quot;&gt;D:\test_data\user.cer&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;WINSCARD_PK_PATH&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Path to the &lt;em&gt;.key&lt;&#x2F;em&gt; file containing the smart card certificate&lt;&#x2F;td&gt;&lt;td&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;blob&#x2F;scard-container-name&#x2F;scard-container-name&#x2F;t2%40tbt.com.key&quot;&gt;D:\test_data\user.key&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;WINSCARD_CONTAINER&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Container name&lt;&#x2F;td&gt;&lt;td&gt;1b22c362-46ba-4889-ad5c-01f7abcabcabedw&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;WINSCARD_READER&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Reader name&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Microsoft Virtual Smart Card 2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;And finally, run &lt;code&gt;HookLoadLibrary.exe&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;debugging&quot;&gt;Debugging&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;the-first-run&quot;&gt;The first run&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s try to sign the data using the emulated smart card.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;failed-signing.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Expectedly (otherwise, this article would not exist 🙂), we got an exception. Our goal for the rest of the article is to figure out the cause of the error and fix it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;error-location&quot;&gt;Error location&lt;&#x2F;h2&gt;
&lt;p&gt;At this point, I don&#x27;t know what caused the error. So, let&#x27;s use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;debugger&quot;&gt;WinDbg&lt;&#x2F;a&gt; and make a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;debuggercmds&#x2F;time-travel-debugging-overview&quot;&gt;TTD&lt;&#x2F;a&gt; recording. Finding a function that returns an error in this way will be easier. With TTD recording I can walk through the execution without rerunning the app.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note.&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; Because the &lt;code&gt;HookLoadLibrary.exe&lt;&#x2F;code&gt; runs the &lt;code&gt;SignDataTpm.exe&lt;&#x2F;code&gt; in a separate process, you should attach WinDbg to this process instead of running the &lt;code&gt;HookLoadLibrary.exe&lt;&#x2F;code&gt; in the WinDbg.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;how-to-tdd.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Good. Now we can start debugging.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;windbg-start-debugging.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;At this point, I can assume only something: some function in &lt;code&gt;msclmd.dll&lt;&#x2F;code&gt; or &lt;code&gt;basecsp.dll&lt;&#x2F;code&gt; fails and breaks the signing. Let&#x27;s see the last &lt;code&gt;sspi-rs&lt;&#x2F;code&gt; FII calls in the logs to have at least some orientation on where to dig. If we catch a moment of the last winscard calls, we&#x27;ll retrieve a call stack and then analyze those functions. These are the last meaningful records in the log file:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;sspi-logs.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We can see the &lt;code&gt;SCardTransmit&lt;&#x2F;code&gt; function call. I&#x27;ll search for them in the WinDbg. But because I use the custom &lt;code&gt;winscard.dll&lt;&#x2F;code&gt;, all WinSCard-related functions have a &lt;code&gt;Rust_&lt;&#x2F;code&gt; prefix. Example:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;windbg-winscard-function-names.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I have omitted some manipulations so that this article is not too boring. In short, on the screenshot below we can see the last &lt;code&gt;SCardTransmit&lt;&#x2F;code&gt; call and part of the call stack:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;windbg-call-stack.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As I expected, we see the &lt;code&gt;msclmd.dll&lt;&#x2F;code&gt; and &lt;code&gt;basecsp.dll&lt;&#x2F;code&gt; functions. The next algorithm is the following: I take the highest function from the call stack and check the resulting status code in the WinDbg. If it succeeds, I take a lower function from the call stack and check its status code. When I finally find a failing function, I&#x27;ll use WinDbg and IDA to see the exact failing point. I expect something like &lt;code&gt;return 0x80100004;&lt;&#x2F;code&gt; or any other status code.&lt;&#x2F;p&gt;
&lt;p&gt;Hmmm 🤔. All functions up to the C#-related ones were succeeded. Perhaps the last calls to &lt;code&gt;SCardTransmit&lt;&#x2F;code&gt; occurred after a signing error and Windows was trying to finalize the error&#x2F;gather some information OR the signing process is not even started yet. I need another function to start with. Let&#x27;s try &lt;code&gt;SCardReadCacheW&lt;&#x2F;code&gt;. I had a &lt;em&gt;&quot;great&quot;&lt;&#x2F;em&gt; experience with smart card caches in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;win-scard-cache&quot;&gt;the past&lt;&#x2F;a&gt;, so maybe it&#x27;ll help me this time. Thanks to TTD I don&#x27;t need to rerun it and can walk through the recording again and again.&lt;&#x2F;p&gt;
&lt;p&gt;After some time I finally found something that looks like data signing 😌.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;windbg-signing-call-stack.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s see the status codes of the highlighted functions:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;windbg-mslmd-pivcardsigndata-fail.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Cool! Now we know what the &lt;code&gt;msclmd!I_PIVCardSignData&lt;&#x2F;code&gt; function returns the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;authentication-return-values&quot;&gt;&lt;code&gt;SCARD_E_INVALID_PARAMETER&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; status code.&lt;&#x2F;p&gt;
&lt;p&gt;I need to find where in this function body the error has been thrown. Walking through every ASM instruction is boring and time-consuming, so I took an IDA and reversed this function as much as I could. After that, I marked some places (other function calls, &lt;code&gt;if&lt;&#x2F;code&gt;s, and so on) that could fail and checked them with WinDbg.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;windbg-mslmd-I_GetKeyAndAlgFromMapIndex-fail.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Okaaay, so, the key algorithm and id extraction have failed 🤔. Reversed pseudo-code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;return_code &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; I_GetKeyAndAlgFromMapIndex&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                card_data,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;                *&lt;&#x2F;span&gt;&lt;span&gt;((_BYTE &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;)signing_info &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; bContainerIndex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;unsigned&lt;&#x2F;span&gt;&lt;span&gt; __int8 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;font-style: italic;&quot;&gt;key_buff&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;                &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;font-style: italic;&quot;&gt;key_alg&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;                &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;font-style: italic;&quot;&gt;key_size&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I dug into it and found exact place where the fail happens. I skipped this part for you and show you the result:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;windbg-failed-I_IsValidPIVCertFileTag.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here is the reversed part of the ASM code above. We can see that invalid cert file tag causes the &lt;code&gt;SCARD_E_INVALID_PARAMETER&lt;&#x2F;code&gt; error:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;ida-SCARD_E_INVALID_PARAMETER.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;On the screenshot above the part of the &lt;code&gt;msclmd!I_GetPIVKeyIDFromPIVCertFileTag&lt;&#x2F;code&gt; function is shown. The &lt;code&gt;msclmd!I_IsValidPIVCertFileTag&lt;&#x2F;code&gt; function has returned &lt;code&gt;0&lt;&#x2F;code&gt; (&lt;code&gt;false&lt;&#x2F;code&gt;). It means that the cert file tag is not valid.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;ida-I_IsValidPIVCertFileTag.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So, the &lt;code&gt;cert_file_tag&lt;&#x2F;code&gt; must meet highlighted conditions to be valid. In our case it&#x27;s equal to &lt;code&gt;0xaaaaaa&lt;&#x2F;code&gt; which is obviously not valid. To fix it we need to figure out how the &lt;code&gt;cert_file_tag&lt;&#x2F;code&gt; is constructed and how we can change it to met one of the needed values. I did it for you, so take a look at the following screenshot:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;ida-cert-file-tag-extraction.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The screenshot above contains a part of the &lt;code&gt;msclmd!I_GetKeyAndAlgFromMapIndex&lt;&#x2F;code&gt; function. This piece of code gives us answers to all our questions. First of all, the &lt;code&gt;cert_file_tag&lt;&#x2F;code&gt; value is extracted from the &lt;code&gt;cmap_record&lt;&#x2F;code&gt; using the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;cpp&#x2F;c-runtime-library&#x2F;reference&#x2F;sscanf-s-sscanf-s-l-swscanf-s-swscanf-s-l?view=msvc-170&quot;&gt;&lt;code&gt;swscanf_s&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function. In simple words, it takes the &lt;code&gt;cmap_record&lt;&#x2F;code&gt; buffer pointer, skips the first 30 characters (bytes), scans the following 6 characters (bytes), converts them from hex to decimal, and, finally, assigns it to the &lt;code&gt;cert_file_tag&lt;&#x2F;code&gt; variable. This is our &lt;code&gt;cert_file_tag&lt;&#x2F;code&gt; which is not valid. In turn, the &lt;code&gt;cmap_record&lt;&#x2F;code&gt; is a pointer to the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;selfrender&#x2F;Windows-Server-2003&#x2F;blob&#x2F;5c6fe3db626b63a384230a1aa6b92ac416b0765f&#x2F;ds&#x2F;security&#x2F;csps&#x2F;wfsccsp&#x2F;inc&#x2F;basecsp.h#L104-L110&quot;&gt;&lt;code&gt;CONTAINER_MAP_RECORD&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; structure where the first field is a container name:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; MAX_CONTAINER_NAME_LEN&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;                  40&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; _CONTAINER_MAP_RECORD&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    WCHAR wszGuid [MAX_CONTAINER_NAME_LEN];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    BYTE bFlags;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    WORD wSigKeySizeBits;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    WORD wKeyExchangeKeySizeBits;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} CONTAINER_MAP_RECORD,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;PCONTAINER_MAP_RECORD;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;According to the Microsoft&#x27;s specification:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The &lt;code&gt;wszGuid&lt;&#x2F;code&gt; member consists of a UNICODE character string representation of an identifier that CAPI assigned to the container. This is usually, but not always, a GUID string. Identifier names cannot contain the special character “\”. When read-only cards are provisioned, the provisioning process must follow the same guidelines for identifier names.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;what&quot;&gt;What?&lt;&#x2F;h2&gt;
&lt;p&gt;😮‍💨 Let&#x27;s summarize it all.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;CONTAINER_MAP_RECORD&lt;&#x2F;code&gt; structure contains a smart card container name. The container map record value is extracted from &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;win-scard-cache&#x2F;#cached-generalfile-mscp-cmapfile&quot;&gt;the smart card cache&lt;&#x2F;a&gt;. This container name (&lt;code&gt;wszGuid&lt;&#x2F;code&gt;) is not a random GUID value. This is a special value that must contain one of the allowed certificate file tags. The smart card driver (&lt;code&gt;msclmd.dll&lt;&#x2F;code&gt;) decides how to sign the data based on this &lt;code&gt;cer_file_tag&lt;&#x2F;code&gt;. All possible certificate file tags are defined and can be found in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;nvlpubs.nist.gov&#x2F;nistpubs&#x2F;SpecialPublications&#x2F;NIST.SP.800-73-4.pdf&quot;&gt;the PIV smart card specification&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;search?q=0x5FC101+language%3AC&amp;amp;type=code&amp;amp;l=C&quot;&gt;open-source projects&lt;&#x2F;a&gt; that follow this spec.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;ida-cert-file-tags.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Soooo, if we just change the container name, then data signing should work?&lt;&#x2F;em&gt; 👉👈&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It seems like yes, it should. We have nothing to lose. Let&#x27;s try it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-fix&quot;&gt;The fix&lt;&#x2F;h2&gt;
&lt;p&gt;Change the &lt;code&gt;WINSCARD_CONTAINER&lt;&#x2F;code&gt; environment variable.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Name&lt;&#x2F;th&gt;&lt;th&gt;Value&lt;&#x2F;th&gt;&lt;th&gt;Example&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;WINSCARD_CONTAINER&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Container name&lt;&#x2F;td&gt;&lt;td&gt;1b22c362-46ba-4889-ad5c-01f7aa5fc10awww&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;🤞🤞🤞&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;signature.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;🎉 It works! 🎉 Ignore the error at the bottom of the terminal. The only important thing is the resulting signature. It means, that the data signing using the emulated smart card works well 😌. Even in the &lt;code&gt;sspi-rs&lt;&#x2F;code&gt; logs we can see &lt;code&gt;SCardTransmit&lt;&#x2F;code&gt; calls with input padded digest and output signature:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;scard-container-name&#x2F;.&#x2F;sspi-signature-logs.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;😊😊😊 I don&#x27;t know why this container name format is not documented anywhere (at least I didn&#x27;t find any mention about it on the Internet).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h1&gt;
&lt;p&gt;There are a lot of ways of debugging programs. In this article, I told you about one of my cases where I need to be creative and patient. In the end, I could tell that Windows is bad and so on, but I&#x27;ll say the following instead:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Everything is possible. Any bug and problem is solvable. Be creative and have patience.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Wish you more interesting bugs and fun debugging! 😝&lt;&#x2F;p&gt;
&lt;h1 id=&quot;doc-references-code&quot;&gt;Doc, references, code&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;smartcard&#x2F;smart-card-minidriver-overview&quot;&gt;Smart Card Minidriver Overview&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;pull&#x2F;210&quot;&gt;Emulated smart cards implementation&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;scard-container-name&#x2F;scard-container-name&quot;&gt;Source code of all used debugging programs&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;debugger&quot;&gt;WinDbg&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;debuggercmds&#x2F;time-travel-debugging-overview&quot;&gt;TTD&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;drive.google.com&#x2F;drive&#x2F;folders&#x2F;1eaQld0SC94sMgzQUMvIZ1Lm7vUo1PoSr?usp=sharing&quot;&gt;TTD recording and log files&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Windows smart card cache</title>
        <published>2024-04-04T00:00:00+00:00</published>
        <updated>2024-04-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/win-scard-cache/"/>
        <id>https://tbt.qkation.com/posts/win-scard-cache/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/win-scard-cache/">&lt;h1 id=&quot;getting-started&quot;&gt;Getting Started&lt;&#x2F;h1&gt;
&lt;p&gt;A few months ago I had a great opportunity to implement &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;pull&#x2F;210&quot;&gt;the smart card emulation&lt;&#x2F;a&gt;. The whole point was to emulate the smart card behavior without an actual smart card. I can talk a lot about such stuff, but in this article, I&#x27;m going to share my experience in smart card cache exploration and implementation.&lt;&#x2F;p&gt;
&lt;p&gt;To make all my decisions clear for you, I provide you with some additional context. Imagine the reimplemented &lt;code&gt;winscard.dll&lt;&#x2F;code&gt; without actual calls to the security device but with the smart card emulation under the hood. Boom 💥! We have scard auth without a physical device.&lt;&#x2F;p&gt;
&lt;p&gt;You can have questions like &lt;em&gt;&quot;How can we replace the original dll&quot;&lt;&#x2F;em&gt;, &lt;em&gt;&quot;What is the point of such implementation&quot;&lt;&#x2F;em&gt;, &lt;em&gt;&quot;What are the limitations of it&quot;&lt;&#x2F;em&gt;, and so on. Unfortunately, it&#x27;s out of the scope of this article. Here I focused only on debugging and smart card cache (I&#x27;ll explain the reason for it further in the article).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;goals&quot;&gt;Goals&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;A brief overview of the smart card architecture in Windows.&lt;&#x2F;li&gt;
&lt;li&gt;Explain some smart card cache items for &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.idmanagement.gov&#x2F;university&#x2F;piv&#x2F;&quot;&gt;&lt;strong&gt;PIV&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; smart cards in Windows.&lt;&#x2F;li&gt;
&lt;li&gt;Fun 🥳.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Who should read this article:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Ones who are interested in how PIV smart cards work on Windows.&lt;&#x2F;li&gt;
&lt;li&gt;Ones who just need PIV scard cache items format (Hi 👋, &lt;code&gt;msclmd.dll&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;non-goals&quot;&gt;Non-goals&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Explain every piece of smart card architecture in Windows.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;overview&quot;&gt;Overview&lt;&#x2F;h1&gt;
&lt;p&gt;In Windows, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winscard&#x2F;&quot;&gt;WinSCard&lt;&#x2F;a&gt; is the lowest accessible API for communicating with smart cards. You operate only using handles (&lt;code&gt;SCARDCONTEXT&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;SCARDHANDLE&lt;&#x2F;code&gt;&#x2F;etc), raw &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Smart_card_application_protocol_data_unit&quot;&gt;APDU&lt;&#x2F;a&gt;s (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winscard&#x2F;nf-winscard-scardtransmit&quot;&gt;SCardTransmit&lt;&#x2F;a&gt; function), and a bunch of other low-level functions. If you look at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;security&#x2F;identity-protection&#x2F;smart-cards&#x2F;smart-card-architecture#base-csp-and-ksp-based-architecture-in-windows&quot;&gt;the CSP and KSP-based architecture diagram&lt;&#x2F;a&gt;, you&#x27;ll see WinScard almost at the bottom of the picture:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;security&#x2F;identity-protection&#x2F;smart-cards&#x2F;smart-card-architecture#base-csp-and-ksp-based-architecture-in-windows&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;security&#x2F;identity-protection&#x2F;smart-cards&#x2F;images&#x2F;sc-image206.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s analyze this diagram above. Usually, when you deal with any crypto operations in Windows, you use some high-level API - &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;seccrypto&#x2F;cryptoapi-system-architecture&quot;&gt;CryptoAPI&lt;&#x2F;a&gt;. But the CryptoAPI is just a high-level API and every &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Cryptographic_Service_Provider&quot;&gt;CSP&lt;&#x2F;a&gt; implements it. In the case of smart cards, the corresponding CSP (&lt;code&gt;basecsp.dll&lt;&#x2F;code&gt;, in our case) can not contain the CryptoAPI implementation because all crypto operations should be performed on the security device. This is why BaseCSP uses (depends on) the smart card minidriver. Such a minidriver translates high-level functions into WinSCard API calls. Nothing more.&lt;&#x2F;p&gt;
&lt;p&gt;Usually, every smart card vendor ships its smart card driver (you can see it on the diagram). The Windows itself contains two smart card drivers:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;One driver for Windows proprietary smart cards with closed specifications and documentation.&lt;&#x2F;li&gt;
&lt;li&gt;And another driver for PIV-compatible smart cards. It has open specifications (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;previous-versions&#x2F;windows&#x2F;hardware&#x2F;design&#x2F;dn631754(v=vs.85)&quot;&gt;Smart Card Minidriver Specification&lt;&#x2F;a&gt; + &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;nvlpubs.nist.gov&#x2F;nistpubs&#x2F;SpecialPublications&#x2F;NIST.SP.800-73-4.pdf&quot;&gt;NIST SP 800-73-4&lt;&#x2F;a&gt;) but closed documentation.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;...two smart card drivers:&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It was a small lie 😅. I mean, yes, it&#x27;s true, but those two drivers are implemented inside one dll: &lt;code&gt;msclmd.dll&lt;&#x2F;code&gt;. &lt;em&gt;For the rest of this article, we&#x27;ll talk &lt;strong&gt;only&lt;&#x2F;strong&gt; about &lt;code&gt;msclmd.dll&lt;&#x2F;code&gt; and &lt;strong&gt;PIV-compatible&lt;&#x2F;strong&gt; smart cards.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Got it. But why is card cache the main topic of this article?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I have a few reasons for it:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;No matter how good our WinSCard implementation is, authentication will fail without a working cache.&lt;&#x2F;li&gt;
&lt;li&gt;Only a few cache items are described in the Window&#x27;s minidriver specification. Many of them are undocumented and unknown (or known but the final file structure is not clear).&lt;&#x2F;li&gt;
&lt;li&gt;It was the hardest part to debug and implement 😝. It took me a few months.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Firstly, I thought I can found cache items format in the specification. But I was wrong. Secondly, I was astonished that I didn&#x27;t found any information about them in the Internet. In the result, it took me more then month to properly reverse&#x2F;debug &lt;code&gt;msclmd.dll&lt;&#x2F;code&gt; and extract all needed information about scard cache items. And I decided to write an article you are reading now.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;&#x2F;strong&gt;. I didn&#x27;t reverse the whole smart card driver. I explored only needed functions. So, this article has gaps in some places filled with my assumptions. If you are more experienced and know more about such places, please, leave a comment and I&#x27;ll edit the article to be more complete. Thanks&lt;&#x2F;em&gt;😌&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;debugging&quot;&gt;Debugging&lt;&#x2F;h1&gt;
&lt;p&gt;It&#x27;s easier to work if we have a concrete destination point. Let&#x27;s take the Remote Desktop Client (&lt;code&gt;mstsc.exe&lt;&#x2F;code&gt;), replace the &lt;code&gt;wiscard.dll&lt;&#x2F;code&gt;, and try to connect to the remote machine using the emulated smart card. The established RDP connection is our goal.&lt;&#x2F;p&gt;
&lt;p&gt;To make my life easier, I took the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;MsRdpEx&#x2F;&quot;&gt;MsRdpEx&lt;&#x2F;a&gt; and hooked the &lt;code&gt;winscard.dll&lt;&#x2F;code&gt; using the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;MsRdpEx&#x2F;pull&#x2F;76&quot;&gt;&lt;code&gt;MSRDPEX_WINSCARD_DLL&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; environment variable. Pretty simple and usable.&lt;&#x2F;p&gt;
&lt;p&gt;For the further work, only two instruments will be used:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;IDA.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;debugger&#x2F;&quot;&gt;WinDbg&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;debuggercmds&#x2F;time-travel-debugging-overview&quot;&gt;&lt;strong&gt;Time Travel Debugging&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;. I encourage you to try it! This technique saved me a lot of time. The possibility of re-playing and moving backward gives us almost unlimited power 💪.&lt;&#x2F;p&gt;
&lt;p&gt;I do &lt;strong&gt;not&lt;&#x2F;strong&gt; recommend debugging smart cards with &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;www.rohitab.com&#x2F;apimonitor&quot;&gt;API Monitor&lt;&#x2F;a&gt; because it can miss some WinSCard API function calls.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;let-s-start-the-journey&quot;&gt;Let&#x27;s start the journey&lt;&#x2F;h1&gt;
&lt;p&gt;I suppose the whole debugging process is boring for you, so I&#x27;ll show relevant reversed parts of the &lt;code&gt;msclmd.dll&lt;&#x2F;code&gt; with small descriptions. If you need only resulting cache items format (structure), then you should skip next sections and jump right to the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L146-L394&quot;&gt;implementation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;At some point in time, the &lt;code&gt;msclmd.dll&lt;&#x2F;code&gt; calls the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winscard&#x2F;nf-winscard-scardreadcachew&quot;&gt;&lt;code&gt;SCardReadCacheW&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function to extract some information from the smart card cache. What data should we return? What format does the data (cache file) have? The next chapters contain answers to those questions.&lt;&#x2F;p&gt;
&lt;p&gt;You can use the following material in two cases:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You are developing your own &lt;code&gt;winscard.dll&lt;&#x2F;code&gt; replacement.&lt;&#x2F;li&gt;
&lt;li&gt;You are using the WinSCard API (maybe developing your minidriver) under Windows and want to know what the &lt;code&gt;SCardReadCacheW&lt;&#x2F;code&gt; function returns.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Otherwise, it&#x27;s just a fun reading for you. Enjoy 😚&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cached-cardmodfile-cached-pin-freshness&quot;&gt;&lt;code&gt;Cached_CardmodFile\Cached_Pin_Freshness&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Usually, when the driver asks you for the &lt;code&gt;Cached_CardmodFile\Cached_Pin_Freshness&lt;&#x2F;code&gt; cache item, it wants to form the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;selfrender&#x2F;Windows-Server-2003&#x2F;blob&#x2F;5c6fe3db626b63a384230a1aa6b92ac416b0765f&#x2F;ds&#x2F;security&#x2F;csps&#x2F;wfsccsp&#x2F;inc&#x2F;basecsp.h#L121-L128&quot;&gt;&lt;code&gt;CARD_CACHE_FILE_FORMAT&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; structure and the PIN freshness counter is the first field in the structure:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; _CARD_CACHE_FILE_FORMAT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    BYTE bVersion;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    BYTE bPinsFreshness;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    WORD wContainersFreshness;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    WORD wFilesFreshness;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} CARD_CACHE_FILE_FORMAT,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;PCARD_CACHE_FILE_FORMAT;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The actual cache file is just one-byte number that represents a PIN freshness counter. If you want, it can be two-byte value, but the value will be casted to one-byte. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L383-L386&quot;&gt;Implementation example&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; PIN_FRESHNESS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0x00&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0x00&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;cache&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;    &amp;quot;Cached_CardmodFile&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;\\&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;Cached_Pin_Freshness&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;    PIN_FRESHNESS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_vec&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All three freshness counters are extracted from the card cache using the &lt;code&gt;msclmd!I_GetPIVCachedFreshnessCounter&lt;&#x2F;code&gt; function. Every freshness counter has an ID:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1&lt;&#x2F;code&gt; - PIN freshness.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;2&lt;&#x2F;code&gt; - file freshness.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;3&lt;&#x2F;code&gt; - container freshness.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;What about &lt;code&gt;bVersion&lt;&#x2F;code&gt; field?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Currently, it&#x27;s always equal to &lt;code&gt;1&lt;&#x2F;code&gt; (this value is hardcoded in the DLL. you&#x27;ll see it on the next screenshots).&lt;&#x2F;p&gt;
&lt;p&gt;But the &lt;code&gt;CARD_CACHE_FILE_FORMAT&lt;&#x2F;code&gt; structure creation is not just cache items copying to the structure fields. The driver has an additional algorithm. Okay, let&#x27;s move on.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cached-cardmodfile-cached-file-freshness&quot;&gt;&lt;code&gt;Cached_CardmodFile\Cached_File_Freshness&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;We are already familiar with freshness counters, so I skip this cache item introduction and jump to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L387-L390&quot;&gt;the implementation&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; FILE_FRESHNESS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0x0b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0x00&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;cache&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;    &amp;quot;Cached_CardmodFile&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;\\&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;Cached_File_Freshness&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;    FILE_FRESHNESS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_vec&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note. The &lt;code&gt;[0x0b, 0x00]&lt;&#x2F;code&gt; is almost random value. The freshness counter is just a counter. More importantly, this counter matches the next cache items (files) in this article. I&#x27;ll explain later what I mean.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cached-cardmodfile-cached-container-freshness&quot;&gt;&lt;code&gt;Cached_CardmodFile\Cached_Container_Freshness&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;And finally, the container freshness counter. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L391-L394&quot;&gt;Code&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; CONTAINER_FRESHNESS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;0x01&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0x00&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;cache&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;    &amp;quot;Cached_CardmodFile&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;\\&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;Cached_Container_Freshness&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;    CONTAINER_FRESHNESS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_vec&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;So the driver can finally create a &lt;code&gt;CARD_CACHE_FILE_FORMAT&lt;&#x2F;code&gt; structure?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;em&gt;Well yes but actually no.&lt;&#x2F;em&gt; Let&#x27;s see a small reversed part of the &lt;code&gt;msclmd!I_GetPIVCache&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;win-scard-cache&#x2F;CARD_CACHE_FILE_FORMAT_creation.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;What is an &lt;code&gt;activity_count&lt;&#x2F;code&gt;?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It&#x27;s a result value of the &lt;code&gt;msclmd!I_GetCardActivityCount&lt;&#x2F;code&gt; function. Here is how it calculated:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;win-scard-cache&#x2F;activity_count_calculation.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The activity counter is calculated based on the &lt;code&gt;dwEventState&lt;&#x2F;code&gt; value returned from the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winscard&#x2F;nf-winscard-scardgetstatuschangew&quot;&gt;&lt;code&gt;SCardGetStatusChangeW&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function. Furthermore, this value also affects the &lt;code&gt;CARD_CACHE_FILE_FORMAT&lt;&#x2F;code&gt; structure creation. I pay attention to it on purpose because it&#x27;s important to know the structure fields&#x27; values.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cached-cardproperty-read-only-mode-0&quot;&gt;&lt;code&gt;Cached_CardProperty_Read Only Mode_0&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To make further explanations easier, I introduce the cache value header:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; _CARD_FILE_HEADER&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    CARD_CACHE_FILE_FORMAT file_format;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    uint16 padding1;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    uint16 padding2;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    uint16 padding3;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    uint32 value_len;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} CARD_FILE_HEADER;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;value_len&lt;&#x2F;code&gt; bytes are placed right after this header. I can assume that padding bytes also have a meaning but in my practice, they are always equal to zero and I didn&#x27;t find any application for them.&lt;&#x2F;p&gt;
&lt;p&gt;This is a general layout for cache items related to the PIV smart card. Now we can finally see, how freshness and activity counters affect other cache files.&lt;&#x2F;p&gt;
&lt;p&gt;In the case of the current cache item, the &lt;code&gt;value_len&lt;&#x2F;code&gt; is 4, and value bytes represent the &lt;code&gt;BOOL&lt;&#x2F;code&gt; flag. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L171-L181&quot;&gt;Example implementation&lt;&#x2F;a&gt;. The meaning of this flag hides in the specification. It represents the &lt;code&gt;CP_CARD_READ_ONLY&lt;&#x2F;code&gt; card property:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If True, all write operations are blocked at the Base CSP layer. This flag also affects the data cache. If the card indicates that it is read-only, the Base CSP&#x2F;KSP does not write to the cardcf file.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;cached-cardproperty-cache-mode-0&quot;&gt;&lt;code&gt;Cached_CardProperty_Cache Mode_0&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The structure of this cache item is the same as in &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;win-scard-cache&#x2F;#cached-cardproperty-read-only-mode-0&quot;&gt;the previous one&lt;&#x2F;a&gt;. The &lt;code&gt;value_len&lt;&#x2F;code&gt; is 4, and value bytes represent the &lt;code&gt;DWORD&lt;&#x2F;code&gt; number. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L182-L192&quot;&gt;Example implementation&lt;&#x2F;a&gt;. It corresponds to the &lt;code&gt;CP_CARD_CACHE_MODE&lt;&#x2F;code&gt; card property and can have one of the possible values:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; CP_CACHE_MODE_GLOBAL_CACHE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;      1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; CP_CACHE_MODE_SESSION_ONLY&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;      2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; CP_CACHE_MODE_NO_CACHE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;          3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;cached-cardproperty-supports-windows-x-509-enrollment-0&quot;&gt;&lt;code&gt;Cached_CardProperty_Supports Windows x.509 Enrollment_0&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;value_len&lt;&#x2F;code&gt; is equal to 4 in the &lt;code&gt;CARD_FILE_HEADER&lt;&#x2F;code&gt; structure and those 4 bytes represent the &lt;code&gt;BOOL&lt;&#x2F;code&gt; value. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L193-L203&quot;&gt;Example implementation&lt;&#x2F;a&gt;. The meaning of this flag is the following:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Indicates whether Windows PKI should be allowed to write or renew certificates on the card. This should be used to avoid unexpected results because of a lack of support for multiple PINs in Windows PKI enrollment client.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;cached-generalfile-mscp-cmapfile&quot;&gt;&lt;code&gt;Cached_GeneralFile&#x2F;mscp&#x2F;cmapfile&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;It is worth noting that smart cards can have a few &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;2528335&#x2F;15125407&quot;&gt;key containers&lt;&#x2F;a&gt;. And here every card container are represented in the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;selfrender&#x2F;Windows-Server-2003&#x2F;blob&#x2F;5c6fe3db626b63a384230a1aa6b92ac416b0765f&#x2F;ds&#x2F;security&#x2F;csps&#x2F;wfsccsp&#x2F;inc&#x2F;basecsp.h#L104-L110&quot;&gt;&lt;code&gt;CONTAINER_MAP_RECORD&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; structure:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; MAX_CONTAINER_NAME_LEN&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 40&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; _CONTAINER_MAP_RECORD&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    WCHAR wszGuid [MAX_CONTAINER_NAME_LEN];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    BYTE bFlags;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    WORD wSigKeySizeBits;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    WORD wKeyExchangeKeySizeBits;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} CONTAINER_MAP_RECORD,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;PCONTAINER_MAP_RECORD;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The current cache item describes one or more such container records. The &lt;code&gt;value_len&lt;&#x2F;code&gt; is equal to &lt;em&gt;&lt;code&gt;0x56&lt;&#x2F;code&gt; (size of the &lt;code&gt;CONTAINER_MAP_RECORD&lt;&#x2F;code&gt;) * amount of container records structures&lt;&#x2F;em&gt;. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L204-L225&quot;&gt;Example implementation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cached-cardmodfile-cached-cmapfile&quot;&gt;&lt;code&gt;Cached_CardmodFile\Cached_CMAPFile&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This one is almost the same as &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;win-scard-cache&#x2F;#cached-generalfile-mscp-cmapfile&quot;&gt;the previous one&lt;&#x2F;a&gt; but without the &lt;code&gt;CARD_FILE_HEADER&lt;&#x2F;code&gt; structure at the start of the cache file. You can just remove the first 16 bytes from the &lt;code&gt;Cached_GeneralFile&#x2F;mscp&#x2F;cmapfile&lt;&#x2F;code&gt; cache file and you&#x27;ll get this one. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L226-L240&quot;&gt;Example implementation&lt;&#x2F;a&gt;. The driver (&lt;code&gt;msclmd.dll&lt;&#x2F;code&gt;) usually uses this cache file to find the needed card container specified in the credentials. For example, &lt;code&gt;basecsp!I_ContainerMapFind&lt;&#x2F;code&gt;, or &lt;code&gt;basecsp!ContainerMapFindContainer&lt;&#x2F;code&gt;, or &lt;code&gt;basecsp!FindCard&lt;&#x2F;code&gt; functions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cached-containerproperty-pin-identifier-0&quot;&gt;&lt;code&gt;Cached_ContainerProperty_PIN Identifier_0&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;value_len&lt;&#x2F;code&gt; is equal to 4 in the &lt;code&gt;CARD_FILE_HEADER&lt;&#x2F;code&gt; structure and those 4 bytes represent the &lt;code&gt;DWORD&lt;&#x2F;code&gt; value. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L241-L251&quot;&gt;Example implementation&lt;&#x2F;a&gt;. As I understand from the specification, the PIN identifier is associated with the role.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef&lt;&#x2F;span&gt;&lt;span&gt;     DWORD                      PIN_ID,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;PPIN_ID;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;     ROLE_EVERYONE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;              0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;     ROLE_USER&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;                  1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;     ROLE_ADMIN&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;                 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;cached-containerinfo-00&quot;&gt;&lt;code&gt;Cached_ContainerInfo_00&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This cache file describes the key container for more information about which keys are present. The &lt;code&gt;value_len&lt;&#x2F;code&gt; of the &lt;code&gt;CARD_FILE_HEADER&lt;&#x2F;code&gt; structure depends on the key inside of this container. You&#x27;ll see it further. Here is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L252-L312&quot;&gt;the example implementation&lt;&#x2F;a&gt;. It&#x27;s easier to follow the explanation when you have the code.&lt;&#x2F;p&gt;
&lt;p&gt;After the &lt;code&gt;CARD_FILE_HEADER&lt;&#x2F;code&gt; structure we have a 16-byte container info header. The purpose of the first 12 bytes is unknown to me, but the last 4 is the length of the rest of the data (which also depends on the container key). The actual data has the following format:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; This structure is assembled by me&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; _CONTAINER_INFO_DATA {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  PUBLICKEYSTRUC public_key_info;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  RSAPUBKEY rsa_pub_key;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  BYTE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;[]&lt;&#x2F;span&gt;&lt;span&gt; public_key_modulus;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} CONTAINER_INFO_DATA;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;wincrypt&#x2F;ns-wincrypt-publickeystruc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; _PUBLICKEYSTRUC {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  BYTE   bType;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  BYTE   bVersion;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  WORD   reserved;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ALG_ID aiKeyAlg;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} BLOBHEADER, PUBLICKEYSTRUC;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;wincrypt&#x2F;ns-wincrypt-rsapubkey&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; _RSAPUBKEY {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DWORD magic;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DWORD bitlen;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DWORD pubexp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} RSAPUBKEY;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Note.&lt;&#x2F;em&gt; If the &lt;code&gt;public_key_modulus&lt;&#x2F;code&gt; is smaller than the specified key length (for example, by one byte), then it should be padded with zeroes to match the key length.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;But you wrote above the smart card can have &lt;strong&gt;more than one&lt;&#x2F;strong&gt; key container. Which one should we use here?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It&#x27;s a trick question. I don&#x27;t know 😞. In my experience, I was working with smart cards that have only one key container.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cached-generalfile-mscp-kxc00&quot;&gt;&lt;code&gt;Cached_GeneralFile&#x2F;mscp&#x2F;kxc00&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In short, this cache file contains a compressed DER-encoded certificate usinf ZLIB compression. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L313-L330&quot;&gt;Example implementation&lt;&#x2F;a&gt;. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;compression.rs#L11&quot;&gt;Compression&lt;&#x2F;a&gt;. Of course, the &lt;code&gt;value_len&lt;&#x2F;code&gt; of the &lt;code&gt;CARD_FILE_HEADER&lt;&#x2F;code&gt; structure depends on the compressed data length. So, move on. The actual data has the following format:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; This structure is assembled by me&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; _CONTAINER_INFO_DATA {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  int16 flags;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  int16 uncompressed_cert_len;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  BYTE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;[]&lt;&#x2F;span&gt;&lt;span&gt; compressed_cert_len;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} CONTAINER_INFO_DATA;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I suppose the first two bytes should indicate if the certificate is compressed or not. But I didn&#x27;t find any evidence about it and just used extracted values from the real smart card.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Again. What certificate should we use?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This time I know 😝. In the specification, &lt;code&gt;kxc00&lt;&#x2F;code&gt; is &lt;em&gt;key exchange cert 0&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cached-cardproperty-capabilities-0&quot;&gt;&lt;code&gt;Cached_CardProperty_Capabilities_0&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This cache file describes the card and card-specific minidriver combination for the functionality that is provided at this level, such as a certificate or file compression. The &lt;code&gt;value_len&lt;&#x2F;code&gt; is equal to 12 in the &lt;code&gt;CARD_FILE_HEADER&lt;&#x2F;code&gt; structure and those 12 bytes represent &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;selfrender&#x2F;Windows-Server-2003&#x2F;blob&#x2F;5c6fe3db626b63a384230a1aa6b92ac416b0765f&#x2F;ds&#x2F;security&#x2F;csps&#x2F;wfsccsp&#x2F;inc&#x2F;cardmod.h#L138-L152&quot;&gt;the &lt;code&gt;CARD_CAPABILITIES&lt;&#x2F;code&gt; structure&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; CARD_CAPABILITIES_CURRENT_VERSION&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; _CARD_CAPABILITIES&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; The version of the structure that is being used.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    DWORD   dwVersion;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Set TRUE to indicate that the card minidriver implements its own compression of certificates.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    BOOL    fCertificateCompression;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Set TRUE to indicate that the card can generate keys.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    BOOL    fKeyGen;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} CARD_CAPABILITIES,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;PCARD_CAPABILITIES;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L331-L343&quot;&gt;Example implementation&lt;&#x2F;a&gt;. (&lt;em&gt;Just a reminder. In Windows, the &lt;code&gt;BOOL&lt;&#x2F;code&gt; type is 4-byte long&lt;&#x2F;em&gt; 😕)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cached-cardproperty-key-sizes-1&quot;&gt;&lt;code&gt;Cached_CardProperty_Key Sizes_1&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This cache file describes the different key length values that are available. The &lt;code&gt;value_len&lt;&#x2F;code&gt; is equal to 20 in the &lt;code&gt;CARD_FILE_HEADER&lt;&#x2F;code&gt; structure and those 20 bytes represent &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;selfrender&#x2F;Windows-Server-2003&#x2F;blob&#x2F;5c6fe3db626b63a384230a1aa6b92ac416b0765f&#x2F;ds&#x2F;security&#x2F;csps&#x2F;wfsccsp&#x2F;inc&#x2F;cardmod.h#L577-L591&quot;&gt;the &lt;code&gt;CARD_KEY_SIZES&lt;&#x2F;code&gt; structure&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; CARD_KEY_SIZES_CURRENT_VERSION&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; _CARD_KEY_SIZES&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    DWORD dwVersion;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    DWORD dwMinimumBitlen;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    DWORD dwDefaultBitlen;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    DWORD dwMaximumBitlen;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    DWORD dwIncrementalBitlen;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} CARD_KEY_SIZES,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;PCARD_KEY_SIZES;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L364-L381&quot;&gt;Example implementation&lt;&#x2F;a&gt;. Sometimes the driver can ask for the &lt;code&gt;Cached_CardProperty_Key Sizes_2&lt;&#x2F;code&gt; cache item. I&#x27;m not sure what this number means. Maybe it depends on the key container, maybe on some algorithm id. IDK 😓&lt;&#x2F;p&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h1&gt;
&lt;p&gt;I&#x27;m not sure what to conclude. The only thing that stuck in my head is that anything related to smart cards is complex, hard to implement&#x2F;understand, or find documentation. Anyway, we have no other choice than to live with what we have and try to improve it 😊&lt;&#x2F;p&gt;
&lt;p&gt;I hope if one day someone is stuck with a similar problem as me, then they&#x27;ll find this article and use it as a reference. I just don&#x27;t know who else might need such a detailed description of smart card cache files 😅&lt;&#x2F;p&gt;
&lt;h1 id=&quot;doc-references-code&quot;&gt;Doc, references, code&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;security&#x2F;identity-protection&#x2F;smart-cards&#x2F;smart-card-architecture&quot;&gt;Smart Card Architecture&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winscard&#x2F;&quot;&gt;&lt;code&gt;winscard.h&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;smartcard&#x2F;smart-card-minidrivers&quot;&gt;Smart Card Minidrivers&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;previous-versions&#x2F;windows&#x2F;hardware&#x2F;design&#x2F;dn631754(v=vs.85)&quot;&gt;Smart Card Minidriver Specification&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Implemented smart card caches: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Devolutions&#x2F;sspi-rs&#x2F;blob&#x2F;4409f9a5235dec0c033edce654aa6fe934a72afc&#x2F;crates&#x2F;winscard&#x2F;src&#x2F;scard_context.rs#L146-L394&quot;&gt;&lt;code&gt;scard_context.rs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;debuggercmds&#x2F;time-travel-debugging-overview&quot;&gt;Time Travel Debugging&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Debugging with API Monitor</title>
        <published>2023-07-28T00:00:00+00:00</published>
        <updated>2023-07-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/debugging-with-api-monitor/"/>
        <id>https://tbt.qkation.com/posts/debugging-with-api-monitor/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/debugging-with-api-monitor/">&lt;p&gt;The &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;www.rohitab.com&#x2F;apimonitor&quot;&gt;API Monitor&lt;&#x2F;a&gt; speaks for itself. It&#x27;s a great tool for the system API calls debugging, monitoring, information extraction, exploring. Especially in cases when you don&#x27;t know how exactly API works.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer&lt;&#x2F;strong&gt;. (If you don&#x27;t get it yet). Mentioned API Monitor is a tool for monitoring the system API calls. So, I you are back&#x2F;front-end dude which is not interested in such stuff, this article will not be useful for you.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;goals&quot;&gt;Goals&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;strong&gt;Goals:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Explain how to deal with cases when existing API definitions are not enough.&lt;&#x2F;li&gt;
&lt;li&gt;Show on the example how we can debug custom DLLs and how to write definitions for them.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Non-goals:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Write the &lt;em&gt;&quot;ultimate&quot;&lt;&#x2F;em&gt; guide to the &lt;code&gt;API Monitor&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Describe how the &lt;code&gt;API Monitor&lt;&#x2F;code&gt; works under the hood.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you are not familiar with the API Monitor, then I propose you reading the following articles:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;www.rohitab.com&#x2F;api-monitor-tutorial-monitoring-your-first-application&quot;&gt;Monitoring your first application&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;IjIfu1y1EdQ&quot;&gt;API Monitor (youtube video)&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The current article does not include API Monitor basics.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;let-s-debug-winscard-api&quot;&gt;Let&#x27;s debug WinSCard API&lt;&#x2F;h1&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;So, what problem or edge cases do you want to talk about?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I prefer example-based explanations, so we start from the API monitoring. And today&#x27;s target is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winscard&#x2F;&quot;&gt;WinSCard API&lt;&#x2F;a&gt;. In a short, it&#x27;s a Microsoft&#x27;s API for the communication with smart cards. I have a small program that uses smart card for some operations. Let&#x27;s assume I don&#x27;t know what exactly it&#x27;s doing or know what but don&#x27;t know how. Out task for now is to try to explore the API calls.&lt;&#x2F;p&gt;
&lt;p&gt;Start as usual:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Select only needed API.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
 &lt;img src=&quot;api-filter.png&quot; alt=&quot;API filter&quot; width=&quot;471&quot; height=&quot;430&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Run the executable in the API Monitor. Here is what I got:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
 &lt;img src=&quot;api-recording.png&quot; alt=&quot;API recording demo&quot; width=&quot;1920&quot; height=&quot;1021&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;p&gt;Cool. We see a lot of functions calls, their before and after parameters, flags, and much more. But here is one problem that blocks us from the further investigation: we don&#x27;t have recorded in- and outbound APDU messages.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note.&lt;&#x2F;em&gt; The APDU message - is the communication unit between a smart card reader and a smart card. More info: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Smart_card_application_protocol_data_unit&quot;&gt;wikipedia&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.yubico.com&#x2F;yesdk&#x2F;users-manual&#x2F;yubikey-reference&#x2F;apdu.html&quot;&gt;yubikey-reference&#x2F;apdu&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winscard&#x2F;nf-winscard-scardtransmit&quot;&gt;&lt;code&gt;ScardTransmit&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function has in- and outbound APDU messages and they defined in the function signature as follows 👇:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;LONG&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; SCardTransmit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;font-style: italic;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt;]                SCARDHANDLE         hCard,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [in]                LPCSCARD_IO_REQUEST pioSendPci,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [in]                LPCBYTE             pbSendBuffer, &#x2F;&#x2F; inbound APDU message buffer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [in]                DWORD               cbSendLength,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [in, out, optional] LPSCARD_IO_REQUEST  pioRecvPci,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [out]               LPBYTE              pbRecvBuffer, &#x2F;&#x2F; outbound APDU message buffer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [in, out]           LPDWORD             pcbRecvLength&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From the function definition we can see that buffers length is defined in the &lt;code&gt;cbSendLength&lt;&#x2F;code&gt; and &lt;code&gt;pcbRecvLength&lt;&#x2F;code&gt; parameters. So, it&#x27;s logical to assume that API Monitor will capture those buffers during the recording because lengths are known. But unfortunately, we have only pointer value recorded.&lt;&#x2F;p&gt;
 &lt;img src=&quot;scardtransmit.png&quot; alt=&quot;SCardTransmit&quot; width=&quot;1456&quot; height=&quot;662&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Why it&#x27;s happening? The API Monitor captures buffers with defined (known) length as I remember from the documentation.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The answer is in the next section.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;time-to-fix-xml-definitions&quot;&gt;Time to fix XML definitions&lt;&#x2F;h1&gt;
&lt;p&gt;To answer the previous question, lets ask a new one: how the API Monitor even parse and recognize the API functions, parameters, etc? Of course, here is no any magic, but XML definitions 😔 . Basically, the API Monitor has XML file for every supported library with defined API in it.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;So, maybe we can just edit existing XML for the WinSCard API and record the buffers?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Exactly. Someone who wrote the XML definition for the WinSCard didn&#x27;t put enough attention and wrote them somehow.&lt;&#x2F;p&gt;
&lt;p&gt;Initially, I read about fixing those XML definitions in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.mysmartlogon.com&#x2F;knowledge-base&#x2F;trace-apdu-on-windows&#x2F;&quot;&gt;this&lt;&#x2F;a&gt; article. I was surprised that only very little devs know about it and how to use it.&lt;&#x2F;p&gt;
&lt;p&gt;Okay, enough talking, time to fix the code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&amp;lt;!-- File: C:\Program Files\rohitab.com\API Monitor\API\Headers\scard.h.xml --&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&amp;lt;!-- [SCARD_DISPOSITION] --&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;[SCARD_DISPOSITION]&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Alias&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Base&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;LONG&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Display&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;LONG&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Set&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;SCARD_LEAVE_CARD&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;              Value&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Set&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;SCARD_RESET_CARD&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;              Value&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Set&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;SCARD_UNPOWER_CARD&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;            Value&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;2&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Set&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;SCARD_EJECT_CARD&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;              Value&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;3&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&amp;lt;!-- File: C:\Program Files\rohitab.com\API Monitor\API\Windows\WinSCard.xml --&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Api&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;SCardDisconnect&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;SCARDHANDLE&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;hCard&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;[SCARD_DISPOSITION]&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;dwDisposition&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;[SCARD_ERROR]&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Api&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Api&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;SCardEndTransaction&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;SCARDHANDLE&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;hCard&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;[SCARD_DISPOSITION]&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;dwDisposition&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;[SCARD_ERROR]&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Api&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Api&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;SCardTransmit&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;SCARDHANDLE&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;hCard&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;LPCSCARD_IO_REQUEST&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;pioSendPci&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;LPCBYTE&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;pbSendBuffer&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Count&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;cbSendLength&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;DWORD&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;cbSendLength&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;LPSCARD_IO_REQUEST&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;pioRecvPci&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;LPBYTE&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;pbRecvBuffer&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; PostCount&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;pcbRecvLength&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;LPDWORD&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;pcbRecvLength&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;[SCARD_ERROR]&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Api&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Note.&lt;&#x2F;strong&gt; You will have other paths if you installed the API Monitor in the non-default location.&lt;&#x2F;p&gt;
&lt;p&gt;You can compare old and new XML and see the difference. Now all should work. Let&#x27;s try again to record API calls. Here is my result:&lt;&#x2F;p&gt;
 &lt;img src=&quot;scardtransmit_with_buffer.png&quot; alt=&quot;SCardTransmit with buffer&quot; width=&quot;1920&quot; height=&quot;1022&quot; loading=&quot;lazy&quot; &#x2F;&gt;
 &lt;img src=&quot;scardtransmit_with_out_buffer.png&quot; alt=&quot;SCardTransmit with buffer&quot; width=&quot;1449&quot; height=&quot;462&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;p&gt;Congratulations 🌺 . Now it works well and we can observe input and output buffers.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-if-we-have-a-custom-dll-to-monitor&quot;&gt;What if we have a custom DLL to monitor?&lt;&#x2F;h1&gt;
&lt;p&gt;Firstly, I was not planned to write this section. But if I touched fixing XML definitions then it&#x27;s obviously fun to write definitions for our custom library and try to debug it.&lt;&#x2F;p&gt;
&lt;p&gt;But before actual debugging, let&#x27;s write the program and dll itself. I suggest a simple task:&lt;&#x2F;p&gt;
&lt;p&gt;Look at this site: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;imgur.com&quot;&gt;https:&#x2F;&#x2F;imgur.com&lt;&#x2F;a&gt;. &lt;em&gt;Imgur&lt;&#x2F;em&gt; is an American online image-sharing and image-hosting service. It has an &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;apidocs.imgur.com&#x2F;&quot;&gt;API&lt;&#x2F;a&gt;. Let&#x27;s write a library that encapsulates API calls and provides us with a simple interface for communication with Imgur. I plan to implement only two functions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ImgurInitClient&lt;&#x2F;code&gt;: initializes the Imgur client (or context).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ImgurGetComment&lt;&#x2F;code&gt;: retrieves the comment information based on its id.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And in order to make a more &quot;real&quot; example, I&#x27;ll pack Rust code into the dll and call its functions from the C++ code.&lt;&#x2F;p&gt;
&lt;div class=&quot;mermaid&quot;&gt;
flowchart TD
    A[C++ code] --&amp;gt; dll[dll]

subgraph dll
    C[Rust FFI bindings] --&amp;gt; D[Rust Imgur API client]
end
&lt;&#x2F;div&gt;&lt;h2 id=&quot;write-a-program-and-dll&quot;&gt;Write a program and dll&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; this section contains a lot of code. There is no point to read it very carefully. You should just have a rough idea of what it does.&lt;&#x2F;p&gt;
&lt;p&gt;Good. We have a purpose but don&#x27;t have any obstacles. Firstly, we need to write a pure Rust implementation. There is no point to explain it in detail, so I just paste the code below:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; The Imgur API client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; ImgurApi&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Imgur application client ID&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    client_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Imgur application client secret&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    _client_secret&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; ImgurApi&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Initializes the Imgur API client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; init&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;I&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;client_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; I&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; _client_secret&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt; Self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;        String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; From&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;I&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;        String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; From&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;S&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;        Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            client_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; client_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;            _client_secret&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; _client_secret&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Retrieves the comment information based on its id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; comment&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; comment_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; ImgurResult&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Comment&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; raw_comment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Client&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;https:&#x2F;&#x2F;api.imgur.com&#x2F;3&#x2F;comment&#x2F;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; comment_id&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;header&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;AUTH_HEADER&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Client-ID {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;font-weight: bold;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;client_id))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; comment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Comment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; serde_json&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from_slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;raw_comment&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;comment&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The full &lt;code&gt;imgur-api-client&lt;&#x2F;code&gt; code: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;c42f4d809849e9475e0d3fb72afbc2d0d18b6732&#x2F;debugging-with-api-monitor&#x2F;imgur-api-client&quot;&gt;@TheBestTvarynka&#x2F;trash-code&#x2F;@c42f4d80&#x2F;debugging-with-api-monitor&#x2F;imgur-api-client&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;After that, the next step is to write a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nomicon&#x2F;ffi.html&quot;&gt;FFI bindings&lt;&#x2F;a&gt;. It&#x27;s not hard because we have two small functions to export:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[no_mangle]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Initializes the Imgur API client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; We return the `*mut c_void` pointer because we don&amp;#39;t want to expose the internal context structure to users&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub unsafe extern&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;C&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; ImgurInitClient&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;client_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; c_char&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; client_secret&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; c_char&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt; *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; c_void&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; client_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; CStr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from_ptr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;client_id&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; client_secret&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; CStr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from_ptr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;client_secret&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; ImgurApi&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;init&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;client_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_str&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; client_secret&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;to_str&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Box&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;into_raw&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; _&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Retrieves the comment information based on its id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[no_mangle]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub unsafe extern&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;C&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; ImgurGetComment&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; c_void&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; comment_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; c_ulonglong&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; comment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: *mut *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; FiiComment&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;ImgurApi&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;from_raw&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt; );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; context&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;comment&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;comment_id&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;comment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;into_raw&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;()));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;        1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And of course, the full &lt;code&gt;imgur-api-dll&lt;&#x2F;code&gt; code you can find here: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;c42f4d809849e9475e0d3fb72afbc2d0d18b6732&#x2F;debugging-with-api-monitor&#x2F;imgur-api-dll&quot;&gt;@TheBestTvarynka&#x2F;trash-code&#x2F;@c42f4d80&#x2F;debugging-with-api-monitor&#x2F;imgur-api-dll&lt;&#x2F;a&gt;. When you build this crate, you&#x27;ll find the &lt;code&gt;imgur_api.dll&lt;&#x2F;code&gt; file in the &lt;code&gt;target&#x2F;debug&#x2F;&lt;&#x2F;code&gt; directory.&lt;&#x2F;p&gt;
&lt;p&gt;Good. And the last part is a C++ code that loads our dll and calls its functions. Before it, we need to generate the &lt;code&gt;.h&lt;&#x2F;code&gt; file with our structures and functions. Sure, with such a small example, we can do it manually. But I wanna show you an easier way: I&#x27;ll use the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mozilla&#x2F;cbindgen&quot;&gt;&lt;code&gt;cbindgen&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Run the following command in the terminal from the &lt;code&gt;imgur-api-dll&lt;&#x2F;code&gt; crate location:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;cbindgen&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --crate&lt;&#x2F;span&gt;&lt;span&gt; imgur-api-dll&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --output&lt;&#x2F;span&gt;&lt;span&gt; imgur_api.h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As a result, you&#x27;ll get the &lt;code&gt;imgur_api.h&lt;&#x2F;code&gt; file ready for use in the C++ project. I&#x27;ll need the types of functions, so I add them manually:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef void*&lt;&#x2F;span&gt;&lt;span&gt; (ImgurInitClientFn)(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; char*&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; char*&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef uint32_t&lt;&#x2F;span&gt;&lt;span&gt; (ImgurGetCommentFn)(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;void*&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; unsigned long long&lt;&#x2F;span&gt;&lt;span&gt;, FiiComment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The full &lt;code&gt;imgur_api.h&lt;&#x2F;code&gt; file: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;blob&#x2F;a333b128ac66a128a4a98c7fb503004812053cb8&#x2F;debugging-with-api-monitor&#x2F;imgur-api-dll&#x2F;imgur_api.h&quot;&gt;@TheBestTvarynka&#x2F;trash-code&#x2F;@a333b128&#x2F;debugging-with-api-monitor&#x2F;imgur-api-dll&#x2F;imgur_api.h&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, we can write our C++ program. I&#x27;m not much of a C++ dev, so don&#x27;t judge me, please.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; code listed below is simplified and some lines are omitted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; follow the link under this snippet to read the full src code&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;HMODULE imgur &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; LoadLibraryA&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;imgur_api.dll&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;FARPROC ImgurInitClientAddress &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; GetProcAddress&lt;&#x2F;span&gt;&lt;span&gt;(imgur,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;ImgurInitClient&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;FARPROC ImgurGetCommentAddress &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; GetProcAddress&lt;&#x2F;span&gt;&lt;span&gt;(imgur,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;ImgurGetComment&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; char*&lt;&#x2F;span&gt;&lt;span&gt; client_id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;3d8012c2f66acfb&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; char*&lt;&#x2F;span&gt;&lt;span&gt; client_secret &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;708d779959d043dd6da2d158abaa022931f708a8&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;void*&lt;&#x2F;span&gt;&lt;span&gt; context &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; ((ImgurInitClientFn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;)ImgurInitClientAddress)(client_id, client_secret);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;unsigned long long&lt;&#x2F;span&gt;&lt;span&gt; comment_id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1911999579&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;FiiComment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; comment &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; nullptr&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;uint32_t&lt;&#x2F;span&gt;&lt;span&gt; status &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; ((ImgurGetCommentFn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;)ImgurGetCommentAddress)(context, comment_id,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;comment);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;status) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cout &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;Success! Comment data:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cout &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;id: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; comment&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; endl;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; some lines are omitted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cout &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;Error: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; status &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; endl;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; don&#x27;t worry about credentials in the code. I&#x27;ve already deleted this application from my Imgur account. So everything is fine.&lt;&#x2F;p&gt;
&lt;p&gt;Read the full src code here: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;a333b128ac66a128a4a98c7fb503004812053cb8&#x2F;debugging-with-api-monitor&#x2F;TestImgurDll&quot;&gt;@TheBestTvarynka&#x2F;trash-code&#x2F;@a333b128&#x2F;debugging-with-api-monitor&#x2F;TestImgurDll&lt;&#x2F;a&gt;. Basically, our program has three main parts:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Initialization: here we obtain module handle and pointers of functions.&lt;&#x2F;li&gt;
&lt;li&gt;Comment information retrieving.&lt;&#x2F;li&gt;
&lt;li&gt;Print the result of the execution.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Pretty simple, I think. If you run this program, you should get smth like this:&lt;&#x2F;p&gt;
 &lt;img src=&quot;TestImgurApiDll-execution.png&quot; alt=&quot;TestImgurApiDll execution&quot; width=&quot;1068&quot; height=&quot;579&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;p&gt;Now we have a working program that uses custom external DLL. Perfect. The most interesting and fun part begins in the next section.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;writing-xml-definitions&quot;&gt;Writing XML definitions&lt;&#x2F;h2&gt;
&lt;p&gt;There are no official guides on how to write such XML definitions. I just explored existing XMLs in the &lt;code&gt;C:\Program Files\rohitab.com\API Monitor\API&lt;&#x2F;code&gt; directory and wrote my own for the &lt;code&gt;imgur_api.dll&lt;&#x2F;code&gt;. Here is my shitty XML:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;ApiMonitor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Filename&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Headers\windows.h.xml&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Module&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;imgur_api.dll&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; CallingConvention&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;STDCALL&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Category&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Imgur&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;FfiCommentData&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Struct&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;UINT64&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;id&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;const char*&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;image_id&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;const char*&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;comment&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;const char*&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;author&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;UINT64&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;author_id&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;char&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;on_album&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;const char*&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;album_cover&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;UINT32&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;ups&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;UINT32&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;downs&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;UINT32&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;points&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;UINT32&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;datetime&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;UINT64&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;parent_id&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;char&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;deleted&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;char&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;is_voted&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;char&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;vote&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;const char*&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;platform&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;char&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;has_admin_badge&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;UINT64*&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;children&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;UINT32&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;children_len&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;FfiComment&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Struct&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;FfiCommentData&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;data&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;UINT32&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;status&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Field&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;char&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;success&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;FfiComment*&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Pointer&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Base&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;FfiComment&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;FfiComment**&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Pointer&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Base&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;FfiComment*&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Api&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;ImgurInitClient&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;const char*&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;client_id&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;const char*&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;client_secret&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;void*&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Api&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Api&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;ImgurGetComment&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;void*&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;context&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;unsigned long&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;comment_id&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;FfiComment**&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;comment&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;UINT32&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Api&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Module&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;ApiMonitor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Why &quot;shitty&quot;?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I don&#x27;t like XML at all. So, for me, every XML is shitty.&lt;&#x2F;p&gt;
&lt;p&gt;The file with the src code: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;blob&#x2F;a333b128ac66a128a4a98c7fb503004812053cb8&#x2F;debugging-with-api-monitor&#x2F;imgur_api.xml&quot;&gt;@TheBestTvarynka&#x2F;trash-code&#x2F;@a333b128&#x2F;debugging-with-api-monitor&#x2F;imgur_api.xml&lt;&#x2F;a&gt;. The code above looks pretty simple and easy to understand, but I&#x27;ll give you some advice on how not to face problems:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If the loaded definitions don&#x27;t have all functions or don&#x27;t have any at all, then they are probably invalid and you need to fix the XML. The API Monitor will not show you any message about what does wrong. For example, it&#x27;ll not tell you that the function uses an unknown param type. It&#x27;ll just ignore this function.&lt;&#x2F;li&gt;
&lt;li&gt;You can split types and variables definitions into &lt;code&gt;.h.xml&lt;&#x2F;code&gt; and &lt;code&gt;.xml&lt;&#x2F;code&gt; files. The idea is obvious: you can include &lt;code&gt;.h.xml&lt;&#x2F;code&gt; files in other API definitions. In such a way you can reduce the code duplication.&lt;&#x2F;li&gt;
&lt;li&gt;If you have the defined &lt;code&gt;MyStruct&lt;&#x2F;code&gt; structure, that does not mean that you automatically have the &lt;code&gt;MyStruct*&lt;&#x2F;code&gt; and &lt;code&gt;MyStruct**&lt;&#x2F;code&gt; pointer types. You should also define pointer types as I did in the code above for the &lt;code&gt;FfiComment**&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Why did I use the &lt;code&gt;char&lt;&#x2F;code&gt; instead of &lt;code&gt;BOOL&lt;&#x2F;code&gt;? The defined &lt;code&gt;BOOL&lt;&#x2F;code&gt; type has a 4-byte len but I need only one byte:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&amp;lt;!-- C:\Program Files\rohitab.com\API Monitor\API\Headers\common.h.xml --&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;BOOL&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Integer&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Size&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;4&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; DefaultName&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;TRUE&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Set&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;TRUE&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    Value&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Set&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;FALSE&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;   Value&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Success&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Return&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;NotEqual&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; Value&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;Variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So I decided just to use &lt;code&gt;char&lt;&#x2F;code&gt;. It&#x27;s enough for us.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;debugging&quot;&gt;Debugging&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;How to tell the API Monitor about our new API?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Just place the file into the &lt;code&gt;API&lt;&#x2F;code&gt; directory. On the next API Monitor start it&#x27;ll load all API definitions again, including our new one. For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;C:\Program Files\rohitab.com\API Monitor\API\Imgur\imgur_api.xml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you did everything right, then you should get smth like this:&lt;&#x2F;p&gt;
 &lt;img src=&quot;imgur_api_filter.png&quot; alt=&quot;Imgur API filter&quot; width=&quot;460&quot; height=&quot;758&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;p&gt;Now let&#x27;s debug the test application we wrote before. Start it as a usual process monitoring. Here is my result:&lt;&#x2F;p&gt;
 &lt;img src=&quot;monitoring_summary.png&quot; alt=&quot;Monitoring summary&quot; width=&quot;1920&quot; height=&quot;313&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;p&gt;Now we can fully observe what has been passed into and returned from our functions. Also, we compare the API Monitor values with those printed in the terminal to ensure that we did nothing wrong in the XML definitions.&lt;&#x2F;p&gt;
 &lt;img src=&quot;imgur_init_client.png&quot; alt=&quot;ImgurInitClient function call&quot; width=&quot;1920&quot; height=&quot;441&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;p&gt;On the screenshot above you can see secrets passed to the init function. Just like I saw passwords and emails during debugging the Windows SSPI 😜.&lt;&#x2F;p&gt;
 &lt;img src=&quot;imgur_get_comment.png&quot; alt=&quot;ImgurGetComment function call&quot; width=&quot;1920&quot; height=&quot;870&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;p&gt;Cool 😎. The values are the same as in the terminal.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;references-final-note&quot;&gt;References &amp;amp; final note&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.mysmartlogon.com&#x2F;knowledge-base&#x2F;trace-apdu-on-windows&#x2F;&quot;&gt;Trace APDU on Windows&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;www.rohitab.com&#x2F;discuss&#x2F;topic&#x2F;37197-api-monitor-v2-r6-release-process-memory-editor-unions-and-arrays&#x2F;&quot;&gt;Process memory editor, Unions and Arrays&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nomicon&#x2F;ffi.html&quot;&gt;Rustonomicon - Foreign Function Interface&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;michael-f-bryan.github.io&#x2F;rust-ffi-guide&#x2F;&quot;&gt;The (unofficial) Rust FFI Guide&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Sometimes our tools are capable of much more than we think. Maybe something you&#x27;re searching for is just around the corner.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Rust Clap recipes</title>
        <published>2023-06-15T00:00:00+00:00</published>
        <updated>2023-06-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/clap-recipes/"/>
        <id>https://tbt.qkation.com/posts/clap-recipes/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/clap-recipes/">&lt;p&gt;I bet you know, but I still wanna recall it. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;clap-rs&#x2F;clap&quot;&gt;&lt;code&gt;Clap&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is a full-featured, fast Command Line Argument Parser for Rust. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;clap&#x2F;latest&#x2F;clap&#x2F;&quot;&gt;docs.rs&lt;&#x2F;a&gt;. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;clap&quot;&gt;crates.io&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;goals&quot;&gt;Goals&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;strong&gt;Goals:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Show non-standard examples of the cli arguments configuration.&lt;&#x2F;li&gt;
&lt;li&gt;Tell you about alternate ways to parse cli args with the &lt;code&gt;clap&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Non-goals:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Write the &lt;em&gt;&quot;ultimate&quot;&lt;&#x2F;em&gt; guide to the &lt;code&gt;clap&lt;&#x2F;code&gt; library.&lt;&#x2F;li&gt;
&lt;li&gt;Create an introduction (or for newbies) article about the clap.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The current article is basically a recipe. It means that here we have described concrete problems, ways to solve them, and examples of their execution.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;recipes&quot;&gt;Recipes&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;collecting-multiple-values&quot;&gt;Collecting multiple values&lt;&#x2F;h2&gt;
&lt;p&gt;Imagine the following situation: you are writing some server. It can be the server-side of some protocol, a proxy server, or something like that. At some point, you decided to add encryption. Now you need to add the ability for the user to pass allowed encryption algorithms (ciphers) for server sessions.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s try to do it. The first idea that comes to mind is just to use a vector of strings:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Server config structure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Parser&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Allowed encryption algorithms list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[arg(long, value_name &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;ENCRYPTION ALGORITHMS&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; enc_algs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Note 1:&lt;&#x2F;strong&gt; personally, I prefer the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;clap&#x2F;latest&#x2F;clap&#x2F;_derive&#x2F;index.html&quot;&gt;&lt;em&gt;derive&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; approach to configure clap instead of a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;clap&#x2F;latest&#x2F;clap&#x2F;index.html&quot;&gt;&lt;em&gt;builder&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; approach.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Note 2:&lt;&#x2F;strong&gt; For all examples in this article, I use the same &lt;code&gt;main&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Just prints the server configuration.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; `Config` is a previously defined structure (like in the example above).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;{:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Config&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;ll work. Here is an example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;cool-server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; aes256&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; des3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; thebesttvarynka &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Config { enc_algs: [&amp;quot;aes256&amp;quot;, &amp;quot;des3&amp;quot;, &amp;quot;thebesttvarynka&amp;quot;] }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Good, but here we have a big problem: values are not validated, and the user can specify unsupported or just wrong algorithms. Let&#x27;s delegate algorithm validation to &lt;code&gt;clap&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;First, we need to implement the &lt;code&gt;Cipher&lt;&#x2F;code&gt; enum. Most likely, you&#x27;ll have such an enum already implemented in the project, but here we need to write it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;, clap&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;ValueEnum&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Cipher&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Aes128&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Aes256&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Des3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; The next traits implementations are omitted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; and left for the reader as a homework 😝&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; impl AsRef&amp;lt;str&amp;gt; for Cipher { ... }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; impl Display for Cipher { ... }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; impl TryFrom&amp;lt;&amp;amp;str&amp;gt; for Cipher { ... }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Pay attention&lt;&#x2F;strong&gt; that we also added the &lt;code&gt;clap::ValueEnum&lt;&#x2F;code&gt; derive. It&#x27;ll generate the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;clap&#x2F;latest&#x2F;clap&#x2F;trait.ValueEnum.html&quot;&gt;&lt;code&gt;ValueEnum&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; trait implementation, and &lt;code&gt;clap&lt;&#x2F;code&gt; will be able to parse the raw string into a concrete enum value. Now time to test it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;cool-server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; aes256&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; des3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Config { enc_algs: [Aes256, Des3] }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;cool-server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; aes256&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; des3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; thebesttvarynka&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# error: invalid value &amp;#39;thebesttvarynka&amp;#39; for &amp;#39;--enc-algs &amp;lt;ENCRYPTION ALGORITHMS&amp;gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   [possible values: aes128, aes256, des3]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# For more information, try &amp;#39;--help&amp;#39;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Very cool 🔥. Clap validates the input for us and even tells the user possible values if smth goes wrong. You can read all code of the example above &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;commit&#x2F;f5bffb732b3f79a2ef00f83e335ae80125fa0294&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In general, we can finish this recipe at this point, but I used to specify multiple values using a comma-separated string. The perfect arg looks to me like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;cool-server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; aes256,des3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# or even&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;cool-server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; aes256:des3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;&quot;This move will cost us&quot;&lt;&#x2F;em&gt; some additional code writing 🥲. We need to create a wrapper over the &lt;code&gt;Vec&amp;lt;Cipher&amp;gt;&lt;&#x2F;code&gt; and implement parsing for it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; EncAlgorithms&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Cipher&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Implementation of this trait is left for the reader.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; impl fmt::Display for EncAlgorithms { ... }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; parse_encryption_algorithms&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;raw_enc_algorithms&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;EncAlgorithms&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; parsed_enc_algs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; raw_enc_alg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; raw_enc_algorithms&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;#39;:&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;| !&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;is_empty&lt;&#x2F;span&gt;&lt;span&gt;()) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        parsed_enc_algs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;raw_enc_alg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;try_into&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; parsed_enc_algs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;is_empty&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;ErrorKind&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;InvalidValue&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;EncAlgorithms&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;parsed_enc_algs&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And only after this, we can use it in our configuration:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Server config structure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Parser&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Allowed encryption algorithms list (separated by &amp;#39;:&amp;#39;).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[arg(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        long,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        value_name &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;ENCRYPTION ALGORITHMS LIST&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;        &#x2F;&#x2F; https:&#x2F;&#x2F;docs.rs&#x2F;clap&#x2F;latest&#x2F;clap&#x2F;struct.Arg.html#method.value_parser&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        value_parser &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; ValueParser&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;new(parse_encryption_algorithms),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        default_value_t &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; EncAlgorithms&lt;&#x2F;span&gt;&lt;span&gt;(vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Cipher&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Aes256&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Cipher&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Aes128&lt;&#x2F;span&gt;&lt;span&gt;]),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; enc_algs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; EncAlgorithms&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Why should we create the wrapper? Why is custom parser + &lt;code&gt;Vec&amp;lt;Cipher&amp;gt;&lt;&#x2F;code&gt; not enough?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Yes, you can write just &lt;code&gt;Vec&amp;lt;Cipher&amp;gt;&lt;&#x2F;code&gt; with custom &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;clap&#x2F;latest&#x2F;clap&#x2F;struct.Arg.html#method.value_parser&quot;&gt;&lt;code&gt;value_parser&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and it&#x27;ll compile. But it&#x27;ll fail at runtime with the following error:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;thread &amp;#39;main&amp;#39; panicked at &amp;#39;Mismatch between definition and access of `enc_algs`. Could not downcast to cool_server::cipher::Cipher, need to downcast to alloc::vec::Vec&amp;lt;cool_server::cipher::Cipher&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;, src&#x2F;main.rs:37:19&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Understandable.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Let&#x27;s try to run the implementation with a wrapper:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;cool-server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; aes256:des3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Config { enc_algs: EncAlgorithms([Aes256, Des3]) }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;cool-server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; aes256:des3:thebesttvarynka&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# error: invalid value &amp;#39;aes256:des3:thebesttvarynka&amp;#39; for &amp;#39;--enc-algs &amp;lt;ENCRYPTION ALGORITHMS LIST&amp;gt;&amp;#39;: error: invalid value &amp;#39;Invalid algorithm name: thebesttvarynka&amp;#39; for &amp;#39;enc-algs&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# For more information, try &amp;#39;--help&amp;#39;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;cool-server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Server config structure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Usage: cool-server [OPTIONS]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Options:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#       --enc-algs &amp;lt;ENCRYPTION ALGORITHMS LIST&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#           Allowed encryption algorithms list (separated by &amp;#39;:&amp;#39;) [default: aes256:aes128]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   -h, --help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#           Print help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The full &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;commit&#x2F;9154610b4ce2343d38ab51abbbe8b5953b35bd61&quot;&gt;src&lt;&#x2F;a&gt; code of the example above.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Okay, but are you sure that we can&#x27;t do better? I am still thinking about a better solution.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;IDK 😕. Let&#x27;s explore the docs more thoroughly... Oh, it turns out it&#x27;s called the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;clap&#x2F;latest&#x2F;clap&#x2F;struct.Arg.html#method.value_delimiter&quot;&gt;value_delimiter&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Server config structure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Parser&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Allowed encryption algorithms list (separated by &amp;#39;:&amp;#39; or space).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[arg(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        long,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        value_name &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;CIPHERS&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        default_values_t &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Cipher&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Aes256&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        value_delimiter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;#39;:&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        num_args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;        &#x2F;&#x2F; at least one allowed cipher type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; enc_algs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Cipher&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Good job. It&#x27;s way better now.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Yep. With this approach, we remove all custom parsing and formatting stuff. Moreover, the help message and error reporting became better:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;cool-server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Server config structure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Usage: cool-server [OPTIONS]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Options:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#       --enc-algs &amp;lt;CIPHERS&amp;gt;...  Allowed encryption algorithms list (separated by &amp;#39;:&amp;#39; or space) [default: aes256] [possible values: aes128, aes256, des3]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   -h, --help                   Print help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;cool-server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; aes256:des3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Config { enc_algs: [Aes256, Des3] }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;cool-server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --enc-algs&lt;&#x2F;span&gt;&lt;span&gt; aes256:des4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# error: invalid value &amp;#39;des4&amp;#39; for &amp;#39;--enc-algs &amp;lt;CIPHERS&amp;gt;...&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   [possible values: aes128, aes256, des3]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   tip: a similar value exists: &amp;#39;des3&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# For more information, try &amp;#39;--help&amp;#39;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The full &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;commit&#x2F;eae20b208693f6dafeb7910fd8b26ca24987937b&quot;&gt;src&lt;&#x2F;a&gt; code of the example above.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;commands-and-arg-groups&quot;&gt;Commands and arg groups&lt;&#x2F;h2&gt;
&lt;p&gt;Before we start this recipe, I wanna recall one thing: the difference between commands and args. First of all, commands don&#x27;t contain any dashes or slashes in their names. They are just words. Commands specify &lt;strong&gt;what&lt;&#x2F;strong&gt; to do, whereas args specify &lt;strong&gt;how&lt;&#x2F;strong&gt; to do it. Example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;gcloud&lt;&#x2F;span&gt;&lt;span&gt; auth login&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --cred-file&lt;&#x2F;span&gt;&lt;span&gt; creds.json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# What to do? `login`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# How to do it? By taking a file with creds named `creds.json`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this recipe, we&#x27;ll work with commands and args. You&#x27;ll see a more complex example of the &lt;code&gt;clap&lt;&#x2F;code&gt; configuration.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Interesting. What do we need to configure? 😄&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;We all know the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;imgur.com&#x2F;&quot;&gt;Imgur&lt;&#x2F;a&gt; site (if not, then just visit). It has an &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;api.imgur.com&#x2F;&quot;&gt;API&lt;&#x2F;a&gt;. Let&#x27;s imagine we decided to write a CLI tool to help us work with the &lt;em&gt;Imgur&lt;&#x2F;em&gt; site using its API. So, now we need to design the tool interface. We do not plan to cover the whole API. Just downloading and uploading. A quick draft configuration:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Subcommand&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Command&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Upload&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Download&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Img tool config structure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Parser&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; command to execute&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[command(subcommand)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; command&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Command&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Path to the api key file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[arg(long, env &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;API-KEY&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; api_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; PathBuff&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We immediately have a few interesting moments: the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;clap&#x2F;latest&#x2F;clap&#x2F;trait.Subcommand.html&quot;&gt;Subcommand&lt;&#x2F;a&gt; trait derive and the &lt;code&gt;PathBuff&lt;&#x2F;code&gt; type in the &lt;code&gt;api_key&lt;&#x2F;code&gt; field. We are not forced to use only simple types for args like &lt;code&gt;String&lt;&#x2F;code&gt;s, numbers, etc. If you have a concrete type that describes your value (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;path&#x2F;struct.PathBuf.html&quot;&gt;&lt;code&gt;PathBuff&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for file path, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;url&#x2F;latest&#x2F;url&#x2F;struct.Url.html&quot;&gt;&lt;code&gt;url::Url&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for URLs, or even custom ones), then use this type in the configuration. It&#x27;ll handle more errors during parsing and make further work easier.&lt;&#x2F;p&gt;
&lt;p&gt;Now we add params for downloading the command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Subcommand&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Command&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Upload&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Download&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;        &#x2F;&#x2F;&#x2F; Source image link&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        #[arg(long)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        link&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Url&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;  &#x2F;&#x2F; &amp;lt;--- Pay attention to the type. We use the `Url` here and not the `String`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;        &#x2F;&#x2F;&#x2F; Path for the image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        #[arg(long)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        dest_file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; PathBuf&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To download the image, we need only two things: the source image link and the destination file path. This is how it works:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;img-tool&lt;&#x2F;span&gt;&lt;span&gt; download&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Usage: img-tool --api-key &amp;lt;API_KEY&amp;gt; download --link &amp;lt;LINK&amp;gt; --dest-file &amp;lt;DEST_FILE&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Options:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#       --link &amp;lt;LINK&amp;gt;            Source image link&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#       --dest-file &amp;lt;DEST_FILE&amp;gt;  Path for the image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   -h, --help                   Print help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;img-tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --api-key&lt;&#x2F;span&gt;&lt;span&gt; key.json download&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --link&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;imgur.com&#x2F;gallery&#x2F;vNOUshX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --dest-file&lt;&#x2F;span&gt;&lt;span&gt; ferris.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Config { command: Download { link: Url { scheme: &amp;quot;https&amp;quot;, cannot_be_a_base: false, username: &amp;quot;&amp;quot;, password: None, host: Some(Domain(&amp;quot;imgur.com&amp;quot;)), port: None, path: &amp;quot;&#x2F;gallery&#x2F;vNOUshX&amp;quot;, query: None, fragment: None }, dest_file: &amp;quot;ferris.png&amp;quot; }, api_key: &amp;quot;key.json&amp;quot; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;img-tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --api-key&lt;&#x2F;span&gt;&lt;span&gt; key.json download&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --link&lt;&#x2F;span&gt;&lt;span&gt; :imgur.com&#x2F;gallery&#x2F;vNOUshX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --dest-file&lt;&#x2F;span&gt;&lt;span&gt; ferris.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# error: invalid value &amp;#39;:imgur.com&#x2F;gallery&#x2F;vNOUshX&amp;#39; for &amp;#39;--link &amp;lt;LINK&amp;gt;&amp;#39;: relative URL without a base&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# For more information, try &amp;#39;--help&amp;#39;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Cool and pretty simple. But the upload is a little bit more complex. We wanna have two options to take the photo to upload: file image on the device or any public URL on the Internet. Here is the configuration for the upload command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Args&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[group(required &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; true, args &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;file&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;link&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;])]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Possible types of the file source&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; FileSource&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Path to the image on the device&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[arg(long)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;PathBuf&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Url to the image on the Internet&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[arg(long)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    link&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Url&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Subcommand&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Command&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Upload&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;        &#x2F;&#x2F;&#x2F; File to upload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        #[command(flatten)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        file_source&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; FileSource&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;        &#x2F;&#x2F;&#x2F; Folder for the image on the site&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        #[arg(long)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        folder&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Download&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt; &#x2F;* omitted *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Okay, we have two file sources: a file or a link. And we use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;clap&#x2F;latest&#x2F;clap&#x2F;struct.ArgGroup.html&quot;&gt;ArgGroup&lt;&#x2F;a&gt; to require the user to specify only one of them: either file or link. And here is the demo:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;img-tool&lt;&#x2F;span&gt;&lt;span&gt; upload&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Possible types of the file source&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Usage: img-tool --api-key &amp;lt;API_KEY&amp;gt; upload --folder &amp;lt;FOLDER&amp;gt; &amp;lt;--file &amp;lt;FILE&amp;gt;|--link &amp;lt;LINK&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Options:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#       --file &amp;lt;FILE&amp;gt;      Path to the image on the device&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#       --link &amp;lt;LINK&amp;gt;      Url to the image on the Internet&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#       --folder &amp;lt;FOLDER&amp;gt;  Folder for the image on the site&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   -h, --help             Print help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;img-tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --api-key&lt;&#x2F;span&gt;&lt;span&gt; key.json upload&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --folder&lt;&#x2F;span&gt;&lt;span&gt; ferris&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --file&lt;&#x2F;span&gt;&lt;span&gt; crab_ferris.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Config { command: Upload { file_source: FileSource { file: Some(&amp;quot;crab_ferris.png&amp;quot;), link: None }, folder: &amp;quot;ferris&amp;quot; }, api_key: &amp;quot;key.json&amp;quot; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;img-tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --api-key&lt;&#x2F;span&gt;&lt;span&gt; key.json upload&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --folder&lt;&#x2F;span&gt;&lt;span&gt; ferris&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --link&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;i.imgflip.com&#x2F;7gq1em.jpg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --file&lt;&#x2F;span&gt;&lt;span&gt; crab_ferris.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# error: the argument &amp;#39;--file &amp;lt;FILE&amp;gt;&amp;#39; cannot be used with &amp;#39;--link &amp;lt;LINK&amp;gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Usage: img-tool --api-key &amp;lt;API_KEY&amp;gt; upload --folder &amp;lt;FOLDER&amp;gt; &amp;lt;--file &amp;lt;FILE&amp;gt;|--link &amp;lt;LINK&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# For more information, try &amp;#39;--help&amp;#39;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;img-tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --api-key&lt;&#x2F;span&gt;&lt;span&gt; key.json upload&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --folder&lt;&#x2F;span&gt;&lt;span&gt; ferris&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --link&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;i.imgflip.com&#x2F;7gq1em.jpg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Config { command: Upload { file_source: FileSource { file: None, link: Some(Url { scheme: &amp;quot;https&amp;quot;, cannot_be_a_base: false, username: &amp;quot;&amp;quot;, password: None, host: Some(Domain(&amp;quot;i.imgflip.com&amp;quot;)), port: None, path: &amp;quot;&#x2F;7gq1em.jpg&amp;quot;, query: None, fragment: None }) }, folder: &amp;quot;ferris&amp;quot; }, api_key: &amp;quot;key.json&amp;quot; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Another interesting thing: we can see the separated &lt;code&gt;--file&lt;&#x2F;code&gt; and &lt;code&gt;--link&lt;&#x2F;code&gt; args in the help message by the &lt;code&gt;&amp;lt;&amp;gt;&lt;&#x2F;code&gt; triangle brackets. It shows the user that only one of them is needed. Cool, right? 😎&lt;&#x2F;p&gt;
&lt;p&gt;The full &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;commit&#x2F;aba3c688fa83a397d14a9339f564efe4625516e1&quot;&gt;src&lt;&#x2F;a&gt; code of the example above.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;parsing-args-into-a-custom-structure&quot;&gt;Parsing args into a custom structure&lt;&#x2F;h2&gt;
&lt;p&gt;This recipe will be smaller than the previous ones and similar to the second one. But I just want to show that we can do such tricks.&lt;&#x2F;p&gt;
&lt;p&gt;We are going to improve the previous example by adding a more flexible way to pass the API key. Assume that for authentication we need two tokens: app id and app secret. And we want to operate them as one structure. Usually, in such cases, developers treat them as two separate strings and then create a single structure based on those strings. But we are smarter and know how to use commands:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Args&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; ApiKey&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; app id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[arg(long)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; api_app_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; app secret&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[arg(long)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; api_app_secret&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Img tool config structure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Parser&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Config&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; command to execute&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[command(subcommand)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; command&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Command&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; API key data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[command(flatten)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; api_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; ApiKey&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s test it and see the trick:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;img-tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Img tool config structure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Usage: img-tool --api-app-id &amp;lt;API_APP_ID&amp;gt; --api-app-secret &amp;lt;API_APP_SECRET&amp;gt; &amp;lt;COMMAND&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Commands:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   upload    Upload image to the Imgur&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   download  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   help      Print this message or the help of the given subcommand(s)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Options:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#       --api-app-id &amp;lt;API_APP_ID&amp;gt;          app id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#       --api-app-secret &amp;lt;API_APP_SECRET&amp;gt;  app secret&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   -h, --help                             Print help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We have two separate args &lt;code&gt;api-app-is&lt;&#x2F;code&gt; and &lt;code&gt;api-app-secret&lt;&#x2F;code&gt;, but they will be parsed and placed in the one &lt;code&gt;ApiKey&lt;&#x2F;code&gt; structure. It&#x27;s very convenient and we can continue to work with the auth data as one structure without any additional actions.&lt;&#x2F;p&gt;
&lt;p&gt;The full &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;commit&#x2F;c3a77caad5bb861c15bd007cb8091d19e5e001c3&quot;&gt;src&lt;&#x2F;a&gt; code of the example above.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;unsolvable-problem&quot;&gt;Unsolvable problem&lt;&#x2F;h2&gt;
&lt;p&gt;This section is not an actual recipe. I&#x27;ll tell you about a problem that doesn&#x27;t have a perfect solution yet (or I just cannot find one).&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s take the previous recipe and make the task more difficult. Assume that the user should specify the app id and secret &lt;strong&gt;OR&lt;&#x2F;strong&gt; API key file. In other words, the user should provide the one &lt;code&gt;--api-key-file&lt;&#x2F;code&gt; arg or &lt;code&gt;--api-app-id&lt;&#x2F;code&gt; and &lt;code&gt;--api-app-secret&lt;&#x2F;code&gt; args. It means one &lt;strong&gt;OR&lt;&#x2F;strong&gt; two arguments.&lt;&#x2F;p&gt;
&lt;p&gt;I found a few similar questions on the Internet:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;users.rust-lang.org&#x2F;t&#x2F;clap-either-a-or-b-and-c-arguments&#x2F;80331&quot;&gt;Clap either -a OR (-b AND -c) arguments&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;74846776&#x2F;using-clap-derive-with-two-groups-of-arguments&quot;&gt;Using clap-derive with two groups of arguments&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But neither of them had any useful answers. So far, the following code is the best way we can solve this problem:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Args&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; ApiKeyData&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; app id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[arg(long, requires &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;api_app_secret&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; api_app_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; app secret&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[arg(long, requires &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;api_app_id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; api_app_secret&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Args&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[group(required &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; true, args &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;api_key_file&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;api_app_id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;api_app_secret&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;])]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F;&#x2F; Possible types of the api key source&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; ApiKey&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Path to the json file with API key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[arg(long)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    api_key_file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;PathBuf&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Specify API key data in args&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[command(flatten)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    api_key_data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; ApiKeyData&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; The `Config` structure remains unchanged since the last recipe&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The main idea is to create an &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;clap&#x2F;latest&#x2F;clap&#x2F;struct.ArgGroup.html&quot;&gt;&lt;code&gt;ArgGroup&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and require additional args in the &lt;code&gt;ApiKeyData&lt;&#x2F;code&gt; structure if one of the needed args is not specified. This approach has a lot of big inconveniences:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Fields in the &lt;code&gt;ApiKeyData&lt;&#x2F;code&gt; structure are optional. Yes, during parsing, they are validated, and 100% have values, but for further work, we are forced to unwrap them and create another structure.&lt;&#x2F;li&gt;
&lt;li&gt;The help message for the user is not fully informative. It shows that among those three arguments, only one is required. That is a lie because we need a key file &lt;strong&gt;OR&lt;&#x2F;strong&gt; app id + secret.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Enough talking. Let&#x27;s see it in action:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;img-tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Img tool config structure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Usage: img-tool &amp;lt;--api-key-file &amp;lt;API_KEY_FILE&amp;gt;|--api-app-id &amp;lt;API_APP_ID&amp;gt;|--api-app-secret &amp;lt;API_APP_SECRET&amp;gt;&amp;gt; &amp;lt;COMMAND&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Commands:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   upload    Upload image to the Imgur&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   download  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   help      Print this message or the help of the given subcommand(s)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Options:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#       --api-key-file &amp;lt;API_KEY_FILE&amp;gt;      Path to the json file with API key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#       --api-app-id &amp;lt;API_APP_ID&amp;gt;          app id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#       --api-app-secret &amp;lt;API_APP_SECRET&amp;gt;  app secret&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   -h, --help                             Print help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;img-tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --api-key-file&lt;&#x2F;span&gt;&lt;span&gt; key.json download&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --link&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;imgur.com&#x2F;gallery&#x2F;vNOUshX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --dest-file&lt;&#x2F;span&gt;&lt;span&gt; ferris.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Config { command: Download { link: Url { scheme: &amp;quot;https&amp;quot;, cannot_be_a_base: false, username: &amp;quot;&amp;quot;, password: None, host: Some(Domain(&amp;quot;imgur.com&amp;quot;)), port: None, path: &amp;quot;&#x2F;gallery&#x2F;vNOUshX&amp;quot;, query: None, fragment: None }, dest_file: &amp;quot;ferris.png&amp;quot; }, api_key: ApiKey { api_key_file: Some(&amp;quot;key.json&amp;quot;), api_key_data: ApiKeyData { api_app_id: None, api_app_secret: None } } }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;img-tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --api-app-id&lt;&#x2F;span&gt;&lt;span&gt; tbt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --api-app-secret&lt;&#x2F;span&gt;&lt;span&gt; secret download&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --link&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;imgur.com&#x2F;gallery&#x2F;vNOUshX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --dest-file&lt;&#x2F;span&gt;&lt;span&gt; ferris.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Config { command: Download { link: Url { scheme: &amp;quot;https&amp;quot;, cannot_be_a_base: false, username: &amp;quot;&amp;quot;, password: None, host: Some(Domain(&amp;quot;imgur.com&amp;quot;)), port: None, path: &amp;quot;&#x2F;gallery&#x2F;vNOUshX&amp;quot;, query: None, fragment: None }, dest_file: &amp;quot;ferris.png&amp;quot; }, api_key: ApiKey { api_key_file: None, api_key_data: ApiKeyData { api_app_id: Some(&amp;quot;tbt&amp;quot;), api_app_secret: Some(&amp;quot;secret&amp;quot;) } } }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;.&#x2F;img-tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --api-app-id&lt;&#x2F;span&gt;&lt;span&gt; tbt download&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --link&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;imgur.com&#x2F;gallery&#x2F;vNOUshX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; --dest-file&lt;&#x2F;span&gt;&lt;span&gt; ferris.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# error: the following required arguments were not provided:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;#   --api-app-secret &amp;lt;API_APP_SECRET&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Usage: img-tool &amp;lt;--api-key-file &amp;lt;API_KEY_FILE&amp;gt;|--api-app-id &amp;lt;API_APP_ID&amp;gt;|--api-app-secret &amp;lt;API_APP_SECRET&amp;gt;&amp;gt; &amp;lt;COMMAND&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# For more information, try &amp;#39;--help&amp;#39;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The full &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;commit&#x2F;6d5ec50ea36aa2ca6fab7409e68c08a46d1a346e&quot;&gt;src&lt;&#x2F;a&gt; code of the example above. Conclusion: this problem is solvable, but in a very inconvenient way.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;references-final-note&quot;&gt;References &amp;amp; final note&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;Official docs: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;clap&#x2F;latest&#x2F;clap&#x2F;_derive&#x2F;index.html&quot;&gt;derive&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;clap&#x2F;latest&#x2F;clap&#x2F;index.html&quot;&gt;builder&lt;&#x2F;a&gt; references.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The end. The official reference has all you need.&lt;&#x2F;p&gt;
&lt;p&gt;As you can see, the &lt;code&gt;clap&lt;&#x2F;code&gt; gives us a lot of opportunities to configure args parsing and validation. Sometimes it&#x27;s really worth it to read the docs or references. &lt;strong&gt;Advice for the future:&lt;&#x2F;strong&gt; try to move as much work as you can to the &lt;code&gt;clap&lt;&#x2F;code&gt;. It&#x27;s a very powerful tool, so you shouldn&#x27;t be bothered by manual parsing or validation of the args.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>SSPI introduction</title>
        <published>2023-04-27T00:00:00+00:00</published>
        <updated>2023-04-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/posts/sspi-introduction/"/>
        <id>https://tbt.qkation.com/posts/sspi-introduction/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/posts/sspi-introduction/">&lt;h1 id=&quot;goals&quot;&gt;Goals&lt;&#x2F;h1&gt;
&lt;p&gt;The main purpose of this article is to tell you about &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;rpc&#x2F;security-support-provider-interface-sspi-&quot;&gt;Windows SSPI&lt;&#x2F;a&gt;. If you know nothing about it and want to start working with it, this article will benefit you.&lt;&#x2F;p&gt;
&lt;p&gt;If you are familiar with SSPI and have worked with it, then this article most likely will not be useful.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Goals&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Provide a comprehensive SSPI description.&lt;&#x2F;li&gt;
&lt;li&gt;Introduce and explain basic SSPI terms.&lt;&#x2F;li&gt;
&lt;li&gt;Understand core SSPI functions, invocation order, and the purpose of each of them.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Non-goals&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Explain how &lt;strong&gt;concrete&lt;&#x2F;strong&gt; SSP packages work (like &lt;code&gt;NTLM&lt;&#x2F;code&gt;, &lt;code&gt;Kerberos&lt;&#x2F;code&gt;, etc).&lt;&#x2F;li&gt;
&lt;li&gt;Teach how to write a custom SSP package. &lt;sub&gt;I mean, after reading this article you will have a brief idea of what you need to write but it&#x27;s obviously not enough.&lt;&#x2F;sub&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Does this article replace reading the documentation?&lt;&#x2F;strong&gt; Of course not. It&#x27;s just a good place to start.&lt;&#x2F;p&gt;
&lt;p&gt;Happy reading! 😃&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-is-sspi&quot;&gt;What is SSPI&lt;&#x2F;h1&gt;
&lt;p&gt;First of all, let&#x27;s start with &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;rpc&#x2F;sspi-architectural-overview&quot;&gt;the official SSPI definition&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;SSPI is a software interface. Distributed programming libraries such as RPC can use it for authenticated communications.
One or more software modules provide the actual authentication capabilities...&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So, now we know that it&#x27;s an interface. It can be used for authentication. The general idea is to provide a unified interface for the authentication and if any program will need to authenticate some user, then it &quot;just&quot; can use SSPI. Moreover, the authentication process (function call order, etc) doesn&#x27;t depend on the underlying authentication protocol. But buffer sizes and types can be different. We&#x27;ll see how we can handle such cases.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;basic-concepts-and-definitions&quot;&gt;Basic concepts and definitions&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;strong&gt;SSP&lt;&#x2F;strong&gt; - &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;security-support-provider-authentication-packages&quot;&gt;Security Support Provider&lt;&#x2F;a&gt; - a dynamic library (&lt;code&gt;.dll&lt;&#x2F;code&gt; file) that has one or more SSPI implementations. &lt;strong&gt;Security package&lt;&#x2F;strong&gt; - one SSPI implementation. Usually, it reflects some authorization protocol.&lt;&#x2F;p&gt;
&lt;p&gt;Good, now let&#x27;s think a little bit. What do we mean under &quot;successful authentication&quot;? Usually, it&#x27;s something like &quot;username + password is correct, we can do our work further&quot; or &quot;we&#x27;ve got some token that proves our identity&#x2F;permissions&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;In SSPI, the process of authenticating is called context establishing. The result of authenticating is the (established) security context with the session key. The session key can be used for further encryption&#x2F;decryption (you&#x27;ll see it later), checksum calculation&#x2F;verification, and so on. It&#x27;s valid only for this session. After another context establishing the security context will have another session key. The Microsoft documentation gives us a good &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;sspi-context-semantics&quot;&gt;&lt;strong&gt;session context&lt;&#x2F;strong&gt; definition&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;A security context is the set of security attributes and rules in effect during a communication session.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;em&gt;A communication session.&lt;&#x2F;em&gt; After successful authentication, the client and the server can continue to send messages to each other. They can use the session key to secure this communication. It means you can still need SSPI even after the authentication process.&lt;&#x2F;p&gt;
&lt;p&gt;Okay, sounds pretty simple and reasonable. Time to see the actual SSPI interface. All mandatory functions are listed in one structure: the SSPI function table. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;ns-sspi-securityfunctiontablew&quot;&gt;Here it is&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; _SECURITY_FUNCTION_TABLE_W&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  unsigned long&lt;&#x2F;span&gt;&lt;span&gt;                        dwVersion;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ENUMERATE_SECURITY_PACKAGES_FN_W     EnumerateSecurityPackagesW;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  QUERY_CREDENTIALS_ATTRIBUTES_FN_W    QueryCredentialsAttributesW;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ACQUIRE_CREDENTIALS_HANDLE_FN_W      AcquireCredentialsHandleW;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FREE_CREDENTIALS_HANDLE_FN           FreeCredentialsHandle;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  void                                 *&lt;&#x2F;span&gt;&lt;span&gt;Reserved2;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  INITIALIZE_SECURITY_CONTEXT_FN_W     InitializeSecurityContextW;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ACCEPT_SECURITY_CONTEXT_FN           AcceptSecurityContext;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  COMPLETE_AUTH_TOKEN_FN               CompleteAuthToken;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DELETE_SECURITY_CONTEXT_FN           DeleteSecurityContext;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  APPLY_CONTROL_TOKEN_FN               ApplyControlToken;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  QUERY_CONTEXT_ATTRIBUTES_FN_W        QueryContextAttributesW;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  IMPERSONATE_SECURITY_CONTEXT_FN      ImpersonateSecurityContext;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  REVERT_SECURITY_CONTEXT_FN           RevertSecurityContext;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  MAKE_SIGNATURE_FN                    MakeSignature;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  VERIFY_SIGNATURE_FN                  VerifySignature;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FREE_CONTEXT_BUFFER_FN               FreeContextBuffer;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  QUERY_SECURITY_PACKAGE_INFO_FN_W     QuerySecurityPackageInfoW;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  void                                 *&lt;&#x2F;span&gt;&lt;span&gt;Reserved3;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  void                                 *&lt;&#x2F;span&gt;&lt;span&gt;Reserved4;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  EXPORT_SECURITY_CONTEXT_FN           ExportSecurityContext;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  IMPORT_SECURITY_CONTEXT_FN_W         ImportSecurityContextW;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ADD_CREDENTIALS_FN_W                 AddCredentialsW;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  void                                 *&lt;&#x2F;span&gt;&lt;span&gt;Reserved8;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  QUERY_SECURITY_CONTEXT_TOKEN_FN      QuerySecurityContextToken;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ENCRYPT_MESSAGE_FN                   EncryptMessage;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DECRYPT_MESSAGE_FN                   DecryptMessage;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  SET_CONTEXT_ATTRIBUTES_FN_W          SetContextAttributesW;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  SET_CREDENTIALS_ATTRIBUTES_FN_W      SetCredentialsAttributesW;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  CHANGE_PASSWORD_FN_W                 ChangeAccountPasswordW;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;  void                                 *&lt;&#x2F;span&gt;&lt;span&gt;Reserved9;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  QUERY_CONTEXT_ATTRIBUTES_EX_FN_W     QueryContextAttributesExW;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  QUERY_CREDENTIALS_ATTRIBUTES_EX_FN_W QueryCredentialsAttributesExW;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; SecurityFunctionTableW&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;PSecurityFunctionTableW&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Along with table &lt;em&gt;W&lt;&#x2F;em&gt;, also a similar &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;ns-sspi-securityfunctiontablea&quot;&gt;table A&lt;&#x2F;a&gt; exists. What&#x27;s the difference? This is not a part of this story but here is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;7424550&#x2F;9123725&quot;&gt;the answer on SO&lt;&#x2F;a&gt;. Today we&#x27;ll work only with the W table. But remember that all things that apply to the W table, are also applicable to the A table.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;sspi&quot;&gt;SSPI&lt;&#x2F;h1&gt;
&lt;p&gt;The SSPI functions table has a lot of &lt;sub&gt;(?terrible?)&lt;&#x2F;sub&gt; functions. We&#x27;ll talk about them, and how and when you should use them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;&#x2F;h2&gt;
&lt;p&gt;To bring at least some order, we will split SSPI functions into four categories. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;authentication-functions#sspi-functions&quot;&gt;The official documentation&lt;&#x2F;a&gt; has a good description of it so we follow it:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Package management.&lt;&#x2F;strong&gt; &lt;em&gt;SSPI package management functions initiate a security package, enumerate available packages, and query the attributes of a security package.&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;EnumerateSecurityPackagesW&lt;&#x2F;code&gt;: list all available security packages in the SSP.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;InitSecurityInterfaceW&lt;&#x2F;code&gt;: initialize security table.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;QuerySecurityPackageInfoW&lt;&#x2F;code&gt;: query some information about the security package.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Credential management.&lt;&#x2F;strong&gt; &lt;em&gt;Functions used to obtain credentials handle for the security context, set credentials attributes, and query information about credentials.&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AcquireCredentialsHandleW&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ExportSecurityContext&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;FreeCredentialsHandle&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ImportSecurityContextW&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;QueryCredentialsAttributesW&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;Context management.&lt;&#x2F;strong&gt; &lt;em&gt;Functions used to establish security context, query and set its attributes, etc.&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AcceptSecurityContext&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ApplyControlToken&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;CompleteAuthToken&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;DeleteSecurityContext&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;FreeContextBuffer&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ImpersonateSecurityContext&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;InitializeSecurityContextW&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;QuerySecurityContextToken&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;QueryContextAttributesW&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;SetContextAttributesW&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;RevertSecurityContext&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;strong&gt;Message support.&lt;&#x2F;strong&gt; &lt;em&gt;Those functions usually are called when the security context is established. You can use them to secure messages (encryption, hashing, etc).&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;EncryptMessage&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;DecryptMessage&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;MakeSignature&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;MakeSignature&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Enough talking. Let&#x27;s see SSPI in action. From the example below you will understand functions call order, and their purpose.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sspi-in-action&quot;&gt;SSPI in action&lt;&#x2F;h2&gt;
&lt;p&gt;Two things are needed to demonstrate SSPI in action:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Client.&lt;&#x2F;li&gt;
&lt;li&gt;Server.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Both of them should use the same security package to successfully authenticate. As the client, I took &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;microsoft-ntlm&quot;&gt;the NTLM security package&lt;&#x2F;a&gt; from &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;ssp-packages-provided-by-microsoft&quot;&gt;the Microsoft-provided SSP&lt;&#x2F;a&gt;. To keep my code example clearer, as the server, I took this &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;sspi&quot;&gt;sspi implementation in Rust&lt;&#x2F;a&gt;. All my code is written in Rust. To call Windows API functions I use crates with bindings like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;winapi&quot;&gt;winapi&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;windows-sys&quot;&gt;windows-sys&lt;&#x2F;a&gt;. You should focus only on the client code and not on the server code.&lt;&#x2F;p&gt;
&lt;p&gt;Why NTLM? Because it&#x27;s simple. It&#x27;s a good protocol to use as an example (but bad for the real world &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.calcomsoftware.com&#x2F;ntlm-security-weaknesses&#x2F;#relay&quot;&gt;[1]&lt;&#x2F;a&gt; &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.securew2.com&#x2F;blog&#x2F;why-ntlm-authentication-is-vulnerable&quot;&gt;[2]&lt;&#x2F;a&gt;. If you can avoid it then avoid it 🐺).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;main&#x2F;sspi-introduction&quot;&gt;Here&lt;&#x2F;a&gt; you can find the source code.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;initialization&quot;&gt;Initialization&lt;&#x2F;h3&gt;
&lt;p&gt;Good so far. Let the journey begin! What do we need to start using SSPI? Correct! SSPI function table. How can we initialize it?  By calling the &lt;code&gt;InitSecurityInterfaceW&lt;&#x2F;code&gt; function. This function returns a structure (see it &lt;a href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;posts&#x2F;sspi-introduction&#x2F;#overview&quot;&gt;above&lt;&#x2F;a&gt;) with function pointers. If we want to use Windows SSP then we can just use Win API. But if we decide to use some custom SSP, then we need to load the corresponding dll, find the &lt;code&gt;InitSecurityInterfaceW&lt;&#x2F;code&gt; function and call it. Example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; load our SSP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sspi_handle&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; LoadLibraryW&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;my_cool_ssp.dll&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; get the pointer to the needed function&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; init_security_interface_fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; GetProcAddress&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;sspi_handle&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;InitSecurityInterfaceW&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; transmute (cast) the pointer to the needed function type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; init_security_interface_w_fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; INIT_SECURITY_INTERFACE_W&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;mem&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;transmute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;init_security_interface_w_fn&lt;&#x2F;span&gt;&lt;span&gt;) };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sspi_function_table&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; init_security_interface_w_fn&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; now we have initialized function table&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; ...further authentication&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But in the scope of this article, I use Windows native SSP. So I don&#x27;t need to initialize the function table. It already is initialized inside Windows. Time to see what Windows can offer us:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; number_of_packages&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; packages&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; null_mut&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Query information about the available Windows security packages&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;nf-sspi-enumeratesecuritypackagesw&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; EnumerateSecurityPackagesW&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; number_of_packages&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; packages&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When I printed it on the screen (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;blob&#x2F;main&#x2F;sspi-introduction&#x2F;src&#x2F;initialization.rs#L11&quot;&gt;src&lt;&#x2F;a&gt;), I got such the output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Number of packages: 13&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-------------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fCapabilities: 8928179&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;wVersion: 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;wRPCID: 9&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cbMaxToken: 48256&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Name: Negotiate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Comment: Microsoft Package Negotiator&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-------------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can see a lot of security packages. But as I said above, today we are working only with NTLM. Let&#x27;s gather more information about the NTLM security package (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;blob&#x2F;main&#x2F;sspi-introduction&#x2F;src&#x2F;initialization.rs#L54&quot;&gt;src&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; raw_package_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; str_to_win_wstring&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;NTLM&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; package_info&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; null_mut&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; QuerySecurityPackageInfoW&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;raw_package_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; package_info&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;{} package info:&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; package_name&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;fCapabilities: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;package_info&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;fCapabilities);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;wVersion: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;package_info&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;wVersion);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;wRPCID: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;package_info&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;wRPCID);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;cbMaxToken: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;package_info&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;cbMaxToken);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;Name: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; c_wide_string_to_rs_string&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;package_info&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Name&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;    &amp;quot;Comment: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    c_wide_string_to_rs_string&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;package_info&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Comment&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NTLM package info:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fCapabilities: 42478391&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;wVersion: 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;wRPCID: 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cbMaxToken: 2888&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Name: NTLM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Comment: NTLM Security Package&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In general, different security packages support different attributes. So refer to the documentation for more concrete information.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;credentials&quot;&gt;Credentials&lt;&#x2F;h3&gt;
&lt;p&gt;Before starting the actual authentication we need to prepare credentials. In other words, to acquire credentials handle. Basically, the credentials handle is a pointer to some structure that contains prepared credentials for use during the authentication, maybe some flags, and other credentials-related information. What type of this structure? We don&#x27;t know and we don&#x27;t need to know. The security provider creates and works with this object. It&#x27;ll be good if you also read &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;acquirecredentialshandle--general&quot;&gt;the official credentials handle definition&lt;&#x2F;a&gt;. Enough talking. Now time back to the code (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;blob&#x2F;main&#x2F;sspi-introduction&#x2F;src&#x2F;credentials.rs#L12&quot;&gt;src&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; credentials_handle&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; CredHandle&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; expiry&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; TimeStamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; package_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; str_to_win_wstring&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;NTLM&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; domain&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; str_to_win_wstring&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; str_to_win_wstring&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;testuser&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; password&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; str_to_win_wstring&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;test&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; identity&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; SEC_WINNT_AUTH_IDENTITY_W&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    User&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    UserLength&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Domain&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; domain&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    DomainLength&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Password&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; password&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    PasswordLength&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    Flags&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0x2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; AcquireCredentialsHandleW&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    null_mut&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    package_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; SECPKG_CRED_OUTBOUND: https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;acquirecredentialshandle--ntlm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;    2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    null_mut&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; identity&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; SEC_WINNT_AUTH_IDENTITY_W&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;    None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    null_mut&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; credentials_handle&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; expiry&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After the &lt;code&gt;AcquireCredentialsHandleW&lt;&#x2F;code&gt; function call, the &lt;code&gt;credentials_handle&lt;&#x2F;code&gt; variable will contain the credentials handle. &lt;strong&gt;Note.&lt;&#x2F;strong&gt; In SSPI all handles (context, credentials, etc) are instances of the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;ns-sspi-sechandle&quot;&gt;&lt;code&gt;SecHandle&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; structure. Each such structure has two numbers (pointers): &lt;em&gt;lower&lt;&#x2F;em&gt; and &lt;em&gt;upper&lt;&#x2F;em&gt;. When you are working with SSPI you don&#x27;t need to know anything more about them. If you are writing your own SSP then you shouldn&#x27;t expose any information about them.&lt;&#x2F;p&gt;
&lt;p&gt;However, to satisfy your curiosity, I will say what there may be (but don&#x27;t tell anyone 😜): One of them can contain a pointer to some object (for example, a security context object), and another one can contain a pointer to the security package name. Because SSP can contain a lot of security packages, we need to store the security package name in some way that is currently used.&lt;&#x2F;p&gt;
&lt;p&gt;This function has a lot of parameters and they are well explained in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;acquirecredentialshandle--general&quot;&gt;the official documentation&lt;&#x2F;a&gt;. Just don&#x27;t forget that the type for the &lt;code&gt;pauthdata&lt;&#x2F;code&gt; pointer is package-specific. It means that different security packages usually require different types of &lt;code&gt;pauthdata&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Also, the SSPI has a place for customization. Security packages implement the &lt;code&gt;QueryCredentialsAttributesW&lt;&#x2F;code&gt; and &lt;code&gt;SetCredentialsAttributesW&lt;&#x2F;code&gt; functions. With them, we can add and get additional information (attributes) about concrete credentials handle. Small example (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;blob&#x2F;main&#x2F;sspi-introduction&#x2F;src&#x2F;credentials.rs#L74&quot;&gt;src&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; credentials_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; SecPkgCredentials_NamesW&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; QueryCredentialsAttributesW&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    client_credentials_handle&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;    SECPKG_CRED_ATTR_NAMES&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; credentials_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; SecPkgCredentials_NamesW&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;    &amp;quot;Credentials name: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    c_wide_string_to_rs_string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;credentials_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sUserName)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Credentials name: &amp;quot;testdomain\\testuser&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;authentication&quot;&gt;Authentication&lt;&#x2F;h3&gt;
&lt;p&gt;Perfect. We have prepared credentials (credentials handle). Time to start actual authentication. The authentication process consists of sequential &lt;code&gt;InitializeSecurityContext&lt;&#x2F;code&gt; function calls.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;When we should stop?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;When this function returns &lt;code&gt;SEC_E_OK&lt;&#x2F;code&gt;, &lt;code&gt;SEC_I_COMPLETE_AND_CONTINUE&lt;&#x2F;code&gt;, or &lt;code&gt;SEC_I_COMPLETE_NEEDED&lt;&#x2F;code&gt; status code. i. e. we call the &lt;code&gt;InitializeSecurityContext&lt;&#x2F;code&gt; function until it returns the appropriate status code. The generalized authentication flow is shown in the diagram below:&lt;&#x2F;p&gt;
&lt;div class=&quot;mermaid&quot;&gt;
flowchart TD
    A(Begin auth) --&amp;gt; B(InitializeSecurityContext)
    B --&amp;gt; C{status code}
    C --&amp;gt;|Error| F(Auth failed)
    C --&amp;gt;|SEC_E_OK,...| E(Auth succeeded)
    C --&amp;gt;|SEC_I_CONTINUE_NEEDED| D(Send buffers to the server)
    D --&amp;gt;|TCP| G(Receive buffers from server)
    G --&amp;gt; B
&lt;&#x2F;div&gt;
&lt;p&gt;Great, pretty simple. Now let&#x27;s implement it in the code (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;blob&#x2F;main&#x2F;sspi-introduction&#x2F;src&#x2F;authentication.rs#L24&quot;&gt;src&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; client_status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; InitializeSecurityContextW&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; client_credentials_handle&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    unwrap_sec_handle&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; client_security_context&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    target_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; MUTUAL_AUTH and ALLOCATE_MEMORY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;    0x2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0x100&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;    0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; Native data representation:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;    0x10&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; client_input_buffers&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;    0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; new_client_security_context&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; client_output_buffers&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; context_attributes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; expiry&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Oh my gosh. So many parameters. We definitely need an explanation.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Agreed. But before I explain each of them, I would like to insert small note about the source code you will find in the repo: I didn&#x27;t create any real servers or TCP&#x2F;TLS connections. I just convert and pass buffers from one function to another. You will see it in the code comments.&lt;&#x2F;p&gt;
&lt;p&gt;Hardest part described below:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;phcredential&lt;&#x2F;code&gt;: a pointer to the credentials handle. We have it after the &lt;code&gt;AcquireCredentialsHandleW&lt;&#x2F;code&gt; function call.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;phcontext&lt;&#x2F;code&gt;: a pointer to the security context handle.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;But wait. We don&#x27;t have a such one.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Yes. On the first function call we pass the &lt;code&gt;NULL&lt;&#x2F;code&gt; here. The security context handle will be created by the function itself during the first invocation and written in the &lt;code&gt;phnewcontext&lt;&#x2F;code&gt; parameter.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;psztargetname&lt;&#x2F;code&gt;: &lt;em&gt;&quot;a pointer to a null-terminated string that indicates the service principal name (SPN)&quot;&lt;&#x2F;em&gt; (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;initializesecuritycontext--ntlm&quot;&gt;docs&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;fcontextreq&lt;&#x2F;code&gt;: a context requirements flags. Basically, this flags tell the security package how to do authentication. Like, what session key to use, what additional things to require, etc. Those flags differ in the different security packages.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;reserved1&lt;&#x2F;code&gt;, &lt;code&gt;reserved2&lt;&#x2F;code&gt; are reserved and not used.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;targetdatarep&lt;&#x2F;code&gt;: &lt;em&gt;&quot;The data representation, such as byte ordering, on the target.&quot;&lt;&#x2F;em&gt; (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;initializesecuritycontext--ntlm&quot;&gt;docs&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;pinput&lt;&#x2F;code&gt;: input buffers for this function. On the first function call, we don&#x27;t have any input buffers so we should pass empty &lt;code&gt;SecBufferDesc&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;What types of security buffers should I choose, how many of them do I need, and in what sequence?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Docs. Search for it in the documentation of the corresponding security package. If you can&#x27;t find it there, then search in the open-source projects. And remember one important thing: &lt;strong&gt;never change buffers&#x27; order or type&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;phnewcontext&lt;&#x2F;code&gt;: a new security context handle will be written here. You should use this handle for the next function call.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;poutput&lt;&#x2F;code&gt;: same as &lt;code&gt;pinput&lt;&#x2F;code&gt; but output buffers instead of input.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;pfcontextattr&lt;&#x2F;code&gt;: flags that describe established security context. We use &lt;code&gt;fcontextreq&lt;&#x2F;code&gt; to specify some options for authentication. Ans use &lt;code&gt;pfcontextattr&lt;&#x2F;code&gt; to see what options have been established (set).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ptsexpiry&lt;&#x2F;code&gt;: the expiration time of the context.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The security context also has functions for setting and getting different attributes: &lt;code&gt;QueryContextAttributesW&lt;&#x2F;code&gt; and &lt;code&gt;SetContextAttributesW&lt;&#x2F;code&gt;. They have similar behavior to the credentials-related functions. For example, in the NTLM security package, we have the possibility to extract the established session key (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;blob&#x2F;main&#x2F;sspi-introduction&#x2F;src&#x2F;authentication.rs#L155&quot;&gt;src&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; session_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; SecPkgContext_SessionKey&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; QueryContextAttributesW&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;    client_security_context&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt;    SECPKG_ATTR_SESSION_KEY&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;    &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; session_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; SecPkgContext_SessionKey&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;    &amp;quot;Established session key: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;    from_raw_parts&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        session_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SessionKey&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as *const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;        session_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;SessionKeyLength&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Established session key: [96, 1, 13, 58, 82, 191, 222, 134, 149, 184, 3, 75, 254, 126, 225, 74]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can run the code a few times. Each time you will have another session key.&lt;&#x2F;p&gt;
&lt;p&gt;Phew, the hardest part is gone. Now we (&lt;em&gt;finally&lt;&#x2F;em&gt;) have the established security context. What&#x27;s next? Now we can do everything we want, but more importantly, we can safely transfer any messages to the server and receive server messages securely.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;communication&quot;&gt;Communication&lt;&#x2F;h3&gt;
&lt;p&gt;Imagine the situation: we want to send a very secret message to the server. In such case we should use the &lt;code&gt;EncryptMessage&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; EncryptMessage&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;client_security_context&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sequence_number&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; send `message` to the server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I think you already guessed it, but still: encryption&#x2F;decryption, and signature generation&#x2F;verification are always in-place. This is why we don&#x27;t have the output buffer parameter in this function.&lt;&#x2F;p&gt;
&lt;p&gt;If we want to read encrypted messages (e. g. received from the server) then:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; DecryptMessage&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;client_security_context&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97E72;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt; &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; message&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; sequence_number&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The same thing with the &lt;code&gt;MakeSignature&lt;&#x2F;code&gt; and &lt;code&gt;VerifySignature&lt;&#x2F;code&gt; functions.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;clean-up&quot;&gt;Clean up&lt;&#x2F;h3&gt;
&lt;p&gt;Yes, &lt;em&gt;memory leaks are memory safe&lt;&#x2F;em&gt;, but it&#x27;s better to not forget to clean up everything. SSPI has three functions for that:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FreeContextBuffer&lt;&#x2F;code&gt;. (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;nf-sspi-freecontextbuffer&quot;&gt;doc&lt;&#x2F;a&gt;). Only one rule: if the buffer was allocated by the security package, then you should free it using this function. If the buffer was allocated by yourself, then you should free it in the usual way.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;FreeCredentialsHandle&lt;&#x2F;code&gt;. (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;nf-sspi-freecredentialshandle&quot;&gt;doc&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;DeleteSecurityContext&lt;&#x2F;code&gt;. (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;nf-sspi-deletesecuritycontext&quot;&gt;doc&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; FreeCredentialsHandle&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;client_cred_handle&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; status&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; DeleteSecurityContext&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;client_context_handle&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h1&gt;
&lt;p&gt;Finally, this story goes to the end. If you want to use SSPI on the server side then just replace the &lt;code&gt;InitializeSecurityContextW&lt;&#x2F;code&gt; function with &lt;code&gt;AcceptSecurityContext&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Wait! You haven&#x27;t described other SSPI functions!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Don&#x27;t panic, I know it. The other functions are rarely used and do not take a direct part in the authorization process.&lt;&#x2F;p&gt;
&lt;p&gt;I hope you enjoy reading it and it&#x27;ll help you in some way. If you want to share some feedback, ask a question, just task to me, then use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tbt.qkation.com&#x2F;about&#x2F;&quot;&gt;this page&lt;&#x2F;a&gt; to contact me.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;doc-references-code&quot;&gt;Doc, references, code&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;rpc&#x2F;security-support-provider-interface-sspi-&quot;&gt;Security Support Provider Interface (SSPI).&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;sspi&quot;&gt;SSPI.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sspi&#x2F;&quot;&gt;&lt;code&gt;sspi.h&lt;&#x2F;code&gt;.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;authentication-functions#sspi-functions&quot;&gt;Authentication Functions.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;secauthn&#x2F;using-sspi&quot;&gt;Using SSPI.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;trash-code&#x2F;tree&#x2F;main&#x2F;sspi-introduction&quot;&gt;Example source code.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>yew-notifications</title>
        <published>2023-04-17T00:00:00+00:00</published>
        <updated>2023-04-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/projects/yew-notifications/"/>
        <id>https://tbt.qkation.com/projects/yew-notifications/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/projects/yew-notifications/">&lt;p&gt;Notifications components library for &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;yew.rs&#x2F;&quot;&gt;Yew&lt;&#x2F;a&gt;. It&#x27;s like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.npmjs.com&#x2F;package&#x2F;react-toastify&quot;&gt;react-toastify&lt;&#x2F;a&gt; but for &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;yew.rs&#x2F;&quot;&gt;Yew&lt;&#x2F;a&gt; and more simpler (so far 😏).&lt;&#x2F;p&gt;
&lt;p&gt;TL;DR: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;yn-docs.qkation.com&#x2F;yew_notifications&#x2F;index.html&quot;&gt;documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;motivation&quot;&gt;Motivation&lt;&#x2F;h3&gt;
&lt;p&gt;I was writing my personal project &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;&quot;&gt;crypto-helper&lt;&#x2F;a&gt; some time ago. I was forced to write awful code (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;blob&#x2F;8ad5ca3180925120a6f7ceb39253000f7ce3f447&#x2F;src&#x2F;notification.rs&quot;&gt;[1]&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;crypto-helper&#x2F;blob&#x2F;8ad5ca3180925120a6f7ceb39253000f7ce3f447&#x2F;src&#x2F;crypto_helper.rs#L81-L131&quot;&gt;[2]&lt;&#x2F;a&gt;) to add some notifications functionality to my web app. So, I decided to write this library that allows the easy showing of notifications to users.&lt;&#x2F;p&gt;
&lt;p&gt;Inspired by &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kinnison&#x2F;linkdoku&#x2F;tree&#x2F;main&#x2F;yew-toastrack&quot;&gt;&lt;code&gt;yew-toastrack&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;core-concepts&quot;&gt;Core concepts&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;First of all, simplicity is one of the main purposes.&lt;&#x2F;strong&gt; I would like to have a general provider and hook that will spawn notifications. Something like that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Provider&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; inner components&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Provider&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;... and spawn notifications in any inner component using one simple hook:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; notifications&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; use_notifications&lt;&#x2F;span&gt;&lt;span&gt;();                              &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;notifications&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;* *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I managed to implement it as I wanted using the yew &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;yew.rs&#x2F;docs&#x2F;next&#x2F;concepts&#x2F;contexts#step-1-providing-the-context&quot;&gt;ContextProvider&lt;&#x2F;a&gt;. Basically, all notifications are saved in this context provider. But we need to add new notifications, remove old ones, and so on. So the simple &lt;code&gt;Vec&lt;&#x2F;code&gt; inside of the context provider is a bad idea. Actually, it holds the &lt;code&gt;UseReducerDispatcher&lt;&#x2F;code&gt; wrapper into the &lt;code&gt;NotificationsManager&lt;&#x2F;code&gt;. This &lt;code&gt;NotificationsManager&lt;&#x2F;code&gt; can spawn new notifications using the inner &lt;code&gt;UseReducerDispatcher&lt;&#x2F;code&gt; and the context will handle them.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The second goal is customization.&lt;&#x2F;strong&gt; I don&#x27;t want to force users to use only built-in notification components. This is a reason why the &lt;code&gt;NotificationsProvider&lt;&#x2F;code&gt; component and &lt;code&gt;use_notifications&lt;&#x2F;code&gt; hook have generic parameters.&lt;&#x2F;p&gt;
&lt;p&gt;For the notifications provider component, we need to specify two generic parameters:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Notifications type.&lt;&#x2F;em&gt; This is a struct that described notification data like title, text, lifetime, etc. You can create your own such struct and use it here. It must implement the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;yn-docs.qkation.com&#x2F;yew_notifications&#x2F;trait.Notifiable.html&quot;&gt;&lt;code&gt;Notifiable&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; trait.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Notification Factory type&lt;&#x2F;em&gt;. The purpose of this type is actual notification component creation. It must implement the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;yn-docs.qkation.com&#x2F;yew_notifications&#x2F;trait.NotifiableComponentFactory.html&quot;&gt;&lt;code&gt;NotifiableComponentFactory&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; trait. When the library will try to render the user&#x27;s notification, it&#x27;ll use this factory to create notification yew component from the Notification instance.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;NotificationsProvider&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Notification&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; NotificationFactory&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; component_creator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;* *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;}&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; some inner components&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;NotificationsProvider&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Notification&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; NotificationFactory&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the &lt;code&gt;use_notifications&lt;&#x2F;code&gt; hook, we need to specify only the notification type:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; notifications&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; use_notification&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Notification&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;();                                         &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;notifications&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Notification&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;* *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Pay attention:&lt;&#x2F;strong&gt; if you specify the different notification types in the provider and hook then the code will compile but fail in the runtime. But you can use different notification types if they provider components do not overlap.&lt;&#x2F;p&gt;
&lt;p&gt;For example, with fully customized notifications, we can achieve the following result:&lt;&#x2F;p&gt;
 &lt;img src=&quot;terminal_example.gif&quot; alt=&quot;terminal example demo&quot; width=&quot;1920&quot; height=&quot;954&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;p&gt;&lt;sub&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;yew-notifications&#x2F;tree&#x2F;main&#x2F;examples&#x2F;terminal&quot;&gt;src&lt;&#x2F;a&gt;. &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;yn-docs.qkation.com&#x2F;examples&#x2F;terminal&#x2F;index.html&quot;&gt;demo site&lt;&#x2F;a&gt;.&lt;&#x2F;sub&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Decide which notification components to use. &lt;code&gt;yew-notifications&lt;&#x2F;code&gt; already has implemented standard notifications but you can write your own. See &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;yew-notifications&#x2F;tree&#x2F;main&#x2F;examples&#x2F;basic&quot;&gt;&lt;code&gt;basic&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;yew-notifications&#x2F;tree&#x2F;main&#x2F;examples&#x2F;custom&quot;&gt;&lt;code&gt;custom&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; examples for more information.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# Cargo.toml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# if you want to use standard notification components&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;yew-notifications&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B6B1B1;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; git&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B6B1B1;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;yew-notifications.git&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; features&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B6B1B1;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;standard-notification&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;# if you decide to write and use custom notification components&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;yew-notifications&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B6B1B1;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; git&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B6B1B1;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt; &amp;quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;yew-notifications.git&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Include &lt;code&gt;yew-notification&lt;&#x2F;code&gt; styles into your project:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;link&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;font-style: italic;&quot;&gt; data-trunk rel&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B6B1B1;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;sass&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;font-style: italic;&quot;&gt; href&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B6B1B1;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;TheBestTvarynka&#x2F;yew-notifications&#x2F;main&#x2F;static&#x2F;notifications_provider.scss&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This one below is needed only when you decide to use components from the &lt;code&gt;yew-notifications&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #72F1B8;&quot;&gt;link&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;font-style: italic;&quot;&gt; data-trunk rel&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B6B1B1;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;sass&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;font-style: italic;&quot;&gt; href&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B6B1B1;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF8B39;&quot;&gt;&amp;quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;TheBestTvarynka&#x2F;yew-notifications&#x2F;main&#x2F;static&#x2F;notification.scss&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or you can copy &lt;em&gt;scss&lt;&#x2F;em&gt; file into your project and specify the path to it instead of the link. At this point, the &lt;em&gt;scss&lt;&#x2F;em&gt; file is one possible way to import styles.&lt;&#x2F;p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Wrap needed components into &lt;code&gt;NotificationProvider&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Notification, NotificationFactory  - your notification types.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; They can be imported from this library or written by yourself (see `custom` example).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; component_creator is an instance of the NotificationFactory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;NotificationsProvider&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Notification&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; NotificationFactory&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; component_creator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;* *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;}&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;    &#x2F;&#x2F; some inner components&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;NotificationsProvider&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Notification&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; NotificationFactory&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Spawn notifications:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #FFFFFF; background-color: #262335;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt; yew_notifications&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;use_notification;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; Notification - your notification type.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #848BBD;font-style: italic;&quot;&gt;&#x2F;&#x2F; It can be imported from this library or written by yourself (see `custom` example).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt; notifications_manager&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFFFFFEE;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt; use_notification&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Notification&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7EDB;&quot;&gt;notifications_manager&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FE4450;&quot;&gt;Notification&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #36F9F6;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FEDE5D;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;See the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;yew-notifications&#x2F;tree&#x2F;main&#x2F;examples&quot;&gt;&lt;code&gt;examples&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; directory for the code examples.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;moving-forward&quot;&gt;Moving forward&lt;&#x2F;h3&gt;
&lt;p&gt;At this point, this library has minimal functionality implemented. I plan to improve it continuously according to my needs and goals. If you have any feature requests, then create an &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;yew-notifications&#x2F;issues&#x2F;new&quot;&gt;issue&lt;&#x2F;a&gt; with the description. It&#x27;ll be a priority for me.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>bytes-formatter</title>
        <published>2023-04-09T00:00:00+00:00</published>
        <updated>2023-04-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tbt.qkation.com/projects/bytes-formatter/"/>
        <id>https://tbt.qkation.com/projects/bytes-formatter/</id>
        
        <content type="html" xml:base="https://tbt.qkation.com/projects/bytes-formatter/">&lt;p&gt;Visit this tool at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;bf.qkation.com&quot;&gt;bf.qkation.com&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
 &lt;img src=&quot;simple_demo.png&quot; alt=&quot;byte-formatter demo screenshot&quot; width=&quot;1920&quot; height=&quot;954&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;h3 id=&quot;motivation&quot;&gt;Motivation&lt;&#x2F;h3&gt;
&lt;p&gt;During my work, I often need to convert bytes between different representations (format) like from &lt;em&gt;hex&lt;&#x2F;em&gt; to &lt;em&gt;decimal&lt;&#x2F;em&gt; and vice versa. From &lt;em&gt;hex&#x2F;base64&lt;&#x2F;em&gt; to &lt;em&gt;ASCII&lt;&#x2F;em&gt;. And so on. Before I just have one small rust project on my laptop with a few dependencies and every time I inserted my new data, run this project, and copy the output. After some time it became inconvenient: I was forced to keep this project on every machine, compile it after every code change, etc. After some suffering, I wrote this user-friendly tool in pure html&#x2F;css&#x2F;js. The code is clear-cut and perfectly does the job.&lt;&#x2F;p&gt;
&lt;p&gt;Features:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;supported formats: &lt;code&gt;decimal&lt;&#x2F;code&gt;, &lt;code&gt;hex&lt;&#x2F;code&gt;, &lt;code&gt;base64&lt;&#x2F;code&gt; (both: usual and url-encoded), &lt;code&gt;ascii&lt;&#x2F;code&gt;, &lt;code&gt;binary&lt;&#x2F;code&gt;, &lt;code&gt;utf-8&lt;&#x2F;code&gt;, and &lt;code&gt;utf-16&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;ability to copy only selected range of the bytes. It automatically counts the amount of the selected bytes.&lt;&#x2F;li&gt;
&lt;li&gt;share by the link.&lt;&#x2F;li&gt;
&lt;li&gt;integrated &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;asn1.qkation.com&quot;&gt;asn1 parser&lt;&#x2F;a&gt; (available for &lt;code&gt;hex&lt;&#x2F;code&gt; and &lt;code&gt;base64&lt;&#x2F;code&gt; output types).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;&#x2F;h3&gt;
&lt;p&gt;Just follow &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;bf.qkation.com&#x2F;&quot;&gt;the link&lt;&#x2F;a&gt; and paste your data. The interface is pretty intuitive. Anyway, it also has examples of the different inputs. Click the &lt;code&gt;Show input examples&lt;&#x2F;code&gt; button to see them. You&#x27;ll see that you can insert even unfiltered data and this tool will do basic filtering and formatting.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;moving-forward&quot;&gt;Moving forward&lt;&#x2F;h3&gt;
&lt;p&gt;I already implemented the needed functionality for me. If you found the bug or have the feature request, then create a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheBestTvarynka&#x2F;bytes-formatter&#x2F;issues&#x2F;new&quot;&gt;new issue&lt;&#x2F;a&gt; with the proper description.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
