git.gammaspectra.live/P2Pool/consensus/v3@v3.8.0/monero/crypto/public.go (about)

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