github.com/jiajun1992/watercarver@v0.0.0-20191031150618-dfc2b17c0c4a/go-ethereum/ctcrypto/crypto/key.go (about) 1 // Copyright 2017-2018 DERO Project. All rights reserved. 2 // Use of this source code in any form is governed by RESEARCH license. 3 // license can be found in the LICENSE file. 4 // GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8 5 // 6 // 7 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 8 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 10 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 11 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 12 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 13 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 14 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 15 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 17 package crypto 18 19 import "io" 20 import "fmt" 21 import "bytes" 22 import "crypto/rand" 23 import "encoding/hex" 24 import "encoding/binary" 25 26 const KeyLength = 32 27 28 // Key can be a Scalar or a Point 29 type Key [KeyLength]byte 30 31 func (k Key) MarshalText() ([]byte, error) { 32 return []byte(fmt.Sprintf("%x", k[:])), nil 33 } 34 35 func (k *Key) UnmarshalText(data []byte) (err error) { 36 byteSlice, _ := hex.DecodeString(string(data)) 37 if len(byteSlice) != 32 { 38 return fmt.Errorf("Incorrect key size") 39 } 40 copy(k[:], byteSlice) 41 return 42 } 43 44 func (k Key) String() string { 45 return fmt.Sprintf("%x", k[:]) 46 } 47 48 func (p *Key) FromBytes(b [KeyLength]byte) { 49 *p = b 50 } 51 52 func (p *Key) ToBytes() (result [KeyLength]byte) { 53 result = [KeyLength]byte(*p) 54 return 55 } 56 57 // convert a hex string to a key 58 func HexToKey(h string) (result Key) { 59 byteSlice, _ := hex.DecodeString(h) 60 if len(byteSlice) != 32 { 61 panic("Incorrect key size") 62 } 63 copy(result[:], byteSlice) 64 return 65 } 66 67 func HexToHash(h string) (result Hash) { 68 byteSlice, _ := hex.DecodeString(h) 69 if len(byteSlice) != 32 { 70 panic("Incorrect key size") 71 } 72 copy(result[:], byteSlice) 73 return 74 } 75 76 // generates a public from the secret key 77 func (p *Key) PublicKey() (pubKey *Key) { 78 point := new(ExtendedGroupElement) 79 GeScalarMultBase(point, p) 80 pubKey = new(Key) 81 point.ToBytes(pubKey) 82 return 83 } 84 85 // tests whether the key is valid ( represents a point on the curve ) 86 // this is equivalent to bool crypto_ops::check_key(const public_key &key) 87 func (k *Key) Public_Key_Valid() bool { 88 var point ExtendedGroupElement 89 return point.FromBytes(k) 90 } 91 92 func (k *Key) Private_Key_Valid() bool { 93 return Sc_check(k) 94 } 95 96 // Creates a point on the Edwards Curve by hashing the key 97 func (p *Key) HashToEC() (result *ExtendedGroupElement) { 98 result = new(ExtendedGroupElement) 99 var p1 ProjectiveGroupElement 100 var p2 CompletedGroupElement 101 h := Key(Keccak256(p[:])) 102 p1.FromBytes(&h) 103 104 // fmt.Printf("p1 %+v\n", p1) 105 GeMul8(&p2, &p1) 106 p2.ToExtended(result) 107 return 108 } 109 110 func (p *Key) HashToPoint() (result Key) { 111 extended := p.HashToEC() 112 extended.ToBytes(&result) 113 return 114 } 115 116 // compatible with hashToPointSimple 117 // NOTE: this is incompatible with HashToPoint ( though it should have been) 118 // there are no side-effects or degradtion of crypto, due to this 119 // however, the mistakes have to kept as they were in original code base 120 // this function is only used to generate H from G 121 func (p *Key) HashToPointSimple() (result Key) { 122 h := Key(Keccak256(p[:])) 123 extended := new(ExtendedGroupElement) 124 extended.FromBytes(&h) 125 126 // convert extended to projective 127 var p1 ProjectiveGroupElement 128 129 extended.ToProjective(&p1) 130 var p2 CompletedGroupElement 131 132 GeMul8(&p2, &p1) 133 p2.ToExtended(extended) 134 extended.ToBytes(&result) 135 return 136 } 137 138 // this uses random number generator from the OS 139 func RandomScalar() (result *Key) { 140 result = new(Key) 141 var reduceFrom [KeyLength * 2]byte 142 tmp := make([]byte, KeyLength*2) 143 rand.Read(tmp) 144 copy(reduceFrom[:], tmp) 145 ScReduce(result, &reduceFrom) 146 return 147 } 148 149 // generate a new private-public key pair 150 func NewKeyPair() (privKey *Key, pubKey *Key) { 151 privKey = RandomScalar() 152 pubKey = privKey.PublicKey() 153 return 154 } 155 156 func ParseKey(buf io.Reader) (result Key, err error) { 157 key := make([]byte, KeyLength) 158 if _, err = buf.Read(key); err != nil { 159 return 160 } 161 copy(result[:], key) 162 return 163 } 164 165 /* 166 //does a * G where a is a scalar and G is the curve basepoint 167 key scalarmultBase(const key & a) { 168 ge_p3 point; 169 key aG; 170 sc_reduce32copy(aG.bytes, a.bytes); //do this beforehand 171 ge_scalarmult_base(&point, aG.bytes); 172 ge_p3_tobytes(aG.bytes, &point); 173 return aG; 174 } 175 */ 176 //does a * G where a is a scalar and G is the curve basepoint 177 178 func ScalarmultBase(a Key) (aG Key) { 179 reduce32copy := a 180 ScReduce32(&reduce32copy) 181 point := new(ExtendedGroupElement) 182 GeScalarMultBase(point, &a) 183 point.ToBytes(&aG) 184 return aG 185 } 186 187 // generates a key which can be used as private key or mask 188 // this function is similiar to RandomScalar except for reduce32, TODO can we merge both 189 func skGen() Key { 190 skey := RandomScalar() 191 ScReduce32(skey) 192 return *skey 193 } 194 func SkGen() Key { 195 return skGen() 196 } 197 198 func (k *Key) ToExtended() (result *ExtendedGroupElement) { 199 result = new(ExtendedGroupElement) 200 result.FromBytes(k) 201 return 202 } 203 204 // bothe the function resturn identity of the ed25519 curve 205 func identity() (result *Key) { 206 result = new(Key) 207 result[0] = 1 208 return 209 } 210 211 func CurveIdentity() (result Key) { 212 result = Identity 213 return result 214 } 215 216 func CurveOrder() (result Key) { 217 result = L 218 return result 219 } 220 221 // convert a uint64 to a scalar 222 func d2h(val uint64) (result *Key) { 223 result = new(Key) 224 for i := 0; val > 0; i++ { 225 result[i] = byte(val & 0xFF) 226 val /= 256 227 } 228 return 229 } 230 231 func HashToScalar(data ...[]byte) (result *Key) { 232 result = new(Key) 233 *result = Key(Keccak256(data...)) 234 ScReduce32(result) 235 return 236 } 237 238 func HashToScalar2(data ...Key) (result *Key) { 239 result = new(Key) 240 tmp := make([][]byte, len(data)) 241 for i := range data { 242 tmp[i] = data[i][:] 243 } 244 *result = Key(Keccak256(tmp...)) 245 ScReduce32(result) 246 return 247 } 248 249 // does a * P where a is a scalar and P is an arbitrary point 250 func ScalarMultKey(Point *Key, scalar *Key) (result *Key) { 251 var P ExtendedGroupElement 252 P.FromBytes(Point) 253 var resultPoint ProjectiveGroupElement 254 GeScalarMult(&resultPoint, scalar, &P) 255 result = new(Key) 256 resultPoint.ToBytes(result) 257 return 258 } 259 260 func Scalarmult8(pointBytes *Key) (result *Key) { 261 var p3 ExtendedGroupElement 262 if !p3.FromBytes(pointBytes) { 263 return nil 264 } 265 var p2 ProjectiveGroupElement 266 p3.ToProjective(&p2) 267 var p1 CompletedGroupElement 268 GeMul8(&p1, &p2) 269 p1.ToProjective(&p2) 270 result = new(Key) 271 p2.ToBytes(result) 272 return 273 } 274 275 // multiply a scalar by H (second curve point of Pedersen Commitment) 276 func ScalarMultH(scalar *Key) (result *Key) { 277 h := new(ExtendedGroupElement) 278 h.FromBytes(&H) 279 resultPoint := new(ProjectiveGroupElement) 280 GeScalarMult(resultPoint, scalar, h) 281 result = new(Key) 282 resultPoint.ToBytes(result) 283 return 284 } 285 286 // add two points together 287 func AddKeys(sum, k1, k2 *Key) { 288 a := k1.ToExtended() 289 var b CachedGroupElement 290 k2.ToExtended().ToCached(&b) 291 var c CompletedGroupElement 292 geAdd(&c, a, &b) 293 var tmp ExtendedGroupElement 294 c.ToExtended(&tmp) 295 tmp.ToBytes(sum) 296 return 297 } 298 299 // compute a*G + b*B 300 func AddKeys2(result, a, b, B *Key) { 301 BPoint := B.ToExtended() 302 var RPoint ProjectiveGroupElement 303 GeDoubleScalarMultVartime(&RPoint, b, BPoint, a) 304 RPoint.ToBytes(result) 305 return 306 } 307 308 // comput a*G + b*H 309 func AddKeys2_2(result, a, b *Key) { 310 var output ExtendedGroupElement 311 DoubleScalarDoubleBaseMulPrecomputed(&output, a, b, &GBASE_H_TABLE) 312 output.ToBytes(result) 313 } 314 315 //addKeys3 316 //aAbB = a*A + b*B where a, b are scalars, A, B are curve points 317 //B must be input after applying "precomp" 318 func AddKeys3(result *Key, a *Key, A *Key, b *Key, B_Precomputed *[8]CachedGroupElement) { 319 var A_Point ExtendedGroupElement 320 A_Point.FromBytes(A) 321 322 var result_projective ProjectiveGroupElement 323 GeDoubleScalarMultPrecompVartime(&result_projective, a, &A_Point, b, B_Precomputed) 324 result_projective.ToBytes(result) 325 326 } 327 328 //addKeys3_3 this is similiar to addkeys3 except it allows for use of precomputed A,B 329 //aAbB = a*A + b*B where a, b are scalars, A, B are curve points 330 //A,B must be input after applying "precomp" 331 func AddKeys3_3(result *Key, a *Key, A_Precomputed *[8]CachedGroupElement, b *Key, B_Precomputed *[8]CachedGroupElement) { 332 var result_projective ProjectiveGroupElement 333 GeDoubleScalarMultPrecompVartime2(&result_projective, a, A_Precomputed, b, B_Precomputed) 334 result_projective.ToBytes(result) 335 336 } 337 338 // subtract two points A - B 339 func SubKeys(diff, k1, k2 *Key) { 340 a := k1.ToExtended() 341 b := new(CachedGroupElement) 342 k2.ToExtended().ToCached(b) 343 c := new(CompletedGroupElement) 344 geSub(c, a, b) 345 tmp := new(ExtendedGroupElement) 346 c.ToExtended(tmp) 347 tmp.ToBytes(diff) 348 return 349 } 350 351 // zero fill the key 352 func Sc_0(k *Key) { 353 for i := 0; i < 32; i++ { 354 k[i] = 0 355 } 356 } 357 358 // RandomPubKey takes a random scalar, interprets it as a point on the curve 359 // remember the low order bug and do more auditing of the entire thing 360 func RandomPubKey() (result *Key) { 361 result = new(Key) 362 p3 := new(ExtendedGroupElement) 363 var p1 ProjectiveGroupElement 364 var p2 CompletedGroupElement 365 h := RandomScalar() 366 p1.FromBytes(h) 367 GeMul8(&p2, &p1) 368 p2.ToExtended(p3) 369 p3.ToBytes(result) 370 return 371 } 372 373 // this is the main key derivation function and is the crux 374 // when deriving keys in the case user A wants to send DERO to another user B ( this is outgoing case) 375 // public key is B's view key 376 // private keys is TX private key 377 // if user B wants to derive key, he needs to ( this is incoming case ) 378 // public key is TX public key 379 // private is B's private keys 380 // HOPE the above is clean and clear 381 382 func KeyDerivation(pub *Key, priv *Key) (KeyDerivation Key) { 383 var point ExtendedGroupElement 384 var point2 ProjectiveGroupElement 385 var point3 CompletedGroupElement 386 387 if !priv.Private_Key_Valid() { 388 panic("Invalid private key.") 389 } 390 tmp := *pub 391 if !point.FromBytes(&tmp) { 392 panic("Invalid public key.") 393 } 394 395 tmp = *priv 396 GeScalarMult(&point2, &tmp, &point) 397 GeMul8(&point3, &point2) 398 point3.ToProjective(&point2) 399 400 point2.ToBytes(&tmp) 401 return tmp 402 } 403 404 // the origincal c implementation needs to be checked for varint overflow 405 // we also need to check the compatibility of golang varint with cryptonote implemented varint 406 // outputIndex is the position of output within that specific transaction 407 func (k *Key) KeyDerivationToScalar(outputIndex uint64) (scalar *Key) { 408 tmp := make([]byte, 12, 12) 409 410 length := binary.PutUvarint(tmp, outputIndex) 411 tmp = tmp[:length] 412 413 var buf bytes.Buffer 414 buf.Write(k[:]) 415 buf.Write(tmp) 416 scalar = HashToScalar(buf.Bytes()) 417 return 418 } 419 420 // generate ephermal keys from a key derivation 421 // base key is the B's public spend key or A's private spend key 422 // outputIndex is the position of output within that specific transaction 423 func (kd *Key) KeyDerivation_To_PublicKey(outputIndex uint64, baseKey Key) Key { 424 425 var point1, point2 ExtendedGroupElement 426 var point3 CachedGroupElement 427 var point4 CompletedGroupElement 428 var point5 ProjectiveGroupElement 429 430 tmp := baseKey 431 if !point1.FromBytes(&tmp) { 432 panic("Invalid public key.") 433 } 434 scalar := kd.KeyDerivationToScalar(outputIndex) 435 GeScalarMultBase(&point2, scalar) 436 point2.ToCached(&point3) 437 geAdd(&point4, &point1, &point3) 438 point4.ToProjective(&point5) 439 point5.ToBytes(&tmp) 440 return tmp 441 } 442 443 // generate ephermal keys from a key derivation 444 // base key is the A's private spend key 445 // outputIndex is the position of output within that specific transaction 446 func (kd *Key) KeyDerivation_To_PrivateKey(outputIndex uint64, baseKey Key) Key { 447 if !baseKey.Private_Key_Valid() { 448 panic("Invalid private key.") 449 } 450 scalar := kd.KeyDerivationToScalar(outputIndex) 451 452 tmp := baseKey 453 ScAdd(&tmp, &tmp, scalar) 454 return tmp 455 } 456 457 // NewKeyImage creates a new KeyImage from the given public and private keys. 458 // The keys are usually the ephemeral keys derived using KeyDerivation. 459 func GenerateKeyImage(pub Key, private Key) Key { 460 var proj ProjectiveGroupElement 461 462 ext := pub.HashToEC() 463 GeScalarMult(&proj, &private, ext) 464 465 var ki Key 466 proj.ToBytes(&ki) 467 return ki 468 }