Compare commits

...

91 Commits

Author SHA1 Message Date
5affbb0043 Merge pull request 'gpio' (#2) from test into main
Reviewed-on: #2
2024-05-14 05:45:25 -07:00
EggMan20339
cfb618134e gpio 2024-05-14 12:44:23 -04:00
cfea64d258 Merge pull request 'gpio' (#1) from test into main
Reviewed-on: #1
2024-05-14 05:42:29 -07:00
e86a794582 Merge branch 'main' into test 2024-05-14 05:42:08 -07:00
EggMan20339
bb9f650edd gpio 2024-05-14 12:40:55 -04:00
EggMan
54eeebdb0f removed NFC 2024-05-14 07:43:22 -04:00
EggMan
f63cb0f92a made 3 second door unlock instead of 5 2024-05-14 07:35:46 -04:00
EggMan20339
165df2de5a gpio 2024-05-09 23:28:50 -04:00
EggMan20339
40df6174a9 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	main.py
2024-05-10 03:23:57 -04:00
EggMan20339
bd6903b7a2 more nfc 2024-05-10 03:23:40 -04:00
EggMan
7e3b6678d6 revert to before nfc 2024-05-09 23:14:52 -04:00
EggMan20339
51cdc8d4e2 more nfc 2024-05-09 22:46:21 -04:00
EggMan20339
fdb0e045f8 more nfc 2024-05-09 22:36:28 -04:00
EggMan20339
eabd40db41 more nfc 2024-05-09 22:34:53 -04:00
EggMan20339
b42085c6ef more nfc 2024-05-09 22:26:26 -04:00
EggMan20339
e800879339 more nfc 2024-05-09 22:13:00 -04:00
EggMan20339
5c4b97fb59 more nfc 2024-05-09 22:02:50 -04:00
EggMan20339
be315e85aa more nfc 2024-05-09 21:59:18 -04:00
EggMan20339
9a55dec5f2 more nfc 2024-05-09 21:53:18 -04:00
EggMan20339
386cbc2c0a try nfc 2024-05-09 21:47:06 -04:00
EggMan20339
88e02f1fee test2 2024-05-09 21:39:07 -04:00
EggMan20339
9a75b7a1e3 test 2024-05-09 21:36:55 -04:00
EggMan20339
0b5197e546 modified script storage path 2024-05-09 21:32:22 -04:00
EggMan20339
002ab064b7 gpio true 2024-05-09 21:25:06 -04:00
EggMan20339
0a9dd2931b nfc test main 2024-05-09 21:21:11 -04:00
EggMan20339
60e769ba05 added nfcpy to install script 2024-05-09 21:19:03 -04:00
EggMan20339
1edbf9c4ae testing NFC 2024-05-09 21:11:20 -04:00
EggMan20339
c3a1359339 changes 2024-05-09 20:16:10 -04:00
EggMan20339
0fd5ded5f9 changes 2024-05-09 20:14:33 -04:00
EggMan20339
53c13621fe changes 2024-05-09 20:11:39 -04:00
EggMan20339
7cc25d2c26 inclueded user ID and keyNumber in Register.py 2024-05-09 20:10:01 -04:00
EggMan20339
00d62ef7e4 script change 2024-05-09 19:39:40 -04:00
EggMan20339
8099e0e495 changed GPIO mode 2024-05-07 09:35:49 -04:00
EggMan20339
131233aa2c need pip fido2 update 2024-05-07 09:18:19 -04:00
EggMan20339
68f89139ac change in readme install scrip 2024-05-07 08:49:54 -04:00
EggMan20339
0a2543361c no pip install fido2 2024-05-07 08:37:26 -04:00
EggMan20339
be8132da64 model change on readme 2024-05-06 22:40:32 -04:00
EggMan20339
17dcdb9cb3 IT WORKED 2024-05-07 01:31:31 -04:00
EggMan20339
4bc9f31f51 yes gpio 2024-05-07 01:15:36 -04:00
EggMan20339
864e3c0931 no gpio 2024-05-07 01:12:54 -04:00
EggMan20339
c98c23a92d changes 2024-05-07 01:07:05 -04:00
EggMan20339
bd69ea7ed9 changed path 2024-05-07 00:56:24 -04:00
EggMan20339
b8793dd0b9 install fido2 2024-05-07 00:27:49 -04:00
EggMan20339
bf840f8539 more path 2024-05-07 00:27:10 -04:00
EggMan20339
62cbe0ac5b more path 2024-05-07 00:21:20 -04:00
EggMan20339
e14a01e521 wrong path 2024-05-07 00:18:23 -04:00
EggMan20339
536cdf875b wrong path 2024-05-07 00:15:00 -04:00
EggMan20339
46f8c36b33 wrong path 2024-05-07 00:04:46 -04:00
EggMan20339
d99b2d9f63 more sudo 2024-05-07 00:00:51 -04:00
EggMan20339
e5ce4e5b3b added sudo 2024-05-06 23:56:05 -04:00
EggMan20339
f5cc42df08 made into one liner 2024-05-06 23:43:24 -04:00
EggMan20339
ae1fcdfc54 i forgor screen install 2024-05-06 23:42:02 -04:00
EggMan20339
c785c06867 worked on scripts and mreadme 2024-05-06 23:35:33 -04:00
EggMan20339
9442566665 worked on scripts 2024-05-06 23:18:45 -04:00
772364f0a7 gpio fix 2024-05-06 16:29:17 -04:00
2cec7a3e0b fixing the door levels 2024-05-06 16:26:33 -04:00
c491ae0db3 added door sec level and user sec level check 2024-05-06 16:06:57 -04:00
d2c224145e led start change 2024-05-06 14:28:46 -04:00
920918ae91 script and crontab 2024-05-06 14:27:09 -04:00
93d6364752 script and crontab 2024-05-06 14:23:37 -04:00
9c53c7e946 more 2024-05-06 14:12:46 -04:00
8d73be773a chanmge 2024-05-06 14:09:53 -04:00
197a1d44b4 made config file 2024-05-06 14:04:37 -04:00
bd824583ed test remote pull again 2024-05-06 13:48:54 -04:00
dda38a3866 test remote pull 2024-05-06 13:47:44 -04:00
EggMan
e3f9b0444d SYNC 2024-05-06 11:52:11 -04:00
EggMan
8b701d218e made red led changes 2024-05-06 10:01:58 -04:00
EggMan
4cd3f6c275 changes 2024-05-06 10:00:10 -04:00
EggMan
8bd7bc2c22 changes 2024-05-06 09:50:26 -04:00
EggMan
6ee877b437 changes 2024-05-06 09:45:03 -04:00
203dde10ae test 2024-05-05 20:30:39 -04:00
5edd9f1041 changes 2024-05-05 20:22:43 -04:00
fe222c75c1 changes 2024-05-05 20:17:07 -04:00
ee9d3a7a58 error handling for untimley removal of key 2024-05-05 20:14:22 -04:00
43846ab6db changes 2024-05-05 20:10:28 -04:00
9ee5a8a9f0 changes 2024-05-05 19:58:51 -04:00
ecf9949d42 changes 2024-05-05 19:52:52 -04:00
359a0a8010 changes 2024-05-05 19:51:57 -04:00
36097703cb changes 2024-05-05 19:49:38 -04:00
d1eb79541d changes 2024-05-05 19:47:50 -04:00
3b8fe12655 changes 2024-05-05 19:45:58 -04:00
23b09a791a messign with leds 2024-05-05 19:34:39 -04:00
EggMan
41a2ec0e4d sync 2024-05-03 19:02:19 -04:00
dd60c4c2e2 added sleep when good auth 2024-05-02 22:24:20 -04:00
2ee000aaa8 idk 2024-05-02 22:11:59 -04:00
fcc3a3afbc somethin 2024-05-02 14:53:02 -04:00
6c37079876 seperated register and main 2024-05-02 14:47:20 -04:00
6f0003557c removed other files 2024-05-02 14:43:34 -04:00
0d7fad8a15 working! 2024-05-02 14:37:00 -04:00
e512edcde5 checkpoint 2024-05-02 13:32:22 -04:00
18507c7d79 idk 2024-05-02 12:25:29 -04:00
16 changed files with 488 additions and 562 deletions

2
.idea/CNSA-276-FP.iml generated
View File

@@ -5,7 +5,7 @@
<excludeFolder url="file://$MODULE_DIR$/.venv" />
<excludeFolder url="file://$MODULE_DIR$/venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.12 (CNSA-276-FP)" jdkType="Python SDK" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

2
.idea/dataSources.xml generated
View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="postgres@postgres.eggtech.net" uuid="75581ce6-3e75-4c9c-8544-e6c26149df60">
<data-source source="LOCAL" name="postgres@postgres.eggtech.net" uuid="6f5d4d62-2b6a-42c3-96e4-608e7bcea06f">
<driver-ref>postgresql</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.postgresql.Driver</jdbc-driver>

View File

@@ -1,45 +1,18 @@
# Copyright (c) 2018 Yubico AB
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import time
"""
Connects to the first FIDO device found (starts from USB, then looks into NFC),
creates a new credential for it, and authenticates the credential.
This works with both FIDO 2.0 devices as well as with U2F devices.
On Windows, the native WebAuthn API will be used.
"""
import pickle
import fido2.webauthn
from fido2.hid import CtapHidDevice
from fido2.client import Fido2Client, WindowsClient, UserInteraction
from fido2.server import Fido2Server
from getpass import getpass
import sys
import ctypes
import psycopg2
from fido2.ctap2 import Ctap2
# Handle user interaction
class CliInteraction(UserInteraction):
def prompt_up(self):
print("\nTouch your authenticator device now...\n")
@@ -59,6 +32,7 @@ if WindowsClient.is_available() and not ctypes.windll.shell32.IsUserAnAdmin():
client = WindowsClient("https://example.com")
else:
# Locate a device
dev = next(CtapHidDevice.list_devices(), None)
if dev is not None:
print("Use USB HID channel.")
@@ -83,12 +57,10 @@ else:
uv = "preferred"
print("Authenticator supports User Verification")
server = Fido2Server({"id": "example.com", "name": "Example RP"}, attestation="direct")
user = {"id": b"user_id", "name": "A. User"}
# Prepare parameters for makeCredential
create_options, state = server.register_begin(
user, user_verification=uv, authenticator_attachment="cross-platform"
@@ -111,10 +83,12 @@ pk_3 = auth_data.credential_data.public_key.get(3)
pk__1 = auth_data.credential_data.public_key.get(-1)
pk__2 = auth_data.credential_data.public_key.get(-2)
pk__3 = auth_data.credential_data.public_key.get(-3)
pickled = pickle.dumps(credentials)
user_id = int(input("Please enter user ID number: "))
keyNumber = (int
(input("Please enter key number: ")))
import psycopg2
# Replace these variables with your connection parameters
dbname = "CNSA-276-FP-DAS"
user = "FP-DEV-USER"
@@ -123,76 +97,49 @@ host = "postgres.eggtech.net"
# Function to connect to the PostgreSQL database and insert data
def insert_data(aaguid, cred_id, pk_algo, pk_1, pk_3, pk__1, pk__2, pk__3):
def insert_data(aaguid, user_id, cred_id, pk_algo, pk_1, pk_3, pk__1, pk__2, pk__3, keyNumber):
conn = None
try:
# Connect to the PostgreSQL server
conn = psycopg2.connect(dbname=dbname, user=user, password=password, host=host)
cur = conn.cursor()
# Define the SQL query for inserting data
insert_query = '''
INSERT INTO credential_data ("AAGUID", "credential_id", "pk_algo", "pk_1", "pk_3", "pk_neg1", "pk_neg2", "pk_neg3")
VALUES (%s, %s, %s, %s, %s, %s, %s, %s);
'''
# Execute the SQL query
cur.execute(insert_query, (aaguid, cred_id, pk_algo, pk_1, pk_3, pk__1, pk__2, pk__3))
# Connect to the PostgreSQL server
conn = psycopg2.connect(dbname=dbname, user=user, password=password, host=host)
cur = conn.cursor()
# Define the SQL query for inserting data
insert_query = '''
INSERT INTO credential_data ("AAGUID", "user_id", "credential_id", "pk_algo", "pk_1", "pk_3", "pk_neg1", "pk_neg2", "pk_neg3", "pickled", "keyNumber")
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);
'''
# Commit the changes
conn.commit()
# Execute the SQL query
cur.execute(insert_query, (aaguid, user_id, cred_id, pk_algo, pk_1, pk_3, pk__1, pk__2, pk__3, pickled, keyNumber))
# Commit the changes
conn.commit()
# Close communication with the database
cur.close()
conn.close()
# Close communication with the database
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
# Assuming auth_data is defined and you've extracted your data as you've shown above
insert_data(
AAGUID,
user_id,
cred_id,
pk_algo,
pk_1,
pk_3,
pk__1,
pk__2,
pk__3
pk__3,
keyNumber
)
print("New credential created!")
print("CLIENT DATA:", result.client_data)
print("ATTESTATION OBJECT:", result.attestation_object)
print()
print("CREDENTIAL DATA:", auth_data.credential_data)
# Prepare parameters for getAssertion
request_options, state = server.authenticate_begin(credentials, user_verification=uv)
# Authenticate the credential
result = client.get_assertion(request_options["publicKey"])
# Only one cred in allowCredentials, only one response.
result = result.get_response(0)
# Complete authenticator
server.authenticate_complete(
state,
credentials,
result.credential_id,
result.client_data,
result.authenticator_data,
result.signature,
)
print("Credential authenticated!")
print("CLIENT DATA:", result.client_data)
print()
print("AUTH DATA:", result.authenticator_data)

7
config.ini Normal file
View File

@@ -0,0 +1,7 @@
[Setup]
dbusername = FP-DEV-USER
dbpassword = purchase-immortal-prescribe-repave-detention-seizing-candied-antiques-episode-list
dbname = CNSA-276-FP-DAS
dbhost = postgres.eggtech.net
doorID = 0

View File

@@ -1,144 +0,0 @@
# Copyright (c) 2018 Yubico AB
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
"""
Connects to the first FIDO device found (starts from USB, then looks into NFC),
creates a new credential for it, and authenticates the credential.
This works with both FIDO 2.0 devices as well as with U2F devices.
On Windows, the native WebAuthn API will be used.
"""
from fido2.hid import CtapHidDevice
from fido2.client import Fido2Client, WindowsClient, UserInteraction
from fido2.server import Fido2Server
from getpass import getpass
import sys
import ctypes
try:
from fido2.pcsc import CtapPcscDevice
except ImportError:
CtapPcscDevice = None
def enumerate_devices():
for dev in CtapHidDevice.list_devices():
yield dev
if CtapPcscDevice:
for dev in CtapPcscDevice.list_devices():
yield dev
# Handle user interaction
class CliInteraction(UserInteraction):
def prompt_up(self):
print("\nTouch your authenticator device now...\n")
def request_pin(self, permissions, rd_id):
return getpass("Enter PIN: ")
def request_uv(self, permissions, rd_id):
print("User Verification required.")
return True
uv = "discouraged"
if WindowsClient.is_available() and not ctypes.windll.shell32.IsUserAnAdmin():
# Use the Windows WebAuthn API if available, and we're not running as admin
client = WindowsClient("https://example.com")
else:
# Locate a device
for dev in enumerate_devices():
client = Fido2Client(
dev, "https://example.com", user_interaction=CliInteraction()
)
if client.info.options.get("rk"):
break
else:
print("No Authenticator with support for resident key found!")
sys.exit(1)
# Prefer UV if supported
if client.info.options.get("uv"):
uv = "preferred"
print("Authenticator supports User Verification")
server = Fido2Server({"id": "example.com", "name": "Example RP"}, attestation="direct")
user = {"id": b"user_id", "name": "A. User"}
# Prepare parameters for makeCredential
create_options, state = server.register_begin(
user,
resident_key_requirement="required",
user_verification=uv,
authenticator_attachment="cross-platform",
)
# Create a credential
result = client.make_credential(create_options["publicKey"])
# Complete registration
auth_data = server.register_complete(
state, result.client_data, result.attestation_object
)
credentials = [auth_data.credential_data]
print("New credential created!")
print("CLIENT DATA:", result.client_data)
print("ATTESTATION OBJECT:", result.attestation_object)
print()
print("CREDENTIAL DATA:", auth_data.credential_data)
# Prepare parameters for getAssertion
request_options, state = server.authenticate_begin(user_verification=uv)
# Authenticate the credential
selection = client.get_assertion(request_options["publicKey"])
result = selection.get_response(0) # There may be multiple responses, get the first.
print("USER ID:", result.user_handle)
# Complete authenticator
server.authenticate_complete(
state,
credentials,
result.credential_id,
result.client_data,
result.authenticator_data,
result.signature,
)
print("Credential authenticated!")
print("CLIENT DATA:", result.client_data)
print()
print("AUTHENTICATOR DATA:", result.authenticator_data)

1
crontab Normal file
View File

@@ -0,0 +1 @@
@reboot /bin/sh /home/user/startup.sh

41
install.sh Normal file
View File

@@ -0,0 +1,41 @@
#!/bin/sh
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get update
sudo apt-get install python3-psycopg2 -y
sudo apt-get install python3-fido2 -y
sudo apt-get install screen -y
sudo apt-get update
sudo apt-get upgrade -y
sudo mkdir /user/CNSA
# Define crontab job
JOB="@reboot /bin/sh /user/CNSA/script/startup.sh"
# Check if the job is already in the crontab and add it if it's not
( crontab -l | grep -F "$JOB" || echo "$JOB" ) | crontab -
sudo git clone https://gitea.eggtech.net/eggman20339/CNSA-276-FP.git /user/CNSA/CNSA-276-FP
sudo mkdir /user/CNSA/script
sudo cp /user/CNSA/CNSA-276-FP/startup.sh /user/CNSA/script/startup.sh
sudo chmod 777 /user/CNSA/script/startup.sh
pip3 install --upgrade fido2 --break-system-packages
pip3 install nfcpy --break-system-packages
pip3 isntall --upgrade nfcpy --break-system-packages
sudo apt-get autoremove -y
echo ""
echo ""
echo ""
echo ""
echo ""
echo "Installation Complete! Rebooting..."
sleep 5
sudo reboot 0

342
main.py Normal file
View File

@@ -0,0 +1,342 @@
# Copyright (c) 2018 Yubico AB
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
"""
Connects to the first FIDO device found (starts from USB, then looks into NFC),
creates a new credential for it, and authenticates the credential.
This works with both FIDO 2.0 devices as well as with U2F devices.
On Windows, the native WebAuthn API will be used.
"""
import time
import configparser
gpie = True
if gpie:
import RPi.GPIO as GPIO
import pickle
import psycopg2
import fido2.webauthn
from fido2.hid import CtapHidDevice
from fido2.client import Fido2Client, WindowsClient, UserInteraction
from fido2.server import Fido2Server
from getpass import getpass
import sys
import ctypes
from fido2.ctap2 import Ctap2
from fido2 import cbor
# from fido2 import CtapNfcDevice
config = configparser.ConfigParser()
config.read('config.ini')
# test
dbusername = config.get('Setup', 'dbusername')
dbpassword = config.get('Setup', 'dbpassword')
dbname = config.get('Setup', 'dbname')
dbhost = config.get('Setup', 'dbhost')
doorID = config.get('Setup', 'doorID')
gotAaguid = None
if gpie:
GPIO.setmode(GPIO.BOARD)
secLevel = 0
user_id = None
greenLed = 8
redLed = 7
door = 40
if gpie:
# badCredentials = False
GPIO.setup(greenLed, GPIO.OUT)
GPIO.output(greenLed, GPIO.LOW)
GPIO.setup(redLed, GPIO.OUT)
GPIO.output(redLed, GPIO.HIGH)
time.sleep(1)
GPIO.output(redLed, GPIO.LOW)
time.sleep(0.2)
GPIO.output(greenLed, GPIO.HIGH)
time.sleep(1)
GPIO.output(greenLed, GPIO.LOW)
time.sleep(0.2)
GPIO.setup(door, GPIO.OUT)
GPIO.output(door, GPIO.LOW)
def badCred():
print("Bad credential!")
# badCredentials = True
# time.sleep(2)
class CliInteraction(UserInteraction):
def prompt_up(self):
print("\nTouch your authenticator device now...\n")
def request_pin(self, permissions, rd_id):
return getpass("Enter PIN: ")
def request_uv(self, permissions, rd_id):
print("User Verification required.")
return True
while True:
# isNfc = False
if gpie:
GPIO.output(door, GPIO.LOW)
print("Waiting for device...")
badCredentials = False
if gpie:
GPIO.output(redLed, GPIO.HIGH)
while True:
try:
dev = next(CtapHidDevice.list_devices(), None)
if dev:
ctap2 = Ctap2(dev)
info = ctap2.get_info()
gotAaguid = info.aaguid
print(str(gotAaguid))
break
time.sleep(0.1)
except Exception as e:
print(e)
# Handle user interaction
try:
server = Fido2Server({"id": "example.com", "name": "Example RP"}, attestation="direct")
uv = "discouraged"
# Set up a FIDO 2 client using the origin https://example.com
client = Fido2Client(dev, "https://example.com", user_interaction=CliInteraction())
# Replace these variables with your connection parameters
user = dbusername
password = dbpassword
host = dbhost
# Define the SQL query for retrieving data
select_query = '''
SELECT "AAGUID", user_id, credential_id, pk_algo, pk_1, pk_3, pk_neg1, pk_neg2, pk_neg3, pickled
FROM credential_data
WHERE "AAGUID" = %s;
'''
# Function to connect to the PostgreSQL database and retrieve data
def fetch_data(aaguid):
conn = None
try:
# Connect to the PostgreSQL server
conn = psycopg2.connect(dbname=dbname, user=user, password=password, host=host)
cur = conn.cursor()
# Execute the SQL query
cur.execute(select_query, (gotAaguid,))
# Fetch the results
result = None
result = cur.fetchone()
if result:
data = {
"AAGUID": result[0],
"user_id": result[1],
"credential_id": result[2],
"pk_algo": result[3],
"pk_1": result[4],
"pk_3": result[5],
"pk_neg1": result[6],
"pk_neg2": result[7],
"pk_neg3": result[8],
"pickled": result[9]
}
return data
else:
print("No data found for AAGUID:", aaguid)
badCred()
raise Exception
return None
# Close communication with the database
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
raise Exception
finally:
if conn is not None:
conn.close()
# Example usage: Fetch data for a specific AAGUID and store in variables
aaguid_data = None
aaguid_data = fetch_data("")
user_id = aaguid_data["user_id"]
if aaguid_data:
# Store each piece of data into a separate variable
testa = aaguid_data["AAGUID"]
cred_id = aaguid_data["credential_id"]
pk_algo = aaguid_data["pk_algo"]
pk_1 = aaguid_data["pk_1"]
pk_3 = aaguid_data["pk_3"]
pk_neg1 = aaguid_data["pk_neg1"]
pk_neg2 = aaguid_data["pk_neg2"]
pk_neg3 = aaguid_data["pk_neg3"]
pickled = aaguid_data["pickled"]
if badCredentials:
raise Exception
credentials = pickle.loads(pickled)
# Prepare parameters for getAssertion
request_options, state = server.authenticate_begin(credentials, user_verification=uv)
# Authenticate the credential
result = client.get_assertion(request_options["publicKey"])
# Only one cred in allowCredentials, only one response.
result = result.get_response(0)
# Complete authenticator
server.authenticate_complete(
state,
credentials,
result.credential_id,
result.client_data,
result.authenticator_data,
result.signature,
)
print("Credential authenticated!")
print("CLIENT DATA:", result.client_data)
print()
print("AUTH DATA:", result.authenticator_data)
# GPIO.output(14, GPIO.LOW)
conn = None
try:
# Connect to the PostgreSQL server
conn = psycopg2.connect(dbname=dbname, user=user, password=password, host=host)
cur = conn.cursor()
select_query = '''
SELECT sec_level
FROM users
WHERE "user_id" = %s;
'''
# Execute the SQL query
cur.execute(select_query, (str(user_id)))
# Fetch the results
result = None
result = cur.fetchone()
if result:
userSecLevel = result[0]
else:
badCred()
raise Exception
# Close communication with the database
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
raise Exception
finally:
if conn is not None:
conn.close()
conn = None
try:
# Connect to the PostgreSQL server
conn = psycopg2.connect(dbname=dbname, user=user, password=password, host=host)
cur = conn.cursor()
select_query = '''
SELECT sec_level
FROM doors
WHERE "door_id" = %s;
'''
# Execute the SQL query
cur.execute(select_query, (doorID))
# Fetch the results
result = None
result = cur.fetchone()
if result:
doorSecLevel = result[0]
else:
badCred()
raise Exception
# Close communication with the database
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
raise Exception
finally:
if conn is not None:
conn.close()
if doorSecLevel < userSecLevel:
raise Exception
if gpie:
GPIO.output(redLed, GPIO.LOW)
for i in range(2):
GPIO.output(greenLed, GPIO.HIGH)
time.sleep(0.05)
GPIO.output(greenLed, GPIO.LOW)
time.sleep(0.05)
GPIO.output(greenLed, GPIO.HIGH)
GPIO.output(door, GPIO.HIGH)
time.sleep(3)
GPIO.output(greenLed, GPIO.LOW)
except Exception as e:
print("Authentication Failed!")
for i in range(5):
if gpie:
GPIO.output(redLed, GPIO.LOW)
time.sleep(0.05)
GPIO.output(redLed, GPIO.HIGH)
time.sleep(0.05)

29
readme.md Normal file
View File

@@ -0,0 +1,29 @@
# Welcome
### This project is a Door access system built on RPIs
#### Getting Started
1) Start by installing the latest version of raspianOS on your Raspberry Pi
1) Get Raspberry Pi Imager from the web
2) Launch it
3) Choose your model (RPI 4)
4) Choose OS (Raspberry PI OS 64-bit)
5) Select your SD card
6) Press Ctrl+Shift+X
7) Set a hostname
8) Set a username and password
9) Set locale settings
10) Press Save
11) Press the "Next" button
12) Continue through any further prompts, keeping all settings that were set
2) Boot the Raspberry Pi
3) Open a command prompt on a seperate computer
4) Ping the hostname set in 1.vii to find the IPv4 address (might need `-4` flag)
5) SSH into the RPI (Raspberry Pi)
6) run `git clone https://gitea.eggtech.net/eggman20339/CNSA-276-FP.git && sudo sh CNSA-276-FP/install.sh`
7) The script should take care of the rest, the RPI will restart and then auto start the program
8) after reboot, to edit the config, SSH back in and navigate to `/user/CNSA/CNSA-276-FP/`
9) run `nano config.ini`
10) alter any config needed
11) use Ctrl+x to exit and save

31
startup.sh Normal file
View File

@@ -0,0 +1,31 @@
#!/bin/sh
sudo cp /user/CNSA/CNSA-276-FP/config.ini /config.bak
sudo rm -R /user/CNSA/CNSA-276-FP
# Function to check internet connectivity
check_internet_connection() {
ping -c 1 1.1.1.1 > /dev/null 2>&1
return $?
}
# Wait for internet connection
while ! check_internet_connection; do
echo "Waiting for internet connection..."
sleep 1 # Wait for 1 seconds before checking again
done
# Internet connection established
echo "Internet connection established. Running the portion of the script that requires it."
# Add your code here that requires an internet connection
sudo mkdir /user/CNSA/CNSA-276-FP/
sudo git clone https://gitea.eggtech.net/eggman20339/CNSA-276-FP.git /user/CNSA/CNSA-276-FP
sudo chmod 777 /user/CNSA/CNSA-276-FP/startup.sh
sudo cp /config.bak /user/CNSA/CNSA-276-FP/config.ini
screen -dmS DoorAuth bash -c "cd /user/CNSA/CNSA-276-FP/ && python3 main.py"
sudo cp /user/CNSA/CNSA-276-FP/startup.sh /user/CNSA/script/startup.sh

View File

View File

@@ -1,84 +0,0 @@
from fido2.hid import CtapHidDevice
from fido2.server import Fido2Server
from fido2.webauthn import PublicKeyCredentialRpEntity, UserVerificationRequirement, PublicKeyCredentialUserEntity, \
PublicKeyCredentialCreationOptions
from fido2.client import Fido2Client
import os
# Initialize the FIDO2 server
rp = PublicKeyCredentialRpEntity("example.com", "Example Corporation")
server = Fido2Server(rp)
# User information
user_id = os.urandom(32)
user = PublicKeyCredentialUserEntity("testuser", b"Example Corporation")
# Create a registration request
registration_data = PublicKeyCredentialCreationOptions(rp, user, os.urandom(32), rp)
state = server.register_begin(user,
challenge=os.urandom(32),
user_verification=UserVerificationRequirement.PREFERRED)
# List FIDO devices
devices = list(CtapHidDevice.list_devices())
if not devices:
print("No FIDO devices found")
exit(1)
# Select the first device (you could add logic to choose a device)
device = devices[0]
print("Using device:", device)
# Simulate client processing and generate a response (normally done in browser)
client = Fido2Client(device, "https://example.com")
attestation_object, client_data = client.make_credential(registration_data)
# Setup Relying Party
rp = PublicKeyCredentialRpEntity("example.com", name="Example Corporation")
server = Fido2Server(rp)
# User information
user_id = os.urandom(32)
user = {"id": user_id, "name": "user@example.com", "displayName": "Example User"}
# Create a registration request
registration_data, state = server.register_begin({
"id": user_id,
"name": user['name'],
"displayName": user['displayName']
},
challenge=os.urandom(32),
user_verification="preferred")
# Use the client to create a credential
attestation_object, client_data = client.make_credential(registration_data)
# Complete registration
authenticator_data = server.register_complete(
state,
client_data,
attestation_object
)
print("Registration complete")
print("Authenticator data:", authenticator_data.credential_data)
# Authentication process
auth_data, state = server.authenticate_begin(user_id)
# Simulate client processing and generate a response
assertion = client.get_assertion(auth_data["publicKey"])
assertion_response = assertion.get_response(0)
# Complete authentication
credentials, user_handle = server.authenticate_complete(
state,
auth_data["allowCredentials"],
assertion_response.client_data,
assertion_response.authenticator_data,
assertion_response.signature
)
print("Authentication complete")
print("User handle:", user_handle)
print("Credentials:", credentials)

56
tet.py
View File

@@ -1,56 +0,0 @@
from fido2.server import Fido2Server
from fido2.webauthn import (PublicKeyCredentialRpEntity, PublicKeyCredentialUserEntity,
PublicKeyCredentialParameters, PublicKeyCredentialCreationOptions)
from fido2.client import Fido2Client
from fido2.hid import CtapHidDevice
import os
# Setup the relying party (RP) entity
rp = PublicKeyCredentialRpEntity("eggtech.net", "test")
# Setup the user entity
user = PublicKeyCredentialUserEntity(
id=b'91974', # User ID as bytes
name="cyrus@eggtech.net",
display_name="Cyrus Schick"
)
# Define the public key credential parameters
cred_params = [
PublicKeyCredentialParameters("public-key", -7), # ES256
PublicKeyCredentialParameters("public-key", -257) # RS256
]
# FIDO2 Server setup
server = Fido2Server(rp)
# Generate a random challenge
challenge = os.urandom(32)
# Manually create the PublicKeyCredentialCreationOptions
options = PublicKeyCredentialCreationOptions(
rp=rp,
user=user,
challenge=challenge,
pub_key_cred_params=cred_params
)
# Start the registration process (adjust this method if needed)
registration_data, state = server.register_begin(
user=user,
challenge=challenge
)
# Assuming the device is the first one connected
device = next(CtapHidDevice.list_devices(), None)
if device is None:
raise ValueError("No FIDO device found")
# Client instance for the device
client = Fido2Client(device, "eggtech.net")
# Use the manual options we created for make_credential
attestation_object, client_data = client.make_credential(options)
# Finalize the registration to validate the response and store the credentials
auth_data = server.register_complete(state, client_data, attestation_object)

View File

@@ -1,46 +0,0 @@
from fido2.hid import CtapHidDevice
from fido2.client import Fido2Client
from fido2.server import Fido2Server
from fido2.webauthn import PublicKeyCredentialRpEntity
while True:
# Discover FIDO2 devices connected via USB
devices = list(CtapHidDevice.list_devices())
if not devices:
#raise ValueError("No FIDO2 device found")
pass
else:
device = devices[0]
break
# Use the first available device
client = Fido2Client(device, "https://example.com")
rp = PublicKeyCredentialRpEntity("example.com", "Example RP")
server = Fido2Server(rp)
# Example: Registration
user = {"id": b"user_id", "name": "john_doe", "displayName": "John Doe"}
challenge = server.register_begin(user)
print(challenge)
# Prompt user to perform registration action on the device
attestation_object, client_data = client.make_credential(challenge)
# Finalize registration on the server
auth_data = server.register_complete(challenge['state'], client_data, attestation_object)
print("Registration complete. Credential ID:", auth_data.credential_data.credential_id)
# Example: Authentication
credentials = [auth_data.credential_data]
challenge = server.authenticate_begin(credentials)
# Prompt user to perform authentication action on the device
assertion, client_data = client.get_assertion(challenge['publicKey'])
assertion_response = assertion[0] # Assuming the first assertion (most common scenario)
# Finalize authentication on the server
server.authenticate_complete(challenge['state'], credentials, assertion_response, client_data)
print("Authentication successful!")

View File

View File

@@ -1,142 +0,0 @@
# Copyright (c) 2018 Yubico AB
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
"""
Connects to the first FIDO device found (starts from USB, then looks into NFC),
creates a new credential for it, and authenticates the credential.
This works with both FIDO 2.0 devices as well as with U2F devices.
On Windows, the native WebAuthn API will be used.
"""
from fido2.hid import CtapHidDevice
from fido2.client import Fido2Client, WindowsClient, UserInteraction
from fido2.server import Fido2Server
from getpass import getpass
import sys
import ctypes
# Handle user interaction
class CliInteraction(UserInteraction):
def prompt_up(self):
print("\nTouch your authenticator device now...\n")
def request_pin(self, permissions, rd_id):
return getpass("Enter PIN: ")
def request_uv(self, permissions, rd_id):
print("User Verification required.")
return True
uv = "discouraged"
if WindowsClient.is_available() and not ctypes.windll.shell32.IsUserAnAdmin():
# Use the Windows WebAuthn API if available, and we're not running as admin
client = WindowsClient("https://example.com")
else:
# Locate a device
dev = next(CtapHidDevice.list_devices(), None)
if dev is not None:
print("Use USB HID channel.")
else:
try:
from fido2.pcsc import CtapPcscDevice
dev = next(CtapPcscDevice.list_devices(), None)
print("Use NFC channel.")
except Exception as e:
print("NFC channel search error:", e)
if not dev:
print("No FIDO device found")
sys.exit(1)
# Set up a FIDO 2 client using the origin https://example.com
client = Fido2Client(dev, "https://example.com", user_interaction=CliInteraction())
# Prefer UV if supported and configured
if client.info.options.get("uv") or client.info.options.get("pinUvAuthToken"):
uv = "preferred"
print("Authenticator supports User Verification")
server = Fido2Server({"id": "example.com", "name": "Example RP"}, attestation="direct")
user = {"id": b"user_id", "name": "A. User"}
# Prepare parameters for makeCredential
create_options, state = server.register_begin(
user, user_verification=uv, authenticator_attachment="cross-platform"
)
# Create a credential
result = client.make_credential(create_options["publicKey"])
# Complete registration
auth_data = server.register_complete(
state, result.client_data, result.attestation_object
)
credentials = [auth_data.credential_data]
print("New credential created!")
print("CLIENT DATA:", result.client_data)
print("ATTESTATION OBJECT:", result.attestation_object)
print()
print("CREDENTIAL DATA:", auth_data.credential_data)
# Prepare parameters for getAssertion
request_options, state = server.authenticate_begin(credentials, user_verification=uv)
# Authenticate the credential
result = client.get_assertion(request_options["publicKey"])
# Only one cred in allowCredentials, only one response.
result = result.get_response(0)
print(str(state))
print(str(credentials))
print(str(result.credential_id))
print(str(result.client_data))
print(str(result.authenticator_data))
print(str(result.signature))
# Complete authenticator
server.authenticate_complete(
state,
credentials,
result.credential_id,
result.client_data,
result.authenticator_data,
result.signature,
)
print("Credential authenticated!")
print("CLIENT DATA:", result.client_data)
print()
print("AUTH DATA:", result.authenticator_data)