@@ -8,8 +8,9 @@ use crate::{
88 File , OptionalPostalAddress , PostalAddress ,
99 company:: { Company , CompanyKeys } ,
1010} ;
11- use borsh:: to_vec;
11+ use borsh:: { from_slice , to_vec} ;
1212use borsh_derive:: { BorshDeserialize , BorshSerialize } ;
13+ use log:: error;
1314use secp256k1:: PublicKey ;
1415use serde:: { Deserialize , Serialize } ;
1516
@@ -26,6 +27,7 @@ pub enum CompanyOpCode {
2627pub struct CompanyBlockDataToHash {
2728 company_id : NodeId ,
2829 id : u64 ,
30+ plaintext_hash : String ,
2931 previous_hash : String ,
3032 data : String ,
3133 timestamp : u64 ,
@@ -54,6 +56,7 @@ pub struct CompanyBlockData {
5456pub struct CompanyBlock {
5557 pub company_id : NodeId ,
5658 pub id : u64 ,
59+ pub plaintext_hash : String ,
5760 pub hash : String ,
5861 pub timestamp : u64 ,
5962 pub data : String ,
@@ -145,6 +148,10 @@ impl Block for CompanyBlock {
145148 & self . op_code
146149 }
147150
151+ fn plaintext_hash ( & self ) -> & str {
152+ & self . plaintext_hash
153+ }
154+
148155 fn hash ( & self ) -> & str {
149156 & self . hash
150157 }
@@ -169,10 +176,52 @@ impl Block for CompanyBlock {
169176 true
170177 }
171178
179+ /// We validate the plaintext hash against the plaintext data from the CompanyBlockData wrapper
180+ fn validate_plaintext_hash ( & self , private_key : & secp256k1:: SecretKey ) -> bool {
181+ match util:: base58_decode ( & self . data ) {
182+ Ok ( decoded_wrapper) => match from_slice :: < CompanyBlockData > ( & decoded_wrapper) {
183+ Ok ( data_wrapper) => match util:: base58_decode ( & data_wrapper. data ) {
184+ Ok ( decoded) => match util:: crypto:: decrypt_ecies ( & decoded, private_key) {
185+ Ok ( decrypted) => self . plaintext_hash ( ) == util:: sha256_hash ( & decrypted) ,
186+ Err ( e) => {
187+ error ! (
188+ "Decrypt Error while validating plaintext hash for id {}: {e}" ,
189+ self . id( )
190+ ) ;
191+ false
192+ }
193+ } ,
194+ Err ( e) => {
195+ error ! (
196+ "Decode Error while validating plaintext hash for id {}: {e}" ,
197+ self . id( )
198+ ) ;
199+ false
200+ }
201+ } ,
202+ Err ( e) => {
203+ error ! (
204+ "Wrapper Deserialize Error while validating plaintext hash for id {}: {e}" ,
205+ self . id( )
206+ ) ;
207+ false
208+ }
209+ } ,
210+ Err ( e) => {
211+ error ! (
212+ "Wrapper Decode Error while validating plaintext hash for id {}: {e}" ,
213+ self . id( )
214+ ) ;
215+ false
216+ }
217+ }
218+ }
219+
172220 fn get_block_data_to_hash ( & self ) -> Self :: BlockDataToHash {
173221 CompanyBlockDataToHash {
174222 company_id : self . company_id . clone ( ) ,
175223 id : self . id ( ) ,
224+ plaintext_hash : self . plaintext_hash ( ) . to_owned ( ) ,
176225 previous_hash : self . previous_hash ( ) . to_owned ( ) ,
177226 data : self . data ( ) . to_owned ( ) ,
178227 timestamp : self . timestamp ( ) ,
@@ -195,6 +244,7 @@ impl CompanyBlock {
195244 identity_keys : & BcrKeys ,
196245 company_keys : & CompanyKeys ,
197246 timestamp : u64 ,
247+ plaintext_hash : String ,
198248 ) -> Result < Self > {
199249 // The order here is important: identity -> company
200250 let keys: Vec < secp256k1:: SecretKey > = vec ! [
@@ -206,6 +256,7 @@ impl CompanyBlock {
206256 let hash = Self :: calculate_hash ( CompanyBlockDataToHash {
207257 company_id : company_id. clone ( ) ,
208258 id,
259+ plaintext_hash : plaintext_hash. clone ( ) ,
209260 previous_hash : previous_hash. clone ( ) ,
210261 data : data. clone ( ) ,
211262 timestamp,
@@ -218,6 +269,7 @@ impl CompanyBlock {
218269 Ok ( Self {
219270 company_id,
220271 id,
272+ plaintext_hash,
221273 hash,
222274 timestamp,
223275 previous_hash,
@@ -238,6 +290,7 @@ impl CompanyBlock {
238290 timestamp : u64 ,
239291 ) -> Result < Self > {
240292 let company_bytes = to_vec ( company) ?;
293+ let plaintext_hash = Self :: calculate_plaintext_hash ( company) ?;
241294 // encrypt data using company pub key
242295 let encrypted_data = util:: base58_encode ( & util:: crypto:: encrypt_ecies (
243296 & company_bytes,
@@ -266,6 +319,7 @@ impl CompanyBlock {
266319 identity_keys,
267320 company_keys,
268321 timestamp,
322+ plaintext_hash,
269323 )
270324 }
271325
@@ -365,6 +419,7 @@ impl CompanyBlock {
365419 op_code : CompanyOpCode ,
366420 ) -> Result < Self > {
367421 let bytes = to_vec ( & data) ?;
422+ let plaintext_hash = Self :: calculate_plaintext_hash ( data) ?;
368423 // encrypt data using the company pub key
369424 let encrypted_data = util:: base58_encode ( & util:: crypto:: encrypt_ecies (
370425 & bytes,
@@ -400,6 +455,7 @@ impl CompanyBlock {
400455 identity_keys,
401456 company_keys,
402457 timestamp,
458+ plaintext_hash,
403459 ) ?;
404460
405461 if !new_block. validate_with_previous ( previous_block) {
@@ -504,6 +560,24 @@ mod tests {
504560 ) ,
505561 )
506562 }
563+
564+ #[ test]
565+ fn test_plaintext_hash ( ) {
566+ let ( _id, ( company, company_keys) ) = get_baseline_company_data ( ) ;
567+
568+ let chain = CompanyBlockchain :: new (
569+ & CompanyCreateBlockData :: from ( company) ,
570+ & BcrKeys :: new ( ) ,
571+ & company_keys,
572+ 1731593928 ,
573+ ) ;
574+ assert ! ( chain. is_ok( ) ) ;
575+ assert ! ( chain. as_ref( ) . unwrap( ) . is_chain_valid( ) ) ;
576+ assert ! (
577+ chain. as_ref( ) . unwrap( ) . blocks( ) [ 0 ] . validate_plaintext_hash( & company_keys. private_key)
578+ ) ;
579+ }
580+
507581 #[ test]
508582 fn create_and_check_validity ( ) {
509583 let ( _id, ( company, company_keys) ) = get_baseline_company_data ( ) ;
@@ -605,6 +679,11 @@ mod tests {
605679 assert ! ( new_chain_from_empty_blocks. is_err( ) ) ;
606680
607681 let blocks = chain. blocks ( ) ;
682+
683+ for block in blocks {
684+ assert ! ( block. validate_plaintext_hash( & company_keys. private_key) ) ;
685+ }
686+
608687 let new_chain_from_blocks = CompanyBlockchain :: new_from_blocks ( blocks. to_owned ( ) ) ;
609688 assert ! ( new_chain_from_blocks. is_ok( ) ) ;
610689 assert ! ( new_chain_from_blocks. as_ref( ) . unwrap( ) . is_chain_valid( ) ) ;
0 commit comments