Skip to content

Instantly share code, notes, and snippets.

@mrmoneyc
Created June 3, 2015 05:53
Show Gist options
  • Save mrmoneyc/f82c90e2e4d9505754cc to your computer and use it in GitHub Desktop.
Save mrmoneyc/f82c90e2e4d9505754cc to your computer and use it in GitHub Desktop.
// Schnorr Signature
// Ref. Textbook: Nigel Smart - Cryptography An Introduction 3e, pp. 228-229
package main
import (
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"math/big"
)
func main() {
// Prime Number
p, _ := new(big.Int).SetString("113256005124119095887362785281379157446404829882999979448622682261851008142579707394232374642751898128900799220373652000701783958989737948170371610619031868024000569000834673195257818439729317108630237021891041144289230787346772418776549397214093418292376184510379483807693634331424008004223721261786568283629", 0)
q, _ := new(big.Int).SetString("58508050319346346411247266832333505875101282222691606960622102756222717350237", 0)
// Generator
g, _ := new(big.Int).SetString("61995837307178551264627902471930418226063720987162275719035943735379849036295356612596402538370130606871549084613181542200476416422180948344921683453084001924786075195620479781873421932856722132237494145265573577037713306883903369443425145319999630695887996282517079193878060590362971381335924171579781687137", 0)
x, _ := rand.Prime(rand.Reader, 255) // Secret Key 0 < x < q
y := new(big.Int).Exp(g, x, p) // Public key y = g^x mod p
k, _ := rand.Prime(rand.Reader, 255) // Ephemeral key 0 < k < q
m := big.NewInt(7) // Message
fmt.Println("Secret Key: ", x)
fmt.Println("Public Key: ", y)
// Sign, signature is (e, s) for message m
r := new(big.Int).Exp(g, k, p) // r = g^k mod p
hashParam := m.String() + r.String() // m||r
hash := sha256.New()
hash.Write([]byte(hashParam))
md := hash.Sum(nil)
fHash := hex.EncodeToString(md)
valfHash, _ := new(big.Int).SetString(fHash, 16)
e := new(big.Int).Mod(valfHash, q) // e = h(m||r) mod q
s := new(big.Int).Mod(new(big.Int).Add(k, new(big.Int).Mul(x, e)), q) // s = k + x * e mod q
fmt.Println("fHash: ", fHash)
fmt.Println("valfHash: ", valfHash.String())
fmt.Println("r: ", r)
fmt.Println("e: ", e)
fmt.Println("s: ", s)
// Verification
yPowe := new(big.Int).Exp(y, e, p) // yPowe = y^e mod p
eInv := new(big.Int).ModInverse(yPowe, p) // eInv = yPowe^-1 mod p
rV := new(big.Int).Mod(new(big.Int).Mul(new(big.Int).Exp(g, s, p), eInv), p) // r = g^s * y^-e mod p
fmt.Println("rV: ", rV)
hashParamV := m.String() + rV.String() // m||rV
hashV := sha256.New()
hashV.Write([]byte(hashParamV))
mdV := hashV.Sum(nil)
fHashV := hex.EncodeToString(mdV)
valfHashV, _ := new(big.Int).SetString(fHashV, 16)
eV := new(big.Int).Mod(valfHashV, q) // eV = h(m||rV) mod q
fmt.Println("fHashV: ", fHashV)
fmt.Println("eV: ", eV)
// Result
var cmpResult string
switch eV.Cmp(e) {
case -1:
cmpResult = "eV < e"
case 0:
cmpResult = "eV = e"
case 1:
cmpResult = "eV > e"
}
fmt.Println("Verification result: ", cmpResult)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment