taler-rust

GNU Taler code in Rust. Largely core banking integrations.
Log | Files | Refs | Submodules | README | LICENSE

api_common.rs (6295B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2024, 2026 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 
     17 use std::{borrow::Cow, fmt::Display, ops::Deref, str::FromStr};
     18 
     19 use aws_lc_rs::{
     20     error::KeyRejected,
     21     signature::{self, Ed25519KeyPair, KeyPair, ParsedPublicKey},
     22 };
     23 use serde::{Deserialize, Deserializer, Serialize, de::Error};
     24 use serde_json::value::RawValue;
     25 
     26 use crate::types::base32::{Base32, Base32Error};
     27 
     28 /// <https://docs.taler.net/core/api-common.html#tsref-type-ErrorDetail>
     29 #[derive(Debug, Clone, Serialize, Deserialize)]
     30 pub struct ErrorDetail {
     31     pub code: u32,
     32     pub hint: Option<Box<str>>,
     33     pub detail: Option<Box<str>>,
     34     pub parameter: Option<Box<str>>,
     35     pub path: Option<Box<str>>,
     36     pub offset: Option<Box<str>>,
     37     pub index: Option<Box<str>>,
     38     pub object: Option<Box<str>>,
     39     pub currency: Option<Box<str>>,
     40     pub type_expected: Option<Box<str>>,
     41     pub type_actual: Option<Box<str>>,
     42     pub extra: Option<Box<RawValue>>,
     43 }
     44 
     45 pub fn safe_u64(nb: u64) -> SafeU64 {
     46     SafeU64::try_from(nb).expect("invalid safe u64")
     47 }
     48 
     49 /// <https://docs.taler.net/core/api-common.html#tsref-type-SafeUint64>
     50 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize)]
     51 pub struct SafeU64(u64);
     52 
     53 impl Deref for SafeU64 {
     54     type Target = u64;
     55 
     56     fn deref(&self) -> &Self::Target {
     57         &self.0
     58     }
     59 }
     60 
     61 #[derive(Debug, thiserror::Error)]
     62 pub enum SafeU64Error {
     63     #[error("{0} unsafe, {0} > (2^53 - 1)")]
     64     Unsafe(u64),
     65     #[error("{0} is negative")]
     66     Negative(i64),
     67 }
     68 
     69 impl TryFrom<u64> for SafeU64 {
     70     type Error = SafeU64Error;
     71 
     72     fn try_from(nb: u64) -> Result<Self, Self::Error> {
     73         if nb < (1 << 53) - 1 {
     74             Ok(SafeU64(nb))
     75         } else {
     76             Err(SafeU64Error::Unsafe(nb))
     77         }
     78     }
     79 }
     80 
     81 impl TryFrom<i64> for SafeU64 {
     82     type Error = SafeU64Error;
     83 
     84     fn try_from(nb: i64) -> Result<Self, Self::Error> {
     85         u64::try_from(nb)
     86             .map_err(|_| SafeU64Error::Negative(nb))
     87             .and_then(|it| it.try_into())
     88     }
     89 }
     90 
     91 impl TryFrom<i32> for SafeU64 {
     92     type Error = SafeU64Error;
     93 
     94     fn try_from(nb: i32) -> Result<Self, Self::Error> {
     95         u64::try_from(nb)
     96             .map_err(|_| SafeU64Error::Negative(nb as i64))
     97             .and_then(|it| it.try_into())
     98     }
     99 }
    100 
    101 impl<'de> Deserialize<'de> for SafeU64 {
    102     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    103     where
    104         D: Deserializer<'de>,
    105     {
    106         SafeU64::try_from(u64::deserialize(deserializer)?).map_err(D::Error::custom)
    107     }
    108 }
    109 
    110 impl Display for SafeU64 {
    111     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    112         self.0.fmt(f)
    113     }
    114 }
    115 
    116 /// 64-byte hash code
    117 pub type HashCode = Base32<64>;
    118 /// 32-bytes hash code
    119 pub type ShortHashCode = Base32<32>;
    120 pub type WadId = Base32<24>;
    121 pub type EddsaSignature = Base32<64>;
    122 
    123 /// EdDSA and ECDHE public keys always point on Curve25519
    124 /// and represented  using the standard 256 bits Ed25519 compact format,
    125 /// converted to Crockford Base32.
    126 #[derive(Debug, Clone, PartialEq, Eq)]
    127 pub struct EddsaPublicKey(Base32<32>);
    128 
    129 impl AsRef<Base32<32>> for EddsaPublicKey {
    130     fn as_ref(&self) -> &Base32<32> {
    131         &self.0
    132     }
    133 }
    134 
    135 impl Serialize for EddsaPublicKey {
    136     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    137     where
    138         S: serde::Serializer,
    139     {
    140         self.0.serialize(serializer)
    141     }
    142 }
    143 
    144 impl<'de> Deserialize<'de> for EddsaPublicKey {
    145     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    146     where
    147         D: Deserializer<'de>,
    148     {
    149         let raw = Cow::<str>::deserialize(deserializer)?;
    150         Self::from_str(&raw).map_err(D::Error::custom)
    151     }
    152 }
    153 
    154 impl Display for EddsaPublicKey {
    155     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    156         self.0.fmt(f)
    157     }
    158 }
    159 
    160 #[derive(Debug, thiserror::Error)]
    161 pub enum EddsaPublicKeyError {
    162     #[error(transparent)]
    163     Base32(#[from] Base32Error<32>),
    164     #[error(transparent)]
    165     Invalid(#[from] KeyRejected),
    166 }
    167 
    168 impl FromStr for EddsaPublicKey {
    169     type Err = EddsaPublicKeyError;
    170 
    171     fn from_str(s: &str) -> Result<Self, Self::Err> {
    172         let encoded = Base32::<32>::from_str(s)?;
    173         Self::try_from(encoded)
    174     }
    175 }
    176 
    177 impl TryFrom<&[u8]> for EddsaPublicKey {
    178     type Error = EddsaPublicKeyError;
    179 
    180     fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
    181         let encoded = Base32::try_from(value)?;
    182         Self::try_from(encoded)
    183     }
    184 }
    185 
    186 impl TryFrom<Base32<32>> for EddsaPublicKey {
    187     type Error = EddsaPublicKeyError;
    188 
    189     fn try_from(value: Base32<32>) -> Result<Self, Self::Error> {
    190         ParsedPublicKey::new(&signature::ED25519, value.as_ref())?;
    191         Ok(Self(value))
    192     }
    193 }
    194 
    195 impl EddsaPublicKey {
    196     pub fn slice(&self) -> &[u8; 32] {
    197         self.0.deref()
    198     }
    199 
    200     pub fn rand() -> EddsaPublicKey {
    201         let signing_key = Ed25519KeyPair::generate().unwrap();
    202         let bytes: [u8; 32] = signing_key.public_key().as_ref().try_into().unwrap();
    203         Self(Base32::from(bytes))
    204     }
    205 }
    206 
    207 impl sqlx::Type<sqlx::Postgres> for EddsaPublicKey {
    208     fn type_info() -> sqlx::postgres::PgTypeInfo {
    209         <Base32<32>>::type_info()
    210     }
    211 }
    212 
    213 impl<'q> sqlx::Encode<'q, sqlx::Postgres> for EddsaPublicKey {
    214     fn encode_by_ref(
    215         &self,
    216         buf: &mut sqlx::postgres::PgArgumentBuffer,
    217     ) -> Result<sqlx::encode::IsNull, sqlx::error::BoxDynError> {
    218         self.0.encode_by_ref(buf)
    219     }
    220 }
    221 
    222 impl<'r> sqlx::Decode<'r, sqlx::Postgres> for EddsaPublicKey {
    223     fn decode(value: sqlx::postgres::PgValueRef<'r>) -> Result<Self, sqlx::error::BoxDynError> {
    224         let raw = <Base32<32>>::decode(value)?;
    225         Ok(Self(raw))
    226     }
    227 }