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