13 May 2024
Today let’s talk a little about more practical security staff. SQL injections is an old kind of security vulnerability
that allows malicious user to execute arbitrary SQL script on you backend. It often causes because of lack of validation
on url query or path parameters that can be applied to the SQL query on your backend. Nowadays, most of popular
frameworks implements a proper validation during SQL construction but if you will try to construct the script by
yourself (without using of popular DAO code generators or built-in SQL library methods) you can miss such validation and
create a big hole in your security.
Let’s take a look on the following example:
stmt := squirrel.Select("*").From("public.users")
params := unsecuresqllib.OffsetPageParams{
Limit: 1,
Order: "desc",
PageNumber: 0,
}
// unsecure ApplyTo method with arguments "sql statement" and "column to apply".
// The last argument causes vulnerability if not validated.
stmt = params.ApplyTo(stmt, "id asc; delete from public.users where id=1; select * from public.users order by id")
str, _, _ := stmt.ToSql()
fmt.Println(str)
// User represents a row from 'public.users'.
type User struct {
ID uint64 `db:"id" json:"id" structs:"-"` // id
Name string `db:"name" json:"name" structs:"name"` // name
}
var users []User
if err := db.SelectContext(context.TODO(), &users, stmt); err != nil {
panic(err)
}
For the table users
with only two columns using an unsecure library (I won’t tell you which one) the simple SELECT
query can be modified by applying order params to drop the entry from this table. This code snippet applies some params
to some statement and some column but the column value is not validated anywhere in the code. Under the hood library
executed stmt = stmt.OrderBy(fmt.Sprintf("%s %s", col, p.Order))
, so the final query that will be submitted to the
database will
be: SELECT * FROM public.users ORDER BY id asc; delete from public.users where id=1; select * from public.users order by id desc LIMIT 1 OFFSET 0
13 May 2024
For the EdDSA signature protocol (that is based on Schnorr authentication scheme) it is required to understand why and
how the challenge is generated. I’ve mentioned earlier that for the challenge generation in the non-interactive protocol
we are using the Fiat-Shamir heuristics. The basic idea is to generate challenges using the hash of all input data. It
is necessary to highlight that we have to include all input data into the hash, otherwise malicious user can be able
to manipulate information that was not included and fixed in hash.
Let’s take a look to the example of challenge generation in EdDSA: it uses the \(c = Hash(aG, K, m)\) and \(r = a + c*
k\) to verify later that \(rG = aG + \hat{c}K\). Using such an approach the signer can not manipulate signature \((A,
r)\) because it’s data is fixed in the challenge. But imagine if we are not including the \(aG\) into the challenge.
Then, malicious signer without any knowledge of private key \(k\) can select a random \(r\) and put the signature as \((
A = rG - cK, r)\). It’s easy to check that such signature passes the verification because verifier can not check that
\(A\) value has been generated randomly and before challenge generation.
08 May 2024
It wasn’t a coincidence that we were talking about *SAG signatures earlier. MLSAG signatures became one of the bases for
Monero blockchain confidentiality and anonymity. Using them, users can create ring signature for spending assets from
one of the keys and nobody will be able to answer “what tokens have been spent?” or “have some certain tokens been
spent?”. This post will describe how RingCT works in Monero and how such
transactions are built.
First of all, let’s take a look on the storage model. Monero uses UTXO-based architecture for storing balances as well
as Bitcoin, so in transactions inputs users operate other transaction outputs. Transaction output constitutes a pair of
elliptic curve points that represents user stealth (one-time) address and hidden amount in Pedersen commitment of form
\(C^a = x\cdot G + a\cdot H\), where \(x\) is a commitment blinding.
Stealth addresses is an approach when sender can transfer money to the generated one-time address of recipient and
nobody will be able to understand that certain two users had any kind of interaction. More precisely, receiver can
share two keys \((K^v, K^s)\) - view key and spend key. Then, sender during the transaction creation will generate a
random value \(r\) and using it will generate a one-time recipient address as \(K^O = H(r\cdot K^v)\cdot G + K^s\).
Also, \(r\cdot G\) will be added to the transaction extra data and called “transaction public key”. Receiver, has to
monitor all transactions and using public transaction data (\(K^O\) and \(rG\)) check if \(K^O - H(k^v\cdot rG)\cdot G =
K^s\). If yes - user understands that he is a receiver of these coins and can also calculate the private key \(k^O = H(
k^v\cdot rG) + k^S\).
So, imagine user wants to transfer some coins using output from other transaction \((K^a_i, C^a_i)\) where
\(i\in\{1,...,m\}\) for the input and \((K^b_j, C^b_j)\) where \(j\in\{1,...,p\}\) for the output (\(K^b_i\) is a
receiver one-time address and \(C^b_j = y_j\cdot G + b_j\cdot H\)). To achieve additional confidentiality, users
generates
\(m\) pseudo-output commitments \(\hat{C}^a_i\) with same amounts but different blinding in a such way that \(\sum
x_i' - \sum y_j = 0\). It’s obvious that
using such construction \(\sum \hat{C}^a_i - \sum C^b_j = 0\), so we can convince verifier that sum of input coins
equals to the output. Also, note that for every \(i\) sender knows the private key for zero-value commitment \(C^a_i
-\hat{C}^a_i= (x_i - x_i')\cdot G = z_i\cdot G\).
Then, for every input \(i\) sender selects a random ring of size \(v+1\) with form:
User can generate a MLSAG signature for using secrets for \(\pi\)
position: \(k_{\pi,j}\) for public key \(K_{\pi,j}\) and \(z_j\) for zero-value commitment \(C^a_
{\pi,i} - \hat{C}^a_{\pi,i} = (x_{\pi,i} - x'_{\pi,i})G\). Also, sender attaches the key image for his key \(K_
{\pi,i}\).
Because this key should be a one-time address we can consider that it can be used only once. So, if there is any
included into the block transaction exist with same key image then we faced the try of double-spending of some output.
Finally, the RingCT transaction (4 equals to type RCTTypeBulletproof2
) consist of:
In conclusion, usage of stealth addresses in a couple with ring signatures and pseudo outputs allows user’s to create an
untraceable transactions with hidden amounts. In particular, stealth addresses helps to hide the connection between
users while ring signatures hides the real output that will be transferred. Finally, pseudo outputs is used to achieve
verification of transacted sum of coins without compromising the achieved anonymity.
05 May 2024
Finally, finishing the posts about ring signatures based on Schnorr authentication protocol we are able to overview the
Multilayer Linkable Spontaneous Anonymous Group (MLSAG) signature protocol. This protocol provides an opportunity to
generate signature with several signers while they are all still hidden in the ring. So, given the ring \(R = \{K_
{i,j}\}\) for \(i \in \{1,2,...n\}\) and \(j \in \{1,2,...m\}\) where we know the private keys \(k_{x,j}\) of the keys
with secret position \(x\) for corresponding public keys \(K_{x,j}\) for \(j \in \{1,2,...m\}\). The MLSAG protocol has
a lot in common with bLSAG protocol:
To verify such signature firstly verifier checks \(\forall j \in \{1,2...m\}: l\cdot\hat{K}_j = 0\) where \(l\) is the
prime order of the big subgroup of our elliptic curve. Then, for the every \(i = 1, 2, ..., n\) (replacing \(n + 1
\rightarrow 1\)) verifier calculates \(c_{i+1} = H(
m, [r_{i,1}\cdot G + c_i\cdot K_{i,1}], [r_{i,1}\cdot H_p(K_{i,1}) + c_i\cdot\hat{K}_1], ...)\) and checks that \(c_1 =
c_1'\).
Finally, if for the two different signatures \(S_1\) and \(S_2\) such indexes \(i,j\) exist that \(\hat{K}_{S_1,i} =
\hat{K}_{S_2,j}\) then these signatures are linked by signing from the same key.
In addition, using signatures linking and one-time stealth addresses Monero blockchain solves a double-spending problem:
if transaction contains the key image that already has been included into the previous block then in seems to be a
double-spending.
05 May 2024
Linkability is a property that describes relation between two signatures. If the protocol has such property
then given two different signatures (ring signatures) it becomes possible to check that them have been produced by the
same signer. Linkability in a couple with anonymity property gives verifier an opportunity to check this relation
without revealing any information about signer.
Back’s Linkable Spontaneous Anonymous Group (bLSAG) signature protocol as a modification of the
described in previous post SAG protocol introduces the ring signature with characterized by anonymity, linkability
properties. Before going thought the protocol let’s describe the special hash function \(H_p(x) \rightarrow \mathbb{G}\)
the gives as the result a point in curve (DL problem can not be solved with overwhelming probability). So, for the given
ring \(R = \{K_1, K_2, ..., K_d\}\) where we know the private key \(k_x\) of the key with secret position \(x\), bLSAG
protocol can be defined as follows:
- Calculate key image \(\hat{K} = k_x\cdot H_p(K_x)\).
- Generate random key \(a\) and \(r_i\) for all \(i\) except of \(i = x\).
- Put \(c_{x+1} = H(m, [a\cdot G], [a\cdot H_p(K_x)])\).
- Then, for every \(i = x+1, x+2, ..., d, 1, 2, ..., x-1\) (replacing \(d + 1 \rightarrow 1\)) calculate \(c_{i+1} = H(
m, [r_i\cdot G + c_i\cdot K_i], [r_i\cdot H_p(K_i) + c_i\cdot\hat{K}])\).
- Put the response \(r_x = a - c_xk_x\).
- Define the signature \((c_1, r_1, ... , r_d)\), ring \(R\) and key image \(\hat{K}\).
To verify such signature firstly verifier checks that \(l\cdot\hat{K} = 0\) where \(l\) is the prime order of the big
subgroup of our elliptic curve. This is required because malicious signer can select points from the subgroup of small
cofactor \(h\) that can affect linkability property. Then, for the every \(i = 1, 2, ..., d\) (replacing \(d + 1
\rightarrow 1\)) verifier calculates \(c_
{i+1}' = H(m, [r_i\cdot G + c_i\cdot K_i], [r_i\cdot H_p(K_i) + c_i\cdot\hat{K}])\) and checks that \(c_1 = c_1'\).
Finally, if the two different signatures (even with different rings) have been produced by the same signer then the both
will
have the same key images \(\hat{K}\).