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  }