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.

159 lines
4.3 KiB

  1. package ringct
  2. //import "fmt"
  3. const ATOMS = 64 // 64 bit in the amount field
  4. type bits64 [ATOMS]bool
  5. // implementation of d2b from rctTypes.cpp
  6. // lays out the number from lowest bit at pos 0 and highest at bit 63
  7. func d2b_uint64_to_bits(amount uint64)(bits64){
  8. var bits bits64
  9. for i := 0; amount != 0; i++ {
  10. if (amount&1) == 1 {
  11. bits[i] = true
  12. }
  13. amount = amount >> 1
  14. }
  15. return bits
  16. }
  17. //ProveRange and VerifyRange
  18. //ProveRange gives C, and mask such that \sumCi = C
  19. // c.f. http://eprint.iacr.org/2015/1098 section 5.1
  20. // and Ci is a commitment to either 0 or 2^i, i=0,...,63
  21. // thus this proves that "amount" is in [0, 2^64]
  22. // mask is a such that C = aG + bH, and b = amount
  23. //VerifyRange verifies that \sum Ci = C and that each Ci is a commitment to 0 or 2^i
  24. // this function proves a range using Pedersen commitment and borromean signatures
  25. // implemented in cryptonote rctSigs.cpp
  26. func ProveRange (C *Key, mask *Key, amount uint64) ( *RangeSig){
  27. Sc_0(mask)
  28. copy(C[:], (*identity())[:]) // set C to identity
  29. var ai Key64
  30. var Cih Key64
  31. var sig RangeSig
  32. bits := d2b_uint64_to_bits(amount)
  33. //fmt.Printf("bits %+v\n", bits)
  34. for i := 0; i < ATOMS;i++{
  35. ai[i] = *(RandomScalar()) // grab a random key
  36. // Sc_0(&ai[i]); // make random key zero for tesing puprpose // BUG if line is uncommented
  37. ScReduce32(&ai[i]) // reduce it
  38. // fmt.Printf("ai[%2d] %x\n",i, ai[i])
  39. sig.ci[i] = ScalarmultBase(ai[i])
  40. // fmt.Printf("ci[%2d] %x\n",i, sig.ci[i])
  41. if bits[i] {
  42. AddKeys(&sig.ci[i],&sig.ci[i],&H2[i])
  43. }
  44. SubKeys(&Cih[i],&sig.ci[i],&H2[i])
  45. ScAdd(mask,mask,&ai[i])
  46. AddKeys(C,C,&sig.ci[i])
  47. }
  48. //fmt.Print("C %x\n", *C)
  49. // TODO caculate Borromean signature here
  50. sig.asig = GenerateBorromean(ai, sig.ci, Cih, bits);
  51. return &sig
  52. }
  53. func VerifyRange(c *Key, as RangeSig) bool {
  54. var CiH Key64
  55. tmp := identity()
  56. for i := 0; i < 64; i++ {
  57. SubKeys(&CiH[i], &as.ci[i], &H2[i])
  58. AddKeys(tmp, tmp, &as.ci[i])
  59. }
  60. // fmt.Printf("C %x\n", *c)
  61. // fmt.Printf("tmp %x\n", *tmp)
  62. if *c != *tmp {
  63. return false
  64. }
  65. //return true
  66. return VerifyBorromean(&as.asig, &as.ci, &CiH)
  67. }
  68. //Borromean (c.f. gmax/andytoshi's paper)
  69. func GenerateBorromean(x Key64, P1 Key64, P2 Key64, indices bits64) (BoroSig){
  70. var bb BoroSig
  71. var alpha Key64
  72. var L [2]Key64
  73. var c Key
  74. var data_bytes []byte
  75. for ii := 0; ii < ATOMS;ii++{
  76. var naught,prime int
  77. if indices[ii]{
  78. naught = 1
  79. }else{
  80. naught = 0
  81. }
  82. prime = (naught+1)%2 // basically it is the inverse of naught
  83. alpha[ii] = skGen() // generate a new random scalar
  84. L[naught][ii] = ScalarmultBase(alpha[ii])
  85. if naught == 0 {
  86. bb.s1[ii] = skGen()
  87. c = *(HashToScalar(L[naught][ii][:]))
  88. AddKeys2(&L[prime][ii], &bb.s1[ii], &c, &P2[ii])
  89. }
  90. // original cryptonote does NOT clear out some unset bytes, verify whether it may be a problem for them
  91. data_bytes = append(data_bytes, L[1][ii][:]...)
  92. }
  93. // take the hash of the L1 keys all 64 of them
  94. // we have been collecting them above
  95. bb.ee = *(HashToScalar(data_bytes));
  96. // fmt.Printf("bb.ee %x\n", bb.ee)
  97. var LL, cc Key
  98. for jj := 0 ; jj < ATOMS;jj++{
  99. if indices[jj] == false {
  100. ScMulSub(&bb.s0[jj], &x[jj], &bb.ee, &alpha[jj])
  101. }else{
  102. bb.s0[jj] = skGen()
  103. AddKeys2(&LL, &bb.s0[jj], &bb.ee, &P1[jj])
  104. cc = *(HashToScalar(LL[:]))
  105. ScMulSub(&bb.s1[jj], &x[jj], &cc, &alpha[jj])
  106. }
  107. }
  108. return bb
  109. }
  110. // Verify the Borromean sig
  111. func VerifyBorromean(b *BoroSig, p1, p2 *Key64) bool {
  112. var data []byte
  113. tmp, tmp2 := new(Key), new(Key)
  114. for i := 0; i < 64; i++ {
  115. AddKeys2(tmp, &b.s0[i], &b.ee, &p1[i])
  116. tmp3 := HashToScalar(tmp[:])
  117. AddKeys2(tmp2, &b.s1[i], tmp3, &p2[i])
  118. data = append(data, tmp2[:]...)
  119. }
  120. computed := HashToScalar(data)
  121. // fmt.Printf("comp %x\n", computed)
  122. return *computed == b.ee
  123. }