| // Copyright 2018 Google LLC |
| // |
| // Use of this source code is governed by an MIT-style |
| // license that can be found in the LICENSE file or at |
| // https://opensource.org/licenses/MIT. |
| |
| //! The Ed25519 signature algorithm. |
| |
| use boringssl::{ed25519_keypair, ed25519_keypair_from_seed, ed25519_sign, ed25519_verify}; |
| use public::{PrivateKey, PublicKey, Signature}; |
| use util::Sealed; |
| use Error; |
| |
| const ED25519_PUBLIC_KEY_LEN: usize = ::boringssl::ED25519_PUBLIC_KEY_LEN as usize; |
| const ED25519_PRIVATE_KEY_LEN: usize = ::boringssl::ED25519_PRIVATE_KEY_LEN as usize; |
| const ED25519_SIGNATURE_LEN: usize = ::boringssl::ED25519_SIGNATURE_LEN as usize; |
| // BoringSSL stores both a private and a public key in their private key |
| // representation. The private key comes first, followed by the public key. |
| const ED25519_PUBLIC_KEY_OFFSET: usize = ED25519_PRIVATE_KEY_LEN - ED25519_PUBLIC_KEY_LEN; |
| |
| /// An Ed25519 public key. |
| pub struct Ed25519PubKey { |
| key: [u8; ED25519_PUBLIC_KEY_LEN], |
| } |
| |
| impl Ed25519PubKey { |
| /// Constructs a new public key from bytes. |
| #[must_use] |
| pub fn from_bytes(bytes: [u8; ED25519_PUBLIC_KEY_LEN]) -> Ed25519PubKey { |
| Ed25519PubKey { key: bytes } |
| } |
| |
| /// Gets the raw bytes of the public key. |
| #[must_use] |
| pub fn bytes(&self) -> &[u8; ED25519_PUBLIC_KEY_LEN] { |
| &self.key |
| } |
| } |
| |
| impl_debug!(Ed25519PubKey, "Ed25519PubKey"); |
| |
| impl Sealed for Ed25519PubKey {} |
| impl PublicKey for Ed25519PubKey { |
| type Private = Ed25519PrivKey; |
| } |
| |
| /// An Ed25519 private key. |
| /// |
| /// An `Ed25519PrivKey` actually includes both the private key and the public |
| /// key in order to make multiple key signing operations with the same key more |
| /// efficient. |
| pub struct Ed25519PrivKey { |
| key: [u8; ED25519_PRIVATE_KEY_LEN], |
| } |
| |
| impl_debug!(Ed25519PrivKey, "Ed25519PrivKey"); |
| |
| impl Ed25519PrivKey { |
| /// Generates a new private key. |
| #[must_use] |
| pub fn generate() -> Ed25519PrivKey { |
| Ed25519PrivKey { |
| key: ed25519_keypair(), |
| } |
| } |
| |
| /// Constructs a new private key from a key pair. |
| /// |
| /// Usually, an Ed25519 private key will be stored as a single 64-byte blob: |
| /// the 32-byte private key followed by the 32-byte public key. However, we |
| /// accept the two keys as separate arguments in case they are stored |
| /// separately. |
| #[must_use] |
| pub fn from_key_pair_bytes(private: [u8; 32], public: &Ed25519PubKey) -> Ed25519PrivKey { |
| let mut key = [0u8; ED25519_PRIVATE_KEY_LEN]; |
| (&mut key[..32]).copy_from_slice(&private); |
| (&mut key[ED25519_PUBLIC_KEY_OFFSET..]).copy_from_slice(&public.key); |
| Ed25519PrivKey { key } |
| } |
| |
| /// Constructs a new private key. |
| /// |
| /// Unlike [`from_key_pair_bytes`], `from_private_key_bytes` reconstructs |
| /// the key (which includes both the private key and the public key |
| /// internally) from only the private key. |
| /// |
| /// [`from_key_pair_bytes`]: ::public::ed25519::Ed25519PrivKey::from_key_pair_bytes |
| #[must_use] |
| pub fn from_private_key_bytes(private: [u8; 32]) -> Ed25519PrivKey { |
| let (_, key) = ed25519_keypair_from_seed(&private); |
| Ed25519PrivKey { key } |
| } |
| |
| /// Gets the raw bytes of the private key. |
| #[must_use] |
| pub fn bytes(&self) -> &[u8; ED25519_PRIVATE_KEY_LEN] { |
| &self.key |
| } |
| } |
| |
| impl Sealed for Ed25519PrivKey {} |
| impl PrivateKey for Ed25519PrivKey { |
| type Public = Ed25519PubKey; |
| |
| fn public(&self) -> Ed25519PubKey { |
| let mut public = [0u8; ED25519_PUBLIC_KEY_LEN]; |
| (&mut public[..]).copy_from_slice(&self.key[ED25519_PUBLIC_KEY_OFFSET..]); |
| Ed25519PubKey { key: public } |
| } |
| } |
| |
| /// An Ed25519 signature. |
| #[must_use] |
| pub struct Ed25519Signature { |
| sig: [u8; ED25519_SIGNATURE_LEN], |
| } |
| |
| impl_debug!(Ed25519Signature, "Ed25519Signature"); |
| |
| impl Ed25519Signature { |
| /// Constructs an `Ed25519Signature` signature from raw bytes. |
| #[must_use] |
| pub fn from_bytes(bytes: [u8; ED25519_SIGNATURE_LEN]) -> Ed25519Signature { |
| Ed25519Signature { sig: bytes } |
| } |
| |
| /// Gets the raw bytes of the signature. |
| #[must_use] |
| pub fn bytes(&self) -> &[u8; ED25519_SIGNATURE_LEN] { |
| &self.sig |
| } |
| |
| /// Sign a message. |
| /// |
| /// `Ed25519Signature` implements [`Signature`], but `Signature`'s [`sign`] |
| /// function conservatively returns a `Result`. Ed25519 signatures never |
| /// fail, so this function is provided to allow the user to compute an |
| /// Ed25519 signature without having to perform error checking. |
| /// |
| /// [`Signature`]: ::public::Signature |
| /// [`sign`]: ::public::Signature::sign |
| #[must_use] |
| pub fn sign_ed25519(key: &Ed25519PrivKey, message: &[u8]) -> Ed25519Signature { |
| Ed25519Signature { |
| // ED25519_sign can only return an error on OOM |
| sig: ed25519_sign(message, &key.key).unwrap(), |
| } |
| } |
| } |
| |
| impl Sealed for Ed25519Signature {} |
| impl Signature for Ed25519Signature { |
| type PrivateKey = Ed25519PrivKey; |
| |
| /// Sign a message. |
| /// |
| /// Though the [`Signature`] trait requires that [`sign`] return a `Result`, |
| /// `Ed25519Signature`'s implementation is guaranteed to always return `Ok`. |
| /// Callers may prefer the [`sign_ed25519`] function, which returns an |
| /// `Ed25519Signature` rather than a `Result`. |
| /// |
| /// [`Signature`]: ::public::Signature |
| /// [`sign`]: ::public::Signature::sign |
| /// [`sign_ed25519`]: ::public::ed25519::Ed25519Signature::sign_ed25519 |
| fn sign(key: &Ed25519PrivKey, message: &[u8]) -> Result<Ed25519Signature, Error> { |
| Ok(Ed25519Signature::sign_ed25519(key, message)) |
| } |
| |
| fn verify(&self, key: &Ed25519PubKey, message: &[u8]) -> bool { |
| ed25519_verify(message, &self.sig, &key.key) |
| } |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| use public::testutil::test_signature_smoke; |
| |
| #[test] |
| fn test_priv_key_constructors() { |
| let key = Ed25519PrivKey::generate(); |
| let mut private = [0u8; 32]; |
| (&mut private[..]).copy_from_slice(&key.key[..32]); |
| let key2 = Ed25519PrivKey::from_private_key_bytes(private); |
| assert_eq!(&key.key[..], &key2.key[..]); |
| |
| let mut private = [0u8; 32]; |
| let mut public = [0u8; 32]; |
| let bytes = *key.bytes(); |
| (&mut private[..]).copy_from_slice(&bytes[..32]); |
| (&mut public[..]).copy_from_slice(&bytes[32..]); |
| let key2 = Ed25519PrivKey::from_key_pair_bytes(private, &Ed25519PubKey::from_bytes(public)); |
| assert_eq!(&key.key[..], &key2.key[..]); |
| } |
| |
| #[test] |
| fn test_smoke() { |
| let key = Ed25519PrivKey::generate(); |
| let from_bytes = |bytes: &[u8]| { |
| let mut sig = [0u8; ED25519_SIGNATURE_LEN]; |
| let len = ::std::cmp::min(sig.len(), bytes.len()); |
| (&mut sig[..len]).copy_from_slice(&bytes[..len]); |
| Ed25519Signature::from_bytes(sig) |
| }; |
| // for some reason, defining this as a closure results in type inference |
| // issues that aren't worth debugging |
| fn to_bytes(sig: &Ed25519Signature) -> &[u8] { |
| &sig.bytes()[..] |
| } |
| test_signature_smoke(&key, from_bytes, to_bytes); |
| } |
| } |