ed25519_dalek/
lib.rs

1// -*- mode: rust; -*-
2//
3// This file is part of ed25519-dalek.
4// Copyright (c) 2017-2019 isis lovecruft
5// See LICENSE for licensing information.
6//
7// Authors:
8// - isis agora lovecruft <isis@patternsinthevoid.net>
9
10//! A Rust implementation of ed25519 key generation, signing, and verification.
11//!
12//! # Example
13//!
14//! Creating an ed25519 signature on a message is simple.
15//!
16//! First, we need to generate a `SigningKey`, which includes both public and
17//! secret halves of an asymmetric key.  To do so, we need a cryptographically
18//! secure pseudorandom number generator (CSPRNG). For this example, we'll use
19//! the operating system's builtin PRNG:
20//!
21#![cfg_attr(feature = "rand_core", doc = "```")]
22#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
23//! # fn main() {
24//! // $ cargo add ed25519_dalek --features rand_core
25//! use rand::rngs::OsRng;
26//! use ed25519_dalek::SigningKey;
27//! use ed25519_dalek::Signature;
28//!
29//! let mut csprng = OsRng;
30//! let signing_key: SigningKey = SigningKey::generate(&mut csprng);
31//! # }
32//! ```
33//!
34//! We can now use this `signing_key` to sign a message:
35//!
36#![cfg_attr(feature = "rand_core", doc = "```")]
37#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
38//! # fn main() {
39//! # use rand::rngs::OsRng;
40//! # use ed25519_dalek::SigningKey;
41//! # let mut csprng = OsRng;
42//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng);
43//! use ed25519_dalek::{Signature, Signer};
44//! let message: &[u8] = b"This is a test of the tsunami alert system.";
45//! let signature: Signature = signing_key.sign(message);
46//! # }
47//! ```
48//!
49//! As well as to verify that this is, indeed, a valid signature on
50//! that `message`:
51//!
52#![cfg_attr(feature = "rand_core", doc = "```")]
53#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
54//! # fn main() {
55//! # use rand::rngs::OsRng;
56//! # use ed25519_dalek::{SigningKey, Signature, Signer};
57//! # let mut csprng = OsRng;
58//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng);
59//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
60//! # let signature: Signature = signing_key.sign(message);
61//! use ed25519_dalek::Verifier;
62//! assert!(signing_key.verify(message, &signature).is_ok());
63//! # }
64//! ```
65//!
66//! Anyone else, given the `public` half of the `signing_key` can also easily
67//! verify this signature:
68//!
69#![cfg_attr(feature = "rand_core", doc = "```")]
70#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
71//! # fn main() {
72//! # use rand::rngs::OsRng;
73//! # use ed25519_dalek::SigningKey;
74//! # use ed25519_dalek::Signature;
75//! # use ed25519_dalek::Signer;
76//! use ed25519_dalek::{VerifyingKey, Verifier};
77//! # let mut csprng = OsRng;
78//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng);
79//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
80//! # let signature: Signature = signing_key.sign(message);
81//!
82//! let verifying_key: VerifyingKey = signing_key.verifying_key();
83//! assert!(verifying_key.verify(message, &signature).is_ok());
84//! # }
85//! ```
86//!
87//! ## Serialisation
88//!
89//! `VerifyingKey`s, `SecretKey`s, `SigningKey`s, and `Signature`s can be serialised
90//! into byte-arrays by calling `.to_bytes()`.  It's perfectly acceptable and
91//! safe to transfer and/or store those bytes.  (Of course, never transfer your
92//! secret key to anyone else, since they will only need the public key to
93//! verify your signatures!)
94//!
95#![cfg_attr(feature = "rand_core", doc = "```")]
96#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
97//! # fn main() {
98//! # use rand::rngs::OsRng;
99//! # use ed25519_dalek::{SigningKey, Signature, Signer, VerifyingKey};
100//! use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
101//! # let mut csprng = OsRng;
102//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng);
103//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
104//! # let signature: Signature = signing_key.sign(message);
105//!
106//! let verifying_key_bytes: [u8; PUBLIC_KEY_LENGTH] = signing_key.verifying_key().to_bytes();
107//! let secret_key_bytes: [u8; SECRET_KEY_LENGTH] = signing_key.to_bytes();
108//! let signing_key_bytes:    [u8; KEYPAIR_LENGTH]    = signing_key.to_keypair_bytes();
109//! let signature_bytes:  [u8; SIGNATURE_LENGTH]  = signature.to_bytes();
110//! # }
111//! ```
112//!
113//! And similarly, decoded from bytes with `::from_bytes()`:
114//!
115#![cfg_attr(feature = "rand_core", doc = "```")]
116#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
117//! # use core::convert::{TryFrom, TryInto};
118//! # use rand::rngs::OsRng;
119//! # use ed25519_dalek::{SigningKey, Signature, Signer, VerifyingKey, SecretKey, SignatureError};
120//! # use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
121//! # fn do_test() -> Result<(SigningKey, VerifyingKey, Signature), SignatureError> {
122//! # let mut csprng = OsRng;
123//! # let signing_key_orig: SigningKey = SigningKey::generate(&mut csprng);
124//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
125//! # let signature_orig: Signature = signing_key_orig.sign(message);
126//! # let verifying_key_bytes: [u8; PUBLIC_KEY_LENGTH] = signing_key_orig.verifying_key().to_bytes();
127//! # let signing_key_bytes: [u8; SECRET_KEY_LENGTH] = signing_key_orig.to_bytes();
128//! # let signature_bytes:  [u8; SIGNATURE_LENGTH]  = signature_orig.to_bytes();
129//! #
130//! let verifying_key: VerifyingKey = VerifyingKey::from_bytes(&verifying_key_bytes)?;
131//! let signing_key: SigningKey = SigningKey::from_bytes(&signing_key_bytes);
132//! let signature: Signature = Signature::try_from(&signature_bytes[..])?;
133//! #
134//! # Ok((signing_key, verifying_key, signature))
135//! # }
136//! # fn main() {
137//! #     do_test();
138//! # }
139//! ```
140//!
141//! ### PKCS#8 Key Encoding
142//!
143//! PKCS#8 is a private key format with support for multiple algorithms.
144//! It can be encoded as binary (DER) or text (PEM).
145//!
146//! You can recognize PEM-encoded PKCS#8 keys by the following:
147//!
148//! ```text
149//! -----BEGIN PRIVATE KEY-----
150//! ```
151//!
152//! To use PKCS#8, you need to enable the `pkcs8` crate feature.
153//!
154//! The following traits can be used to decode/encode [`SigningKey`] and
155//! [`VerifyingKey`] as PKCS#8. Note that [`pkcs8`] is re-exported from the
156//! toplevel of the crate:
157//!
158//! - [`pkcs8::DecodePrivateKey`]: decode private keys from PKCS#8
159//! - [`pkcs8::EncodePrivateKey`]: encode private keys to PKCS#8
160//! - [`pkcs8::DecodePublicKey`]: decode public keys from PKCS#8
161//! - [`pkcs8::EncodePublicKey`]: encode public keys to PKCS#8
162//!
163//! #### Example
164//!
165//! NOTE: this requires the `pem` crate feature.
166//!
167#![cfg_attr(feature = "pem", doc = "```")]
168#![cfg_attr(not(feature = "pem"), doc = "```ignore")]
169//! use ed25519_dalek::{VerifyingKey, pkcs8::DecodePublicKey};
170//!
171//! let pem = "-----BEGIN PUBLIC KEY-----
172//! MCowBQYDK2VwAyEAGb9ECWmEzf6FQbrBZ9w7lshQhqowtrbLDFw4rXAxZuE=
173//! -----END PUBLIC KEY-----";
174//!
175//! let verifying_key = VerifyingKey::from_public_key_pem(pem)
176//!     .expect("invalid public key PEM");
177//! ```
178//!
179//! ### Using Serde
180//!
181//! If you prefer the bytes to be wrapped in another serialisation format, all
182//! types additionally come with built-in [serde](https://serde.rs) support by
183//! building `ed25519-dalek` via:
184//!
185//! ```bash
186//! $ cargo build --features="serde"
187//! ```
188//!
189//! They can be then serialised into any of the wire formats which serde supports.
190//! For example, using [bincode](https://github.com/TyOverby/bincode):
191//!
192#![cfg_attr(all(feature = "rand_core", feature = "serde"), doc = "```")]
193#![cfg_attr(not(all(feature = "rand_core", feature = "serde")), doc = "```ignore")]
194//! # fn main() {
195//! # use rand::rngs::OsRng;
196//! # use ed25519_dalek::{SigningKey, Signature, Signer, Verifier, VerifyingKey};
197//! use bincode::serialize;
198//! # let mut csprng = OsRng;
199//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng);
200//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
201//! # let signature: Signature = signing_key.sign(message);
202//! # let verifying_key: VerifyingKey = signing_key.verifying_key();
203//! # let verified: bool = verifying_key.verify(message, &signature).is_ok();
204//!
205//! let encoded_verifying_key: Vec<u8> = serialize(&verifying_key).unwrap();
206//! let encoded_signature: Vec<u8> = serialize(&signature).unwrap();
207//! # }
208//! ```
209//!
210//! After sending the `encoded_verifying_key` and `encoded_signature`, the
211//! recipient may deserialise them and verify:
212//!
213#![cfg_attr(all(feature = "rand_core", feature = "serde"), doc = "```")]
214#![cfg_attr(not(all(feature = "rand_core", feature = "serde")), doc = "```ignore")]
215//! # fn main() {
216//! # use rand::rngs::OsRng;
217//! # use ed25519_dalek::{SigningKey, Signature, Signer, Verifier, VerifyingKey};
218//! # use bincode::serialize;
219//! use bincode::deserialize;
220//!
221//! # let mut csprng = OsRng;
222//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng);
223//! let message: &[u8] = b"This is a test of the tsunami alert system.";
224//! # let signature: Signature = signing_key.sign(message);
225//! # let verifying_key: VerifyingKey = signing_key.verifying_key();
226//! # let verified: bool = verifying_key.verify(message, &signature).is_ok();
227//! # let encoded_verifying_key: Vec<u8> = serialize(&verifying_key).unwrap();
228//! # let encoded_signature: Vec<u8> = serialize(&signature).unwrap();
229//! let decoded_verifying_key: VerifyingKey = deserialize(&encoded_verifying_key).unwrap();
230//! let decoded_signature: Signature = deserialize(&encoded_signature).unwrap();
231//!
232//! # assert_eq!(verifying_key, decoded_verifying_key);
233//! # assert_eq!(signature, decoded_signature);
234//! #
235//! let verified: bool = decoded_verifying_key.verify(&message, &decoded_signature).is_ok();
236//!
237//! assert!(verified);
238//! # }
239//! ```
240
241#![no_std]
242#![warn(future_incompatible, rust_2018_idioms)]
243#![deny(missing_docs)] // refuse to compile if documentation is missing
244#![deny(clippy::unwrap_used)] // don't allow unwrap
245#![cfg_attr(not(test), forbid(unsafe_code))]
246#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg, doc_cfg_hide))]
247#![cfg_attr(docsrs, doc(cfg_hide(docsrs)))]
248
249#[cfg(feature = "batch")]
250extern crate alloc;
251
252#[cfg(any(feature = "std", test))]
253#[macro_use]
254extern crate std;
255
256pub use ed25519;
257
258#[cfg(feature = "batch")]
259mod batch;
260mod constants;
261#[cfg(feature = "digest")]
262mod context;
263mod errors;
264mod signature;
265mod signing;
266mod verifying;
267
268#[cfg(feature = "hazmat")]
269pub mod hazmat;
270#[cfg(not(feature = "hazmat"))]
271mod hazmat;
272
273#[cfg(feature = "digest")]
274pub use curve25519_dalek::digest::Digest;
275#[cfg(feature = "digest")]
276pub use sha2::Sha512;
277
278#[cfg(feature = "batch")]
279pub use crate::batch::*;
280pub use crate::constants::*;
281#[cfg(feature = "digest")]
282pub use crate::context::Context;
283pub use crate::errors::*;
284pub use crate::signing::*;
285pub use crate::verifying::*;
286
287// Re-export the `Signer` and `Verifier` traits from the `signature` crate
288#[cfg(feature = "digest")]
289pub use ed25519::signature::{DigestSigner, DigestVerifier};
290pub use ed25519::signature::{Signer, Verifier};
291pub use ed25519::Signature;
292
293#[cfg(feature = "pkcs8")]
294pub use ed25519::pkcs8;