You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Triptych, a next-generation transaction protocol under consideration for Monero, uses a style of key images different from Monero's current key images (also RingCT3.0 and one version of Omniring). This poses some challenges for multisig-based transactions, where key images must be constructed by collaboration between cosigners. Other details related to multisig are not discussed here.
Note: To transition from current bLSAG-style key images to inversion-style key images, the question of verifying double spends comes up, since double spends are identified when the same key image appears. The simple solution is that post-hardfork all new outputs can only be spent with TriptychType1 transactions (that use Triptych to sign them), while all old (pre-Triptych) outputs can only be spent with RingCT transactions (signing with MLSAG, or CLSAG). This way key images are clearly related to subsets of outputs, with no risk of cross-over. Note that in practice it means ring membership is constrained.
Key images; before and after
Using the hash-to-point function H_p(), and one-time address K^o (with private key k^o), our current key images are made like this KI = k^o*H_p(K^o)
In Triptych (and others), key images are made like this, where U is an elliptic curve generator (not the normal one G), e.g. U = H_p("U") (or something similar) KI^{inv} = (1/k^o)*U
Current multisig, where multiple participants, indexed e, own components of the group's private key (e.g. k^{o,grp} = k^o_1 + k^o_2 + ...) reconstruct the key image as a simple sum KI = \sum k^o_e*H_p(K^{o,grp})
Clearly that won't work with Triptych key images, which contain an inversion of the private key. Thankfully, Paillier encryption, which I won't pretend to understand, provides a route to constructing aggregate inversions without compromising any participant's share of the full private key (see Gennaro and Goldfeder's original paper, especially Section 3).
Inversion-style aggregate key images for multisig
The method explained here was first explored for Monero by @SarangNoether. My objective is to document the process (also documented by sarang here), and also recommend some optimizations regarding message rounds.
An aside: Paillier encryption
First it will be helpful to lay out Paillier encryption, which is very RSA-esque.
A person has a public key N = p*q, where p and q are prime numbers. The private key is phi = (p-1)*(q-1) mod N^2.
Encrypt a message m using a randomly generated scalar r with E(m) = [(1+N)^m * r^N] mod N^2.
Decrypt with m = [[E(m)^(phi) mod N^2 - 1]/N * (1/phi mod N)] mod N. Note that r 'disappears' during decryption, and so only the encrypter needs to know it.
The process
There are many participants, indexed e, with components k_e of a group key k^{grp}, where the aggregate public key is K^{grp} = (\sum k_e)*G, who wish to construct the inversion-style key image KI^{inv} = (1/k^{grp})*U. In each round participants will perform some computations then send information to other participants, and the next round doesn't begin until the previous round is done.
Each participant must learn the other participants' Paillier public keys N_e.
Each participant e
a) privately generates a random scalar gamma_e, computes gamma_e*U, and generates a Schnorr signature sigma_e proving knowledge of gamma_e in gamma_e*U
b) privately generates a commitment mask x_e, and computes the commitment C_e = H_p("MPC gamma commit", gamma_e*U, x_e)
c) privately, for each other participant i, generate a random scalar beta_e_i
d) privately encrypts their private key with their Paillier public key N_e,E_e = E_e(k_e)
e) sends C_e and E_e to the other participants
Each participant e
a) privately computes, for each other participant i (using the value beta_e_i generated for them earlier), c_e_i = [E_i(x)^gamma_e mod N_i^2]*E_i(-beta_e_i) mod N_i^2
b) sends c_e_i to participant i
Each participant e
a. privately computes, using the values c_e_i received from other participants, alpha_e_i = decrypt(c_e_i, N_e) for each of those participants; this is where the Paillier encryption magic shows its face (although exactly how, I couldn't say)
b. privately computes local_delta_e = k_e*gamma_e + \sum_i alpha_e_i + \sum_i beta_e_i
c. sends gamma_e*U (the value committed to in C_e) and x_e, sigma_e, and local_delta_e to the other participants
Each participant e
a. privately verifies for each other participant i, that C_i ?= H_p("MPC gamma commit", gamma_i*U, x_i)
b. privately computes the full key image KI^{inv} = (\sum_e local_delta_e)^(-1)*(\sum gamma_e*U)
Seamless escrowed multisig
For a 2-of-3 escrowed marketplace, with buyer, vendor, and moderator, it is important to minimize the number of communication rounds. Escrowed markets with the current Monero transaction protocol can do collaborative transaction signing in the following steps (A is the buyer, B is the vendor). Please see Zero to Monero: Second Edition, chapter 10. There is a controversial optimization, namely single-commitment signing, which I won't get into here, but is a big part of the system I designed (and also part of this key image process).
Buyer (A) encounters vendor's (B's) shop. A collects some information found at the shop, which may be useful for an escrowed purchase.
A: initiates transaction (message sent to B)
B: creates partial transaction (message sent to A)
A: partially signs transaction (message sent to B)
B: finishes signing transaction (submits tx to nextwork)
Thankfully, making inversion-style key images can fit into that framework without disrupting the existing pattern.
A: collects N_B, and E_B, which were pre-computed/prepared by B. B's private key component is the shared secret between buyer-moderator, while A's private key component will be the sum of buyer-vendor and buyer-moderator key components and the part related to the sender-receiver shared secret based on the view key for a given one-time address owned by the multisig group (for efficiency, even though the buyer will also know the buyer-vendor key component and view key component).
B: [privately] computes alpha_B_A, generates beta_B_A; [stuff to send] computes c_A_B, local_delta_B, gamma_B*U, sigma_B. He does not create a commitment for gamma_B*U (I don't know if this is a legitimate simplification).
After a multisig group key image has been created, it is useful to also prove it is a legitimate key so other cosigners can learn it without needing to go through the whole process again. The most straightforward way, which any M cosigners (for M-of-N multisig) can do together, is a multibase Schnorr signature on base keys (G, KI^{inv}), and public keys (K^(grp), U) (see zero to monero 2 chapter 8 and section 9.5).
Triptych, a next-generation transaction protocol under consideration for Monero, uses a style of key images different from Monero's current key images (also RingCT3.0 and one version of Omniring). This poses some challenges for multisig-based transactions, where key images must be constructed by collaboration between cosigners. Other details related to multisig are not discussed here.
Note: To transition from current bLSAG-style key images to inversion-style key images, the question of verifying double spends comes up, since double spends are identified when the same key image appears. The simple solution is that post-hardfork all new outputs can only be spent with TriptychType1 transactions (that use Triptych to sign them), while all old (pre-Triptych) outputs can only be spent with RingCT transactions (signing with MLSAG, or CLSAG). This way key images are clearly related to subsets of outputs, with no risk of cross-over. Note that in practice it means ring membership is constrained.
Key images; before and after
Using the hash-to-point function
H_p()
, and one-time addressK^o
(with private keyk^o
), our current key images are made like thisKI = k^o*H_p(K^o)
In Triptych (and others), key images are made like this, where
U
is an elliptic curve generator (not the normal oneG
), e.g.U = H_p("U")
(or something similar)KI^{inv} = (1/k^o)*U
Current multisig, where multiple participants, indexed
e
, own components of the group's private key (e.g.k^{o,grp} = k^o_1 + k^o_2 + ...
) reconstruct the key image as a simple sumKI = \sum k^o_e*H_p(K^{o,grp})
Clearly that won't work with Triptych key images, which contain an inversion of the private key. Thankfully, Paillier encryption, which I won't pretend to understand, provides a route to constructing aggregate inversions without compromising any participant's share of the full private key (see Gennaro and Goldfeder's original paper, especially Section 3).
Inversion-style aggregate key images for multisig
The method explained here was first explored for Monero by @SarangNoether. My objective is to document the process (also documented by sarang here), and also recommend some optimizations regarding message rounds.
An aside: Paillier encryption
First it will be helpful to lay out Paillier encryption, which is very RSA-esque.
N = p*q
, wherep
andq
are prime numbers. The private key isphi = (p-1)*(q-1) mod N^2
.m
using a randomly generated scalarr
withE(m) = [(1+N)^m * r^N] mod N^2
.m = [[E(m)^(phi) mod N^2 - 1]/N * (1/phi mod N)] mod N
. Note thatr
'disappears' during decryption, and so only the encrypter needs to know it.The process
There are many participants, indexed
e
, with componentsk_e
of a group keyk^{grp}
, where the aggregate public key isK^{grp} = (\sum k_e)*G
, who wish to construct the inversion-style key imageKI^{inv} = (1/k^{grp})*U
. In each round participants will perform some computations then send information to other participants, and the next round doesn't begin until the previous round is done.N_e
.e
a) privately generates a random scalar
gamma_e
, computesgamma_e*U
, and generates a Schnorr signaturesigma_e
proving knowledge ofgamma_e
ingamma_e*U
b) privately generates a commitment mask
x_e
, and computes the commitmentC_e = H_p("MPC gamma commit", gamma_e*U, x_e)
c) privately, for each other participant
i
, generate a random scalarbeta_e_i
d) privately encrypts their private key with their Paillier public key
N_e
,E_e = E_e(k_e)
e) sends
C_e
andE_e
to the other participantse
a) privately computes, for each other participant
i
(using the valuebeta_e_i
generated for them earlier),c_e_i = [E_i(x)^gamma_e mod N_i^2]*E_i(-beta_e_i) mod N_i^2
b) sends
c_e_i
to participanti
e
a. privately computes, using the values
c_e_i
received from other participants,alpha_e_i = decrypt(c_e_i, N_e)
for each of those participants; this is where the Paillier encryption magic shows its face (although exactly how, I couldn't say)b. privately computes
local_delta_e = k_e*gamma_e + \sum_i alpha_e_i + \sum_i beta_e_i
c. sends
gamma_e*U
(the value committed to inC_e
) andx_e
,sigma_e
, andlocal_delta_e
to the other participantse
a. privately verifies for each other participant
i
, thatC_i ?= H_p("MPC gamma commit", gamma_i*U, x_i)
b. privately computes the full key image
KI^{inv} = (\sum_e local_delta_e)^(-1)*(\sum gamma_e*U)
Seamless escrowed multisig
For a 2-of-3 escrowed marketplace, with buyer, vendor, and moderator, it is important to minimize the number of communication rounds. Escrowed markets with the current Monero transaction protocol can do collaborative transaction signing in the following steps (A is the buyer, B is the vendor). Please see Zero to Monero: Second Edition, chapter 10. There is a controversial optimization, namely single-commitment signing, which I won't get into here, but is a big part of the system I designed (and also part of this key image process).
Thankfully, making inversion-style key images can fit into that framework without disrupting the existing pattern.
N_B
, andE_B
, which were pre-computed/prepared by B. B's private key component is the shared secret between buyer-moderator, while A's private key component will be the sum of buyer-vendor and buyer-moderator key components and the part related to the sender-receiver shared secret based on the view key for a given one-time address owned by the multisig group (for efficiency, even though the buyer will also know the buyer-vendor key component and view key component).gamma_A
, computesgamma_A*U
, generatesx_A
, generatesbeta_A_B
; [stuff to send] computesE_A
,c_B_A
,C_A
, and prepares Paillier keyN_A
alpha_B_A
, generatesbeta_B_A
; [stuff to send] computesc_A_B
,local_delta_B
,gamma_B*U
,sigma_B
. He does not create a commitment forgamma_B*U
(I don't know if this is a legitimate simplification).alpha_A_B
,KI^{inv}
; [stuff to send]gamma_A*U
,x_A
, createssigma_A
, computeslocal_delta_A
C_A
, and computesKI^{inv}
Crucially, A learns
K^{inv}
in step 3 when she needs to make her partial signature, and likewise B learns it in step 4 when he finishes the signature.The text was updated successfully, but these errors were encountered: