From: server Date: Mon, 20 Jan 2025 18:07:47 +0000 (-0500) Subject: Mon Jan 20 01:07:47 PM EST 2025 X-Git-Url: http://www.foleosoft.com/?a=commitdiff_plain;h=4cc1cd5b578be66070aaeecbeda714e16150293a;p=RosadoAPI.git Mon Jan 20 01:07:47 PM EST 2025 --- diff --git a/README.md b/README.md index f15b7de..409bc59 100644 --- a/README.md +++ b/README.md @@ -9,139 +9,169 @@ Please click the `tree` link at the top and navigate to the code for the simulator. ``` - qansel-source-base.zip + rosado-source-base.zip ``` To compile it, navigate to the folder it installed within and run the following commands within that folder. ```sh - mkdir qansel - mv *qansel-source-base.zip qansel - cd qansel - unzip *qansel-source-base.zip + mkdir rosado + mv *rosado-source-base.zip qansel + cd rosado + unzip *rosado-source-base.zip make ``` -If you are compiling for a device which cannot support -hardware acceleration, then you can use `make simple` which -will build the program with those features stripped out. +You can also use `make install` after running `make` to +install it. ## Usage +To convert a CLI program to a web API, it must be designed such that +it takes in its input as standard input and provides its output as +standard output. +This project expects a MySQL/MariaDB installation with a schema +titled RosadoAPI. The first time the program is executed, it will +automatically create the necessary tables within this schema. Make +sure that the password to login to the database is stored as the +first line of text in the configuration file in the path below. +The second line is used to set the port number. +``` + /etc/rosadoapi.conf +``` +The API uses two tables. The first table is ServiceInfo which is +used to set up a CLI program to be used as an API. Below is the +structure for this table. -Many example programs that can be executed inside of QAnsel can -be found by clicking the `tree` link at the top fo the page and -then navigating to the `examples` folder. Simply click on one of -the examples in order to see the source code. +```sql -## Usage -The QAnsel simulator expects programs to be written in a language -similar to OpenQASM 2.0. These programs must be piped into QAnsel -as standard input and the simulation results will be displayed as -standard output. Below is an example using a here document. +``` + +The `service` field is the name of the service and also corresponds +to the path that must be pinged to access it. For example, if the +service is named `myapi` and hosted at `localhost` then to access +this service, the client will need to ping `localhost/myapi`. + +The `path` field is the actual full path of the executable program. +The `parameters` field is any command line parameters that should be +passed into the program when it is called. + +The second table is the `AuthInfo` table. This is related to +authentication for users trying to ping the API. Below is the +structure for this table. + +```sql + +``` + +The `service` field must correspond to a `service` in the `ServiceInfo` +table. The `username` field is the name of a registered user allowed +to access an API. The `authkey` is their authentication token which is +also used for encryption and decryption. The `timeout` value is how +long the user is able to run an application for. Different users can +be authorized to run programs for longer periods of time. + +To generate a unique `authkey` for a user, use the command below. ```sh - $ ./QAnsel << EOF - > qreg q[2]; - > creg c[2]; - > h q[0]; - > cx q[0], q[1]; - > measure q[0] -> c[0]; - > measure q[1] -> c[1]; - > sample c; - > EOF - 00: 50.7% - 01: 0.0% - 10: 0.0% - 11: 49.3% + openssl rand -hex 32 ``` -Please use the `-?` flag to see a help document. +Communication with the API service is encrypted with ChaCha20-HMAC +This means it cannot be pinged using plaintext. To ping it and get a +response, the request must be encrypted using ChaCha20-HMAC, and +the response also must be decrypted in the same way. -## Special Hardware +Below are variables that will need to be populated in order to +ping the API service. -To enable a hardware random number generator, the `-r` -flag must be used. This flag will select the hardware -random number generator based on an order of precedence. -The order is as follows. +- `$srvc`: The service to send a request to. +- `$user`: The user requesting the service. +- `$auth`: The authentication key. +- `$rqst`: The request data. +- `$sess`: A session identifier. -1. Quantis-PCIe-40M -2. TrueRNG V3 -3. Secure Key Technology +Below is the beginnings of a Bash script defining these values +grabbing most from command line arguments except for the request +itself which comes from standard input as well as the session ID +which is randomly generated. -To enable GPU acceleration, the `-oX` flag has to be -set replacing `X` with an optimization level equal to -4 or greater. +```sh + srvc=$1 + user=$2 + auth=$3 + read rqst + sess=$(openssl rand -hex 12) +``` -It is recommended that you run a simple program with the -`-v` flag which will produce output stating which hardware -devices were actually found and enabled. +The next step is to generate the request data which is computed +simply by taking the plaintext request and encrypting it with +ChaCha20 using the authentication key. Then, a digest will also +need to be computed for the message which allows the server to +verify the message has not been tampered with. This must be +calculated from the plaintext message using HMAC-SHA256. -QAnsel can handle up to 16 qubits, however, qubit counts -greater than 14 will not fit into most consumer-end GPUs. -The amount of qubits that can fit is limited by the -amount of VRAM. The GPU must have at least 8 GB for 14 -qubits, 16 GB for 15 qubits, and 48 GB for 16 qubits. +Both of these values also need to be encoded as base64. Below +is a Bash script that generates the body and digest for the +request. -## API and Web Interface +```sh + data=$(echo -n "$rqst" | openssl enc -chacha20 -K $auth -iv 00000000$sess | base64 | tr -d '\n') + dgst=$(echo -n "$data" | base64 -d | openssl sha256 -hex -mac HMAC -macopt hexkey:$auth | cut -d '=' -f 2 | xargs) +``` -There is a drag-and-drop interface that runs in the browser -that can be found by clicking the `tree` button and navigating -to the `bin` folder and downloading the following file. +The username, session, data, and digest then can be combined +to form the post request in `application/x-www-form-urlencoded` +format. Below is an example of how to produce such a request +and store the response in variable in Bash. +```sh + resp=$(curl -s -X POST -d "user=$user&sess=$sess&dgst=$dgst&data=$data" "$srvr/$srvc") ``` - qansel-source-web.zip + +The response from the server is in a similar format, so it +should first be parsed into different response variables. + +```sh + for param in user sess dgst data + do + eval r$param=$(echo "$resp" | sed -e "s/.*$param=//" -e "s/&.*//") 2> /dev/null + done ``` -This web front end expects to connect to an API. The API -service is handled through FoleoAPI. Please see the FoleoAPI -project in order to set up this service. +The response message needs to be validated by recomputing +the digest and verifying it matches the received digest +and verifying the user matches the requested user. + +```sh + if [ "$user" != "$ruser" ] + then + echo "Invalid response: user mismatch." + exit 1 + fi + dgst=$(echo -n "$rdata" | base64 -d | openssl sha256 -hex -mac HMAC -macopt hexkey:$auth | cut -d '=' -f 2 | xargs) + if [ "$dgst" != "$rdgst" ] + then + echo "Invalid response: digest mismatch." + exit 1 + fi +``` -Once FoleoAPI is running, a ServiceInfo record will need to be -added to the APIService schema. Below is an example of how this -entry may look. +Finally, once the response is received and verified, it +can be decrypted using ChaCha20. ChaCha20 uses the same +command to encrypt as it does to decrypt because it +is a symmetrical cipher. -```sql - MariaDB [APIService]> select * from ServiceInfo; - +----+---------+---------------------------------+-------------+ - | id | service | path | parameters | - +----+---------+---------------------------------+-------------+ - | 1 | qansel | /fakepath/QAnsel | -q14 -o5 -r | - +----+---------+---------------------------------+-------------+ +``` + echo -n "$rdata" | base64 -d | openssl enc -d -chacha20 -K $auth -iv 00000000$rsess ``` -The `-qX` parameter is useful here as it allows one to cap -the maximum qubit count allowed for the process in case the -hardware running the simulator is not sufficient to handle large -qubit counts. In this case, it is capped at 14 to make sure that -programs that exceed the limitations of the GPU are rejected. - -The web interface expects an API key. The API key is formed in three -parts `A:B:C` where `A` is the `APIService.AuthInfo.username`, `B` is -the `APIService.AuthInfo.authkey`, and `C` is the URL which it needs -to ping. It is important that the address does not contain `http://` -or `https://`. For example, if the address is `http://example.com/api`, -then `C` should simply be written as `example.com/api`. - -Once `A:B:C` is filled out, the entire thing needs to be converted to -a base64 string. This can be done in JavaScript in the developer console -in the web browser using the `btoa()` function. This final encoded string -functions as the API key for the web interface. Any equal signs at the -end of the API key should be removed. - -The web interface allows for appending the URL with `?apikey=` followed by -an API key to auto fill the API key. This can be useful if the service is -linked from another source (such as another website or an email) and will -prevent the user from having to input the APIkey themselves. - -## Android - -The Android app version of this project merely is enclose a web view -containing the web interface. This means it requires pinging a server -running the API for it to work. It must be compiled using Android Studio. +Please click the `tree` button on the top left of the +page and click the `ping.sh` file to see this complete +Bash script. diff --git a/ping.sh b/ping.sh new file mode 100644 index 0000000..ff2c452 --- /dev/null +++ b/ping.sh @@ -0,0 +1,38 @@ +set -e +if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ] +then + echo "$0 [address] [service] [username] [authkey]" + exit +fi + +addr=$1 +srvc=$2 +user=$3 +auth=$4 +read rqst +sess=$(openssl rand -hex 12) + +data=$(echo -n "$rqst" | openssl enc -chacha20 -K $auth -iv 00000000$sess | base64 | tr -d '\n') +dgst=$(echo -n "$data" | base64 -d | openssl sha256 -hex -mac HMAC -macopt hexkey:$auth | cut -d '=' -f 2 | xargs) + +resp=$(curl -s -X POST -d "user=$user&sess=$sess&dgst=$dgst&data=$data" "$addr/$srvc") + +for param in user sess dgst data +do + eval r$param=$(echo "$resp" | sed -e "s/.*$param=//" -e "s/\&.*//") 2>/dev/null +done + +if [ "$user" != "$ruser" ] +then + echo "Invalid response: user mismatch." + exit 1 +fi + +dgst=$(echo -n "$rdata" | base64 -d | openssl sha256 -hex -mac HMAC -macopt hexkey:$auth | cut -d '=' -f 2 | xargs) +if [ "$dgst" != "$rdgst" ] +then + echo "Invalid response: digest mismatch." + exit 1 +fi + +echo -n "$rdata" | base64 -d | openssl enc -d -chacha20 -K $auth -iv 00000000$rsess