api_common.rs (6627B)
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(Clone, PartialEq, Eq)] 127 pub struct EddsaPublicKey(Base32<32>); 128 129 impl Deref for EddsaPublicKey { 130 type Target = Base32<32>; 131 132 fn deref(&self) -> &Self::Target { 133 &self.0 134 } 135 } 136 137 impl Serialize for EddsaPublicKey { 138 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 139 where 140 S: serde::Serializer, 141 { 142 self.0.serialize(serializer) 143 } 144 } 145 146 impl<'de> Deserialize<'de> for EddsaPublicKey { 147 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 148 where 149 D: Deserializer<'de>, 150 { 151 let raw = Cow::<str>::deserialize(deserializer)?; 152 Self::from_str(&raw).map_err(D::Error::custom) 153 } 154 } 155 156 impl Display for EddsaPublicKey { 157 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 158 self.0.fmt(f) 159 } 160 } 161 162 impl std::fmt::Debug for EddsaPublicKey { 163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 164 Display::fmt(&self.0, f) 165 } 166 } 167 168 #[derive(Debug, thiserror::Error)] 169 pub enum EddsaPublicKeyError { 170 #[error(transparent)] 171 Base32(#[from] Base32Error<32>), 172 #[error(transparent)] 173 Invalid(#[from] KeyRejected), 174 } 175 176 impl FromStr for EddsaPublicKey { 177 type Err = EddsaPublicKeyError; 178 179 fn from_str(s: &str) -> Result<Self, Self::Err> { 180 let encoded = Base32::<32>::from_str(s)?; 181 Self::try_from(encoded) 182 } 183 } 184 185 impl TryFrom<&[u8]> for EddsaPublicKey { 186 type Error = EddsaPublicKeyError; 187 188 fn try_from(value: &[u8]) -> Result<Self, Self::Error> { 189 let encoded = Base32::try_from(value)?; 190 Self::try_from(encoded) 191 } 192 } 193 194 impl TryFrom<[u8; 32]> for EddsaPublicKey { 195 type Error = EddsaPublicKeyError; 196 197 fn try_from(value: [u8; 32]) -> Result<Self, Self::Error> { 198 let encoded = Base32::from(value); 199 Self::try_from(encoded) 200 } 201 } 202 203 impl TryFrom<Base32<32>> for EddsaPublicKey { 204 type Error = EddsaPublicKeyError; 205 206 fn try_from(value: Base32<32>) -> Result<Self, Self::Error> { 207 ParsedPublicKey::new(&signature::ED25519, value.as_ref())?; 208 Ok(Self(value)) 209 } 210 } 211 212 impl EddsaPublicKey { 213 pub fn rand() -> EddsaPublicKey { 214 let signing_key = Ed25519KeyPair::generate().unwrap(); 215 let bytes: [u8; 32] = signing_key.public_key().as_ref().try_into().unwrap(); 216 Self(Base32::from(bytes)) 217 } 218 } 219 220 impl sqlx::Type<sqlx::Postgres> for EddsaPublicKey { 221 fn type_info() -> sqlx::postgres::PgTypeInfo { 222 <Base32<32>>::type_info() 223 } 224 } 225 226 impl<'q> sqlx::Encode<'q, sqlx::Postgres> for EddsaPublicKey { 227 fn encode_by_ref( 228 &self, 229 buf: &mut sqlx::postgres::PgArgumentBuffer, 230 ) -> Result<sqlx::encode::IsNull, sqlx::error::BoxDynError> { 231 self.0.encode_by_ref(buf) 232 } 233 } 234 235 impl<'r> sqlx::Decode<'r, sqlx::Postgres> for EddsaPublicKey { 236 fn decode(value: sqlx::postgres::PgValueRef<'r>) -> Result<Self, sqlx::error::BoxDynError> { 237 let raw = <Base32<32>>::decode(value)?; 238 Ok(Self(raw)) 239 } 240 }