Claus P. Schnorr and Daniel J. Bernstein

Schnorr and Bernstein joins Rivest, Johnson and Kravitz: EdDSA Joins The Digital Signature Hall of Fame


Meet the Schnorr signature

EdDSA and Ed25519

package main
import (
func Base64Encode(message []byte) []byte {
b := make([]byte, base64.StdEncoding.EncodedLen(len(message)))
base64.StdEncoding.Encode(b, message)
return b
func main() {
msg := "Hello 123"
argCount := len(os.Args[1:])
if argCount > 0 {
msg = os.Args[1]
publ, priv, _ := ed25519.GenerateKey((nil))
m := []byte(msg)
sig := ed25519.Sign(priv, m)
fmt.Printf("=== Message ===\n")
fmt.Printf("Msg: %s\nHash: %x\n", msg, m)
fmt.Printf("\n=== Public key ===\n")
fmt.Printf("Public key: %x\n", publ)
fmt.Printf(" Public key (Base64): %s\n", Base64Encode(publ))
fmt.Printf("\n=== Private key ===\n")
fmt.Printf("Private key: %x\n", priv[0:32])
fmt.Printf(" Private key (Base64): %s\n", Base64Encode(priv[0:32]))
fmt.Printf(" Private key (Base64) Full key: %s\n", Base64Encode(priv))
fmt.Printf(" Private key (Full key): %x\n", priv)
fmt.Printf("\n=== Signature (R,s) ===\n")
fmt.Printf("Signature: R=%x s=%x\n", sig[0:32], sig[32:64])
fmt.Printf(" Signature (Base64)=%s\n\n", Base64Encode(sig))
rtn := ed25519.Verify(publ, m, sig)
if rtn {
fmt.Printf("Signature verifies")
} else {
fmt.Printf("Signature does not verify")
=== Message ===
Msg: Hello
Hash: 48656c6c6f
=== Public key ===
Public key: c3903a26c73a433554325859c963056acd2d503fc36313ae21647f911e723fab
Public key (Base64): w5A6Jsc6QzVUMlhZyWMFas0tUD/DYxOuIWR/kR5yP6s=
=== Private key ===
Private key: fc225cb6dd8969541e57754b4120b51e6a92673107c7c8e1dc25a7a3e6b1066b
Private key (Base64): /CJctt2JaVQeV3VLQSC1HmqSZzEHx8jh3CWno+axBms=
Private key (Base64) Full key: /CJctt2JaVQeV3VLQSC1HmqSZzEHx8jh3CWno+axBmvDkDomxzpDNVQyWFnJYwVqzS1QP8NjE64hZH+RHnI/qw==
Private key (Full key): fc225cb6dd8969541e57754b4120b51e6a92673107c7c8e1dc25a7a3e6b1066bc3903a26c73a433554325859c963056acd2d503fc36313ae21647f911e723fab
=== Signature (R,s) ===
Signature: R=fbee75ddd533296a9ebacbe653a3335d1b9a99d6e6c7941d4651e04a6268ad2e s=086b3da235c4f4e426d1a2e76a731c0a81844d98fe59f412abd869fb3008d00d
Signature (Base64)=++513dUzKWqeusvmU6MzXRuamdbmx5QdRlHgSmJorS4Iaz2iNcT05CbRoudqcxwKgYRNmP5Z9BKr2Gn7MAjQDQ==
Signature verifies


package mainimport (
"strings" ""
)func getCurve(s string) elliptic.Curve {
if strings.Contains(s, "224") {
return (elliptic.P224())
} else if strings.Contains(s, "384") {
return (elliptic.P384())
} else if strings.Contains(s, "521") {
return (elliptic.P521())
return (ecc.P256k1())
}func main() { msg := "Hello 123"
curveType := "" argCount := len(os.Args[1:])
if argCount > 0 {
msg = os.Args[1]
if argCount > 1 {
curveType = os.Args[2]
} pubkeyCurve := getCurve(curveType)
m := []byte(msg)
digest := sha256.Sum256(m) privatekey, _ := ecdsa.GenerateKey(pubkeyCurve, rand.Reader) pubkey := privatekey.PublicKey r, s, _ := ecdsa.Sign(rand.Reader, privatekey, digest[:]) fmt.Printf("=== Message ===\n")
fmt.Printf("Msg=%s\nHash=%x\n", msg, digest)
fmt.Printf("\n=== Private key ===\n")
fmt.Printf("Private key=%x\n", privatekey.D)
fmt.Printf("Curve=%s\n", privatekey.Curve.Params().Name)
fmt.Printf("Bit size=%d\n", privatekey.Curve.Params().BitSize)
fmt.Printf("Base point (G) =(%d, %d)\n", privatekey.Curve.Params().Gx, privatekey.Curve.Params().Gy)
fmt.Printf("Prime=%d, Order=%d", privatekey.Curve.Params().P, privatekey.Curve.Params().N)
fmt.Printf("\n=== Public key (X,Y) ===\n")
fmt.Printf("X=%s Y=%s\n", pubkey.X, pubkey.Y)
fmt.Printf(" Hex: X=%x Y=%x\n", pubkey.X.Bytes(), pubkey.Y.Bytes())
fmt.Printf("\n=== Signature (R,S) ===\n")
fmt.Printf("R=%s S=%s\n", r, s)
fmt.Printf(" Hex: R=%x S=%x\n", r, s) rtn := ecdsa.Verify(&pubkey, digest[:], r, s) if rtn {
fmt.Printf(\n"Signature verifies")
} else {
fmt.Printf("\nSignature does not verify")
=== Message ===
Msg=Hello 123
Hash=859e38d581e214dc7c8c871c425642913363a829065cf4acddd120ed5391b04b=== Private key ===
Private key=b3645f2efea9a96d28cbeb5bf8a5304a3dc96b2a42bee21c0b3aaa88f595df2d
Bit size=256
Base point (G) =(55066263022277343669578718895168534326250603453777594175500187360389116729240, 32670510020758816978083085130507043184471273380659243275938904335757337482424)
Prime=115792089237316195423570985008687907853269984665640564039457584007908834671663, Order=115792089237316195423570985008687907852837564279074904382605163141518161494337
=== Public key (X,Y) ===
X=77007236596272499552697218405908714888874625059778411542685725622785792316534 Y=20745252821220973789342590850065442758134973002375340605949893038975196614597
Hex: X=aa408d244da8a2ea673213ef63536ea96486ce0412a5294c9cdf0959cc689476 Y=2ddd65a19ed17f361b0381a72713f740b63d4fdca059427c389239da39004fc5=== Signature (R,S) ===
R=33027995512220841690000083421269061534408622570666620793995266029032826750381 S=44867240085578618664628913670877492263668786345184239470907981535519639811276
Hex: R=49052ed8fcf1903f530bda10ea9b578b6bb77487ea6b22b5558fc68524e045ad S=6331f53ce5e1a64e4043712631aeeb3f5c0ed753140a0fd76a8c5367e69b34cc
Signature verifies

Key points on EdDSA and ECDSA

  1. Ed25519 was proposed in 2011 by Daniel J. Bernstein, Niels Duif, Tanja Lange, Peter Schwabe, and Bo-Yin Yang, while ECDSA was proposed around 2001 by Don Johnson, Alfred Menezes, and Scott Vanstone.
  2. ECDSA uses the secp256k1 curve, and EdDSA uses Curve 25519.
  3. Bitcoin and Ethereum uses ECDSA, while IOTA uses EdDSA.
  4. EdDSA uses the Schnorr signature method, and which is now out of patent. It supports the aggregation of keys in the signature, and also the aggregation of the signature for multiple parties.
  5. For improved security, ECDSA supports a 521-bit curve (P521), while EdDSA supports X448.
  6. ECDSA has a random nonce value created within the signature creation, whereas EdDSA does not. In ECDSA, we need to be careful in making sure that we do not reuse this nonce value, and that it is random.
  7. ECDSA signatures change each time based on the nonce used, whereas EdDSA signatures do not change for the same set of keys and the same message.
  8. ECDSA is often used to keep compatibility with Bitcoin and Ethereum.
  9. ECDSA public keys are (x,y) coordinates and thus have 512 bits (for secp256k1), while Ed25519 uses just the y co-ordinate value for the point, and thus has 256 bits.
  10. ECDSA and EdDSA typically have equivalent performance and security levels.

RSA Signatures


And …. and dark cloud




This publication brings together interesting articles related to cyber security.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Prof Bill Buchanan OBE

Professor of Cryptography. Serial innovator. Believer in fairness, justice & freedom. Based in Edinburgh. Old World Breaker. New World Creator. Building trust.