You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
3.6 KiB

  1. package ringct
  2. import "io"
  3. import "crypto/rand"
  4. import "github.com/deroproject/derosuite/crypto"
  5. const KeyLength = 32
  6. // Key can be a Scalar or a Point
  7. type Key [KeyLength]byte
  8. func (p *Key) FromBytes(b [KeyLength]byte) {
  9. *p = b
  10. }
  11. func (p *Key) ToBytes() (result [KeyLength]byte) {
  12. result = [KeyLength]byte(*p)
  13. return
  14. }
  15. func (p *Key) PubKey() (pubKey *Key) {
  16. point := new(ExtendedGroupElement)
  17. GeScalarMultBase(point, p)
  18. pubKey = new(Key)
  19. point.ToBytes(pubKey)
  20. return
  21. }
  22. // Creates a point on the Edwards Curve by hashing the key
  23. func (p *Key) HashToEC() (result *ExtendedGroupElement) {
  24. result = new(ExtendedGroupElement)
  25. var p1 ProjectiveGroupElement
  26. var p2 CompletedGroupElement
  27. h := Key(crypto.Keccak256(p[:]))
  28. p1.FromBytes(&h)
  29. GeMul8(&p2, &p1)
  30. p2.ToExtended(result)
  31. return
  32. }
  33. func RandomScalar() (result *Key) {
  34. result = new(Key)
  35. var reduceFrom [KeyLength * 2]byte
  36. tmp := make([]byte, KeyLength*2)
  37. rand.Read(tmp)
  38. copy(reduceFrom[:], tmp)
  39. ScReduce(result, &reduceFrom)
  40. return
  41. }
  42. func NewKeyPair() (privKey *Key, pubKey *Key) {
  43. privKey = RandomScalar()
  44. pubKey = privKey.PubKey()
  45. return
  46. }
  47. func ParseKey(buf io.Reader) (result Key, err error) {
  48. key := make([]byte, KeyLength)
  49. if _, err = buf.Read(key); err != nil {
  50. return
  51. }
  52. copy(result[:], key)
  53. return
  54. }
  55. /*
  56. //does a * G where a is a scalar and G is the curve basepoint
  57. key scalarmultBase(const key & a) {
  58. ge_p3 point;
  59. key aG;
  60. sc_reduce32copy(aG.bytes, a.bytes); //do this beforehand
  61. ge_scalarmult_base(&point, aG.bytes);
  62. ge_p3_tobytes(aG.bytes, &point);
  63. return aG;
  64. }
  65. */
  66. //does a * G where a is a scalar and G is the curve basepoint
  67. func ScalarmultBase(a Key) (aG Key){
  68. reduce32copy := a
  69. ScReduce32(&reduce32copy)
  70. point := new(ExtendedGroupElement)
  71. GeScalarMultBase(point, &a)
  72. point.ToBytes(&aG)
  73. return aG
  74. }
  75. // generates a key which can be used as private key or mask
  76. // this function is similiar to RandomScalar except for reduce32, TODO can we merge both
  77. func skGen() Key {
  78. skey := RandomScalar()
  79. ScReduce32(skey)
  80. return *skey
  81. }
  82. func (k *Key) ToExtended() (result *ExtendedGroupElement) {
  83. result = new(ExtendedGroupElement)
  84. result.FromBytes(k)
  85. return
  86. }
  87. func identity() (result *Key) {
  88. result = new(Key)
  89. result[0] = 1
  90. return
  91. }
  92. // convert a uint64 to a scalar
  93. func d2h(val uint64) (result *Key) {
  94. result = new(Key)
  95. for i := 0; val > 0; i++ {
  96. result[i] = byte(val & 0xFF)
  97. val /= 256
  98. }
  99. return
  100. }
  101. func HashToScalar(data ...[]byte) (result *Key) {
  102. result = new(Key)
  103. *result = Key(crypto.Keccak256(data...))
  104. ScReduce32(result)
  105. return
  106. }
  107. // multiply a scalar by H (second curve point of Pedersen Commitment)
  108. func ScalarMultH(scalar *Key) (result *Key) {
  109. h := new(ExtendedGroupElement)
  110. h.FromBytes(&H)
  111. resultPoint := new(ProjectiveGroupElement)
  112. GeScalarMult(resultPoint, scalar, h)
  113. result = new(Key)
  114. resultPoint.ToBytes(result)
  115. return
  116. }
  117. // add two points together
  118. func AddKeys(sum, k1, k2 *Key) {
  119. a := k1.ToExtended()
  120. b := new(CachedGroupElement)
  121. k2.ToExtended().ToCached(b)
  122. c := new(CompletedGroupElement)
  123. geAdd(c, a, b)
  124. tmp := new(ExtendedGroupElement)
  125. c.ToExtended(tmp)
  126. tmp.ToBytes(sum)
  127. return
  128. }
  129. // compute a*G + b*B
  130. func AddKeys2(result, a, b, B *Key) {
  131. BPoint := B.ToExtended()
  132. RPoint := new(ProjectiveGroupElement)
  133. GeDoubleScalarMultVartime(RPoint, b, BPoint, a)
  134. RPoint.ToBytes(result)
  135. return
  136. }
  137. // subtract two points A - B
  138. func SubKeys(diff, k1, k2 *Key) {
  139. a := k1.ToExtended()
  140. b := new(CachedGroupElement)
  141. k2.ToExtended().ToCached(b)
  142. c := new(CompletedGroupElement)
  143. geSub(c, a, b)
  144. tmp := new(ExtendedGroupElement)
  145. c.ToExtended(tmp)
  146. tmp.ToBytes(diff)
  147. return
  148. }