github.com/annchain/OG@v0.0.9/deprecated/ogcrypto/extra25519/extra25519.go (about)

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package extra25519
     6  
     7  import (
     8  	"crypto/sha512"
     9  
    10  	"github.com/annchain/OG/deprecated/ogcrypto/ed25519"
    11  )
    12  
    13  // PrivateKeyToCurve25519 converts an ed25519 private key into a corresponding
    14  // curve25519 private key such that the resulting curve25519 public key will
    15  // equal the result from PublicKeyToCurve25519.
    16  func PrivateKeyToCurve25519(curve25519Private *[32]byte, privateKey *[64]byte) {
    17  	h := sha512.New()
    18  	h.Write(privateKey[:32])
    19  	digest := h.Sum(nil)
    20  
    21  	digest[0] &= 248
    22  	digest[31] &= 127
    23  	digest[31] |= 64
    24  
    25  	copy(curve25519Private[:], digest)
    26  }
    27  
    28  func edwardsToMontgomeryX(outX, y *edwards25519.FieldElement) {
    29  	// We only need the x-coordinate of the curve25519 point, which I'll
    30  	// call u. The isomorphism is u=(y+1)/(1-y), since y=Y/Z, this gives
    31  	// u=(Y+Z)/(Z-Y). We know that Z=1, thus u=(Y+1)/(1-Y).
    32  	var oneMinusY edwards25519.FieldElement
    33  	edwards25519.FeOne(&oneMinusY)
    34  	edwards25519.FeSub(&oneMinusY, &oneMinusY, y)
    35  	edwards25519.FeInvert(&oneMinusY, &oneMinusY)
    36  
    37  	edwards25519.FeOne(outX)
    38  	edwards25519.FeAdd(outX, outX, y)
    39  
    40  	edwards25519.FeMul(outX, outX, &oneMinusY)
    41  }
    42  
    43  // PublicKeyToCurve25519 converts an Ed25519 public key into the curve25519
    44  // public key that would be generated from the same private key.
    45  func PublicKeyToCurve25519(curve25519Public *[32]byte, publicKey *[32]byte) bool {
    46  	var A edwards25519.ExtendedGroupElement
    47  	if !A.FromBytes(publicKey) {
    48  		return false
    49  	}
    50  
    51  	// A.Z = 1 as a postcondition of FromBytes.
    52  	var x edwards25519.FieldElement
    53  	edwardsToMontgomeryX(&x, &A.Y)
    54  	edwards25519.FeToBytes(curve25519Public, &x)
    55  	return true
    56  }
    57  
    58  // sqrtMinusA is sqrt(-486662)
    59  var sqrtMinusA = edwards25519.FieldElement{
    60  	12222970, 8312128, 11511410, -9067497, 15300785, 241793, -25456130, -14121551, 12187136, -3972024,
    61  }
    62  
    63  // sqrtMinusHalf is sqrt(-1/2)
    64  var sqrtMinusHalf = edwards25519.FieldElement{
    65  	-17256545, 3971863, 28865457, -1750208, 27359696, -16640980, 12573105, 1002827, -163343, 11073975,
    66  }
    67  
    68  // halfQMinus1Bytes is (2^255-20)/2 expressed in little endian form.
    69  var halfQMinus1Bytes = [32]byte{
    70  	0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
    71  }
    72  
    73  // feBytesLess returns one if a <= b and zero otherwise.
    74  func feBytesLE(a, b *[32]byte) int32 {
    75  	equalSoFar := int32(-1)
    76  	greater := int32(0)
    77  
    78  	for i := uint(31); i < 32; i-- {
    79  		x := int32(a[i])
    80  		y := int32(b[i])
    81  
    82  		greater = (^equalSoFar & greater) | (equalSoFar & ((x - y) >> 31))
    83  		equalSoFar = equalSoFar & (((x ^ y) - 1) >> 31)
    84  	}
    85  
    86  	return int32(^equalSoFar & 1 & greater)
    87  }
    88  
    89  // ScalarBaseMult computes a curve25519 public key from a private key and also
    90  // a uniform representative for that public key. Note that this function will
    91  // fail and return false for about half of private keys.
    92  // See http://elligator.cr.yp.to/elligator-20130828.pdf.
    93  func ScalarBaseMult(publicKey, representative, privateKey *[32]byte) bool {
    94  	var maskedPrivateKey [32]byte
    95  	copy(maskedPrivateKey[:], privateKey[:])
    96  
    97  	maskedPrivateKey[0] &= 248
    98  	maskedPrivateKey[31] &= 127
    99  	maskedPrivateKey[31] |= 64
   100  
   101  	var A edwards25519.ExtendedGroupElement
   102  	edwards25519.GeScalarMultBase(&A, &maskedPrivateKey)
   103  
   104  	var inv1 edwards25519.FieldElement
   105  	edwards25519.FeSub(&inv1, &A.Z, &A.Y)
   106  	edwards25519.FeMul(&inv1, &inv1, &A.X)
   107  	edwards25519.FeInvert(&inv1, &inv1)
   108  
   109  	var t0, u edwards25519.FieldElement
   110  	edwards25519.FeMul(&u, &inv1, &A.X)
   111  	edwards25519.FeAdd(&t0, &A.Y, &A.Z)
   112  	edwards25519.FeMul(&u, &u, &t0)
   113  
   114  	var v edwards25519.FieldElement
   115  	edwards25519.FeMul(&v, &t0, &inv1)
   116  	edwards25519.FeMul(&v, &v, &A.Z)
   117  	edwards25519.FeMul(&v, &v, &sqrtMinusA)
   118  
   119  	var b edwards25519.FieldElement
   120  	edwards25519.FeAdd(&b, &u, &edwards25519.A)
   121  
   122  	var c, b3, b8 edwards25519.FieldElement
   123  	edwards25519.FeSquare(&b3, &b)   // 2
   124  	edwards25519.FeMul(&b3, &b3, &b) // 3
   125  	edwards25519.FeSquare(&c, &b3)   // 6
   126  	edwards25519.FeMul(&c, &c, &b)   // 7
   127  	edwards25519.FeMul(&b8, &c, &b)  // 8
   128  	edwards25519.FeMul(&c, &c, &u)
   129  	q58(&c, &c)
   130  
   131  	var chi edwards25519.FieldElement
   132  	edwards25519.FeSquare(&chi, &c)
   133  	edwards25519.FeSquare(&chi, &chi)
   134  
   135  	edwards25519.FeSquare(&t0, &u)
   136  	edwards25519.FeMul(&chi, &chi, &t0)
   137  
   138  	edwards25519.FeSquare(&t0, &b)   // 2
   139  	edwards25519.FeMul(&t0, &t0, &b) // 3
   140  	edwards25519.FeSquare(&t0, &t0)  // 6
   141  	edwards25519.FeMul(&t0, &t0, &b) // 7
   142  	edwards25519.FeSquare(&t0, &t0)  // 14
   143  	edwards25519.FeMul(&chi, &chi, &t0)
   144  	edwards25519.FeNeg(&chi, &chi)
   145  
   146  	var chiBytes [32]byte
   147  	edwards25519.FeToBytes(&chiBytes, &chi)
   148  	// chi[1] is either 0 or 0xff
   149  	if chiBytes[1] == 0xff {
   150  		return false
   151  	}
   152  
   153  	// Calculate r1 = sqrt(-u/(2*(u+A)))
   154  	var r1 edwards25519.FieldElement
   155  	edwards25519.FeMul(&r1, &c, &u)
   156  	edwards25519.FeMul(&r1, &r1, &b3)
   157  	edwards25519.FeMul(&r1, &r1, &sqrtMinusHalf)
   158  
   159  	var maybeSqrtM1 edwards25519.FieldElement
   160  	edwards25519.FeSquare(&t0, &r1)
   161  	edwards25519.FeMul(&t0, &t0, &b)
   162  	edwards25519.FeAdd(&t0, &t0, &t0)
   163  	edwards25519.FeAdd(&t0, &t0, &u)
   164  
   165  	edwards25519.FeOne(&maybeSqrtM1)
   166  	edwards25519.FeCMove(&maybeSqrtM1, &edwards25519.SqrtM1, edwards25519.FeIsNonZero(&t0))
   167  	edwards25519.FeMul(&r1, &r1, &maybeSqrtM1)
   168  
   169  	// Calculate r = sqrt(-(u+A)/(2u))
   170  	var r edwards25519.FieldElement
   171  	edwards25519.FeSquare(&t0, &c)   // 2
   172  	edwards25519.FeMul(&t0, &t0, &c) // 3
   173  	edwards25519.FeSquare(&t0, &t0)  // 6
   174  	edwards25519.FeMul(&r, &t0, &c)  // 7
   175  
   176  	edwards25519.FeSquare(&t0, &u)   // 2
   177  	edwards25519.FeMul(&t0, &t0, &u) // 3
   178  	edwards25519.FeMul(&r, &r, &t0)
   179  
   180  	edwards25519.FeSquare(&t0, &b8)   // 16
   181  	edwards25519.FeMul(&t0, &t0, &b8) // 24
   182  	edwards25519.FeMul(&t0, &t0, &b)  // 25
   183  	edwards25519.FeMul(&r, &r, &t0)
   184  	edwards25519.FeMul(&r, &r, &sqrtMinusHalf)
   185  
   186  	edwards25519.FeSquare(&t0, &r)
   187  	edwards25519.FeMul(&t0, &t0, &u)
   188  	edwards25519.FeAdd(&t0, &t0, &t0)
   189  	edwards25519.FeAdd(&t0, &t0, &b)
   190  	edwards25519.FeOne(&maybeSqrtM1)
   191  	edwards25519.FeCMove(&maybeSqrtM1, &edwards25519.SqrtM1, edwards25519.FeIsNonZero(&t0))
   192  	edwards25519.FeMul(&r, &r, &maybeSqrtM1)
   193  
   194  	var vBytes [32]byte
   195  	edwards25519.FeToBytes(&vBytes, &v)
   196  	vInSquareRootImage := feBytesLE(&vBytes, &halfQMinus1Bytes)
   197  	edwards25519.FeCMove(&r, &r1, vInSquareRootImage)
   198  
   199  	edwards25519.FeToBytes(publicKey, &u)
   200  	edwards25519.FeToBytes(representative, &r)
   201  	return true
   202  }
   203  
   204  // q58 calculates out = z^((p-5)/8).
   205  func q58(out, z *edwards25519.FieldElement) {
   206  	var t1, t2, t3 edwards25519.FieldElement
   207  	var i int
   208  
   209  	edwards25519.FeSquare(&t1, z)     // 2^1
   210  	edwards25519.FeMul(&t1, &t1, z)   // 2^1 + 2^0
   211  	edwards25519.FeSquare(&t1, &t1)   // 2^2 + 2^1
   212  	edwards25519.FeSquare(&t2, &t1)   // 2^3 + 2^2
   213  	edwards25519.FeSquare(&t2, &t2)   // 2^4 + 2^3
   214  	edwards25519.FeMul(&t2, &t2, &t1) // 4,3,2,1
   215  	edwards25519.FeMul(&t1, &t2, z)   // 4..0
   216  	edwards25519.FeSquare(&t2, &t1)   // 5..1
   217  	for i = 1; i < 5; i++ {           // 9,8,7,6,5
   218  		edwards25519.FeSquare(&t2, &t2)
   219  	}
   220  	edwards25519.FeMul(&t1, &t2, &t1) // 9,8,7,6,5,4,3,2,1,0
   221  	edwards25519.FeSquare(&t2, &t1)   // 10..1
   222  	for i = 1; i < 10; i++ {          // 19..10
   223  		edwards25519.FeSquare(&t2, &t2)
   224  	}
   225  	edwards25519.FeMul(&t2, &t2, &t1) // 19..0
   226  	edwards25519.FeSquare(&t3, &t2)   // 20..1
   227  	for i = 1; i < 20; i++ {          // 39..20
   228  		edwards25519.FeSquare(&t3, &t3)
   229  	}
   230  	edwards25519.FeMul(&t2, &t3, &t2) // 39..0
   231  	edwards25519.FeSquare(&t2, &t2)   // 40..1
   232  	for i = 1; i < 10; i++ {          // 49..10
   233  		edwards25519.FeSquare(&t2, &t2)
   234  	}
   235  	edwards25519.FeMul(&t1, &t2, &t1) // 49..0
   236  	edwards25519.FeSquare(&t2, &t1)   // 50..1
   237  	for i = 1; i < 50; i++ {          // 99..50
   238  		edwards25519.FeSquare(&t2, &t2)
   239  	}
   240  	edwards25519.FeMul(&t2, &t2, &t1) // 99..0
   241  	edwards25519.FeSquare(&t3, &t2)   // 100..1
   242  	for i = 1; i < 100; i++ {         // 199..100
   243  		edwards25519.FeSquare(&t3, &t3)
   244  	}
   245  	edwards25519.FeMul(&t2, &t3, &t2) // 199..0
   246  	edwards25519.FeSquare(&t2, &t2)   // 200..1
   247  	for i = 1; i < 50; i++ {          // 249..50
   248  		edwards25519.FeSquare(&t2, &t2)
   249  	}
   250  	edwards25519.FeMul(&t1, &t2, &t1) // 249..0
   251  	edwards25519.FeSquare(&t1, &t1)   // 250..1
   252  	edwards25519.FeSquare(&t1, &t1)   // 251..2
   253  	edwards25519.FeMul(out, &t1, z)   // 251..2,0
   254  }
   255  
   256  // chi calculates out = z^((p-1)/2). The result is either 1, 0, or -1 depending
   257  // on whether z is a non-zero square, zero, or a non-square.
   258  func chi(out, z *edwards25519.FieldElement) {
   259  	var t0, t1, t2, t3 edwards25519.FieldElement
   260  	var i int
   261  
   262  	edwards25519.FeSquare(&t0, z)     // 2^1
   263  	edwards25519.FeMul(&t1, &t0, z)   // 2^1 + 2^0
   264  	edwards25519.FeSquare(&t0, &t1)   // 2^2 + 2^1
   265  	edwards25519.FeSquare(&t2, &t0)   // 2^3 + 2^2
   266  	edwards25519.FeSquare(&t2, &t2)   // 4,3
   267  	edwards25519.FeMul(&t2, &t2, &t0) // 4,3,2,1
   268  	edwards25519.FeMul(&t1, &t2, z)   // 4..0
   269  	edwards25519.FeSquare(&t2, &t1)   // 5..1
   270  	for i = 1; i < 5; i++ {           // 9,8,7,6,5
   271  		edwards25519.FeSquare(&t2, &t2)
   272  	}
   273  	edwards25519.FeMul(&t1, &t2, &t1) // 9,8,7,6,5,4,3,2,1,0
   274  	edwards25519.FeSquare(&t2, &t1)   // 10..1
   275  	for i = 1; i < 10; i++ {          // 19..10
   276  		edwards25519.FeSquare(&t2, &t2)
   277  	}
   278  	edwards25519.FeMul(&t2, &t2, &t1) // 19..0
   279  	edwards25519.FeSquare(&t3, &t2)   // 20..1
   280  	for i = 1; i < 20; i++ {          // 39..20
   281  		edwards25519.FeSquare(&t3, &t3)
   282  	}
   283  	edwards25519.FeMul(&t2, &t3, &t2) // 39..0
   284  	edwards25519.FeSquare(&t2, &t2)   // 40..1
   285  	for i = 1; i < 10; i++ {          // 49..10
   286  		edwards25519.FeSquare(&t2, &t2)
   287  	}
   288  	edwards25519.FeMul(&t1, &t2, &t1) // 49..0
   289  	edwards25519.FeSquare(&t2, &t1)   // 50..1
   290  	for i = 1; i < 50; i++ {          // 99..50
   291  		edwards25519.FeSquare(&t2, &t2)
   292  	}
   293  	edwards25519.FeMul(&t2, &t2, &t1) // 99..0
   294  	edwards25519.FeSquare(&t3, &t2)   // 100..1
   295  	for i = 1; i < 100; i++ {         // 199..100
   296  		edwards25519.FeSquare(&t3, &t3)
   297  	}
   298  	edwards25519.FeMul(&t2, &t3, &t2) // 199..0
   299  	edwards25519.FeSquare(&t2, &t2)   // 200..1
   300  	for i = 1; i < 50; i++ {          // 249..50
   301  		edwards25519.FeSquare(&t2, &t2)
   302  	}
   303  	edwards25519.FeMul(&t1, &t2, &t1) // 249..0
   304  	edwards25519.FeSquare(&t1, &t1)   // 250..1
   305  	for i = 1; i < 4; i++ {           // 253..4
   306  		edwards25519.FeSquare(&t1, &t1)
   307  	}
   308  	edwards25519.FeMul(out, &t1, &t0) // 253..4,2,1
   309  }
   310  
   311  // RepresentativeToPublicKey converts a uniform representative value for a
   312  // curve25519 public key, as produced by ScalarBaseMult, to a curve25519 public
   313  // key.
   314  func RepresentativeToPublicKey(publicKey, representative *[32]byte) {
   315  	var rr2, v edwards25519.FieldElement
   316  	edwards25519.FeFromBytes(&rr2, representative)
   317  	representativeToMontgomeryX(&v, &rr2)
   318  	edwards25519.FeToBytes(publicKey, &v)
   319  }
   320  
   321  // representativeToMontgomeryX consumes the rr2 input
   322  func representativeToMontgomeryX(v, rr2 *edwards25519.FieldElement) {
   323  	var e edwards25519.FieldElement
   324  	edwards25519.FeSquare2(rr2, rr2)
   325  	rr2[0]++
   326  	edwards25519.FeInvert(rr2, rr2)
   327  	edwards25519.FeMul(v, &edwards25519.A, rr2)
   328  	edwards25519.FeNeg(v, v)
   329  
   330  	var v2, v3 edwards25519.FieldElement
   331  	edwards25519.FeSquare(&v2, v)
   332  	edwards25519.FeMul(&v3, v, &v2)
   333  	edwards25519.FeAdd(&e, &v3, v)
   334  	edwards25519.FeMul(&v2, &v2, &edwards25519.A)
   335  	edwards25519.FeAdd(&e, &v2, &e)
   336  	chi(&e, &e)
   337  	var eBytes [32]byte
   338  	edwards25519.FeToBytes(&eBytes, &e)
   339  	// eBytes[1] is either 0 (for e = 1) or 0xff (for e = -1)
   340  	eIsMinus1 := int32(eBytes[1]) & 1
   341  	var negV edwards25519.FieldElement
   342  	edwards25519.FeNeg(&negV, v)
   343  	edwards25519.FeCMove(v, &negV, eIsMinus1)
   344  
   345  	edwards25519.FeZero(&v2)
   346  	edwards25519.FeCMove(&v2, &edwards25519.A, eIsMinus1)
   347  	edwards25519.FeSub(v, v, &v2)
   348  }
   349  
   350  func montgomeryXToEdwardsY(out, x *edwards25519.FieldElement) {
   351  	var t, tt edwards25519.FieldElement
   352  	edwards25519.FeOne(&t)
   353  	edwards25519.FeAdd(&tt, x, &t)   // u+1
   354  	edwards25519.FeInvert(&tt, &tt)  // 1/(u+1)
   355  	edwards25519.FeSub(&t, x, &t)    // u-1
   356  	edwards25519.FeMul(out, &tt, &t) // (u-1)/(u+1)
   357  }
   358  
   359  // HashToEdwards converts a 256-bit hash output into a point on the Edwards
   360  // curve isomorphic to Curve25519 in a manner that preserves
   361  // collision-resistance. The returned curve points are NOT indistinguishable
   362  // from random even if the hash value is.
   363  // Specifically, first one bit of the hash output is set aside for parity and
   364  // the rest is truncated and fed into the elligator bijection (which covers half
   365  // of the points on the elliptic curve).
   366  func HashToEdwards(out *edwards25519.ExtendedGroupElement, h *[32]byte) {
   367  	hh := *h
   368  	bit := hh[31] >> 7
   369  	hh[31] &= 127
   370  	edwards25519.FeFromBytes(&out.Y, &hh)
   371  	representativeToMontgomeryX(&out.X, &out.Y)
   372  	montgomeryXToEdwardsY(&out.Y, &out.X)
   373  	if ok := out.FromParityAndY(bit, &out.Y); !ok {
   374  		panic("HashToEdwards: point not on curve")
   375  	}
   376  }