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.

209 lines
5.1 KiB

  1. package blindsecp256k1
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "math/big"
  6. "github.com/ethereum/go-ethereum/crypto"
  7. )
  8. // swapEndianness swaps the order of the bytes in the slice.
  9. func swapEndianness(b []byte) []byte {
  10. o := make([]byte, len(b))
  11. for i := range b {
  12. o[len(b)-1-i] = b[i]
  13. }
  14. return o
  15. }
  16. // MarshalJSON implements the json marshaler for the Point
  17. func (p Point) MarshalJSON() ([]byte, error) {
  18. return json.Marshal(&struct {
  19. X string `json:"x"`
  20. Y string `json:"y"`
  21. }{
  22. X: p.X.String(),
  23. Y: p.Y.String(),
  24. })
  25. }
  26. // UnmarshalJSON implements the json unmarshaler for the Point
  27. func (p *Point) UnmarshalJSON(b []byte) error {
  28. aux := &struct {
  29. X string `json:"x"`
  30. Y string `json:"y"`
  31. }{}
  32. err := json.Unmarshal(b, &aux)
  33. if err != nil {
  34. return err
  35. }
  36. x, ok := new(big.Int).SetString(aux.X, 10)
  37. if !ok {
  38. return fmt.Errorf("Can not parse Point.X %s", aux.X)
  39. }
  40. y, ok := new(big.Int).SetString(aux.Y, 10)
  41. if !ok {
  42. return fmt.Errorf("Can not parse Point.Y %s", aux.Y)
  43. }
  44. p.X = x
  45. p.Y = y
  46. return nil
  47. }
  48. // Bytes returns a byte array of length 64, with the X & Y coordinates of the
  49. // Point encoded in little-endian. [ X (32 bytes) | Y (32 bytes)]
  50. func (p *Point) Bytes() []byte {
  51. var b [64]byte
  52. copy(b[:32], swapEndianness(p.X.Bytes()))
  53. copy(b[32:], swapEndianness(p.Y.Bytes()))
  54. return b[:]
  55. }
  56. // NewPointFromBytes returns a new *Point from a given byte array with length
  57. // 64 which has encoded the point coordinates each one as 32 bytes in
  58. // little-endian.
  59. func NewPointFromBytes(b []byte) (*Point, error) {
  60. if len(b) != 64 { //nolint:gomnd
  61. return nil, fmt.Errorf("Can not parse bytes to Point,"+
  62. " expected byte array of length %d, current %d",
  63. 64, len(b))
  64. }
  65. p := &Point{}
  66. p.X = new(big.Int).SetBytes(swapEndianness(b[:32]))
  67. p.Y = new(big.Int).SetBytes(swapEndianness(b[32:]))
  68. return p, nil
  69. }
  70. // MarshalJSON implements the json marshaler for the PublicKey
  71. func (pk PublicKey) MarshalJSON() ([]byte, error) {
  72. return json.Marshal(pk.Point())
  73. }
  74. // UnmarshalJSON implements the json unmarshaler for the PublicKey
  75. func (pk *PublicKey) UnmarshalJSON(b []byte) error {
  76. var point *Point
  77. err := json.Unmarshal(b, &point)
  78. if err != nil {
  79. return err
  80. }
  81. pk.X = point.X
  82. pk.Y = point.Y
  83. return nil
  84. }
  85. // Bytes returns a byte array of length 64, with the X & Y coordinates of the
  86. // PublicKey encoded in little-endian. [ X (32 bytes) | Y (32 bytes)]
  87. func (pk *PublicKey) Bytes() []byte {
  88. return pk.Point().Bytes()
  89. }
  90. // NewPublicKeyFromBytes returns a new *PublicKey from a given byte array with
  91. // length 64 which has encoded the public key coordinates each one as 32 bytes
  92. // in little-endian.
  93. func NewPublicKeyFromBytes(b []byte) (*PublicKey, error) {
  94. p, err := NewPointFromBytes(b)
  95. if err != nil {
  96. return nil, err
  97. }
  98. pk := PublicKey(*p)
  99. return &pk, nil
  100. }
  101. // NewPublicKeyFromECDSA returns a *PublicKey from a serialized/marshaled array
  102. // of bytes generated by the ethereum/standard ECDSA PubKey implementation.
  103. func NewPublicKeyFromECDSA(b []byte) (*PublicKey, error) {
  104. pub, err := crypto.UnmarshalPubkey(b)
  105. if err != nil {
  106. return nil, err
  107. }
  108. pk := new(PublicKey)
  109. pk.X = pub.X
  110. pk.Y = pub.Y
  111. return pk, nil
  112. }
  113. // MarshalJSON implements the json marshaler for the Signature
  114. func (sig Signature) MarshalJSON() ([]byte, error) {
  115. return json.Marshal(&struct {
  116. S string `json:"s"`
  117. F struct {
  118. X string `json:"x"`
  119. Y string `json:"y"`
  120. } `json:"f"`
  121. }{
  122. S: sig.S.String(),
  123. F: struct {
  124. X string `json:"x"`
  125. Y string `json:"y"`
  126. }{
  127. X: sig.F.X.String(),
  128. Y: sig.F.Y.String(),
  129. },
  130. })
  131. }
  132. // UnmarshalJSON implements the json unmarshaler for the Signature
  133. func (sig *Signature) UnmarshalJSON(b []byte) error {
  134. aux := &struct {
  135. S string `json:"s"`
  136. F struct {
  137. X string `json:"x"`
  138. Y string `json:"y"`
  139. } `json:"f"`
  140. }{}
  141. err := json.Unmarshal(b, &aux)
  142. if err != nil {
  143. return err
  144. }
  145. s, ok := new(big.Int).SetString(aux.S, 10)
  146. if !ok {
  147. return fmt.Errorf("Can not parse sig.S %s", aux.S)
  148. }
  149. sig.S = s
  150. x, ok := new(big.Int).SetString(aux.F.X, 10)
  151. if !ok {
  152. return fmt.Errorf("Can not parse sig.F.X %s", aux.F.X)
  153. }
  154. y, ok := new(big.Int).SetString(aux.F.Y, 10)
  155. if !ok {
  156. return fmt.Errorf("Can not parse sig.F.Y %s", aux.F.Y)
  157. }
  158. sig.F = &Point{}
  159. sig.F.X = x
  160. sig.F.Y = y
  161. return nil
  162. }
  163. // Bytes returns a byte array of length 96, with the S, F.X and F.Y coordinates
  164. // of the Signature encoded in little-endian.
  165. // [ S (32 bytes | F.X (32 bytes) | F.Y (32 bytes)]
  166. func (sig *Signature) Bytes() []byte {
  167. var b [96]byte
  168. copy(b[:32], swapEndianness(sig.S.Bytes()))
  169. copy(b[32:96], sig.F.Bytes())
  170. return b[:]
  171. }
  172. // NewSignatureFromBytes returns a new *Signature from a given byte array with
  173. // length 96 which has encoded S and the F point coordinates each one as 32
  174. // bytes in little-endian.
  175. func NewSignatureFromBytes(b []byte) (*Signature, error) {
  176. if len(b) != 96 { //nolint:gomnd
  177. return nil,
  178. fmt.Errorf("Can not parse bytes to Signature,"+
  179. " expected byte array of length %d, current %d",
  180. 96, len(b))
  181. }
  182. s := new(big.Int).SetBytes(swapEndianness(b[:32]))
  183. f, err := NewPointFromBytes(b[32:96])
  184. if err != nil {
  185. return nil, err
  186. }
  187. return &Signature{
  188. S: s,
  189. F: f,
  190. }, nil
  191. }