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 }