git.gammaspectra.live/P2Pool/consensus@v0.0.0-20240403173234-a039820b20c9/monero/crypto/public.go (about)

     1  package crypto
     2  
     3  import (
     4  	"bytes"
     5  	"database/sql/driver"
     6  	"encoding/hex"
     7  	"errors"
     8  	"git.gammaspectra.live/P2Pool/consensus/utils"
     9  	"git.gammaspectra.live/P2Pool/edwards25519"
    10  	fasthex "github.com/tmthrgd/go-hex"
    11  )
    12  
    13  type PublicKey interface {
    14  	AsSlice() PublicKeySlice
    15  	AsBytes() PublicKeyBytes
    16  	AsPoint() *PublicKeyPoint
    17  
    18  	String() string
    19  	UnmarshalJSON(b []byte) error
    20  	MarshalJSON() ([]byte, error)
    21  }
    22  
    23  const PublicKeySize = 32
    24  
    25  var ZeroPublicKeyBytes PublicKeyBytes
    26  
    27  type PublicKeyPoint edwards25519.Point
    28  
    29  func (k *PublicKeyPoint) AsSlice() PublicKeySlice {
    30  	return k.Point().Bytes()
    31  }
    32  
    33  func (k *PublicKeyPoint) AsBytes() (buf PublicKeyBytes) {
    34  	copy(buf[:], k.AsSlice())
    35  	return
    36  }
    37  
    38  func (k *PublicKeyPoint) AsPoint() *PublicKeyPoint {
    39  	return k
    40  }
    41  
    42  func (k *PublicKeyPoint) Point() *edwards25519.Point {
    43  	return (*edwards25519.Point)(k)
    44  }
    45  
    46  func (k *PublicKeyPoint) Add(b *PublicKeyPoint) *PublicKeyPoint {
    47  	return PublicKeyFromPoint(GetEdwards25519Point().Add(k.Point(), b.Point()))
    48  }
    49  
    50  func (k *PublicKeyPoint) Subtract(b *PublicKeyPoint) *PublicKeyPoint {
    51  	return PublicKeyFromPoint(GetEdwards25519Point().Subtract(k.Point(), b.Point()))
    52  }
    53  
    54  func (k *PublicKeyPoint) Multiply(b *PrivateKeyScalar) *PublicKeyPoint {
    55  	return PublicKeyFromPoint(GetEdwards25519Point().ScalarMult(b.Scalar(), k.Point()))
    56  }
    57  
    58  func (k *PublicKeyPoint) Cofactor() *PublicKeyPoint {
    59  	return PublicKeyFromPoint(GetEdwards25519Point().MultByCofactor(k.Point()))
    60  }
    61  
    62  func PublicKeyFromPoint(point *edwards25519.Point, _ ...any) *PublicKeyPoint {
    63  	return (*PublicKeyPoint)(point)
    64  }
    65  
    66  func (k *PublicKeyPoint) String() string {
    67  	return hex.EncodeToString(k.Point().Bytes())
    68  }
    69  
    70  func (k *PublicKeyPoint) UnmarshalJSON(b []byte) error {
    71  	var s string
    72  	if err := utils.UnmarshalJSON(b, &s); err != nil {
    73  		return err
    74  	}
    75  
    76  	if buf, err := hex.DecodeString(s); err != nil {
    77  		return err
    78  	} else {
    79  		if len(buf) != PublicKeySize {
    80  			return errors.New("wrong key size")
    81  		}
    82  
    83  		if _, err = k.Point().SetBytes(buf); err != nil {
    84  			return err
    85  		}
    86  
    87  		return nil
    88  	}
    89  }
    90  
    91  func (k *PublicKeyPoint) MarshalJSON() ([]byte, error) {
    92  	return []byte("\"" + k.String() + "\""), nil
    93  }
    94  
    95  type PublicKeyBytes [PublicKeySize]byte
    96  
    97  func (k *PublicKeyBytes) AsSlice() PublicKeySlice {
    98  	return (*k)[:]
    99  }
   100  
   101  func (k *PublicKeyBytes) AsBytes() PublicKeyBytes {
   102  	return *k
   103  }
   104  
   105  func (k *PublicKeyBytes) AsPoint() *PublicKeyPoint {
   106  	return PublicKeyFromPoint(GetEdwards25519Point().SetBytes(k.AsSlice()))
   107  }
   108  
   109  func (k *PublicKeyBytes) String() string {
   110  	return hex.EncodeToString(k.AsSlice())
   111  }
   112  
   113  func (k *PublicKeyBytes) Scan(src any) error {
   114  	if src == nil {
   115  		return nil
   116  	} else if buf, ok := src.([]byte); ok {
   117  		if len(buf) == 0 {
   118  			return nil
   119  		}
   120  		if len(buf) != PublicKeySize {
   121  			return errors.New("invalid key size")
   122  		}
   123  		copy((*k)[:], buf)
   124  
   125  		return nil
   126  	}
   127  	return errors.New("invalid type")
   128  }
   129  
   130  func (k *PublicKeyBytes) Value() (driver.Value, error) {
   131  	var zeroPubKey PublicKeyBytes
   132  	if *k == zeroPubKey {
   133  		return nil, nil
   134  	}
   135  	return []byte((*k)[:]), nil
   136  }
   137  
   138  func (k *PublicKeyBytes) UnmarshalJSON(b []byte) error {
   139  	if len(b) == 0 || len(b) == 2 {
   140  		return nil
   141  	}
   142  
   143  	if len(b) != PublicKeySize*2+2 {
   144  		return errors.New("wrong key size")
   145  	}
   146  
   147  	if _, err := fasthex.Decode(k[:], b[1:len(b)-1]); err != nil {
   148  		return err
   149  	} else {
   150  		return nil
   151  	}
   152  }
   153  
   154  func (k *PublicKeyBytes) MarshalJSON() ([]byte, error) {
   155  	var buf [PublicKeySize*2 + 2]byte
   156  	buf[0] = '"'
   157  	buf[PublicKeySize*2+1] = '"'
   158  	fasthex.Encode(buf[1:], k[:])
   159  	return buf[:], nil
   160  }
   161  
   162  type PublicKeySlice []byte
   163  
   164  func (k *PublicKeySlice) AsSlice() PublicKeySlice {
   165  	return *k
   166  }
   167  
   168  func (k *PublicKeySlice) AsBytes() (buf PublicKeyBytes) {
   169  	copy(buf[:], *k)
   170  	return buf
   171  }
   172  
   173  func (k *PublicKeySlice) AsPoint() *PublicKeyPoint {
   174  	return PublicKeyFromPoint(GetEdwards25519Point().SetBytes(*k))
   175  }
   176  
   177  func (k *PublicKeySlice) String() string {
   178  	return hex.EncodeToString(*k)
   179  }
   180  
   181  func (k *PublicKeySlice) Scan(src any) error {
   182  	if src == nil {
   183  		return nil
   184  	} else if buf, ok := src.([]byte); ok {
   185  		if len(buf) == 0 {
   186  			return nil
   187  		}
   188  		if len(buf) != PublicKeySize {
   189  			return errors.New("invalid key size")
   190  		}
   191  		copy(*k, buf)
   192  
   193  		return nil
   194  	}
   195  	return errors.New("invalid type")
   196  }
   197  
   198  func (k *PublicKeySlice) Value() (driver.Value, error) {
   199  	var zeroPubKey PublicKeyBytes
   200  	if bytes.Compare(*k, zeroPubKey[:]) == 0 {
   201  		return nil, nil
   202  	}
   203  	return []byte(*k), nil
   204  }
   205  
   206  func (k *PublicKeySlice) UnmarshalJSON(b []byte) error {
   207  	var s string
   208  	if err := utils.UnmarshalJSON(b, &s); err != nil {
   209  		return err
   210  	}
   211  
   212  	if buf, err := hex.DecodeString(s); err != nil {
   213  		return err
   214  	} else {
   215  		if len(buf) != PublicKeySize {
   216  			return errors.New("wrong key size")
   217  		}
   218  
   219  		*k = buf
   220  		return nil
   221  	}
   222  }
   223  
   224  func (k *PublicKeySlice) MarshalJSON() ([]byte, error) {
   225  	var buf [PublicKeySize*2 + 2]byte
   226  	buf[0] = '"'
   227  	buf[PublicKeySize*2+1] = '"'
   228  	fasthex.Encode(buf[1:], (*k)[:])
   229  	return buf[:], nil
   230  }