<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://nickler.ninja/">
  <title>Category: Cpp | nickler&#39;s</title>
  <link href="https://nickler.ninja/categories/cpp/atom.xml" rel="self"/>
  <link href="https://nickler.ninja/"/>
  <updated>2017-05-23T16:41:00+00:00</updated>
  <id>https://jonasnick.github.io/</id>
  <author>
    <name>Jonas Nick</name>
  </author>
  <generator uri="https://www.getzola.org/">Zola</generator>
  <entry>
    <title type="html">Exploiting Low Order Generators in One-Time Ring Signatures</title>
    <link href="https://nickler.ninja/blog/2017/05/23/exploiting-low-order-generators-in-one-time-ring-signatures/"/>
    <updated>2017-05-23T16:41:00+00:00</updated>
    <id>https://jonasnick.github.io/blog/2017/05/23/exploiting-low-order-generators-in-one-time-ring-signatures</id>
    <content type="html">&lt;p&gt;Last week the Monero team disclosed &lt;a rel=&quot;external&quot; href=&quot;https://getmonero.org/2017/05/17/disclosure-of-a-major-bug-in-cryptonote-based-currencies.html&quot;&gt;a major bug in CryptoNote based cryptocurrencies&lt;/a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https://www.reddit.com/r/Monero/comments/6buu5j/disclosure_of_a_major_bug_in_cryptonotebased/&quot;&gt;reddit thread&lt;/a&gt;) which could be used to create “create an infinite amount of coins”.
Monero itself was quietly fixed in February (&lt;a rel=&quot;external&quot; href=&quot;https://github.com/monero-project/monero/releases/tag/v0.10.2&quot;&gt;release&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/monero-project/monero/pull/1744&quot;&gt;pull request&lt;/a&gt;) and the since then every user syncing the blockchain from scratch validates that it was never exploited in Monero.
However, it was used in CryptoNote based shitcoin ByteCoin to create about 700 million &lt;a rel=&quot;external&quot; href=&quot;https://github.com/amjuarez/bytecoin/issues/104&quot;&gt;coins out of thin air&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are already a few good explanations of the bug, for example at the &lt;a rel=&quot;external&quot; href=&quot;https://monero.stackexchange.com/questions/4241/how-does-the-recent-patched-key-image-exploit-work-in-practice&quot;&gt;Monero StackExchange&lt;/a&gt; and the &lt;a rel=&quot;external&quot; href=&quot;https://moderncrypto.org/mail-archive/curves/2017/000898.html&quot;&gt;modern crypto mailing list&lt;/a&gt;.
This article gives additional background about the signature scheme and the properties of the curve that allowed this bug to slip in.&lt;/p&gt;
&lt;p&gt;Apart from the value at stake, this bug is interesting because it shows the risks of breaking a specialized cryptosystems such as &lt;a rel=&quot;external&quot; href=&quot;https://ed25519.cr.yp.to/index.html&quot;&gt;Ed25519&lt;/a&gt; apart and apply the parts in other contexts.
Ed25519 is designed for plain cryptographic signatures and the curve it is based on is used in CryptoNote to implement &lt;em&gt;one-time ring signatures&lt;/em&gt;.
In contrast to a regular signature scheme, one-time ring signatures using the curve require that part of the signature does not generate a small subgroup.
Ensuring this is necessary when &lt;a rel=&quot;external&quot; href=&quot;https://cr.yp.to/ecdh.html#validate&quot;&gt;using curves with a cofactor&lt;/a&gt;. CryptoNote did not do that.&lt;/p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;/span&gt;&lt;h2 id=&quot;hash-based-ring-signatures&quot;&gt;Hash-based ring signatures&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://en.wikipedia.org/wiki/Ring_signature&quot;&gt;A ring signature&lt;/a&gt; proves that the signer is among a &lt;em&gt;set&lt;/em&gt; of public keys (aka “the ring”), without revealing which public key belongs to the signer.
The construction used in CryptoNote/Monero and also for example in &lt;a rel=&quot;external&quot; href=&quot;https://github.com/ElementsProject/secp256k1-zkp&quot;&gt;Confidential Transactions&lt;/a&gt; is based on hash rings.&lt;/p&gt;
&lt;p&gt;For simplicity assume that for now the ring only consists of 1 key, which essentially reduces the scheme to a Schnorr signature.
As usual, &lt;code&gt;G&lt;/code&gt; is a generator of cyclic group in which the discrete logarithm is hard and we’re using additive notation for group operations.
Then the signature scheme consists of the of the following three algorithms (keygen, sign, verify):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;keygen:
draw scalar x uniformly at random
P &amp;lt;- x*G
publish public key P

sign message m (ring size 1):
draw scalar k uniformly at random
e &amp;lt;- hash(m, k*G)
s &amp;lt;- k - e*x
publish signature (e, s)

verify signature (e, s) over message m for public key P (ring size 1):
e == hash(m, s*G + e*P)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s get a basic informal understanding for why such Schnorr based schemes work by taking the perspective of Eve, who does not know the discrete logarithm &lt;code&gt;x&lt;/code&gt; of &lt;code&gt;P&lt;/code&gt;.
Obviously, Eve would invalidate the signature when attempting to just change the message &lt;code&gt;m&lt;/code&gt;.
Further, when trying to fake a signature without knowing &lt;code&gt;x&lt;/code&gt; Eve can not to just set &lt;code&gt;s&lt;/code&gt; as in the regular signing algorithm.
But to make a signature that passes verification for some public key &lt;code&gt;P&lt;/code&gt; Eve must find &lt;code&gt;s&lt;/code&gt;, s.t. &lt;code&gt;k*G = s*G + e*P&lt;/code&gt;.
We can rearrange that in the following way:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;k*G - s*G = e*P
(k - s)*G = e*P
((k - s)/e)*G = P
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That means that if she would find such an &lt;code&gt;s&lt;/code&gt; she could compute the discrete logarithm of &lt;code&gt;P&lt;/code&gt;.
This is a contradiction.&lt;/p&gt;
&lt;p&gt;Note that during verification the output of the hash function &lt;code&gt;e&lt;/code&gt; is also part of the input to the hash function.
How about during signing Eve chooses &lt;code&gt;s&lt;/code&gt; at random and then simply hashes &lt;code&gt;s*G + e*P&lt;/code&gt;?
The problem is that the properties of a cryptographic hash function prevent Eve from knowing &lt;code&gt;e&lt;/code&gt; before before evaluating the hash function.
So &lt;code&gt;e&lt;/code&gt; can not be fed into the hash function and as a consequence &lt;code&gt;s&lt;/code&gt; must be chosen to account for &lt;code&gt;e&lt;/code&gt; only after hashing.&lt;/p&gt;
&lt;p&gt;Rings of size one naturally don’t make a lot of sense but are sufficient for this post’s purpose.
The curious can for example have a look at the explanation in the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Blockstream/borromean_paper/raw/master/borromean_draft_0.01_9ade1e49.pdf&quot;&gt;Borromean signature paper&lt;/a&gt;(section 2.2).&lt;/p&gt;
&lt;h2 id=&quot;one-time-ring-signatures&quot;&gt;One-time ring signatures&lt;/h2&gt;
&lt;p&gt;One-time ring signatures are used in CryptoNote to allow combining the privacy properties of ring signatures with a mechanism to detect double spending.
This is done by introducing the concept of a “key image”.
The key image is a group element that is deterministically derived from a key but in itself doesn’t reveal anything about the key.
Define &lt;code&gt;hashp&lt;/code&gt; to be a hash function that hashes to an element in the group.
Then the key image &lt;code&gt;I&lt;/code&gt; for the key pair &lt;code&gt;(x, P=x*G)&lt;/code&gt; is &lt;code&gt;I = x*hashp(P)&lt;/code&gt; so &lt;code&gt;P&lt;/code&gt; and &lt;code&gt;I&lt;/code&gt; have the same discrete logarithm.
A one-time ring signature includes the key image belonging to the signer.&lt;/p&gt;
&lt;p&gt;The CryptoNote protocol allows using ring signatures when spending coins by enforcing that each key image can occur only once in the blockchain.
Let’s for example assume there are two unspent coins – in our case just represented by public keys &lt;code&gt;P1&lt;/code&gt; and &lt;code&gt;P2&lt;/code&gt;.
Alice knows the private key to &lt;code&gt;P1&lt;/code&gt;, so she can spend the coin by providing a one-time ring signature with &lt;code&gt;P1&lt;/code&gt;, &lt;code&gt;P2&lt;/code&gt; and the key image &lt;code&gt;I&lt;/code&gt; corresponding to &lt;code&gt;P1&lt;/code&gt;.
An observer can not tell whether &lt;code&gt;P1&lt;/code&gt; or &lt;code&gt;P2&lt;/code&gt; was spend.
But if Alice would attempt to spend &lt;code&gt;P1&lt;/code&gt; again (even with a different ring) she would require the same key image which is rejected by the network.
However, &lt;code&gt;P2&lt;/code&gt; can still be spent because the signature uses a different key image.&lt;/p&gt;
&lt;p&gt;Now the concrete one-time ring signature scheme – again shown only for rings of size 1:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;keygen:
draw scalar x uniformly at random
P &amp;lt;- x*G
publish public key P

sign message m (ring size 1):
I &amp;lt;- x*hashp(P)
draw scalar k uniformly at random
e &amp;lt;- hash(m, k*G, k*hashp(P))
s &amp;lt;- k - e*x
publish signature (I, e, s)

verify signature (I, e, s) on message m for public key P (ring size 1):
e == hash(m, s*G + e*P, s*hashp(P) + e*I)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Intuitively, it’s very hard to create a signature where &lt;code&gt;I != x*hashp(P)&lt;/code&gt; because the same &lt;code&gt;s&lt;/code&gt; that is used to prove knowledge of the discrete logarithm &lt;code&gt;x&lt;/code&gt; of &lt;code&gt;P&lt;/code&gt; is also used for &lt;code&gt;I&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The one-time ring signature scheme for rings larger than 1 is described in the &lt;a rel=&quot;external&quot; href=&quot;https://cryptonote.org/whitepaper.pdf&quot;&gt;CryptoNote whitepaper&lt;/a&gt;(section 4.4) although in &lt;a rel=&quot;external&quot; href=&quot;https://bitcointalk.org/index.php?topic=972541.0&quot;&gt;a less space efficient way&lt;/a&gt;.
The construction is also related to the proof of discrete log equality used in &lt;a rel=&quot;external&quot; href=&quot;https://blog.chain.com/preparing-for-a-quantum-future-45535b316314&quot;&gt;perfectly binding Confidential Transactions&lt;/a&gt;.
Note that actually by now a more general scheme that is based on one-time ring signatures called &lt;a rel=&quot;external&quot; href=&quot;http://www.ledgerjournal.org/ojs/index.php/ledger/article/download/34/61&quot;&gt;Ring Confidential Transactions&lt;/a&gt; has replaced regular one-time ring signatures in Monero.&lt;/p&gt;
&lt;h2 id=&quot;low-order-keys-in-ed25519&quot;&gt;Low order keys in Ed25519&lt;/h2&gt;
&lt;p&gt;As mentioned in the beginning, CryptoNote uses Ed25519’s curve (also referred to simply as “Ed25519”) to represent its group elements.
One of Ed25519’s properties is that the number of points on the curve (curve order) is larger than the number of points in the group generated by the base point &lt;code&gt;G&lt;/code&gt; (group order).
The group order is the prime &lt;code&gt;l = 2^252 + 27742317777372353535851937790883648493&lt;/code&gt; and the curve order is &lt;code&gt;8*l&lt;/code&gt;
The ratio of the curve order and the group order is known as the &lt;em&gt;cofactor&lt;/em&gt; which is 8 in the case of Ed25519.
This is, for example, different to the curve secp256k1 used in Bitcoin which has cofactor 1.&lt;/p&gt;
&lt;p&gt;The cofactor indicates that there are groups of low order on the curve.
For example, let &lt;code&gt;P&lt;/code&gt; be the point represented by &lt;code&gt;26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05&lt;/code&gt; then &lt;code&gt;P&lt;/code&gt; generates the (unique) group of order &lt;code&gt;8&lt;/code&gt; which implies &lt;code&gt;8*P = 0&lt;/code&gt;.
There are only few points on the curve with low order.
One way to find them is to generate a random point on the curve with order &lt;code&gt;a*l&lt;/code&gt; and then multiply by &lt;code&gt;l&lt;/code&gt; to get a point of order &lt;code&gt;1 &amp;lt;= a &amp;lt;= 8&lt;/code&gt;.
On the other hand, &lt;code&gt;hashp&lt;/code&gt; ensures that the resulting point is in the prime order group by multiplying it by &lt;code&gt;8&lt;/code&gt; before outputting it.&lt;/p&gt;
&lt;p&gt;In the case of the regular Ed25519 signature algorithm it doesn’t matter if a public key is of low order.
But Ed25519 implementations make sure that a private key is a multiple of 8 (&lt;a rel=&quot;external&quot; href=&quot;https://moderncrypto.org/mail-archive/curves/2017/000858.html&quot;&gt;“clamping”&lt;/a&gt;), so when multiplying it with a low order point then the result is always 0 (instead of leaking bits from the private key).
Therefore, after running the Diffie-Hellman protocol on such a curve the key shared between the two parties can be &lt;code&gt;0&lt;/code&gt; if one party doesn’t behave &lt;a rel=&quot;external&quot; href=&quot;https://cr.yp.to/ecdh.html#validate&quot;&gt;“contributory”&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;attack-fix&quot;&gt;Attack &amp;amp; Fix&lt;/h2&gt;
&lt;p&gt;Assume the attacker owns a coin and therefore can create a regular one-time ring signature to spend it with key image &lt;code&gt;I = x*hashp(P)&lt;/code&gt;.
The attacker can spend the coin again with key &lt;code&gt;I&#39; = I + L&lt;/code&gt; where &lt;code&gt;L&lt;/code&gt; is a low order point with order &lt;code&gt;o&lt;/code&gt;.
Remember the verification equation includes &lt;code&gt;s*hashp(P) + e*I&lt;/code&gt;.
If &lt;code&gt;o&lt;/code&gt; divides &lt;code&gt;e&lt;/code&gt;, (&lt;code&gt;e = e&#39;*o&lt;/code&gt;) then &lt;code&gt;e*I&#39; = e*I + e&#39;*o*L = e*I&lt;/code&gt; so a valid signature with &lt;code&gt;I&#39;&lt;/code&gt; can created in the same way as with &lt;code&gt;I&lt;/code&gt; (except that the message &lt;code&gt;m&lt;/code&gt; now has to commit to &lt;code&gt;I&#39;&lt;/code&gt;).
Since &lt;code&gt;o&lt;/code&gt; is at most &lt;code&gt;8&lt;/code&gt; it is easy to to retry signing until there is a suitable hash &lt;code&gt;e&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Interestingly, in ByteCoin this was exploited in &lt;a rel=&quot;external&quot; href=&quot;https://monero.stackexchange.com/a/4252&quot;&gt;a much less effective way&lt;/a&gt;.
The attacker used a low order public key &lt;code&gt;P&lt;/code&gt; requiring a low order key image &lt;code&gt;I&lt;/code&gt;.
Because there are only 8 low order points on the curve (multiple representations of the same point are disallowed in CryptoNote) this attack can be only performed 8 times in one blockchain.&lt;/p&gt;
&lt;p&gt;The fix implemented in Monero is to verify that each key image &lt;code&gt;I&lt;/code&gt; generates a group of the prime order &lt;code&gt;l&lt;/code&gt; by checking that &lt;code&gt;l*I = 0&lt;/code&gt;.
If &lt;code&gt;I&lt;/code&gt; actually had order &lt;code&gt;l&#39; != l&lt;/code&gt; then for &lt;code&gt;l*I = 0&lt;/code&gt; to hold, &lt;code&gt;l&lt;/code&gt; must be divisible by &lt;code&gt;l&#39;&lt;/code&gt; which is a contradiction because &lt;code&gt;l&lt;/code&gt; is prime.
So the additional cost introduced by the fix is one scalar multiplication per transaction input.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This article gave yet another example for how cryptographic parts can not be easily repurposed.
In particular, when implementing more complex protocols based on curves with a cofactor (like for example Ed25519 or Curve25519) the group order of user supplied generator points should always be verified.
Deciding case-by-case whether that’s necessary is quite dangerous in practice.
There is, however, potential to get rid of this bug class for some cryptosystems by eliminating cofactors through point compression (see &lt;a rel=&quot;external&quot; href=&quot;https://eprint.iacr.org/2015/673.pdf&quot;&gt;Decaf&lt;/a&gt;).
Alternatively, when designing a new cryptosystem it should be considered to use a prime order curve such as &lt;a rel=&quot;external&quot; href=&quot;https://github.com/bitcoin-core/secp256k1&quot;&gt;secp256k1&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title type="html">A Problem with Monero&#39;s RingCT</title>
    <link href="https://nickler.ninja/blog/2016/12/17/a-problem-with-ringct/"/>
    <updated>2016-12-17T17:33:00+00:00</updated>
    <id>https://jonasnick.github.io/blog/2016/12/17/a-problem-with-ringct</id>
    <content type="html">&lt;p&gt;The crypto-currency &lt;a rel=&quot;external&quot; href=&quot;https://getmonero.org/home&quot;&gt;Monero&lt;/a&gt; is about to introduce a new milestone in Blockchain technology: &lt;a rel=&quot;external&quot; href=&quot;https://eprint.iacr.org/2015/1098&quot;&gt;RingCT&lt;/a&gt;.
This is a scheme that allows using &lt;a rel=&quot;external&quot; href=&quot;https://people.xiph.org/~greg/confidential_values.txt&quot;&gt;Confidential Transactions (CT)&lt;/a&gt; while keeping the non-interactive coin mixing typical for Monero.
CT enables hiding the transaction amounts from anyone but sender and receiver while full nodes are still able to verify that input amounts are equal to output amounts.
RingCT is currently not active in Monero; it is designed to be introduced as a hard fork early January.&lt;/p&gt;
&lt;p&gt;I am a complete outsider to Monero and especially the Monero development community, but having reviewed the CT design and implementation (&lt;a rel=&quot;external&quot; href=&quot;https://github.com/ElementsProject/secp256k1-zkp&quot;&gt;in libsecp256k1&lt;/a&gt;) extensively during my day job, I was very interested in the design decisions underlying RingCT.
Very quickly I found a &lt;a rel=&quot;external&quot; href=&quot;https://twitter.com/n1ckler/status/801485209220718592&quot;&gt;red flag&lt;/a&gt; in the ring signature scheme called ASNL used in the range proofs.
This scheme is a new contribution by the paper and indeed turned out to be exploitable such that an &lt;strong&gt;attacker would be able to create coins from nothing&lt;/strong&gt;.
You can find the exploit code on &lt;a rel=&quot;external&quot; href=&quot;https://github.com/jonasnick/monero/commit/ad405e514c7c82bb81d7d49282fa11729420ea85&quot;&gt;GitHub&lt;/a&gt; and a detailed explanation in this post.&lt;/p&gt;
&lt;p&gt;While writing the exploit code and preparing this blog post I learned that &lt;a rel=&quot;external&quot; href=&quot;https://github.com/monero-project/research-lab/issues/4&quot;&gt;an anonymous person called RandomRun reported&lt;/a&gt; a flaw in the security proof of ASNL, which convinced the Monero devs to publish a &lt;a rel=&quot;external&quot; href=&quot;https://github.com/monero-project/monero/releases/tag/v0.10.1&quot;&gt;bugfix release&lt;/a&gt; that switches to &lt;a rel=&quot;external&quot; href=&quot;https://github.com/ElementsProject/borromean-signatures-writeup&quot;&gt;Borromean signatures&lt;/a&gt; (good call!).
As a result &lt;strong&gt;the upcoming hard fork will not be vulnerable to this exploit&lt;/strong&gt;.
Interestingly, the error in the security proof is exactly the flip-side of the vulnerability discussed in this post.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;EDIT:&lt;/strong&gt; The Monero community reacted to this article (&lt;a rel=&quot;external&quot; href=&quot;https://www.reddit.com/r/Monero/comments/5j4z1e/a_problem_with_ring_ct/&quot;&gt;see reddit&lt;/a&gt;) but they didn’t like its style. Also, they got the timeline of the discovery of the bug wrong.&lt;/p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;/span&gt;
&lt;p&gt;I have the highest respect for RandomRun and parts of the Monero community.
It takes an incredibly strong character to drop an 0day worth tens of millions USD.
However, that the original hard fork schedule of RingCT remains unchanged despite a complete break of the system raises more than a few questions.
Even more so when the author of RingCT &lt;a rel=&quot;external&quot; href=&quot;https://github.com/monero-project/research-lab/issues/4#issuecomment-256261207&quot;&gt;called for more review&lt;/a&gt; by the end of October.&lt;/p&gt;
&lt;h2 id=&quot;aggregate-schnorr-non-linkable-ring-signature-asnl&quot;&gt;Aggregate Schnorr Non-linkable Ring Signature (ASNL)&lt;/h2&gt;
&lt;p&gt;Confidential transactions include a range proof to prevent negative amounts.
These range proofs use a generalization of ring signatures in which
the conjunction of multiple rings is proven, for example that the prover knows the discrete logarithm of &lt;code&gt;(Pk1 OR Pk2) AND (Pk1 OR Pk3) AND ...&lt;/code&gt;
The original CT scheme introduced Borromean signatures for that purpose which are based on rings of hashes and provide space savings when public keys appear more than once.&lt;/p&gt;
&lt;p&gt;Instead, the RingCT paper proposes a new scheme called Aggregate Schnorr Non-linkable Ring Signature because it has “perhaps simpler security proofs” (RingCT paper).&lt;/p&gt;
&lt;p&gt;A ASNL signature consists tuples &lt;code&gt;(P1_j, P2_j, L1_j, s2_j)&lt;/code&gt; for &lt;code&gt;j = 1, ..., n&lt;/code&gt; and &lt;code&gt;s&lt;/code&gt; which
is supposed to prove that the signer knows the DL of &lt;code&gt;(P1_1 OR P2_1) AND ... AND (P1_n OR P2_n)&lt;/code&gt;.
Let’s consider the &lt;code&gt;n = 1&lt;/code&gt; case (no conjunction) informally.
The verifier checks that&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;L1 = s*G + H(s2*G + H(L1)*P2)*P1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;H&lt;/code&gt; is a hash function.&lt;/p&gt;
&lt;p&gt;So either&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The prover knows the DL &lt;code&gt;x&lt;/code&gt; of &lt;code&gt;P1&lt;/code&gt; then sets&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;a, s2 &amp;lt;- random scalar
L1    &amp;lt;- a*G
s     &amp;lt;- a - H(s2*G + H(L1)*P2)*x
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Or the prover knows the DL &lt;code&gt;x&lt;/code&gt; of &lt;code&gt;P2&lt;/code&gt; then sets&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;a, s &amp;lt;- random scalar
L1   &amp;lt;- s*G +H(a*G)*P1
s2   &amp;lt;- a - x*H(L1)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the case of multiple conjunctions (&lt;code&gt;n &amp;gt; 1&lt;/code&gt;), the verifier computes &lt;code&gt;LHS &amp;lt;- L1_1 + ... L1_n&lt;/code&gt; and &lt;code&gt;RHS &amp;lt;- s*G + H(s2_1*G + H(L1_1)P2_1)P1_1 + ... + H(s2_n*G + H(L1_n)P2_n)P1_n&lt;/code&gt; and checks that &lt;code&gt;LHS = RHS&lt;/code&gt;.
In short, this is vulnerable because you can just choose some &lt;code&gt;L1_j&lt;/code&gt; such that it cancels out the summand on the right hand side where both DLs of P1 and P2 are unknown.
In contrast, the “proof” of security of ASNL assumes that any adversaries knows &lt;code&gt;a&lt;/code&gt; s.t. &lt;code&gt;a*G = L1_j&lt;/code&gt; for all &lt;code&gt;j&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;forgery&quot;&gt;Forgery&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/jonasnick/monero/commit/ad405e514c7c82bb81d7d49282fa11729420ea85&quot;&gt;Implementation&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Theorem
Given any curve points P1_1, P2_1, an adversary is able to forge a ASNL signature
(P1_j, P2_j, L1_j, s2_j) for j=1, ..., n and s where n &amp;gt; 1 such that ASNL verify accepts.

Proof
Without loss of generality assume n = 2.
1. Let P1_2 = xG
    Set
    a, s2_1, s2_2 &amp;lt;- random scalar
    L1_1 &amp;lt;- a*G
    L1_2 &amp;lt;- H(s2_1*G + H(L1_1)*P2_1)*P1_1
    s &amp;lt;- a - H(s2_2*G + H(L1_2)*P2_2)*x
    Then during verification it holds that
    L1_1 + L1_2 = s*G + H(s2_1*G + H(L1_1)*P2_1)*P1_1 + H(s2_2*G + H(L1_2)*P2_2)*P1_2
    &amp;lt;=&amp;gt; L1_1 = (a - H(s2_2*G + H(L1_2)*P2_2)*x)*G + H(s2_2*G + H(L1_2)*P2_2)*P1_2
    &amp;lt;=&amp;gt; L1_1 = a*G
2. Let P2_2 = xG
    Set
    a, s, s2_1 &amp;lt;- random scalar
    L2_2 &amp;lt;- a*G
    L1_1 &amp;lt;- s*G + H(L2_2)*P1_2
    L1_2 &amp;lt;- H(s2_1*G + H(L1_1)*P2_1)*P1_1
    s2_2 &amp;lt;- a - H(L1_2)*x
    Then during verification it holds that
    L1_1 + L1_2 = s*G + H(s2_1*G + H(L1_1)*P2_1)*P1_1 + H(s2_2*G + H(L1_2)*P2_2)*P1_2
    &amp;lt;=&amp;gt; L1_1 = s*G + H(s2_2 + H(L1_2)*P2_2)*P1_2
    &amp;lt;=&amp;gt; L1_1 = s*G + H(a*G)*P1_2
&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <title type="html">Labormensch - a Puzzle</title>
    <link href="https://nickler.ninja/blog/2012/11/28/labormensch-a-puzzle/"/>
    <updated>2012-11-28T20:31:00+00:00</updated>
    <id>https://jonasnick.github.io/blog/2012/11/28/labormensch-a-puzzle</id>
    <content type="html">&lt;p&gt;This is a mod for Valve’s source engine. It deludes the player’s cognitive map of the world. Despite his efforts to escape he always returns to his start location. However there is one solution to escape…&lt;/p&gt;
&lt;iframe class=&quot;youtube-player&quot; width=&quot;420&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/3QaHo0QgKeQ&quot;&gt;&lt;/iframe&gt;
</content>
  </entry>
</feed>
