// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use core::fmt::Debug; // User-facing, crypto-provider independent structs /// The length of a ed25519 `Signature`, in bytes. pub const SIGNATURE_LENGTH: usize = 64; /// The length of an ed25519 `PrivateKey`, in bytes. pub const PRIVATE_KEY_LENGTH: usize = 32; /// The length of an ed25519 `PrivateKey`, in bytes. pub const PUBLIC_KEY_LENGTH: usize = 32; /// A byte buffer the size of a ed25519 `Signature`. pub type RawSignature = [u8; SIGNATURE_LENGTH]; /// A byte buffer the size of a ed25519 `PublicKey`. pub type RawPublicKey = [u8; PUBLIC_KEY_LENGTH]; /// A byte buffer the size of a ed25519 `PrivateKey`. pub type RawPrivateKey = [u8; PRIVATE_KEY_LENGTH]; /// A permission token which may be supplied to methods which allow /// converting private keys to/from raw bytes. /// /// In general, operations of this kind should only be done in /// development-tools, tests, or in credential storage layers /// to prevent accidental exposure of the private key. pub struct RawPrivateKeyPermit { _marker: (), } impl RawPrivateKeyPermit { pub(crate) fn new() -> Self { Self { _marker: () } } } #[cfg(feature = "raw_private_key_permit")] impl core::default::Default for RawPrivateKeyPermit { fn default() -> Self { Self::new() } } /// A crypto-provider-independent representation of the private /// key of an ed25519 key-pair, kept in such a way that /// it does not permit de-structuring it into raw bytes, /// nor constructing one from raw bytes. /// /// Useful for when you want a data-structure to be /// crypto-provider independent and contain a private key. #[derive(Clone)] pub struct PrivateKey(RawPrivateKey); impl PrivateKey { /// Derives the public key corresponding to this private key. pub fn derive_public_key(&self) -> PublicKey { let key_pair = E::KeyPair::from_private_key(self); key_pair.public_key().to_external() } /// Sign the given message and return a digital signature pub fn sign(&self, msg: &[u8]) -> Signature { let key_pair = E::KeyPair::from_private_key(self); key_pair.sign(msg).to_external() } /// Generate an ed25519 private key from a CSPRNG /// generate is not available in `no-std`. #[cfg(feature = "std")] pub fn generate() -> Self { let key_pair = E::KeyPair::generate(); key_pair.private_key() } /// Returns the raw bytes of this private key. /// This operation is only possible while holding a [`RawPrivateKeyPermit`]. pub fn raw_private_key(&self, _permit: &RawPrivateKeyPermit) -> RawPrivateKey { self.0 } /// Constructs a private key from the raw bytes of the key. /// This operation is only possible while holding a [`RawPrivateKeyPermit`]. pub fn from_raw_private_key(wrapped: RawPrivateKey, _permit: &RawPrivateKeyPermit) -> Self { PrivateKey(wrapped) } } /// error returned when bad bytes are provided to generate keypair #[derive(Debug)] pub struct InvalidPublicKeyBytes; /// Error returned if the verification on the signature + message fails #[derive(Debug)] pub struct SignatureError; /// A crypto-provider-independent representation of a valid /// public key for an ed25519 key-pair in the Edwards Y-format. /// /// Useful for when you want a data-structure to be crypto-provider /// independent and contain a public key. #[derive(Clone, Debug, PartialEq, Eq)] pub struct PublicKey(RawPublicKey); impl PublicKey { /// Attempts to parse a public key from an array of bytes. /// If the input is not in the Edwards Y-format, this method /// will yield an `InvalidPublicKeyBytes` error. pub fn from_bytes( wrapped: RawPublicKey, ) -> Result { // Simply verify that we can construct the crypto-provider-dependent variant. let _ = ::from_bytes(&wrapped)?; Ok(PublicKey(wrapped)) } /// Converts this public-key into the raw bytes of this public-key. pub fn into_bytes(self) -> RawPublicKey { self.0 } /// Converts this crypto-provider-independent public key to a crypto-provider's internal rep. #[allow(clippy::expect_used)] fn as_internal(&self) -> E::PublicKey { ::from_bytes(&self.0) .expect("Public key bytes validated upon construction.") } /// Succeeds if the signature on the given message is verified /// by this public key. pub fn verify_strict( &self, message: &[u8], signature: Signature, ) -> Result<(), SignatureError> { let public_key = self.as_internal::(); let signature = signature.as_internal::(); public_key.verify_strict(message, &signature) } } /// A crypto-provider-independent representation of an Ed25519 signature. /// The underlying representation here can be any arbitrary bytes - verifying /// code handles determining whether/not the signature actually corresponds /// to a real Ed25519 signature and matches the given public key. #[derive(Clone)] pub struct Signature(RawSignature); impl From for Signature { fn from(wrapped: RawSignature) -> Self { Signature(wrapped) } } impl Signature { /// Constructs a signature from raw bytes. pub fn new(wrapped: RawSignature) -> Self { Signature(wrapped) } /// Transforms this signature back into raw bytes. pub fn to_bytes(self) -> RawSignature { self.0 } /// Converts this crypto-provider-independent signature to a crypto-provider's internal rep. fn as_internal(&self) -> E::Signature { ::from_bytes(&self.0) } } // Implementor-facing crypto-provider-internal traits. /// Collection of types used to provide an implementation of ed25519, the Edwards-curve Digital /// Signature Algorithm scheme using sha-512 (sha2) and Curve25519 pub trait Ed25519Provider { /// The internal representation of a keypair which includes both public and secret halves of an asymmetric key. type KeyPair: KeyPairImpl; /// The internal representation of an ed25519 public key, used when verifying a message type PublicKey: PublicKeyImpl; /// The internal representation of an ed25519 signature which is the result of signing a message type Signature: SignatureImpl; } /// The keypair which includes both public and secret halves of an asymmetric key. pub trait KeyPairImpl: Sized { /// The ed25519 public key, used when verifying a message type PublicKey: PublicKeyImpl; /// The ed25519 signature returned when signing a message type Signature: SignatureImpl; /// Returns the private key bytes of the `KeyPair`. /// This operation is only possible while holding a [`RawPrivateKeyPermit`]. fn raw_private_key(&self, _permit: &RawPrivateKeyPermit) -> RawPrivateKey; /// Builds a key-pair from a `RawPrivateKey` array of bytes. /// This operation is only possible while holding a [`RawPrivateKeyPermit`]. fn from_raw_private_key(bytes: &RawPrivateKey, _permit: &RawPrivateKeyPermit) -> Self where Self: Sized; /// Returns the private key of the `KeyPair` in an opaque form. fn private_key(&self) -> PrivateKey { // We're okay to reach in and grab the bytes of the private key, // since the way that we're exposing it would require a valid // [`RawPrivateKeyPermit`] to extract them again. let wrapped = self.raw_private_key(&RawPrivateKeyPermit::new()); PrivateKey(wrapped) } /// Builds a key-pair from a [`PrivateKey`], given in an opaque form. fn from_private_key(private_key: &PrivateKey) -> Self where Self: Sized, { // We're okay to reach in and construct an instance from // the bytes of the private key, since the way that they // were originally expressed would still require a valid // [`RawPrivateKeyPermit`] to access them. let raw_private_key = &private_key.0; Self::from_raw_private_key(raw_private_key, &RawPrivateKeyPermit::new()) } /// Sign the given message and return a digital signature fn sign(&self, msg: &[u8]) -> Self::Signature; /// Generate an ed25519 keypair from a CSPRNG /// generate is not available in `no-std` #[cfg(feature = "std")] fn generate() -> Self; /// getter function for the Public Key of the key pair fn public_key(&self) -> Self::PublicKey; } /// An ed25519 signature pub trait SignatureImpl: Sized { /// Create a new signature from a fixed size byte array. This represents a container for the /// byte serialization of an Ed25519 signature, and does not necessarily represent well-formed /// field or curve elements. /// /// Signature verification libraries are expected to reject invalid field /// elements at the time a signature is verified (not constructed). fn from_bytes(bytes: &RawSignature) -> Self; /// Returns a slice of the signature bytes fn to_bytes(&self) -> RawSignature; /// Returns a crypto-provider-independent `Signature` from this implementation-specific struct. fn to_external(&self) -> Signature { let wrapped = self.to_bytes(); Signature(wrapped) } } /// An ed25519 public key pub trait PublicKeyImpl { /// the signature type being used by verify type Signature: SignatureImpl; /// Builds this public key from an array of bytes in /// the format yielded by `to_bytes`. fn from_bytes(bytes: &RawPublicKey) -> Result where Self: Sized; /// Yields the bytes of the public key fn to_bytes(&self) -> RawPublicKey; /// Returns a crypto-provider-independent `PublicKey` from this implementation-specific struct. fn to_external(&self) -> PublicKey { let wrapped = self.to_bytes(); PublicKey(wrapped) } /// Succeeds if the signature was a valid signature created by this Keypair on the prehashed_message. fn verify_strict( &self, message: &[u8], signature: &Self::Signature, ) -> Result<(), SignatureError>; }