-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
126 changed files
with
90,977 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 16 | ||
VisualStudioVersion = 16.0.28729.10 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tx_blockchain", "tx_blockchain\tx_blockchain.csproj", "{6AACD7A7-B242-4B60-8687-A3AE6F09596F}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{6AACD7A7-B242-4B60-8687-A3AE6F09596F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{6AACD7A7-B242-4B60-8687-A3AE6F09596F}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{6AACD7A7-B242-4B60-8687-A3AE6F09596F}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{6AACD7A7-B242-4B60-8687-A3AE6F09596F}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {EA8AC697-9C2A-4A34-AE6D-3407B0364D85} | ||
EndGlobalSection | ||
EndGlobal |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Web; | ||
using System.Web.Mvc; | ||
using System.Web.Routing; | ||
|
||
namespace tx_blockchain | ||
{ | ||
public class RouteConfig | ||
{ | ||
public static void RegisterRoutes(RouteCollection routes) | ||
{ | ||
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); | ||
|
||
routes.MapRoute( | ||
name: "Default", | ||
url: "{controller}/{action}/{id}", | ||
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Web.Http; | ||
|
||
namespace tx_blockchain | ||
{ | ||
public static class WebApiConfig | ||
{ | ||
public static void Register(HttpConfiguration config) | ||
{ | ||
// Web API configuration and services | ||
|
||
// Web API routes | ||
config.MapHttpAttributeRoutes(); | ||
|
||
config.Routes.MapHttpRoute( | ||
name: "DefaultApi", | ||
routeTemplate: "api/{controller}/{id}", | ||
defaults: new { id = RouteParameter.Optional } | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using System; | ||
using System.Security.Cryptography; | ||
using System.Text; | ||
|
||
// this class contains the structure of a single block in the | ||
// blockchain and stores the document MD5 hash in the data property. | ||
public class Block | ||
{ | ||
public int Index { get; set; } | ||
public DateTime TimeStamp { get; set; } | ||
public string PreviousBlockHash { get; set; } | ||
public string BlockHash { get; set; } | ||
public string Data { get; set; } | ||
public int Nonce { get; set; } = 0; | ||
|
||
// constructor | ||
public Block (DateTime timeStamp, string previousBlockHash, string data) | ||
{ | ||
Index = 0; | ||
TimeStamp = timeStamp; | ||
PreviousBlockHash = previousBlockHash; | ||
Data = data; | ||
BlockHash = GenerateBlockHash(); | ||
} | ||
|
||
// generates a new hash for the block including the time stamp, | ||
// the previous block has, the data and the nonce. | ||
internal string GenerateBlockHash() | ||
{ | ||
SHA256 sha256 = SHA256.Create(); | ||
|
||
byte[] bInput = Encoding.ASCII.GetBytes($"{TimeStamp}-{PreviousBlockHash ?? ""}-{Data}-{Nonce}"); | ||
byte[] bOutput = sha256.ComputeHash(bInput); | ||
|
||
return Convert.ToBase64String(bOutput); | ||
} | ||
|
||
// this method is generating hashes until a new hash with a specific | ||
// number of leading zeros is created | ||
public void Mine(int difficulty) | ||
{ | ||
string sLeadingZeros = new string('0', difficulty); | ||
|
||
while (this.BlockHash == null || this.BlockHash.Substring(0, difficulty) != sLeadingZeros) | ||
{ | ||
this.Nonce++; | ||
this.BlockHash = this.GenerateBlockHash(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Web; | ||
|
||
// this class implements the actual linked list | ||
public class Blockchain | ||
{ | ||
public IList<Block> Chain { set; get; } | ||
public int Difficulty { set; get; } = 2; | ||
|
||
public Blockchain() | ||
{ | ||
InitializeChain(); | ||
} | ||
|
||
public Blockchain(bool newBlockChain) | ||
{ | ||
InitializeChain(); | ||
AddGenesisBlock(); // add the first block | ||
} | ||
|
||
public void InitializeChain() | ||
{ | ||
Chain = new List<Block>(); | ||
} | ||
|
||
public Block CreateGenesisBlock() | ||
{ | ||
return new Block(DateTime.Now, null, "{}"); | ||
} | ||
|
||
public void AddGenesisBlock() | ||
{ | ||
Chain.Add(CreateGenesisBlock()); | ||
} | ||
|
||
// return the last block in the list | ||
public Block GetCurrentBlock() | ||
{ | ||
return Chain[Chain.Count - 1]; | ||
} | ||
|
||
// adds a new block to the chain | ||
public void AddBlock(Block block) | ||
{ | ||
// check blockchain consistency first | ||
if (this.IsValid() == true) | ||
{ | ||
Block latestBlock = GetCurrentBlock(); | ||
block.Index = latestBlock.Index + 1; | ||
block.PreviousBlockHash = latestBlock.BlockHash; | ||
|
||
// mine for a valid hash | ||
block.Mine(this.Difficulty); | ||
|
||
// add the block to the chain | ||
Chain.Add(block); | ||
} | ||
} | ||
|
||
// checks, if the blockchain is consistent by | ||
// re-generating and comparing the hashes in each block | ||
public bool IsValid() | ||
{ | ||
for (int i = 1; i < Chain.Count; i++) | ||
{ | ||
Block currentBlock = Chain[i]; | ||
Block previousBlock = Chain[i - 1]; | ||
|
||
if (currentBlock.BlockHash != currentBlock.GenerateBlockHash()) | ||
{ | ||
return false; | ||
} | ||
|
||
if (currentBlock.PreviousBlockHash != previousBlock.BlockHash) | ||
{ | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
.viewer { | ||
height: calc(100vh - 56px); | ||
} | ||
|
||
.verified::before { | ||
font-size: 100px; | ||
font-family: "Font Awesome 5 Free"; | ||
font-weight: 900; | ||
content: "\f058"; | ||
} | ||
|
||
.notverified::before { | ||
font-size: 100px; | ||
font-family: "Font Awesome 5 Free"; | ||
font-weight: 900; | ||
content: "\f057"; | ||
} | ||
|
||
.result { | ||
display: block; | ||
} | ||
|
||
.verified { | ||
color: green; | ||
} | ||
|
||
.notverified { | ||
color: red; | ||
} | ||
|
||
.result-text-notverified::before { | ||
content: "The document could not be validated with the last block on the blockchain."; | ||
} | ||
|
||
.result-text-verified::before { | ||
content: "The document has been validated with the last block on the blockchain."; | ||
} | ||
|
||
#tx-documentViewer { | ||
top: 56px !important; | ||
height: calc(100vH - 56px) !important; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<ClassDiagram /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
using Newtonsoft.Json; | ||
using System; | ||
using System.Web.Http; | ||
using System.Web.Mvc; | ||
using tx_blockchain.Helpers; | ||
using tx_blockchain.Models; | ||
|
||
namespace tx_blockchain.Controllers | ||
{ | ||
public class DocumentController : Controller | ||
{ | ||
// this method stores the document hash in the blockchain | ||
[System.Web.Http.HttpPost] | ||
public ActionResult StoreDocument( | ||
[FromBody] string Document, | ||
[FromBody] string UniqueId, | ||
[FromBody] string SignerName) | ||
{ | ||
byte[] bPDF; | ||
|
||
// create temporary ServerTextControl | ||
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl()) | ||
{ | ||
tx.Create(); | ||
|
||
// load the document | ||
tx.Load(Convert.FromBase64String(Document), | ||
TXTextControl.BinaryStreamType.InternalUnicodeFormat); | ||
|
||
TXTextControl.SaveSettings saveSettings = new TXTextControl.SaveSettings() | ||
{ | ||
CreatorApplication = "TX Text Control Sample Application", | ||
}; | ||
|
||
// save the document as PDF | ||
tx.Save(out bPDF, TXTextControl.BinaryStreamType.AdobePDF, saveSettings); | ||
} | ||
|
||
// calculate the MD5 checksum of the binary data | ||
// and store in SignedDocument object | ||
SignedDocument document = new SignedDocument() | ||
{ | ||
Checksum = Checksum.CalculateMD5(bPDF) | ||
}; | ||
|
||
// define a Blockchain object | ||
Blockchain bcDocument; | ||
|
||
// if the blockchain exists, load it | ||
if (System.IO.File.Exists( | ||
Server.MapPath("~/App_Data/Blockchains/" + UniqueId + ".bc"))) | ||
{ | ||
string bc = System.IO.File.ReadAllText( | ||
Server.MapPath("~/App_Data/Blockchains/" + UniqueId + ".bc")); | ||
|
||
bcDocument = JsonConvert.DeserializeObject<Blockchain>(bc); | ||
} | ||
else | ||
bcDocument = new Blockchain(true); // otherwise create a new blockchain | ||
|
||
// add a new block to the blockchain and store the SignedDocument object | ||
bcDocument.AddBlock(new Block(DateTime.Now, null, JsonConvert.SerializeObject(document))); | ||
|
||
// store the blockchain as a file | ||
System.IO.File.WriteAllText( | ||
Server.MapPath("~/App_Data/Blockchains/" + UniqueId + ".bc"), | ||
JsonConvert.SerializeObject(bcDocument)); | ||
|
||
// create and return a view model with the PDF and the unique document ID | ||
StoredDocument storedDocument = new StoredDocument() | ||
{ | ||
PDF = Convert.ToBase64String(bPDF), | ||
DocumentId = UniqueId | ||
}; | ||
|
||
return new JsonResult() { Data = storedDocument, | ||
JsonRequestBehavior = JsonRequestBehavior.AllowGet }; | ||
} | ||
|
||
// this method validates a document with the last block on the blockchain | ||
[System.Web.Http.HttpPost] | ||
public bool ValidateDocument([FromBody] string Document, [FromBody] string UniqueId) | ||
{ | ||
if (Document == null || UniqueId == null) | ||
return false; | ||
|
||
// calculate the MD5 of the uploaded document | ||
string sChecksum = Checksum.CalculateMD5(Convert.FromBase64String(Document)); | ||
|
||
Blockchain newDocument; | ||
|
||
// load the associated blockchain | ||
if (System.IO.File.Exists( | ||
Server.MapPath("~/App_Data/Blockchains/" + UniqueId + ".bc"))) | ||
{ | ||
string bc = System.IO.File.ReadAllText( | ||
Server.MapPath("~/App_Data/Blockchains/" + UniqueId + ".bc")); | ||
|
||
newDocument = JsonConvert.DeserializeObject<Blockchain>(bc); | ||
|
||
// get the SignedDocument object from the block | ||
SignedDocument signedDocument = | ||
JsonConvert.DeserializeObject<SignedDocument>(newDocument.GetCurrentBlock().Data); | ||
|
||
// compare the checksum in the stored block | ||
// with the checksum of the uploaded document | ||
if (signedDocument.Checksum == sChecksum) | ||
return true; // document valid | ||
else | ||
return false; // not valid | ||
} | ||
else | ||
return false; // blockchain doesn't exist | ||
} | ||
} | ||
} |
Oops, something went wrong.