diff --git a/.github/badges/branches.svg b/.github/badges/branches.svg index a699172..4b1f6ef 100644 --- a/.github/badges/branches.svg +++ b/.github/badges/branches.svg @@ -1 +1 @@ -branches31.4% \ No newline at end of file +branches31.1% \ No newline at end of file diff --git a/.github/badges/jacoco.svg b/.github/badges/jacoco.svg index 5cc1340..5205c3d 100644 --- a/.github/badges/jacoco.svg +++ b/.github/badges/jacoco.svg @@ -1 +1 @@ -coverage54.2% \ No newline at end of file +coverage53.6% \ No newline at end of file diff --git a/.github/workflows/dockerhub.yml b/.github/workflows/dockerhub.yml index 6cfaf7d..1e858d9 100644 --- a/.github/workflows/dockerhub.yml +++ b/.github/workflows/dockerhub.yml @@ -1,6 +1,6 @@ on: push: - branches: [ main ] + branches: [ main, hyperfridge ] jobs: push_to_dockerhub: name: build image and push to dockerhub diff --git a/.gitignore b/.gitignore index d2106bf..aa7986f 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,25 @@ node_modules .DS_Store /bin/ src/main/resources/simulated-account-statements.zip-10 +x.log +scripts/backupfile +scripts/backupfile.sik +scripts/hist.txt +scratch +trace +work_out +keys/bank_public_key.pem +keys/bank_public_key.pem-enc +keys/client_private_key.pem +keys/client_public_key.pem +keys/bank_public_key.pem +keys/bank_public_key.pem-enc +keys/client_private_key.pem +keys/client_public_key.pem +keys/bank_public_key.pem +keys/bank_public_key.pem-enc +keys/client_private_key.pem +keys/client_public_key.pem +docs/TEST-old.md +receipt.json +result.json diff --git a/Dockerfile b/Dockerfile index e919037..fbf7085 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ # sudo docker run -it --entrypoint sh ebics # sudo docker run -v $HOME/ebics:/root/ebics ebics -cp "ebics-cli.jar:lib/*" org.kopi.ebics.client.EbicsClient --sta -o /root/ebics/out sta.txt -FROM gradle:6-jdk11-hotspot as build +FROM gradle:6-jdk11 AS build # build ebics-client jar and server jars; RUN ls -la; mkdir /app; @@ -21,8 +21,9 @@ COPY ./src /app/src ENV GENERATE_GIT_PROPERTIES="false" WORKDIR /app RUN gradle clean build bootJar -DGENERATE_GIT_PROPERTIES=$GENERATE_GIT_PROPERTIES + #create runtime for jars -FROM openjdk:18-jdk-alpine as runtime +FROM openjdk:18-jdk as runtime RUN mkdir /app RUN mkdir /app/lib WORKDIR /app diff --git a/build.gradle b/build.gradle index a05c909..6bd30b1 100644 --- a/build.gradle +++ b/build.gradle @@ -7,11 +7,12 @@ buildscript { plugins { id 'org.springframework.boot' id 'java' - id "com.gorylenko.gradle-git-properties" version "2.3.1" id "org.owasp.dependencycheck" id "jacoco" id 'checkstyle' + id "com.gorylenko.gradle-git-properties" version "2.4.1" } + //apply from: "dependencyCheck.gradle" apply plugin: 'io.spring.dependency-management' @@ -26,13 +27,13 @@ repositories { ext { set('springCloudVersion', springCloudVersion) + set('lombokVersion', lombokVersion) } springBoot { buildInfo() } build.doFirst { bootBuildInfo } compileJava.doFirst { generateGitProperties } - // Disable generate Git Properties via environment - e.g. if we are in a Docker build ext.generateGitProps=System.getProperty('GENERATE_GIT_PROPERTIES') ext.generateGitProps=ext.generateGitProps==null?"true":ext.generateGitProps @@ -75,8 +76,8 @@ dependencies { implementation 'org.apache.commons:commons-lang3:3.6' implementation 'org.apache.commons:commons-exec:1.3' implementation 'commons-io:commons-io:2.6' - implementation 'org.projectlombok:lombok:1.18.10' - annotationProcessor 'org.projectlombok:lombok:1.18.10' + implementation 'org.projectlombok:lombok:'+lombokVersion + annotationProcessor 'org.projectlombok:lombok:'+lombokVersion testImplementation 'org.springframework.boot:spring-boot-starter-test' } diff --git a/docker-compose.yml b/docker-compose.yml index ae36ddc..eea15b9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,7 @@ version: "3.2" services: postgres: + container_name: pg image: postgres:11 restart: always environment: @@ -16,13 +17,14 @@ services: # - PGDATA="/var/lib/postgresql/data/pgdata" # ports: # - "5432:5432" - #volumes: - #- ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh - # GCP: - /mnt/stateful_partition/APP/postgres/db:/var/lib/postgresql/data/pgdata - # local dir: - ${DATADIR:?}/postgres:/var/lib/postgresql/data libeufin: - image: e36io/libeufin:mergeLibeufin + container_name: libeufin + image: e36io/libeufin:hyperfridge + # local dev: + # build: + # context: ../LibEuFin + depends_on: - postgres environment: @@ -42,14 +44,15 @@ services: - POSTGRES_HOST=postgres - POSTGRES_DB=libeufindb - DANGEROUSLY_DISABLE_HOST_CHECK=true + + # not used because they are default values + # - CLIENT_PR_KEY_OUT=/app/keys/client_private_key.pem + # - CLIENT_PUB_KEY_OUT=/app/keys/client_public_key.pem + # - BANK_PUB_KEY_OUT=/app/keys/bank_public_key.pem command: /app/scripts/init_libeufin_sandbox.sh tty: true stdin_open: true # without this node doesn't start; https://stackoverflow.com/questions/61857267/how-to-make-yarn-start-work-inside-docker-image-with-react-scripts-3-4-and-babel - expose: - - 5016 - - 3000 - - 5000 ports: - "5016:5016" # sandbox - "5001:5000" # nexus @@ -59,12 +62,15 @@ services: - 3000 - 5001 volumes: - - ./scripts:/app/scripts + - ./scripts:/app/scripts:rw + - ./keys:/app/keys:rw + - ./trace:/app/trace:rw ebics-service: - #image: e36io/ebics-service:updateLibeufin - build: - context: . + image: e36io/ebics-service:hyperfridge + # container_name: ebics + # build: + # context: . depends_on: - libeufin environment: @@ -73,8 +79,67 @@ services: - LIBEUFIN_NEXUS_URL=http://libeufin:5000 - LIBEUFIN_SANDBOX_ADMIN_PASSWORD=superpassword - LIBEUFIN_SANDBOX_USERNAME=admin - - LIBEUFIN_SANDBOX_PASSWORD=superpassword + - LIBEUFIN_SANDBOX_PASSWORD=superpassword + - FRIDGE_OUT_DIR=file:/app/work_out/ ports: - "8093:8093" expose: - 8093 + volumes: + - recipie-dir:/app/work_out/:rw + + hyperfridge: + # profiles: + # - dev + container_name: fridge + image: e36io/hyperfridge-r0:latest + # build: + # context: /home/w/workspace/hyperfridge-r0 + # dockerfile: ${DOCKERFILE:-DockerfileLinux} # Default to DockerfileLinux, override with DOCKERFILE environment variable if provided + + environment: + # for watchdog.sh which generates a new proof in /app/out/ as soon as new file ebics file is dedected in /app/in/ + - CLIENT_PR_KEY=/app/keys/client_private_key.pem + - CLIENT_PUB_KEY=/app/keys/client_public_key.pem + - BANK_PUB_KEY=/app/keys/bank_public_key.pem + - WITNESS_PUB_KEY=/data/pub_witness.pem + - WITNESS_PR_KEY=/data/witness.pem + - IN_DIR=/app/in/ + - WORK_DIR=/app/work/ + - OUT_DIR=/app/out/ + - HOST_CMD=/app/host + command: /data/watchdog.sh + working_dir: /data + volumes: + - recipie-dir:/app/out/:rw + - ./keys/:/app/keys/:ro + - ./trace:/app/in:ro + # for DEV + # - /home/w/workspace/hyperfridge-r0/data/checkResponse.sh:/data/checkResponse.sh + # - /home/w/workspace/hyperfridge-r0/data/watchdog.sh:/data/watchdog.sh + + pgadmin: + profiles: + - dev + container_name: dbadmin + image: dpage/pgadmin4:7.6 + environment: + PGADMIN_DEFAULT_EMAIL: admin@example.com + PGADMIN_DEFAULT_PASSWORD: root + MAX_LOGIN_ATTEMPTS: '15' # Ensure this is a string, not a number + POSTGRES_USER: pgrootuser + POSTGRES_PASSWORD: pgrootpassword + POSTGRES_HOST: postgres + POSTGRES_DB: libeufindb + DANGEROUSLY_DISABLE_HOST_CHECK: 'true' # Ensure this is a string, not a boolean + + depends_on: + - postgres + volumes: + - /home/w/pgadmin:/var/lib/pgadmin:rw + user: root + ports: + - "53603:53603" + - "8081:80" #mapped on w.e36.io:35050; admin@example.com root; add server medi medi medi +volumes: + recipie-dir: \ No newline at end of file diff --git a/docs/HOWTO.md b/docs/HOWTO.md index a770797..ac4a1fe 100644 --- a/docs/HOWTO.md +++ b/docs/HOWTO.md @@ -41,8 +41,14 @@ The successful setup is shown by: 2021-05-22 07:53:48,251 INFO - Configuration initialization 2021-05-22 07:53:48,254 INFO - Loading user 4444444 2021-05-22 07:53:48,355 INFO - The user 4444444 was loaded successfully - - + +### Set up docker based development environment and test + +- Use docker compose rm/build/run +- On Swagger: http://localhost:8093/ebics/swagger-ui/?url=/ebics/v2/api-docs/#/ebics-controller/createPaymentOrderUsingPOST + - Create order just change the amount: http://localhost:8093/ebics/swagger-ui/?url=/ebics/v2/api-docs/#/ebics-controller/createPaymentOrderUsingPOST + - Do fetch-transactions by calling this endpoint - you should see the above amount in there: http://localhost:8093/ebics/swagger-ui/?url=/ebics/v2/api-docs/#/ebics-controller/getPaymentsUsingGET + ## FAQ ### Setup with your bank diff --git a/docs/TEST.md b/docs/TEST.md index 7eaab57..9b17d92 100644 --- a/docs/TEST.md +++ b/docs/TEST.md @@ -1,63 +1,105 @@ # Tests -## Run unit tests +## Run unit tests ![Coverage](../.github/badges/jacoco.svg) -Run tests for the ebics-java-client on linux - it mounts sources into a docker container with java and the maven build tool - so you do not need to install java or gradle on your local machine: +Run tests for the ebics-java-client on linux - it mounts sources into a gradle docker container with java and the maven build tool - so you do not need to install java or gradle on your local machine: git clone https://github.com/element36-io/ebics-java-service.git - cd ebics-java-service; mkdir ./app; - docker run -it -v $PWD:/app -w /app gradle:6-jdk8-hotspot gradle test + cd ebics-java-service + docker run -it -v $PWD:/app -w /app gradle:6-jdk11 gradle clean test + On your host machine, test results are stored `./build/reports/tests/test/index.html`, test documents are stored in `./out`. With minimum Java 8 and Maven run tests on your host machine with `gradle test`, again see `./build/reports/tests/test/index.html` for test results. For test coverage: `./build/reports/jacoco/test/html/index.html`. Test for vulnerabilities `gradle dependencyCheckAggregate`- see report in `./build/reports`. -See [here](https://github.com/element36-io/ebics-java-client/blob/master/README.md) how to run tests on ebics-java-client. +If you are interested in the Ebics Client implementation as well, look [here](https://github.com/element36-io/ebics-java-client/blob/master/README.md). -## Test API manually +# Run with docker - docker run -p 8093:8093 e36io/ebics-service +Checkout [hyperfridge](https://github.com/element36-io/hyperfridge-r0) and [banking backend](https://github.com/element36-io/LibEuFin) at same directory as ebics-java-service to build images locally: -or with existing Ebics configuration + git clone git@github.com:element36-io/LibEuFin.git + cd LibEuFin + ./bootstrap + cd .. + git cline git@github.com:element36-io/XXXXXXX.git - docker run -p 8093:8093 -v $HOME/ebics:/root/ebics e36io/ebics-service +Build on Linux: -or with existing Ebics configuration and in production mode + cd ebics-java-service + docker compose build - docker run -p 8093:8093 -v $HOME/ebics:/root/ebics --env spring.profiles.active=prod e36io/ebics-service +On Mac: -Open [Swagger](http://localhost:8093/ebics/swagger-ui/?url=/ebics/v2/api-docs/) in your -browser and test the API. Ony if you set the image to production mode, it will -try co connect with your bank. In dev mode it will log its commands and generated -documents. You may check and download the payment document (ebics document) under `./app` -which can be tested manually against your bank. To set up and connect to your banks -Ebics API you need to [switch to productive spring boot -profile](https://www.baeldung.com/spring-profiles) by using `export spring_profiles_active=prod`. + cd ebics-java-service + DOCKERFILE=DockerfileMacOs docker compose build + + +## Test API and download ZK proof + +First create a Payment on the banking backend: + + curl -X 'POST' \ + 'http://localhost:8093/ebics/api-v1/createOrder' \ + -H 'accept: */*' \ + -H 'Content-Type: application/json' \ + -d '{ + "amount": "123", + "clearingSystemMemberId": "HYPLCH22XXX", + "currency": "EUR", + "msgId": "emtpy", + "nationalPayment": true, + "ourReference": "empty", + "pmtInfId": "empty", + "purpose": "0x9A0cab4250613cb8437F06ecdEc64F4644Df4D87", + "receipientBankName": "Hypi Lenzburg AG", + "receipientCity": "Baar", + "receipientCountry": "CH", + "receipientIban": "CH1230116000289537313", + "receipientName": "element36 AG", + "receipientStreet": "Bahnmatt", + "receipientStreetNr": "25", + "receipientZip": "6340", + "sourceBic": "HYPLCH22XXX", + "sourceIban": "CH2108307000289537320" + }' -### Test `/ebics/api-v1/simulate' +Download daily statement which should inluce prior payment and the STARK: -Create a test transaction - send funds form your bank account to somebody else. -The result shows the Ebics file generated by the request. -You may test this file with your bank prior to activating Ebics: Many -banks offer buld-upload function which read Camt.053 format via web-interface. + curl -X 'GET' \ + 'http://localhost:8093/ebics/api-v1/bankstatements' \ + -H 'accept: */*' -o result.json -Same behaviour in dev and prod environment. +Extract the filename of the proof and download it: -### Test `/ebics/api-v1/bankstatements' + PROOF=$(cat result.json | grep \ + -o '"receiptUrl":"[^"]*"' | cut -d'"' -f4) + wget "http://localhost:8093/ebics/$PROOF" -O receipt.json -Retrieves bank statement and translates Camt.053 format to Json. +Verify the proof with the verifier: + + # we need the image id and the receipt + imageid=$(docker run fridge cat /app/IMAGE_ID.hex) + docker cp receipt.json fridge:/app/receipt.json + docker exec -it -e RISC0_DEV_MODE=true fridge verifier \ + verify --imageid-hex="$imageid" --proof-json="/app/receipt.json" + + +## Test API manually with Swagger + +Open [Swagger](http://localhost:8093/ebics/swagger-ui/?url=/ebics/v2/api-docs/) in your +browser and test the API and follow instructions [here](manual/manual.md) for a manual test. -In dev mode you see the command which is issued to query the daily statement. -### Test `/ebics/api-v1/unpeg' +## Login to simulated banking backend UI -Create a tarnsaction with your pegging account configured in `ebics.pegging.account`. -:warning: In prod mode it sends real money - in dev mode it shows the command and the Ebics document in the result. +Open [LibFinEu](http://localhost:3000) in your +browser with 'foo' and 'superpassword'. -### Test `/ebics/api-v1/createOrder' +Go to [Activity](http://localhost:3000/activity) and select 'CH2108307000289537320' to see the transations you created before. -At your bank you can have more than one bank account. The Ebics interface allows you to access all of them at once: -Daily statements will cover transactions of all accounts - and you can create new transactions from any bank account from the Ebics interface. +Note that this is an external component which also can be used to connect to any bank supporting EBICS. It shows that the protocoll is used in a standard way. diff --git a/docs/advanced-testing.md b/docs/advanced-testing.md new file mode 100644 index 0000000..ec8d7a3 --- /dev/null +++ b/docs/advanced-testing.md @@ -0,0 +1,64 @@ +# Tests + +## Run unit tests + +![Coverage](../.github/badges/jacoco.svg) + +Run tests for the ebics-java-client on linux - it mounts sources into a gradle docker container with java and the maven build tool - so you do not need to install java or gradle on your local machine: + + git clone https://github.com/element36-io/ebics-java-service.git + cd ebics-java-service + docker run -it -v $PWD:/app -w /app gradle:6-jdk11 gradle clean test + + +On your host machine, test results are stored `./build/reports/tests/test/index.html`, test documents are stored in `./out`. With minimum Java 8 and Maven run tests on your host machine with `gradle test`, again see `./build/reports/tests/test/index.html` for test results. + +For test coverage: `./build/reports/jacoco/test/html/index.html`. +Test for vulnerabilities `gradle dependencyCheckAggregate`- see report in `./build/reports`. + +If you are interested in the Ebics Client implementation as well, look [here](https://github.com/element36-io/ebics-java-client/blob/master/README.md). + +## Test API manually + + docker run -p 8093:8093 e36io/ebics-service + +or with existing Ebics configuration + + docker run -p 8093:8093 -v $HOME/ebics:/root/ebics e36io/ebics-service + +or with existing Ebics configuration and in production mode + + docker run -p 8093:8093 -v $HOME/ebics:/root/ebics --env spring.profiles.active=prod e36io/ebics-service + +Open [Swagger](http://localhost:8093/ebics/swagger-ui/?url=/ebics/v2/api-docs/) in your +browser and test the API. Ony if you set the image to production mode, it will +try co connect with your bank. In dev mode it will log its commands and generated +documents. You may check and download the payment document (ebics document) under `./app` +which can be tested manually against your bank. To set up and connect to your banks +Ebics API you need to [switch to productive spring boot +profile](https://www.baeldung.com/spring-profiles) by using `export spring_profiles_active=prod`. + +### Test `/ebics/api-v1/simulate' + +Create a test transaction - send funds form your bank account to somebody else. +The result shows the Ebics file generated by the request. +You may test this file with your bank prior to activating Ebics: Many +banks offer buld-upload function which read Camt.053 format via web-interface. + +Same behaviour in dev and prod environment. + +### Test `/ebics/api-v1/bankstatements' + +Retrieves bank statement and translates Camt.053 format to Json. + +In dev mode you see the command which is issued to query the daily statement. + +### Test `/ebics/api-v1/unpeg' + +Create a tarnsaction with your pegging account configured in `ebics.pegging.account`. +:warning: In prod mode it sends real money - in dev mode it shows the command and the Ebics document in the result. + +### Test `/ebics/api-v1/createOrder' + +At your bank you can have more than one bank account. The Ebics interface allows you to access all of them at once: +Daily statements will cover transactions of all accounts - and you can create new transactions from any bank account from the Ebics interface. diff --git a/docs/superfridge.svg b/docs/hyperfridge.svg similarity index 100% rename from docs/superfridge.svg rename to docs/hyperfridge.svg diff --git a/docs/manual/1.png b/docs/manual/1.png new file mode 100644 index 0000000..ab39cce Binary files /dev/null and b/docs/manual/1.png differ diff --git a/docs/manual/2.png b/docs/manual/2.png new file mode 100644 index 0000000..95fa930 Binary files /dev/null and b/docs/manual/2.png differ diff --git a/docs/manual/3.png b/docs/manual/3.png new file mode 100644 index 0000000..103eb6d Binary files /dev/null and b/docs/manual/3.png differ diff --git a/docs/manual/4.png b/docs/manual/4.png new file mode 100644 index 0000000..6f3d3dc Binary files /dev/null and b/docs/manual/4.png differ diff --git a/docs/manual/5.png b/docs/manual/5.png new file mode 100644 index 0000000..3da9b01 Binary files /dev/null and b/docs/manual/5.png differ diff --git a/docs/manual/6.png b/docs/manual/6.png new file mode 100644 index 0000000..ba186a0 Binary files /dev/null and b/docs/manual/6.png differ diff --git a/docs/manual/7.png b/docs/manual/7.png new file mode 100644 index 0000000..5c006b9 Binary files /dev/null and b/docs/manual/7.png differ diff --git a/docs/manual/manual.md b/docs/manual/manual.md new file mode 100644 index 0000000..d921480 --- /dev/null +++ b/docs/manual/manual.md @@ -0,0 +1,27 @@ +# UI Tests + +Use Swagger for API call: + +## Create a payment + +![Click Endpoint ](1.png) +![Try It ](2.png) +![Change Amount ](3.png) + +Hit Execute. + +## Generate Dailay Statement + + +![Click Endpoint ](4.png) +![Try It ](5.png) +![Change Amount ](6.png) + +Note the receiptUrl for later download: +![Hit Execute ](7.png) + +## Download the proof + +Add the value of recieptUrl to 'http://localhost:8093/ebics/': + +http://localhost:8093/ebics/receipt_XXXXXXXXXXXX.json diff --git a/docs/milestones.md b/docs/milestones.md new file mode 100644 index 0000000..4b1f0f7 --- /dev/null +++ b/docs/milestones.md @@ -0,0 +1,38 @@ +# Overview of Milestone deliveries + +## Milestone 2 - Banking API Integration + +- **Estimated duration:** 1 month +- **FTE:** 1.2 +- **Costs:** 5,000 USD + +| Number | Deliverable | Specification | Assets | +| ----- | ----------- | ------------- | ------ | +| 0a. | License | Apache 2.0 | [Link to Licence](https://github.com/element36-io/ebics-java-client?tab=LGPL-2.1-1-ov-file) | +| 0b. | Documentation | We will provide both inline documentation of the code and a basic tutorial that explains how a user can start the backend and send test transactions, which will show how the new functionality works.| [Link to Documentation Root](https://github.com/element36-io/ebics-java-service?tab=readme-ov-file) | +| 0c. | Testing Guide | Adapt unit tests of core functions and test data to ensure functionality and robustness of the overall system (bridge and proofs). In the guide, we will describe how to run these tests. | [Testing Guide](TEST.md)| +| 0d. | Docker | We will provide a Dockerfile(s) that can be used to test all the functionality delivered with this milestone. |[Testing Guide: "Run with Docker"](TEST.md)| +| 1. | Generate Receipt | Retrieve data form backend and generate receipt (proof) using the proving system. | [Testing Guide: Run with Docker](TEST.md)| +| 2. | Provide API | We will provide an application based on Spring-Boot that will contain `getBankstatements():Statement[]` (which includes account balance), `createOrder (OutgoingPayment)` and `simulatePayment(Payment)` as a REST interface as [described](#b-bank-account-rest-api). The recipe data is added in the [backend API](http://w.e36.io:8093/ebics/swagger-ui/?url=/ebics/v2/api-docs/#/) `/ebics/api-v1/bankstatements`` with two new fields in the top level of the JSON-response: `recipeiUrl` so that clients can use a public verifier to check the proof. | [Testing Guide](TEST.md), go to "Test API manually with Swagger"| +| 3. | Provide Banking-UI | Show a UI to see the status of banking backend (show accounts, transactions etc). We will use [LibEuFin](https://github.com/element36-io/ebics-java-service/blob/main/docs/SANDBOX.md) - same as in our first grant. | [Testing Guide](TEST.md), got to "Login to simulated banking backend UI"| +| 4. | Unit Tests | We will adapt unit tests and test data to cover creating and validating proofs. | [Testing Guide](TEST.md), go to "Run unit tests" on top of the document.| +| 5. | Repository | Repository will be the existing repo [ebics-java-service](https://github.com/element36-io/ebics-java-service) | [ebics-java-service](https://github.com/element36-io/ebics-java-service) | +| 6. | Backend-Docker | Provide docker-compose images for setting up banking API wrapper, LibEuFin proxy for banking-API. Set up test data in the backend via script and run tests which include the proving system. | [Testing Guide](TEST.md) - when starting services with docker compose. Test data and scripts [here](../scripts/). | +| 7. | Swagger | Provide Swagger docu for the backend. | [localhost:8093](http://localhost:8093/ebics/swagger-ui/?url=/ebics/v2/api-docs/#/) | + + +##DONE: Milestone 1 from [Hyperfridge](https://github.com/element36-io/hyperfridge-r0) + + +| Number | Deliverable | Specification | Assets | +| -----: | ----------- | ------------- | ------ | +| 0a. | License | Apache 2.0 | [Link to Licence](https://github.com/element36-io/hyperfridge-r0/blob/main/LICENSE) | +| 0b. | Documentation | We will provide both inline documentation of the code, a basic tutorial and a markdown description of the proof system. | [Link to Documentation Root](https://github.com/element36-io/hyperfridge-r0/blob/main/README.md)| +| 0c. | Testing Guide | Provide unit tests of core functions and test data to ensure functionality. In the guide, we will describe how to run these tests. | [Link to Testing Guide](https://github.com/element36-io/hyperfridge-r0/blob/main/docs/INSTRUCTIONS.md) | +| 0d. | Docker | We will provide a Dockerfile(s) that can be used to test all the functionality delivered with this milestone. | [Dockerhub](https://hub.docker.com/repository/docker/e36io/hyperfridge-r0/general) [Testing Guide](https://github.com/element36-io/hyperfridge-r0/blob/main/docs/INSTRUCTIONS.md) +| 1a. | risc0 Guest Program | Code (circuit) to generate the proof, later used by the proving system. Secret input of [Guest Program](https://dev.risczero.com/terminology#guest-program): Ebics envelope as XML and Z53/Camt53 file(s) as ZIP binary - see XML examples above. The Public input is: Public Certificate of the Bank or name of bank, bank account number, balance and date. The [journal](https://dev.risczero.com/terminology#journal) will contain balance, currency, timestamp in the ebics-envelope, timestamp of the proof, client-account-number, Bank-ID and sequence number of the bank-statement. The circuit will check the hash of the (zipped) Z53 documents and compares it with the data given in the ebicsRequest. It checks the signature of the Ebics request and the signed hash of the ZIP file using crypto standards X002 and E002. "X002" refers to RSA signature key with a key length of 2048 bits, "E002" defines RSA algorithm for encryption using ECB (Electronic Codebook) and PKCS#1 v1.5 padding.| [Repo](https://github.com/element36-io/hyperfridge-r0/tree/main/methods/guest) +| 1b. | Generate Receipt | Generate [receipt](https://dev.risczero.com/terminology#receipt) which proves that the computation (e.g. balance) is correct and signed by the bank. | [Testing Guide](https://github.com/element36-io/hyperfridge-r0/blob/main/docs/INSTRUCTIONS.md)| +| 1c. | Validator | Code to validate the receipt. | [Repo](https://github.com/element36-io/hyperfridge-r0/tree/main/verifier)| +| 1d. | Hyperfridge Crate | The crate to create and validate recipes (ZKPs), wrapping the functionality. | [Repo](https://github.com/element36-io/hyperfridge-r0/tree/main/host) +| 2. | Unit Tests | We will add unit tests and test data for creating and validating proofs which includes edge cases like wrong balance claims or faulty signature of the bank. | [Testing Guide](https://github.com/element36-io/hyperfridge-r0/blob/main/docs/INSTRUCTIONS.md) | +| 3. | Performance Benchmark | Present a table with performance metrics, so that hyperfride proofing times can be interpolated with data from [risc-zero](https://dev.risczero.com/datasheet.pdf). | [Benchmarks](runtime.md) | \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 30c168e..9dd458c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ springCloudVersion=2020.0.1 #systemProp.gradle.springRelease='2.2.12.RELEASE' springVersion=2.4.5 -lombokVersion=1.18.10 +lombokVersion=1.18.16 owaspVersion=6.0.1 jaxbVersion=2.3.1 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 87b738c..7454180 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4d9ca16..2e6e589 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index af6708f..1b6c787 100755 --- a/gradlew +++ b/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m"' +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 0f8d593..ac1b06f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/hyperfridge-notes.md b/hyperfridge-notes.md new file mode 100644 index 0000000..6fa2c32 --- /dev/null +++ b/hyperfridge-notes.md @@ -0,0 +1,12 @@ +# client libeufin-nexus + +https://docs.taler.net/manpages/libeufin-nexus.conf.5.html + +PARTNER_ID +EBICS specific: partner ID of the EBICS subscriber. This value must be assigned by the bank after having activated a new EBICS subscriber. + +BANK_PUBLIC_KEYS_FILE +Filesystem location where Nexus should store the bank public keys. + +CLIENT_PRIVATE_KEYS_FILE + diff --git a/keys/bank_public_key.pem b/keys/bank_public_key.pem new file mode 100644 index 0000000..9297b7a --- /dev/null +++ b/keys/bank_public_key.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh8lqYMCn4etXrj8bCmRN +d5k7HO2LFptyMXH9pbW6jGCBZvkOMLAV5JXaRkjygX53PgQ9UMH/4RxIgyFLurxY +PnqWdV+BXn1hFPtUBGnRLHvXMpq4lcQ4NUq7u6U0QXr8WIMuYV1XB+HCSweJiWhD +wPMKHjIuqnW0uamoPIPmj6ZYUdyTQXkH0rtCIIYge0dQ0d47w95o+DSYn2ZX6FBx +4BpcoVHRs7sK+HyURJU6dgtdnuC0p5DD1ageExUuUhSht5QBXVycxmOMmxIGyfRi +Do7WEIzxReMshVZt2UlVqM6Ok/GYGEePt8k46foHN4YRDHEQz8UyAD5yXa+G+g+l +LQIDAQAB +-----END PUBLIC KEY----- diff --git a/keys/bank_public_key.pem-enc b/keys/bank_public_key.pem-enc new file mode 100644 index 0000000..b71c3dd --- /dev/null +++ b/keys/bank_public_key.pem-enc @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr11VRbdiRkzBARVAe2i1 +bZJWEV3c+nVNCJP7Sp+vF3il0OVeoUNBeqwHUr7CPUWTchQAWQE3eTFmvuOxonUX +fOFLcRLRkcx9WAyQPHFnxV4KDpETvz+JRUBJQ+z7t5EGfVkaaZyYHcIph76lLmKS +O1IeArWp+TcqgWHzOUUDGIlnILQB4q6QJME10OEsXQw/XPue5sm8t2sGtxvLxjGp ++dy1J5xJ0NAdX38CcHK7oJ8+Ku6LyV/Zs4gsYGQ8NtK7oZGl8rc9h/VvMayYwpK8 +2CmRBPoQ09w+Va7HpjT3MQlv9m35pCgGA2hvjufgG+UDBnRyR6c7avteLok7MYk7 +wQIDAQAB +-----END PUBLIC KEY----- diff --git a/keys/client_private_key.pem b/keys/client_private_key.pem new file mode 100644 index 0000000..dc74cf3 --- /dev/null +++ b/keys/client_private_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDF7hoYeRuZv7z2 +0sdblQSwG8J3BUmU3OKgowGGUkeIdiXC1fH1giKnPla9fucKSOZYSMPem51wyms/ +NDHJL75WMN2+u9/cuFnMlxGhEcIvamKjNNpdZl3/dTY510X9Mp+GDSpGFvjW/sJn +sgCBT26CgQ4G04AvezMiFu9GXRzliGjjw+H9+wzr9Y6GdhNtmYOibJxtr5O627uB +weggLdlFpANEAkLwnEPVVrThcdvrRTnCkrhtYv9m8tqFeULKjGamLuIP+AzL5ZHI +H/lPW6PlzgLdzaXbI6mVGoUmL8TlrMY3tHeqqcrIJdK3FcV8nUmfjpgZVWNTAnL5 +ZsgpukR3AgMBAAECggEALLspxJwiI7YUY4exLD5aR96OLU3RmkXtJbaREqUnq2xg +Dk9BlmVppXhOLBcw6b8d55fSRE3Q3/uvDyKhmcEjd+ElTASzi/NRwA3oGwmjZAnb +7txz+SW4WpJHxfyjwZweNzJkemCYriX3E25D9PVZmT7HR72mu5RRMwQR4UoLzMeH ++8BDilRx/Sx7VkUnUfoNhJ9vzBGwfU+5oD3fzigpQ8YAtdZPh96LOlenOyCBuovz +8pWvYTm5DRvID0qpvIgLVz1uNJW7avTaYRy/yN+PKx9YxowHu0jzfeSimfVnUIhY +kf+5PBkKok6XkswsHNE5kdGFGYKR7SjmQMhPXxwgOQKBgQD5jR92BSgc3uVmyk4t +xFkTYaC7imS4OmwzBLI9wClo+Np1iMLJOxAZ6M9SUpQL+QjPXg7m+fv8dPIWmgg3 +dNdN1Des5Iuz+E6m9ceiTW1GCzmx4BNWeaFf1mYIusdvSuRtmvrRrD6v+jqzVqBd +vS+PfwvrPOc5lkx1rEL97QPphQKBgQDLC3w2jYFMN+LGUvizSsBM4KBiLyDP3odM +5G5MDaPl0WxvFsBgYmQHECvjc7eU4mRD1snsrOOBsfMf/iGAMQ0GcR/07E0u3YGQ +rxC3Awx1R5443SZiiz00utBXClIaE/yugo0r5kjVkvl87kgsZKUVHJFrmC4DTRuz +iWsRgs84ywKBgCEqdlHzIX+kyAw/OuCuRcBjqz8Bh51MdnDZYO8ACQDggfg48tpX +tS4cWOFyBCcLM/aLY6Oi+bB1wm7qjckBCFRZrgSWY1LJ33olFCEn9Svn9gUD6M4H +YEEid3EVkcfixjUi8c7H+5Tbxs1q5+lNaXLCycy7zWdD6GmDOWwSAgEZAoGAblQ4 +U4BCoMLBQ9iz8OCOa3enTpKjNrCJPnvlfwfuZiOM0zQ+pmDwT3I3Fum6+Hin2MDu +id9L5B5oqJqzY2/DzxtLLQ/1xKByFcc6wucyLswSqn1orSVRxcQ5DwK5qBfyNnUT +9qW0L/EkBgGIUC8EENusHRXc8shEZCMofaRhq08CgYEAkIaB/ob+Ie4LUatvKKdK +Uzkqp6WHU2frGXdmxmqT7PqbOMwZpvZE1/9IZf3sKQXBWUO1o932RRAGlL0myCku +I3qUAj69EYae4VMclcATFZ5CMUo4oODEp5nAnaXoJPwl58/4LpQFf4bvpQj5rhbI +a2gMDicAD0bzPR2+zd4ecW8= +-----END PRIVATE KEY----- diff --git a/keys/client_public_key.pem b/keys/client_public_key.pem new file mode 100644 index 0000000..591debb --- /dev/null +++ b/keys/client_public_key.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxe4aGHkbmb+89tLHW5UE +sBvCdwVJlNzioKMBhlJHiHYlwtXx9YIipz5WvX7nCkjmWEjD3pudcMprPzQxyS++ +VjDdvrvf3LhZzJcRoRHCL2piozTaXWZd/3U2OddF/TKfhg0qRhb41v7CZ7IAgU9u +goEOBtOAL3szIhbvRl0c5Yho48Ph/fsM6/WOhnYTbZmDomycba+Tutu7gcHoIC3Z +RaQDRAJC8JxD1Va04XHb60U5wpK4bWL/ZvLahXlCyoxmpi7iD/gMy+WRyB/5T1uj +5c4C3c2l2yOplRqFJi/E5azGN7R3qqnKyCXStxXFfJ1Jn46YGVVjUwJy+WbIKbpE +dwIDAQAB +-----END PUBLIC KEY----- diff --git a/scripts/init_libeufin_sandbox.sh b/scripts/init_libeufin_sandbox.sh index aa4ec8f..6db5c5f 100755 --- a/scripts/init_libeufin_sandbox.sh +++ b/scripts/init_libeufin_sandbox.sh @@ -14,7 +14,7 @@ export REGISTERED_BIC=HYPLCH22XXX export CONNECTION_NAME=testconnection export SECRET=backupsecret -export BACKUP_FILE=/app/backupfile +export BACKUP_FILE=/app/scripts/backupfile export EBICS_USER_ID=e36 export EBICS_HOST_ID=testhost export EBICS_PARTNER_ID=e36 @@ -36,11 +36,12 @@ echo ... start nexus libeufin-nexus serve --port 5000 --host 0.0.0.0 & echo starting sandbox -libeufin-sandbox serve --port 5016 --auth & + libeufin-sandbox serve --port 5016 --auth & +# libeufin-sandbox serve --port 5016 & -echo check if sandbox is up +echo "Check if sandbox is up" until libeufin-cli sandbox check; do - >&2 echo "Sandbox is unavailable - sleeping" + echo "Sandbox is unavailable - sleeping" >&2 sleep 1 done @@ -54,6 +55,7 @@ if [ ! -f "/app/initdone" ]; then libeufin-cli sandbox ebicshost list echo ... create user $LIBEUFIN_SANDBOX_URL + libeufin-cli sandbox --help libeufin-cli sandbox --sandbox-url $LIBEUFIN_SANDBOX_URL/demobanks/default demobank register fi @@ -73,6 +75,7 @@ echo hostid $EBICS_HOST_ID echo partnerid $EBICS_PARTNER_ID echo userid $EBICS_USER_ID + # create sandbox accounts if [ ! -f "/app/initdone" ]; then @@ -110,8 +113,8 @@ if [ ! -f "/app/initdone" ]; then --ebics-user-id $EBICS_USER_ID \ $CONNECTION_NAME - # echo ... backup - # libeufin-cli connections export-backup --passphrase $SECRET --output-file $BACKUP_FILE $CONNECTION_NAME + echo ... backup + libeufin-cli connections export-backup --passphrase $SECRET --output-file $BACKUP_FILE $CONNECTION_NAME # This syncronization happens through the INI, HIA, and finally, HPB message types @@ -210,9 +213,6 @@ if [ ! -f "/app/initdone" ]; then fi -touch /app/initdone -ls -la /app/initdone - # install versions according to LibFinEu/frontend/README.md echo list ebicssubscriber @@ -225,6 +225,41 @@ libeufin-cli connections list-connections echo list show-connection libeufin-cli connections show-connection $CONNECTION_NAME +if [ ! -f "/app/initdone" ]; then + apt update --allow-releaseinfo-change + apt-get install -y jq qpdf xxd libxml2-utils openssl + + # client_pr_key="${CLIENT_PR_KEY:-/app/scripts/client_private_key.pem}" + # client_pub_key="${CLIENT_PUB_KEY:-/app/scripts/client_public_key.pem}" + # cat /app/scripts/backupfile | jq -r '.sigBlob' | openssl enc -d -base64 -A | openssl pkcs8 -inform DER -outform PEM -out $client_pr_key -passin pass:$SECRET + # openssl rsa -pubout -in $client_pr_key -out $client_pub_key + # echo "client pk exported to $client_pr_key public key to $client_pub_key " + client_pr_key=${CLIENT_PR_KEY_OUT:-/app/keys/client_private_key.pem} + client_pub_key=${CLIENT_PUB_KEY_OUT:-/app/keys/client_public_key.pem} + bank_pub_key=${BANK_PUB_KEY_OUT:-/app/keys/bank_public_key.pem} + + echo "save keys to $client_pr_key $client_pub_key $bank_pub_key " + sql="SELECT \"encryptionPrivateKey\" from nexusebicssubscribers s where \"hostID\"='testhost'" + # read hex key | convert to binary | create pem + PGPASSWORD=$POSTGRES_PASSWORD psql -d "$POSTGRES_DB" -h "$POSTGRES_HOST" -U "$POSTGRES_USER" -t -c "$sql" | xxd -r -p | openssl pkcs8 -topk8 -nocrypt -inform DER -out $client_pr_key + openssl rsa -in $client_pr_key -pubout -out $client_pub_key + echo "get bank pub auth key" + sql="SELECT \"bankAuthenticationPublicKey\" from nexusebicssubscribers s where \"hostID\"='testhost'" + PGPASSWORD=$POSTGRES_PASSWORD psql -d "$POSTGRES_DB" -h "$POSTGRES_HOST" -U "$POSTGRES_USER" -t -c "$sql" | xxd -r -p | openssl rsa -pubin -inform DER -outform PEM -out $bank_pub_key + sql="SELECT \"bankEncryptionPublicKey\" from nexusebicssubscribers s where \"hostID\"='testhost'" + PGPASSWORD=$POSTGRES_PASSWORD psql -d "$POSTGRES_DB" -h "$POSTGRES_HOST" -U "$POSTGRES_USER" -t -c "$sql" | xxd -r -p | openssl rsa -pubin -inform DER -outform PEM -out $bank_pub_key-enc + + echo "key generation done" +fi + +touch /app/initdone +ls -la /app/initdone + +read -t 10 -p "Setup & startup of nexus and sandbox complete, starting Libeufin react-ui UI on localhost:3000, login with: $LIBEUFIN_NEXUS_USERNAME $LIBEUFIN_NEXUS_PASSWORD " || true +#serve -s build +# /app/scripts/peg100.sh +# /app/scripts/test1.sh +echo "...starting yarn" echo versions of yarn npm node yarn --version npm --version @@ -233,5 +268,4 @@ cd /app/frontend/ #read -t 10 -p "Setup & startup of nexus and sandbox complete, starting Libeufin react-ui UI on localhost:3000, login with: $LIBEUFIN_NEXUS_USERNAME $LIBEUFIN_NEXUS_PASSWORD " #serve -s build -yarn start - +yarn start \ No newline at end of file diff --git a/scripts/shell.sh b/scripts/shell.sh new file mode 100755 index 0000000..cf6e38c --- /dev/null +++ b/scripts/shell.sh @@ -0,0 +1,30 @@ +#!/bin/bash +export IBAN=CH2108307000289537320 +export BIC=HYPLCH22XXX +export EXTERNAL_IBAN=CH1230116000289537312 +export EXTERNAL_BIC=HYPLCH22XXX +export REGISTERED_IBAN=CH2108307000289537313 +export REGISTERED_BIC=HYPLCH22XXX + +export CONNECTION_NAME=testconnection +export SECRET=backupsecret +export BACKUP_FILE=/app/scripts/backupfile +export EBICS_USER_ID=e36 +export EBICS_HOST_ID=testhost +export EBICS_PARTNER_ID=e36 +export LIBEUFIN_NEXUS_USERNAME=foo +export LIBEUFIN_NEXUS_PASSWORD=superpassword + +client_pr_key=${CLIENT_PR_KEY_OUT:-/app/keys/client_private_key.pem} +client_pub_key=${CLIENT_PUB_KEY_OUT:-/app/keys/client_public_key.pem} +bank_pub_key=${BANK_PUB_KEY_OUT:-/app/keys/bank_public_key.pem} + +sql="SELECT \"bankEncryptionPublicKey\" from nexusebicssubscribers s where \"hostID\"='testhost'" +echo $POSTGRES_PASSWORD +# PGPASSWORD=$POSTGRES_PASSWORD psql -d "$POSTGRES_DB" -h "$POSTGRES_HOST" -U "$POSTGRES_USER" -t -c "$sql" | xxd -r -p | openssl rsa -pubin -inform DER -outform PEM -out $bank_pub_key-enc + PGPASSWORD=$POSTGRES_PASSWORD psql -d "$POSTGRES_DB" -h "$POSTGRES_HOST" -U "$POSTGRES_USER" -t -c "$sql" | xxd -r -p | openssl rsa -pubin -inform DER -outform PEM -out /app/keys/t-bankEncryptionPublicKey.pem + +sql="SELECT \"bankAuthenticationPublicKey\" from nexusebicssubscribers s where \"hostID\"='testhost'" +echo $POSTGRES_PASSWORD +# PGPASSWORD=$POSTGRES_PASSWORD psql -d "$POSTGRES_DB" -h "$POSTGRES_HOST" -U "$POSTGRES_USER" -t -c "$sql" | xxd -r -p | openssl rsa -pubin -inform DER -outform PEM -out $bank_pub_key-enc + PGPASSWORD=$POSTGRES_PASSWORD psql -d "$POSTGRES_DB" -h "$POSTGRES_HOST" -U "$POSTGRES_USER" -t -c "$sql" | xxd -r -p | openssl rsa -pubin -inform DER -outform PEM -out /app/keys/t-bankAuthenticationPublicKey.pem diff --git a/scripts/test1.sh b/scripts/test1.sh index 2e06eae..4777355 100755 --- a/scripts/test1.sh +++ b/scripts/test1.sh @@ -6,7 +6,7 @@ echo "start\n" function send() { printf "\n create order from:$from, to:$to, amount:$amt." curl -X 'POST' \ - 'http://localhost:8093/ebics/api-v1/createOrder' \ + 'http://w.e36.io:8093/ebics/api-v1/createOrder' \ -H 'accept: */*' \ -H 'Content-Type: application/json' \ -d '{ @@ -65,27 +65,40 @@ function statement() { }' } +<<<<<<< Updated upstream statement from="CH2108307000289537313"; to="CH2108307000289537320"; amt="100"; send from="CH1230116000289537312"; to="CH2108307000289537320"; amt="100"; send statement +======= +#statement +#from="CH1230116000289537313"; to="CH2108307000289537320"; amt="100"; +#send +#from="CH1230116000289537312"; to="CH2108307000289537320"; amt="100"; +#send +#statement + +>>>>>>> Stashed changes printf "\n --> from 20" -from="CH2108307000289537320"; to="CH2108307000289537312"; amt="100"; -send +#from="CH2108307000289537320"; to="CH2108307000289537312"; amt="100"; +#send from="CH2108307000289537320"; to="CH2108307000289537313"; amt="100"; send -to="CH2108307000289537313"; amt="100"; -unpeg -statement -# -to="CH2108307000289537312"; amt="100"; -unpeg -statement +#statement -#/bank-accounts/CH2108307000289537320/transactions -#/bank-accounts/CH2108307000289537320/payment-initiations +#to="CH2108307000289537312"; amt="100"; +#unpeg +#statement +#to="CH2108307000289537313"; amt="100"; +#unpeg +statement +#to="CH2108307000289537312"; amt="100"; +#unpeg +#statement +#works /bank-accounts/CH2108307000289537320/transactions +# /bank-accounts/CH2108307000289537320/payment-initiations diff --git a/scripts/testkey.sh b/scripts/testkey.sh new file mode 100755 index 0000000..0cb39fb --- /dev/null +++ b/scripts/testkey.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Read the JSON file +json_file="backup.json" +contents=$(<"$json_file") + +# Extract and decode the three blob fields +auth_blob=$(echo "$contents" | jq -r '.authBlob') +enc_blob=$(echo "$contents" | jq -r '.encBlob') +sig_blob=$(echo "$contents" | jq -r '.sigBlob') + +# Convert base64 encoded keys to PEM format +echo "$auth_blob" | base64 -d > auth_public_key.pem +echo "$enc_blob" | base64 -d > enc_public_key.pem +echo "$sig_blob" | base64 -d > sig_public_key.pem + diff --git a/src/main/java/io/element36/cash36/ebics/config/SpringFoxConfig.java b/src/main/java/io/element36/cash36/ebics/config/SpringFoxConfig.java index 441a283..6f1ee80 100644 --- a/src/main/java/io/element36/cash36/ebics/config/SpringFoxConfig.java +++ b/src/main/java/io/element36/cash36/ebics/config/SpringFoxConfig.java @@ -34,8 +34,9 @@ public Docket api() { private ApiInfo apiInfo() { return new ApiInfo( - "Rest Wrapper for ebics-java-client", - "Access your bank account based on EBICS inface over a simple REST-API.", + "Rest Wrapper for ebics-java-client with Zero-Knowledge proofs (risc0-receipts) ", + "Access your bank account based on EBICS inface over a simple REST-API. "+ + "Access receipts via /ebics/receipt_(imageId)_(transactionId).json - transactionID is part of the bankstatements API. ", "API terms of service - see Apache 2.0 licence", "https://www.apache.org/licenses/LICENSE-2.0", new Contact("element36", "element36.io", "ask@element36.io"), diff --git a/src/main/java/io/element36/cash36/ebics/controller/EbicsController.java b/src/main/java/io/element36/cash36/ebics/controller/EbicsController.java index 15ce4ae..96cfa26 100644 --- a/src/main/java/io/element36/cash36/ebics/controller/EbicsController.java +++ b/src/main/java/io/element36/cash36/ebics/controller/EbicsController.java @@ -8,6 +8,7 @@ import javax.xml.datatype.DatatypeConfigurationException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -57,7 +58,8 @@ public class EbicsController { @Autowired GeneratePaymentIds generatePaymentIds; - @Autowired EbicsStatementService ebicsStatementService; + @Autowired + EbicsStatementService ebicsStatementService; @Autowired EbicsPaymentService ebicsPaymentService; @@ -286,7 +288,9 @@ public ResponseEntity simulate(@RequestBody @Valid Payment request) + "Anyway you see all Camt.053 files in the configured out folder (ebics.outputDir). " + "In dev mode you see the command which is issued to query the daily statement. " + "See https://wiki.xmldation.com/General_Information/Payment_Standards/ISO_20022/Bank-to-Customer_Cash_Management " - + "for more information about the standard. ") + + "for more information about the standard. \n\n" + + "Zero-Knowledge-Proofs: The service call will also Risc-Zero receipt and make is accessible via this endpoint, URL is in 'receiptUrl' parameter in the resuling JSON. " + + "A 404 indicates that the receipt is not ready yet or if the receipt could not be generated.") @GetMapping("/bankstatements") public ResponseEntity> getPayments() { log.debug("getStatement "); diff --git a/src/main/java/io/element36/cash36/ebics/dto/StatementDTO.java b/src/main/java/io/element36/cash36/ebics/dto/StatementDTO.java index 5f4cab5..9f74a2e 100644 --- a/src/main/java/io/element36/cash36/ebics/dto/StatementDTO.java +++ b/src/main/java/io/element36/cash36/ebics/dto/StatementDTO.java @@ -34,6 +34,12 @@ public class StatementDTO { @ApiModelProperty("IBAN of the account - in case you have more than one account at the bank") private String iban; + @ApiModelProperty("TransactionId of the EbicsRequest") + private String transactionId; + + @ApiModelProperty("Download-URL of the Risk0-receipt. You will get a 404 if the receipt is not ready yet or if the receipt could not be generated.") + private String receiptUrl; + @ApiModelProperty( "Closing booked balance (OPDB): https://subsembly.com/apidoc/sepa/Subsembly.Sepa.SepaBalanceType.html") private BigDecimal balanceOP; diff --git a/src/main/java/io/element36/cash36/ebics/service/impl/EbicsStatementServiceLibeufin.java b/src/main/java/io/element36/cash36/ebics/service/impl/EbicsStatementServiceLibeufin.java index 76dcb25..74180ff 100644 --- a/src/main/java/io/element36/cash36/ebics/service/impl/EbicsStatementServiceLibeufin.java +++ b/src/main/java/io/element36/cash36/ebics/service/impl/EbicsStatementServiceLibeufin.java @@ -82,8 +82,14 @@ public List getBankStatement() throws IOException { entity, FetchTransactionsResponse.class); - this.log.debug(" call --> " + uri); + this.log.debug(" call --> " + uri); this.log.debug(" response --> " + resp.getBody().toString()); + this.log.debug(" response.header Transaction-ID --> " + resp.getHeaders().getFirst("Transaction-ID")); + String transactionId = resp.getHeaders().getFirst("Transaction-ID"); + String receiptUrl=""; + if (transactionId != null) { + receiptUrl="receipt_"+transactionId+".json"; + } if (resp.getStatusCode() != HttpStatus.OK) throw new RuntimeException("Error fetching transactions from sandbox"); @@ -189,6 +195,8 @@ public List getBankStatement() throws IOException { libeufinConfig.accountBalance = libeufinConfig.accountBalance.add(updateBalance); smtResult + .receiptUrl(receiptUrl) + .transactionId(transactionId) .balanceCL(libeufinConfig.accountBalance) .balanceCLCurrency(libeufinConfig.accountCurrency) .balanceCLDate(now) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 6322deb..dbe3fd0 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -4,6 +4,13 @@ spring: name: cash36-ebics profiles: active: ${SPRING_PROFILES_ACTIVE:dev} + # web: + # resources: + # static-locations: file:./work_out/ + web: + resources: + static-locations: ${FRIDGE_OUT_DIR:file:./work_out/} + output: ansi: enabled: ${CASH36_ANSI:ALWAYS} @@ -34,9 +41,14 @@ ebics: proxy: # sends this ebics file when simulate is called statement: ${CASH36_EBICS_STATEMENT:simulated-account-statements.zip} + + + logging: level: - org.springframework: WARN - io.element36: TRACE - ROOT: WARN \ No newline at end of file + org.springframework: WARN + org.springframework.boot: DEBUG + org.springframework.web: DEBUG + io.element36: TRACE + ROOT: WARN \ No newline at end of file