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:
parent
fc71b73ce2
commit
096ccec741
11
Cargo.toml
11
Cargo.toml
@ -11,10 +11,11 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.32"
|
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"
|
base64 = "0.12.3"
|
||||||
confy = "0.4.0"
|
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"
|
||||||
|
48
src/lib.rs
48
src/lib.rs
@ -1,9 +1,12 @@
|
|||||||
use anyhow::Result;
|
use anyhow::{anyhow, Result};
|
||||||
|
use isahc::http::StatusCode;
|
||||||
use isahc::prelude::*;
|
use isahc::prelude::*;
|
||||||
use openssl::hash::MessageDigest;
|
use rsa::pkcs1::{DecodeRsaPrivateKey, EncodeRsaPrivateKey};
|
||||||
use openssl::pkey::PKey;
|
use rsa::RsaPrivateKey;
|
||||||
use openssl::rsa::Rsa;
|
use rsa::pkcs1v15::SigningKey;
|
||||||
use openssl::sign::Signer;
|
use rsa::pkcs8::{EncodePublicKey, LineEnding};
|
||||||
|
use rsa::signature::RandomizedSigner;
|
||||||
|
use rsa::sha2::Sha256;
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
const BASE: &str = "https://api.bunq.com";
|
const BASE: &str = "https://api.bunq.com";
|
||||||
@ -47,12 +50,11 @@ struct UserPerson {
|
|||||||
id: i64,
|
id: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign<K: openssl::pkey::HasPrivate>(body: &str, key: &PKey<K>) -> Result<String> {
|
fn sign(body: &str, key: &RsaPrivateKey) -> Result<String> {
|
||||||
let mut signer = Signer::new(MessageDigest::sha256(), key)?;
|
let signing_key = SigningKey::<Sha256>::new(key.clone());
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
let sig = signer.sign_oneshot_to_vec(body.as_bytes())?;
|
let signature = signing_key.sign_with_rng(&mut rng, body.as_bytes());
|
||||||
|
Ok(base64::encode(signature.to_string()))
|
||||||
Ok(base64::encode(&sig))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -111,7 +113,7 @@ pub struct BunqConfig {
|
|||||||
}
|
}
|
||||||
pub struct BunqConfigReady {
|
pub struct BunqConfigReady {
|
||||||
token: String,
|
token: String,
|
||||||
keypair: PKey<openssl::pkey::Private>,
|
keypair: RsaPrivateKey,
|
||||||
user_id: i64,
|
user_id: i64,
|
||||||
}
|
}
|
||||||
impl BunqConfig {
|
impl BunqConfig {
|
||||||
@ -126,15 +128,14 @@ impl BunqConfig {
|
|||||||
let api_key = &self.api_key;
|
let api_key = &self.api_key;
|
||||||
|
|
||||||
let keypair = if let Some(state) = &self.state {
|
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 {
|
} else {
|
||||||
let rsa = Rsa::generate(2048)?;
|
let mut rng = rand::thread_rng();
|
||||||
let pem_private = rsa.private_key_to_pem()?;
|
|
||||||
let pem_private = String::from_utf8(pem_private)?;
|
|
||||||
|
|
||||||
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 {
|
let body = Installation {
|
||||||
client_public_key: &pem_public,
|
client_public_key: &pem_public,
|
||||||
@ -157,9 +158,15 @@ impl BunqConfig {
|
|||||||
.header("X-Bunq-Client-Authentication", &token)
|
.header("X-Bunq-Client-Authentication", &token)
|
||||||
.body(body)?
|
.body(body)?
|
||||||
.send()?;
|
.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()?;
|
self.save()?;
|
||||||
|
|
||||||
keypair
|
keypair
|
||||||
@ -175,6 +182,7 @@ impl BunqConfig {
|
|||||||
.send()?
|
.send()?
|
||||||
.text()?;
|
.text()?;
|
||||||
let r: SessionServerResponse = deserialize_retarded_response(&response)?.response;
|
let r: SessionServerResponse = deserialize_retarded_response(&response)?.response;
|
||||||
|
|
||||||
Ok(BunqConfigReady {
|
Ok(BunqConfigReady {
|
||||||
keypair,
|
keypair,
|
||||||
token: r.token.token,
|
token: r.token.token,
|
||||||
|
Loading…
Reference in New Issue
Block a user