jose_b64/stream/
mod.rs

1// SPDX-FileCopyrightText: 2022 Profian Inc. <opensource@profian.com>
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! Streamed encoding/decoding types
5//!
6//! **SECURITY NOTE**: DO NOT use these types for decoding secrets.
7//!
8//! These types are useful for streams feeding into JWS or JWE. However, since
9//! they report invalid base64 errors for each block, this could be used in a
10//! timing attack if used to decode secrets.
11//!
12//! ```
13//! use jose_b64::stream::{Decoder, Encoder, Update};
14//! use jose_b64::base64ct::Base64UrlUnpadded;
15//!
16//! let mut enc: Encoder<String, Base64UrlUnpadded> = Encoder::default();
17//! enc.update("Hello world!").unwrap();
18//! let encoded = enc.finish().unwrap();
19//! assert_eq!(encoded, "SGVsbG8gd29ybGQh");
20//!
21//! // If you may need to serialize potentially invalid UTF8 or can't guarantee that your
22//! // chunks are at utf8 boundaries, use `Decoder<Vec<u8>, _>` instead
23//! let mut dec: Decoder<String, Base64UrlUnpadded> = Decoder::default();
24//! dec.update(encoded).unwrap();
25//! let decoded = dec.finish().unwrap();
26//! assert_eq!(decoded, "Hello world!");
27//! ```
28
29use core::convert::Infallible;
30
31mod dec;
32mod enc;
33mod optional;
34mod update;
35
36pub use dec::Decoder;
37pub use enc::Encoder;
38pub use optional::Optional;
39pub use update::Update;
40
41/// A Base64 error.
42#[derive(Debug)]
43pub enum Error<T> {
44    /// An embedded error.
45    Inner(T),
46
47    /// The length is invalid.
48    Length,
49
50    /// An invalid value was found.
51    Value,
52}
53
54impl Error<Infallible> {
55    /// Casts an infallible error to any other kind of error.
56    pub fn cast<T>(&self) -> Error<T> {
57        match self {
58            Self::Inner(..) => unreachable!(),
59            Self::Length => Error::Length,
60            Self::Value => Error::Value,
61        }
62    }
63}
64
65impl<T> From<base64ct::Error> for Error<T> {
66    fn from(error: base64ct::Error) -> Self {
67        match error {
68            base64ct::Error::InvalidEncoding => Self::Value,
69            base64ct::Error::InvalidLength => Self::Length,
70        }
71    }
72}