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.

146 lines
3.9 KiB

  1. // Package blindsecp256k1v0 implements the Blind signature scheme explained at
  2. // "An Efficient Blind Signature Scheme Based on the Elliptic Curve Discrete
  3. // Logarithm Problem", by Morteza Nikooghadama & Ali Zakerolhosseini
  4. // http://www.isecure-journal.com/article_39171_47f9ec605dd3918c2793565ec21fcd7a.pdf
  5. //
  6. // LICENSE can be found at https://github.com/arnaucube/go-blindsecp256k1/blob/master/LICENSE
  7. //
  8. package blindsecp256k1v0
  9. // WARNING: WIP code
  10. import (
  11. "bytes"
  12. "crypto/rand"
  13. "math/big"
  14. "github.com/arnaucube/go-blindsecp256k1"
  15. )
  16. // WIP
  17. func newRand() *big.Int {
  18. var b [32]byte
  19. _, err := rand.Read(b[:])
  20. if err != nil {
  21. panic(err)
  22. }
  23. bi := new(big.Int).SetBytes(b[:])
  24. return new(big.Int).Mod(bi, blindsecp256k1.N)
  25. }
  26. // PrivateKey represents the signer's private key
  27. type PrivateKey big.Int
  28. // NewPrivateKey returns a new random private key
  29. func NewPrivateKey() *PrivateKey {
  30. k := newRand()
  31. sk := PrivateKey(*k)
  32. return &sk
  33. }
  34. // BigInt returns a *big.Int representation of the PrivateKey
  35. func (sk *PrivateKey) BigInt() *big.Int {
  36. return (*big.Int)(sk)
  37. }
  38. // Public returns the PublicKey from the PrivateKey
  39. func (sk *PrivateKey) Public() *blindsecp256k1.PublicKey {
  40. Q := blindsecp256k1.G.Mul(sk.BigInt())
  41. pk := blindsecp256k1.PublicKey(*Q)
  42. return &pk
  43. }
  44. // NewRequestParameters returns a new random k (secret) & R (public) parameters
  45. func NewRequestParameters() (*big.Int, *blindsecp256k1.Point) {
  46. k := newRand()
  47. return k, blindsecp256k1.G.Mul(k) // R = kG
  48. }
  49. // BlindSign performs the blind signature on the given mBlinded using
  50. // SignerPrivateData values
  51. func (sk *PrivateKey) BlindSign(mBlinded *big.Int, k *big.Int) *big.Int {
  52. // TODO add pending checks
  53. // s' = d(m') + k
  54. sBlind := new(big.Int).Add(
  55. new(big.Int).Mul(sk.BigInt(), mBlinded),
  56. k)
  57. return sBlind
  58. }
  59. // UserSecretData contains the secret values from the User (a, b, c) and the
  60. // public F
  61. type UserSecretData struct {
  62. A *big.Int
  63. B *big.Int
  64. C *big.Int
  65. F *blindsecp256k1.Point // public
  66. }
  67. // Blind performs the blinding operation on m using SignerPublicData parameters
  68. func Blind(m *big.Int, signerPubK *blindsecp256k1.PublicKey,
  69. signerR *blindsecp256k1.Point) (*big.Int, *UserSecretData) {
  70. u := &UserSecretData{}
  71. u.A = newRand()
  72. u.B = newRand()
  73. u.C = newRand()
  74. binv := new(big.Int).ModInverse(u.B, blindsecp256k1.N)
  75. // F = b^-1 R + a b^-1 Q + c G
  76. bR := signerR.Mul(binv)
  77. abinv := new(big.Int).Mul(u.A, binv)
  78. abinv = new(big.Int).Mod(abinv, blindsecp256k1.N)
  79. abQ := signerPubK.Point().Mul(abinv)
  80. cG := blindsecp256k1.G.Mul(u.C)
  81. u.F = bR.Add(abQ).Add(cG)
  82. // TODO check F==O
  83. r := new(big.Int).Mod(u.F.X, blindsecp256k1.N)
  84. // m' = br(m)+a
  85. br := new(big.Int).Mul(u.B, r)
  86. brm := new(big.Int).Mul(br, m)
  87. mBlinded := new(big.Int).Add(brm, u.A)
  88. mBlinded = new(big.Int).Mod(mBlinded, blindsecp256k1.N)
  89. return mBlinded, u
  90. }
  91. // Signature contains the signature values S & F
  92. type Signature struct {
  93. S *big.Int
  94. F *blindsecp256k1.Point
  95. }
  96. // Unblind performs the unblinding operation of the blinded signature for the
  97. // given and the UserSecretData
  98. func Unblind(sBlind *big.Int, u *UserSecretData) *Signature {
  99. // s = b^-1 s' + c
  100. binv := new(big.Int).ModInverse(u.B, blindsecp256k1.N)
  101. bs := new(big.Int).Mul(binv, sBlind)
  102. s := new(big.Int).Add(bs, u.C)
  103. s = new(big.Int).Mod(s, blindsecp256k1.N)
  104. return &Signature{
  105. S: s,
  106. F: u.F,
  107. }
  108. }
  109. // Verify checks the signature of the message m for the given PublicKey
  110. func Verify(m *big.Int, signature *Signature, q *blindsecp256k1.PublicKey) bool {
  111. // TODO add pending checks
  112. sG := blindsecp256k1.G.Mul(signature.S) // sG
  113. r := new(big.Int).Mod(signature.F.X, blindsecp256k1.N) // r = Fx mod N
  114. rm := new(big.Int).Mul(r, m)
  115. rm = new(big.Int).Mod(rm, blindsecp256k1.N)
  116. rmQ := q.Point().Mul(rm)
  117. rmQF := rmQ.Add(signature.F) // rmQ + F
  118. // check sG == rmQ + F
  119. if bytes.Equal(sG.X.Bytes(), rmQF.X.Bytes()) &&
  120. bytes.Equal(sG.Y.Bytes(), rmQF.Y.Bytes()) {
  121. return true
  122. }
  123. return false
  124. }