const EthCrypto = require('eth-crypto');
const crypto = require('crypto');
const fs = require('fs');
const { idData, prA, puB, prB } = require('./parameters');
// File paths
const originalFile = './paper.pdf';
const encryptedFile = './C.pdf';
const decryptedFile = './decrypted.pdf';
const keyFile = './k.txt';
const ivFile = './iv.txt';
const HMACFILE = './HMAC.txt';
const hFile = './h.txt';
const idFile = './id.txt';
const fcFile = './fc.txt';
// Function to encrypt the notification message
const encryptM = async () => {
try {
// Read the original file into a buffer
const fileBuffer = fs.readFileSync(originalFile);
// Encrypt the file buffer using ECIES
const ECIES_output_params = await EthCrypto.encryptWithPublicKey(
puB,
fileBuffer.toString('hex')
);
console.log("ECIES output params: ", ECIES_output_params);
// Compress the ephemeral public key from the encryption output
const ephemPublicKeyCompressed = EthCrypto.publicKey.compress(
ECIES_output_params.ephemPublicKey
);
// Convert the compressed ephemeral public key to a hex string with '0x' prefix
const k = `0x${ephemPublicKeyCompressed}`;
// Convert the initialization vector (IV) from hex to base64
const bufferIV = Buffer.from(ECIES_output_params.iv, 'hex');
const iv = bufferIV.toString('base64');
// Convert the HMAC (Hash-based Message Authentication Code) from hex to base64
const bufferHMAC = Buffer.from(ECIES_output_params.mac, 'hex');
const HMAC = bufferHMAC.toString('base64');
// Save the encryption output params to their respective files
fs.writeFileSync(encryptedFile, ECIES_output_params.ciphertext, 'hex');
fs.writeFileSync(keyFile, k);
fs.writeFileSync(ivFile, iv);
fs.writeFileSync(HMACFILE, HMAC);
} catch (error) {
console.error('Error reading or writing file:', error);
}
}
// Function to compute h
const getH = async () => {
try {
// Read the encrypted file into a buffer
const fileBuffer = fs.readFileSync(encryptedFile);
// Create a SHA-256 hash object
const hashSum = crypto.createHash('sha256');
hashSum.update(fileBuffer);
// Compute the hash as a hexadecimal string
const hex = hashSum.digest('hex');
// Format the hash as a Solidity-compatible bytes32 string
const solidityBytes32 = `0x${hex}`;
console.log('SHA-256 file hash (Bytes32):', solidityBytes32);
// Write the hash to the specified file
fs.writeFileSync(hFile, solidityBytes32);
} catch (error) {
console.error('Error reading or hashing file:', error);
}
}
// Function to obtain the notification ID
const getID = async () => {
try {
// Read the h file into a buffer
const fileBuffer = fs.readFileSync(hFile);
const h = fileBuffer.toString();
// Calculate the Keccak-256 hash of the given inputs to get the notification ID
const signHash = EthCrypto.hash.keccak256([
{
type: 'address',
value: idData.addrA
}, {
type: 'address',
value: idData.addrB
}, {
type: 'address',
value: idData.addrSC
}, {
type: 'uint256',
value: idData.tm
}, {
type: 'uint256',
value: idData.td
}, {
type: 'bytes32',
value: h
}
]);
// Write the calculated hash to the file specified by idFile
fs.writeFileSync(idFile, signHash);
console.log("id = ", signHash);
} catch (error) {
console.error('Error writing file:', error);
}
}
// Function to obtain f(C)
const getFC = async () => {
try {
// Read the contents of the files idFile, hFile and convert them to a string
const idBuffer = fs.readFileSync(idFile);
const id = idBuffer.toString();
const hBuffer = fs.readFileSync(hFile);
const h = hBuffer.toString();
// Create a keccak256 hash of the concatenated values
const signHash = EthCrypto.hash.keccak256([
{
type: 'bytes32',
value: id
}, {
type: 'uint256',
value: idData.tm
}, {
type: 'uint256',
value: idData.td
}, {
type: 'bytes32',
value: h
}
]);
// Sign the keccak256 hash with the private key prA
const fc = EthCrypto.sign(
prA,
signHash
);
// Write the signed hash (fc) to the fcFile
fs.writeFileSync(fcFile, fc);
console.log("Fc: ", fc);
} catch (error) {
console.error('Error writing file:', error);
}
}
// Function to verify the signer of f(C)
const verifyFC = async () => {
try {
// Read the contents of the files idFile, hFile, fcFile and convert them to a string
const idBuffer = fs.readFileSync(idFile);
const id = idBuffer.toString();
const hBuffer = fs.readFileSync(hFile);
const h = hBuffer.toString();
const fc = fs.readFileSync(fcFile, 'utf8');
// Compute the keccak256 hash of the given data fields
const signHash = EthCrypto.hash.keccak256([
{
type: 'bytes32',
value: id
}, {
type: 'uint256',
value: idData.tm
}, {
type: 'uint256',
value: idData.td
}, {
type: 'bytes32',
value: h
}
]);
// Recover the signer's address from the given signature (fc) and the hash (signHash)
const signer = EthCrypto.recover(
fc,
signHash
);
// Log success message and the signer's address (@A)
console.log('FC verified successfully!');
console.log('Signer: ', signer);
} catch (error) {
console.error('Error reading file:', error);
}
}
// Function to decrypt C and recover the original file
const decryptC = async () => {
try {
// Read encrypted data from file
const encryptedBuffer = fs.readFileSync(encryptedFile, 'hex');
// Read HMAC and encryption key from files
const hmacBase64 = fs.readFileSync(HMACFILE, 'utf8');
const key = fs.readFileSync(keyFile, 'utf8');
// Decompress the public key for encryption
const ephemPublicKey = EthCrypto.publicKey.decompress(
key.substring(2) // Removing '0x' prefix before decompression
);
// Format the decompressed public key with its prefix '04'
const k = `04${ephemPublicKey}`;
// Read Initialization Vector (IV) from file and convert from Base64 to string
const ivBase64 = fs.readFileSync(ivFile, 'utf8');
const ivBuffer = Buffer.from(ivBase64, 'base64');
const iv = ivBuffer.toString('hex');
// Convert HMAC from Base64 to hexadecimal string
const hmacBuffer = Buffer.from(hmacBase64, 'base64');
const hmac = hmacBuffer.toString('hex');
// Prepare parameters required for ECIES decryption
const ECIES_output_params = {
iv: iv,
ephemPublicKey: k,
ciphertext: encryptedBuffer,
mac: hmac
};
// Decrypt the encrypted data using a private key (prB)
const decrypted = await EthCrypto.decryptWithPrivateKey(
prB,
ECIES_output_params
);
// Convert decrypted data from hexadecimal string to Buffer and write to a file
const decryptedBuffer = Buffer.from(decrypted, 'hex');
fs.writeFileSync(decryptedFile, decryptedBuffer);
} catch (error) {
console.error('Error reading or writing file:', error);
}
}
// Execute all functions in order
const execute = async () => {
await encryptM();
await getH();
await getID();
await getFC();
await verifyFC();
await decryptC();
}
execute();