chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

87
vendor/ed25519/src/hex.rs vendored Normal file
View File

@@ -0,0 +1,87 @@
//! Hexadecimal encoding support
// TODO(tarcieri): use `base16ct`?
use crate::{ComponentBytes, Error, Signature};
use core::{fmt, str};
/// Format a signature component as hex.
pub(crate) struct ComponentFormatter<'a>(pub(crate) &'a ComponentBytes);
impl fmt::Debug for ComponentFormatter<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "0x")?;
for byte in self.0 {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}
impl fmt::LowerHex for Signature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for component in [&self.R, &self.s] {
for byte in component {
write!(f, "{:02x}", byte)?;
}
}
Ok(())
}
}
impl fmt::UpperHex for Signature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for component in [&self.R, &self.s] {
for byte in component {
write!(f, "{:02X}", byte)?;
}
}
Ok(())
}
}
/// Decode a signature from hexadecimal.
///
/// Upper and lower case hexadecimal are both accepted, however mixed case is
/// rejected.
// TODO(tarcieri): use `base16ct`?
impl str::FromStr for Signature {
type Err = Error;
fn from_str(hex: &str) -> signature::Result<Self> {
if hex.as_bytes().len() != Signature::BYTE_SIZE * 2 {
return Err(Error::new());
}
let mut upper_case = None;
// Ensure all characters are valid and case is not mixed
for &byte in hex.as_bytes() {
match byte {
b'0'..=b'9' => (),
b'a'..=b'z' => match upper_case {
Some(true) => return Err(Error::new()),
Some(false) => (),
None => upper_case = Some(false),
},
b'A'..=b'Z' => match upper_case {
Some(true) => (),
Some(false) => return Err(Error::new()),
None => upper_case = Some(true),
},
_ => return Err(Error::new()),
}
}
let mut result = [0u8; Self::BYTE_SIZE];
for (digit, byte) in hex.as_bytes().chunks_exact(2).zip(result.iter_mut()) {
*byte = str::from_utf8(digit)
.ok()
.and_then(|s| u8::from_str_radix(s, 16).ok())
.ok_or_else(Error::new)?;
}
Self::try_from(&result[..])
}
}

419
vendor/ed25519/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,419 @@
#![no_std]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![doc = include_str!("../README.md")]
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
#![allow(non_snake_case)]
#![forbid(unsafe_code)]
#![warn(
clippy::unwrap_used,
missing_docs,
rust_2018_idioms,
unused_lifetimes,
unused_qualifications
)]
//! # Using Ed25519 generically over algorithm implementations/providers
//!
//! By using the `ed25519` crate, you can write code which signs and verifies
//! messages using the Ed25519 signature algorithm generically over any
//! supported Ed25519 implementation (see the next section for available
//! providers).
//!
//! This allows consumers of your code to plug in whatever implementation they
//! want to use without having to add all potential Ed25519 libraries you'd
//! like to support as optional dependencies.
//!
//! ## Example
//!
//! ```
//! use ed25519::signature::{Signer, Verifier};
//!
//! pub struct HelloSigner<S>
//! where
//! S: Signer<ed25519::Signature>
//! {
//! pub signing_key: S
//! }
//!
//! impl<S> HelloSigner<S>
//! where
//! S: Signer<ed25519::Signature>
//! {
//! pub fn sign(&self, person: &str) -> ed25519::Signature {
//! // NOTE: use `try_sign` if you'd like to be able to handle
//! // errors from external signing services/devices (e.g. HSM/KMS)
//! // <https://docs.rs/signature/latest/signature/trait.Signer.html#tymethod.try_sign>
//! self.signing_key.sign(format_message(person).as_bytes())
//! }
//! }
//!
//! pub struct HelloVerifier<V> {
//! pub verifying_key: V
//! }
//!
//! impl<V> HelloVerifier<V>
//! where
//! V: Verifier<ed25519::Signature>
//! {
//! pub fn verify(
//! &self,
//! person: &str,
//! signature: &ed25519::Signature
//! ) -> Result<(), ed25519::Error> {
//! self.verifying_key.verify(format_message(person).as_bytes(), signature)
//! }
//! }
//!
//! fn format_message(person: &str) -> String {
//! format!("Hello, {}!", person)
//! }
//! ```
//!
//! ## Using above example with `ed25519-dalek`
//!
//! The [`ed25519-dalek`] crate natively supports the [`ed25519::Signature`][`Signature`]
//! type defined in this crate along with the [`signature::Signer`] and
//! [`signature::Verifier`] traits.
//!
//! Below is an example of how a hypothetical consumer of the code above can
//! instantiate and use the previously defined `HelloSigner` and `HelloVerifier`
//! types with [`ed25519-dalek`] as the signing/verification provider:
//!
//! *NOTE: requires [`ed25519-dalek`] v2 or newer for compatibility with
//! `ed25519` v2.2+*.
//!
//! ```
//! use ed25519_dalek::{Signer, Verifier, Signature};
//! #
//! # pub struct HelloSigner<S>
//! # where
//! # S: Signer<Signature>
//! # {
//! # pub signing_key: S
//! # }
//! #
//! # impl<S> HelloSigner<S>
//! # where
//! # S: Signer<Signature>
//! # {
//! # pub fn sign(&self, person: &str) -> Signature {
//! # // NOTE: use `try_sign` if you'd like to be able to handle
//! # // errors from external signing services/devices (e.g. HSM/KMS)
//! # // <https://docs.rs/signature/latest/signature/trait.Signer.html#tymethod.try_sign>
//! # self.signing_key.sign(format_message(person).as_bytes())
//! # }
//! # }
//! #
//! # pub struct HelloVerifier<V> {
//! # pub verifying_key: V
//! # }
//! #
//! # impl<V> HelloVerifier<V>
//! # where
//! # V: Verifier<Signature>
//! # {
//! # pub fn verify(
//! # &self,
//! # person: &str,
//! # signature: &Signature
//! # ) -> Result<(), ed25519::Error> {
//! # self.verifying_key.verify(format_message(person).as_bytes(), signature)
//! # }
//! # }
//! #
//! # fn format_message(person: &str) -> String {
//! # format!("Hello, {}!", person)
//! # }
//! use rand_core::OsRng; // Requires the `std` feature of `rand_core`
//!
//! /// `HelloSigner` defined above instantiated with `ed25519-dalek` as
//! /// the signing provider.
//! pub type DalekHelloSigner = HelloSigner<ed25519_dalek::SigningKey>;
//!
//! let signing_key = ed25519_dalek::SigningKey::generate(&mut OsRng);
//! let signer = DalekHelloSigner { signing_key };
//! let person = "Joe"; // Message to sign
//! let signature = signer.sign(person);
//!
//! /// `HelloVerifier` defined above instantiated with `ed25519-dalek`
//! /// as the signature verification provider.
//! pub type DalekHelloVerifier = HelloVerifier<ed25519_dalek::VerifyingKey>;
//!
//! let verifying_key: ed25519_dalek::VerifyingKey = signer.signing_key.verifying_key();
//! let verifier = DalekHelloVerifier { verifying_key };
//! assert!(verifier.verify(person, &signature).is_ok());
//! ```
//!
//! ## Using above example with `ring-compat`
//!
//! The [`ring-compat`] crate provides wrappers for [*ring*] which implement
//! the [`signature::Signer`] and [`signature::Verifier`] traits for
//! [`ed25519::Signature`][`Signature`].
//!
//! Below is an example of how a hypothetical consumer of the code above can
//! instantiate and use the previously defined `HelloSigner` and `HelloVerifier`
//! types with [`ring-compat`] as the signing/verification provider:
//!
//! ```
//! use ring_compat::signature::{
//! ed25519::{Signature, SigningKey, VerifyingKey},
//! Signer, Verifier
//! };
//! #
//! # pub struct HelloSigner<S>
//! # where
//! # S: Signer<Signature>
//! # {
//! # pub signing_key: S
//! # }
//! #
//! # impl<S> HelloSigner<S>
//! # where
//! # S: Signer<Signature>
//! # {
//! # pub fn sign(&self, person: &str) -> Signature {
//! # // NOTE: use `try_sign` if you'd like to be able to handle
//! # // errors from external signing services/devices (e.g. HSM/KMS)
//! # // <https://docs.rs/signature/latest/signature/trait.Signer.html#tymethod.try_sign>
//! # self.signing_key.sign(format_message(person).as_bytes())
//! # }
//! # }
//! #
//! # pub struct HelloVerifier<V> {
//! # pub verifying_key: V
//! # }
//! #
//! # impl<V> HelloVerifier<V>
//! # where
//! # V: Verifier<Signature>
//! # {
//! # pub fn verify(
//! # &self,
//! # person: &str,
//! # signature: &Signature
//! # ) -> Result<(), ed25519::Error> {
//! # self.verifying_key.verify(format_message(person).as_bytes(), signature)
//! # }
//! # }
//! #
//! # fn format_message(person: &str) -> String {
//! # format!("Hello, {}!", person)
//! # }
//! use rand_core::{OsRng, RngCore}; // Requires the `std` feature of `rand_core`
//!
//! /// `HelloSigner` defined above instantiated with *ring* as
//! /// the signing provider.
//! pub type RingHelloSigner = HelloSigner<SigningKey>;
//!
//! let mut ed25519_seed = [0u8; 32];
//! OsRng.fill_bytes(&mut ed25519_seed);
//!
//! let signing_key = SigningKey::from_bytes(&ed25519_seed);
//! let verifying_key = signing_key.verifying_key();
//!
//! let signer = RingHelloSigner { signing_key };
//! let person = "Joe"; // Message to sign
//! let signature = signer.sign(person);
//!
//! /// `HelloVerifier` defined above instantiated with *ring*
//! /// as the signature verification provider.
//! pub type RingHelloVerifier = HelloVerifier<VerifyingKey>;
//!
//! let verifier = RingHelloVerifier { verifying_key };
//! assert!(verifier.verify(person, &signature).is_ok());
//! ```
//!
//! # Available Ed25519 providers
//!
//! The following libraries support the types/traits from the `ed25519` crate:
//!
//! - [`ed25519-dalek`] - mature pure Rust implementation of Ed25519
//! - [`ring-compat`] - compatibility wrapper for [*ring*]
//! - [`yubihsm`] - host-side client library for YubiHSM2 devices from Yubico
//!
//! [`ed25519-dalek`]: https://docs.rs/ed25519-dalek
//! [`ring-compat`]: https://docs.rs/ring-compat
//! [*ring*]: https://github.com/briansmith/ring
//! [`yubihsm`]: https://github.com/iqlusioninc/yubihsm.rs/blob/develop/README.md
//!
//! # Features
//!
//! The following features are presently supported:
//!
//! - `pkcs8`: support for decoding/encoding PKCS#8-formatted private keys using the
//! [`KeypairBytes`] type.
//! - `std` *(default)*: Enable `std` support in [`signature`], which currently only affects whether
//! [`signature::Error`] implements `std::error::Error`.
//! - `serde`: Implement `serde::Deserialize` and `serde::Serialize` for [`Signature`]. Signatures
//! are serialized as their bytes.
//! - `serde_bytes`: Implement `serde_bytes::Deserialize` and `serde_bytes::Serialize` for
//! [`Signature`]. This enables more compact representations for formats with an efficient byte
//! array representation. As per the `serde_bytes` documentation, this can most easily be realised
//! using the `#[serde(with = "serde_bytes")]` annotation, e.g.:
//!
//! ```ignore
//! # use ed25519::Signature;
//! # use serde::{Deserialize, Serialize};
//! #[derive(Deserialize, Serialize)]
//! #[serde(transparent)]
//! struct SignatureAsBytes(#[serde(with = "serde_bytes")] Signature);
//! ```
#[cfg(feature = "alloc")]
extern crate alloc;
mod hex;
#[cfg(feature = "pkcs8")]
pub mod pkcs8;
#[cfg(feature = "serde")]
mod serde;
pub use signature::{self, Error, SignatureEncoding};
#[cfg(feature = "pkcs8")]
pub use crate::pkcs8::{KeypairBytes, PublicKeyBytes};
use core::fmt;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
/// Size of a single component of an Ed25519 signature.
const COMPONENT_SIZE: usize = 32;
/// Size of an `R` or `s` component of an Ed25519 signature when serialized
/// as bytes.
pub type ComponentBytes = [u8; COMPONENT_SIZE];
/// Ed25519 signature serialized as a byte array.
pub type SignatureBytes = [u8; Signature::BYTE_SIZE];
/// Ed25519 signature.
///
/// This type 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.
#[derive(Copy, Clone, Eq, PartialEq)]
#[repr(C)]
pub struct Signature {
R: ComponentBytes,
s: ComponentBytes,
}
impl Signature {
/// Size of an encoded Ed25519 signature in bytes.
pub const BYTE_SIZE: usize = COMPONENT_SIZE * 2;
/// Parse an Ed25519 signature from a byte slice.
pub fn from_bytes(bytes: &SignatureBytes) -> Self {
let mut R = ComponentBytes::default();
let mut s = ComponentBytes::default();
let components = bytes.split_at(COMPONENT_SIZE);
R.copy_from_slice(components.0);
s.copy_from_slice(components.1);
Self { R, s }
}
/// Parse an Ed25519 signature from its `R` and `s` components.
pub fn from_components(R: ComponentBytes, s: ComponentBytes) -> Self {
Self { R, s }
}
/// Parse an Ed25519 signature from a byte slice.
///
/// # Returns
/// - `Ok` on success
/// - `Err` if the input byte slice is not 64-bytes
pub fn from_slice(bytes: &[u8]) -> signature::Result<Self> {
SignatureBytes::try_from(bytes)
.map(Into::into)
.map_err(|_| Error::new())
}
/// Bytes for the `R` component of a signature.
pub fn r_bytes(&self) -> &ComponentBytes {
&self.R
}
/// Bytes for the `s` component of a signature.
pub fn s_bytes(&self) -> &ComponentBytes {
&self.s
}
/// Return the inner byte array.
pub fn to_bytes(&self) -> SignatureBytes {
let mut ret = [0u8; Self::BYTE_SIZE];
let (R, s) = ret.split_at_mut(COMPONENT_SIZE);
R.copy_from_slice(&self.R);
s.copy_from_slice(&self.s);
ret
}
/// Convert this signature into a byte vector.
#[cfg(feature = "alloc")]
pub fn to_vec(&self) -> Vec<u8> {
self.to_bytes().to_vec()
}
}
impl SignatureEncoding for Signature {
type Repr = SignatureBytes;
fn to_bytes(&self) -> SignatureBytes {
self.to_bytes()
}
}
impl From<Signature> for SignatureBytes {
fn from(sig: Signature) -> SignatureBytes {
sig.to_bytes()
}
}
impl From<&Signature> for SignatureBytes {
fn from(sig: &Signature) -> SignatureBytes {
sig.to_bytes()
}
}
impl From<SignatureBytes> for Signature {
fn from(bytes: SignatureBytes) -> Self {
Signature::from_bytes(&bytes)
}
}
impl From<&SignatureBytes> for Signature {
fn from(bytes: &SignatureBytes) -> Self {
Signature::from_bytes(bytes)
}
}
impl TryFrom<&[u8]> for Signature {
type Error = Error;
fn try_from(bytes: &[u8]) -> signature::Result<Self> {
Self::from_slice(bytes)
}
}
impl fmt::Debug for Signature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ed25519::Signature")
.field("R", &hex::ComponentFormatter(self.r_bytes()))
.field("s", &hex::ComponentFormatter(self.s_bytes()))
.finish()
}
}
impl fmt::Display for Signature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:X}", self)
}
}

356
vendor/ed25519/src/pkcs8.rs vendored Normal file
View File

@@ -0,0 +1,356 @@
//! PKCS#8 private key support.
//!
//! Implements Ed25519 PKCS#8 private keys as described in RFC8410 Section 7:
//! <https://datatracker.ietf.org/doc/html/rfc8410#section-7>
//!
//! ## SemVer Notes
//!
//! The `pkcs8` module of this crate is exempted from SemVer as it uses a
//! pre-1.0 dependency (the `pkcs8` crate).
//!
//! However, breaking changes to this module will be accompanied by a minor
//! version bump.
//!
//! Please lock to a specific minor version of the `ed25519` crate to avoid
//! breaking changes when using this module.
pub use pkcs8::{
spki, DecodePrivateKey, DecodePublicKey, Error, ObjectIdentifier, PrivateKeyInfo, Result,
};
#[cfg(feature = "alloc")]
pub use pkcs8::{spki::EncodePublicKey, EncodePrivateKey};
#[cfg(feature = "alloc")]
pub use pkcs8::der::{asn1::BitStringRef, Document, SecretDocument};
use core::fmt;
#[cfg(feature = "pem")]
use {
alloc::string::{String, ToString},
core::str,
};
#[cfg(feature = "zeroize")]
use zeroize::Zeroize;
/// Algorithm [`ObjectIdentifier`] for the Ed25519 digital signature algorithm
/// (`id-Ed25519`).
///
/// <http://oid-info.com/get/1.3.101.112>
pub const ALGORITHM_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.101.112");
/// Ed25519 Algorithm Identifier.
pub const ALGORITHM_ID: pkcs8::AlgorithmIdentifierRef<'static> = pkcs8::AlgorithmIdentifierRef {
oid: ALGORITHM_OID,
parameters: None,
};
/// Ed25519 keypair serialized as bytes.
///
/// This type is primarily useful for decoding/encoding PKCS#8 private key
/// files (either DER or PEM) encoded using the following traits:
///
/// - [`DecodePrivateKey`]: decode DER or PEM encoded PKCS#8 private key.
/// - [`EncodePrivateKey`]: encode DER or PEM encoded PKCS#8 private key.
///
/// PKCS#8 private key files encoded with PEM begin with:
///
/// ```text
/// -----BEGIN PRIVATE KEY-----
/// ```
///
/// Note that this type operates on raw bytes and performs no validation that
/// keys represent valid Ed25519 field elements.
pub struct KeypairBytes {
/// Ed25519 secret key.
///
/// Little endian serialization of an element of the Curve25519 scalar
/// field, prior to "clamping" (i.e. setting/clearing bits to ensure the
/// scalar is actually a valid field element)
pub secret_key: [u8; Self::BYTE_SIZE / 2],
/// Ed25519 public key (if available).
///
/// Compressed Edwards-y encoded curve point.
pub public_key: Option<PublicKeyBytes>,
}
impl KeypairBytes {
/// Size of an Ed25519 keypair when serialized as bytes.
const BYTE_SIZE: usize = 64;
/// Parse raw keypair from a 64-byte input.
pub fn from_bytes(bytes: &[u8; Self::BYTE_SIZE]) -> Self {
let (sk, pk) = bytes.split_at(Self::BYTE_SIZE / 2);
Self {
secret_key: sk.try_into().expect("secret key size error"),
public_key: Some(PublicKeyBytes(
pk.try_into().expect("public key size error"),
)),
}
}
/// Serialize as a 64-byte keypair.
///
/// # Returns
///
/// - `Some(bytes)` if the `public_key` is present.
/// - `None` if the `public_key` is absent (i.e. `None`).
pub fn to_bytes(&self) -> Option<[u8; Self::BYTE_SIZE]> {
if let Some(public_key) = &self.public_key {
let mut result = [0u8; Self::BYTE_SIZE];
let (sk, pk) = result.split_at_mut(Self::BYTE_SIZE / 2);
sk.copy_from_slice(&self.secret_key);
pk.copy_from_slice(public_key.as_ref());
Some(result)
} else {
None
}
}
}
impl Drop for KeypairBytes {
fn drop(&mut self) {
#[cfg(feature = "zeroize")]
self.secret_key.zeroize()
}
}
#[cfg(feature = "alloc")]
impl EncodePrivateKey for KeypairBytes {
fn to_pkcs8_der(&self) -> Result<SecretDocument> {
// Serialize private key as nested OCTET STRING
let mut private_key = [0u8; 2 + (Self::BYTE_SIZE / 2)];
private_key[0] = 0x04;
private_key[1] = 0x20;
private_key[2..].copy_from_slice(&self.secret_key);
let private_key_info = PrivateKeyInfo {
algorithm: ALGORITHM_ID,
private_key: &private_key,
public_key: self.public_key.as_ref().map(|pk| pk.0.as_slice()),
};
let result = SecretDocument::encode_msg(&private_key_info)?;
#[cfg(feature = "zeroize")]
private_key.zeroize();
Ok(result)
}
}
impl TryFrom<PrivateKeyInfo<'_>> for KeypairBytes {
type Error = Error;
fn try_from(private_key: PrivateKeyInfo<'_>) -> Result<Self> {
private_key.algorithm.assert_algorithm_oid(ALGORITHM_OID)?;
if private_key.algorithm.parameters.is_some() {
return Err(Error::ParametersMalformed);
}
// Ed25519 PKCS#8 keys are represented as a nested OCTET STRING
// (i.e. an OCTET STRING within an OCTET STRING).
//
// This match statement checks and removes the inner OCTET STRING
// header value:
//
// - 0x04: OCTET STRING tag
// - 0x20: 32-byte length
let secret_key = match private_key.private_key {
[0x04, 0x20, rest @ ..] => rest.try_into().map_err(|_| Error::KeyMalformed),
_ => Err(Error::KeyMalformed),
}?;
let public_key = private_key
.public_key
.map(|bytes| bytes.try_into().map_err(|_| Error::KeyMalformed))
.transpose()?
.map(PublicKeyBytes);
Ok(Self {
secret_key,
public_key,
})
}
}
impl TryFrom<&[u8]> for KeypairBytes {
type Error = Error;
fn try_from(der_bytes: &[u8]) -> Result<Self> {
Self::from_pkcs8_der(der_bytes)
}
}
impl fmt::Debug for KeypairBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("KeypairBytes")
.field("public_key", &self.public_key)
.finish_non_exhaustive()
}
}
#[cfg(feature = "pem")]
impl str::FromStr for KeypairBytes {
type Err = Error;
fn from_str(pem: &str) -> Result<Self> {
Self::from_pkcs8_pem(pem)
}
}
/// Ed25519 public key serialized as bytes.
///
/// This type is primarily useful for decoding/encoding SPKI public key
/// files (either DER or PEM) encoded using the following traits:
///
/// - [`DecodePublicKey`]: decode DER or PEM encoded PKCS#8 private key.
/// - [`EncodePublicKey`]: encode DER or PEM encoded PKCS#8 private key.
///
/// SPKI public key files encoded with PEM begin with:
///
/// ```text
/// -----BEGIN PUBLIC KEY-----
/// ```
///
/// Note that this type operates on raw bytes and performs no validation that
/// public keys represent valid compressed Ed25519 y-coordinates.
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct PublicKeyBytes(pub [u8; Self::BYTE_SIZE]);
impl PublicKeyBytes {
/// Size of an Ed25519 public key when serialized as bytes.
const BYTE_SIZE: usize = 32;
/// Returns the raw bytes of the public key.
pub fn to_bytes(&self) -> [u8; Self::BYTE_SIZE] {
self.0
}
}
impl AsRef<[u8; Self::BYTE_SIZE]> for PublicKeyBytes {
fn as_ref(&self) -> &[u8; Self::BYTE_SIZE] {
&self.0
}
}
#[cfg(feature = "alloc")]
impl EncodePublicKey for PublicKeyBytes {
fn to_public_key_der(&self) -> spki::Result<Document> {
pkcs8::SubjectPublicKeyInfoRef {
algorithm: ALGORITHM_ID,
subject_public_key: BitStringRef::new(0, &self.0)?,
}
.try_into()
}
}
impl TryFrom<spki::SubjectPublicKeyInfoRef<'_>> for PublicKeyBytes {
type Error = spki::Error;
fn try_from(spki: spki::SubjectPublicKeyInfoRef<'_>) -> spki::Result<Self> {
spki.algorithm.assert_algorithm_oid(ALGORITHM_OID)?;
if spki.algorithm.parameters.is_some() {
return Err(spki::Error::KeyMalformed);
}
spki.subject_public_key
.as_bytes()
.ok_or(spki::Error::KeyMalformed)?
.try_into()
.map(Self)
.map_err(|_| spki::Error::KeyMalformed)
}
}
impl TryFrom<&[u8]> for PublicKeyBytes {
type Error = spki::Error;
fn try_from(der_bytes: &[u8]) -> spki::Result<Self> {
Self::from_public_key_der(der_bytes)
}
}
impl TryFrom<KeypairBytes> for PublicKeyBytes {
type Error = spki::Error;
fn try_from(keypair: KeypairBytes) -> spki::Result<PublicKeyBytes> {
PublicKeyBytes::try_from(&keypair)
}
}
impl TryFrom<&KeypairBytes> for PublicKeyBytes {
type Error = spki::Error;
fn try_from(keypair: &KeypairBytes) -> spki::Result<PublicKeyBytes> {
keypair.public_key.ok_or(spki::Error::KeyMalformed)
}
}
impl fmt::Debug for PublicKeyBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("PublicKeyBytes(")?;
for &byte in self.as_ref() {
write!(f, "{:02X}", byte)?;
}
f.write_str(")")
}
}
#[cfg(feature = "pem")]
impl str::FromStr for PublicKeyBytes {
type Err = spki::Error;
fn from_str(pem: &str) -> spki::Result<Self> {
Self::from_public_key_pem(pem)
}
}
#[cfg(feature = "pem")]
impl ToString for PublicKeyBytes {
fn to_string(&self) -> String {
self.to_public_key_pem(Default::default())
.expect("PEM serialization error")
}
}
#[cfg(feature = "pem")]
#[cfg(test)]
mod tests {
use super::{KeypairBytes, PublicKeyBytes};
use hex_literal::hex;
const SECRET_KEY_BYTES: [u8; 32] =
hex!("D4EE72DBF913584AD5B6D8F1F769F8AD3AFE7C28CBF1D4FBE097A88F44755842");
const PUBLIC_KEY_BYTES: [u8; 32] =
hex!("19BF44096984CDFE8541BAC167DC3B96C85086AA30B6B6CB0C5C38AD703166E1");
#[test]
fn to_bytes() {
let valid_keypair = KeypairBytes {
secret_key: SECRET_KEY_BYTES,
public_key: Some(PublicKeyBytes(PUBLIC_KEY_BYTES)),
};
assert_eq!(
valid_keypair.to_bytes().unwrap(),
hex!("D4EE72DBF913584AD5B6D8F1F769F8AD3AFE7C28CBF1D4FBE097A88F4475584219BF44096984CDFE8541BAC167DC3B96C85086AA30B6B6CB0C5C38AD703166E1")
);
let invalid_keypair = KeypairBytes {
secret_key: SECRET_KEY_BYTES,
public_key: None,
};
assert_eq!(invalid_keypair.to_bytes(), None);
}
}

121
vendor/ed25519/src/serde.rs vendored Normal file
View File

@@ -0,0 +1,121 @@
//! `serde` support.
use crate::{Signature, SignatureBytes};
use ::serde::{de, ser, Deserialize, Serialize};
use core::fmt;
impl Serialize for Signature {
fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use ser::SerializeTuple;
let mut seq = serializer.serialize_tuple(Signature::BYTE_SIZE)?;
for byte in self.to_bytes() {
seq.serialize_element(&byte)?;
}
seq.end()
}
}
// serde lacks support for deserializing arrays larger than 32-bytes
// see: <https://github.com/serde-rs/serde/issues/631>
impl<'de> Deserialize<'de> for Signature {
fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct ByteArrayVisitor;
impl<'de> de::Visitor<'de> for ByteArrayVisitor {
type Value = [u8; Signature::BYTE_SIZE];
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("bytestring of length 64")
}
fn visit_seq<A>(self, mut seq: A) -> Result<[u8; Signature::BYTE_SIZE], A::Error>
where
A: de::SeqAccess<'de>,
{
use de::Error;
let mut arr = [0u8; Signature::BYTE_SIZE];
for (i, byte) in arr.iter_mut().enumerate() {
*byte = seq
.next_element()?
.ok_or_else(|| Error::invalid_length(i, &self))?;
}
Ok(arr)
}
}
deserializer
.deserialize_tuple(Signature::BYTE_SIZE, ByteArrayVisitor)
.map(Into::into)
}
}
#[cfg(feature = "serde_bytes")]
impl serde_bytes::Serialize for Signature {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_bytes(&self.to_bytes())
}
}
#[cfg(feature = "serde_bytes")]
impl<'de> serde_bytes::Deserialize<'de> for Signature {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct ByteArrayVisitor;
impl<'de> de::Visitor<'de> for ByteArrayVisitor {
type Value = SignatureBytes;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("bytestring of length 64")
}
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
where
E: de::Error,
{
use de::Error;
bytes
.try_into()
.map_err(|_| Error::invalid_length(bytes.len(), &self))
}
}
deserializer
.deserialize_bytes(ByteArrayVisitor)
.map(Into::into)
}
}
#[cfg(test)]
mod tests {
use crate::{Signature, SignatureBytes};
use hex_literal::hex;
const SIGNATURE_BYTES: SignatureBytes = hex!(
"
e5564300c360ac729086e2cc806e828a
84877f1eb8e5d974d873e06522490155
5fb8821590a33bacc61e39701cf9b46b
d25bf5f0595bbe24655141438e7a100b
"
);
#[test]
fn round_trip() {
let signature = Signature::from_bytes(&SIGNATURE_BYTES);
let serialized = bincode::serialize(&signature).unwrap();
let deserialized = bincode::deserialize(&serialized).unwrap();
assert_eq!(signature, deserialized);
}
}