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.

261 lines
6.5 KiB

  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. package ringct
  17. import "io"
  18. import "fmt"
  19. import "crypto/rand"
  20. import "github.com/deroproject/derosuite/crypto"
  21. const KeyLength = 32
  22. // Key can be a Scalar or a Point
  23. type Key [KeyLength]byte
  24. func (k Key) MarshalText() ([]byte, error) {
  25. return []byte(fmt.Sprintf("%x", k[:])), nil
  26. }
  27. func (k Key) String() string {
  28. return fmt.Sprintf("%x", k[:])
  29. }
  30. func (p *Key) FromBytes(b [KeyLength]byte) {
  31. *p = b
  32. }
  33. func (p *Key) ToBytes() (result [KeyLength]byte) {
  34. result = [KeyLength]byte(*p)
  35. return
  36. }
  37. func (p *Key) PubKey() (pubKey *Key) {
  38. point := new(ExtendedGroupElement)
  39. GeScalarMultBase(point, p)
  40. pubKey = new(Key)
  41. point.ToBytes(pubKey)
  42. return
  43. }
  44. // Creates a point on the Edwards Curve by hashing the key
  45. func (p *Key) HashToEC() (result *ExtendedGroupElement) {
  46. result = new(ExtendedGroupElement)
  47. var p1 ProjectiveGroupElement
  48. var p2 CompletedGroupElement
  49. h := Key(crypto.Keccak256(p[:]))
  50. p1.FromBytes(&h)
  51. GeMul8(&p2, &p1)
  52. p2.ToExtended(result)
  53. return
  54. }
  55. func (p *Key) HashToPoint() (result Key) {
  56. extended := p.HashToEC()
  57. extended.ToBytes(&result)
  58. return
  59. }
  60. func RandomScalar() (result *Key) {
  61. result = new(Key)
  62. var reduceFrom [KeyLength * 2]byte
  63. tmp := make([]byte, KeyLength*2)
  64. rand.Read(tmp)
  65. copy(reduceFrom[:], tmp)
  66. ScReduce(result, &reduceFrom)
  67. return
  68. }
  69. func NewKeyPair() (privKey *Key, pubKey *Key) {
  70. privKey = RandomScalar()
  71. pubKey = privKey.PubKey()
  72. return
  73. }
  74. func ParseKey(buf io.Reader) (result Key, err error) {
  75. key := make([]byte, KeyLength)
  76. if _, err = buf.Read(key); err != nil {
  77. return
  78. }
  79. copy(result[:], key)
  80. return
  81. }
  82. /*
  83. //does a * G where a is a scalar and G is the curve basepoint
  84. key scalarmultBase(const key & a) {
  85. ge_p3 point;
  86. key aG;
  87. sc_reduce32copy(aG.bytes, a.bytes); //do this beforehand
  88. ge_scalarmult_base(&point, aG.bytes);
  89. ge_p3_tobytes(aG.bytes, &point);
  90. return aG;
  91. }
  92. */
  93. //does a * G where a is a scalar and G is the curve basepoint
  94. func ScalarmultBase(a Key) (aG Key) {
  95. reduce32copy := a
  96. ScReduce32(&reduce32copy)
  97. point := new(ExtendedGroupElement)
  98. GeScalarMultBase(point, &a)
  99. point.ToBytes(&aG)
  100. return aG
  101. }
  102. // generates a key which can be used as private key or mask
  103. // this function is similiar to RandomScalar except for reduce32, TODO can we merge both
  104. func skGen() Key {
  105. skey := RandomScalar()
  106. ScReduce32(skey)
  107. return *skey
  108. }
  109. func (k *Key) ToExtended() (result *ExtendedGroupElement) {
  110. result = new(ExtendedGroupElement)
  111. result.FromBytes(k)
  112. return
  113. }
  114. // bothe the function resturn identity of the ed25519 curve
  115. func identity() (result *Key) {
  116. result = new(Key)
  117. result[0] = 1
  118. return
  119. }
  120. func CurveIdentity() (result Key) {
  121. result = Identity
  122. return result
  123. }
  124. func CurveOrder() (result Key) {
  125. result = L
  126. return result
  127. }
  128. // convert a uint64 to a scalar
  129. func d2h(val uint64) (result *Key) {
  130. result = new(Key)
  131. for i := 0; val > 0; i++ {
  132. result[i] = byte(val & 0xFF)
  133. val /= 256
  134. }
  135. return
  136. }
  137. //32 byte key to uint long long
  138. // if the key holds a value > 2^64
  139. // then the value in the first 8 bytes is returned
  140. func h2d(input Key) (value uint64) {
  141. for j := 7; j >= 0; j-- {
  142. value = (value*256 + uint64(input[j]))
  143. }
  144. return value
  145. }
  146. func HashToScalar(data ...[]byte) (result *Key) {
  147. result = new(Key)
  148. *result = Key(crypto.Keccak256(data...))
  149. ScReduce32(result)
  150. return
  151. }
  152. // does a * P where a is a scalar and P is an arbitrary point
  153. func ScalarMultKey(Point *Key, scalar *Key) (result *Key) {
  154. P := new(ExtendedGroupElement)
  155. P.FromBytes(Point)
  156. resultPoint := new(ProjectiveGroupElement)
  157. GeScalarMult(resultPoint, scalar, P)
  158. result = new(Key)
  159. resultPoint.ToBytes(result)
  160. return
  161. }
  162. // multiply a scalar by H (second curve point of Pedersen Commitment)
  163. func ScalarMultH(scalar *Key) (result *Key) {
  164. h := new(ExtendedGroupElement)
  165. h.FromBytes(&H)
  166. resultPoint := new(ProjectiveGroupElement)
  167. GeScalarMult(resultPoint, scalar, h)
  168. result = new(Key)
  169. resultPoint.ToBytes(result)
  170. return
  171. }
  172. // add two points together
  173. func AddKeys(sum, k1, k2 *Key) {
  174. a := k1.ToExtended()
  175. b := new(CachedGroupElement)
  176. k2.ToExtended().ToCached(b)
  177. c := new(CompletedGroupElement)
  178. geAdd(c, a, b)
  179. tmp := new(ExtendedGroupElement)
  180. c.ToExtended(tmp)
  181. tmp.ToBytes(sum)
  182. return
  183. }
  184. // compute a*G + b*B
  185. func AddKeys2(result, a, b, B *Key) {
  186. BPoint := B.ToExtended()
  187. RPoint := new(ProjectiveGroupElement)
  188. GeDoubleScalarMultVartime(RPoint, b, BPoint, a)
  189. RPoint.ToBytes(result)
  190. return
  191. }
  192. //addKeys3
  193. //aAbB = a*A + b*B where a, b are scalars, A, B are curve points
  194. //B must be input after applying "precomp"
  195. func AddKeys3(result *Key, a *Key, A *Key, b *Key, B_Precomputed *[8]CachedGroupElement) {
  196. A_Point := new(ExtendedGroupElement)
  197. A_Point.FromBytes(A)
  198. result_projective := new(ProjectiveGroupElement)
  199. GeDoubleScalarMultPrecompVartime(result_projective, a, A_Point, b, B_Precomputed)
  200. result_projective.ToBytes(result)
  201. }
  202. // subtract two points A - B
  203. func SubKeys(diff, k1, k2 *Key) {
  204. a := k1.ToExtended()
  205. b := new(CachedGroupElement)
  206. k2.ToExtended().ToCached(b)
  207. c := new(CompletedGroupElement)
  208. geSub(c, a, b)
  209. tmp := new(ExtendedGroupElement)
  210. c.ToExtended(tmp)
  211. tmp.ToBytes(diff)
  212. return
  213. }
  214. // this gives you a commitment from an amount
  215. // this is used to convert tx fee or miner tx amount to commitment
  216. func Commitment_From_Amount(amount uint64) Key {
  217. return *(ScalarMultH(d2h(amount)))
  218. }
  219. // this is used to convert miner tx commitment to mask
  220. // equivalent to rctOps.cpp zeroCommit
  221. func ZeroCommitment_From_Amount(amount uint64) Key {
  222. mask := *(identity())
  223. mask = ScalarmultBase(mask)
  224. am := d2h(amount)
  225. bH := ScalarMultH(am)
  226. AddKeys(&mask, &mask, bH)
  227. return mask
  228. }