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

     1  package crypto
     2  
     3  import (
     4  	"git.gammaspectra.live/P2Pool/consensus/v3/types"
     5  	"git.gammaspectra.live/P2Pool/edwards25519"
     6  )
     7  
     8  // Signature Schnorr signature
     9  type Signature struct {
    10  	// C hash of data in signature, also called e
    11  	C *edwards25519.Scalar
    12  	// R result of the signature, also called s
    13  	R *edwards25519.Scalar
    14  }
    15  
    16  // SignatureSigningHandler receives k, inserts it or a pubkey into its data, and produces a []byte buffer for Signing/Verifying
    17  type SignatureSigningHandler func(r PrivateKey) []byte
    18  
    19  // SignatureVerificationHandler receives r = pubkey(k), inserts it into its data, and produces a []byte buffer for Signing/Verifying
    20  type SignatureVerificationHandler func(r PublicKey) []byte
    21  
    22  func NewSignatureFromBytes(buf []byte) *Signature {
    23  	if len(buf) != types.HashSize*2 {
    24  		return nil
    25  	}
    26  	signature := &Signature{}
    27  	var err error
    28  	if signature.C, err = GetEdwards25519Scalar().SetCanonicalBytes(buf[:32]); err != nil {
    29  		return nil
    30  	} else if signature.R, err = GetEdwards25519Scalar().SetCanonicalBytes(buf[32:]); err != nil {
    31  		return nil
    32  	} else {
    33  		return signature
    34  	}
    35  }
    36  
    37  func (s *Signature) Bytes() []byte {
    38  	buf := make([]byte, 0, types.HashSize*2)
    39  	buf = append(buf, s.C.Bytes()...)
    40  	buf = append(buf, s.R.Bytes()...)
    41  	return buf
    42  }
    43  
    44  // Verify checks a Schnorr Signature using H = keccak
    45  func (s *Signature) Verify(handler SignatureVerificationHandler, publicKey PublicKey) (ok bool, r *PublicKeyPoint) {
    46  	//s = C * k, R * G
    47  	sp := GetEdwards25519Point().VarTimeDoubleScalarBaseMult(s.C, publicKey.AsPoint().Point(), s.R)
    48  	if sp.Equal(infinityPoint) == 1 {
    49  		return false, nil
    50  	}
    51  	r = PublicKeyFromPoint(sp)
    52  	return s.C.Equal(HashToScalar(handler(r))) == 1, r
    53  }
    54  
    55  // CreateSignature produces a Schnorr Signature using H = keccak
    56  func CreateSignature(handler SignatureSigningHandler, privateKey PrivateKey) *Signature {
    57  	k := PrivateKeyFromScalar(RandomScalar())
    58  
    59  	signature := &Signature{
    60  		// e
    61  		C: HashToScalar(handler(k)),
    62  		R: &edwards25519.Scalar{},
    63  	}
    64  
    65  	// s = k - x * e
    66  	// EdDSA is an altered version, with addition instead of subtraction
    67  	signature.R = signature.R.Subtract(k.Scalar(), GetEdwards25519Scalar().Multiply(signature.C, privateKey.AsScalar().Scalar()))
    68  	return signature
    69  }
    70  
    71  func CreateMessageSignature(prefixHash types.Hash, key PrivateKey) *Signature {
    72  	buf := &SignatureComm{}
    73  	buf.Hash = prefixHash
    74  	buf.Key = key.PublicKey()
    75  
    76  	return CreateSignature(func(k PrivateKey) []byte {
    77  		buf.Comm = k.PublicKey()
    78  		return buf.Bytes()
    79  	}, key)
    80  }
    81  
    82  func VerifyMessageSignature(prefixHash types.Hash, publicKey PublicKey, signature *Signature) bool {
    83  	return VerifyMessageSignatureSplit(prefixHash, publicKey, publicKey, signature)
    84  }
    85  
    86  // VerifyMessageSignatureSplit Allows specifying a different signer key than for the rest. Use VerifyMessageSignature in all other cases
    87  func VerifyMessageSignatureSplit(prefixHash types.Hash, commPublicKey, signPublicKey PublicKey, signature *Signature) bool {
    88  	buf := &SignatureComm{}
    89  	buf.Hash = prefixHash
    90  	buf.Key = commPublicKey
    91  
    92  	ok, _ := signature.Verify(func(r PublicKey) []byte {
    93  		buf.Comm = r
    94  		return buf.Bytes()
    95  	}, signPublicKey)
    96  	return ok
    97  }