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 }