most missing docs for llcrypto

This commit is contained in:
Nick Mathewson 2020-05-08 11:19:13 -04:00
parent 3c7f75302b
commit b48597fb18
6 changed files with 70 additions and 22 deletions

View File

@ -1,4 +1,7 @@
//! Ciphers used to implement the Tor protocols.
//!
//! Fortunately, Tor has managed not to proliferate ciphers. It only
//! uses AES, and (so far) only uses AES in counter mode.
/// Re-exports implementations of counter-mode AES
pub mod aes {

View File

@ -3,13 +3,16 @@
//! In various places, for legacy reasons, Tor uses SHA1, SHA2,
//! SHA3, and SHAKE. We re-export them all here, implementing
//! the Digest trait.
//!
//! Other code should access these digests via the Digest trait.
// These implement Digest, so we can just use them as-is.
pub use sha2::{Sha256, Sha512};
pub use sha3::{Sha3_256, Shake128, Shake256};
// The Sha1 crate, OTOH, doesn't expose Digest. I'll do it myself.
/// Wrapper for Sha1 that implements the Digest trait.
/// A Sha1 implementation that implements the Digest trait.
///
/// (This is just a thin wrapper around the Sha1 crate.)
#[derive(Clone, Default)]
pub struct Sha1(sha1::Sha1);

View File

@ -1,17 +1,16 @@
//! Low-level crypto implementations for Tor.
//!
//! This crate doesn't have anything interesting: it just wraps other
//! crates that implement lower-level cryptographic functionality that
//! Tor does not implement itself. In some cases the functionality is
//! just re-exported; in others, it is wrapped to present a
//! conseistent interface.
//! This crate doesn't have much of interest: for the most part it
//! just wraps other crates that implement lower-level cryptographic
//! functionality. In some cases the functionality is just
//! re-exported; in others, it is wrapped to present a conseistent
//! interface.
//!
//! Encryption is implemented in `cipher`, digests are in `d`, and
//! public key cryptography (including signatures, encryption, and key
//! agreement) are in `pk`.
// TODO -- the long-term intention here is that this functionality
// should be replaceable at compile time with other implementations.
#![deny(missing_docs)]
pub mod cipher;
pub mod d;

View File

@ -1,4 +1,7 @@
//! Re-exporting public-key cryptography.
//! Public-key cryptography for Tor.
//!
//! In old places, Tor uses RSA; newer Tor public-key cryptography is
//! basd on curve25519 and ed25519.
pub mod keymanip;
pub mod rsa;
@ -6,7 +9,7 @@ pub mod rsa;
/// Re-exporting Curve25519 implementations.
///
/// Eventually there should probably be a key-agreement trait or two
/// that this implements, but for now I'm just using the API from
/// that this implements, but for now I'm just re-using the API from
/// x25519-dalek.
pub mod curve25519 {
pub use x25519_dalek::{EphemeralSecret, PublicKey, SharedSecret, StaticSecret};

View File

@ -1,3 +1,15 @@
//! Key manipulation functions for use with public keys.
//!
//! Tor does some interesting and not-really-standard things with its
//! curve25519 and ed25519 keys, for several reasons.
//!
//! In order to prove ownership of a curve25519 private key, Tor
//! converts it into an ed25519 key, and then uses that ed25519 key to
//! sign its identity key.
//!
//! TODO: This is also where we would put the key-derivation code that
//! Tor uses in the hsv3 onion services protocol.
use crate::pk;
use digest::Digest;
use zeroize::Zeroizing;
@ -7,6 +19,7 @@ use zeroize::Zeroizing;
///
/// Note that this formula is not terribly standardized; don't use
/// it for anything besides cross-certification.
///
pub fn convert_curve25519_to_ed25519_public(
pubkey: &pk::curve25519::PublicKey,
signbit: u8,
@ -16,9 +29,10 @@ pub fn convert_curve25519_to_ed25519_public(
let point = MontgomeryPoint(*pubkey.as_bytes());
let edpoint = point.to_edwards(signbit)?;
// TODO: This is inefficient; we shouldn't have to re-compress this
// point to get the public key we wanted. But there's no way I
// can to construct an ed25519 public key from a compressed point.
// TODO: This is inefficient; we shouldn't have to re-compress
// this point to get the public key we wanted. But there's no way
// with the current API that I can to construct an ed25519 public
// key from a compressed point.
let compressed_y = edpoint.compress();
pk::ed25519::PublicKey::from_bytes(compressed_y.as_bytes()).ok()
}

View File

@ -1,11 +1,13 @@
//! Re-exporting RSA implementations.
//!
//! This module can currently handle public keys and signature
//! verification as they work in the Tor directory protocol and
//! verification used in the Tor directory protocol and
//! similar places.
//!
//! Currently, that means supporting validating PKCSv1
//! signatures, and encoding and decoding keys from DER.
//!
//! Currently missing is signing and RSA-OEAP.
use arrayref::array_ref;
use subtle::*;
use zeroize::Zeroize;
@ -16,7 +18,7 @@ use zeroize::Zeroize;
pub const RSA_ID_LEN: usize = 20;
/// An identifier for a Tor relay, based on its legacy RSA
/// identity key.
/// identity key. These are used all over the Tor protocol.
#[derive(Clone, Zeroize, Debug)]
pub struct RSAIdentity {
pub id: [u8; RSA_ID_LEN],
@ -31,9 +33,23 @@ impl PartialEq<RSAIdentity> for RSAIdentity {
impl Eq for RSAIdentity {}
impl RSAIdentity {
/// Expose and RSAIdentity as a slice of bytes.
pub fn as_bytes(&self) -> &[u8] {
&self.id[..]
}
/// Construct an RSAIdentity from a slice of bytes.
///
/// Returns None if the input is not of the correct length.
///
/// ```
/// let bytes = b"xyzzyxyzzyxyzzyxyzzy";
/// let id = RSAIdentity::from_bytes(&bytes);
/// assert_eq!(id.unwrap().as_bytes(), bytes);
///
/// let truncated = b"xyzzy";
/// let id = RSAIdentity::from_bytes(truncated);
/// assert_eq!(id, None);
/// ```
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() == RSA_ID_LEN {
Some(RSAIdentity {
@ -46,11 +62,15 @@ impl RSAIdentity {
}
/// An RSA public key.
///
/// This implementation is a simple wrapper so that we can define new
/// methods and traits on the type.
pub struct PublicKey(rsa::RSAPublicKey);
/// An RSA Private key.
/// An RSA private key.
pub struct PrivateKey(rsa::RSAPrivateKey);
impl PrivateKey {
/// Return the public component of this key.
pub fn to_public_key(&self) -> PublicKey {
PublicKey(self.0.to_public_key())
}
@ -73,16 +93,22 @@ impl PublicKey {
///
/// Tor uses RSA-PKCSv1 signatures, with hash algorithm OIDs
/// omitted.
///
/// ## Issues
///
/// XXXX We probably shouldn't be exposing rsa::errors::Result().
///
pub fn verify(&self, hashed: &[u8], sig: &[u8]) -> rsa::errors::Result<()> {
use rsa::PublicKey;
self.0
.verify::<rsa::hash::Hashes>(rsa::PaddingScheme::PKCS1v15, None, hashed, sig)
// XXXX I don't want to expose rsa::errors::Result, really.
}
/// Decode an alleged DER byte string into a PublicKey. Return None
/// if the DER string does not have a valid PublicKey.
/// Decode an alleged DER byte string into a PublicKey.
///
/// (Does not expect or allow an OID.)
/// Return None if the DER string does not have a valid PublicKey.
///
/// (This function expects an RSAPublicKey, as used by Tor. It
/// does not expect or accept a PublicKeyInfo.)
pub fn from_der(der: &[u8]) -> Option<Self> {
// We can't use the rsa-der crate, since it expects to find the
// key inside of a bitstring inside of another asn1 object.
@ -120,7 +146,7 @@ impl PublicKey {
}
/// Encode this public key into the DER format as used by Tor.
///
/// Does not attach an OID.
/// The result is an RSAPublicKey, not a PublicKeyInfo.
pub fn to_der(&self) -> Vec<u8> {
use simple_asn1::ASN1Block;
// XXX do I really need both of these crates? rsa uses