1 | |
---|
2 | |
---|
3 | ===================================================== |
---|
4 | Python Bindings to Ed25519 Digital Signature System |
---|
5 | ===================================================== |
---|
6 | |
---|
7 | This package provides python bindings to a C implementation of the Ed25519 |
---|
8 | public-key signature system ¹_. The C code is copied from the SUPERCOP |
---|
9 | benchmark suite ²_, using the portable "ref" implementation (not the |
---|
10 | high-performance assembly code), and is very similar to the copy in the NaCl |
---|
11 | library ³_. |
---|
12 | |
---|
13 | With this library, you can quickly (2ms) create signing+verifying keypairs, |
---|
14 | derive a verifying key from a signing key, sign messages, and verify the |
---|
15 | signatures. The keys and signatures are very short, making them easy to |
---|
16 | handle and incorporate into other protocols. All known attacks take at least |
---|
17 | 2¹²⁸ operations, providing a security level comparable to AES-128, NIST |
---|
18 | P-256, and RSA-3248. |
---|
19 | |
---|
20 | |
---|
21 | Speed and Key Sizes |
---|
22 | ------------------- |
---|
23 | |
---|
24 | Signing keys are just 32 bytes (256 bits) of random data, so generating a |
---|
25 | signing key is trivial: signingkey = os.urandom(32). Deriving a public |
---|
26 | verifying key takes more time, as do the actual signing and verifying |
---|
27 | operations. |
---|
28 | |
---|
29 | A 256-bit elliptic curve key is estimated to be as strong as a much larger |
---|
30 | RSA key. The "ECRYPT II" cryptographic experts group estimate the strength of |
---|
31 | a 256-bit elliptic curve key to similar to the strength of a 3248-bit RSA |
---|
32 | public key: http://keylength.com |
---|
33 | |
---|
34 | On Brian Warner's 2010-era Mac laptop (2.8GHz Core2Duo), deriving a verifying |
---|
35 | key takes 1.9ms, signing takes 1.9ms, and verification takes 6.3ms. The |
---|
36 | high-performance assembly code in SUPERCOP (amd64-51-30k and amd64-64-24k) is |
---|
37 | up to 100x faster than the portable reference version, and the python |
---|
38 | overhead appears to be minimal (1-2us), so future releases may run even |
---|
39 | faster. |
---|
40 | |
---|
41 | Ed25519 private signing keys are 32 bytes long (this is expanded internally |
---|
42 | to 64 bytes when necessary). The public verifying keys are also 32 bytes |
---|
43 | long. Signatures are 64 bytes long. All operations provide a 128-bit |
---|
44 | security level. |
---|
45 | |
---|
46 | |
---|
47 | Security |
---|
48 | -------- |
---|
49 | |
---|
50 | The Ed25519 algorithm and C implementation are carefully designed to prevent |
---|
51 | timing attacks. The Python wrapper might not preserve this property. Until it |
---|
52 | has been audited for this purpose, do not allow attackers to measure how long |
---|
53 | it takes you to generate a keypair or sign a message. Key generation depends |
---|
54 | upon a strong source of random numbers. Do not use it on a system where |
---|
55 | os.urandom() is weak. |
---|
56 | |
---|
57 | Unlike typical DSA/ECDSA algorithms, signing does *not* require a source of |
---|
58 | entropy. Ed25519 signatures are deterministic: using the same key to sign the |
---|
59 | same data any number of times will result in the same signature each time. |
---|
60 | |
---|
61 | |
---|
62 | Usage |
---|
63 | ----- |
---|
64 | |
---|
65 | The first step is to generate a signing key and store it. At the same time, |
---|
66 | you'll probably need to derive the verifying key and give it to someone else. |
---|
67 | Signing keys are 32-byte uniformly-random strings. The safest way to generate |
---|
68 | a key is with os.urandom(32):: |
---|
69 | |
---|
70 | import os |
---|
71 | from pycryptopp.publickey import ed25519 |
---|
72 | |
---|
73 | sk_bytes = os.urandom(32) |
---|
74 | signing_key = ed25519.SigningKey(sk_bytes) |
---|
75 | open("my-secret-key","wb").write(sk_bytes) |
---|
76 | |
---|
77 | vkey_hex = signing_key.get_verifying_key_bytes().encode('hex') |
---|
78 | print "the public key is", vkey_hex |
---|
79 | |
---|
80 | To reconstruct the same key from the stored form later, just pass it back |
---|
81 | into SigningKey:: |
---|
82 | |
---|
83 | sk_bytes = open("my-secret-key","rb").read() |
---|
84 | signing_key = ed25519.SigningKey(sk_bytes) |
---|
85 | |
---|
86 | |
---|
87 | Once you have the SigningKey instance, use its .sign() method to sign a |
---|
88 | message. The signature is 64 bytes:: |
---|
89 | |
---|
90 | sig = signing_key.sign("hello world") |
---|
91 | print "sig is:", sig.encode('hex') |
---|
92 | |
---|
93 | On the verifying side, the receiver first needs to construct a |
---|
94 | ed25519.VerifyingKey instance from the serialized form, then use its |
---|
95 | .verify() method on the signature and message:: |
---|
96 | |
---|
97 | vkey_hex = "1246b84985e1ab5f83f4ec2bdf271114666fd3d9e24d12981a3c861b9ed523c6" |
---|
98 | verifying_key = ed25519.VerifyingKey(vkey_hex.decode('hex')) |
---|
99 | try: |
---|
100 | verifying_key.verify(sig, "hello world") |
---|
101 | print "signature is good" |
---|
102 | except ed25519.BadSignatureError: |
---|
103 | print "signature is bad!" |
---|
104 | |
---|
105 | If you happen to have the SigningKey but not the corresponding VerifyingKey, |
---|
106 | you can derive it with .get_verifying_key_bytes(). This allows the sending |
---|
107 | side to hold just 32 bytes of data and derive everything else from that. |
---|
108 | Deriving a verifying key takes about 1.9ms:: |
---|
109 | |
---|
110 | sk_bytes = open("my-secret-key","rb").read() |
---|
111 | signing_key = ed25519.SigningKey(sk_bytes) |
---|
112 | verifying_key = ed25519.VerifyingKey(signing_key.get_verifying_key_bytes()) |
---|
113 | |
---|
114 | There is also a basic command-line keygen/sign/verify tool in bin/edsig . |
---|
115 | |
---|
116 | |
---|
117 | API Summary |
---|
118 | ----------- |
---|
119 | |
---|
120 | The complete API is summarized here:: |
---|
121 | |
---|
122 | sk_bytes = os.urandom(32) |
---|
123 | sk = SigningKey(sk_bytes) |
---|
124 | vk_bytes = sk.get_verifying_key_bytes() |
---|
125 | vk = VerifyingKey(vk_bytes) |
---|
126 | |
---|
127 | signature = sk.sign(message) |
---|
128 | vk.verify(signature, message) |
---|
129 | |
---|
130 | |
---|
131 | footnotes |
---|
132 | --------- |
---|
133 | |
---|
134 | .. _¹: http://ed25519.cr.yp.to/ |
---|
135 | .. _²: http://bench.cr.yp.to/supercop.html |
---|
136 | .. _³: http://nacl.cr.yp.to/ |
---|