From 7472c79283202ad9e40f2c912a3340d558921722 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 6 May 2019 09:44:31 -0700 Subject: [PATCH 1/2] lift_x returns a point, not a tuple --- bip-schnorr.mediawiki | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index d4e4ff18ca..adc9496e6b 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -103,10 +103,10 @@ The following convention is used, with constants as defined for secp256k1: ** The function ''point(x)'', where ''x'' is a 33-byte array, returns the point ''P'' for which ''x(P) = int(x[1:33])'' and ''y(P) & 1 = int(x[0:1]) - 0x02)'', or fails if no such point exists. The function ''point(x)'' is equivalent to the following pseudocode: *** Fail if (''x[0:1] ≠ 0x02'' and ''x[0:1] ≠ 0x03''). *** Set flag ''odd'' if ''x[0:1] = 0x03''. -*** Let ''(r, y) = lift_x(x)''; fail if ''lift_x(x)'' fails. -*** If (flag ''odd'' is set and ''y'' is an even integer) or (flag ''odd'' is not set and ''y'' is an odd integer): -**** Let ''y = p - y''. -*** Return ''(r, y)''. +*** Let ''P = lift_x(x)''; fail if ''lift_x(x)'' fails. +*** If (flag ''odd'' is set and ''y(P)'' is an even integer) or (flag ''odd'' is not set and ''y(P)'' is an odd integer): +**** Return ''-P'' +*** Return ''P''. ** The function ''hash(x)'', where ''x'' is a byte array, returns the 32-byte SHA256 hash of ''x''. ** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. From 97b541a4048590cbc6fd7d35d4a6776ede83555a Mon Sep 17 00:00:00 2001 From: jackiszhp <94544458@qq.com> Date: Thu, 15 Aug 2019 06:49:41 +0800 Subject: [PATCH 2/2] a typo explaining lift_x(x), x(P)=x, there is not r here. though usually it is the r part of the signature. --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index adc9496e6b..93253ab4e0 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -99,7 +99,7 @@ The following convention is used, with constants as defined for secp256k1: ** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''y(P)'' is a quadratic residue modulo ''p'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. -*** Return ''(r, y)''. +*** Return ''(x, y)''. ** The function ''point(x)'', where ''x'' is a 33-byte array, returns the point ''P'' for which ''x(P) = int(x[1:33])'' and ''y(P) & 1 = int(x[0:1]) - 0x02)'', or fails if no such point exists. The function ''point(x)'' is equivalent to the following pseudocode: *** Fail if (''x[0:1] ≠ 0x02'' and ''x[0:1] ≠ 0x03''). *** Set flag ''odd'' if ''x[0:1] = 0x03''.