wrote example for our algorithm and tried to add a cli
This commit is contained in:
parent
b7080ddd0c
commit
8ebb40c0f6
46 changed files with 543 additions and 221 deletions
20
assets/admin/certificate.pem
Normal file
20
assets/admin/certificate.pem
Normal 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
27
assets/admin/private.key
Normal 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-----
|
20
assets/machine/Beauvais/certificate.pem
Normal file
20
assets/machine/Beauvais/certificate.pem
Normal 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-----
|
27
assets/machine/Beauvais/private.key
Normal file
27
assets/machine/Beauvais/private.key
Normal 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
31
mains/__main__.py
Normal 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()
|
|
@ -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
3
mains/role/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from . import admin
|
||||
from . import client
|
||||
from . import machine
|
2
mains/role/admin/__init__.py
Normal file
2
mains/role/admin/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
from .argparse import load_parse
|
||||
from .run import run
|
2
mains/role/admin/action/__init__.py
Normal file
2
mains/role/admin/action/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
from . import create
|
||||
from . import init
|
2
mains/role/admin/action/create/__init__.py
Normal file
2
mains/role/admin/action/create/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
from .argparse import load_parse
|
||||
from .run import run
|
11
mains/role/admin/action/create/argparse.py
Normal file
11
mains/role/admin/action/create/argparse.py
Normal 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)
|
2
mains/role/admin/action/create/create_role/__init__.py
Normal file
2
mains/role/admin/action/create/create_role/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
from . import machine
|
||||
from . import client
|
|
@ -0,0 +1,2 @@
|
|||
from .argparse import load_parse
|
||||
from .run import run
|
|
@ -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)
|
38
mains/role/admin/action/create/create_role/client/run.py
Normal file
38
mains/role/admin/action/create/create_role/client/run.py
Normal 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,
|
||||
)
|
||||
)
|
|
@ -0,0 +1,2 @@
|
|||
from .argparse import load_parse
|
||||
from .run import run
|
|
@ -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)
|
67
mains/role/admin/action/create/create_role/machine/run.py
Normal file
67
mains/role/admin/action/create/create_role/machine/run.py
Normal 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 !")
|
15
mains/role/admin/action/create/run.py
Normal file
15
mains/role/admin/action/create/run.py
Normal 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()
|
2
mains/role/admin/action/init/__init__.py
Normal file
2
mains/role/admin/action/init/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
from .argparse import load_parse
|
||||
from .run import run
|
5
mains/role/admin/action/init/argparse.py
Normal file
5
mains/role/admin/action/init/argparse.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
import argparse
|
||||
|
||||
|
||||
def load_parse(subparsers):
|
||||
subparser: argparse.ArgumentParser = subparsers.add_parser("init")
|
53
mains/role/admin/action/init/run.py
Normal file
53
mains/role/admin/action/init/run.py
Normal 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))
|
11
mains/role/admin/argparse.py
Normal file
11
mains/role/admin/argparse.py
Normal 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
15
mains/role/admin/run.py
Normal 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()
|
2
mains/role/client/__init__.py
Normal file
2
mains/role/client/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
from .argparse import load_parse
|
||||
from .run import run
|
2
mains/role/client/action/__init__.py
Normal file
2
mains/role/client/action/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
from . import vote
|
||||
from .argparse import load_parse
|
9
mains/role/client/action/argparse.py
Normal file
9
mains/role/client/action/argparse.py
Normal 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)
|
23
mains/role/client/action/vote.py
Normal file
23
mains/role/client/action/vote.py
Normal 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.")
|
15
mains/role/client/argparse.py
Normal file
15
mains/role/client/argparse.py
Normal 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
13
mains/role/client/run.py
Normal 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()
|
2
mains/role/machine/__init__.py
Normal file
2
mains/role/machine/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
from .argparse import load_parse
|
||||
from .run import run
|
11
mains/role/machine/argparse.py
Normal file
11
mains/role/machine/argparse.py
Normal 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
23
mains/role/machine/run.py
Normal 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)
|
|
@ -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)
|
|
@ -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,
|
||||
|
|
|
@ -167,8 +167,9 @@ class Machine:
|
|||
if elector is None:
|
||||
print("L’électeur n’est 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]:
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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"]} s’authentifie avec le mdp {personne["password"]} et l’empreinte {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
2
tests/exemple2.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
|
||||
# Vote à distance
|
Loading…
Reference in a new issue