consensus/monero/crypto/signature.go
DataHoarder e2885687b2
All checks were successful
continuous-integration/drone/push Build is passing
Implement Miner Options page, add webhook notifications
2024-02-25 14:12:33 +01:00

98 lines
3.1 KiB
Go

package crypto
import (
"git.gammaspectra.live/P2Pool/edwards25519"
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
)
// Signature Schnorr signature
type Signature struct {
// C hash of data in signature, also called e
C *edwards25519.Scalar
// R result of the signature, also called s
R *edwards25519.Scalar
}
// SignatureSigningHandler receives k, inserts it or a pubkey into its data, and produces a []byte buffer for Signing/Verifying
type SignatureSigningHandler func(r PrivateKey) []byte
// SignatureVerificationHandler receives r = pubkey(k), inserts it into its data, and produces a []byte buffer for Signing/Verifying
type SignatureVerificationHandler func(r PublicKey) []byte
func NewSignatureFromBytes(buf []byte) *Signature {
if len(buf) != types.HashSize*2 {
return nil
}
signature := &Signature{}
var err error
if signature.C, err = GetEdwards25519Scalar().SetCanonicalBytes(buf[:32]); err != nil {
return nil
} else if signature.R, err = GetEdwards25519Scalar().SetCanonicalBytes(buf[32:]); err != nil {
return nil
} else {
return signature
}
}
func (s *Signature) Bytes() []byte {
buf := make([]byte, 0, types.HashSize*2)
buf = append(buf, s.C.Bytes()...)
buf = append(buf, s.R.Bytes()...)
return buf
}
// Verify checks a Schnorr Signature using H = keccak
func (s *Signature) Verify(handler SignatureVerificationHandler, publicKey PublicKey) (ok bool, r *PublicKeyPoint) {
//s = C * k, R * G
sp := GetEdwards25519Point().VarTimeDoubleScalarBaseMult(s.C, publicKey.AsPoint().Point(), s.R)
if sp.Equal(infinityPoint) == 1 {
return false, nil
}
r = PublicKeyFromPoint(sp)
return s.C.Equal(HashToScalar(handler(r))) == 1, r
}
// CreateSignature produces a Schnorr Signature using H = keccak
func CreateSignature(handler SignatureSigningHandler, privateKey PrivateKey) *Signature {
k := PrivateKeyFromScalar(RandomScalar())
signature := &Signature{
// e
C: HashToScalar(handler(k)),
R: &edwards25519.Scalar{},
}
// s = k - x * e
// EdDSA is an altered version, with addition instead of subtraction
signature.R = signature.R.Subtract(k.Scalar(), GetEdwards25519Scalar().Multiply(signature.C, privateKey.AsScalar().Scalar()))
return signature
}
func CreateMessageSignature(prefixHash types.Hash, key PrivateKey) *Signature {
buf := &SignatureComm{}
buf.Hash = prefixHash
buf.Key = key.PublicKey()
return CreateSignature(func(k PrivateKey) []byte {
buf.Comm = k.PublicKey()
return buf.Bytes()
}, key)
}
func VerifyMessageSignature(prefixHash types.Hash, publicKey PublicKey, signature *Signature) bool {
return VerifyMessageSignatureSplit(prefixHash, publicKey, publicKey, signature)
}
// VerifyMessageSignatureSplit Allows specifying a different signer key than for the rest. Use VerifyMessageSignature in all other cases
func VerifyMessageSignatureSplit(prefixHash types.Hash, commPublicKey, signPublicKey PublicKey, signature *Signature) bool {
buf := &SignatureComm{}
buf.Hash = prefixHash
buf.Key = commPublicKey
ok, _ := signature.Verify(func(r PublicKey) []byte {
buf.Comm = r
return buf.Bytes()
}, signPublicKey)
return ok
}