wrote example for our algorithm and tried to add a cli

This commit is contained in:
Faraphel 2024-07-05 00:23:26 +02:00
parent b7080ddd0c
commit 8ebb40c0f6
46 changed files with 543 additions and 221 deletions

View file

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIUFiOqi4pgJB9drME4SMSjaF+PoyMwDQYJKoZIhvcNAQEL
BQAwXzELMAkGA1UEBhMCRlIxETAPBgNVBAgMCFByb3ZpbmNlMREwDwYDVQQHDAhM
b2NhbGl0eTEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRMwEQYDVQQDDApkb21haW4u
Y29tMB4XDTI0MDcwNDAwMDI1MVoXDTI1MDcwNTAwMDI1MVowXzELMAkGA1UEBhMC
RlIxETAPBgNVBAgMCFByb3ZpbmNlMREwDwYDVQQHDAhMb2NhbGl0eTEVMBMGA1UE
CgwMT3JnYW5pemF0aW9uMRMwEQYDVQQDDApkb21haW4uY29tMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEApvut4HKl4ZyECZFgL8DGnsr8UJmT7MYwReWJ
Q6nuAucUD8lkWWikYwoSiz57ptpYXLMRLWzOot0h3GBWHB6zcMgFOfTXjrd8heN5
pknbNQYywVUFJsdN3GXJ1IjSDFNSlsBmDh1mvVmVqWNeGv2rpJSxC6hV0iLMRXYK
J9dLM4IIH2zLUdSkpmzxzOejTH1SYAiqyk91eJvikA0SjlwUC8gRe71HSVIuNqyQ
wVCv/00wjIg6A8Q2fOhFlfvp4IoKCtTviKuDnXIK7Tn02dICHcDeNWis7G8NNosU
nRTbG9UH62eJ0g5IW3e/3ZA4peX20rGwPf599VlFLzGxnW35CwIDAQABMA0GCSqG
SIb3DQEBCwUAA4IBAQCmH/UHxIcVDjNFQDAQuWe6+UEfOq97qgd4D3j/igAmbfvx
6puPKuCFZKWCeNMb3B9+rFRDHq4NJgbPL22iGUPdZwBjdjt8HZhrheQ+/TEy4Zcf
I6NvuTVAjJmijfHTDQ14koWIrvznlKBNTX1cPtUQnyCrhKpzUUXp9kpuwVlRt5JQ
WpYCJw5XycJiW52vXyZsCd2S1xecD0Pwq5u6+25jM/yblx3s2C2ezcNhIzBufG2i
xz8TSykG+NjhzHfvg8M5eln05kTaf9wHvwkyuH9+WHQUZFeauUzOFX/E6SEJ74s9
vYssU5Rue2tBOZhuSkqRgE2FsVGJ0ccZQWVfZ6X3
-----END CERTIFICATE-----

27
assets/admin/private.key Normal file
View file

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEApvut4HKl4ZyECZFgL8DGnsr8UJmT7MYwReWJQ6nuAucUD8lk
WWikYwoSiz57ptpYXLMRLWzOot0h3GBWHB6zcMgFOfTXjrd8heN5pknbNQYywVUF
JsdN3GXJ1IjSDFNSlsBmDh1mvVmVqWNeGv2rpJSxC6hV0iLMRXYKJ9dLM4IIH2zL
UdSkpmzxzOejTH1SYAiqyk91eJvikA0SjlwUC8gRe71HSVIuNqyQwVCv/00wjIg6
A8Q2fOhFlfvp4IoKCtTviKuDnXIK7Tn02dICHcDeNWis7G8NNosUnRTbG9UH62eJ
0g5IW3e/3ZA4peX20rGwPf599VlFLzGxnW35CwIDAQABAoIBAEuzh9VcRIWunlF0
HaYogCMXJSIpLd3Gz7WwZPVPAX9BYV/yzlKWVQgtVdDYp9gx3qNP7vaoAFnnZGVz
KzaeWH1FwNDQhjTGTGaqhMj1bLJyN+pb7/TvoAXOA50d1hQOZj+/w8ScYapwBaCA
UvZrkDgRzN3bF+UnL3JCHEKJoScdDCGZGlvM/c7hQZYyZ94MuUT9+njkymGXm/H2
Xkyf1AWnXMeQRs1vBLwtNxshQzfpoEAuYQ01mNjaHNyyW8/VYXzY+cUUDjuQMoxR
0VT/3N7IJFrdQdw2d5nfae59iX+mJM3dZ5hsSNimN9p4Q+5jG6uDOJP6QC/TKkDm
gYLFf/ECgYEA63q9cJuQ4CYbCRllyR/JhjeczT87D9wCE4/TxPLHIRbYXUTwvVbd
tII4lHR4mnsJUVK+cDhXzPWtgLhFZ3oY7tjv89Nj8SMAZA+gh7XLS8mYuvG8OjgJ
TZoJbSOGR5RJDV5BLxaR2czC+si/IsDn2rEjuAeBzu7cdBd6yq7EUjMCgYEAtYje
kn62UQjqCPcprA5Zumki8zBJfQlHXOPJh58hczla+T+wyFCMA4e3rE2ZYUUeCUZu
fM+qbqAP7CQW2lY7msidtlH+uhutgjCmJ9mHFpFS9bN7iRX7t6oGfnQJ13nvoaF0
7D8ebxVnn5paCeu4vUBQ2mYKxjhJdnTx/3yH1ckCgYBG0OG5xL77+dm1kdK/enTD
jWP1gaeEbHifY2ifWRezhshIvFvdxQrlpyfW1XQTmR7DOywUWY1mERg9lq0gomJv
KgR3gkITGaCbduujBHP/9b+dsOcXZxS9Jq7hCIbwbdLOV2MpAxOXuXGFs+tvSy4u
4YjJZlCOZ90aeJkv7QETawKBgEmzQqF5Hi2yD8oKBnoa7WTX8F+JGBzSWo2k0Rnl
iiAMhhmxOOVqhh2cyP4EFyQ9el9Ln+m+KbR1+WDmmfyUi+hgUF9H1MHcIMo9VAfT
sZuA7oxgDORv71z2g2JtW92GXLpjIWQUkBeLOiG6+ZkTgVIcPXcdfHxTN8gG3ITc
Gw25AoGAcdR8DNJO/Oo7BlZKV/g5nUSzbdgIrT2gtT6ZUBaQZw3mLjiMHFfihtPn
hXfmXZ+ymaXxm6IRGcz9c28V0a9M+q29P1hWfQQVCk7yEdMHxlE4FBVg7ejIhw07
8dgM9v8tg6Nf3b0KGWrgnD87ds3uR6D536Bhh3jmhq27U8k45OY=
-----END RSA PRIVATE KEY-----

View file

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIUaZDZAVUe0kK/3m6RxCg44Rv8ToswDQYJKoZIhvcNAQEL
BQAwXzELMAkGA1UEBhMCRlIxETAPBgNVBAgMCFByb3ZpbmNlMREwDwYDVQQHDAhM
b2NhbGl0eTEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRMwEQYDVQQDDApkb21haW4u
Y29tMB4XDTI0MDcwNDAwMDI1NVoXDTI1MDcwNTAwMDI1NVowXzELMAkGA1UEBhMC
RlIxETAPBgNVBAgMCFByb3ZpbmNlMREwDwYDVQQHDAhMb2NhbGl0eTEVMBMGA1UE
CgwMT3JnYW5pemF0aW9uMRMwEQYDVQQDDApkb21haW4uY29tMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0xfSOKdy/FKvLsNatkdg22vbwgKHjHeS0kXu
k+MVHvbp+r2uwwhbYilhLWBk6OM94ftVJh0441bkCnoPACMd1goqxvUkP4m+4uaX
+lVup5JHAre5YXher3rX5K1Jyd7Rns7V0q01y6J7LnjRSMY2hZIgrQEoVc+HXVqS
idPaOl30W4U12UQv405y+yAHCjqWZEp9ZNO7cg6zMQCGyTs+u9/4wyqXIrXly0Br
R/MV1VyCvBSpT0913WksRXb2xJvPSwsiRGzgKJ0/LtiFC3hfNZWkfi4FVRazYO69
OPiXw+MbmodI9ie2TNvmk7TuxFPntrm9P0YqsOacymOYXS05uwIDAQABMA0GCSqG
SIb3DQEBCwUAA4IBAQBaNv/xmhRBmBfJQXnA8N03xg9vYlC0VyHQzhYRQ3kE9wb7
j4/lzbDgqRb5ok2zIrPPewcwZ4yM5tIyi78I0dYPtlCSLEyEqQJ2kNfYHWnKvC5D
ipDeJrymCz0VGNAAqH9Ib18HoxrLM2+tQtavs6p0Iu9V14H3D/ouJhdfQV04PvgC
8QFFCmrvqw8WSAzhoXaD9pAxCQc4fJIDrMUN45nOjIUjSdi4vGClIryJ2Fmz7LP+
a/ZqciybqgybLz5pGp9gPFL7FKhw/sgypP7HqvUEyw+mejLNxcDXbmk+01Wjspfj
VAi/u0nCupYv5UfBVyPG6vBZ4qcOcX89qkHv4xl9
-----END CERTIFICATE-----

View file

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA0xfSOKdy/FKvLsNatkdg22vbwgKHjHeS0kXuk+MVHvbp+r2u
wwhbYilhLWBk6OM94ftVJh0441bkCnoPACMd1goqxvUkP4m+4uaX+lVup5JHAre5
YXher3rX5K1Jyd7Rns7V0q01y6J7LnjRSMY2hZIgrQEoVc+HXVqSidPaOl30W4U1
2UQv405y+yAHCjqWZEp9ZNO7cg6zMQCGyTs+u9/4wyqXIrXly0BrR/MV1VyCvBSp
T0913WksRXb2xJvPSwsiRGzgKJ0/LtiFC3hfNZWkfi4FVRazYO69OPiXw+MbmodI
9ie2TNvmk7TuxFPntrm9P0YqsOacymOYXS05uwIDAQABAoIBABjvZ+w8T3dh1wK5
ndYJUXYp5AAjZ1qe50+CZj++48hQF2yAiovMSWsrgyimidT+vtkaZMEHU6h7I53f
NDVqcIRPmCT/YSRGQ6+u2IYAIH2X6F54UGQkoV6uLqF7HMvFT9KoERb9Uez3iQCA
0gv8KgWWMNju2ZJlXNKYt9WjGlSpfIVbAxdGlFNWGKwWvAypfXMfdJY5P5U+Lk1Q
CqNZ/U1B5uaqbVbd9RfQJYtZny3h2OQGf4nSDXE2Gq63fOIbPdISjhaYCnHWBoBD
HzaO14tbz7hGeHLmNLB8p5SeoY1ZOA10YTdF1jtH+4gloKEwf1vcxUEXf3novn1X
f8NB620CgYEA9y+3wAx91c2sK57HVJEuicp9xmtXNjKVeoPnuk50DGjL4D/V3C1r
eM7hGfbD/98euSMkNs0F7zIkqXiBC45U4wOIaQHgVZbJM5Mhdvh4S7pZstETUA7k
XrN+c71ktms8fg7EjiBRfzi3wULWk5bmjKsc+sTlPACCFUt4zYe6zS0CgYEA2p6m
AtxYLkWA0Ci6xho4xU0iKCmGHeR+R4YuLd60/L7PHAySMCBzrha8jx9PpAppi27M
DaOu9H9VpNnApGBJVuHDTRq672ZPpPQ8Rbj8ZvCQ6TlsoMJuEO4kcTBfccYVCNS+
wYbRWpteK7GfL6YXC5HdxL9vFV2hpK0IFmuBg4cCgYEAyOddv5fnhqidsO5iMFe3
rYKI64Y+4ewHFgazhvdQ1u0uF1uK5GN+IDh1OHcaIpMkE3F+c5P7qMfmiF9K8yuB
zukGK+K8hJQDgAmrf1i/3TzevrmzqrQP5PCabFOY0bMi/YnfM20NEAv3PfqnEFnr
lJVW/nKdpkD7eXdX/iS9LRkCgYEAhzv0PXjII3djA2DuiHTYAVSBeI6XJA6f/uaF
0mIdWus9eoBcPeEVLe9qnK4lubenKlVTbGyAYUYTWHJKtGPLei8VfLC4SjbjtYpP
bmHL4HGXcm3PQHKFW3u0lz/xCpQZlujjRxt6ja3mRukNK5B2WPXWVUqGEJVm1FMk
2ZmO+CkCgYA6X1eHTPfY9Wy7uQEyamA6H/nUGFyKM85tGYU0D7xdU9ls0VFTuME4
0FAq8k1k9BbSAhrpsyYp/eIAHJ3gF88w/NyP/1HO1RTzpLcXiI/fzGb59i4hY6Gg
g7AyGGe62nfVhAD/WaMp+0iidXtd/ZwR09PaECUuU+UJ91BojlbwzA==
-----END RSA PRIVATE KEY-----

31
mains/__main__.py Normal file
View file

@ -0,0 +1,31 @@
import argparse
from mains import role
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest="role")
role.admin.load_parse(subparsers)
role.client.load_parse(subparsers)
role.machine.load_parse(subparsers)
arguments = parser.parse_args()
if not arguments:
parser.print_help()
exit(1)
match arguments.role:
case "admin":
role.admin.run(parser, arguments)
case "machine":
role.machine.run(parser, arguments)
case "client":
role.client.run(parser, arguments)
# if the role is unknown, show the usage
case _:
parser.print_usage()

View file

@ -1,21 +0,0 @@
import argparse
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument("-H", "--host", dest="hostname", type=str, default="127.0.0.1")
arg_parser.add_argument("-p", "--port", dest="port", type=int, default=57823)
arguments = arg_parser.parse_args()
if arguments:
import ssl
import socket
context = ssl.create_default_context()
with socket.create_connection((arguments.hostname, 443)) as sock_client:
with context.wrap_socket(sock_client, server_hostname=arguments.hostname) as ssl_sock_client:
print(ssl_sock_client.version())
ssl_sock_client.send(b"Hello World!")

3
mains/role/__init__.py Normal file
View file

@ -0,0 +1,3 @@
from . import admin
from . import client
from . import machine

View file

@ -0,0 +1,2 @@
from .argparse import load_parse
from .run import run

View file

@ -0,0 +1,2 @@
from . import create
from . import init

View file

@ -0,0 +1,2 @@
from .argparse import load_parse
from .run import run

View file

@ -0,0 +1,11 @@
import argparse
from . import create_role
def load_parse(subparsers):
subparser: argparse.ArgumentParser = subparsers.add_parser("create")
subsubparsers = subparser.add_subparsers(dest="create_role")
create_role.client.load_parse(subsubparsers)
create_role.machine.load_parse(subsubparsers)

View file

@ -0,0 +1,2 @@
from . import machine
from . import client

View file

@ -0,0 +1,2 @@
from .argparse import load_parse
from .run import run

View file

@ -0,0 +1,8 @@
import argparse
def load_parse(subparsers):
subparser: argparse.ArgumentParser = subparsers.add_parser("client")
subparser.add_argument("-u", "--username", dest="username", type=str, required=True)
subparser.add_argument("-p", "--password", dest="password", type=str, required=True)

View file

@ -0,0 +1,38 @@
import argparse
from pathlib import Path
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
def run(parser: argparse.ArgumentParser, arguments: argparse.Namespace):
# TODO(Faraphel): should NOT be named "client"
print("creating new client...")
directory_client = Path(f"./assets/client/{arguments.username}/")
if directory_client.exists():
raise ValueError("This client already exists !")
directory_client.mkdir(parents=True)
# Generate a private key
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend(),
)
(directory_client / "private.key").write_bytes(
private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.OpenSSH,
encryption_algorithm=serialization.BestAvailableEncryption(arguments.password.encode()),
)
)
(directory_client / "public.key").write_bytes(
private_key.public_key().public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.OpenSSH,
)
)

View file

@ -0,0 +1,2 @@
from .argparse import load_parse
from .run import run

View file

@ -0,0 +1,7 @@
import argparse
def load_parse(subparsers):
subparser: argparse.ArgumentParser = subparsers.add_parser("machine")
subparser.add_argument("-n", "--name", dest="name", type=str, required=True)

View file

@ -0,0 +1,67 @@
import argparse
from datetime import datetime, timedelta
from pathlib import Path
from cryptography import x509
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import rsa
def run(parser: argparse.ArgumentParser, arguments: argparse.Namespace):
print("creating a new machine...")
directory_admin = Path("./assets/admin/")
if not directory_admin.exists():
raise ValueError("Can't find the admin. Have you initialized it ?")
directory_machine = Path(f"./assets/machine/{arguments.name}/")
if directory_machine.exists():
raise ValueError("This machine already exists !")
directory_machine.mkdir(parents=True)
# Generate a private key
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
(directory_machine / "private.key").write_bytes(
private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption(),
)
)
certificate_admin = x509.load_pem_x509_certificate(
(directory_admin / "certificate.pem").read_bytes()
)
private_key_admin = serialization.load_pem_private_key(
(directory_admin / "private.key").read_bytes(),
password=None
)
# Generate a self-signed root certificate
subject = x509.Name([
x509.NameAttribute(x509.NameOID.COUNTRY_NAME, "FR"),
x509.NameAttribute(x509.NameOID.STATE_OR_PROVINCE_NAME, "Province"),
x509.NameAttribute(x509.NameOID.LOCALITY_NAME, "Locality"),
x509.NameAttribute(x509.NameOID.ORGANIZATION_NAME, "Organization"),
x509.NameAttribute(x509.NameOID.COMMON_NAME, "domain.com"),
])
certificate = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(certificate_admin.subject)
.public_key(private_key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.now() - timedelta(days=1)) # TODO(Faraphel): settings
.not_valid_after(datetime.now() + timedelta(days=365)) # TODO(Faraphel): settings
.sign(private_key_admin, hashes.SHA256())
)
# Save the root certificate to a file
(directory_machine / "certificate.pem").write_bytes(certificate.public_bytes(serialization.Encoding.PEM))
print("machine created !")

View file

@ -0,0 +1,15 @@
import argparse
from . import create_role
def run(parser: argparse.ArgumentParser, arguments: argparse.Namespace):
match arguments.create_role:
case "client":
create_role.client.run(parser, arguments)
case "machine":
create_role.machine.run(parser, arguments)
# if the subcommand is not known, show the help
case _:
parser.print_usage()

View file

@ -0,0 +1,2 @@
from .argparse import load_parse
from .run import run

View file

@ -0,0 +1,5 @@
import argparse
def load_parse(subparsers):
subparser: argparse.ArgumentParser = subparsers.add_parser("init")

View file

@ -0,0 +1,53 @@
import argparse
from datetime import datetime, timedelta
from pathlib import Path
from cryptography import x509
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import rsa
def run(parser: argparse.ArgumentParser, arguments: argparse.Namespace):
print("initializing the admin...")
directory = Path(f"./assets/admin/")
if directory.exists():
raise ValueError("The admin already exists !")
directory.mkdir(parents=True)
# Generate a private key
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=4096,
)
(directory / "private.key").write_bytes(
private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption(),
)
)
# Generate a self-signed root certificate
subject = x509.Name([
x509.NameAttribute(x509.NameOID.COUNTRY_NAME, "FR"),
x509.NameAttribute(x509.NameOID.STATE_OR_PROVINCE_NAME, "Province"),
x509.NameAttribute(x509.NameOID.LOCALITY_NAME, "Locality"),
x509.NameAttribute(x509.NameOID.ORGANIZATION_NAME, "Organization"),
x509.NameAttribute(x509.NameOID.COMMON_NAME, "domain.com"),
])
certificate = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(subject)
.public_key(private_key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.now() - timedelta(days=1)) # TODO(Faraphel): settings
.not_valid_after(datetime.now() + timedelta(days=365)) # TODO(Faraphel): settings
.sign(private_key, hashes.SHA256())
)
# Save the root certificate to a file
(directory / "certificate.pem").write_bytes(certificate.public_bytes(serialization.Encoding.PEM))

View file

@ -0,0 +1,11 @@
import argparse
from . import action
def load_parse(subparsers):
subparser: argparse.ArgumentParser = subparsers.add_parser("admin")
subsubparsers = subparser.add_subparsers(dest="action")
action.create.load_parse(subsubparsers)
action.init.load_parse(subsubparsers)

15
mains/role/admin/run.py Normal file
View file

@ -0,0 +1,15 @@
import argparse
from . import action
def run(parser: argparse.ArgumentParser, arguments: argparse.Namespace):
match arguments.action:
case "create":
action.create.run(parser, arguments)
case "init":
action.init.run(parser, arguments)
# if the subcommand is not known, show the help
case _:
parser.print_usage()

View file

@ -0,0 +1,2 @@
from .argparse import load_parse
from .run import run

View file

@ -0,0 +1,2 @@
from . import vote
from .argparse import load_parse

View file

@ -0,0 +1,9 @@
import argparse
def load_parse(subparsers):
subparser: argparse.ArgumentParser = subparsers.add_parser("vote")
subparser.add_argument("-u", "--username", dest="username", type=str, required=True)
subparser.add_argument("-p", "--password", dest="password", type=str, required=True)
subparser.add_argument("-v", "--vote", dest="vote", type=str, required=True)

View file

@ -0,0 +1,23 @@
import argparse
import json
import ssl
import socket
def run(parser: argparse.ArgumentParser, arguments: argparse.Namespace):
context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT)
context.load_verify_locations(arguments.certificate)
context.check_hostname = False
with (
socket.create_connection((arguments.hostname, arguments.port)) as sock_client,
context.wrap_socket(sock_client, server_hostname=arguments.hostname) as ssl_sock_client
):
data = {
"username": arguments.username,
"password": arguments.password,
"vote": arguments.vote,
}
ssl_sock_client.send(json.dumps(data).encode())
print("message sent.")

View file

@ -0,0 +1,15 @@
import argparse
from pathlib import Path
from . import action
def load_parse(subparsers):
subparser: argparse.ArgumentParser = subparsers.add_parser("client")
subparser.add_argument("-H", "--host", dest="hostname", type=str, default="127.0.0.1")
subparser.add_argument("-P", "--port", dest="port", type=int, default=57823)
subparser.add_argument("-cc", "--certificate", dest="certificate", type=Path, required=False)
subsubparsers = subparser.add_subparsers(dest="action")
action.load_parse(subsubparsers)

13
mains/role/client/run.py Normal file
View file

@ -0,0 +1,13 @@
import argparse
from . import action
def run(parser: argparse.ArgumentParser, arguments: argparse.Namespace):
match arguments.action:
case "vote":
action.vote.run(parser, arguments)
# if the subcommand is not known, show the help
case _:
parser.print_usage()

View file

@ -0,0 +1,2 @@
from .argparse import load_parse
from .run import run

View file

@ -0,0 +1,11 @@
import argparse
from pathlib import Path
def load_parse(subparsers):
subparser: argparse.ArgumentParser = subparsers.add_parser("machine")
subparser.add_argument("-H", "--host", dest="hostname", type=str, default="0.0.0.0")
subparser.add_argument("-p", "--port", dest="port", type=int, default=57823)
subparser.add_argument("-cc", "--certificate", dest="certificate", type=Path, required=True)
subparser.add_argument("-ck", "--private-key", dest="private_key", type=Path, required=True)

23
mains/role/machine/run.py Normal file
View file

@ -0,0 +1,23 @@
import argparse
import json
def run(parser: argparse.ArgumentParser, arguments: argparse.Namespace):
import ssl
import socket
context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(arguments.certificate, arguments.private_key)
with (
socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock_server,
context.wrap_socket(sock_server, server_side=True) as ssl_sock_server
):
ssl_sock_server.bind((arguments.hostname, arguments.port))
ssl_sock_server.listen(5)
while True:
print("waiting for a connection...")
connect, address = ssl_sock_server.accept()
data = json.loads(connect.recv())
print(data)

View file

@ -1,24 +0,0 @@
import argparse
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument("-H", "--host", dest="hostname", type=str, default="0.0.0.0")
arg_parser.add_argument("-p", "--port", dest="port", type=int, default=57823)
arguments = arg_parser.parse_args()
if arguments:
import ssl
import socket
context = ssl.create_default_context()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock_server:
sock_server.bind((arguments.hostname, arguments.port))
sock_server.listen(5)
with context.wrap_socket(sock_server, server_side=True) as ssl_sock_server:
data = ssl_sock_server.recv()
print(data)

View file

@ -10,9 +10,7 @@ class Card:
Represent the card of an elector.
"""
def __init__(self, name: str, pin: str):
self.name = name
def __init__(self, pin: str):
self._private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,

View file

@ -167,8 +167,9 @@ class Machine:
if elector is None:
print("Lélecteur nest pas inscrit dans la liste électorale.")
return False
print(f"Lélecteur {elector.name} vote par procuration.")
print(f"Lélecteur {elector.name} peut voter.")
print(f"Lélecteur {elector.name} est sur la liste électorale et vote par procuration.")
else:
print(f"Lélecteur {elector.name} est sur la liste électorale.")
# Is the fingerprint matching?
if not self.check_fingerprint(elector, fingerprint):
@ -176,7 +177,7 @@ class Machine:
return False
# Lélecteur est authentifié.
print(f"Électeur {elector.name} authentifié")
print(f"Lélecteur {elector.name} est authentifié")
return True
def vote(self, card: Card, vote: str) -> bool:
@ -256,7 +257,7 @@ class Machine:
self._vote_list.append(vote)
random.shuffle(self._vote_list)
print(f"Vote de {elector.name} comptabilisé!")
print(f"Vote de {elector.name} comptabilisé(e)!")
return True
def cloture_du_vote(self) -> tuple[list[str], bytes]:

View file

@ -55,6 +55,3 @@ machine_certificate = builder.sign(admin_private_key, algorithm=hashes.SHA256())
print(machine_certificate)
# check that the machine
machine_certificate.verify_directly_issued_by(admin_certificate)
#

View file

@ -8,7 +8,7 @@ from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
class Proof:
date: datetime
public_key_votant: RSAPublicKey
public_key_elector: RSAPublicKey
public_key_mandataire: RSAPublicKey
proof_signature: bytes

View file

@ -1,16 +0,0 @@
class Electeur:
def __init__(self, nom, prenom, empreinte_digitale):
self.nom = nom
self.prenom = prenom
self.empreinte_digitale = empreinte_digitale
self.carte_election = None
self.code_pin = None
def recevoir_carte_election(self, carte_election):
self.carte_election = carte_election
def definir_code_pin(self, code_pin):
self.code_pin = code_pin
def authentifier(self):
return self.carte_election.est_authentique(self.empreinte_digitale, self.code_pin)

View file

@ -1,48 +0,0 @@
from source.Card import Card
from source.wtf.Electeur import Electeur
from source.wtf.Machine2 import Machine2
if __name__ == "__main__":
# Création d'un électeur
electeur1 = Electeur("Alice", "Dupont", "empreinte_alice123")
electeur2 = Electeur("Bob", "Martin", "empreinte_bob456")
# Création de cartes d'élection pour les électeurs
carte1 = Card(electeur1, "cle_publique_alice")
carte2 = Card(electeur2, "cle_publique_bob")
# Activation des cartes avec un code PIN
carte1.activer("cle_privee_chiffree_alice", "code_pin_chiffre_alice")
carte2.activer("cle_privee_chiffree_bob", "code_pin_chiffre_bob")
# Attribution des cartes aux électeurs
electeur1.recevoir_carte_election(carte1)
electeur2.recevoir_carte_election(carte2)
# Définition des codes PIN
electeur1.definir_code_pin("1234")
electeur2.definir_code_pin("5678")
# Création d'une machine à voter avec un certificat
certificat_machine = "certificat_de_la_machine"
machine = Machine2(certificat_machine)
# Chargement de la liste électorale dans la machine
liste_electorale = {
"cle_publique_alice": electeur1.nom,
"cle_publique_bob": electeur2.nom
}
machine.charger_liste_electorale(liste_electorale)
# Authentification et vote d'un électeur
if machine.authentifier_electeur(electeur1):
preuve_vote = {
"vote": "Choix d'Alice",
"preuve": "Preuve de vote d'Alice"
}
machine.enregistrer_vote(preuve_vote)
# Fin du vote et publication des résultats
machine.fin_de_vote()
resultats = machine.publier_resultats()
print("Résultats publiés:", resultats)

View file

@ -1,23 +0,0 @@
class Machine2:
def __init__(self, certificat):
self.certificat = certificat
self.liste_electorale = {}
self.bdd_votes = []
self.bdd_preuves = []
def charger_liste_electorale(self, liste_electorale):
self.liste_electorale = liste_electorale
def authentifier_electeur(self, electeur):
return electeur.authentifier() and electeur.carte_election.cle_publique in self.liste_electorale
def enregistrer_vote(self, preuve_vote):
self.bdd_votes.append(preuve_vote['vote'])
self.bdd_preuves.append(preuve_vote)
def publier_resultats(self):
return self.bdd_votes
def fin_de_vote(self):
# Bloquer les nouveaux votes
self.bloque = True

View file

View file

@ -1,37 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "initial_id",
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
""
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View file

@ -1,61 +1,82 @@
import hashlib
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.asymmetric import padding
from source.Card import Card
from source.models.Elector import Elector
#from source.Certificate import Certificate
from source.Machine import Machine
# Vote électronique
# 3 personnes
alice = {
"name": "Alice",
"password": "6060",
"empreinte": "empreinteA",
"vote": "Riri",
}
bob = {
"name": "Bob",
"password": "0100",
"empreinte": "empreinteB",
"vote": "Toto",
}
eve = {
"name": "Eve",
"password": "008",
"empreinte": "empreinteE",
"vote": "Jack",
}
personnes = [alice, bob, eve]
# Création des cartes
alice_card = Card("Alice", "6060")
bob_card = Card("Bob", "0100")
eve_card = Card("Eve", "0008")
print(f"carte alice pubkey: {alice_card.public_key}")
print("Cartes délections créent")
input()
alice["card"] = Card(alice["password"])
bob["card"] = Card(bob["password"])
eve["card"] = Card(eve["password"])
print(f"Liste de cartes : {[personne['card'] for personne in personnes]}")
print("Cartes délections créées.")
print()
# Création de la liste électorale
# Eve peut voter pour Alice
alice_elector = Elector(name="Alice",
public_key_elector=alice_card.public_key,
fingerprint_elector="empreinteA",
public_key_mandataire=eve_card.public_key,
fingerprint_mandataire="empreinteE")
bob_elector = Elector("Bob", bob_card.public_key, "empreinteB")
eve_elector = Elector("Eve", eve_card.public_key, "empreinteE")
emerging_list = [alice_elector, bob_elector, eve_elector]
print(f"alice name: {alice_elector.name}")
print(f"alice pubkey: {alice_elector.public_key_elector}")
print(f"alice pubkey mandataire: {alice_elector.public_key_mandataire}")
print(f"alice empreinte: {alice_elector.hashed_fingerprint_elector}")
print(f"alice empreinte mandataire: {alice_elector.hashed_fingerprint_mandataire}")
print(f"liste démargement: {emerging_list}")
print("Liste électorale crée.")
alice_elector = Elector(name=alice["name"],
public_key_elector=alice["card"].public_key, fingerprint_elector=alice["empreinte"],
public_key_mandataire=eve["card"].public_key, fingerprint_mandataire=eve["empreinte"])
bob_elector = Elector(name=bob["name"],
public_key_elector=bob["card"].public_key, fingerprint_elector=bob["empreinte"])
input()
emerging_list = [alice_elector, bob_elector]
print(f"Liste démargement: {emerging_list}")
print("Liste électorale créée.")
print()
# Création de la machine
machine = Machine(emerging_list)
print(f"machine pubkey : {machine._public_key.public_bytes()}")
print("Machine pour voter crée")
print(f"Machine pubkey : {machine.public_key}")
print("Machine pour voter créée")
print()
input()
# Votes des personnes
alice["password"] = "fleur"
for personne in personnes:
# Authentification
print()
print(f"La personne {personne["name"]} sauthentifie avec le mdp {personne["password"]} et lempreinte {personne["empreinte"]}.")
if not machine.authenticate(personne["card"], personne["password"], personne["empreinte"]):
continue
# Authentification
# Vote
# Vote
print()
print(f"La personne {personne["name"]} va voter pour {personne["vote"]}")
if not machine.vote(personne["card"], personne["vote"]):
continue
# Publication des résultats
#Machine.authenticate(Alice_card, 6060, "azerty")
#Machine.vote(Alice_card)
votes, sig_votes = machine.cloture_du_vote()
print()
print(votes)

2
tests/exemple2.py Normal file
View file

@ -0,0 +1,2 @@
# Vote à distance