Mirror of https://github.com/roostorg/osprey github.com/roostorg/osprey
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 106145d75ff4dc44f9ce3a2de38ab39bfbca6689 98 lines 3.2 kB view raw
1use anyhow::{anyhow, Result}; 2use base64::engine::Engine as _; 3use prost::Message; 4use tink_aead::subtle::AesGcm; 5use tink_core::Aead; 6use tonic::codegen::InterceptedService; 7 8use crate::gcloud::auth::AuthorizationHeaderInterceptor; 9use crate::gcloud::google::crypto::tink::AesGcmKey; 10use crate::gcloud::google::kms::v1 as proto; 11use crate::gcloud::google::kms::v1::key_management_service_client::KeyManagementServiceClient; 12use crate::gcloud::grpc::connection::Connection; 13 14pub const GOOGLE_KMS_DOMAIN: &str = "cloudkms.googleapis.com"; 15 16const GCP_PREFIX: &str = "gcp-kms://"; 17 18impl Connection { 19 pub fn create_kms_aes_gcm_envelope( 20 &self, 21 key_uri: String, 22 associated_data: Vec<u8>, 23 base64_encoded: bool, 24 ) -> Result<AesGcmEnvelope> { 25 let key_uri = key_uri 26 .strip_prefix(GCP_PREFIX) 27 .ok_or_else(|| anyhow!("key uri must start with {}", GCP_PREFIX))?; 28 Ok(AesGcmEnvelope { 29 kms_client: self.create_kms_client(), 30 key_uri: key_uri.into(), 31 associated_data, 32 base64_encoded, 33 }) 34 } 35 36 fn create_kms_client( 37 &self, 38 ) -> KeyManagementServiceClient< 39 InterceptedService<tonic::transport::Channel, AuthorizationHeaderInterceptor>, 40 > { 41 KeyManagementServiceClient::with_interceptor( 42 self.channel.clone(), 43 self.authorization_header_interceptor.clone(), 44 ) 45 } 46} 47 48/// Reimplements some logic from tink-rust (https://github.com/project-oak/tink-rust) because the library doesn't 49/// work with async code. 50pub struct AesGcmEnvelope { 51 kms_client: KeyManagementServiceClient< 52 InterceptedService<tonic::transport::Channel, AuthorizationHeaderInterceptor>, 53 >, 54 key_uri: String, 55 associated_data: Vec<u8>, 56 base64_encoded: bool, 57} 58 59impl AesGcmEnvelope { 60 // TODO: implement encrypt 61 62 pub async fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>> { 63 let ciphertext_decoded = if self.base64_encoded { 64 Some(base64::engine::general_purpose::STANDARD.decode(ciphertext)?) 65 } else { 66 None 67 }; 68 69 let ciphertext = ciphertext_decoded 70 .as_ref() 71 .map(Vec::as_slice) 72 .unwrap_or(ciphertext); 73 74 let enc_dek_len = u32::from_be_bytes(ciphertext[..4].try_into()?) as usize; 75 let ciphertext = &ciphertext[4..]; 76 77 let encrypted_dek = &ciphertext[..enc_dek_len]; 78 let payload = &ciphertext[enc_dek_len..]; 79 80 let decrypt_req = proto::DecryptRequest { 81 name: self.key_uri.clone(), 82 ciphertext: encrypted_dek.to_vec(), 83 ..Default::default() 84 }; 85 86 let mut client_clone = self.kms_client.clone(); 87 88 let decrypt_res = client_clone.decrypt(decrypt_req).await?.into_inner(); 89 90 let data_encryption_key = AesGcmKey::decode(decrypt_res.plaintext.as_slice())?; 91 let aes_gcm = AesGcm::new(&data_encryption_key.key_value) 92 .map_err(|e| anyhow!("failed initializing AesGcm key object: {:#?}", e))?; 93 94 Ok(aes_gcm 95 .decrypt(payload, &self.associated_data) 96 .map_err(|e| anyhow!("failed decrypting payload: {:#?}", e))?) 97 } 98}