switching os
This commit is contained in:
parent
94811a651a
commit
e3e0b3853b
@ -5,7 +5,7 @@
|
|||||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.11 (CNSA-276-FP)" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.12 (CNSA-276-FP)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
@ -3,5 +3,5 @@
|
|||||||
<component name="Black">
|
<component name="Black">
|
||||||
<option name="sdkName" value="Python 3.12 (CNSA-276-FP)" />
|
<option name="sdkName" value="Python 3.12 (CNSA-276-FP)" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (CNSA-276-FP)" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (CNSA-276-FP)" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
21
tet.py
Normal file
21
tet.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from fido2.server import Fido2Server
|
||||||
|
from fido2.webauthn import PublicKeyCredentialRpEntity
|
||||||
|
|
||||||
|
rp = PublicKeyCredentialRpEntity("example.com", "Example RP")
|
||||||
|
server = Fido2Server(rp)
|
||||||
|
registration_data, state = server.register_begin({
|
||||||
|
"91974": b"user_id", # user ID as bytes
|
||||||
|
"Cyrus": "cyrus@eggtech.net",
|
||||||
|
"displayName": "Admin"
|
||||||
|
})
|
||||||
|
from fido2.client import Fido2Client
|
||||||
|
from fido2.hid import CtapHidDevice
|
||||||
|
|
||||||
|
# List FIDO devices on the system
|
||||||
|
devices = list(CtapHidDevice.list_devices())
|
||||||
|
if not devices:
|
||||||
|
raise ValueError("No FIDO device found")
|
||||||
|
device = devices[0]
|
||||||
|
|
||||||
|
client = Fido2Client(device, "https://example.com")
|
||||||
|
attestation_object, client_data = client.make_credential(registration_data)
|
@ -3,11 +3,16 @@ from fido2.client import Fido2Client
|
|||||||
from fido2.server import Fido2Server
|
from fido2.server import Fido2Server
|
||||||
from fido2.webauthn import PublicKeyCredentialRpEntity
|
from fido2.webauthn import PublicKeyCredentialRpEntity
|
||||||
|
|
||||||
|
while True:
|
||||||
|
|
||||||
# Discover FIDO2 devices connected via USB
|
# Discover FIDO2 devices connected via USB
|
||||||
devices = list(CtapHidDevice.list_devices())
|
devices = list(CtapHidDevice.list_devices())
|
||||||
if not devices:
|
if not devices:
|
||||||
raise ValueError("No FIDO2 device found")
|
#raise ValueError("No FIDO2 device found")
|
||||||
|
pass
|
||||||
|
else:
|
||||||
device = devices[0]
|
device = devices[0]
|
||||||
|
break
|
||||||
|
|
||||||
# Use the first available device
|
# Use the first available device
|
||||||
client = Fido2Client(device, "https://example.com")
|
client = Fido2Client(device, "https://example.com")
|
||||||
@ -21,7 +26,7 @@ challenge = server.register_begin(user)
|
|||||||
print(challenge)
|
print(challenge)
|
||||||
|
|
||||||
# Prompt user to perform registration action on the device
|
# Prompt user to perform registration action on the device
|
||||||
attestation_object, client_data = client.make_credential()
|
attestation_object, client_data = client.make_credential(challenge)
|
||||||
|
|
||||||
# Finalize registration on the server
|
# Finalize registration on the server
|
||||||
auth_data = server.register_complete(challenge['state'], client_data, attestation_object)
|
auth_data = server.register_complete(challenge['state'], client_data, attestation_object)
|
||||||
|
177
u2fServer.py
177
u2fServer.py
@ -1,177 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# Copyright (c) 2013 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.
|
|
||||||
|
|
||||||
"""
|
|
||||||
Example web server providing single factor U2F enrollment and authentication.
|
|
||||||
It is intended to be run standalone in a single process, and stores user data
|
|
||||||
in memory only, with no permanent storage.
|
|
||||||
|
|
||||||
Enrollment will overwrite existing users.
|
|
||||||
If username is omitted, a default value of "user" will be used.
|
|
||||||
|
|
||||||
Any error will be returned as a stacktrace with a 400 response code.
|
|
||||||
|
|
||||||
Note that this is intended for test/demo purposes, not production use!
|
|
||||||
|
|
||||||
This example requires webob to be installed.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from u2flib_server.u2f import (begin_registration, begin_authentication,
|
|
||||||
complete_registration, complete_authentication)
|
|
||||||
from cryptography import x509
|
|
||||||
from cryptography.hazmat.backends import default_backend
|
|
||||||
from cryptography.hazmat.primitives.serialization import Encoding
|
|
||||||
from webob.dec import wsgify
|
|
||||||
from webob import exc
|
|
||||||
import logging as log
|
|
||||||
import json
|
|
||||||
import traceback
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
|
|
||||||
def get_origin(environ):
|
|
||||||
if environ.get('HTTP_HOST'):
|
|
||||||
host = environ['HTTP_HOST']
|
|
||||||
else:
|
|
||||||
host = environ['SERVER_NAME']
|
|
||||||
if environ['wsgi.url_scheme'] == 'https':
|
|
||||||
if environ['SERVER_PORT'] != '443':
|
|
||||||
host += ':' + environ['SERVER_PORT']
|
|
||||||
else:
|
|
||||||
if environ['SERVER_PORT'] != '80':
|
|
||||||
host += ':' + environ['SERVER_PORT']
|
|
||||||
|
|
||||||
return '%s://%s' % (environ['wsgi.url_scheme'], host)
|
|
||||||
|
|
||||||
|
|
||||||
class U2FServer(object):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Very basic server providing a REST API to enroll one or more U2F device with
|
|
||||||
a user, and to perform authentication with the enrolled devices.
|
|
||||||
Only one challenge is valid at a time.
|
|
||||||
|
|
||||||
Four calls are provided: enroll, bind, sign and verify. Each of these
|
|
||||||
expects a username parameter, and bind and verify expect a
|
|
||||||
second parameter, data, containing the JSON formatted data which is output
|
|
||||||
by the U2F browser API upon calling the ENROLL or SIGN commands.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.users = {}
|
|
||||||
|
|
||||||
@wsgify
|
|
||||||
def __call__(self, request):
|
|
||||||
self.facet = get_origin(request.environ)
|
|
||||||
self.app_id = self.facet
|
|
||||||
|
|
||||||
page = request.path_info_pop()
|
|
||||||
|
|
||||||
if not page:
|
|
||||||
return json.dumps([self.facet])
|
|
||||||
|
|
||||||
try:
|
|
||||||
username = request.params.get('username', 'user')
|
|
||||||
data = request.params.get('data', None)
|
|
||||||
|
|
||||||
if page == 'enroll':
|
|
||||||
return self.enroll(username)
|
|
||||||
elif page == 'bind':
|
|
||||||
return self.bind(username, data)
|
|
||||||
elif page == 'sign':
|
|
||||||
return self.sign(username)
|
|
||||||
elif page == 'verify':
|
|
||||||
return self.verify(username, data)
|
|
||||||
else:
|
|
||||||
raise exc.HTTPNotFound()
|
|
||||||
except Exception:
|
|
||||||
log.exception("Exception in call to '%s'", page)
|
|
||||||
return exc.HTTPBadRequest(comment=traceback.format_exc())
|
|
||||||
|
|
||||||
def enroll(self, username):
|
|
||||||
if username not in self.users:
|
|
||||||
self.users[username] = {}
|
|
||||||
|
|
||||||
user = self.users[username]
|
|
||||||
enroll = begin_registration(self.app_id, user.get('_u2f_devices_', []))
|
|
||||||
user['_u2f_enroll_'] = enroll.json
|
|
||||||
return json.dumps(enroll.data_for_client)
|
|
||||||
|
|
||||||
def bind(self, username, data):
|
|
||||||
user = self.users[username]
|
|
||||||
enroll = user.pop('_u2f_enroll_')
|
|
||||||
device, cert = complete_registration(enroll, data, [self.facet])
|
|
||||||
user.setdefault('_u2f_devices_', []).append(device.json)
|
|
||||||
|
|
||||||
log.info("U2F device enrolled. Username: %s", username)
|
|
||||||
cert = x509.load_der_x509_certificate(cert, default_backend())
|
|
||||||
log.debug("Attestation certificate:\n%s",
|
|
||||||
cert.public_bytes(Encoding.PEM))
|
|
||||||
|
|
||||||
return json.dumps(True)
|
|
||||||
|
|
||||||
def sign(self, username):
|
|
||||||
user = self.users[username]
|
|
||||||
challenge = begin_authentication(
|
|
||||||
self.app_id, user.get('_u2f_devices_', []))
|
|
||||||
user['_u2f_challenge_'] = challenge.json
|
|
||||||
return json.dumps(challenge.data_for_client)
|
|
||||||
|
|
||||||
def verify(self, username, data):
|
|
||||||
user = self.users[username]
|
|
||||||
|
|
||||||
challenge = user.pop('_u2f_challenge_')
|
|
||||||
device, c, t = complete_authentication(challenge, data, [self.facet])
|
|
||||||
return json.dumps({
|
|
||||||
'keyHandle': device['keyHandle'],
|
|
||||||
'touch': t,
|
|
||||||
'counter': c
|
|
||||||
})
|
|
||||||
|
|
||||||
application = U2FServer()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
from wsgiref.simple_server import make_server
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description='U2F test server',
|
|
||||||
add_help=True,
|
|
||||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter
|
|
||||||
)
|
|
||||||
parser.add_argument('-i', '--interface', nargs='?', default='localhost',
|
|
||||||
help='network interface to bind to')
|
|
||||||
parser.add_argument('-p', '--port', nargs='?', type=int, default=8081,
|
|
||||||
help='TCP port to bind to')
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
log.basicConfig(level=log.DEBUG, format='%(asctime)s %(message)s',
|
|
||||||
datefmt='[%d/%b/%Y %H:%M:%S]')
|
|
||||||
log.info("Starting server on http://%s:%d", args.interface, args.port)
|
|
||||||
httpd = make_server(args.interface, args.port, application)
|
|
||||||
httpd.serve_forever()
|
|
Loading…
Reference in New Issue
Block a user