Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 10 additions & 13 deletions client/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use common::{
read_object_into_headers_sync, Hash, Header, Mode, ObjectType, BLOB_KEY, INDEX_KEY, TREE_KEY,
};
use rayon::prelude::*;
use sha2::{Digest, Sha512};
use sha2::{Digest, Sha256};
use std::{
collections::HashMap,
fs::{create_dir, create_dir_all, read_dir, File},
Expand Down Expand Up @@ -202,7 +202,7 @@ impl<'a> CacheObject<'a> {

let mode = Mode::from_str(mode).expect("valid mode");

let mut hash: [u8; 64] = [0; 64];
let mut hash: [u8; 32] = [0; 32];
file.read_exact(&mut hash).expect("file to contain hash");

let hash = Hash::from(hash);
Expand Down Expand Up @@ -306,7 +306,7 @@ impl Object for Index {

fn get_hash(&self) -> Hash {
let body = self.get_body();
let mut hasher = Sha512::new();
let mut hasher = Sha256::new();
write!(hasher, "{}{}", self.get_prefix(), body).unwrap();
Hash::from(hasher)
}
Expand Down Expand Up @@ -425,7 +425,7 @@ impl Object for Tree {

fn get_hash(&self) -> Hash {
let body = self.get_body();
let mut hasher = Sha512::new();
let mut hasher = Sha256::new();
write!(hasher, "{}", self.get_prefix()).unwrap();
hasher
.write_all(&body)
Expand Down Expand Up @@ -487,7 +487,7 @@ impl Blob {
let size = src.metadata().unwrap().len();
let prefix = format!("{} {}\0", BLOB_KEY, size);

let mut hasher = Sha512::new();
let mut hasher = Sha256::new();
hasher.write_all(prefix.as_bytes()).unwrap();

let f = File::open(src).unwrap();
Expand Down Expand Up @@ -543,7 +543,7 @@ impl Object for Blob {
}

fn get_hash(&self) -> Hash {
let mut hasher = Sha512::new();
let mut hasher = Sha256::new();
hasher.write_all(self.get_prefix().as_bytes()).unwrap();

let f = File::open(&self.file).unwrap();
Expand Down Expand Up @@ -1034,7 +1034,7 @@ fn unpack_archive(cache: &Path, path: &Path) -> anyhow::Result<()> {
let index_data = archive.index.to_data();
let index_header = Header::new(ObjectType::Index, index_data.len() as u64);

let mut hasher = Sha512::new();
let mut hasher = Sha256::new();
hasher.write_all(index_header.to_string().as_bytes())?;
hasher.write_all(&index_data)?;
assert!(Hash::from(hasher) == archive.hash);
Expand Down Expand Up @@ -1377,21 +1377,18 @@ mod tests {
let mut reader = BufReader::new(f);
let archive = Archive::<RawEntryData>::from_data(&mut reader).expect("archive to parse");

// Archive hash must match the SHA-512 of the index header + body bytes —
// the same integrity invariant `unpack_archive` enforces when restoring
// into a store. This catches mismatches between archive.hash and
// archive.index without needing a separate reference build.
// Archive hash must match the SHA-256 of the index header + body bytes
let index_data = archive.index.to_data();
let index_header = Header::new(ObjectType::Index, index_data.len() as u64);
let mut hasher = Sha512::new();
let mut hasher = Sha256::new();
hasher
.write_all(index_header.to_string().as_bytes())
.unwrap();
hasher.write_all(&index_data).unwrap();
assert_eq!(
archive.hash,
Hash::from(hasher),
"archive hash must equal sha512(index header + body)"
"archive hash must equal Sha256(index header + body)"
);

// Body has 1 tree + 3 blobs = 4 entries (index is in the archive header, not body).
Expand Down
10 changes: 5 additions & 5 deletions common/src/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use anyhow::anyhow;
use futures::AsyncReadExt;
use lzma_rust2::LzmaOptions;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha512};
use sha2::{Digest, Sha256};

use crate::{
object_body::{Index, Object},
Expand Down Expand Up @@ -229,7 +229,7 @@ where
.try_into()
.map_err(|_| anyhow!("Invalid Compression"))?;

let mut hash: [u8; 64] = [0; 64];
let mut hash: [u8; 32] = [0; 32];
reader.read_exact(&mut hash)?;
let hash: Hash = hash.into();

Expand Down Expand Up @@ -444,7 +444,7 @@ where
break;
}

let mut hash: [u8; 64] = [0; 64];
let mut hash: [u8; 32] = [0; 32];
reader.read_exact(&mut hash)?;
let hash: Hash = hash.into();

Expand Down Expand Up @@ -476,7 +476,7 @@ where
let mut data: Vec<u8> = vec![0; amount as usize];
reader.read_exact(&mut data[..])?;

let mut hasher = Sha512::new();
let mut hasher = Sha256::new();
hasher.write_all(&data)?;
assert!(Hash::from(hasher) == entry.hash);

Expand All @@ -499,7 +499,7 @@ mod tests {
use std::collections::HashMap;

fn empty_archive(compression: CompressionAlgorithm) -> Archive<RawEntryData> {
let zero = Hash::from([0u8; 64]);
let zero = Hash::from([0u8; 32]);
Archive {
header: HEADER,
compression,
Expand Down
54 changes: 25 additions & 29 deletions common/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer, Serialize};
use sha2::digest::FixedOutput;

use sha2::Sha512;
use sha2::Sha256;
use std::fmt::{self, Debug, Display};
use std::path::{Path, PathBuf};
use std::str::FromStr;
// use std::hash::Hash;

#[derive(Clone, Serialize)]
pub struct Hash {
// Sha512 Hash value
// Sha256 Hash value
#[serde(skip)]
pub hash: [u8; 64],
pub hash: [u8; 32],
hash_string: String,
}

Expand All @@ -27,13 +27,13 @@ impl Hash {
}

pub fn from_string(value: &str) -> Option<Self> {
if value.len() != 128 {
if value.len() != 64 {
return None;
}

let hash = hex::decode(value).ok()?;

if hash.len() != 64 {
if hash.len() != 32 {
return None;
}

Expand All @@ -56,7 +56,7 @@ impl Hash {
return None;
}

if filename.len() != 126 {
if filename.len() != 62 {
return None;
}

Expand Down Expand Up @@ -90,13 +90,11 @@ impl TryFrom<String> for Hash {
type Error = anyhow::Error;

fn try_from(value: String) -> Result<Self, Self::Error> {
if value.len() != 128 {
return Err(anyhow!(
"Invalid length. Hash has to be 128 characters long"
));
if value.len() != 64 {
return Err(anyhow!("Invalid length. Hash has to be 64 characters long"));
}

let mut hash = [0u8; 64];
let mut hash = [0u8; 32];
hex::decode_to_slice(&value, &mut hash)?;

Ok(Self {
Expand All @@ -110,13 +108,11 @@ impl TryFrom<&str> for Hash {
type Error = anyhow::Error;

fn try_from(value: &str) -> Result<Self, Self::Error> {
if value.len() != 128 {
return Err(anyhow!(
"Invalid length. Hash has to be 128 characters long"
));
if value.len() != 64 {
return Err(anyhow!("Invalid length. Hash has to be 64 characters long"));
}

let mut hash = [0u8; 64];
let mut hash = [0u8; 32];
hex::decode_to_slice(value, &mut hash)?;

Ok(Self {
Expand All @@ -130,30 +126,30 @@ impl TryFrom<&[u8]> for Hash {
type Error = anyhow::Error;

fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
if value.len() != 64 {
return Err(anyhow!("Invalid length. Slice must be 64 bytes long"));
if value.len() != 32 {
return Err(anyhow!("Invalid length. Slice must be 32 bytes long"));
}

let data: [u8; 64] = value.try_into()?;
let data: [u8; 32] = value.try_into()?;
Ok(Self {
hash_string: hex::encode(value),
hash: data,
})
}
}

impl From<[u8; 64]> for Hash {
fn from(value: [u8; 64]) -> Self {
impl From<[u8; 32]> for Hash {
fn from(value: [u8; 32]) -> Self {
Self {
hash_string: hex::encode(value),
hash: value,
}
}
}

impl From<Sha512> for Hash {
fn from(value: Sha512) -> Self {
Self::from(Into::<[u8; 64]>::into(value.finalize_fixed()))
impl From<Sha256> for Hash {
fn from(value: Sha256) -> Self {
Self::from(Into::<[u8; 32]>::into(value.finalize_fixed()))
}
}

Expand All @@ -180,17 +176,17 @@ impl<'de> Deserialize<'de> for Hash {
type Value = Hash;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("Sha512 hex string Hash")
formatter.write_str("Sha256 hex string Hash")
}

fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
if value.len() != 128 {
if value.len() != 64 {
return Err(de::Error::invalid_length(
value.len(),
&"A hex string with 128 characters",
&"A hex string with 64 characters",
));
}

Expand All @@ -201,10 +197,10 @@ impl<'de> Deserialize<'de> for Hash {
where
E: serde::de::Error,
{
if value.len() != 128 {
if value.len() != 64 {
return Err(de::Error::invalid_length(
value.len(),
&"A hex string with 128 characters",
&"A hex string with 64 characters",
));
}

Expand Down
4 changes: 2 additions & 2 deletions common/src/object.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{Hash, Header};
use anyhow::{anyhow, Result};
use sha2::{Digest, Sha512};
use sha2::{Digest, Sha256};
use std::io::{BufReader, Read, Write};

pub struct Object {
Expand All @@ -10,7 +10,7 @@ pub struct Object {

impl Object {
pub fn to_hash(&self) -> Hash {
let mut hasher = Sha512::new();
let mut hasher = Sha256::new();
hasher
.write_all(self.header.to_string().as_bytes())
.expect("Out of Memory");
Expand Down
4 changes: 2 additions & 2 deletions docs/designs/design.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Design

The ArtifactRepository design is based on a SHA2-512 Merkel Tree which serves as the foundation of the Artifact. Each file within an Artifact is content addressed by its sha512 hash and directories are stored in an identical format to git. In general the object structure closely matches that of git.
The ArtifactRepository design is based on a SHA2-256 Merkel Tree which serves as the foundation of the Artifact. Each file within an Artifact is content addressed by its sha256 hash and directories are stored in an identical format to git. In general the object structure closely matches that of git.

The very top level of an Artifact is called an **Index** (git calls it a commit). This defines the artifact and contains any and all relevant metadata, such as the timestamp of creation. But since it simply contains any and all metadata in a simple key value format similar to HTTP headers, it allows for the same level of flexibility and metadata to be attached to an index.
Some possibilities could include:
Expand Down Expand Up @@ -45,7 +45,7 @@ It is structured as follows:
| [u8; 4] | header / magic number |
| [u8; 1] | version |
| [u8; 2] | compression method |
| [u8; 64] | SHA2 512 index hash |
| [u8; 32] | SHA2 256 index hash |
| [u8; N] | index data |
| [u8; 1] | null byte |
| [u8; N] | data (compressed with above method) |
Expand Down
2 changes: 1 addition & 1 deletion server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ impl From<std::io::Error> for ErrorResult {

// let file = File::create(path).await?;
// let mut writer = BufWriter::new(file).compat_write();
// let mut hasher = Sha512::new();
// let mut hasher = Sha256::new();

// header.write_to(&mut hasher)?;
// header.write_to_async(&mut writer).await?;
Expand Down
Loading