I'm trying to implement a guessing game with the user signs the guess and sends it to the user first so that the user can't change their mind once the other user shows their guess. So I decided to use a ECDSA type signature scheme to sign the guess, which could then be verified by anyone in possession of the public key and message.
Both players are initialized with a guessList
package main
import (
"fmt"
"math/big"
"crypto/elliptic"
"crypto/ecdsa"
"crypto/rand"
)
type Signature struct {
R, S *big.Int
}
func (sig Signature) Signature() []byte {
signature := sig.R.Bytes()
return append(signature, sig.R.Bytes()...)
}
func NewKeyPair() *ecdsa.PrivateKey {
curve := elliptic.P256()
private, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
panic(err)
}
return private
}
func SignMessage(privateK *ecdsa.PrivateKey, message []byte) (*Signature, error) {
r, s, e := ecdsa.Sign(rand.Reader, privateK, message[:])
return &Signature{r, s}, e
}
func VerifyMessage(pub *ecdsa.PublicKey, hash []byte, sig *Signature) bool {
return ecdsa.Verify(pub, hash, sig.R, sig.S)
}
func main() {
guessList := []string{"Mars", "Jupiter"}
alice := player.New(guessList)
bob := player.New(guessList)
aliceSig := alice.SignedGuess()
aliceGuess := alice.Guess()
alicePubKey := alice.GetPublicKey()
bobSig := bob.SignedGuess()
bobGuess := bob.Guess()
bobPubKey := bob.GetPublicKey()
// verify alice guess
fmt.Println("Alice", alicePubKey, aliceGuess, aliceSig)
if VerifyMessage(alicePubKey, aliceGuess, aliceSig) {
fmt.Println("ALICE SUCCESS!")
} else {
fmt.Println("ALICE FAILED!")
}
// verify bobs guess
fmt.Println("Bob", bobPubKey, bobGuess, bobSig)
if VerifyMessage(bobPubKey, bobGuess, bobSig) {
fmt.Println("BOB SUCCESS!")
} else {
fmt.Println("BOB FAILED!")
}
}
The output I get from the program is this
Alice &{{0xc000020140}
26541568154822848983620128269856234041217234096048716391831199412184305810014
46017364145923341784005989279989107750425172024567802836365554482938755917819}
[75 105 110 103]
&{45428775092069671177294278394620607723009196108687109167047693925148373855304
21398323948827903161400251641544489668567906805954246758420846993478153627340}
ALICE SUCCESS!
Bob &{{0xc000020140}
54261756095293936047079955957168587853577177849754426936860409293345237796196
50444495206085077811181575107480292702435765653886051687921522668605526305849}
[75 105 110 103]
&{99482635395166070373862991446297505261390994952487975582277256967392658727119
37668499365517297659868450187384121785982944941801349500949385160175327365263}
BOB FAILED!
As you can see from the output, bob verification failed and I have no clue why.
UPDATE
The Private key Is generated like this
func NewKeyPair() *ecdsa.PrivateKey {
curve := elliptic.P256()
private, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
panic(err)
}
return private
}
Player struct is implemented like this, calling the NewKeyPair once on New
type Player struct {
guessList []string
privateKey *ecdsa.PrivateKey
publicKey *ecdsa.PublicKey
}
func New(guessList []string) *Player {
privateK := cryptoHelper.NewKeyPair()
pubK := privateK.PublicKey
return &Player{guessList: guessList, privateKey: privateK, publicKey: &pubK}
}
func (p *Player) SignedGuess() *cryptoHelper.Signature {
guess := p.guess()
sig, err := cryptoHelper.SignMessage(p.privateKey, guess)
if err != nil {
panic(err)
}
return sig
}
func (p *Player) Guess() []byte {
return p.guess()
}
func (p *Player) GetPublicKey() *ecdsa.PublicKey {
return p.publicKey
}
func (p *Player) guess() []byte {
n := len(p.guessList)
index, err := rand.Int(rand.Reader, big.NewInt(int64(n)))
if err != nil {
panic(err)
}
return []byte(p.guessList[index.Int64()])
}