JakeDern commented on PR #585:
URL:
https://github.com/apache/arrow-rs-object-store/pull/585#issuecomment-3760929295
@tustvold Tried it out this morning, it worked great for me - Thank you for
taking this up!
I tried it with both the built-in ring implementation and with a quick
openssl implementation. Here it is in case you would like to include something
similar as an example:
```rust
use object_store::azure::MicrosoftAzureBuilder;
use object_store::client::{
CryptoProvider, DigestAlgorithm, DigestContext, HmacContext, Signer,
SigningAlgorithm,
};
use object_store::path::Path;
use object_store::{ObjectStore, ObjectStoreExt, Result};
use openssl::hash::MessageDigest;
use openssl::pkey::{PKey, Private};
use openssl::sign::Signer as OpenSslSigner;
use std::sync::Arc;
#[derive(Debug, thiserror::Error)]
pub enum OpenSslCryptoError {
#[error("OpenSSL error: {0}")]
OpenSsl(#[from] openssl::error::ErrorStack),
#[error("No RSA key found in PEM file")]
MissingKey,
}
impl From<OpenSslCryptoError> for object_store::Error {
fn from(value: OpenSslCryptoError) -> Self {
Self::Generic {
store: "OpenSslCryptoProvider",
source: Box::new(value),
}
}
}
#[derive(Debug, Default)]
pub struct OpenSslCryptoProvider;
impl CryptoProvider for OpenSslCryptoProvider {
fn digest(&self, algorithm: DigestAlgorithm) -> Result<Box<dyn
DigestContext>> {
let md = match algorithm {
DigestAlgorithm::Sha256 => MessageDigest::sha256(),
_ => unimplemented!("unsupported digest algorithm: {:?}",
algorithm),
};
let hasher =
openssl::hash::Hasher::new(md).map_err(OpenSslCryptoError::from)?;
Ok(Box::new(OpenSslDigestContext {
hasher,
output: Vec::new(),
}))
}
fn hmac(&self, algorithm: DigestAlgorithm, secret: &[u8]) ->
Result<Box<dyn HmacContext>> {
let md = match algorithm {
DigestAlgorithm::Sha256 => MessageDigest::sha256(),
_ => unimplemented!("unsupported digest algorithm: {:?}",
algorithm),
};
let key = PKey::hmac(secret).map_err(OpenSslCryptoError::from)?;
let signer = OpenSslSigner::new(md,
&key).map_err(OpenSslCryptoError::from)?;
Ok(Box::new(OpenSslHmacContext {
signer,
output: Vec::new(),
}))
}
fn sign(&self, algorithm: SigningAlgorithm, pem: &[u8]) ->
Result<Box<dyn Signer>> {
match algorithm {
SigningAlgorithm::RS256 => {
let key =
PKey::private_key_from_pem(pem).map_err(OpenSslCryptoError::from)?;
Ok(Box::new(OpenSslRsaSigner { key }))
}
_ => unimplemented!("unsupported signing algorithm: {:?}",
algorithm),
}
}
}
struct OpenSslDigestContext {
hasher: openssl::hash::Hasher,
output: Vec<u8>,
}
impl DigestContext for OpenSslDigestContext {
fn update(&mut self, data: &[u8]) {
let _ = self.hasher.update(data);
}
fn finish(&mut self) -> Result<&[u8]> {
let digest = self.hasher.finish().map_err(OpenSslCryptoError::from)?;
self.output = digest.to_vec();
Ok(&self.output)
}
}
struct OpenSslHmacContext {
signer: OpenSslSigner<'static>,
output: Vec<u8>,
}
impl HmacContext for OpenSslHmacContext {
fn update(&mut self, data: &[u8]) {
let _ = self.signer.update(data);
}
fn finish(&mut self) -> Result<&[u8]> {
self.output = self
.signer
.sign_to_vec()
.map_err(OpenSslCryptoError::from)?;
Ok(&self.output)
}
}
#[derive(Debug)]
struct OpenSslRsaSigner {
key: PKey<Private>,
}
impl Signer for OpenSslRsaSigner {
fn sign(&self, data: &[u8]) -> Result<Vec<u8>> {
let mut signer = OpenSslSigner::new(MessageDigest::sha256(),
&self.key)
.map_err(OpenSslCryptoError::from)?;
signer.update(data).map_err(OpenSslCryptoError::from)?;
let signature =
signer.sign_to_vec().map_err(OpenSslCryptoError::from)?;
Ok(signature)
}
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
let crypto_provider = Arc::new(OpenSslCryptoProvider);
let azure = MicrosoftAzureBuilder::new()
.with_account("mystorageaccount")
.with_access_key("myaccesskey")
.with_container_name("mycontainer")
.with_crypto_provider(crypto_provider)
.build()?;
// Write a file
let path = Path::from("example_openssl.txt");
let data = bytes::Bytes::from("Hello from OpenSSL crypto provider!");
azure.put(&path, data.into()).await?;
// Read it back
let result = azure.get(&path).await?;
let bytes = result.bytes().await?;
println!("Content: {}", String::from_utf8_lossy(&bytes));
Ok(())
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]