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.

404 lines
10 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 crypto
  17. import "io"
  18. import "fmt"
  19. import "bytes"
  20. import "crypto/rand"
  21. import "encoding/hex"
  22. import "encoding/binary"
  23. const KeyLength = 32
  24. // Key can be a Scalar or a Point
  25. type Key [KeyLength]byte
  26. func (k Key) MarshalText() ([]byte, error) {
  27. return []byte(fmt.Sprintf("%x", k[:])), nil
  28. }
  29. func (k Key) String() string {
  30. return fmt.Sprintf("%x", k[:])
  31. }
  32. func (p *Key) FromBytes(b [KeyLength]byte) {
  33. *p = b
  34. }
  35. func (p *Key) ToBytes() (result [KeyLength]byte) {
  36. result = [KeyLength]byte(*p)
  37. return
  38. }
  39. // convert a hex string to a key
  40. func HexToKey(h string) (result Key) {
  41. byteSlice, _ := hex.DecodeString(h)
  42. if len(byteSlice) != 32 {
  43. panic("Incorrect key size")
  44. }
  45. copy(result[:], byteSlice)
  46. return
  47. }
  48. func HexToHash(h string) (result Hash) {
  49. byteSlice, _ := hex.DecodeString(h)
  50. if len(byteSlice) != 32 {
  51. panic("Incorrect key size")
  52. }
  53. copy(result[:], byteSlice)
  54. return
  55. }
  56. // generates a public from the secret key
  57. func (p *Key) PublicKey() (pubKey *Key) {
  58. point := new(ExtendedGroupElement)
  59. GeScalarMultBase(point, p)
  60. pubKey = new(Key)
  61. point.ToBytes(pubKey)
  62. return
  63. }
  64. // tests whether the key is valid ( represents a point on the curve )
  65. func (k *Key) Public_Key_Valid() bool {
  66. var point ExtendedGroupElement
  67. return point.FromBytes(k)
  68. }
  69. func (k *Key) Private_Key_Valid() bool {
  70. return Sc_check(k)
  71. }
  72. // Creates a point on the Edwards Curve by hashing the key
  73. func (p *Key) HashToEC() (result *ExtendedGroupElement) {
  74. result = new(ExtendedGroupElement)
  75. var p1 ProjectiveGroupElement
  76. var p2 CompletedGroupElement
  77. h := Key(Keccak256(p[:]))
  78. p1.FromBytes(&h)
  79. GeMul8(&p2, &p1)
  80. p2.ToExtended(result)
  81. return
  82. }
  83. func (p *Key) HashToPoint() (result Key) {
  84. extended := p.HashToEC()
  85. extended.ToBytes(&result)
  86. return
  87. }
  88. // this uses random number generator from the OS
  89. func RandomScalar() (result *Key) {
  90. result = new(Key)
  91. var reduceFrom [KeyLength * 2]byte
  92. tmp := make([]byte, KeyLength*2)
  93. rand.Read(tmp)
  94. copy(reduceFrom[:], tmp)
  95. ScReduce(result, &reduceFrom)
  96. return
  97. }
  98. // generate a new private-public key pair
  99. func NewKeyPair() (privKey *Key, pubKey *Key) {
  100. privKey = RandomScalar()
  101. pubKey = privKey.PublicKey()
  102. return
  103. }
  104. func ParseKey(buf io.Reader) (result Key, err error) {
  105. key := make([]byte, KeyLength)
  106. if _, err = buf.Read(key); err != nil {
  107. return
  108. }
  109. copy(result[:], key)
  110. return
  111. }
  112. /*
  113. //does a * G where a is a scalar and G is the curve basepoint
  114. key scalarmultBase(const key & a) {
  115. ge_p3 point;
  116. key aG;
  117. sc_reduce32copy(aG.bytes, a.bytes); //do this beforehand
  118. ge_scalarmult_base(&point, aG.bytes);
  119. ge_p3_tobytes(aG.bytes, &point);
  120. return aG;
  121. }
  122. */
  123. //does a * G where a is a scalar and G is the curve basepoint
  124. func ScalarmultBase(a Key) (aG Key) {
  125. reduce32copy := a
  126. ScReduce32(&reduce32copy)
  127. point := new(ExtendedGroupElement)
  128. GeScalarMultBase(point, &a)
  129. point.ToBytes(&aG)
  130. return aG
  131. }
  132. // generates a key which can be used as private key or mask
  133. // this function is similiar to RandomScalar except for reduce32, TODO can we merge both
  134. func skGen() Key {
  135. skey := RandomScalar()
  136. ScReduce32(skey)
  137. return *skey
  138. }
  139. func (k *Key) ToExtended() (result *ExtendedGroupElement) {
  140. result = new(ExtendedGroupElement)
  141. result.FromBytes(k)
  142. return
  143. }
  144. // bothe the function resturn identity of the ed25519 curve
  145. func identity() (result *Key) {
  146. result = new(Key)
  147. result[0] = 1
  148. return
  149. }
  150. func CurveIdentity() (result Key) {
  151. result = Identity
  152. return result
  153. }
  154. func CurveOrder() (result Key) {
  155. result = L
  156. return result
  157. }
  158. // convert a uint64 to a scalar
  159. func d2h(val uint64) (result *Key) {
  160. result = new(Key)
  161. for i := 0; val > 0; i++ {
  162. result[i] = byte(val & 0xFF)
  163. val /= 256
  164. }
  165. return
  166. }
  167. func HashToScalar(data ...[]byte) (result *Key) {
  168. result = new(Key)
  169. *result = Key(Keccak256(data...))
  170. ScReduce32(result)
  171. return
  172. }
  173. // does a * P where a is a scalar and P is an arbitrary point
  174. func ScalarMultKey(Point *Key, scalar *Key) (result *Key) {
  175. P := new(ExtendedGroupElement)
  176. P.FromBytes(Point)
  177. resultPoint := new(ProjectiveGroupElement)
  178. GeScalarMult(resultPoint, scalar, P)
  179. result = new(Key)
  180. resultPoint.ToBytes(result)
  181. return
  182. }
  183. // multiply a scalar by H (second curve point of Pedersen Commitment)
  184. func ScalarMultH(scalar *Key) (result *Key) {
  185. h := new(ExtendedGroupElement)
  186. h.FromBytes(&H)
  187. resultPoint := new(ProjectiveGroupElement)
  188. GeScalarMult(resultPoint, scalar, h)
  189. result = new(Key)
  190. resultPoint.ToBytes(result)
  191. return
  192. }
  193. // add two points together
  194. func AddKeys(sum, k1, k2 *Key) {
  195. a := k1.ToExtended()
  196. b := new(CachedGroupElement)
  197. k2.ToExtended().ToCached(b)
  198. c := new(CompletedGroupElement)
  199. geAdd(c, a, b)
  200. tmp := new(ExtendedGroupElement)
  201. c.ToExtended(tmp)
  202. tmp.ToBytes(sum)
  203. return
  204. }
  205. // compute a*G + b*B
  206. func AddKeys2(result, a, b, B *Key) {
  207. BPoint := B.ToExtended()
  208. RPoint := new(ProjectiveGroupElement)
  209. GeDoubleScalarMultVartime(RPoint, b, BPoint, a)
  210. RPoint.ToBytes(result)
  211. return
  212. }
  213. //addKeys3
  214. //aAbB = a*A + b*B where a, b are scalars, A, B are curve points
  215. //B must be input after applying "precomp"
  216. func AddKeys3(result *Key, a *Key, A *Key, b *Key, B_Precomputed *[8]CachedGroupElement) {
  217. A_Point := new(ExtendedGroupElement)
  218. A_Point.FromBytes(A)
  219. result_projective := new(ProjectiveGroupElement)
  220. GeDoubleScalarMultPrecompVartime(result_projective, a, A_Point, b, B_Precomputed)
  221. result_projective.ToBytes(result)
  222. }
  223. // subtract two points A - B
  224. func SubKeys(diff, k1, k2 *Key) {
  225. a := k1.ToExtended()
  226. b := new(CachedGroupElement)
  227. k2.ToExtended().ToCached(b)
  228. c := new(CompletedGroupElement)
  229. geSub(c, a, b)
  230. tmp := new(ExtendedGroupElement)
  231. c.ToExtended(tmp)
  232. tmp.ToBytes(diff)
  233. return
  234. }
  235. // this gives you a commitment from an amount
  236. // this is used to convert tx fee or miner tx amount to commitment
  237. func Commitment_From_Amount(amount uint64) Key {
  238. return *(ScalarMultH(d2h(amount)))
  239. }
  240. // this is used to convert miner tx commitment to mask
  241. // equivalent to rctOps.cpp zeroCommit
  242. func ZeroCommitment_From_Amount(amount uint64) Key {
  243. mask := *(identity())
  244. mask = ScalarmultBase(mask)
  245. am := d2h(amount)
  246. bH := ScalarMultH(am)
  247. AddKeys(&mask, &mask, bH)
  248. return mask
  249. }
  250. // zero fill the key
  251. func Sc_0(k *Key) {
  252. for i := 0; i < 32; i++ {
  253. k[i] = 0
  254. }
  255. }
  256. // RandomPubKey takes a random scalar, interprets it as a point on the curve
  257. // remember the low order bug and do more auditing of the entire thing
  258. func RandomPubKey() (result *Key) {
  259. result = new(Key)
  260. p3 := new(ExtendedGroupElement)
  261. var p1 ProjectiveGroupElement
  262. var p2 CompletedGroupElement
  263. h := RandomScalar()
  264. p1.FromBytes(h)
  265. GeMul8(&p2, &p1)
  266. p2.ToExtended(p3)
  267. p3.ToBytes(result)
  268. return
  269. }
  270. // this is the main key derivation function and is the crux
  271. // when deriving keys in the case user A wants to send DERO to another user B ( this is outgoing case)
  272. // public key is B's view key
  273. // private keys is TX private key
  274. // if user B wants to derive key, he needs to ( this is incoming case )
  275. // public key is TX public key
  276. // private is B's private keys
  277. // HOPE the above is clean and clear
  278. func KeyDerivation(pub *Key, priv *Key) (KeyDerivation Key) {
  279. var point ExtendedGroupElement
  280. var point2 ProjectiveGroupElement
  281. var point3 CompletedGroupElement
  282. if !priv.Private_Key_Valid() {
  283. panic("Invalid private key.")
  284. }
  285. tmp := *pub
  286. if !point.FromBytes(&tmp) {
  287. panic("Invalid public key.")
  288. }
  289. tmp = *priv
  290. GeScalarMult(&point2, &tmp, &point)
  291. GeMul8(&point3, &point2)
  292. point3.ToProjective(&point2)
  293. point2.ToBytes(&tmp)
  294. return tmp
  295. }
  296. // the origincal c implementation needs to be checked for varint overflow
  297. // we also need to check the compatibility of golang varint with cryptonote implemented varint
  298. // outputIndex is the position of output within that specific transaction
  299. func (k *Key) KeyDerivationToScalar(outputIndex uint64) (scalar *Key) {
  300. tmp := make([]byte, 12, 12)
  301. length := binary.PutUvarint(tmp, outputIndex)
  302. tmp = tmp[:length]
  303. var buf bytes.Buffer
  304. buf.Write(k[:])
  305. buf.Write(tmp)
  306. scalar = HashToScalar(buf.Bytes())
  307. return
  308. }
  309. // generate ephermal keys from a key derivation
  310. // base key is the B's public spend key or A's private spend key
  311. // outputIndex is the position of output within that specific transaction
  312. func (kd *Key) KeyDerivation_To_PublicKey(outputIndex uint64, baseKey Key) Key {
  313. var point1, point2 ExtendedGroupElement
  314. var point3 CachedGroupElement
  315. var point4 CompletedGroupElement
  316. var point5 ProjectiveGroupElement
  317. tmp := baseKey
  318. if !point1.FromBytes(&tmp) {
  319. panic("Invalid public key.")
  320. }
  321. scalar := kd.KeyDerivationToScalar(outputIndex)
  322. GeScalarMultBase(&point2, scalar)
  323. point2.ToCached(&point3)
  324. geAdd(&point4, &point1, &point3)
  325. point4.ToProjective(&point5)
  326. point5.ToBytes(&tmp)
  327. return tmp
  328. }
  329. // generate ephermal keys from a key derivation
  330. // base key is the A's private spend key
  331. // outputIndex is the position of output within that specific transaction
  332. func (kd *Key) KeyDerivation_To_PrivateKey(outputIndex uint64, baseKey Key) Key {
  333. if !baseKey.Private_Key_Valid() {
  334. panic("Invalid private key.")
  335. }
  336. scalar := kd.KeyDerivationToScalar(outputIndex)
  337. tmp := baseKey
  338. ScAdd(&tmp, &tmp, scalar)
  339. return tmp
  340. }
  341. // NewKeyImage creates a new KeyImage from the given public and private keys.
  342. // The keys are usually the ephemeral keys derived using KeyDerivation.
  343. func GenerateKeyImage(pub Key, private Key) Key {
  344. var proj ProjectiveGroupElement
  345. ext := pub.HashToEC()
  346. GeScalarMult(&proj, &private, ext)
  347. var ki Key
  348. proj.ToBytes(&ki)
  349. return ki
  350. }