Skip to content

Commit

Permalink
Merge pull request #13 from atsign-foundation/cpswan-ossf-fixes
Browse files Browse the repository at this point in the history
chore: ossf fixes
  • Loading branch information
cpswan authored Dec 1, 2023
2 parents 5c037ee + b8329f2 commit affb087
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 54 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/clippy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Clippy
on:
workflow_dispatch:
push:
branches: [trunk]
pull_request:
branches: [trunk]

permissions:
contents: read

jobs:
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Install Rust
run: rustup update stable

- name: Install Clippy
run: rustup component add clippy

- name: Run Clippy
run: cargo clippy
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
## v0.2.1

- Fix linter warnings
- Add linter workflow
- Add OpenSSF Best Practices badge

## v0.2.0

- Interoperability with other Atsign SDKs
- Autobug workflow
- Removed direct dependency on a specific TLS client
- OpenSSF Scorecard
- create at_secrets from values

## v0.1.0

- Initial version with PKAM auth and simple data exchange
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "at_rust"
version = "0.2.0"
version = "0.2.1"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<img width=250px src="https://atsign.dev/assets/img/atPlatform_logo_gray.svg?sanitize=true">

[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/atsign-foundation/at_rust/badge)](https://api.securityscorecards.dev/projects/github.com/atsign-foundation/at_rust)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8148/badge)](https://www.bestpractices.dev/projects/8148)

# Rust SDK - (⚠️Alpha version⚠️)
This repo contains libraries, tools, samples and examples for developers who wish to work with the atPlatform from Rust code.
Expand Down
32 changes: 15 additions & 17 deletions src/at_chops/at_chops.rs → src/at_chops/chops.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use log::{info, warn};
//use log::{info, warn};

use super::utils::{
base64_decode, base64_encode, construct_aes_key, construct_rsa_private_key,
Expand All @@ -19,7 +19,7 @@ pub fn decrypt_private_key(
) -> String {
let iv: [u8; 16] = [0x00; 16];
let mut cypher = construct_aes_key(decoded_self_encryption_key, &iv);
let decoded_private_key = base64_decode(&encrypted_private_key);
let decoded_private_key = base64_decode(encrypted_private_key);

let mut output: Vec<u8> = vec![0; decoded_private_key.len()];
cypher.process(&decoded_private_key, &mut output);
Expand All @@ -36,9 +36,9 @@ pub fn decrypt_private_key(

/// Sign a given challenge with the decrypted private key.
pub fn sign_challenge(challenge: &str, decrypted_private_key: &str) -> String {
let decoded_private_key = base64_decode(&decrypted_private_key);
let decoded_private_key = base64_decode(decrypted_private_key);
let rsa_private_key = construct_rsa_private_key(&decoded_private_key);
rsa_sign(rsa_private_key, &challenge.as_bytes())
rsa_sign(rsa_private_key, challenge.as_bytes())
}

/// Cut a new symmetric key to be used when interacting with a new atSign.
Expand All @@ -49,37 +49,35 @@ pub fn create_new_shared_symmetric_key() -> String {

/// Decrypt the symmetric key with "our" private key.
pub fn decrypt_symmetric_key(encrypted_symmetric_key: &str, decrypted_private_key: &str) -> String {
let decoded_private_key = base64_decode(&decrypted_private_key);
let decoded_private_key = base64_decode(decrypted_private_key);
let rsa_private_key = construct_rsa_private_key(&decoded_private_key);
let decoded_symmetric_key = base64_decode(&encrypted_symmetric_key);
let decrypted_symmetric_key =
decrypt_symm_key_with_private_key(&rsa_private_key, &decoded_symmetric_key);
decrypted_symmetric_key
let decoded_symmetric_key = base64_decode(encrypted_symmetric_key);
decrypt_symm_key_with_private_key(&rsa_private_key, &decoded_symmetric_key)
}

/// Encrypt data with our RSA public key.
pub fn encrypt_data_with_public_key(encoded_public_key: &str, data: &str) -> String {
let decoded_public_key = base64_decode(&encoded_public_key);
let decoded_public_key = base64_decode(encoded_public_key);
let rsa_public_key = construct_rsa_public_key(&decoded_public_key);
let encrypted_data = encrypt_with_public_key(&rsa_public_key, &data.as_bytes());
let encrypted_data = encrypt_with_public_key(&rsa_public_key, data.as_bytes());
encrypted_data
}

/// Encrypt data with AES symm key.
pub fn encrypt_data_with_shared_symmetric_key(encoded_symmetric_key: &str, data: &str) -> String {
let decoded_symmetric_key = base64_decode(&encoded_symmetric_key);
let decoded_symmetric_key = base64_decode(encoded_symmetric_key);
let iv: [u8; 16] = [0x00; 16];
let mut cypher = construct_aes_key(&decoded_symmetric_key, &iv);
let encrypted_data = encrypt_data_with_aes_key(&mut cypher, &data.as_bytes());
let encrypted_data = encrypt_data_with_aes_key(&mut cypher, data.as_bytes());
base64_encode(&encrypted_data)
}

/// Decrypt data with an encoded AES symm key.
pub fn decrypt_data_with_shared_symmetric_key(encoded_symmetric_key: &str, data: &str) -> String {
let decoded_symmetric_key = base64_decode(&encoded_symmetric_key);
let decoded_symmetric_key = base64_decode(encoded_symmetric_key);
let iv: [u8; 16] = [0x00; 16];
let mut cypher = construct_aes_key(&decoded_symmetric_key, &iv);
let decoded_data = base64_decode(&data);
let decoded_data = base64_decode(data);
let decrypted_data = decrypt_data_with_aes_key(&mut cypher, &decoded_data);
String::from_utf8(decrypted_data).expect("Unable to convert to UTF-8")
}
Expand Down Expand Up @@ -115,13 +113,13 @@ mod test {
#[test]
fn decrypt_private_key_test() {
let self_encryption_key = decode_self_encryption_key(SELF_ENCRYPTION_KEY_ENCODED);
let result = decrypt_private_key(&PKAM_KEY_ENCRYPTED_AND_ENCODED, &self_encryption_key);
let result = decrypt_private_key(PKAM_KEY_ENCRYPTED_AND_ENCODED, &self_encryption_key);
assert_eq!(result, PKAM_KEY_DECRYPTED_AND_ENCODED);
}

#[test]
fn sign_challenge_test() {
let result = sign_challenge(CHALLENGE_TEXT, &PKAM_KEY_DECRYPTED_AND_ENCODED);
let result = sign_challenge(CHALLENGE_TEXT, PKAM_KEY_DECRYPTED_AND_ENCODED);
assert_eq!(result, CHALLENGE_RESULT);
}

Expand Down
2 changes: 1 addition & 1 deletion src/at_chops/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub mod at_chops;
pub mod chops;
mod b64_encoded_string;
mod utils;

27 changes: 12 additions & 15 deletions src/at_chops/utils.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::iter::repeat;
//use std::iter::repeat;

use crypto::{aes::KeySize, symmetriccipher::SynchronousStreamCipher};

use base64::{engine::general_purpose, Engine as _};
use log::info;
//use log::info;
use rsa::{
pkcs1v15::SigningKey,
pkcs8::{DecodePrivateKey, DecodePublicKey},
Expand Down Expand Up @@ -33,16 +33,14 @@ pub fn construct_aes_key(data: &[u8], iv: &[u8; 16]) -> Box<dyn SynchronousStrea

/// Construct an RSA private key from a decoded key.
pub fn construct_rsa_private_key(data: &[u8]) -> RsaPrivateKey {
let rsa_key = RsaPrivateKey::from_pkcs8_der(&data).expect("Unable to create RSA Private Key");
let rsa_key = RsaPrivateKey::from_pkcs8_der(data).expect("Unable to create RSA Private Key");
rsa_key.validate().expect("Invalid RSA Private Key");
rsa_key
}

/// Construct an RSA public key from a decoded key.
pub fn construct_rsa_public_key(data: &[u8]) -> RsaPublicKey {
let rsa_key =
RsaPublicKey::from_public_key_der(&data).expect("Unable to create RSA Public Key");
rsa_key
RsaPublicKey::from_public_key_der(data).expect("Unable to create RSA Public Key")
}

/// Sign data using an RSA private key.
Expand All @@ -53,16 +51,15 @@ pub fn rsa_sign(key: RsaPrivateKey, data: &[u8]) -> String {
let verifying_key = signing_key.verifying_key();

// Sign
let signature = signing_key.sign_with_rng(&mut rng, &data);
let signature = signing_key.sign_with_rng(&mut rng, data);
verifying_key
.verify(&data, &signature)
.verify(data, &signature)
.expect("failed to verify");
let binding = signature.to_bytes();
let signature_bytes = binding.as_ref();

// Encode signature
let sha256_signature_encoded = base64_encode(&signature_bytes);
sha256_signature_encoded
base64_encode(signature_bytes)
}

/// Create a new AES-256 key from scratch.
Expand Down Expand Up @@ -116,7 +113,7 @@ pub fn decrypt_data_with_aes_key(
data: &[u8],
) -> Vec<u8> {
let mut output: Vec<u8> = vec![0; data.len()];
aes_key.process(&data, &mut output);
aes_key.process(data, &mut output);
// Remove padding due to PkCS#7 padding used by other SDKs
let last = output.last().unwrap();
output.truncate(output.len() - usize::from(*last));
Expand Down Expand Up @@ -182,7 +179,7 @@ mod test {
#[test]
fn construct_rsa_private_key_test() {
// Arrange
let private_key = base64_decode(&PKAM_KEY_DECRYPTED_AND_ENCODED);
let private_key = base64_decode(PKAM_KEY_DECRYPTED_AND_ENCODED);
// Act
let _ = construct_rsa_private_key(&private_key);
// Assert it doesn't panic
Expand All @@ -191,7 +188,7 @@ mod test {
#[test]
fn construct_rsa_public_key_test() {
// Arrange
let public_key = base64_decode(&PUBLIC_ENCRYPTION_KEY);
let public_key = base64_decode(PUBLIC_ENCRYPTION_KEY);
// Act
let _ = construct_rsa_public_key(&public_key);
// Assert it doesn't panic
Expand All @@ -200,7 +197,7 @@ mod test {
#[test]
fn rsa_sign_test() {
// Arrange
let private_key = base64_decode(&PKAM_KEY_DECRYPTED_AND_ENCODED);
let private_key = base64_decode(PKAM_KEY_DECRYPTED_AND_ENCODED);
let rsa_key = construct_rsa_private_key(&private_key);
// Act
let decrypted = rsa_sign(rsa_key, CHALLENGE_TEXT.as_bytes());
Expand All @@ -216,7 +213,7 @@ mod test {

#[test]
fn encrypt_with_public_key_test() {
let public_key = base64_decode(&PUBLIC_ENCRYPTION_KEY);
let public_key = base64_decode(PUBLIC_ENCRYPTION_KEY);
let public_key = construct_rsa_public_key(&public_key);
let _ = encrypt_with_public_key(&public_key, &TEST_KEY_DECODED);
// Assert it doesn't panic.
Expand Down
22 changes: 11 additions & 11 deletions src/at_client.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use log::info;

use crate::at_chops::at_chops::{
use crate::at_chops::chops::{
create_new_shared_symmetric_key, decrypt_data_with_shared_symmetric_key, decrypt_symmetric_key,
encrypt_data_with_public_key, encrypt_data_with_shared_symmetric_key,
};
Expand Down Expand Up @@ -59,7 +59,7 @@ impl AtClient {
// Save for our use
let encrypted_encoded_sym_key =
encrypt_data_with_public_key(&self.secrets.encrypt_public_key, &new_key);
let _ = UpdateVerb::execute(
UpdateVerb::execute(
&mut self.tls_client,
UpdateVerbInputs::new(
&self.at_sign,
Expand All @@ -82,7 +82,7 @@ impl AtClient {
symm_key_encrypted_with_recipient_public_key
);
// Send data
let _ = UpdateVerb::execute(
UpdateVerb::execute(
&mut self.tls_client,
UpdateVerbInputs::new(
&self.at_sign,
Expand All @@ -96,9 +96,9 @@ impl AtClient {
} else if response.contains("data") {
info!("Already have a copy of the key");
// Decrypt symm key
let encrypted_symmetric_key = response.split(":").collect::<Vec<_>>()[1];
let encrypted_symmetric_key = response.split(':').collect::<Vec<_>>()[1];
symm_key =
decrypt_symmetric_key(&encrypted_symmetric_key, &self.secrets.encrypt_private_key);
decrypt_symmetric_key(encrypted_symmetric_key, &self.secrets.encrypt_private_key);
info!("Decrypted symmetric key: {}", symm_key);
} else {
return Err(AtError::new(String::from("Unknown response from server")));
Expand All @@ -110,7 +110,7 @@ impl AtClient {
UpdateVerbInputs::new(
&self.at_sign,
// TODO: Pass this in as an option somewhere
&record_id,
record_id,
&encrypted_data_to_send,
Some(&self.namespace),
None,
Expand All @@ -128,23 +128,23 @@ impl AtClient {
&mut self.tls_client,
LookupVerbInputs::new(&from, record_id, Some(&self.namespace)),
)?;
let encrypted_and_encoded_data = response.split(":").collect::<Vec<_>>()[1];
let encrypted_and_encoded_data = response.split(':').collect::<Vec<_>>()[1];
info!("Fetching symmetric key");
// Fetch symm key
let response = LookupVerb::execute(
&mut self.tls_client,
LookupVerbInputs::new(&from, "shared_key", None),
)?;
info!("Decrypting symmetric key");
let encrypted_and_encoded_symm_key = response.split(":").collect::<Vec<_>>()[1];
let encrypted_and_encoded_symm_key = response.split(':').collect::<Vec<_>>()[1];
let symm_key = decrypt_symmetric_key(
&encrypted_and_encoded_symm_key,
encrypted_and_encoded_symm_key,
&self.secrets.encrypt_private_key,
);
info!("Decrypted symmetric key: {}", symm_key);
info!("Decrypting data");
let encoded_data =
decrypt_data_with_shared_symmetric_key(&symm_key, &encrypted_and_encoded_data);
decrypt_data_with_shared_symmetric_key(&symm_key, encrypted_and_encoded_data);
info!("Decrypted data: {}", encoded_data);

Ok(())
Expand Down Expand Up @@ -183,7 +183,7 @@ fn get_at_sign_server_addr(

// Trimming to remove the newline character
let addr = addr.trim();
let addr = addr.split(":").collect::<Vec<_>>();
let addr = addr.split(':').collect::<Vec<_>>();
let host = addr[0].to_string();
let port = addr[1]
.parse::<u16>()
Expand Down
12 changes: 6 additions & 6 deletions src/at_secrets.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::at_chops::at_chops::{decode_self_encryption_key, decrypt_private_key};
use crate::at_chops::chops::{decode_self_encryption_key, decrypt_private_key};
use crate::at_error::Result;
use log::info;
use serde_json::{from_str, Value};
Expand Down Expand Up @@ -64,17 +64,17 @@ impl AtSecrets {
) -> Result<AtSecrets> {
info!("Decoding keys");
// Decode the self encrypt key from base64
let decoded_self_encrypted_key = decode_self_encryption_key(&aes_self_encrypt_key);
let decoded_self_encrypted_key = decode_self_encryption_key(aes_self_encrypt_key);

// Use the key to decrypt all the other private keys
let pkam_public_key =
decrypt_private_key(&aes_pkam_public_key, &decoded_self_encrypted_key);
decrypt_private_key(aes_pkam_public_key, &decoded_self_encrypted_key);
let pkam_private_key =
decrypt_private_key(&aes_pkam_private_key, &decoded_self_encrypted_key);
decrypt_private_key(aes_pkam_private_key, &decoded_self_encrypted_key);
let encrypt_public_key =
decrypt_private_key(&aes_encrypt_public_key, &decoded_self_encrypted_key);
decrypt_private_key(aes_encrypt_public_key, &decoded_self_encrypted_key);
let encrypt_private_key =
decrypt_private_key(&aes_encrypt_private_key, &decoded_self_encrypted_key);
decrypt_private_key(aes_encrypt_private_key, &decoded_self_encrypted_key);

info!("Keys decoded and decrypted");

Expand Down
4 changes: 2 additions & 2 deletions src/verbs/from.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use log::info;

use crate::at_chops::at_chops::sign_challenge;
use crate::at_chops::chops::sign_challenge;

use super::{prelude::*, Verb};

Expand Down Expand Up @@ -29,7 +29,7 @@ impl<'a> Verb<'a> for FromVerb {
let (_, data) = response.split_at(6);
info!("Challenge: {}", data);

let signed_challenge = sign_challenge(&data, input.priv_pkam);
let signed_challenge = sign_challenge(data, input.priv_pkam);

tls_client.send(format!("pkam:{}\n", signed_challenge))?;
let response = tls_client.read_line()?;
Expand Down
2 changes: 1 addition & 1 deletion src/verbs/lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl<'a> Verb<'a> for LookupVerb {
send_string.push_str(&format!(".{}", namespace));
}
send_string.push_str(&format!("@{}", input.to_at_sign.get_at_sign()));
send_string.push_str(&format!("\n"));
send_string.push('\n');
tls_client.send(send_string)?;
let response = tls_client.read_line()?;
Ok(response)
Expand Down

0 comments on commit affb087

Please sign in to comment.