Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #43

Merged
merged 46 commits into from
Apr 21, 2024
Merged
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
f43bacb
Ag 17 commitlint fix (#1)
g3k0 Mar 24, 2024
9260287
feat(@agora): AG-35 basic workflow (#3)
g3k0 Mar 25, 2024
3424f31
docs(@agora): AG-35 updloaded image (#5)
g3k0 Mar 26, 2024
56f40f9
Ag 18 eoa implementation (#7)
g3k0 Mar 28, 2024
db20673
Ag 19 DECsRegistry smart contract (#8)
g3k0 Mar 29, 2024
0dc0d57
Ag 20 election smart contract (#9)
g3k0 Mar 30, 2024
fb1dc90
Ag 20 election smart contract (#10)
g3k0 Mar 30, 2024
07a2bad
Merge branch 'main' into develop
g3k0 Mar 30, 2024
ed96d8d
Ag 25 deploy contracts (#13)
g3k0 Mar 31, 2024
202b9fa
Ag 26 register election script (#14)
g3k0 Apr 7, 2024
b7d36ec
Merge branch 'main' into develop
g3k0 Apr 7, 2024
c3eb2ba
Merge branch 'main' into develop
g3k0 Apr 7, 2024
2639ecd
Ag 37 actions api layer (#16)
g3k0 Apr 7, 2024
c9596a4
docs(@docs): updated README
g3k0 Apr 7, 2024
81f457a
Merge branch 'main' into develop
g3k0 Apr 7, 2024
3e5dd41
Merge branch 'main' into develop
g3k0 Apr 7, 2024
03e502d
fix(@ci): AG-36 fixed github username (#19)
g3k0 Apr 7, 2024
93631f7
Ag 39 encrypt dec data (#21)
g3k0 Apr 9, 2024
14581fc
Ag 40 dec registration (#22)
g3k0 Apr 11, 2024
7aeb927
Merge branch 'main' into develop
g3k0 Apr 11, 2024
82bb5c4
fix(@CICD): AG-42 fix github actions (#24)
g3k0 Apr 11, 2024
9241c8e
fix(CICD): AG-42 workflow fixes (#26)
g3k0 Apr 11, 2024
37ecada
Merge branch 'main' into develop
g3k0 Apr 11, 2024
86f3780
Merge branch 'main' into develop
g3k0 Apr 11, 2024
3dad309
Ag 42 fixes 2 (#28)
g3k0 Apr 11, 2024
8dec442
Merge branch 'main' into develop
g3k0 Apr 11, 2024
e79d573
Merge branch 'develop' of https://github.com/nova-collective/agora in…
g3k0 Apr 11, 2024
a3ea86f
Merge branch 'main' into develop
g3k0 Apr 11, 2024
3f87a38
AG-42 fixes (#30)
g3k0 Apr 11, 2024
e7463b6
Merge branch 'main' into develop
g3k0 Apr 11, 2024
3d205f3
fixes (#32)
g3k0 Apr 11, 2024
112da11
Merge branch 'main' into develop
g3k0 Apr 11, 2024
5314b97
Merge branch 'main' into develop
g3k0 Apr 11, 2024
af2ab5e
Merge branch 'main' into develop
g3k0 Apr 11, 2024
33a7097
Merge branch 'main' into develop
g3k0 Apr 12, 2024
cf01269
Merge branch 'main' into develop
g3k0 Apr 12, 2024
6575a17
Ag 32 zokrates init (#36)
g3k0 Apr 14, 2024
d1d6fdf
Merge branch 'main' into develop
g3k0 Apr 14, 2024
970496f
fix(CI/CD): AG-45 added set -e parameter to workflow (#38)
g3k0 Apr 17, 2024
c166750
feat(zk-snarks): AG-32 defined voting program (#39)
g3k0 Apr 18, 2024
91fc545
updated version
g3k0 Apr 18, 2024
6a9023f
Merge branch 'main' into develop
g3k0 Apr 20, 2024
a08b208
Merge branch 'main' into develop
g3k0 Apr 20, 2024
b2a7637
Merge branch 'main' into develop
g3k0 Apr 20, 2024
aec0591
Ag 50 crypto lib integration (#42)
g3k0 Apr 21, 2024
748162e
updated version number
g3k0 Apr 21, 2024
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
Prev Previous commit
Next Next commit
Ag 50 crypto lib integration (#42)
* feat(script): AG-50 import crypto-py

added isntruction for the integration of external libs using symlinks

* feat(scripts): AG-50 integrated crypto-py lib

integrated cripto-py lib in the project and updated smart contracts, scripts and tests

* updated readme

* feat(CI/CD): AG-50 implemented step for python lib

added a step in the CI/CD workflow for the installation of python libs

* yaml fix

* updated workflow

* updated workflow

* updated workflow

* updated workflow

* feat(CI/CD): AG-50 imtegrated python libs in ci/cd

integrated the installation of python libs in the CI/CD workflow
  • Loading branch information
g3k0 authored Apr 21, 2024
commit aec0591d33f7e8235d153c3d616c3cd8817f5091
8 changes: 8 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -22,9 +22,17 @@ jobs:
uses: actions/setup-node@v2
with:
node-version: 20.x

- name: Set up Python 3
uses: actions/setup-python@v2
with:
python-version: '3.11'

- name: Install dependencies
run: node ci --function installDeps

- name: install python libs
run: node ci --function installPythonLibs --params "{\"libs\":[\"crypto-py\"]}"

- name: Run linter
run: node ci --function lint
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -18,4 +18,7 @@ node_modules
report

#ignition files
/ignition/deployments
/ignition/deployments

# external libs linked by symlinks
crypto-py
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@ Agora is a web3 dApp based on the [Hardhat framework](https://hardhat.org/) and
In order to run the application you need the following software installed on you machine:

* [Node.js](https://nodejs.org/en) v20.11.1 or above
* [Python](https://www.python.org/) v3.11.2 or above

You also need an Alchemy account.

@@ -39,6 +40,18 @@ To setup the application follow these steps:
* `REPORT_GAS` enable or disable the gas report on smart contracts unit tests executions;
* `NODE_ENV` set `development` for your local machine;

### Install crypto-py

Agora uses a Python external library for cryptographic operations called [crypto-py](https://github.com/nova-collective/crypto-py). This library needs to be
manually integrated into the Hardhat framework, follow this steps:

5. from the root folder of application, go to the `lib` folder;
6. clone `crypto-py` inside the lib folder;
6. go inside the crypto-py folder and install the dependencies `pip install -r requirements.txt`;
7. if you decide to set a python environment inside the crypto-py folder, remember to activate the environment;

Alternatively, If you are in a Unix environment, you can clone the library somewhere else and create a symbolic link inside the Agora lib folder.

## How to commit

The `main` and the `develop` branches are protected. It is required to open and review pull requests in order to merge the code.
@@ -66,7 +79,7 @@ Smart contracts code coverage documentation [here](https://www.npmjs.com/package

| step | library used | theshold | is error blocking |
|------|--------------|----------|-------------------|
| Code Linting | [eslint](https://www.npmjs.com/package/eslint) | No thesholds | yes |
| Code Linting | [eslint](https://www.npmjs.com/package/eslint) | Not applicable | yes |
| Code duplication | [jscpd](https://www.npmjs.com/package/jscpd) | 10% | yes |
| Smart contracts unit tests | [jest](https://www.npmjs.com/package/jest) | all tests must pass | yes |
| TypeScript files unit tests | [jest](https://www.npmjs.com/package/jest) | all tests must pass; 80% code coverage | yes |
7 changes: 7 additions & 0 deletions ci/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const config = {
installPythonLibs: {
cryptoPyRepo: "https://github.com/nova-collective/crypto-py",
},
};

module.exports = config;
21 changes: 21 additions & 0 deletions ci/functions.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const execSync = require("child_process").execSync;
const fs = require("fs");
const path = require("path");
const config = require("./config");

const execSyncOptions = { stdio: "inherit" };

@@ -68,6 +70,25 @@ const functions = {
process.exit(1);
}
},
installPythonLibs: function ({ libs }) {
console.log(libs);

try {
if (libs.includes("crypto-py")) {
const libPath = path.resolve("lib");
const repo = config.installPythonLibs.cryptoPyRepo;

execSync(`cd ${libPath} && git clone ${repo}`, execSyncOptions);
execSync(
`cd ${libPath}/crypto-py && pip install -r requirements.txt`,
execSyncOptions,
);
}
} catch (e) {
console.log(e);
process.exit(1);
}
},
};

module.exports = functions;
6 changes: 2 additions & 4 deletions contracts/DEC.sol
Original file line number Diff line number Diff line change
@@ -12,10 +12,8 @@ contract DEC {
Encrypted country;

struct Encrypted {
string iv;
string ephemPublicKey;
string ciphertext;
string mac;
string chiper;
string nonce;
}

constructor(
10 changes: 5 additions & 5 deletions election-scripts/create-dec.ts
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ import { ethers } from "hardhat";
import { DEC, Response, result, CreateDECResponse } from "./types";
import { DECMock, VoterEOA } from "./__mocks__";
import { encryptString } from "../lib";
import { Encrypted } from "eth-crypto";
import { Encrypted } from "../lib/types";

/**
* This function encrypt the Voter's DECs data and deploys the smart contract instance.
@@ -35,10 +35,10 @@ export async function main(
const dec = decsData || DECMock;
const key = privateKey || VoterEOA.privateKey;

const eTaxCode: Encrypted = await encryptString(dec.taxCode, key);
const eMunicipality: Encrypted = await encryptString(dec.municipality, key);
const eRegion: Encrypted = await encryptString(dec.region, key);
const eCountry: Encrypted = await encryptString(dec.country, key);
const eTaxCode: Encrypted = encryptString(dec.taxCode, key);
const eMunicipality: Encrypted = encryptString(dec.municipality, key);
const eRegion: Encrypted = encryptString(dec.region, key);
const eCountry: Encrypted = encryptString(dec.country, key);

const contract = await ContractFactory.deploy(
eTaxCode,
27 changes: 18 additions & 9 deletions lib/crypto-utils.test.ts
Original file line number Diff line number Diff line change
@@ -4,21 +4,30 @@ import { mockEOAs } from "./__mocks__";
describe("Crypto Utils", () => {
const privateKey = mockEOAs[0].privateKey;

it("should encrypt and decrypt a string", async () => {
it("should encrypt and decrypt a string", () => {
const originalString = "Hello, world!";
const encryptedString = await encryptString(originalString, privateKey);
const encryptedString = encryptString(originalString, privateKey);

const decryptedString = await decryptString(encryptedString, privateKey);
expect(decryptedString).toEqual(originalString);
const decryptedString = decryptString(
encryptedString.chiper,
privateKey,
encryptedString.nonce,
);
expect(decryptedString.message).toEqual(originalString);
});

it("should handle decryption with incorrect private key", async () => {
const originalString = "Hello, world!";
const encryptedString = await encryptString(originalString, privateKey);
const encryptedString = encryptString(originalString, privateKey);
const incorrectPrivateKey = "incorrectPrivateKey";

await expect(
decryptString(encryptedString, incorrectPrivateKey),
).rejects.toThrow("Error decrypting string");
try {
decryptString(
encryptedString.chiper,
incorrectPrivateKey,
encryptedString.nonce,
);
} catch (e: any) {
expect(e.message).toBe("Error decrypting string");
}
});
});
83 changes: 64 additions & 19 deletions lib/crypto-utils.ts
Original file line number Diff line number Diff line change
@@ -6,8 +6,9 @@
* is because If we send the data and then encrypt it in solidity, the data will be visible in the transaction that
* in the first place was used to send the data to the contract. Also, solidity doesn't have a function to encrypt.
*/
import * as EthCrypto from "eth-crypto";
import { Encrypted } from "eth-crypto";
import { Encrypted, Decrypted } from "./types";
import { execSync, ExecSyncOptionsWithStringEncoding } from "child_process";
import * as path from "path";

/**
* This function encrypt a string by using a private key possibly from an EOA (Voter's account).
@@ -16,20 +17,36 @@ import { Encrypted } from "eth-crypto";
*
* @param {string} decryptedString - the string to be encrypted
* @param {string} privateKey - a private key, e.g. from the EOA
* @returns {Promise<Encrypted>} - the encrypted output string
* @returns {Encrypted} - the encrypted output string
*/
export async function encryptString(
export function encryptString(
decryptedString: string,
privateKey: string,
): Promise<Encrypted> {
): Encrypted {
try {
const publicKey = await EthCrypto.publicKeyByPrivateKey(privateKey);
const execSyncOptions = {
stdio: "pipe",
} as ExecSyncOptionsWithStringEncoding;

const encrypted = await EthCrypto.encryptWithPublicKey(
publicKey,
decryptedString,
if (privateKey.startsWith("0x")) {
privateKey = privateKey.substring(2);
}

const cryptoPyPath = getCryptoPyPath();

const encrypted = execSync(
`cd ${cryptoPyPath} && python3 Crypto.py AESGCM_encrypt --key="${privateKey}" --secret="${decryptedString}"`,
execSyncOptions,
);
return encrypted;

const en = encrypted.toString().split("\n");
const chiper = en[0].split(" ")[1];
const nonce = en[1].split(" ")[1];

return {
chiper,
nonce,
};
} catch (e) {
console.error(e);
throw new Error("Error encrypting string");
@@ -41,20 +58,48 @@ export async function encryptString(
*
* @param {Encrypted} encryptedString - the secret to decrypt
* @param {string} privateKey - A private key possibly from an EOA
* @returns {Promise<string>} - the string decrypted
* @param {string} nonce - The nonce value used for the encryption
* @returns {Decrypted} - the string decrypted
*/
export async function decryptString(
encryptedString: Encrypted,
export function decryptString(
encryptedString: string,
privateKey: string,
): Promise<string> {
nonce: string,
): Decrypted {
try {
const decrypted = await EthCrypto.decryptWithPrivateKey(
privateKey,
encryptedString,
const execSyncOptions = {
stdio: "pipe",
} as ExecSyncOptionsWithStringEncoding;

if (privateKey.startsWith("0x")) {
privateKey = privateKey.substring(2);
}

const cryptoPyPath = getCryptoPyPath();
const decrypted = execSync(
`cd ${cryptoPyPath} && python3 Crypto.py AESGCM_decrypt --key=${privateKey} --nonce=${nonce} --chiper=${encryptedString}`,
execSyncOptions,
);

const de = decrypted.toString().split("\n");
const message = de[0].substring(
de[0].indexOf("message: ") + "message: ".length,
);
return decrypted;

return { message };
} catch (e) {
console.error(e);
throw new Error("Error decrypting string");
}
}

/**
* The crypto-py library should be manually copy-pasted (or git cloned) inside the lib folder.
* Linux and MacOS users can in alternative create a symbolic link.
* After that, activate the python venv in the crypto-py folder, e.g. for linux: source venv/bin/activate
*
* @returns {string} - the absolute path of the crypto-py library
*/
function getCryptoPyPath() {
const cryptoRelativePath = path.join("lib", "crypto-py");
return path.resolve(cryptoRelativePath);
}
8 changes: 8 additions & 0 deletions lib/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type Encrypted = {
chiper: string;
nonce: string;
};

export type Decrypted = {
message: string;
};
Loading