libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit b3bb50692eaf339ba3989b83bb0fbf0f69f7e95a
parent 9d4f2e889eed5ab35ed11b9629c72bedf940daf3
Author: Antoine A <>
Date:   Wed, 16 Sep 2026 14:01:30 +0200

common: more fixes

Diffstat:
Mlibeufin-bank/src/api/token.rs | 4+++-
Mlibeufin-ebics/src/crypto.rs | 17+++++++++--------
Mlibeufin-ebics/src/ebics.rs | 16++++++----------
Mlibeufin-ebisync/src/api.rs | 3++-
Mlibeufin-nexus/src/api.rs | 6+++++-
5 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/libeufin-bank/src/api/token.rs b/libeufin-bank/src/api/token.rs @@ -169,8 +169,10 @@ pub fn token_api() -> Router<Arc<BankState>> { async |UserAuth { token, .. }: UserRAuth, State(state): State<Arc<BankState>>| { if let Some(token) = token { db::token::delete(&state.db, &token).await?; + ApiResult::Ok(NoContent) + } else { + ApiResult::Err(bad_request("Basic auth not supported here")) } - ApiResult::Ok(NoContent) }, ), ) diff --git a/libeufin-ebics/src/crypto.rs b/libeufin-ebics/src/crypto.rs @@ -155,22 +155,23 @@ pub fn encrypt_ebics_e002(transaction_key: &[u8; 16], mut data: Vec<u8>) -> Vec< data } -pub fn decrypt_ebics_e002(transaction_key: &DecryptingKey, mut encrypted_data: Vec<u8>) -> Vec<u8> { +pub fn decrypt_ebics_e002( + transaction_key: &DecryptingKey, + mut encrypted_data: Vec<u8>, +) -> Result<Vec<u8>, ()> { let iv = FixedLength::from([0u8; 16]); - let plaintext = transaction_key - .decrypt(&mut encrypted_data, DecryptionContext::Iv128(iv)) - .unwrap(); + let plaintext = transaction_key.decrypt(&mut encrypted_data, DecryptionContext::Iv128(iv))?; // Strip X9.23 / ANSI X9.23 padding: // The last byte holds the number of padding bytes to remove. - let pad_len = *plaintext.last().unwrap() as usize; + let pad_len = *plaintext.last().ok_or(())? as usize; if pad_len == 0 || pad_len > 16 || pad_len > plaintext.len() { - panic!("WTF"); + return Err(()); } let decoded = plaintext.len() - pad_len; encrypted_data.truncate(decoded); - encrypted_data + Ok(encrypted_data) } pub fn decrypt_ebics_e002_key( @@ -232,7 +233,7 @@ mod test { ); let enc = encrypt_ebics_e002(&tx_key, data.to_vec()); let key = decrypt_ebics_e002_key(key, &encrypted_key); - let dec = decrypt_ebics_e002(&key, enc); + let dec = decrypt_ebics_e002(&key, enc).unwrap(); assert_eq!(&data, &dec.as_slice()); } diff --git a/libeufin-ebics/src/ebics.rs b/libeufin-ebics/src/ebics.rs @@ -38,7 +38,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use sqlx::PgPool; use taler_common::encoding::base64; use thiserror::Error; -use tracing::{debug, info, trace, warn}; +use tracing::{debug, info, trace}; use crate::{ cli::EbicsLogs, @@ -492,14 +492,8 @@ impl<'a> EbicsClient<'a> { // Receipt phase ctx = ctx.receipt(&tx_id); let xml = receipt(&self.cfg, client, order, &tx_id, res.is_ok() && !peek); - if let Err(e) = async { - self.post_bts(xml, &ctx, &bank.auth, parse_receipt).await?; - ebics_remove(db, &tx_id).await.ctx(&ctx) - } - .await - { - warn!(target: "ebics", "{e}") - } + self.post_bts(xml, &ctx, &bank.auth, parse_receipt).await?; + ebics_remove(db, &tx_id).await.ctx(&ctx)?; res } @@ -570,6 +564,8 @@ pub enum DecDeErr { Digest, #[error(transparent)] Key(#[from] KeyRejected), + #[error("E002 decryption failed")] + Decrypt, } /** Decrypts and decompresses EBICS BTS payload */ @@ -581,7 +577,7 @@ fn decrypt_and_decompress_payload( let enc_key = PrivateDecryptingKey::from_pkcs8(key_pair.as_der().unwrap().as_ref())?; let tx_key = decrypt_ebics_e002_key(enc_key, &encryption_info.tx_key); let mut decoder = ZlibDecoder::new(Vec::new()); - let decrypted = decrypt_ebics_e002(&tx_key, payload); + let decrypted = decrypt_ebics_e002(&tx_key, payload).map_err(|_| DecDeErr::Decrypt)?; decoder.write_all(&decrypted)?; Ok(decoder.finish()?) } diff --git a/libeufin-ebisync/src/api.rs b/libeufin-ebisync/src/api.rs @@ -138,7 +138,7 @@ pub fn sync_api(state: Arc<EbisyncState>, spa: &str, auth: AuthMethod) -> Router .map_err(|_| bad_request("Invalid order field"))?, ); } - _ => { + "file" => { // treat as file let data = field .bytes() @@ -147,6 +147,7 @@ pub fn sync_api(state: Arc<EbisyncState>, spa: &str, auth: AuthMethod) -> Router xml = Some(data); } + _ => {} } } diff --git a/libeufin-nexus/src/api.rs b/libeufin-nexus/src/api.rs @@ -357,7 +357,11 @@ impl Revenue for NexusApi { impl PreparedTransfer for NexusApi { fn supported_formats(&self) -> &[SubjectFormat] { - &[SubjectFormat::SIMPLE] + if self.qr_iban.is_some() { + &[SubjectFormat::SIMPLE, SubjectFormat::CH_QR_BILL] + } else { + &[SubjectFormat::SIMPLE] + } } async fn registration(&self, req: RegistrationRequest) -> ApiResult<RegistrationResponse> {