xpx_chain_crypto/
lib.rs

1// Copyright 2018 ProximaX Limited. All rights reserved.
2// Use of this source code is governed by the Apache 2.0
3// license that can be found in the LICENSE file.
4
5//! A Rust implementation of ed25519 key generation, signing, and verification.
6//!
7//! # Example
8//!
9//! Creating an ed25519 signature on a message is simple.
10//!
11//! First, we need to generate a `Keypair`, which includes both public and
12//! secret halves of an asymmetric key.  To do so, we need a cryptographically
13//! secure pseudorandom number generator (CSPRNG). For this example, we'll use
14//! the operating system's builtin PRNG:
15//!
16//! ```
17//! extern crate rand;
18//! extern crate xpx_chain_crypto;
19//!
20//! # #[cfg(feature = "std")]
21//! # fn main() {
22//! use rand::Rng;
23//! use rand::rngs::OsRng;
24//! use xpx_chain_crypto::Keypair;
25//! use xpx_chain_crypto::Signature;
26//!
27//! let mut csprng = OsRng{};
28//! let keypair: Keypair = Keypair::generate(&mut csprng);
29//! # }
30//! #
31//! # #[cfg(not(feature = "std"))]
32//! # fn main() { }
33//! ```
34//!
35//! We can now use this `keypair` to sign a message:
36//!
37//! ```
38//! # extern crate rand;
39//! # extern crate xpx_chain_crypto;
40//! # fn main() {
41//! # use rand::Rng;
42//! # use rand::thread_rng;
43//! # use xpx_chain_crypto::Keypair;
44//! # use xpx_chain_crypto::Signature;
45//! # let mut csprng = thread_rng();
46//! # let keypair: Keypair = Keypair::generate(&mut csprng);
47//! let message: &[u8] = b"ProximaX Limited.";
48//! let signature: Signature = keypair.sign(message);
49//! # }
50//! ```
51//!
52//! As well as to verify that this is, indeed, a valid signature on
53//! that `message`:
54//!
55//! ```
56//! # extern crate rand;
57//! # extern crate xpx_chain_crypto;
58//! # fn main() {
59//! # use rand::Rng;
60//! # use rand::thread_rng;
61//! # use xpx_chain_crypto::Keypair;
62//! # use xpx_chain_crypto::Signature;
63//! # let mut csprng = thread_rng();
64//! # let keypair: Keypair = Keypair::generate(&mut csprng);
65//! # let message: &[u8] = b"ProximaX Limited.";
66//! # let signature: Signature = keypair.sign(message);
67//! assert!(keypair.verify(message, &signature).is_ok());
68//! # }
69//! ```
70//!
71//! Anyone else, given the `public` half of the `keypair` can also easily
72//! verify this signature:
73//!
74//! ```
75//! # extern crate rand;
76//! # extern crate xpx_chain_crypto;
77//! # fn main() {
78//! # use rand::Rng;
79//! # use rand::thread_rng;
80//! # use xpx_chain_crypto::Keypair;
81//! # use xpx_chain_crypto::Signature;
82//! use xpx_chain_crypto::PublicKey;
83//! # let mut csprng = thread_rng();
84//! # let keypair: Keypair = Keypair::generate(&mut csprng);
85//! # let message: &[u8] = b"ProximaX Limited.";
86//! # let signature: Signature = keypair.sign(message);
87//!
88//! let public_key: PublicKey = keypair.public;
89//! assert!(public_key.verify(message, &signature).is_ok());
90//! # }
91//! ```
92//!
93//! ## Serialisation
94//!
95//! `PublicKey`s, `SecretKey`s, `Keypair`s, and `Signature`s can be serialised
96//! into byte-arrays by calling `.to_bytes()`.  It's perfectly acceptible and
97//! safe to transfer and/or store those bytes.  (Of course, never transfer your
98//! secret key to anyone else, since they will only need the public key to
99//! verify your signatures!)
100//!
101//! ```
102//! # extern crate rand;
103//! # extern crate xpx_chain_crypto;
104//! # fn main() {
105//! # use rand::Rng;
106//! # use rand::thread_rng;
107//! # use xpx_chain_crypto::{Keypair, Signature, PublicKey};
108//! use xpx_chain_crypto::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
109//! # let mut csprng = thread_rng();
110//! # let keypair: Keypair = Keypair::generate(&mut csprng);
111//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
112//! # let signature: Signature = keypair.sign(message);
113//! # let public_key: PublicKey = keypair.public;
114//!
115//! let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = public_key.to_bytes();
116//! let secret_key_bytes: [u8; SECRET_KEY_LENGTH] = keypair.secret.to_bytes();
117//! let keypair_bytes:    [u8; KEYPAIR_LENGTH]    = keypair.to_bytes();
118//! let signature_bytes:  [u8; SIGNATURE_LENGTH]  = signature.to_bytes();
119//! # }
120//! ```
121//!
122//! And similarly, decoded from bytes with `::from_bytes()`:
123//!
124//! ```
125//! # extern crate rand;
126//! # extern crate xpx_chain_crypto;
127//! # use rand::Rng;
128//! # use rand::thread_rng;
129//! # use xpx_chain_crypto::{Keypair, Signature, PublicKey, SecretKey, SignatureError};
130//! # use xpx_chain_crypto::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
131//! # fn do_test() -> Result<(SecretKey, PublicKey, Keypair, Signature), SignatureError> {
132//! # let mut csprng = thread_rng();
133//! # let keypair_orig: Keypair = Keypair::generate(&mut csprng);
134//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
135//! # let signature_orig: Signature = keypair_orig.sign(message);
136//! # let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = keypair_orig.public.to_bytes();
137//! # let secret_key_bytes: [u8; SECRET_KEY_LENGTH] = keypair_orig.secret.to_bytes();
138//! # let keypair_bytes:    [u8; KEYPAIR_LENGTH]    = keypair_orig.to_bytes();
139//! # let signature_bytes:  [u8; SIGNATURE_LENGTH]  = signature_orig.to_bytes();
140//! #
141//! let public_key: PublicKey = PublicKey::from_bytes(&public_key_bytes)?;
142//! let secret_key: SecretKey = SecretKey::from_bytes(&secret_key_bytes)?;
143//! let keypair:    Keypair   = Keypair::from_bytes(&keypair_bytes)?;
144//! let signature:  Signature = Signature::from_bytes(&signature_bytes)?;
145//! #
146//! # Ok((secret_key, public_key, keypair, signature))
147//! # }
148//! # fn main() {
149//! #     do_test();
150//! # }
151//! ```
152//!
153//! ### Using Serde
154//!
155//! If you prefer the bytes to be wrapped in another serialisation format, all
156//! types additionally come with built-in [serde](https://serde.rs) support by
157//! building `rust-xpx-crypto` via:
158//!
159//! ```bash
160//! $ cargo build --features="serde"
161//! ```
162//!
163//! They can be then serialised into any of the wire formats which serde supports.
164//! For example, using [bincode](https://github.com/TyOverby/bincode):
165//!
166//! ```
167//! # extern crate rand;
168//! # extern crate xpx_chain_crypto;
169//! # #[cfg(feature = "serde")]
170//! extern crate serde;
171//! # #[cfg(feature = "serde")]
172//! extern crate bincode;
173//!
174//! # #[cfg(feature = "serde")]
175//! # fn main() {
176//! # use rand::Rng;
177//! # use rand::thread_rng;
178//! # use xpx_chain_crypto::{Keypair, Signature, PublicKey};
179//! use bincode::{serialize, Infinite};
180//! # let mut csprng = thread_rng();
181//! # let keypair: Keypair = Keypair::generate(&mut csprng);
182//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
183//! # let signature: Signature = keypair.sign(message);
184//! # let public_key: PublicKey = keypair.public;
185//! # let verified: bool = public_key.verify(message, &signature).is_ok();
186//!
187//! let encoded_public_key: Vec<u8> = serialize(&public_key, Infinite).unwrap();
188//! let encoded_signature: Vec<u8> = serialize(&signature, Infinite).unwrap();
189//! # }
190//! # #[cfg(not(feature = "serde"))]
191//! # fn main() {}
192//! ```
193//!
194//! After sending the `encoded_public_key` and `encoded_signature`, the
195//! recipient may deserialise them and verify:
196//!
197//! ```
198//! # extern crate rand;
199//! # extern crate xpx_chain_crypto;
200//! # #[cfg(feature = "serde")]
201//! # extern crate serde;
202//! # #[cfg(feature = "serde")]
203//! # extern crate bincode;
204//! #
205//! # #[cfg(feature = "serde")]
206//! # fn main() {
207//! # use rand::Rng;
208//! # use rand::thread_rng;
209//! # use xpx_chain_crypto::{Keypair, Signature, PublicKey};
210//! # use bincode::{serialize, Infinite};
211//! use bincode::{deserialize};
212//!
213//! # let mut csprng = thread_rng();
214//! # let keypair: Keypair = Keypair::generate(&mut csprng);
215//! let message: &[u8] = b"This is a test of the tsunami alert system.";
216//! # let signature: Signature = keypair.sign(message);
217//! # let public_key: PublicKey = keypair.public;
218//! # let verified: bool = public_key.verify(message, &signature).is_ok();
219//! # let encoded_public_key: Vec<u8> = serialize(&public_key, Infinite).unwrap();
220//! # let encoded_signature: Vec<u8> = serialize(&signature, Infinite).unwrap();
221//! let decoded_public_key: PublicKey = deserialize(&encoded_public_key).unwrap();
222//! let decoded_signature: Signature = deserialize(&encoded_signature).unwrap();
223//!
224//! # assert_eq!(public_key, decoded_public_key);
225//! # assert_eq!(signature, decoded_signature);
226//! #
227//! let verified: bool = decoded_public_key.verify(&message, &decoded_signature).is_ok();
228//!
229//! assert!(verified);
230//! # }
231//! # #[cfg(not(feature = "serde"))]
232//! # fn main() {}
233//! ```
234
235#![no_std]
236#![warn(future_incompatible)]
237#![warn(rust_2018_compatibility)]
238// #![deny(missing_docs)] // refuse to compile if documentation is missing
239
240#[cfg(any(feature = "std", test))]
241#[macro_use]
242extern crate std;
243
244extern crate aes;
245extern crate block_modes;
246extern crate clear_on_drop;
247extern crate curve25519_dalek;
248extern crate failure;
249extern crate rand;
250#[cfg(feature = "serde")]
251extern crate serde;
252extern crate sha3;
253
254mod block_cipher;
255mod constants;
256mod ed25519;
257mod errors;
258mod public;
259mod secret;
260mod signature;
261
262// Export everything public in ed25519.
263pub use crate::ed25519::*;