github.com/hhwill/poc-eth@v0.0.0-20240218063348-3bb107c90dbf/crypto/curve25519/curve25519.go (about)

     1  package curve25519
     2  
     3  import "bytes"
     4  
     5  /* group order (a prime near 2^252+2^124) */
     6  var order = []byte{
     7  	237, 211, 245, 92, 26, 99, 18, 88,
     8  	214, 156, 247, 162, 222, 249, 222, 20,
     9  	0, 0, 0, 0, 0, 0, 0, 0,
    10  	0, 0, 0, 0, 0, 0, 0, 16,
    11  }
    12  
    13  /* smallest multiple of the order that's >= 2^255 */
    14  var orderTimes8 = []byte{
    15  	104, 159, 174, 231, 210, 24, 147, 192,
    16  	178, 230, 188, 23, 245, 206, 247, 166,
    17  	0, 0, 0, 0, 0, 0, 0, 0,
    18  	0, 0, 0, 0, 0, 0, 0, 128,
    19  }
    20  
    21  /* Private key clamping
    22   *   k [out] your private key for key agreement
    23   *   k [in]  32 random bytes
    24   */
    25  func clamp(k []byte) {
    26  	k[31] &= 0x7F
    27  	k[31] |= 0x40
    28  	k[0] &= 0xF8
    29  }
    30  
    31  /* Key-pair generation
    32   *   P  [out] your public key
    33   *   s  [out] your private key for signing, may be nil if you don't care
    34   *   k  [out] your private key for key agreement
    35   *   k  [in]  32 random bytes
    36   *
    37   * WARNING: if s is not NULL, this function has data-dependent timing */
    38  func keygen(P, s, k []byte) {
    39  	clamp(k)
    40  	core(P, s, k, nil)
    41  }
    42  
    43  /* Key agreement
    44   *   Z  [out] shared secret (needs hashing before use)
    45   *   k  [in]  your private key for key agreement
    46   *   P  [in]  peer's public key
    47   */
    48  func curve(Z, k, P []byte) {
    49  	core(Z, nil, k, P)
    50  }
    51  
    52  /* P = kG  and s = sign(P)/k  */
    53  func core(Px, s, k, Gx []byte) {
    54  	dx := new(long10)
    55  	t1 := new(long10)
    56  	t2 := new(long10)
    57  	t3 := new(long10)
    58  	t4 := new(long10)
    59  
    60  	x := [2]*long10{new(long10), new(long10)}
    61  	z := [2]*long10{new(long10), new(long10)}
    62  
    63  	/* unpack the base */
    64  	if Gx != nil {
    65  		dx.unpack(Gx)
    66  
    67  	} else {
    68  		dx.set(9)
    69  	}
    70  
    71  	/* 0G = point-at-infinity */
    72  	x[0].set(1)
    73  	z[0].set(0)
    74  
    75  	/* 1G = G */
    76  	x[1].cpy(dx)
    77  	z[1].set(1)
    78  
    79  	for i := 31; i >= 0; i-- {
    80  		for j := 7; j >= 0; j-- {
    81  			/* swap arguments depending on bit */
    82  			uj := uint(j)
    83  			bit1 := (k[i] & 0xFF) >> uj & 1
    84  			bit0 := ^(k[i] & 0xFF) >> uj & 1
    85  
    86  			ax := x[bit0]
    87  			az := z[bit0]
    88  			bx := x[bit1]
    89  			bz := z[bit1]
    90  
    91  			/* a' = a + b */
    92  			/* b' = 2 b */
    93  			montPrep(t1, t2, ax, az)
    94  			montPrep(t3, t4, bx, bz)
    95  			montAdd(t1, t2, t3, t4, ax, az, dx)
    96  			montDbl(t1, t2, t3, t4, bx, bz)
    97  		}
    98  	}
    99  
   100  	t1.recip(z[0], false)
   101  	dx.mul(x[0], t1)
   102  	dx.pack(Px)
   103  
   104  	/* calculate s such that s abs(P) = G  .. assumes G is std base point */
   105  	if s != nil {
   106  		t1.xToY2(dx, t2)      /* t1 = Py^2  */
   107  		t3.recip(z[1], false) /* where Q=P+G ... */
   108  		t2.mul(x[1], t3)      /* t2 = Qx  */
   109  		t2.add(t2, dx)        /* t2 = Qx + Px  */
   110  		t2[0] += 9 + 486662   /* t2 = Qx + Px + Gx + 486662  */
   111  		dx[0] -= 9            /* dx = Px - Gx  */
   112  		t3.sqr(dx)            /* t3 = (Px - Gx)^2  */
   113  		dx.mul(t2, t3)        /* dx = t2 (Px - Gx)^2  */
   114  		dx.sub(dx, t1)        /* dx = t2 (Px - Gx)^2 - Py^2  */
   115  		dx[0] -= 39420360     /* dx = t2 (Px - Gx)^2 - Py^2 - Gy^2  */
   116  		t1.mul(dx, baseR2y)   /* t1 = -Py  */
   117  		if t1.isNegative() {  /* sign is 1, so just copy  */
   118  			copy(s, k)
   119  		} else { /* sign is -1, so negate  */
   120  			mulaSmall(s, orderTimes8, 0, k, 32, -1)
   121  		}
   122  
   123  		/* reduce s mod q
   124  		 * (is this needed?  do it just in case, it's fast anyway) */
   125  		//divmod((dstptr) t1, s, 32, order25519, 32);
   126  
   127  		/* take reciprocal of s mod q */
   128  		temp1 := make([]byte, 32)
   129  		temp2 := make([]byte, 64)
   130  		temp3 := make([]byte, 64)
   131  		copy(temp1, order)
   132  		copy(s, egcd32(temp2, temp3, s, temp1))
   133  		if (s[31] & 0x80) != 0 {
   134  			mulaSmall(s, s, 0, order, 32, 1)
   135  		}
   136  	}
   137  }
   138  
   139  /* deterministic EC-KCDSA
   140   *
   141   *    s is the private key for signing
   142   *    P is the corresponding public key
   143   *    Z is the context data (signer public key or certificate, etc)
   144   *
   145   * signing:
   146   *
   147   *    m = hash(Z, message)
   148   *    x = hash(m, s)
   149   *    keygen25519(Y, NULL, x);
   150   *    r = hash(Y);
   151   *    h = m XOR r
   152   *    sign25519(v, h, x, s);
   153   *
   154   *    output (v,r) as the signature
   155   *
   156   * verification:
   157   *
   158   *    m = hash(Z, message);
   159   *    h = m XOR r
   160   *    verify25519(Y, v, h, P)
   161   *
   162   *    confirm  r == hash(Y)
   163   *
   164   * It would seem to me that it would be simpler to have the signer directly do
   165   * h = hash(m, Y) and send that to the recipient instead of r, who can verify
   166   * the signature by checking h == hash(m, Y).  If there are any problems with
   167   * such a scheme, please let me know.
   168   *
   169   * Also, EC-KCDSA (like most DS algorithms) picks x random, which is a waste of
   170   * perfectly good entropy, but does allow Y to be calculated in advance of (or
   171   * parallel to) hashing the message.
   172   */
   173  
   174  /* Signature generation primitive, calculates (x-h)s mod q
   175   *   v  [out] signature value
   176   *   h  [in]  signature hash (of message, signature pub key, and context data)
   177   *   x  [in]  signature private key
   178   *   s  [in]  private key for signing
   179   * returns true on success, false on failure (use different x or h)
   180   */
   181  func sign(v, h, x, s []byte) bool {
   182  	// v = (x - h) s  mod q
   183  	h1 := make([]byte, 32)
   184  	x1 := make([]byte, 32)
   185  	tmp1 := make([]byte, 64)
   186  	tmp2 := make([]byte, 64)
   187  	tmp3 := make([]byte, 32)
   188  
   189  	// Don't clobber the arguments, be nice!
   190  	copy(h1, h)
   191  	copy(x1, x)
   192  
   193  	// Reduce modulo group order
   194  	divmod(tmp3, h1, 32, order, 32)
   195  	divmod(tmp3, x1, 32, order, 32)
   196  
   197  	// v = x1 - h1
   198  	// If v is negative, add the group order to it to become positive.
   199  	// If v was already positive we don't have to worry about overflow
   200  	// when adding the order because v < ORDER and 2*ORDER < 2^256
   201  	mulaSmall(v, x1, 0, h1, 32, -1)
   202  	mulaSmall(v, v, 0, order, 32, 1)
   203  
   204  	// tmp1 = (x-h)*s mod q
   205  	mula32(tmp1, v, s, 32, 1)
   206  	divmod(tmp2, tmp1, 64, order, 32)
   207  	w := byte(0)
   208  	for i := 0; i < 32; i++ {
   209  		v[i] = tmp1[i]
   210  		w |= tmp1[i]
   211  	}
   212  	return w != 0
   213  }
   214  
   215  /* Signature verification primitive, calculates Y = vP + hG
   216   *   Y  [out] signature public key
   217   *   v  [in]  signature value
   218   *   h  [in]  signature hash
   219   *   P  [in]  public key
   220   */
   221  func verify(Y, v, h, P []byte) {
   222  	/* Y = v abs(P) + h G  */
   223  	d := make([]byte, 32)
   224  	p := [2]*long10{new(long10), new(long10)}
   225  	s := [2]*long10{new(long10), new(long10)}
   226  	yx := [3]*long10{new(long10), new(long10), new(long10)}
   227  	yz := [3]*long10{new(long10), new(long10), new(long10)}
   228  	t1 := [3]*long10{new(long10), new(long10), new(long10)}
   229  	t2 := [3]*long10{new(long10), new(long10), new(long10)}
   230  
   231  	/* set p[0] to G and p[1] to P  */
   232  
   233  	p[0].set(9)
   234  	p[1].unpack(P)
   235  
   236  	/* set s[0] to P+G and s[1] to P-G  */
   237  
   238  	/* s[0] = (Py^2 + Gy^2 - 2 Py Gy)/(Px - Gx)^2 - Px - Gx - 486662  */
   239  	/* s[1] = (Py^2 + Gy^2 + 2 Py Gy)/(Px - Gx)^2 - Px - Gx - 486662  */
   240  
   241  	t2[0].xToY2(p[1], t1[0]) /* t2[0] = Py^2  */
   242  	t1[0].sqrt(t2[0])        /* t1[0] = Py or -Py  */
   243  	j := 0
   244  	if t1[0].isNegative() {
   245  		j = 1
   246  	}
   247  	t2[0][0] += 39420360      /* t2[0] = Py^2 + Gy^2  */
   248  	t2[1].mul(base2y, t1[0])  /* t2[1] = 2 Py Gy or -2 Py Gy  */
   249  	t1[j].sub(t2[0], t2[1])   /* t1[0] = Py^2 + Gy^2 - 2 Py Gy  */
   250  	t1[1-j].add(t2[0], t2[1]) /* t1[1] = Py^2 + Gy^2 + 2 Py Gy  */
   251  	t2[0].cpy(p[1])           /* t2[0] = Px  */
   252  	t2[0][0] -= 9             /* t2[0] = Px - Gx  */
   253  	t2[1].sqr(t2[0])          /* t2[1] = (Px - Gx)^2  */
   254  	t2[0].recip(t2[1], false) /* t2[0] = 1/(Px - Gx)^2  */
   255  	s[0].mul(t1[0], t2[0])    /* s[0] = t1[0]/(Px - Gx)^2  */
   256  	s[0].sub(s[0], p[1])      /* s[0] = t1[0]/(Px - Gx)^2 - Px  */
   257  	s[0][0] -= 9 + 486662     /* s[0] = X(P+G)  */
   258  	s[1].mul(t1[1], t2[0])    /* s[1] = t1[1]/(Px - Gx)^2  */
   259  	s[1].sub(s[1], p[1])      /* s[1] = t1[1]/(Px - Gx)^2 - Px  */
   260  	s[1][0] -= 9 + 486662     /* s[1] = X(P-G)  */
   261  	s[0].mulSmall(s[0], 1)    /* reduce s[0] */
   262  	s[1].mulSmall(s[1], 1)    /* reduce s[1] */
   263  
   264  	/* prepare the chain  */
   265  	var vi, hi, di, nvh int
   266  	for i := 0; i < 32; i++ {
   267  		vi = (vi >> 8) ^ int(v[i]&0xFF) ^ (int(v[i]&0xFF) << 1)
   268  		hi = (hi >> 8) ^ int(h[i]&0xFF) ^ (int(h[i]&0xFF) << 1)
   269  		nvh = ^(vi ^ hi)
   270  		di = (nvh & ((di & 0x80) >> 7)) ^ vi
   271  		di ^= nvh & ((di & 0x01) << 1)
   272  		di ^= nvh & ((di & 0x02) << 1)
   273  		di ^= nvh & ((di & 0x04) << 1)
   274  		di ^= nvh & ((di & 0x08) << 1)
   275  		di ^= nvh & ((di & 0x10) << 1)
   276  		di ^= nvh & ((di & 0x20) << 1)
   277  		di ^= nvh & ((di & 0x40) << 1)
   278  		d[i] = byte(di)
   279  	}
   280  
   281  	di = ((nvh & ((di & 0x80) << 1)) ^ vi) >> 8
   282  
   283  	/* initialize state */
   284  	yx[0].set(1)
   285  	yx[1].cpy(p[di])
   286  	yx[2].cpy(s[0])
   287  	yz[0].set(0)
   288  	yz[1].set(1)
   289  	yz[2].set(1)
   290  
   291  	/* y[0] is (even)P + (even)G
   292  	 * y[1] is (even)P + (odd)G  if current d-bit is 0
   293  	 * y[1] is (odd)P + (even)G  if current d-bit is 1
   294  	 * y[2] is (odd)P + (odd)G
   295  	 */
   296  
   297  	vi = 0
   298  	hi = 0
   299  
   300  	/* and go for it! */
   301  	for i := 31; i >= 0; i-- {
   302  		vi = (vi << 8) | int(v[i]&0xFF)
   303  		hi = (hi << 8) | int(h[i]&0xFF)
   304  		di = (di << 8) | int(d[i]&0xFF)
   305  		for j = 7; j >= 0; j-- {
   306  			montPrep(t1[0], t2[0], yx[0], yz[0])
   307  			montPrep(t1[1], t2[1], yx[1], yz[1])
   308  			montPrep(t1[2], t2[2], yx[2], yz[2])
   309  
   310  			uj := uint(j)
   311  			k := ((vi ^ vi>>1) >> uj & 1) + ((hi ^ hi>>1) >> uj & 1)
   312  			montDbl(yx[2], yz[2], t1[k], t2[k], yx[0], yz[0])
   313  			k = (di >> uj & 2) ^ ((di >> uj & 1) << 1)
   314  			montAdd(t1[1], t2[1], t1[k], t2[k], yx[1], yz[1], p[di>>uj&1])
   315  			montAdd(t1[2], t2[2], t1[0], t2[0], yx[2], yz[2], s[((vi^hi)>>uj&2)>>1])
   316  		}
   317  	}
   318  
   319  	k := (vi & 1) + (hi & 1)
   320  	t1[0].recip(yz[k], false)
   321  	t1[1].mul(yx[k], t1[0])
   322  	t1[1].pack(Y)
   323  }
   324  
   325  func isCanonicalSignature(v []byte) bool {
   326  	if len(v) < 32 {
   327  		return false
   328  	}
   329  	vCopy := append(v[:0:0], v[:32]...)
   330  	divmod(make([]byte, 32), vCopy, 32, order, 32)
   331  	return bytes.Equal(vCopy, v[:32])
   332  }
   333  
   334  func isCanonicalPublicKey(P []byte) bool {
   335  	if len(P) != 32 {
   336  		return false
   337  	}
   338  
   339  	rawP := new(long10)
   340  	rawP.unpack(P)
   341  	PCopy := rawP.pack(nil)
   342  	return bytes.Equal(PCopy, P)
   343  }