Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
83d68a0
implements merkle tree implementation and insertion to it
onacitarhan17 Apr 13, 2022
877ba35
implements merkle tree authentication
onacitarhan17 Apr 13, 2022
e57e613
Merge branch 'master' into ozan/merkletree
onacitarhan17 Apr 13, 2022
b4cf75f
implements tests
onacitarhan17 Apr 13, 2022
2846da5
implements hash table for searching in merkle tree
onacitarhan17 Apr 17, 2022
99f469f
implements thread safety to merkle tree implementation
onacitarhan17 Apr 17, 2022
d5d5d14
fixes lint & spotbugs issues
onacitarhan17 Apr 17, 2022
1f8b40b
Merge branch 'master' into ozan/merkletree
onacitarhan17 Apr 17, 2022
29bb463
renames Merkle Tree creation function in MerkleTreeFixture.java
onacitarhan17 Apr 19, 2022
4bb13ff
Merge branch 'master' into ozan/merkletree
onacitarhan17 Apr 19, 2022
ff38dea
suppresses EI_EXPOSE_REP warnings in spotbugs
onacitarhan17 Apr 19, 2022
7c9f4d7
Merge remote-tracking branch 'origin/ozan/merkletree' into ozan/merkl…
onacitarhan17 Apr 19, 2022
f767ff8
suppresses warnings in spotbugs
onacitarhan17 Apr 19, 2022
df3b433
adds comments for unit tests
onacitarhan17 Apr 20, 2022
94cfe9b
handles exceptions on MerkleTree.java
onacitarhan17 Apr 20, 2022
d3b1343
changes how id of an entity is stored on the merkle tree, changed fro…
onacitarhan17 Apr 20, 2022
ccffc17
handles exceptions better for locks
onacitarhan17 Apr 20, 2022
cc555b4
changes get method in a way it gets the AuthenticatedEntity by id not…
onacitarhan17 Apr 20, 2022
8cdb9a2
improves thread safety check
onacitarhan17 Apr 20, 2022
205970f
improves exception handling1
onacitarhan17 Apr 20, 2022
d0f93ab
improves the hashing and how proofs are created in merkle tree
onacitarhan17 Apr 20, 2022
21cef64
applies revisions
thep2p Apr 24, 2022
a3b33b7
applies revisions
thep2p Apr 24, 2022
9d20b36
applies revisions
thep2p Apr 24, 2022
d4a77a7
applies revisions
thep2p Apr 24, 2022
8696b0f
fixes lint
thep2p Apr 24, 2022
df806a8
removes unnecessary setters
thep2p Apr 24, 2022
8b5d912
removes unnecessary setters
thep2p Apr 24, 2022
bd1ad65
fixes a java doc
thep2p Apr 24, 2022
afee4e1
applies revisions
thep2p Apr 24, 2022
b4a394b
fixes lint
thep2p Apr 24, 2022
2ad6832
applies revisions
thep2p Apr 24, 2022
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
51 changes: 49 additions & 2 deletions src/main/java/crypto/Sha3256Hasher.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,21 @@

import model.codec.EncodedEntity;
import model.crypto.Sha3256Hash;
import model.lightchain.Identifier;

/**
* Implements SHA3-256 hashing functionality.
*/
public class Sha3256Hasher implements Hasher {

private static final String HASH_ALG_SHA_3_256 = "SHA3-256";

private static byte[] concat(final byte[] e1, final byte[] e2) {
byte[] result = new byte[e1.length + e2.length];
System.arraycopy(e1, 0, result, 0, e1.length);
System.arraycopy(e2, 0, result, e1.length, e2.length);
return result;
}

/**
* Computes hash of the given encoded entity.
*
Expand All @@ -21,12 +28,52 @@ public class Sha3256Hasher implements Hasher {
*/
@Override
public Sha3256Hash computeHash(EncodedEntity e) {
return this.computeHash(e.getBytes());
}

/**
* Computes hash of the given identifier.
*
* @param id input identifier
* @return SHA3-256 hash object of the entity
*/
public Sha3256Hash computeHash(Identifier id) {
return this.computeHash(id.getBytes());
}

/**
* Computes hash of the given bytes.
*
* @param bytes input bytes.
* @return SHA3-256 hash object of the given bytes.
*/
public Sha3256Hash computeHash(byte[] bytes) {
try {
MessageDigest md = MessageDigest.getInstance(HASH_ALG_SHA_3_256);
byte[] hashValue = md.digest(e.getBytes());
byte[] hashValue = md.digest(bytes);
return new Sha3256Hash(hashValue);
} catch (NoSuchAlgorithmException ex) {
throw new IllegalStateException(HASH_ALG_SHA_3_256 + "algorithm not found.", ex);
}
}

/**
* Commutative hashing of two given byte arrays.
*
* @param b1 first byte array.
* @param b2 second byte array.
* @return SHA3-256 hash object of the commutative concatenation of the two byte arrays.
*/
public Sha3256Hash computeHash(byte[] b1, byte[] b2) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not always h(b1||b2)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in d0f93ab

try {
MessageDigest md = MessageDigest.getInstance(HASH_ALG_SHA_3_256);
return new Sha3256Hash(md.digest(concat(b1, b2)));
} catch (NoSuchAlgorithmException ex) {
throw new IllegalStateException(HASH_ALG_SHA_3_256 + "algorithm not found.", ex);
}
}

public Sha3256Hash computeHash(Sha3256Hash h1, Sha3256Hash h2) {
return computeHash(h1.getBytes(), h2.getBytes());
}
}
2 changes: 2 additions & 0 deletions src/main/java/modules/ads/AuthenticatedDataStructure.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ public interface AuthenticatedDataStructure {
AuthenticatedEntity put(Entity e);

AuthenticatedEntity get(Identifier id);

int size();
}
4 changes: 2 additions & 2 deletions src/main/java/modules/ads/AuthenticatedEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* that entity against a root identifier.
*/
public abstract class AuthenticatedEntity extends Entity {
abstract Entity getEntity();
public abstract Entity getEntity();

abstract MembershipProof getMembershipProof();
public abstract MembershipProof getMembershipProof();
}
17 changes: 10 additions & 7 deletions src/main/java/modules/ads/MembershipProof.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package modules.ads;

import model.lightchain.Identifier;
import java.util.ArrayList;

import model.crypto.Sha3256Hash;

/**
* Represents a Merkle Proof of membership against a certain root identifier.
Expand All @@ -9,15 +11,16 @@ public interface MembershipProof {
/**
* Root of the authenticated data structure that this proof belongs to.
*
* @return root identifier.
* @return hash value of the root node.
*/
Identifier getRoot();
Sha3256Hash getRoot();

/**
* Sibling of the given identifier on the membership Merkle Proof path to the root.
* Returns the path of the proof of membership.
*
* @param identifier identifier of the entity.
* @return sibling of given identifier.
* @return path of the proof of membership.
*/
Identifier getSiblingOf(Identifier identifier);
ArrayList<Sha3256Hash> getPath();

ArrayList<Boolean> getIsLeftNode();
}
117 changes: 117 additions & 0 deletions src/main/java/modules/ads/merkletree/MerkleNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package modules.ads.merkletree;

import crypto.Sha3256Hasher;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import model.Entity;
import model.crypto.Sha3256Hash;

/**
* A node in the Merkle tree.
*/
public class MerkleNode {
private static final Sha3256Hasher hasher = new Sha3256Hasher();
private MerkleNode left;
private MerkleNode right;
private MerkleNode parent;
private boolean isLeft;
private Sha3256Hash hash;

/**
* Default constructor.
*/
public MerkleNode() {
this.left = null;
this.right = null;
this.parent = null;
this.isLeft = false;
this.hash = null;
}

/**
* Constructor with entity and isLeft.
*
* @param e input entity
* @param isLeft boolean that specifies if the node is left child or not
*/
public MerkleNode(Entity e, boolean isLeft) {
this.left = null;
this.right = null;
this.parent = null;
this.isLeft = isLeft;
this.hash = hasher.computeHash(e.id());
}

/**
* Constructor with hash of the entity.
*
* @param hash input hash of the entity corresponding to that node
*/
public MerkleNode(Sha3256Hash hash) {
this.left = null;
this.right = null;
this.parent = null;
this.isLeft = false;
this.hash = hash;
}

/**
* Constructor of a parent node.
*
* @param hash input hash of the entity corresponding to that node
* @param left left child of the node
* @param right right child of the node
*/
@SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "left and right are intentionally mutable externally")
public MerkleNode(Sha3256Hash hash, MerkleNode left, MerkleNode right) {
this.left = left;
this.right = right;
this.parent = null;
this.isLeft = false;
this.hash = hash;
}

@SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "internal representation is intentionally returned")
public MerkleNode getLeft() {
return left;
}

@SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "internal representation is intentionally returned")
public MerkleNode getRight() {
return right;
}

@SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "internal representation is intentionally returned")
public MerkleNode getParent() {
return parent;
}

@SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "parent is intentionally mutable externally")
public void setParent(MerkleNode parent) {
this.parent = parent;
}

public Sha3256Hash getHash() {
return hash;
}

public boolean isLeft() {
return isLeft;
}

public void setLeft(boolean isLeft) {
this.isLeft = isLeft;
}

/**
* Returns the sibling of the node.
*
* @return the sibling of the node
*/
public MerkleNode getSibling() {
if (isLeft()) {
return parent.getRight();
} else {
return parent.getLeft();
}
}
}
71 changes: 71 additions & 0 deletions src/main/java/modules/ads/merkletree/MerkleProof.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package modules.ads.merkletree;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import model.crypto.Sha3256Hash;
import modules.ads.MembershipProof;

/**
* A proof of membership in a Merkle tree.
*/
public class MerkleProof implements MembershipProof {
private ArrayList<Sha3256Hash> path;
private final ArrayList<Boolean> isLeftNode;
private final Sha3256Hash root;

/**
* Constructs a proof from a list of hashes and a root.
*
* @param path the list of hashes
* @param root the root
* @param isLeftNode the list of isLeft Boolean values of the hashes
*/
public MerkleProof(ArrayList<Sha3256Hash> path, Sha3256Hash root, ArrayList<Boolean> isLeftNode) {
this.path = new ArrayList<>(path);
this.root = root;
this.isLeftNode = new ArrayList<>(isLeftNode);
}

@Override
public ArrayList<Sha3256Hash> getPath() {
return new ArrayList<>(path);
}

public void setPath(ArrayList<Sha3256Hash> path) {
this.path = new ArrayList<>(path);
}

@SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "internal representation is intentionally returned")
public ArrayList<Boolean> getIsLeftNode() {
return isLeftNode;
}

public Sha3256Hash getRoot() {
return root;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MerkleProof proof = (MerkleProof) o;
for (int i = 0; i < path.size(); i++) {
if (!Arrays.equals(path.get(i).getBytes(), proof.path.get(i).getBytes())) {
return false;
}
}
return root.equals(proof.root);
}

@Override
public int hashCode() {
return Objects.hash(path, root);
}
}
Loading