Use crate rsa instead of openssl

The rsa crate contains a pure rust implementation of the same
primitives.

This helps with cross platform support, such as Windows.

Signed-off-by: Jacob Kiers <code@kiers.eu>
This commit is contained in:
Jacob Kiers 2024-02-29 19:20:24 +01:00
parent fc71b73ce2
commit 096ccec741
2 changed files with 34 additions and 25 deletions

View File

@ -11,10 +11,11 @@ edition = "2018"
[dependencies]
anyhow = "1.0.32"
isahc = { version = "0.9.8", features = ["json"] }
dotenv = "0.15.0"
openssl = "0.10.30"
serde_json = "1.0.57"
serde = { version = "1.0.116", features = ["derive"] }
base64 = "0.12.3"
confy = "0.4.0"
dotenv = "0.15.0"
isahc = { version = "0.9.8", features = ["json"] }
rand = "0.8.5"
rsa = { version = "0.9.6", features = ["sha2"] }
serde = { version = "1.0.116", features = ["derive"] }
serde_json = "1.0.57"

View File

@ -1,9 +1,12 @@
use anyhow::Result;
use anyhow::{anyhow, Result};
use isahc::http::StatusCode;
use isahc::prelude::*;
use openssl::hash::MessageDigest;
use openssl::pkey::PKey;
use openssl::rsa::Rsa;
use openssl::sign::Signer;
use rsa::pkcs1::{DecodeRsaPrivateKey, EncodeRsaPrivateKey};
use rsa::RsaPrivateKey;
use rsa::pkcs1v15::SigningKey;
use rsa::pkcs8::{EncodePublicKey, LineEnding};
use rsa::signature::RandomizedSigner;
use rsa::sha2::Sha256;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
const BASE: &str = "https://api.bunq.com";
@ -47,12 +50,11 @@ struct UserPerson {
id: i64,
}
fn sign<K: openssl::pkey::HasPrivate>(body: &str, key: &PKey<K>) -> Result<String> {
let mut signer = Signer::new(MessageDigest::sha256(), key)?;
let sig = signer.sign_oneshot_to_vec(body.as_bytes())?;
Ok(base64::encode(&sig))
fn sign(body: &str, key: &RsaPrivateKey) -> Result<String> {
let signing_key = SigningKey::<Sha256>::new(key.clone());
let mut rng = rand::thread_rng();
let signature = signing_key.sign_with_rng(&mut rng, body.as_bytes());
Ok(base64::encode(signature.to_string()))
}
#[derive(Deserialize)]
@ -111,7 +113,7 @@ pub struct BunqConfig {
}
pub struct BunqConfigReady {
token: String,
keypair: PKey<openssl::pkey::Private>,
keypair: RsaPrivateKey,
user_id: i64,
}
impl BunqConfig {
@ -126,15 +128,14 @@ impl BunqConfig {
let api_key = &self.api_key;
let keypair = if let Some(state) = &self.state {
PKey::private_key_from_pem(state.pem_private.as_bytes())?
RsaPrivateKey::from_pkcs1_pem(&*state.pem_private)?
} else {
let rsa = Rsa::generate(2048)?;
let pem_private = rsa.private_key_to_pem()?;
let pem_private = String::from_utf8(pem_private)?;
let mut rng = rand::thread_rng();
let keypair = PKey::from_rsa(rsa)?;
let bits = 2048;
let keypair = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
let pem_public = String::from_utf8(keypair.public_key_to_pem()?)?;
let pem_public = keypair.to_public_key().to_public_key_pem(LineEnding::CRLF)?;
let body = Installation {
client_public_key: &pem_public,
@ -157,9 +158,15 @@ impl BunqConfig {
.header("X-Bunq-Client-Authentication", &token)
.body(body)?
.send()?;
println!("{}", response.text()?);
self.state = Some(AppState { pem_private, token });
let response_text = response.text()?;
println!("{}", response_text);
if response.status() != StatusCode::OK {
return Err(anyhow!(response_text));
}
self.state = Some(AppState { pem_private: keypair.to_pkcs1_pem(LineEnding::CRLF)?.to_string(), token });
self.save()?;
keypair
@ -175,6 +182,7 @@ impl BunqConfig {
.send()?
.text()?;
let r: SessionServerResponse = deserialize_retarded_response(&response)?.response;
Ok(BunqConfigReady {
keypair,
token: r.token.token,