git.gammaspectra.live/P2Pool/consensus@v0.0.0-20240403173234-a039820b20c9/monero/crypto/private.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 PrivateKey interface {
    14  	AsSlice() PrivateKeySlice
    15  	AsBytes() PrivateKeyBytes
    16  	AsScalar() *PrivateKeyScalar
    17  
    18  	PublicKey() PublicKey
    19  
    20  	// GetDerivation derives a secret via a peer PublicKey, ECDH
    21  	GetDerivation(public PublicKey) PublicKey
    22  
    23  	// GetDerivationCofactor derives a secret via a peer PublicKey, ECDH, making sure it is in the proper range (*8)
    24  	GetDerivationCofactor(public PublicKey) PublicKey
    25  
    26  	String() string
    27  	UnmarshalJSON(b []byte) error
    28  	MarshalJSON() ([]byte, error)
    29  }
    30  
    31  const PrivateKeySize = 32
    32  
    33  var ZeroPrivateKeyBytes PrivateKeyBytes
    34  
    35  type PrivateKeyScalar edwards25519.Scalar
    36  
    37  func (p *PrivateKeyScalar) AsSlice() PrivateKeySlice {
    38  	return p.Scalar().Bytes()
    39  }
    40  
    41  func (p *PrivateKeyScalar) AsBytes() (buf PrivateKeyBytes) {
    42  	copy(buf[:], p.AsSlice())
    43  	return
    44  }
    45  
    46  func (p *PrivateKeyScalar) AsScalar() *PrivateKeyScalar {
    47  	return p
    48  }
    49  
    50  func PrivateKeyFromScalar(scalar *edwards25519.Scalar) *PrivateKeyScalar {
    51  	return (*PrivateKeyScalar)(scalar)
    52  }
    53  
    54  func (p *PrivateKeyScalar) Scalar() *edwards25519.Scalar {
    55  	return (*edwards25519.Scalar)(p)
    56  }
    57  
    58  func (p *PrivateKeyScalar) PublicKey() PublicKey {
    59  	return PublicKeyFromPoint(GetEdwards25519Point().ScalarBaseMult(p.Scalar()))
    60  }
    61  
    62  func (p *PrivateKeyScalar) GetDerivation(public PublicKey) PublicKey {
    63  	return deriveKeyExchangeSecret(p, public.AsPoint())
    64  }
    65  
    66  func (p *PrivateKeyScalar) GetDerivationCofactor(public PublicKey) PublicKey {
    67  	return deriveKeyExchangeSecretCofactor(p, public.AsPoint())
    68  }
    69  
    70  func (p *PrivateKeyScalar) String() string {
    71  	return hex.EncodeToString(p.Scalar().Bytes())
    72  }
    73  
    74  func (p *PrivateKeyScalar) UnmarshalJSON(b []byte) error {
    75  	var s string
    76  	if err := utils.UnmarshalJSON(b, &s); err != nil {
    77  		return err
    78  	}
    79  
    80  	if buf, err := hex.DecodeString(s); err != nil {
    81  		return err
    82  	} else {
    83  		if len(buf) != PrivateKeySize {
    84  			return errors.New("wrong key size")
    85  		}
    86  
    87  		if _, err = p.Scalar().SetCanonicalBytes(buf); err != nil {
    88  			return err
    89  		}
    90  
    91  		return nil
    92  	}
    93  }
    94  
    95  func (p *PrivateKeyScalar) MarshalJSON() ([]byte, error) {
    96  	return []byte("\"" + p.String() + "\""), nil
    97  }
    98  
    99  type PrivateKeyBytes [PrivateKeySize]byte
   100  
   101  func (k *PrivateKeyBytes) AsSlice() PrivateKeySlice {
   102  	return (*k)[:]
   103  }
   104  
   105  func (k *PrivateKeyBytes) AsBytes() PrivateKeyBytes {
   106  	return *k
   107  }
   108  
   109  func (k *PrivateKeyBytes) AsScalar() *PrivateKeyScalar {
   110  	secret, _ := GetEdwards25519Scalar().SetCanonicalBytes((*k)[:])
   111  	return PrivateKeyFromScalar(secret)
   112  }
   113  
   114  func (k *PrivateKeyBytes) PublicKey() PublicKey {
   115  	return PublicKeyFromPoint(GetEdwards25519Point().ScalarBaseMult(k.AsScalar().Scalar()))
   116  }
   117  
   118  func (k *PrivateKeyBytes) GetDerivation(public PublicKey) PublicKey {
   119  	return k.AsScalar().GetDerivation(public)
   120  }
   121  
   122  func (k *PrivateKeyBytes) GetDerivationCofactor(public PublicKey) PublicKey {
   123  	return k.AsScalar().GetDerivationCofactor(public)
   124  }
   125  
   126  func (k *PrivateKeyBytes) String() string {
   127  	return hex.EncodeToString(k.AsSlice())
   128  }
   129  
   130  func (k *PrivateKeyBytes) Scan(src any) error {
   131  	if src == nil {
   132  		return nil
   133  	} else if buf, ok := src.([]byte); ok {
   134  		if len(buf) == 0 {
   135  			return nil
   136  		}
   137  		if len(buf) != PrivateKeySize {
   138  			return errors.New("invalid key size")
   139  		}
   140  		copy((*k)[:], buf)
   141  
   142  		return nil
   143  	}
   144  	return errors.New("invalid type")
   145  }
   146  
   147  func (k *PrivateKeyBytes) Value() (driver.Value, error) {
   148  	var zeroPrivKey PrivateKeyBytes
   149  	if *k == zeroPrivKey {
   150  		return nil, nil
   151  	}
   152  	return []byte((*k)[:]), nil
   153  }
   154  
   155  func (k *PrivateKeyBytes) UnmarshalJSON(b []byte) error {
   156  	if len(b) == 0 || len(b) == 2 {
   157  		return nil
   158  	}
   159  
   160  	if len(b) != PrivateKeySize*2+2 {
   161  		return errors.New("wrong key size")
   162  	}
   163  
   164  	if _, err := fasthex.Decode(k[:], b[1:len(b)-1]); err != nil {
   165  		return err
   166  	} else {
   167  		return nil
   168  	}
   169  }
   170  
   171  func (k *PrivateKeyBytes) MarshalJSON() ([]byte, error) {
   172  	var buf [PrivateKeySize*2 + 2]byte
   173  	buf[0] = '"'
   174  	buf[PrivateKeySize*2+1] = '"'
   175  	fasthex.Encode(buf[1:], k[:])
   176  	return buf[:], nil
   177  }
   178  
   179  type PrivateKeySlice []byte
   180  
   181  func (k *PrivateKeySlice) AsSlice() PrivateKeySlice {
   182  	return *k
   183  }
   184  
   185  func (k *PrivateKeySlice) AsBytes() (buf PrivateKeyBytes) {
   186  	copy(buf[:], *k)
   187  	return
   188  }
   189  
   190  func (k *PrivateKeySlice) AsScalar() *PrivateKeyScalar {
   191  	secret, _ := GetEdwards25519Scalar().SetCanonicalBytes(*k)
   192  	return PrivateKeyFromScalar(secret)
   193  }
   194  
   195  func (k *PrivateKeySlice) PublicKey() PublicKey {
   196  	return PublicKeyFromPoint(GetEdwards25519Point().ScalarBaseMult(k.AsScalar().Scalar()))
   197  }
   198  
   199  func (k *PrivateKeySlice) GetDerivation(public PublicKey) PublicKey {
   200  	return k.AsScalar().GetDerivation(public)
   201  }
   202  
   203  func (k *PrivateKeySlice) GetDerivationCofactor(public PublicKey) PublicKey {
   204  	return k.AsScalar().GetDerivationCofactor(public)
   205  }
   206  
   207  func (k *PrivateKeySlice) String() string {
   208  	return hex.EncodeToString(*k)
   209  }
   210  
   211  func (k *PrivateKeySlice) Scan(src any) error {
   212  	if src == nil {
   213  		return nil
   214  	} else if buf, ok := src.([]byte); ok {
   215  		if len(buf) == 0 {
   216  			return nil
   217  		}
   218  		if len(buf) != PrivateKeySize {
   219  			return errors.New("invalid key size")
   220  		}
   221  		copy(*k, buf)
   222  
   223  		return nil
   224  	}
   225  	return errors.New("invalid type")
   226  }
   227  
   228  func (k *PrivateKeySlice) Value() (driver.Value, error) {
   229  	var zeroPrivKey PublicKeyBytes
   230  	if bytes.Compare(*k, zeroPrivKey[:]) == 0 {
   231  		return nil, nil
   232  	}
   233  	return []byte(*k), nil
   234  }
   235  
   236  func (k *PrivateKeySlice) UnmarshalJSON(b []byte) error {
   237  	var s string
   238  	if err := utils.UnmarshalJSON(b, &s); err != nil {
   239  		return err
   240  	}
   241  
   242  	if buf, err := hex.DecodeString(s); err != nil {
   243  		return err
   244  	} else {
   245  		if len(buf) != PrivateKeySize {
   246  			return errors.New("wrong key size")
   247  		}
   248  
   249  		*k = buf
   250  		return nil
   251  	}
   252  }
   253  
   254  func (k *PrivateKeySlice) MarshalJSON() ([]byte, error) {
   255  	var buf [PrivateKeySize*2 + 2]byte
   256  	buf[0] = '"'
   257  	buf[PrivateKeySize*2+1] = '"'
   258  	fasthex.Encode(buf[1:], (*k)[:])
   259  	return buf[:], nil
   260  }
   261  
   262  func deriveKeyExchangeSecretCofactor(private *PrivateKeyScalar, public *PublicKeyPoint) *PublicKeyPoint {
   263  	return public.Multiply(private).Cofactor()
   264  }
   265  
   266  func deriveKeyExchangeSecret(private *PrivateKeyScalar, public *PublicKeyPoint) *PublicKeyPoint {
   267  	return public.Multiply(private)
   268  }