Skip to content

Commit

Permalink
#3 fixes, updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ph4r05 committed Oct 17, 2018
1 parent 760ddc0 commit 58b286f
Showing 1 changed file with 20 additions and 19 deletions.
39 changes: 20 additions & 19 deletions monero.tex
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ \section{Sending a transaction}

The majority of transaction building process is performed in the software wallet while only the low-level crypto operations with the secret keys are performed in the Ledger.

The sensitive sub-results are returned sealed to the software wallet, encrypted by simple AES/ECB encryption with transaction-specific encryption key, so the sensitive values cannot be used beyond the transaction scope. Ledger has to unseal the inputs, perform the operation and reseal the outputs before returning the result to the wallet. Moreover, to protect the protocol integrity the inputs are hashed in the Ledger.
The sensitive sub-results are returned sealed to the software wallet, encrypted by simple AES/CBC encryption with transaction-specific encryption key, so the sensitive values cannot be used beyond the transaction scope. Ledger has to unseal the inputs, perform the operation and reseal the outputs before returning the result to the wallet. Moreover, to protect the protocol integrity the inputs are hashed in the Ledger.

\;
\noindent Pros:
Expand Down Expand Up @@ -497,16 +497,16 @@ \subsection{RingCT MLSAG Signature details}

\paragraph{Final message hash} The final message hash has the following structure:

\begin{equation} \label{eq:final_message_hash}
\text{final\_message\_hash} = H(H(\text{transaction\_prefix}) \; || \; H(\text{rctSigBase}) \; || \; H(\text{rangeSigs}))
\begin{equation} \label{eq:full_message_hash}
\text{full\_message\_hash} = H(H(\text{transaction\_prefix}) \; || \; H(\text{rctSigBase}) \; || \; H(\text{rangeSigs}))
\end{equation}

Final message is hashed from 3 independent components. This fact is used in the subdivided signing protocol for incremental hashing of the \emph{final\_message}. E.g., range proof is hashed to the third component even though \emph{rctSigBase} and \emph{transaction\_prefix} hashing is not finished which saves few protocol round trips.
The \emph{final\_message} hash is generated by \verb|get_pre_mlsag_hash()| in the official Monero code base.
For the exact structures definition please refer to the appendix \ref{sec:structs}.

\paragraph{Security implications}
The fact that RingCT signature signs \emph{final\_message\_hash} which includes the \emph{transaction\_prefix\_hash} gives quite strong security guarantees. In fact, the signed TXO can be spent only in the context of the given transaction. The signature cannot be re-used for spending in a different transaction as the verification would fail. This protects from the attack where an attacker takes a valid transaction, reassembles it and submits own tampered version instead of the valid one.
The fact that RingCT signature signs \emph{full\_message\_hash} which includes the \emph{transaction\_prefix\_hash} gives quite strong security guarantees. In fact, the signed TXO can be spent only in the context of the given transaction. The signature cannot be re-used for spending in a different transaction as the verification would fail. This protects from the attack where an attacker takes a valid transaction, reassembles it and submits own tampered version instead of the valid one.

Thus if we can build the transaction prefix and its hash securely in the Trezor we can use the protocol subdivision on the transaction inputs, RingCT signing one input TXO at a time with the offloading result to the host.

Expand All @@ -524,7 +524,7 @@ \subsection{Subdividing output processing}
For an easier description I use the field names used in the JSON transaction representation.\footnote{Example: \url{https://xmrchain.net/tx/599533a7e42e82aa23c8da1d730fec047915ee5614556883cdce90739f1a94d3/1}}

\paragraph{Intro to hashing}
All \emph{final\_message\_hash} components are hashed independently to reduce round trips and save the state memory on the device.
All \emph{full\_message\_hash} components are hashed independently to reduce round trips and save the state memory on the device.
The \emph{tx\_prefix\_hash} is hashed during input and output processing. All inputs and outputs have to be processed in order to compute this hash.

The \emph{rctSigBase} has the following structure with respect to the hashing:
Expand All @@ -549,7 +549,7 @@ \subsection{Subdividing output processing}
\end{figure}


VctPseudoOuts is hashed only for RctSimple transaction type. There are two different UTXO signature schemes, \emph{full} and \emph{simple}. The Full scheme is only used with single UTXO and only with Borromean range signatures. Otherwise the simple mode is used. The VctPseudoOuts is hashed only in the simple mode with the Borromean range signature. The simple mode with Bulletproofs has stored pseudo outputs in the prunnable part of the signature thus it is not hashed.
VctPseudoOuts is hashed only for RctSimple transaction type. There are two different UTXO signature schemes, \emph{full} and \emph{simple}. The Full scheme is only used with single UTXO and only with Borromean range signatures. Otherwise the simple mode is used. The VctPseudoOuts is hashed only in the simple mode with the Borromean range signature. The full mode is used only with Borromean range proof, all Bulletproofs are in the simple mode. Moreover, the simple mode with Bulletproofs has stored pseudo outputs in the prunnable part of the signature thus it is not hashed.

For detailed structure definitions please refer to the Appendix \ref{sec:structs}.

Expand Down Expand Up @@ -600,6 +600,7 @@ \subsection{Data offloading}

This approach can be implemented easily using polymorphism on item access. Vector object defines \\ \verb|__getitem__(self, item)| method which dynamically computes mask from the internal state. For the sequentially accessed masks it can reset the keystream if the index is zero. In this way the object behaves like normally generated mask so there are no changes to the other parts needed.

This offloading technique is currently used only in Bulletproofs implementation to save memory for random mask vectors.

\subsection{Range proof offloading}
Range proof could be potentially offloaded to the host to reduce computation time and the RAM consumption.
Expand Down Expand Up @@ -842,7 +843,7 @@ \subsection{Subdivided protocol overview}
The subdivided protocol description follows:

\begin{enumerate}
\item Initialize the new protocol run as in the original one-step protocol. Send TsxData(version, payment\_id, unlock\_time, outputs, change\_dest, num\_inputs, mixin, fee, account\_id, minor\_indices).
\item Initialize the new protocol run as in the original one-step protocol. Send TsxData(version, payment\_id, unlock\_time, outputs, change\_dest, num\_inputs, mixin, fee, account\_id, minor\_indices, rsig\_data with rsig\_type and rsig\_grouping, integrated\_indices).
\begin{enumerate}
\item Generate transaction master key $k_{mst} = \textit{KDF}(TsxData \; || \; r \; || \; \text{rand\_nonce})$.

Expand All @@ -860,23 +861,23 @@ \subsection{Subdivided protocol overview}
\item $H \rightarrow T$: Send all transaction inputs $T_{in}$, one by one, as \verb|tx_source_entry|.\\
$T_{in,i} = ((\text{idx}, P_j,C_j)_j, \text{amount}, \text{mask}, \pi, \text{pubs}, \dots)_i$
\begin{enumerate}
\item Trezor computes $x_{in}, \mathcal{D}_{in}, I_{in}$. The $x_{in}$ is stored in the Trezor transaction state.
If the number of inputs grows large the secret value
will have to be offloaded in an encrypted form.
\item Trezor computes $x_{in}, \mathcal{D}_{in}, I_{in}$. The $x_{in}$ is offloaded to the host in an encrypted form.

\item Compute transaction prefix field $tx.vin_i$, hash it incrementally to tx prefix hash.

\item Compute HMAC on the data: HMAC($T_{in,i} \; || \; vin_i$), HMAC key: $\textit{KDF}(k_{hmac} \; || \; \text{"txin"} \; || \; i)$.

\item Compute pseudo-out, i.e., Pedersen commitment on the UTXO amount. $ \text{pseudo\_out}_{in} = \alpha_{in} G + \text{amount}_{in} H$.
\item If RCTSimple: Compute pseudo-out, i.e., Pedersen commitment on the UTXO amount. $ \text{pseudo\_out}_{in} = \alpha_{in} G + \text{amount}_{in} H$.

\item Return $tx.vin_i$ part, HMAC($T_{in,i} \; || \; tx.vin_i$), $\text{pseudo\_out}_{in}$, HMAC($\text{pseudo\_out}_{in}$), Chacha20Poly1305($\alpha_{in}$)
\item Return $tx.vin_i$ part, HMAC($T_{in,i} \; || \; tx.vin_i$). If RCTSimple also return: $\text{pseudo\_out}_{in}$, HMAC($\text{pseudo\_out}_{in}$), Chacha20Poly1305($\alpha_{in}$)
\end{enumerate}

\item $H \rightarrow T$: Set inputs permutation, inputs sorted by the key image. Permutation is represented as a simple integer array.

\item $H \rightarrow T$: Send all transaction inputs $T_{in}$, one by one, as \verb|tx_source_entry|, with corresponding $tx.vin_i$ part and HMAC. Trezor verifies the HMAC and incrementally hashes $tx.vin_i$ to the \emph{transaction\_prefix\_hash}. Trezor also hashes $\text{pseudo\_out}_{in}$ to the RctSigBase.

\item $H \rightarrow T$: All inputs set: Finalizes phase of setting inputs. Generates all output commitment masks. If Bulletproof offloading is enabled (number of outputs $\ge 2$) the response contains commitment masks so host can generate the range proof.

\item $H \rightarrow T$: Send all transaction outputs $T_{out}$, one by one, as \verb|tx_destination_entry|, together with corresponding HMAC generated in the init step. $T_{out,i} = ((A_d, B_d), \text{amount}, \dots)_i$. Change output $T_{chx}$ is the last transaction output if $T_{chx} \neq \perp$.
\begin{enumerate}
\item Generate the key derivation $\mathcal{D}_{out}$, i.e., the \emph{amount key}.
Expand All @@ -888,8 +889,8 @@ \subsection{Subdivided protocol overview}
\item Compute the transaction prefix fields $tx.vout_i$ and $tx.extra_i$.

\item Compute range proof on the output amount. \\
- Generate scalar masks for each bit in the output amount $a_{i, j}, j \in [0, 63]$. \\
- The range proof computes $C, rsig = \text{prove\_range}(a_{i, j}, amount_i)$, where $C$ is a Pedersen commitment on the output value: $C = \sum_{j}a_{i, j} G + amount_i H$. \\
- Use commitment masks $a_i$ generated in step 5. \\
- If the range proof is offloaded, check the range proof sent by host. If is generated on the device then compute $C, rsig = \text{prove\_range}(a_i, amount_i)$, where $C$ is a Pedersen commitment on the output value: $C = a_i G + amount_i H$. \\
- Hash the range proof incrementally to the \emph{final\_message}.\\
- Compute $\text{out\_pk}_i = \text{CtKey}(\text{dest}=tx.vout_i.output,\text{mask}=C)$.\\
- Compute $\text{ecdh\_info}_i$ masked with the \emph{amount key}. Plaintext data is $\text{amount}_i$ and mask $\sum_{j}a_{i, j}$. \\ \medskip
Expand All @@ -908,12 +909,12 @@ \subsection{Subdivided protocol overview}
\begin{enumerate}
\item Check that sum of masks from the pseudo-outputs and output commitments are equal $\sum \alpha = \sum a_{i,j}$.

\item Finalize incremental hashing of transaction prefix: hash $\text{out\_pk}_i$ from state. All \emph{final\_message\_hash} components are complete now.
\item Finalize incremental hashing of transaction prefix: hash $\text{out\_pk}_i$ from state.

\item Return transaction prefix hash, tx.extra, initial \emph{RctSig} structure
\end{enumerate}

\item $H \rightarrow T$: Get full message hash. Trezor returns \emph{final\_message\_hash}.
\item $H \rightarrow T$: Get full message hash. Trezor returns \emph{full\_message\_hash}.

\item $H \rightarrow T$: RingCT Sign $T_{in}$. Send all transaction inputs $T_{in}$, one by one, with hmacs, pseudo output, alpha.
\begin{enumerate}
Expand All @@ -930,7 +931,7 @@ \subsection{Subdivided protocol overview}
% TODO: final message, encryption.

\paragraph{Alpha offloading}
The $\alpha_i$ mask values are required during signing (simple RCT variant with \#UTXO $\ge 1$). As the number of UTXO can be quite large the state memory does not have to be big enough to hold all masks. In that case we need to offload the alpha values to the host.
The $\alpha_i$ mask values are required during signing (RCTSimple variant with (\#UTXO $\ge 1$ or Bulletproofs used)). As the number of UTXO can be quite large the state memory does not have to be big enough to hold all masks. In that case we need to offload the alpha values to the host.

The Chacha20Poly1305 is used with the key $\textit{KDF}\left(k_{enc} \; || \; \text{"txin-alpha"} \; || \; i\right)$. The $\alpha_i$ is then passed back to the Trezor in the signing phase. Alternative to offloading is deterministic mask generation described in section \ref{mask_reconstruction}.

Expand All @@ -942,8 +943,8 @@ \subsection{Subdivided protocol overview}

%The message is generated by function \verb|get_pre_mlsag_hash|.
\subsection{Protocol selection}
The multi-step protocol is a generalization of the one-step version.
If the estimated size of the transaction is below a certain value (depends on $|T_{in}|, |T_{out}|, mixin$) the transaction is computed in one step to minimize the roundtrips.
For the sake of simplicity and uniform protocol workflow the current implementation performs all described steps.
The protocol could be simplified a bit if number of UTXO is low so the offloading of UTXO-related information is not needed. In that case one could drop steps 3 and 4 dealing with the key image sort permutation and UTXO hashing.

Multi-sig is not supported in the first implementation.

Expand Down

0 comments on commit 58b286f

Please sign in to comment.