diff options
author | Florian Dold <florian@dold.me> | 2021-10-07 12:01:40 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2021-10-07 12:01:40 +0200 |
commit | e2fe2d6db16b422ee6d69ef03f1393e1f0f42749 (patch) | |
tree | 7016f657b08b284afd62a55752baeab69d7be946 | |
parent | 2c3456608e8e87a86a5b2f62301b4ea78a2cb00d (diff) |
add anastasis skeleton, put crypto in taler-util
48 files changed, 1502 insertions, 376 deletions
diff --git a/packages/anastasis-core/package.json b/packages/anastasis-core/package.json new file mode 100644 index 000000000..acc46f7c1 --- /dev/null +++ b/packages/anastasis-core/package.json @@ -0,0 +1,30 @@ +{ + "name": "anastasis-core", + "version": "0.0.1", + "description": "", + "main": "index.js", + "scripts": { + "prepare": "tsc", + "compile": "tsc", + "pretty": "prettier --write src", + "test": "tsc && ava", + "coverage": "tsc && nyc ava", + "clean": "rimraf dist lib tsconfig.tsbuildinfo" + }, + "author": "Florian Dold <dold@taler.net>", + "license": "AGPL-3-or-later", + "type": "module", + "devDependencies": { + "ava": "^3.15.0", + "typescript": "^4.4.3" + }, + "dependencies": { + "@gnu-taler/taler-util": "workspace:^0.8.3", + "hash-wasm": "^4.9.0" + }, + "ava": { + "files": [ + "lib/**/*test.*" + ] + } +} diff --git a/packages/anastasis-core/src/anastasis-data.ts b/packages/anastasis-core/src/anastasis-data.ts new file mode 100644 index 000000000..4946e9dfd --- /dev/null +++ b/packages/anastasis-core/src/anastasis-data.ts @@ -0,0 +1,742 @@ +// This file is auto-generated, do not modify. +// Generated from v0.2.0-4-g61ea83c on Tue, 05 Oct 2021 10:40:32 +0200 +// To re-generate, run contrib/gen-ts.sh from the main anastasis code base. + +export const anastasisData = { + providersList: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + anastasis_provider: [ + { + url: "https://anastasis.demo.taler.net/", + currency: "KUDOS", + }, + { + url: "https://kudos.demo.anastasis.lu/", + currency: "KUDOS", + }, + { + url: "http://localhost:8086/", + currency: "TESTKUDOS", + }, + { + url: "http://localhost:8087/", + currency: "TESTKUDOS", + }, + { + url: "http://localhost:8088/", + currency: "TESTKUDOS", + }, + { + url: "http://localhost:8089/", + currency: "TESTKUDOS", + }, + ], + }, + countriesList: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + countries: [ + { + code: "al", + name: "Albania", + continent: "Europe", + name_i18n: { + de_DE: "Albanien", + en_UK: "Albania", + }, + currency: "ALL", + call_code: "+355", + }, + { + code: "be", + name: "Belgium", + continent: "Europe", + name_i18n: { + de_DE: "Belgien", + en_UK: "Belgium", + }, + currency: "EUR", + call_code: "+32", + }, + { + code: "ch", + name: "Switzerland", + continent: "Europe", + name_i18n: { + de_DE: "Schweiz", + de_CH: "Schwiiz", + fr_FR: "Suisse", + en_UK: "Swiss", + }, + currency: "CHF", + call_code: "+41", + }, + { + code: "cz", + name: "Czech Republic", + continent: "Europe", + name_i18n: { + en_UK: "Czech Republic", + }, + currency: "CZK", + call_code: "+420", + }, + { + code: "de", + name: "Germany", + continent: "Europe", + continent_i18n: { de_DE: "Europa" }, + name_i18n: { + de_DE: "Deutschland", + de_CH: "Deutschland", + fr_FR: "Allemagne", + en_UK: "Germany", + }, + currency: "EUR", + call_code: "+49", + }, + { + code: "dk", + name: "Denmark", + continent: "Europe", + continent_i18n: { de_DE: "Europa" }, + name_i18n: { + en_UK: "Denmark", + }, + currency: "DKK", + call_code: "+45", + }, + { + code: "es", + name: "Spain", + continent: "Europe", + continent_i18n: { es_ES: "Europa" }, + name_i18n: { + es_ES: "España", + }, + currency: "EUR", + call_code: "+44", + }, + { + code: "in", + name: "India", + continent: "India", + continent_i18n: { en_EN: "India" }, + name_i18n: { + de_DE: "Indien", + de_CH: "Indien", + fr_FR: "l'Inde", + en_UK: "India", + }, + currency: "INR", + call_code: "+91", + }, + { + code: "it", + name: "Italy", + continent: "Europe", + name_i18n: { + de_DE: "Italien", + en_UK: "Italy", + }, + currency: "EUR", + call_code: "+39", + }, + { + code: "jp", + name: "Japan", + continent: "Asia", + continent_i18n: { en_EN: "Japan" }, + name_i18n: { + de_DE: "Japan", + de_CH: "Japan", + en_UK: "Japan", + }, + currency: "JPY", + call_code: "+81", + }, + { + code: "sl", + name: "Slovakia", + continent: "Europe", + name_i18n: { + en_UK: "Slovakia", + }, + currency: "EUR", + call_code: "+421", + }, + { + code: "us", + name: "United States of America (USA)", + continent: "North America", + continent_i18n: { de_DE: "Nordamerika" }, + name_i18n: { + de_DE: "Vereinigte Staaten von Amerika (USA)", + de_CH: "Vereinigte Staaten von Amerika (USA)", + fr_FR: "États-Unis d'Amérique (USA)", + en_UK: "United States of America (USA)", + }, + currency: "USD", + call_code: "+1", + }, + { + code: "xx", + name: "Testland", + continent: "Testcontinent", + continent_i18n: { de_DE: "Testkontinent" }, + name_i18n: { + de_DE: "Testlandt", + de_CH: "Testlandi", + fr_FR: "Testpais", + en_UK: "Testland", + }, + currency: "TESTKUDOS", + call_code: "+00", + }, + { + code: "xy", + name: "Demoland", + continent: "Testcontinent", + continent_i18n: { de_DE: "Testkontinent" }, + name_i18n: { + de_DE: "Demolandt", + de_CH: "Demolandi", + fr_FR: "Demopais", + en_UK: "Demoland", + }, + currency: "KUDOS", + call_code: "+01", + }, + ], + }, + countryDetails: { + al: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "string", + name: "birthplace", + label: "Birthplace", + widget: "anastasis_gtk_ia_birthplace", + uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f", + }, + { + type: "string", + name: "nid_number", + label: "Numri i Identitetit", + label_i18n: { + en: "Identity Number", + al: "Numri i Identitetit", + }, + widget: "anastasis_gtk_ia_nid_al", + uuid: "256e5d30-d65e-481b-9ac4-55f5ac03b24a", + "validation-regex": + "^[0-9A-T][0-9](((0|5)[0-9])|10|11|51|52)[0-9]{3}[A-W]$", + "validation-logic": "AL_NID_check", + }, + ], + }, + be: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "date", + name: "birthdate", + label: "Birthdate", + widget: "anastasis_gtk_ia_birthdate", + uuid: "83d655c7-bdb6-484d-904e-80c1058c8854", + }, + { + type: "string", + name: "birthplace", + label: "Birthplace", + widget: "anastasis_gtk_ia_birthplace", + uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f", + }, + { + type: "string", + name: "nrn_number", + label: "National Register Number", + label_i18n: { + en: "National Register Number", + }, + widget: "anastasis_gtk_ia_nid_be", + uuid: "0452f99a-06f7-48bd-8ac0-2e4ed9a24560", + "validation-regex": "^[0-9]{11}$", + "validation-logic": "BE_NRN_check", + }, + ], + }, + ch: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "date", + name: "birthdate", + label: "Birthdate", + widget: "anastasis_gtk_ia_birthdate", + uuid: "83d655c7-bdb6-484d-904e-80c1058c8854", + }, + { + type: "string", + name: "birthplace", + label: "Birthplace", + widget: "anastasis_gtk_ia_birthplace", + uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f", + }, + { + type: "string", + name: "ahv_number", + label: "AHV number", + label_i18n: { + de_DE: "AHV-Nummer", + de_CH: "AHV-Nummer", + }, + widget: "anastasis_gtk_ia_ahv", + uuid: "1da87570-ba16-4f62-8a7e-cbda92f51591", + "validation-regex": + "^(756).[0-9]{4}.[0-9]{4}.[0-9]{2}|(756)[0-9]{10}$", + "validation-logic": "CH_AHV_check", + }, + ], + }, + cz: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "string", + name: "birthplace", + label: "Birthplace", + widget: "anastasis_gtk_ia_birthplace", + uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f", + }, + { + type: "string", + name: "birth_number", + label: "Birth Number", + label_i18n: { + en: "Birth Number", + cz: "rodné číslo", + }, + widget: "anastasis_gtk_ia_birthnumber_cz", + uuid: "03e3a05b-1192-44f1-ac36-7425512eee1a", + "validation-regex": + "^[0-9]{2}(((0|2|5|7)[0-9])|10|11|31|32|51|52|81|82)/[0-9]{3}[0-9]?$", + "validation-logic": "CZ_BN_check", + }, + ], + }, + de: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "date", + name: "birthdate", + label: "Birthdate", + widget: "anastasis_gtk_ia_birthdate", + uuid: "83d655c7-bdb6-484d-904e-80c1058c8854", + }, + { + type: "string", + name: "birthplace", + label: "Birthplace", + widget: "anastasis_gtk_ia_birthplace", + uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f", + }, + { + type: "string", + name: "tax_number", + label: "Taxpayer identification number", + label_i18n: { + de_DE: "Steuerliche Identifikationsnummer", + en: "German taxpayer identification number", + }, + widget: "anastasis_gtk_ia_tax_de", + uuid: "dae48f85-e3ff-47a4-a4a3-ed981ed8c3c6", + "validation-regex": "^[0-9]{11}$", + "validation-logic": "DE_TIN_check", + }, + { + type: "string", + name: "social_security_number", + label: "Social security number", + label_i18n: { + de_DE: "Deutsche Sozialversicherungsnummer", + en: "German Social security number", + }, + widget: "anastasis_gtk_ia_ssn_de", + uuid: "d5e2aa79-1c88-4cf4-a4d2-252508b38e05", + "validation-regex": "^[0-9]{8}[[:upper:]][0-9]{3}$", + "validation-logic": "DE_SVN_check", + optional: true, + }, + ], + }, + dk: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "string", + name: "birthplace", + label: "Birthplace", + widget: "anastasis_gtk_ia_birthplace", + uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f", + }, + { + type: "string", + name: "cpr_number", + label: "CPR-nummer", + label_i18n: { + en: "CPR Number", + dk: "CPR-nummer", + }, + widget: "anastasis_gtk_ia_cpr_dk", + uuid: "38f13a4d-4302-4ada-ada1-c3ff4a8ff689", + "validation-regex": + "^(0[1-9]|[1-2][0-9]|30|31)((0[1-9]|10|11|12))[0-9]{2}-[0-9A-Z]{4}$", + }, + ], + }, + es: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "date", + name: "birthdate", + label: "Birthdate", + widget: "anastasis_gtk_ia_birthdate", + uuid: "83d655c7-bdb6-484d-904e-80c1058c8854", + }, + { + type: "string", + name: "birthplace", + label: "Birthplace", + widget: "anastasis_gtk_ia_birthplace", + uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f", + }, + { + type: "string", + name: "tax_number", + label: "Tax number", + label_i18n: { + es_ES: "Número de Identificación Fiscal (DNI, NIE)", + }, + widget: "anastasis_gtk_ia_es_dni", + uuid: "ac8bd865-6be8-445c-b650-6a18eef16a49", + "validation-regex": "^[0-9MXYZ][0-9]{7}[TRWAGMYFPDXBNJZSQVHLCKE]$", + "validation-logic": "ES_DNI_check", + }, + { + type: "string", + name: "ssn_number", + label: "Social security number", + label_i18n: { + es_ES: "Número de Seguridad Social", + }, + widget: "anastasis_gtk_ia_es_ssn", + uuid: "22396a19-f3bb-497e-b63a-961fd639140e", + "validation-regex": "^[0-9]{11}$", + }, + ], + }, + in: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "date", + name: "birthdate", + label: "Birthdate", + widget: "anastasis_gtk_ia_birthdate", + uuid: "83d655c7-bdb6-484d-904e-80c1058c8854", + }, + { + type: "string", + name: "birthplace", + label: "Birthplace", + widget: "anastasis_gtk_ia_birthplace", + uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f", + }, + { + type: "string", + name: "aadhar_number", + label: "Aadhar number", + label_i18n: { + en: "Aadhar number", + }, + widget: "anastasis_gtk_ia_aadhar_in", + uuid: "55afe97a-98bc-48d1-bb37-a9658be3fdc9", + "validation-regex": "^[2-9]{1}[0-9]{3}\\s[0-9]{4}\\s[0-9]{4}$", + "validation-logic": "IN_AADHAR_check", + }, + ], + }, + it: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "string", + name: "birthplace", + label: "Birthplace", + widget: "anastasis_gtk_ia_birthplace", + uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f", + }, + { + type: "string", + name: "fiscal_code", + label: "Codice fiscale", + label_i18n: { + it: "Codice fiscale", + en: "Fiscal code", + }, + widget: "anastasis_gtk_ia_cf_it", + uuid: "88f53c51-52ad-4d63-a163-ec042589f925", + "validation-regex": + "^[[:upper:]]{6}[0-9]{2}[A-EHLMPRT](([0-24-6][0-9])|(30|31|70|71))[A-MZ][0-9]{3}[A-Z]$", + "validation-logic": "IT_CF_check", + }, + ], + }, + jp: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "date", + name: "birthdate", + label: "Birthdate", + widget: "anastasis_gtk_ia_birthdate", + uuid: "83d655c7-bdb6-484d-904e-80c1058c8854", + }, + { + type: "string", + name: "birthplace", + label: "Birthplace", + widget: "anastasis_gtk_ia_birthplace", + uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f", + }, + { + type: "string", + name: "my_number", + label: "My number", + label_i18n: { + en: "My number", + jp: "マイナンバー", + }, + widget: "anastasis_gtk_ia_my_jp", + uuid: "90848f42-a83e-4226-8186-329696c14152", + "validation-regex": "^[0-9]{12}$", + }, + ], + }, + sk: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "string", + name: "birthplace", + label: "Birthplace", + widget: "anastasis_gtk_ia_birthplace", + uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f", + }, + { + type: "string", + name: "birth_number", + label: "Birth Number", + label_i18n: { + en: "Birth Number", + sk: "rodné číslo", + }, + widget: "anastasis_gtk_ia_birthnumber_sk", + uuid: "1cd372fe-2cea-4928-9f29-66f2bdd8555c", + "validation-regex": + "^[0-9]{2}(((0|2|5|7)[0-9])|10|11|31|32|51|52|81|82)/[0-9]{3}[0-9]?$", + "validation-logic": "CZ_BN_check", + }, + ], + }, + us: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "date", + name: "birthdate", + label: "Birthdate", + widget: "anastasis_gtk_ia_birthdate", + uuid: "83d655c7-bdb6-484d-904e-80c1058c8854", + }, + { + type: "string", + name: "birthplace", + label: "Birthplace", + widget: "anastasis_gtk_ia_birthplace", + uuid: "4c822e8e-89c6-11eb-95c4-8b077ad8489f", + }, + { + type: "string", + name: "social_security_number", + label: "Social security number", + label_i18n: { + en: "US Social security number", + }, + widget: "anastasis_gtk_ia_ssn_us", + uuid: "310a138c-b0b7-4985-b8b8-d00e765e9f9b", + "validation-regex": "^d{3}-d{2}-d{4}$", + }, + ], + }, + xx: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "date", + name: "birthdate", + label: "Birthdate", + widget: "anastasis_gtk_ia_birthdate", + uuid: "83d655c7-bdb6-484d-904e-80c1058c8854", + }, + { + type: "string", + name: "sq_number", + label: "Square number", + widget: "anastasis_gtk_xx_square", + uuid: "ed790bca-89bf-11eb-96f2-233996cf644e", + "validation-regex": "^[0-9]+$", + "validation-logic": "XX_SQUARE_check", + }, + ], + }, + xy: { + license: "GPLv3+", + "SPDX-License-Identifier": "GPL3.0-or-later", + required_attributes: [ + { + type: "string", + name: "full_name", + label: "Full name", + widget: "anastasis_gtk_ia_full_name", + uuid: "9e8f463f-575f-42cb-85f3-759559997331", + }, + { + type: "date", + name: "birthdate", + label: "Birthdate", + widget: "anastasis_gtk_ia_birthdate", + uuid: "83d655c7-bdb6-484d-904e-80c1058c8854", + }, + { + type: "string", + name: "prime_number", + label: "Prime number", + widget: "anastasis_gtk_xx_prime", + uuid: "39190a95-cacb-4412-8bae-1f7da3f980b4", + "validation-regex": "^[0-9]+$", + "validation-logic": "XY_PRIME_check", + }, + ], + }, + }, +}; diff --git a/packages/anastasis-core/src/crypto.test.ts b/packages/anastasis-core/src/crypto.test.ts new file mode 100644 index 000000000..346806fac --- /dev/null +++ b/packages/anastasis-core/src/crypto.test.ts @@ -0,0 +1,16 @@ +import test from "ava"; + +// Vector generated with taler-anastasis-tvg +const userIdVector = { + input_id_data: { + name: "Fleabag", + ssn: "AB123", + }, + input_server_salt: "FZ48EFS7WS3R2ZR4V53A3GFFY4", + output_id: + "YS45R6CGJV84K1NN7T14ZBCPVTZ6H15XJSM1FV0R748MHPV82SM0126EBZKBAAGCR34Q9AFKPEW1HRT2Q9GQ5JRA3642AB571DKZS18", +}; + +test("user ID derivation", async (t) => { + t.fail(); +}); diff --git a/packages/anastasis-core/src/crypto.ts b/packages/anastasis-core/src/crypto.ts new file mode 100644 index 000000000..54f27b646 --- /dev/null +++ b/packages/anastasis-core/src/crypto.ts @@ -0,0 +1,21 @@ +import { argon2id } from "hash-wasm"; + +async function userIdentifierDerive( + idData: any, + serverSalt: string, +): Promise<string> { + throw Error("not implemented"); +} + +// interface Keypair { +// pub: string; +// priv: string; +// } + +// async function accountKeypairDerive(): Promise<Keypair> {} + +// async function secureAnswerHash( +// answer: string, +// truthUuid: string, +// questionSalt: string, +// ): Promise<string> {} diff --git a/packages/anastasis-core/src/index.ts b/packages/anastasis-core/src/index.ts new file mode 100644 index 000000000..7a14440a6 --- /dev/null +++ b/packages/anastasis-core/src/index.ts @@ -0,0 +1,14 @@ +import { md5, sha1, sha512, sha3 } from 'hash-wasm'; + +async function run() { + console.log('MD5:', await md5('demo')); + + const int8Buffer = new Uint8Array([0, 1, 2, 3]); + console.log('SHA1:', await sha1(int8Buffer)); + console.log('SHA512:', await sha512(int8Buffer)); + + const int32Buffer = new Uint32Array([1056, 641]); + console.log('SHA3-256:', await sha3(int32Buffer, 256)); +} + +run();
\ No newline at end of file diff --git a/packages/anastasis-core/tsconfig.json b/packages/anastasis-core/tsconfig.json new file mode 100644 index 000000000..34027c4ac --- /dev/null +++ b/packages/anastasis-core/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compileOnSave": true, + "compilerOptions": { + "composite": true, + "target": "ES2018", + "module": "ESNext", + "moduleResolution": "node", + "sourceMap": true, + "lib": ["es6"], + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "strict": true, + "strictPropertyInitialization": false, + "outDir": "lib", + "noImplicitAny": true, + "noImplicitThis": true, + "incremental": true, + "esModuleInterop": true, + "importHelpers": true, + "rootDir": "src", + "baseUrl": "./src", + "typeRoots": ["./node_modules/@types"] + }, + "include": ["src/**/*"], + "references": [ + { + "path": "../taler-util/" + } + ] +} diff --git a/packages/idb-bridge/src/bridge-idb.ts b/packages/idb-bridge/src/bridge-idb.ts index ecabfbc7a..f015d2a9f 100644 --- a/packages/idb-bridge/src/bridge-idb.ts +++ b/packages/idb-bridge/src/bridge-idb.ts @@ -805,7 +805,7 @@ export class BridgeIDBFactory { oldVersion, }); request.dispatchEvent(event2); - } catch (err) { + } catch (err: any) { request.error = new Error(); request.error.name = err.name; request.readyState = "done"; @@ -846,7 +846,7 @@ export class BridgeIDBFactory { if (BridgeIDBFactory.enableTracing) { console.log("TRACE: connected!"); } - } catch (err) { + } catch (err: any) { if (BridgeIDBFactory.enableTracing) { console.log( "TRACE: caught exception while trying to connect with backend", @@ -2704,7 +2704,7 @@ export class BridgeIDBTransaction this._active = false; throw err; } - } catch (err) { + } catch (err: any) { if (BridgeIDBFactory.enableTracing) { console.log("TRACING: error during operation: ", err); } diff --git a/packages/idb-bridge/src/idb-wpt-ported/wptsupport.ts b/packages/idb-bridge/src/idb-wpt-ported/wptsupport.ts index d6c0b011a..38b44bbec 100644 --- a/packages/idb-bridge/src/idb-wpt-ported/wptsupport.ts +++ b/packages/idb-bridge/src/idb-wpt-ported/wptsupport.ts @@ -542,7 +542,7 @@ export function is_transaction_active( e.stopPropagation(); }; return true; - } catch (ex) { + } catch (ex: any) { console.log(ex.stack); t.deepEqual( ex.name, diff --git a/packages/taler-util/package.json b/packages/taler-util/package.json index 4cbd829b9..33942abf6 100644 --- a/packages/taler-util/package.json +++ b/packages/taler-util/package.json @@ -3,19 +3,17 @@ "version": "0.8.3", "description": "Generic helper functionality for GNU Taler", "exports": { - ".": "./lib/index.js" - }, - "module": "./lib/index.js", - "main": "./lib/index.js", - "browser": { - "./lib/index.js": "./lib/index.browser.js" + ".": "./lib/index.node.js" }, + "module": "./lib/index.node.js", + "main": "./lib/index.node.js", + "browser": "./lib/index.browser.js", "type": "module", - "types": "./lib/index.d.ts", + "types": "./lib/index.node.d.ts", "typesVersions": { "*": { - "lib/index.d.ts": [ - "lib/index.d.ts" + "lib/index.node.d.ts": [ + "lib/index.node.d.ts" ], "src/*": [], "*": [] @@ -40,6 +38,7 @@ "typescript": "^4.2.3" }, "dependencies": { + "big-integer": "^1.6.48", "jed": "^1.1.1", "tslib": "^2.1.0" }, diff --git a/packages/taler-util/src/index.browser.ts b/packages/taler-util/src/index.browser.ts index 1c379bd93..3b8e194b3 100644 --- a/packages/taler-util/src/index.browser.ts +++ b/packages/taler-util/src/index.browser.ts @@ -1,22 +1,21 @@ -import { TalerErrorCode } from "./taler-error-codes.js"; +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. -export { TalerErrorCode }; + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. -export * from "./amounts.js"; -export * from "./backupTypes.js"; -export * from "./codec.js"; -export * from "./helpers.js"; -export * from "./libtool-version.js"; -export * from "./notifications.js"; -export * from "./payto.js"; -export * from "./ReserveStatus.js"; -export * from "./ReserveTransaction.js"; -export * from "./talerTypes.js"; -export * from "./taleruri.js"; -export * from "./time.js"; -export * from "./transactionsTypes.js"; -export * from "./walletTypes.js"; -export * from "./i18n.js"; -export * from "./logging.js"; -export * from "./url.js"; -export { fnutil } from "./fnutils.js";
\ No newline at end of file + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +// Entry point for the browser. + +import { loadBrowserPrng } from "./prng-browser.js"; +loadBrowserPrng(); +export * from "./index.js"; diff --git a/packages/taler-util/src/index.node.ts b/packages/taler-util/src/index.node.ts new file mode 100644 index 000000000..018b4767f --- /dev/null +++ b/packages/taler-util/src/index.node.ts @@ -0,0 +1,23 @@ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +// Entry point for nodejs. + +import { initNodePrng } from "./prng-node.js"; +initNodePrng(); +export * from "./index.js"; +export * from "./talerconfig.js"; +export * from "./globbing/minimatch.js"; diff --git a/packages/taler-util/src/index.ts b/packages/taler-util/src/index.ts index 06951231e..ccb917f6e 100644 --- a/packages/taler-util/src/index.ts +++ b/packages/taler-util/src/index.ts @@ -1,3 +1,25 @@ -export * from "./index.browser.js"; -export * from "./talerconfig.js"; -export * from "./globbing/minimatch.js"; +import { TalerErrorCode } from "./taler-error-codes.js"; + +export { TalerErrorCode }; + +export * from "./amounts.js"; +export * from "./backupTypes.js"; +export * from "./codec.js"; +export * from "./helpers.js"; +export * from "./libtool-version.js"; +export * from "./notifications.js"; +export * from "./payto.js"; +export * from "./ReserveStatus.js"; +export * from "./ReserveTransaction.js"; +export * from "./talerTypes.js"; +export * from "./taleruri.js"; +export * from "./time.js"; +export * from "./transactionsTypes.js"; +export * from "./walletTypes.js"; +export * from "./i18n.js"; +export * from "./logging.js"; +export * from "./url.js"; +export { fnutil } from "./fnutils.js"; +export * from "./kdf.js"; +export * from "./talerCrypto.js"; +export { randomBytes, secretbox, secretbox_open } from "./nacl-fast.js"; diff --git a/packages/taler-util/src/kdf.d.ts b/packages/taler-util/src/kdf.d.ts new file mode 100644 index 000000000..80a6da41e --- /dev/null +++ b/packages/taler-util/src/kdf.d.ts @@ -0,0 +1,5 @@ +export declare function sha512(data: Uint8Array): Uint8Array; +export declare function hmac(digest: (d: Uint8Array) => Uint8Array, blockSize: number, key: Uint8Array, message: Uint8Array): Uint8Array; +export declare function hmacSha512(key: Uint8Array, message: Uint8Array): Uint8Array; +export declare function hmacSha256(key: Uint8Array, message: Uint8Array): Uint8Array; +export declare function kdf(outputLength: number, ikm: Uint8Array, salt: Uint8Array, info: Uint8Array): Uint8Array; diff --git a/packages/taler-util/src/kdf.js b/packages/taler-util/src/kdf.js new file mode 100644 index 000000000..32f17beac --- /dev/null +++ b/packages/taler-util/src/kdf.js @@ -0,0 +1,76 @@ +/* + This file is part of GNU Taler + (C) 2019 GNUnet e.V. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +import * as nacl from "./nacl-fast.js"; +import { sha256 } from "./sha256.js"; +export function sha512(data) { + return nacl.hash(data); +} +export function hmac(digest, blockSize, key, message) { + if (key.byteLength > blockSize) { + key = digest(key); + } + if (key.byteLength < blockSize) { + const k = key; + key = new Uint8Array(blockSize); + key.set(k, 0); + } + const okp = new Uint8Array(blockSize); + const ikp = new Uint8Array(blockSize); + for (let i = 0; i < blockSize; i++) { + ikp[i] = key[i] ^ 0x36; + okp[i] = key[i] ^ 0x5c; + } + const b1 = new Uint8Array(blockSize + message.byteLength); + b1.set(ikp, 0); + b1.set(message, blockSize); + const h0 = digest(b1); + const b2 = new Uint8Array(blockSize + h0.length); + b2.set(okp, 0); + b2.set(h0, blockSize); + return digest(b2); +} +export function hmacSha512(key, message) { + return hmac(sha512, 128, key, message); +} +export function hmacSha256(key, message) { + return hmac(sha256, 64, key, message); +} +export function kdf(outputLength, ikm, salt, info) { + // extract + const prk = hmacSha512(salt, ikm); + // expand + const N = Math.ceil(outputLength / 32); + const output = new Uint8Array(N * 32); + for (let i = 0; i < N; i++) { + let buf; + if (i == 0) { + buf = new Uint8Array(info.byteLength + 1); + buf.set(info, 0); + } + else { + buf = new Uint8Array(info.byteLength + 1 + 32); + for (let j = 0; j < 32; j++) { + buf[j] = output[(i - 1) * 32 + j]; + } + buf.set(info, 32); + } + buf[buf.length - 1] = i + 1; + const chunk = hmacSha256(prk, buf); + output.set(chunk, i * 32); + } + return output.slice(0, outputLength); +} +//# sourceMappingURL=kdf.js.map
\ No newline at end of file diff --git a/packages/taler-util/src/kdf.js.map b/packages/taler-util/src/kdf.js.map new file mode 100644 index 000000000..be357dd96 --- /dev/null +++ b/packages/taler-util/src/kdf.js.map @@ -0,0 +1 @@ +{"version":3,"file":"kdf.js","sourceRoot":"","sources":["kdf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,UAAU,MAAM,CAAC,IAAgB;IACrC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,IAAI,CAClB,MAAqC,EACrC,SAAiB,EACjB,GAAe,EACf,OAAmB;IAEnB,IAAI,GAAG,CAAC,UAAU,GAAG,SAAS,EAAE;QAC9B,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;KACnB;IACD,IAAI,GAAG,CAAC,UAAU,GAAG,SAAS,EAAE;QAC9B,MAAM,CAAC,GAAG,GAAG,CAAC;QACd,GAAG,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;QAChC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;KACf;IACD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;IACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE;QAClC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QACvB,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;KACxB;IACD,MAAM,EAAE,GAAG,IAAI,UAAU,CAAC,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1D,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACf,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IACtB,MAAM,EAAE,GAAG,IAAI,UAAU,CAAC,SAAS,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;IACjD,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACf,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IACtB,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAe,EAAE,OAAmB;IAC7D,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAe,EAAE,OAAmB;IAC7D,OAAO,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,GAAG,CACjB,YAAoB,EACpB,GAAe,EACf,IAAgB,EAChB,IAAgB;IAEhB,UAAU;IACV,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAElC,SAAS;IACT,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;QAC1B,IAAI,GAAG,CAAC;QACR,IAAI,CAAC,IAAI,CAAC,EAAE;YACV,GAAG,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;YAC1C,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;SAClB;aAAM;YACL,GAAG,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;YAC/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;gBAC3B,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;aACnC;YACD,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;SACnB;QACD,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;KAC3B;IAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;AACvC,CAAC"}
\ No newline at end of file diff --git a/packages/taler-wallet-core/src/crypto/primitives/kdf.ts b/packages/taler-util/src/kdf.ts index af4d05035..af4d05035 100644 --- a/packages/taler-wallet-core/src/crypto/primitives/kdf.ts +++ b/packages/taler-util/src/kdf.ts diff --git a/packages/taler-wallet-core/src/crypto/primitives/nacl-fast.ts b/packages/taler-util/src/nacl-fast.ts index 909c6a60a..909c6a60a 100644 --- a/packages/taler-wallet-core/src/crypto/primitives/nacl-fast.ts +++ b/packages/taler-util/src/nacl-fast.ts diff --git a/packages/taler-util/src/prng-browser.ts b/packages/taler-util/src/prng-browser.ts new file mode 100644 index 000000000..79d399e03 --- /dev/null +++ b/packages/taler-util/src/prng-browser.ts @@ -0,0 +1,19 @@ +import { setPRNG } from "./nacl-fast.js"; + +export function loadBrowserPrng() { + // Initialize PRNG if environment provides CSPRNG. + // If not, methods calling randombytes will throw. + // @ts-ignore-error + const cr = typeof self !== "undefined" ? self.crypto || self.msCrypto : null; + + const QUOTA = 65536; + setPRNG(function (x: Uint8Array, n: number) { + let i; + const v = new Uint8Array(n); + for (i = 0; i < n; i += QUOTA) { + cr.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); + } + for (i = 0; i < n; i++) x[i] = v[i]; + for (i = 0; i < v.length; i++) v[i] = 0; + }); +} diff --git a/packages/taler-util/src/prng-node.ts b/packages/taler-util/src/prng-node.ts new file mode 100644 index 000000000..226923b8b --- /dev/null +++ b/packages/taler-util/src/prng-node.ts @@ -0,0 +1,30 @@ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +import { setPRNG } from "./nacl-fast.js"; +import cr from "crypto"; + +export function initNodePrng() { + // Initialize PRNG if environment provides CSPRNG. + // If not, methods calling randombytes will throw. + if (cr && cr.randomBytes) { + setPRNG(function (x: Uint8Array, n: number) { + const v = cr.randomBytes(n); + for (let i = 0; i < n; i++) x[i] = v[i]; + for (let i = 0; i < v.length; i++) v[i] = 0; + }); + } +} diff --git a/packages/taler-wallet-core/src/crypto/primitives/sha256.ts b/packages/taler-util/src/sha256.ts index 97723dbfc..97723dbfc 100644 --- a/packages/taler-wallet-core/src/crypto/primitives/sha256.ts +++ b/packages/taler-util/src/sha256.ts diff --git a/packages/taler-wallet-core/src/crypto/talerCrypto-test.ts b/packages/taler-util/src/talerCrypto.test.ts index 3718290d7..ffd1d25cd 100644 --- a/packages/taler-wallet-core/src/crypto/talerCrypto-test.ts +++ b/packages/taler-util/src/talerCrypto.test.ts @@ -25,14 +25,11 @@ import { eddsaGetPublic, keyExchangeEddsaEcdhe, keyExchangeEcdheEddsa, - rsaBlind, - rsaUnblind, stringToBytes, bytesToString, - rsaVerify, } from "./talerCrypto.js"; -import { sha512, kdf } from "./primitives/kdf.js"; -import * as nacl from "./primitives/nacl-fast.js"; +import { sha512, kdf } from "./kdf.js"; +import * as nacl from "./nacl-fast.js"; test("encoding", (t) => { const s = "Hello, World"; diff --git a/packages/taler-wallet-core/src/crypto/talerCrypto.ts b/packages/taler-util/src/talerCrypto.ts index 71a804f98..aab7571a3 100644 --- a/packages/taler-wallet-core/src/crypto/talerCrypto.ts +++ b/packages/taler-util/src/talerCrypto.ts @@ -21,9 +21,12 @@ /** * Imports. */ -import * as nacl from "./primitives/nacl-fast.js"; +import * as nacl from "./nacl-fast.js"; +import { kdf } from "./kdf.js"; import bigint from "big-integer"; -import { kdf } from "./primitives/kdf.js"; +import { initNodePrng } from "./prng-node.js"; + +initNodePrng(); export function getRandomBytes(n: number): Uint8Array { return nacl.randomBytes(n); diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts index 2d50e226b..0985ba884 100644 --- a/packages/taler-wallet-cli/src/index.ts +++ b/packages/taler-wallet-cli/src/index.ts @@ -40,14 +40,14 @@ import { codecForString, Logger, Configuration, + decodeCrock, + rsaBlind, } from "@gnu-taler/taler-util"; import { NodeHttpLib, getDefaultNodeWallet, OperationFailedAndReportedError, OperationFailedError, - decodeCrock, - rsaBlind, NodeThreadCryptoWorkerFactory, CryptoApi, walletCoreDebugFlags, @@ -810,7 +810,7 @@ advancedCli coinPubList = coinPubListCodec.decode( JSON.parse(args.suspendCoins.coinPubSpec), ); - } catch (e) { + } catch (e: any) { console.log("could not parse coin list:", e.message); process.exit(1); } @@ -835,7 +835,7 @@ advancedCli coinPubList = coinPubListCodec.decode( JSON.parse(args.unsuspendCoins.coinPubSpec), ); - } catch (e) { + } catch (e: any) { console.log("could not parse coin list:", e.message); process.exit(1); } diff --git a/packages/taler-wallet-cli/src/integrationtests/harness.ts b/packages/taler-wallet-cli/src/integrationtests/harness.ts index d47dfe098..a3a6e9e1c 100644 --- a/packages/taler-wallet-cli/src/integrationtests/harness.ts +++ b/packages/taler-wallet-cli/src/integrationtests/harness.ts @@ -44,11 +44,6 @@ import { MerchantInstancesResponse, } from "./merchantApiTypes"; import { - createEddsaKeyPair, - eddsaGetPublic, - EddsaKeyPair, - encodeCrock, - getRandomBytes, openPromise, OperationFailedError, WalletCoreApiClient, @@ -64,6 +59,11 @@ import { Duration, parsePaytoUri, CoreApiResponse, + createEddsaKeyPair, + eddsaGetPublic, + EddsaKeyPair, + encodeCrock, + getRandomBytes, } from "@gnu-taler/taler-util"; import { CoinConfig } from "./denomStructures.js"; @@ -441,7 +441,7 @@ export async function pingProc( const resp = await axios.get(url); console.log(`service ${serviceName} available`); return; - } catch (e) { + } catch (e: any) { console.log(`service ${serviceName} not ready:`, e.toString()); await delayMs(1000); } @@ -1074,8 +1074,12 @@ export class ExchangeService implements ExchangeServiceInterface { async purgeSecmodKeys(): Promise<void> { const cfg = Configuration.load(this.configFilename); - const rsaKeydir = cfg.getPath("taler-exchange-secmod-rsa", "KEY_DIR").required(); - const eddsaKeydir = cfg.getPath("taler-exchange-secmod-eddsa", "KEY_DIR").required(); + const rsaKeydir = cfg + .getPath("taler-exchange-secmod-rsa", "KEY_DIR") + .required(); + const eddsaKeydir = cfg + .getPath("taler-exchange-secmod-eddsa", "KEY_DIR") + .required(); // Be *VERY* careful when changing this, or you will accidentally delete user data. await sh(this.globalState, "rm-secmod-keys", `rm -rf ${rsaKeydir}/COIN_*`); await sh(this.globalState, "rm-secmod-keys", `rm ${eddsaKeydir}/*`); @@ -1119,11 +1123,7 @@ export class ExchangeService implements ExchangeServiceInterface { this.exchangeHttpProc = this.globalState.spawnService( "taler-exchange-httpd", - [ - "-c", - this.configFilename, - ...this.timetravelArgArr, - ], + ["-c", this.configFilename, ...this.timetravelArgArr], `exchange-httpd-${this.name}`, ); diff --git a/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts b/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts index 6a09de77d..d6d0e2dce 100644 --- a/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts +++ b/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts @@ -28,7 +28,7 @@ import { BankAccessApi, CreditDebitIndicator, } from "./harness"; -import { createEddsaKeyPair, encodeCrock } from "@gnu-taler/taler-wallet-core"; +import { createEddsaKeyPair, encodeCrock } from "@gnu-taler/taler-util"; import { defaultCoinConfig } from "./denomStructures"; /** diff --git a/packages/taler-wallet-cli/src/integrationtests/test-merchant-spec-public-orders.ts b/packages/taler-wallet-cli/src/integrationtests/test-merchant-spec-public-orders.ts index ab7bf1acd..867af99d5 100644 --- a/packages/taler-wallet-cli/src/integrationtests/test-merchant-spec-public-orders.ts +++ b/packages/taler-wallet-cli/src/integrationtests/test-merchant-spec-public-orders.ts @@ -21,13 +21,10 @@ import { ConfirmPayResultType, PreparePayResultType, URL, -} from "@gnu-taler/taler-util"; -import { encodeCrock, getRandomBytes, - NodeHttpLib, - WalletApiOperation, -} from "@gnu-taler/taler-wallet-core"; +} from "@gnu-taler/taler-util"; +import { NodeHttpLib, WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { BankService, ExchangeService, @@ -566,11 +563,9 @@ async function testWithoutClaimToken( * specification of the endpoint. */ export async function runMerchantSpecPublicOrdersTest(t: GlobalTestState) { - const { - bank, - exchange, - merchant, - } = await createSimpleTestkudosEnvironment(t); + const { bank, exchange, merchant } = await createSimpleTestkudosEnvironment( + t, + ); // Base URL for the default instance. const merchantBaseUrl = merchant.makeInstanceBaseUrl(); diff --git a/packages/taler-wallet-cli/src/lint.ts b/packages/taler-wallet-cli/src/lint.ts index 4b9633871..0fed68c34 100644 --- a/packages/taler-wallet-cli/src/lint.ts +++ b/packages/taler-wallet-cli/src/lint.ts @@ -35,9 +35,9 @@ import { codecForExchangeKeysJson, codecForKeysManagementResponse, Configuration, + decodeCrock, } from "@gnu-taler/taler-util"; import { - decodeCrock, NodeHttpLib, readSuccessResponseJsonOrThrow, } from "@gnu-taler/taler-wallet-core"; diff --git a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts index 7112964db..4ca0576b0 100644 --- a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts +++ b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts @@ -63,9 +63,9 @@ import { setupTipPlanchet, setupWithdrawPlanchet, eddsaGetPublic, -} from "../talerCrypto.js"; -import { randomBytes } from "../primitives/nacl-fast.js"; -import { kdf } from "../primitives/kdf.js"; +} from "@gnu-taler/taler-util"; +import { randomBytes } from "@gnu-taler/taler-util"; +import { kdf } from "@gnu-taler/taler-util"; import { Timestamp, timestampTruncateToSecond } from "@gnu-taler/taler-util"; import { Logger } from "@gnu-taler/taler-util"; diff --git a/packages/taler-wallet-core/src/headless/NodeHttpLib.ts b/packages/taler-wallet-core/src/headless/NodeHttpLib.ts index 9655d363f..5a90994b1 100644 --- a/packages/taler-wallet-core/src/headless/NodeHttpLib.ts +++ b/packages/taler-wallet-core/src/headless/NodeHttpLib.ts @@ -28,8 +28,7 @@ import { import { RequestThrottler } from "../util/RequestThrottler.js"; import Axios, { AxiosResponse } from "axios"; import { OperationFailedError, makeErrorDetails } from "../errors.js"; -import { Logger } from "@gnu-taler/taler-util"; -import { bytesToString } from "../crypto/talerCrypto.js"; +import { Logger, bytesToString } from "@gnu-taler/taler-util"; import { TalerErrorCode, URL } from "@gnu-taler/taler-util"; const logger = new Logger("NodeHttpLib.ts"); @@ -83,7 +82,7 @@ export class NodeHttpLib implements HttpRequestLibrary { timeout, maxRedirects: 0, }); - } catch (e) { + } catch (e: any) { throw OperationFailedError.fromCode( TalerErrorCode.WALLET_NETWORK_ERROR, `${e.message}`, diff --git a/packages/taler-wallet-core/src/headless/helpers.ts b/packages/taler-wallet-core/src/headless/helpers.ts index 1867fab67..f2285e149 100644 --- a/packages/taler-wallet-core/src/headless/helpers.ts +++ b/packages/taler-wallet-core/src/headless/helpers.ts @@ -92,7 +92,7 @@ export async function getDefaultNodeWallet( }); const dbContent = JSON.parse(dbContentStr); myBackend.importDump(dbContent); - } catch (e) { + } catch (e: any) { const code: string = e.code; if (code === "ENOENT") { logger.trace("wallet file doesn't exist yet"); diff --git a/packages/taler-wallet-core/src/index.browser.ts b/packages/taler-wallet-core/src/index.browser.ts index d0b82d3e0..88ea52479 100644 --- a/packages/taler-wallet-core/src/index.browser.ts +++ b/packages/taler-wallet-core/src/index.browser.ts @@ -15,58 +15,3 @@ */ export * from "./index.js"; - -import { setPRNG } from './crypto/primitives/nacl-fast.js'; -// export default API; - -function cleanup(arr: Uint8Array): void { - for (let i = 0; i < arr.length; i++) arr[i] = 0; -} - -// Initialize PRNG if environment provides CSPRNG. -// If not, methods calling randombytes will throw. -// @ts-ignore-error -const cr = typeof self !== "undefined" ? self.crypto || self.msCrypto : null; - -const QUOTA = 65536; -setPRNG(function (x: Uint8Array, n: number) { - let i; - const v = new Uint8Array(n); - for (i = 0; i < n; i += QUOTA) { - cr.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); - } - for (i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); -}); -// function initPRNG() { -// // Initialize PRNG if environment provides CSPRNG. -// // If not, methods calling randombytes will throw. -// // @ts-ignore-error -// const cr = typeof self !== "undefined" ? self.crypto || self.msCrypto : null; -// if (cr && cr.getRandomValues) { -// // Browsers. -// const QUOTA = 65536; -// setPRNG(function (x: Uint8Array, n: number) { -// let i; -// const v = new Uint8Array(n); -// for (i = 0; i < n; i += QUOTA) { -// cr.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); -// } -// for (i = 0; i < n; i++) x[i] = v[i]; -// cleanup(v); -// }); -// } else if (typeof require !== "undefined") { -// // Node.js. -// // eslint-disable-next-line @typescript-eslint/no-var-requires -// const cr = require("crypto"); -// if (cr && cr.randomBytes) { -// setPRNG(function (x: Uint8Array, n: number) { -// const v = cr.randomBytes(n); -// for (let i = 0; i < n; i++) x[i] = v[i]; -// cleanup(v); -// }); -// } -// } -// } - -// initPRNG();
\ No newline at end of file diff --git a/packages/taler-wallet-core/src/index.node.ts b/packages/taler-wallet-core/src/index.node.ts index a3be6b5f6..0860ccc26 100644 --- a/packages/taler-wallet-core/src/index.node.ts +++ b/packages/taler-wallet-core/src/index.node.ts @@ -22,22 +22,4 @@ export { getDefaultNodeWallet, DefaultNodeWalletArgs, } from "./headless/helpers.js"; - -import { setPRNG } from './crypto/primitives/nacl-fast.js'; -import cr from 'crypto'; - -function cleanup(arr: Uint8Array): void { - for (let i = 0; i < arr.length; i++) arr[i] = 0; -} - -// Initialize PRNG if environment provides CSPRNG. -// If not, methods calling randombytes will throw. -if (cr && cr.randomBytes) { - setPRNG(function (x: Uint8Array, n: number) { - const v = cr.randomBytes(n); - for (let i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); - }); -} - export * from "./crypto/workers/nodeThreadWorker.js"; diff --git a/packages/taler-wallet-core/src/index.ts b/packages/taler-wallet-core/src/index.ts index 035edc76b..0b360a248 100644 --- a/packages/taler-wallet-core/src/index.ts +++ b/packages/taler-wallet-core/src/index.ts @@ -36,7 +36,6 @@ export * from "./db-utils.js"; export { CryptoImplementation } from "./crypto/workers/cryptoImplementation.js"; export type { CryptoWorker } from "./crypto/workers/cryptoWorker.js"; export { CryptoWorkerFactory, CryptoApi } from "./crypto/workers/cryptoApi.js"; -export * from "./crypto/talerCrypto.js"; export * from "./pending-types.js"; diff --git a/packages/taler-wallet-core/src/operations/backup/export.ts b/packages/taler-wallet-core/src/operations/backup/export.ts index 0410ab3af..a66bc2e84 100644 --- a/packages/taler-wallet-core/src/operations/backup/export.ts +++ b/packages/taler-wallet-core/src/operations/backup/export.ts @@ -53,14 +53,12 @@ import { Logger, timestampToIsoString, WalletBackupContentV1, -} from "@gnu-taler/taler-util"; -import { InternalWalletState } from "../../common.js"; -import { hash } from "../../crypto/primitives/nacl-fast.js"; -import { + hash, encodeCrock, getRandomBytes, stringToBytes, -} from "../../crypto/talerCrypto.js"; +} from "@gnu-taler/taler-util"; +import { InternalWalletState } from "../../common.js"; import { AbortStatus, CoinSourceType, diff --git a/packages/taler-wallet-core/src/operations/backup/index.ts b/packages/taler-wallet-core/src/operations/backup/index.ts index b3b98fe1b..913ffcb2e 100644 --- a/packages/taler-wallet-core/src/operations/backup/index.ts +++ b/packages/taler-wallet-core/src/operations/backup/index.ts @@ -55,11 +55,11 @@ import { } from "@gnu-taler/taler-util"; import { gunzipSync, gzipSync } from "fflate"; import { InternalWalletState } from "../../common.js"; -import { kdf } from "../../crypto/primitives/kdf.js"; +import { kdf } from "@gnu-taler/taler-util"; import { secretbox, secretbox_open, -} from "../../crypto/primitives/nacl-fast.js"; +} from "@gnu-taler/taler-util"; import { bytesToString, decodeCrock, @@ -70,7 +70,7 @@ import { hash, rsaBlind, stringToBytes, -} from "../../crypto/talerCrypto.js"; +} from "@gnu-taler/taler-util"; import { CryptoApi } from "../../crypto/workers/cryptoApi.js"; import { BackupProviderRecord, diff --git a/packages/taler-wallet-core/src/operations/backup/state.ts b/packages/taler-wallet-core/src/operations/backup/state.ts index 3a7311d14..dc89c3d99 100644 --- a/packages/taler-wallet-core/src/operations/backup/state.ts +++ b/packages/taler-wallet-core/src/operations/backup/state.ts @@ -14,7 +14,7 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { encodeCrock, getRandomBytes } from "../../crypto/talerCrypto.js"; +import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util"; import { ConfigRecord, WalletBackupConfState, diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts index c6c80ce9f..740242050 100644 --- a/packages/taler-wallet-core/src/operations/deposits.ts +++ b/packages/taler-wallet-core/src/operations/deposits.ts @@ -39,12 +39,12 @@ import { URL, } from "@gnu-taler/taler-util"; import { InternalWalletState } from "../common.js"; -import { kdf } from "../crypto/primitives/kdf.js"; +import { kdf } from "@gnu-taler/taler-util"; import { encodeCrock, getRandomBytes, stringToBytes, -} from "../crypto/talerCrypto.js"; +} from "@gnu-taler/taler-util"; import { DepositGroupRecord } from "../db.js"; import { guardOperationException } from "../errors.js"; import { selectPayCoins } from "../util/coinSelection.js"; diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts index 9cd20c673..fc776c81f 100644 --- a/packages/taler-wallet-core/src/operations/exchanges.ts +++ b/packages/taler-wallet-core/src/operations/exchanges.ts @@ -40,7 +40,7 @@ import { TalerErrorDetails, Timestamp, } from "@gnu-taler/taler-util"; -import { decodeCrock, encodeCrock, hash } from "../crypto/talerCrypto.js"; +import { decodeCrock, encodeCrock, hash } from "@gnu-taler/taler-util"; import { CryptoApi } from "../crypto/workers/cryptoApi.js"; import { DenominationRecord, diff --git a/packages/taler-wallet-core/src/operations/pay.ts b/packages/taler-wallet-core/src/operations/pay.ts index 91268400a..079ffcd9a 100644 --- a/packages/taler-wallet-core/src/operations/pay.ts +++ b/packages/taler-wallet-core/src/operations/pay.ts @@ -54,7 +54,7 @@ import { URL, getDurationRemaining, } from "@gnu-taler/taler-util"; -import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto.js"; +import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util"; import { PayCoinSelection, CoinCandidateSelection, diff --git a/packages/taler-wallet-core/src/operations/recoup.ts b/packages/taler-wallet-core/src/operations/recoup.ts index 634469923..b1f46e4ba 100644 --- a/packages/taler-wallet-core/src/operations/recoup.ts +++ b/packages/taler-wallet-core/src/operations/recoup.ts @@ -32,7 +32,7 @@ import { RefreshReason, TalerErrorDetails, } from "@gnu-taler/taler-util"; -import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto.js"; +import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util"; import { CoinRecord, CoinSourceType, diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts index a7b64f5d3..85de813dc 100644 --- a/packages/taler-wallet-core/src/operations/refresh.ts +++ b/packages/taler-wallet-core/src/operations/refresh.ts @@ -14,7 +14,7 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto.js"; +import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util"; import { CoinRecord, CoinSourceType, diff --git a/packages/taler-wallet-core/src/operations/reserves.ts b/packages/taler-wallet-core/src/operations/reserves.ts index 4cbb9b9b5..4b5862bef 100644 --- a/packages/taler-wallet-core/src/operations/reserves.ts +++ b/packages/taler-wallet-core/src/operations/reserves.ts @@ -32,7 +32,7 @@ import { TalerErrorCode, addPaytoQueryParams, } from "@gnu-taler/taler-util"; -import { randomBytes } from "../crypto/primitives/nacl-fast.js"; +import { randomBytes } from "@gnu-taler/taler-util"; import { ReserveRecordStatus, ReserveBankInfo, @@ -63,7 +63,7 @@ import { processWithdrawGroup, getBankWithdrawalInfo, } from "./withdraw.js"; -import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto.js"; +import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util"; import { Logger, URL } from "@gnu-taler/taler-util"; import { readSuccessResponseJsonOrErrorCode, diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts index 29eeb8d59..a90e5270f 100644 --- a/packages/taler-wallet-core/src/operations/tip.ts +++ b/packages/taler-wallet-core/src/operations/tip.ts @@ -55,7 +55,7 @@ import { getHttpResponseErrorDetails, readSuccessResponseJsonOrThrow, } from "../util/http.js"; -import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto.js"; +import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util"; const logger = new Logger("operations/tip.ts"); diff --git a/packages/taler-wallet-core/src/util/contractTerms.ts b/packages/taler-wallet-core/src/util/contractTerms.ts index e52802441..652ef707d 100644 --- a/packages/taler-wallet-core/src/util/contractTerms.ts +++ b/packages/taler-wallet-core/src/util/contractTerms.ts @@ -15,14 +15,14 @@ */ import { canonicalJson } from "@gnu-taler/taler-util"; -import { kdf } from "../crypto/primitives/kdf.js"; +import { kdf } from "@gnu-taler/taler-util"; import { decodeCrock, encodeCrock, getRandomBytes, hash, stringToBytes, -} from "../crypto/talerCrypto.js"; +} from "@gnu-taler/taler-util"; export namespace ContractTermsUtil { export type PathPredicate = (path: string[]) => boolean; diff --git a/packages/taler-wallet-core/src/util/http.ts b/packages/taler-wallet-core/src/util/http.ts index e056ffcee..d01f2ee42 100644 --- a/packages/taler-wallet-core/src/util/http.ts +++ b/packages/taler-wallet-core/src/util/http.ts @@ -198,7 +198,7 @@ export async function readSuccessResponseJsonOrErrorCode<T>( let parsedResponse: T; try { parsedResponse = codec.decode(respJson); - } catch (e) { + } catch (e: any) { throw OperationFailedError.fromCode( TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE, "Response invalid", diff --git a/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx b/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx index 6b6e8f5c2..55686ee97 100644 --- a/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx +++ b/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx @@ -14,13 +14,24 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { Amounts, BackupBackupProviderTerms, canonicalizeBaseUrl, i18n } from "@gnu-taler/taler-util"; -import { verify } from "@gnu-taler/taler-wallet-core/src/crypto/primitives/nacl-fast"; +import { + Amounts, + BackupBackupProviderTerms, + canonicalizeBaseUrl, + i18n, +} from "@gnu-taler/taler-util"; import { VNode, h } from "preact"; import { useEffect, useState } from "preact/hooks"; import { Checkbox } from "../components/Checkbox"; import { ErrorMessage } from "../components/ErrorMessage"; -import { Button, ButtonPrimary, Input, LightText, PopupBox, SmallLightText } from "../components/styled/index"; +import { + Button, + ButtonPrimary, + Input, + LightText, + PopupBox, + SmallLightText, +} from "../components/styled/index"; import * as wxApi from "../wxApi"; interface Props { @@ -30,52 +41,65 @@ interface Props { function getJsonIfOk(r: Response) { if (r.ok) { - return r.json() + return r.json(); } else { if (r.status >= 400 && r.status < 500) { - throw new Error(`URL may not be right: (${r.status}) ${r.statusText}`) + throw new Error(`URL may not be right: (${r.status}) ${r.statusText}`); } else { - throw new Error(`Try another server: (${r.status}) ${r.statusText || 'internal server error'}`) + throw new Error( + `Try another server: (${r.status}) ${ + r.statusText || "internal server error" + }`, + ); } } } - export function ProviderAddPage({ onBack }: Props): VNode { - const [verifying, setVerifying] = useState<{ url: string, name: string, provider: BackupBackupProviderTerms } | undefined>(undefined) - - async function getProviderInfo(url: string): Promise<BackupBackupProviderTerms> { + const [verifying, setVerifying] = useState< + | { url: string; name: string; provider: BackupBackupProviderTerms } + | undefined + >(undefined); + + async function getProviderInfo( + url: string, + ): Promise<BackupBackupProviderTerms> { return fetch(`${url}config`) - .catch(e => { throw new Error(`Network error`) }) - .then(getJsonIfOk) + .catch((e) => { + throw new Error(`Network error`); + }) + .then(getJsonIfOk); } if (!verifying) { - return <SetUrlView - onCancel={onBack} - onVerify={(url) => getProviderInfo(url)} - onConfirm={(url, name) => getProviderInfo(url) - .then((provider) => { - setVerifying({ url, name, provider }); - }) - .catch(e => e.message) - } - /> + return ( + <SetUrlView + onCancel={onBack} + onVerify={(url) => getProviderInfo(url)} + onConfirm={(url, name) => + getProviderInfo(url) + .then((provider) => { + setVerifying({ url, name, provider }); + }) + .catch((e) => e.message) + } + /> + ); } - return <ConfirmProviderView - provider={verifying.provider} - url={verifying.url} - onCancel={() => { - setVerifying(undefined); - }} - onConfirm={() => { - wxApi.addBackupProvider(verifying.url, verifying.name).then(onBack) - }} - - /> + return ( + <ConfirmProviderView + provider={verifying.provider} + url={verifying.url} + onCancel={() => { + setVerifying(undefined); + }} + onConfirm={() => { + wxApi.addBackupProvider(verifying.url, verifying.name).then(onBack); + }} + /> + ); } - export interface SetUrlViewProps { initialValue?: string; onCancel: () => void; @@ -84,83 +108,137 @@ export interface SetUrlViewProps { withError?: string; } -export function SetUrlView({ initialValue, onCancel, onVerify, onConfirm, withError }: SetUrlViewProps) { - const [value, setValue] = useState<string>(initialValue || "") - const [urlError, setUrlError] = useState(false) - const [name, setName] = useState<string|undefined>(undefined) - const [error, setError] = useState<string | undefined>(withError) +export function SetUrlView({ + initialValue, + onCancel, + onVerify, + onConfirm, + withError, +}: SetUrlViewProps) { + const [value, setValue] = useState<string>(initialValue || ""); + const [urlError, setUrlError] = useState(false); + const [name, setName] = useState<string | undefined>(undefined); + const [error, setError] = useState<string | undefined>(withError); useEffect(() => { try { - const url = canonicalizeBaseUrl(value) - onVerify(url).then(r => { - setUrlError(false) - setName(new URL(url).hostname) - }).catch(() => { - setUrlError(true) - setName(undefined) - }) + const url = canonicalizeBaseUrl(value); + onVerify(url) + .then((r) => { + setUrlError(false); + setName(new URL(url).hostname); + }) + .catch(() => { + setUrlError(true); + setName(undefined); + }); } catch { - setUrlError(true) - setName(undefined) + setUrlError(true); + setName(undefined); } - }, [value]) - return <PopupBox> - <section> - <h1> Add backup provider</h1> - <ErrorMessage title={error && "Could not get provider information"} description={error} /> - <LightText> Backup providers may charge for their service</LightText> - <p> - <Input invalid={urlError}> - <label>URL</label> - <input type="text" placeholder="https://" value={value} onChange={(e) => setValue(e.currentTarget.value)} /> - </Input> - <Input> - <label>Name</label> - <input type="text" disabled={name === undefined} value={name} onChange={e => setName(e.currentTarget.value)}/> - </Input> - </p> - </section> - <footer> - <Button onClick={onCancel}><i18n.Translate> < Back</i18n.Translate></Button> - <ButtonPrimary - disabled={!value && !urlError} - onClick={() => { - const url = canonicalizeBaseUrl(value) - return onConfirm(url, name!).then(r => r ? setError(r) : undefined) - }}><i18n.Translate>Next</i18n.Translate></ButtonPrimary> - </footer> - </PopupBox> + }, [value]); + return ( + <PopupBox> + <section> + <h1> Add backup provider</h1> + <ErrorMessage + title={error && "Could not get provider information"} + description={error} + /> + <LightText> Backup providers may charge for their service</LightText> + <p> + <Input invalid={urlError}> + <label>URL</label> + <input + type="text" + placeholder="https://" + value={value} + onChange={(e) => setValue(e.currentTarget.value)} + /> + </Input> + <Input> + <label>Name</label> + <input + type="text" + disabled={name === undefined} + value={name} + onChange={(e) => setName(e.currentTarget.value)} + /> + </Input> + </p> + </section> + <footer> + <Button onClick={onCancel}> + <i18n.Translate> < Back</i18n.Translate> + </Button> + <ButtonPrimary + disabled={!value && !urlError} + onClick={() => { + const url = canonicalizeBaseUrl(value); + return onConfirm(url, name!).then((r) => + r ? setError(r) : undefined, + ); + }} + > + <i18n.Translate>Next</i18n.Translate> + </ButtonPrimary> + </footer> + </PopupBox> + ); } export interface ConfirmProviderViewProps { - provider: BackupBackupProviderTerms, - url: string, + provider: BackupBackupProviderTerms; + url: string; onCancel: () => void; onConfirm: () => void; } -export function ConfirmProviderView({ url, provider, onCancel, onConfirm }: ConfirmProviderViewProps) { +export function ConfirmProviderView({ + url, + provider, + onCancel, + onConfirm, +}: ConfirmProviderViewProps) { const [accepted, setAccepted] = useState(false); - return <PopupBox> - <section> - <h1>Review terms of service</h1> - <div>Provider URL: <a href={url} target="_blank">{url}</a></div> - <SmallLightText>Please review and accept this provider's terms of service</SmallLightText> - <h2>1. Pricing</h2> - <p> - {Amounts.isZero(provider.annual_fee) ? 'free of charge' : `${provider.annual_fee} per year of service`} - </p> - <h2>2. Storage</h2> - <p> - {provider.storage_limit_in_megabytes} megabytes of storage per year of service - </p> - <Checkbox label="Accept terms of service" name="terms" onToggle={() => setAccepted(old => !old)} enabled={accepted} /> - </section> - <footer> - <Button onClick={onCancel}><i18n.Translate> < Back</i18n.Translate></Button> - <ButtonPrimary - disabled={!accepted} - onClick={onConfirm}><i18n.Translate>Add provider</i18n.Translate></ButtonPrimary> - </footer> - </PopupBox> + return ( + <PopupBox> + <section> + <h1>Review terms of service</h1> + <div> + Provider URL:{" "} + <a href={url} target="_blank"> + {url} + </a> + </div> + <SmallLightText> + Please review and accept this provider's terms of service + </SmallLightText> + <h2>1. Pricing</h2> + <p> + {Amounts.isZero(provider.annual_fee) + ? "free of charge" + : `${provider.annual_fee} per year of service`} + </p> + <h2>2. Storage</h2> + <p> + {provider.storage_limit_in_megabytes} megabytes of storage per year of + service + </p> + <Checkbox + label="Accept terms of service" + name="terms" + onToggle={() => setAccepted((old) => !old)} + enabled={accepted} + /> + </section> + <footer> + <Button onClick={onCancel}> + <i18n.Translate> < Back</i18n.Translate> + </Button> + <ButtonPrimary disabled={!accepted} onClick={onConfirm}> + <i18n.Translate>Add provider</i18n.Translate> + </ButtonPrimary> + </footer> + </PopupBox> + ); } diff --git a/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx b/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx index 14384f23f..1c7fdc829 100644 --- a/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx +++ b/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx @@ -14,13 +14,24 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { Amounts, BackupBackupProviderTerms, canonicalizeBaseUrl, i18n } from "@gnu-taler/taler-util"; -import { verify } from "@gnu-taler/taler-wallet-core/src/crypto/primitives/nacl-fast"; +import { + Amounts, + BackupBackupProviderTerms, + canonicalizeBaseUrl, + i18n, +} from "@gnu-taler/taler-util"; import { VNode, h } from "preact"; import { useEffect, useState } from "preact/hooks"; import { Checkbox } from "../components/Checkbox"; import { ErrorMessage } from "../components/ErrorMessage"; -import { Button, ButtonPrimary, Input, LightText, WalletBox, SmallLightText } from "../components/styled/index"; +import { + Button, + ButtonPrimary, + Input, + LightText, + WalletBox, + SmallLightText, +} from "../components/styled/index"; import * as wxApi from "../wxApi"; interface Props { @@ -30,52 +41,65 @@ interface Props { function getJsonIfOk(r: Response) { if (r.ok) { - return r.json() + return r.json(); } else { if (r.status >= 400 && r.status < 500) { - throw new Error(`URL may not be right: (${r.status}) ${r.statusText}`) + throw new Error(`URL may not be right: (${r.status}) ${r.statusText}`); } else { - throw new Error(`Try another server: (${r.status}) ${r.statusText || 'internal server error'}`) + throw new Error( + `Try another server: (${r.status}) ${ + r.statusText || "internal server error" + }`, + ); } } } - export function ProviderAddPage({ onBack }: Props): VNode { - const [verifying, setVerifying] = useState<{ url: string, name: string, provider: BackupBackupProviderTerms } | undefined>(undefined) - - async function getProviderInfo(url: string): Promise<BackupBackupProviderTerms> { + const [verifying, setVerifying] = useState< + | { url: string; name: string; provider: BackupBackupProviderTerms } + | undefined + >(undefined); + + async function getProviderInfo( + url: string, + ): Promise<BackupBackupProviderTerms> { return fetch(`${url}config`) - .catch(e => { throw new Error(`Network error`) }) - .then(getJsonIfOk) + .catch((e) => { + throw new Error(`Network error`); + }) + .then(getJsonIfOk); } if (!verifying) { - return <SetUrlView - onCancel={onBack} - onVerify={(url) => getProviderInfo(url)} - onConfirm={(url, name) => getProviderInfo(url) - .then((provider) => { - setVerifying({ url, name, provider }); - }) - .catch(e => e.message) - } - /> + return ( + <SetUrlView + onCancel={onBack} + onVerify={(url) => getProviderInfo(url)} + onConfirm={(url, name) => + getProviderInfo(url) + .then((provider) => { + setVerifying({ url, name, provider }); + }) + .catch((e) => e.message) + } + /> + ); } - return <ConfirmProviderView - provider={verifying.provider} - url={verifying.url} - onCancel={() => { - setVerifying(undefined); - }} - onConfirm={() => { - wxApi.addBackupProvider(verifying.url, verifying.name).then(onBack) - }} - - /> + return ( + <ConfirmProviderView + provider={verifying.provider} + url={verifying.url} + onCancel={() => { + setVerifying(undefined); + }} + onConfirm={() => { + wxApi.addBackupProvider(verifying.url, verifying.name).then(onBack); + }} + /> + ); } - export interface SetUrlViewProps { initialValue?: string; onCancel: () => void; @@ -84,83 +108,137 @@ export interface SetUrlViewProps { withError?: string; } -export function SetUrlView({ initialValue, onCancel, onVerify, onConfirm, withError }: SetUrlViewProps) { - const [value, setValue] = useState<string>(initialValue || "") - const [urlError, setUrlError] = useState(false) - const [name, setName] = useState<string|undefined>(undefined) - const [error, setError] = useState<string | undefined>(withError) +export function SetUrlView({ + initialValue, + onCancel, + onVerify, + onConfirm, + withError, +}: SetUrlViewProps) { + const [value, setValue] = useState<string>(initialValue || ""); + const [urlError, setUrlError] = useState(false); + const [name, setName] = useState<string | undefined>(undefined); + const [error, setError] = useState<string | undefined>(withError); useEffect(() => { try { - const url = canonicalizeBaseUrl(value) - onVerify(url).then(r => { - setUrlError(false) - setName(new URL(url).hostname) - }).catch(() => { - setUrlError(true) - setName(undefined) - }) + const url = canonicalizeBaseUrl(value); + onVerify(url) + .then((r) => { + setUrlError(false); + setName(new URL(url).hostname); + }) + .catch(() => { + setUrlError(true); + setName(undefined); + }); } catch { - setUrlError(true) - setName(undefined) + setUrlError(true); + setName(undefined); } - }, [value]) - return <WalletBox> - <section> - <h1> Add backup provider</h1> - <ErrorMessage title={error && "Could not get provider information"} description={error} /> - <LightText> Backup providers may charge for their service</LightText> - <p> - <Input invalid={urlError}> - <label>URL</label> - <input type="text" placeholder="https://" value={value} onChange={(e) => setValue(e.currentTarget.value)} /> - </Input> - <Input> - <label>Name</label> - <input type="text" disabled={name === undefined} value={name} onChange={e => setName(e.currentTarget.value)}/> - </Input> - </p> - </section> - <footer> - <Button onClick={onCancel}><i18n.Translate> < Back</i18n.Translate></Button> - <ButtonPrimary - disabled={!value && !urlError} - onClick={() => { - const url = canonicalizeBaseUrl(value) - return onConfirm(url, name!).then(r => r ? setError(r) : undefined) - }}><i18n.Translate>Next</i18n.Translate></ButtonPrimary> - </footer> - </WalletBox> + }, [value]); + return ( + <WalletBox> + <section> + <h1> Add backup provider</h1> + <ErrorMessage + title={error && "Could not get provider information"} + description={error} + /> + <LightText> Backup providers may charge for their service</LightText> + <p> + <Input invalid={urlError}> + <label>URL</label> + <input + type="text" + placeholder="https://" + value={value} + onChange={(e) => setValue(e.currentTarget.value)} + /> + </Input> + <Input> + <label>Name</label> + <input + type="text" + disabled={name === undefined} + value={name} + onChange={(e) => setName(e.currentTarget.value)} + /> + </Input> + </p> + </section> + <footer> + <Button onClick={onCancel}> + <i18n.Translate> < Back</i18n.Translate> + </Button> + <ButtonPrimary + disabled={!value && !urlError} + onClick={() => { + const url = canonicalizeBaseUrl(value); + return onConfirm(url, name!).then((r) => + r ? setError(r) : undefined, + ); + }} + > + <i18n.Translate>Next</i18n.Translate> + </ButtonPrimary> + </footer> + </WalletBox> + ); } export interface ConfirmProviderViewProps { - provider: BackupBackupProviderTerms, - url: string, + provider: BackupBackupProviderTerms; + url: string; onCancel: () => void; onConfirm: () => void; } -export function ConfirmProviderView({ url, provider, onCancel, onConfirm }: ConfirmProviderViewProps) { +export function ConfirmProviderView({ + url, + provider, + onCancel, + onConfirm, +}: ConfirmProviderViewProps) { const [accepted, setAccepted] = useState(false); - return <WalletBox> - <section> - <h1>Review terms of service</h1> - <div>Provider URL: <a href={url} target="_blank">{url}</a></div> - <SmallLightText>Please review and accept this provider's terms of service</SmallLightText> - <h2>1. Pricing</h2> - <p> - {Amounts.isZero(provider.annual_fee) ? 'free of charge' : `${provider.annual_fee} per year of service`} - </p> - <h2>2. Storage</h2> - <p> - {provider.storage_limit_in_megabytes} megabytes of storage per year of service - </p> - <Checkbox label="Accept terms of service" name="terms" onToggle={() => setAccepted(old => !old)} enabled={accepted} /> - </section> - <footer> - <Button onClick={onCancel}><i18n.Translate> < Back</i18n.Translate></Button> - <ButtonPrimary - disabled={!accepted} - onClick={onConfirm}><i18n.Translate>Add provider</i18n.Translate></ButtonPrimary> - </footer> - </WalletBox> + return ( + <WalletBox> + <section> + <h1>Review terms of service</h1> + <div> + Provider URL:{" "} + <a href={url} target="_blank"> + {url} + </a> + </div> + <SmallLightText> + Please review and accept this provider's terms of service + </SmallLightText> + <h2>1. Pricing</h2> + <p> + {Amounts.isZero(provider.annual_fee) + ? "free of charge" + : `${provider.annual_fee} per year of service`} + </p> + <h2>2. Storage</h2> + <p> + {provider.storage_limit_in_megabytes} megabytes of storage per year of + service + </p> + <Checkbox + label="Accept terms of service" + name="terms" + onToggle={() => setAccepted((old) => !old)} + enabled={accepted} + /> + </section> + <footer> + <Button onClick={onCancel}> + <i18n.Translate> < Back</i18n.Translate> + </Button> + <ButtonPrimary disabled={!accepted} onClick={onConfirm}> + <i18n.Translate>Add provider</i18n.Translate> + </ButtonPrimary> + </footer> + </WalletBox> + ); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bea05decd..b14baed12 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,6 +12,19 @@ importers: '@linaria/shaker': 3.0.0-beta.7 esbuild: 0.12.21 + packages/anastasis-core: + specifiers: + '@gnu-taler/taler-util': workspace:^0.8.3 + ava: ^3.15.0 + hash-wasm: ^4.9.0 + typescript: ^4.4.3 + dependencies: + '@gnu-taler/taler-util': link:../taler-util + hash-wasm: 4.9.0 + devDependencies: + ava: 3.15.0 + typescript: 4.4.3 + packages/idb-bridge: specifiers: '@rollup/plugin-commonjs': ^17.1.0 @@ -52,6 +65,7 @@ importers: specifiers: '@types/node': ^14.14.22 ava: ^3.15.0 + big-integer: ^1.6.48 esbuild: ^0.9.2 jed: ^1.1.1 prettier: ^2.2.1 @@ -59,6 +73,7 @@ importers: tslib: ^2.1.0 typescript: ^4.2.3 dependencies: + big-integer: 1.6.48 jed: 1.1.1 tslib: 2.1.0 devDependencies: @@ -11813,6 +11828,10 @@ packages: safe-buffer: 5.2.1 dev: true + /hash-wasm/4.9.0: + resolution: {integrity: sha512-7SW7ejyfnRxuOc7ptQHSf4LDoZaWOivfzqw+5rpcQku0nHfmicPKE51ra9BiRLAmT8+gGLestr1XroUkqdjL6w==} + dev: false + /hash.js/1.1.7: resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} dependencies: @@ -19292,6 +19311,12 @@ packages: hasBin: true dev: true + /typescript/4.4.3: + resolution: {integrity: sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + /uglify-js/3.12.5: resolution: {integrity: sha512-SgpgScL4T7Hj/w/GexjnBHi3Ien9WS1Rpfg5y91WXMj9SY997ZCQU76mH4TpLwwfmMvoOU8wiaRkIf6NaH3mtg==} engines: {node: '>=0.8.0'} |