From 6ab357530299b7a0c5ead9108ce5451a60b3bcd0 Mon Sep 17 00:00:00 2001 From: thomasrosen Date: Sat, 19 Nov 2022 23:36:12 +0100 Subject: [PATCH] feat: copied old frontend code --- .../Ubuntu/4iCs6KVjbNBYlgoKcQ72nU6AF7xm.woff2 | Bin 0 -> 17612 bytes .../Ubuntu/4iCs6KVjbNBYlgoKcg72nU6AF7xm.woff2 | Bin 0 -> 8744 bytes .../Ubuntu/4iCs6KVjbNBYlgoKcw72nU6AF7xm.woff2 | Bin 0 -> 5104 bytes .../Ubuntu/4iCs6KVjbNBYlgoKew72nU6AF7xm.woff2 | Bin 0 -> 8128 bytes .../Ubuntu/4iCs6KVjbNBYlgoKfA72nU6AF7xm.woff2 | Bin 0 -> 5620 bytes .../Ubuntu/4iCs6KVjbNBYlgoKfw72nU6AFw.woff2 | Bin 0 -> 13720 bytes frontend/_DATA_.js | 486 ++++ frontend/index.html | 1578 ++++++++++++ frontend/jsSHA/.gitignore | 2 + frontend/jsSHA/.npmignore | 3 + frontend/jsSHA/.travis.yml | 4 + frontend/jsSHA/CHANGELOG.md | 164 ++ frontend/jsSHA/LICENSE | 26 + frontend/jsSHA/README.md | 125 + frontend/jsSHA/bower.json | 51 + frontend/jsSHA/build/externs.js | 5 + frontend/jsSHA/build/make-release | 10 + frontend/jsSHA/externs/sha.js | 49 + frontend/jsSHA/package.json | 54 + frontend/jsSHA/src/sha.js | 43 + frontend/jsSHA/src/sha1.js | 23 + frontend/jsSHA/src/sha256.js | 27 + frontend/jsSHA/src/sha3.js | 27 + frontend/jsSHA/src/sha512.js | 34 + frontend/jsSHA/src/sha_dev.js | 2254 +++++++++++++++++ frontend/jsSHA/test/genHashRounds.py | 67 + frontend/jsSHA/test/genShake.py | 42 + frontend/jsSHA/test/hash-file.html | 114 + frontend/jsSHA/test/sha3.py | 106 + frontend/jsSHA/test/test.html | 38 + frontend/jsSHA/test/test_hashes.js | 1213 +++++++++ frontend/jsSHA/test/test_hmac.js | 533 ++++ frontend/jsSHA/test/test_multi.js | 220 ++ frontend/thumbnail.png | Bin 0 -> 47333 bytes index.js | 6 +- 35 files changed, 7299 insertions(+), 5 deletions(-) create mode 100644 frontend/Ubuntu/4iCs6KVjbNBYlgoKcQ72nU6AF7xm.woff2 create mode 100644 frontend/Ubuntu/4iCs6KVjbNBYlgoKcg72nU6AF7xm.woff2 create mode 100644 frontend/Ubuntu/4iCs6KVjbNBYlgoKcw72nU6AF7xm.woff2 create mode 100644 frontend/Ubuntu/4iCs6KVjbNBYlgoKew72nU6AF7xm.woff2 create mode 100644 frontend/Ubuntu/4iCs6KVjbNBYlgoKfA72nU6AF7xm.woff2 create mode 100644 frontend/Ubuntu/4iCs6KVjbNBYlgoKfw72nU6AFw.woff2 create mode 100644 frontend/_DATA_.js create mode 100644 frontend/index.html create mode 100755 frontend/jsSHA/.gitignore create mode 100755 frontend/jsSHA/.npmignore create mode 100755 frontend/jsSHA/.travis.yml create mode 100755 frontend/jsSHA/CHANGELOG.md create mode 100755 frontend/jsSHA/LICENSE create mode 100755 frontend/jsSHA/README.md create mode 100755 frontend/jsSHA/bower.json create mode 100755 frontend/jsSHA/build/externs.js create mode 100755 frontend/jsSHA/build/make-release create mode 100755 frontend/jsSHA/externs/sha.js create mode 100755 frontend/jsSHA/package.json create mode 100755 frontend/jsSHA/src/sha.js create mode 100755 frontend/jsSHA/src/sha1.js create mode 100755 frontend/jsSHA/src/sha256.js create mode 100755 frontend/jsSHA/src/sha3.js create mode 100755 frontend/jsSHA/src/sha512.js create mode 100755 frontend/jsSHA/src/sha_dev.js create mode 100755 frontend/jsSHA/test/genHashRounds.py create mode 100755 frontend/jsSHA/test/genShake.py create mode 100755 frontend/jsSHA/test/hash-file.html create mode 100755 frontend/jsSHA/test/sha3.py create mode 100755 frontend/jsSHA/test/test.html create mode 100755 frontend/jsSHA/test/test_hashes.js create mode 100755 frontend/jsSHA/test/test_hmac.js create mode 100755 frontend/jsSHA/test/test_multi.js create mode 100644 frontend/thumbnail.png diff --git a/frontend/Ubuntu/4iCs6KVjbNBYlgoKcQ72nU6AF7xm.woff2 b/frontend/Ubuntu/4iCs6KVjbNBYlgoKcQ72nU6AF7xm.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..ae52f5c0c933e3de0128f39ee79bf894e56afe81 GIT binary patch literal 17612 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 literal 0 HcmV?d00001 diff --git a/frontend/Ubuntu/4iCs6KVjbNBYlgoKcg72nU6AF7xm.woff2 b/frontend/Ubuntu/4iCs6KVjbNBYlgoKcg72nU6AF7xm.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..b96c82c9bab74f49c533b287da06c7d2f6aee604 GIT binary patch literal 8744 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 literal 0 HcmV?d00001 diff --git a/frontend/Ubuntu/4iCs6KVjbNBYlgoKfA72nU6AF7xm.woff2 b/frontend/Ubuntu/4iCs6KVjbNBYlgoKfA72nU6AF7xm.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..b496474fcac3f1b43c39bd49d82389200a2a936a GIT binary patch literal 5620 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 literal 0 HcmV?d00001 diff --git a/frontend/Ubuntu/4iCs6KVjbNBYlgoKfw72nU6AFw.woff2 b/frontend/Ubuntu/4iCs6KVjbNBYlgoKfw72nU6AFw.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..39e70aaac91e945facddfee6f983aa7dd85e9734 GIT binary patch literal 13720 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 CkDg)x literal 0 HcmV?d00001 diff --git a/frontend/_DATA_.js b/frontend/_DATA_.js new file mode 100644 index 0000000..a32cae6 --- /dev/null +++ b/frontend/_DATA_.js @@ -0,0 +1,486 @@ + + + +const _DATA_ = { + translation_texts: { + website_title: { + is_plain: true, + prefix: 'Volt - ', + use_instead: 'website_heading', + }, + website_heading: { + de: 'Umfrage zur\ninternen Diversität', + en: 'Internal\nDiversity\nSurvey', + }, + website_description: { + // de: ` + // Um unseren internen Diversitäts-Ansprüchen nachkommen zu können, müssen wir rausfinden wie divers wir sind. + // Mit dieser Umfrage möchten wir ein Bild davon bekommen. + // `, + de: ` + Um unseren internen Diversitäts-Ansprüchen nachzukommen, müssen wir rausfinden wie divers wir sind. + Mit dieser Umfrage machen wir uns ein Bild davon. + `, + en: ` + To meet our internal diversity goals, we need to find out how diverse we actually are. + With this survey, we'll get a picture of that. + `, + }, + //website_privacy: {de:` + // Da uns Privatsphäre wichtig ist, werden die Antworten jeweils zur Frage gruppiert gespeichert, sodass die hier eingegebenen Daten nicht auf dich zurückführbar sind. + // + // Zu den einzelnen Datensätzen werden nur die im folgenden Kasten genannten Metadaten gespeichert. + // + // Bei Fragen kannst du dich an thomas.rosen@volteuropa.org wenden. + //`}, + + // necessary_metadata: {de: 'Benötigte Metadaten: '}, + // voluntary_metadata: {de: 'Freiwillige Metadaten: '}, + // metadata_running_year: {de: 'Das laufende Jahr:'}, + // metadata_running_month: {de: 'Der laufende Monat:'}, + // metadata_tatc_info: {de: 'Ein, für jede Frage unterschiedlicher, annonymer Tracking-Code.'}, + // metadata_if_it_is_first_completion: {de: 'Ob du das erste Mal an der Umfrage teilnimmst.'}, + // your_country: {de: 'Dein Land:'}, + // your_city: {de: 'Deine Stadt:'}, + // voluntary_metadata_description: {de: 'Jeweils das Land und/oder das Städteteam in dem du am aktivsten bist.'}, + + button_to_privacy: { + de: 'Los geht\'s', + en: 'Let\'s start', + }, + + heading_privacy: { + de: 'Privatsphäre und Datenschutz', + en: 'Privacy', + }, + heading_optional: { + de: 'Freiwillig', + en: 'Optional', + }, + optional_info: { + de: 'Beantworte nur die Fragen die du beantworten möchtest.', + en: 'Only answer the questions you want to answer.', + }, + heading_anonymous: { + de: 'Anonym', + en: 'Anonymous', + }, + anonymous_info: { + de: 'Die Antworten werden jeweils zur Frage gruppiert gespeichert. Rückschlüsse auf Dich sind nicht möglich.', + en: 'The answers are saved in groups for each question. It is not possible to draw conclusions about you.', + }, + privacy_details: { + de: ` + Zu jeder Frage werden das aktuelle Jahr und der aktuelle Monat gespeichert. Optional werden dazu noch dein Land und deine Stadt gespeichert. + + Volt Europa verwendet Deine im Rahmen dieser Umfrage angegebenen Daten ausschließlich, um die Umfrage auszuwerten und die Ergebnisse gegebenenfalls mit Mitgliedern von Volt Europa zu teilen. Weitere Informationen kannst Du unserer Datenschutzerklärung auf www.volteuropa.org/privacy entnehmen. + + Bei Fragen zu dieser Umfrage kannst du dich an thomas.rosen@volteuropa.org wenden. + `, + en: ` + For each question the current year and month are saved. Optionally, your current country and city are saved as well. + + Volt Europa will only use the information you provide in this survey for the purpose of evaluating the survey and sharing the results with Volt Europa members, if applicable. For more information, please see our privacy policy at www.volteuropa.org/privacy. + + If you have any questions about this survey, please contact thomas.rosen@volteuropa.org. + `, + }, + button_to_questions: { + de: 'Zu den Fragen', + en: 'To the questions', + }, + + metadata_is_this_the_first_completion: { + de: 'Nimmst du das erste Mal an der Umfrage teil?', + en: 'Is this your first time participating in the survey?', + }, + button_send_to_volt: { + de: 'An Volt senden', + en: 'Send to Volt', + }, + + saving: { + de: 'Deine Antworten werden gespeichert…', + en: 'Your answers are being saved…', + }, + success: { + de: 'Deine Antworten wurden gespeichert!', + en: 'Your answers have been saved!', + }, + error: { + de: 'Es gab ein technisches Problem!\nBist du eventuell nicht mit dem Internet verbunden?\n\nMelde dich bei Bedarf bei Thomas Rosen.', + en: 'There was a technical problem! Perhaps you are not connected to the internet?\n\nContact Thomas Rosen if necessary.', + }, + + results: { + de: 'Ergebnisse', + en: 'Results', + }, + }, + sections: [ + { + heading: { + de: 'Metadaten', + en: 'Metadata', + }, + questions: { + metadata_country: { + question: { + de: 'Dein Land', + en: 'Your country', + }, + type: 'chooser', + options: {}, + }, + metadata_city: { + question: { + de: 'Dein Städteteam', + en: 'Your cityteam', + }, + type: 'one_line_text', + }, + } + }, + { + heading: { + de: 'Bildung', + en: 'Education', + }, + questions: { + highest_degree_of_education: { + question: { de: 'Dein höchster Bildungsabschluss…' }, + // why: {de: 'Aus welcher Bildungsschicht kommen unsere Mitglieder?'}, + type: 'radio', // 'chooser', + options: { + 'none': { de: 'Kein Abschluss' }, + 'ISCED_1': { de: 'Vollendung der Grundschule' }, + 'ISCED_2': { de: 'Haupt- / Realschulabschluss' }, + 'ISCED_3': { de: 'Abitur' }, + 'ISCED_4': { de: 'Fachhochschulreife / Fachabitur' }, // {de: 'Fachhochschulreife / Fachgebundene Hochschulreife(Fachabitur)'}, + 'ISCED_5': { de: 'Meister' }, + 'ISCED_6': { de: 'Bachelor / Diplom(FH)' }, + 'ISCED_7': { de: 'Master / Diplom(Uni)' }, + 'ISCED_8': { de: 'Doktorat / PhD' }, + } + }, + good_communication_in_english: { + question: { de: 'Kannst du dich gut auf Englisch verständigen?' }, + why: { de: 'Als internationale Organisation wird viel auf Englisch kommuniziert. Hiermit möchten wir schauen, ob mehr in die einzelnen Sprachen übersetzt werden sollte.' }, + type: 'radio', + options: { + 'yes': { + de: 'Ja', + en: 'Yes', + }, + 'no': { + de: 'Nein', + en: 'No', + }, + } + }, + problems_with_computers: { + question: { de: 'Hast du gelegentlich/oft Probleme dich am Computer oder Handy zurecht zu finden?' }, + why: { de: 'Wir schauen hiermit, wie viel wir innerhalb von Volt auf technische Lösungen setzten können?' }, + type: 'radio', + options: { + 'yes': { de: '(Eher) Ja' }, + 'no': { de: '(Eher) Nein' }, + 'depends': { de: 'Kommt drauf an (Gerät, Betriebsystem, Anwendung,…)' }, + } + }, + } + }, + { + heading: { de: 'Kultur' }, + questions: { + amount_of_kown_languages: { + question: { de: 'Wie viele Sprachen kannst du sprechen/verstehen?' }, + why: { de: 'Austausch über die eigene Sprach-Bubble hinaus.' }, + info: { de: 'Zähl auch Mutter- und Gebärdensprachen dazu.' }, + type: 'radio', + options: { + '1': { de: '1' }, + '2': { de: '2' }, + '3': { de: '3' }, + '4': { de: '4' }, + '5+': { de: '5 oder mehr' }, + } + }, + different_country_of_origin: { + question: { de: 'Lebst du in einem anderen Land als du geboren bist?' }, + why: { de: 'Wissen anderer Kulturen in Volt.' }, + type: 'radio', + options: { + 'yes': { + de: 'Ja', + en: 'Yes', + }, + 'no': { + de: 'Nein', + en: 'No', + }, + } + }, + } + }, + { + heading: { de: 'LGBTQ*' }, + questions: { + gender: { + question: { de: 'Wie bezeichnest du dein Gender?' }, + why: { de: 'Gender ist nicht das Geschlecht in deinem Ausweiß, sondern beschreibt die nicht an biologische Merkmale gebundenen Geschlechtsaspekte des Menschen.' }, + type: 'radio', // 'chooser', + options: { + 'female': { de: 'weiblich' }, + 'male': { de: 'männlich' }, + 'non_binary': { de: 'non-binary / weder weiblich noch männlich' }, + 'gender_fluid': { de: 'gender-fluid' }, + 'not_sure': { de: 'Ich bin mir nicht sicher.' }, + 'terms_dont_fit': { de: 'Diese Begriffe passen nicht zu mir.' }, + }, + }, + gender_identity: { + question: { de: 'Wie bezeichnest du deine Geschlechtsidentität?' }, + why: { de: 'Um die Probleme einer Trans-Person vollständig nachvollziehen zu können, muss man selbst Trans* sein. Daher sollten wir wissen, wie gut wir zu diesem Thema aufgestellt sind.' }, + info: { de: 'Cisgender: Biologisches Geschlecht und Gender sind gleich.' }, + type: 'radio', // 'chooser', + options: { + 'transgender': { de: 'Transgender' }, + 'cisgender': { de: 'Cisgender' }, + 'not_sure': { de: 'Ich bin mir nicht sicher' }, + 'terms_dont_fit': { de: 'Diese Begriffe passen nicht zu mir.' }, + }, + }, + sexual_orientation: { + question: { de: 'Wie bezeichnest du deine sexuelle Orientierung?' }, + why: { de: 'Um die Probleme einer queeren Person vollständig nachvollziehen zu können, muss man queer sein. Daher sollten wir wissen, wie gut wir zu diesem Thema aufgestellt sind.' }, + type: 'radio', // 'chooser', + options: { + 'homosexual': { de: 'homosexuell / lesbisch / schwul / …' }, + 'interested_in_more_than_one_gender': { de: 'bisexuell / pansexuell / polysexuell / …' }, // {de: 'bisexuell / bi / ambisexuell / pansexuell / polysexuell / …'}, + 'queer': { de: 'queer' }, + 'asexual': { de: 'asexuell' }, + 'heterosexual': { de: 'heterosexuell / straight' }, + 'not_sure': { de: 'Ich bin mir nicht sicher.' }, + 'terms_dont_fit': { de: 'Diese Begriffe passen nicht zu mir.' }, + }, + }, + }, + }, + { + heading: { de: 'Diskriminierung' }, + // Diskriminierung sollte hinter LGBTQ* sein, da wir dort den Begriff "Gender" erklären. (EN: Discrimination should be after LGBTQ*, cause we teach the term "gender" in it.) + questions: { + discriminatory_experiences: { + question: { de: 'In welchen Bereichen hast du schonmal diskriminierende Erfahrungen gemacht?' }, + // why: {de: 'Hier mit möchten wir herrausfinden, wie privilegiert Volt Mitglieder sind.'}, + type: 'checkbox', + options: { + 'ancestry': { de: 'Ethnische Herkunft oder Hauttyp' }, + 'sex_or_gender': { de: 'Geschlecht oder Gender' }, + 'sexual_orientation': { de: 'Sexuelle Orientierung' }, + 'age': { de: 'Alter' }, + 'disabilities': { de: 'Behinderung oder chronische Krankheit' }, + 'ideology': { de: 'Religion oder Weltanschauung' }, + 'classism': { de: 'Vermögen oder sozialen Herkunft' }, + 'other': { de: 'andere Bereiche' }, + }, + }, + // discriminatory_experiences_within_volt: { + // question: {de: 'Hast diskriminierende Erfahrungen innerhalb von Volt gemacht?'}, + // // why: {de: 'Hier mit möchten wir herrausfinden, wie privilegiert Volt Mitglieder sind.'}, + // type: 'checkbox', + // options: { + // 'yes': {de: 'Ja'}, + // 'no': {de: 'Nein'}, + // }, + // }, + }, + }, + { + heading: { de: 'Psyche' }, + questions: { + psychological_difficulties: { + question: { de: 'Hast du (unabhängig von einer psychiatrischen Diagnose) mit anhaltenden oder immer wiederkehrenden psychischen Schwierigkeiten zu tun haben?' }, + why: { de: 'Unsere Reaktion auf, für uns ungewohntes Verhalten der Mitglieder.' }, + type: 'radio', + options: { + 'yes': { + de: 'Ja', + en: 'Yes', + }, + 'no': { + de: 'Nein', + en: 'No', + }, + } + }, + //introverted_or_extroverted: { + // question: {de: 'Bist du eher introvertiert oder extrovertiert?'}, + // why: {de: 'Wir müssen auch auf Mitglieder achten, die sich bei Diskussion nicht selbstständig durchsetzten? Oder denen viele Menschen ab und zu zuanstrengend sind.'}, + // type: 'radio', + // options: { + // 'more_introverted': {de: 'eher introvertiert'}, + // 'terms_dont_fit': {de: 'je nachdem / weder noch / kommt drauf an'}, + // 'more_extroverted': {de: 'eher extrovertiert'}, + // } + //}, + participating_in_offline_discussions: { + question: { de: 'Wie wohl würdest du dich fühlen, an einer Diskussion bei einer face-to-face Veranstaltung (z.B. einem Meet & Greet) teilzunehmen?' }, + why: { de: 'Wir müssen auch auf Mitglieder achten, die sich bei Diskussion nicht selbstständig durchsetzten, oder denen viele Menschen ab und zu zuanstrengend sind.' }, + type: 'radio', + options: { + '5': { de: 'Sehr wohl' }, + '4': { de: 'Eher wohl' }, // Einigermaßen wohl + '3': { de: 'Weder noch' }, + '2': { de: 'Eher unwohl' }, // Einigermaßen unwohl + '1': { de: 'Sehr unwohl' }, + } + }, + participating_in_online_discussions: { + question: { de: 'Wie wohl würdest du dich fühlen, an einer Diskussion auf Workplace (oder einem anderen Online-Tool) teilzunehmen?' }, + why: { de: '(Begründung, siehe vorherige Frage.)' }, + type: 'radio', + options: { + '5': { de: 'Sehr wohl' }, + '4': { de: 'Eher wohl' }, + '3': { de: 'Weder noch' }, + '2': { de: 'Eher unwohl' }, + '1': { de: 'Sehr unwohl' }, + } + }, + }, + }, + { + heading: { de: 'Hilfsmittel' }, + questions: { + everyday_aids: { + question: { de: 'Welche Hilfsmittel benötigst du im Alltag?' }, + why: { de: 'Erreichbarkeit und Verständigung bei den Events.' }, + type: 'checkbox', + options: { + 'wheelchair': { de: 'Rollstuhl' }, + 'walking_aid': { de: 'Rollator / Krücken / Gehstock / …' }, + 'hearing_aid': { de: 'Hörgerät / Mikrofon' }, + 'seeing_aid': { de: 'Brille / Lupe' }, + 'assistance': { de: 'Assistenz (Tier, Mensch oder Roboter)' }, + + 'prosthesis': { de: 'Prothese' }, + 'orthosis': { de: 'Orthese' }, + + 'other': { de: 'andere Hilfsmittel' }, // (Screenreader, Brailledisplay, …) + } + }, + financial_help: { + question: { de: 'Bekommst du finanzielle Hilfe. (Bafög, Hartz4, Jugendamt, …)' }, + why: { de: 'Je nach verfügbarer Geldmenge kann man einfacher an bestimmten Events teilnehmen.' }, + type: 'radio', + options: { + 'yes': { + de: 'Ja', + en: 'Yes', + }, + 'no': { + de: 'Nein', + en: 'No', + }, + } + }, + } + }, + { + heading: { de: 'Verbesserung der Umfrage' }, + intro: { de: 'Die ist unsere erste Umfrage dieser Art. Hier kannst du uns helfen diese weiter zu entwickeln …' }, + questions: { + text_whats_missing: { + question: { de: 'Welche Merkmale fehlen Deiner Meinung nach hier, sind aber aus Deiner Sicht für Diversität in Volt wichtig?' }, + // why: '', + info: { de: '(und sollten noch abgefragt werden)' }, + type: 'text', + }, + text_whats_to_much: { + question: { de: 'Welche Merkmale sollten wir künftig nicht mehr abfragen?' }, + // why: '(Hinweis: Alle Antworten sind freiwillig!)', + type: 'text', + }, + text_other_stuff: { + question: { de: 'Sonstige Anmerkungen?' }, + // why: '', + type: 'text', + }, + }, + }, + ], + countries: [ + // The List is from: https://volt.team/teams + + { title: 'Keine Angabe' }, + { disabled: true }, + { value: 'AUT', local_name: 'Österreich', en: 'Austria' }, + { value: 'BEL', local_name: 'Belgique / Belgie', en: 'Belgium' }, + { value: 'BGR', local_name: 'Bulgaria', en: 'Bulgaria' }, + { value: 'CYP', local_name: 'Kibris / Kypros', en: 'Cyprus' }, + { value: 'CZE', local_name: 'Ceska Republika', en: 'Czech Republic' }, + { value: 'DNK', local_name: 'Danmark', en: 'Denmark' }, + { value: 'DEU', local_name: 'Deutschland', en: 'Germany' }, + { value: 'EST', local_name: 'Eesti Vabariik', en: 'Estonia' }, + { value: 'IRL', local_name: 'Éire', en: 'Ireland' }, + { value: 'ESP', local_name: 'España', en: 'Spain' }, + { value: 'FRA', local_name: 'France', en: 'France' }, + { value: 'GRC', local_name: 'Ellas / Ellada', en: 'Greece' }, + { value: 'HRV', local_name: 'Hrvatska', en: 'Croatia' }, + { value: 'HUN', local_name: 'Magyarorszag', en: 'Hungary' }, + { value: 'ITA', local_name: 'Italia', en: 'Italy' }, + { value: 'LVA', local_name: 'Latvija', en: 'Latvia' }, + { value: 'LTU', local_name: 'Lietuva', en: 'Lithuania' }, + { value: 'LUX', local_name: 'Luxembourg / Letzebuerg', en: 'Luxembourg' }, + { value: 'MLT', local_name: 'Malta', en: 'Malta' }, + { value: 'NLD', local_name: 'Nederland / Holland', en: 'Netherlands' }, + { value: 'POL', local_name: 'Polska', en: 'Poland' }, + { value: 'PRT', local_name: 'Portugal', en: 'Portugal' }, + { value: 'ROU', local_name: 'Romania', en: 'Romania' }, + { value: 'SVK', local_name: 'Slovensko', en: 'Slovakia' }, + { value: 'SVN', local_name: 'Slovenija', en: 'Slovenia' }, + { value: 'FIN', local_name: 'Suomi', en: 'Finland' }, + { value: 'SWE', local_name: 'Sverige', en: 'Sweden' }, + { value: 'GBR', local_name: 'United Kingdom', en: 'United Kingdom' }, + + // Volt New Territories: + { disabled: true }, + { value: 'ALA', local_name: 'Landskapet Åland / Ahvenanmaan maakunta', en: 'Åland Islands' }, + { value: 'ALB', local_name: 'Shqiperia', en: 'Albania' }, + { value: 'AND', local_name: 'Andorra', en: 'Andorra' }, + { value: 'BIH', local_name: 'Bosna i Hercegovina', en: 'Bosnia and Herzegovina' }, + { value: 'FRO', local_name: 'Føroyar', en: 'Faroe Islands' }, + { value: 'GIB', local_name: 'Gibraltar', en: 'Gibraltar' }, + { value: 'GGY', local_name: 'Guernsey', en: 'Guernsey' }, + { value: 'ISL', local_name: 'Ísland', en: 'Iceland' }, + { value: 'IMN', local_name: 'Isle of Man', en: 'Isle of Man' }, + { value: 'JEY', local_name: 'Jersey', en: 'Jersey' }, + { value: 'LIE', local_name: 'Liechtenstein', en: 'Liechtenstein' }, + { value: 'MKD', local_name: 'Makedonija', en: 'Macedonia (FYROM)' }, + { value: 'MDA', local_name: 'Moldova', en: 'Moldova' }, + { value: 'MCO', local_name: 'Monaco', en: 'Monaco' }, + { value: 'MNE', local_name: 'Crna Gora', en: 'Montenegro' }, + { value: 'NOR', local_name: 'Norge', en: 'Norway' }, + { value: 'SMR', local_name: 'San Marino', en: 'San Marino' }, + { value: 'CHE', local_name: 'Schweiz / Suisse / Svizzera', en: 'Switzerland' }, + { value: 'BLR', local_name: 'Беларусь', en: 'Belarus' }, + { value: 'SRB', local_name: 'Србија', en: 'Serbia' }, + { value: 'UKR', local_name: 'Україна', en: 'Ukraine' }, + + { disabled: true }, + { value: 'Volt Abroad', title: 'Volt Abroad (Australia, Canada, Singapore, Thailand, Uruguay, USA, …)' }, + // TODO: Should there be an entry "Volt Europa"? + ] +} + +try { + if (!!module && module.exports) { + module.exports = _DATA_ + } +} catch (error) { + if (!!_DATA_GOT_LOADED) { + _DATA_GOT_LOADED() + } +} diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..39d4a38 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,1578 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Volt — Internal Diversity Survey + + + + + + + + + + + + + + +
+
+

+ + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + +

+

+ +
+
+

+ + +
+
+ + +
+
+ + + +
+
+

+ +
+
+

+


+ +

+

+


+ +

+
+
+

+
+
+ + +
+
+ + +
+
+ +
+ +
+ +
+ + + +
+

+

+

+
+
+
+ + + + + + + + + + + diff --git a/frontend/jsSHA/.gitignore b/frontend/jsSHA/.gitignore new file mode 100755 index 0000000..532b129 --- /dev/null +++ b/frontend/jsSHA/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +*.pyc diff --git a/frontend/jsSHA/.npmignore b/frontend/jsSHA/.npmignore new file mode 100755 index 0000000..e04e7ce --- /dev/null +++ b/frontend/jsSHA/.npmignore @@ -0,0 +1,3 @@ +build +test +src/sha_dev.js diff --git a/frontend/jsSHA/.travis.yml b/frontend/jsSHA/.travis.yml new file mode 100755 index 0000000..12c4e53 --- /dev/null +++ b/frontend/jsSHA/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "node" + diff --git a/frontend/jsSHA/CHANGELOG.md b/frontend/jsSHA/CHANGELOG.md new file mode 100755 index 0000000..6067e51 --- /dev/null +++ b/frontend/jsSHA/CHANGELOG.md @@ -0,0 +1,164 @@ +jsSHA - ChangeLog +========================= + +2.3.1 (2017-06-10) +------------------------- +- Fix issue with SHA-3 and using a combination of TEXT/UTF-16 input + (thanks frostschutz!) + +2.3.0 (2017-05-13) +------------------------- +- Sped up SHA-3 implementation by adding little-endian capability to + conversion functions +- Further sped up SHA-3 implementation by decomposing xor\_64 function + (thanks frostschutz!) +- Fixed incorrect results when using ArrayBuffers (thanks conref!) +- Added externs/sha.js for Google Closure Compiler users (thanks IvanRF!) + +2.2.0 (2016-07-10) +------------------------- +- Added support for the SHA-3 family of hashes (SHA3-224, SHA3-256, + SHA3-384, SHA3-512, SHAKE128, and SHAKE256) +- Fixed bug with using ARRAYBUFFER as a HMAC key type +- Switched testing framework to Mocha and Chai + +2.1.0 (2016-05-13) +------------------------- +- Added ability to call `update` on hashes between `getHash` and `getHMAC` calls +- Added new input and output type, "ARRAYBUFFER" which is a JavaScript + ArrayBuffer +- Now keeping smaller build files in NPM (thanks vogievetsky!) +- Fixed problem with hashing strings over 4 billion bits (thanks Eicar!) + +2.0.2 (2015-10-31) +------------------------- +- Fixed inability to have a blank "b64Pad" (thanks xlc!) +- Added file hashing test (thanks kofalt!) + +2.0.1 (2015-06-25) +------------------------- +- Fixed major issue with all hashes failing if raw input was a particular size + (thanks treus!) + +2.0.0 (2015-06-13) +------------------------- +- Completely reworked API to support streaming inputs +- Exceptions now throw Errors instead of strings (thanks jclem!) + +1.6.1 (2015-06-25) +------------------------- +- Fixed issue with SHA-512 family of hashes failing is raw input was a + particular size + +1.6.0 (2015-03-08) +------------------------- +This marks the last v1.X new feature release. The API is changing +significantly with upcoming v2.0 to support streaming and it will be too +difficult to support the older API style with new features. + +- Added a BYTES input and output format that is a raw byte string +- Fixed broken AMD support (thanks drewcovi!) +- Fixed broken UTF-8 parsing on non-BMP Unicode characters +- Changed array references to remove warnings on Icedove +- Replaced "UTF16" encoding with "UTF16BE" (big endian) and "UTF16LE" (little + endian) to remove confusion + +1.5.1 (2013-12-15) +------------------------- +- Changed Google Closure Compiler options to produce "strict" compatible code + +1.5 (2013-12-15) +------------------------- +- Added optional numRounds argument to getHash + - Note: this necessitated removing the hash result caching functionality +- Reduced file size by optimizing internal constants +- Removed charSize input and replaced with encoding to handle Unicode. NOTE: + Only Code points up to 0xFFFF are supported. + - charSize = 16 is effectively replaced by encoding = "UTF16" + - charSize = 8 was wrong in terms of handling UTF-8 and has been replaced by + encoding = "UTF8" +- Changed method of referencing "window" to be compatible with WebWorkers, + Node.js, and AMD (thanks piranna!) + +1.42 (2012-12-28) +------------------------- +- Readded v1.4 Safari patch to support older versions + +1.41 (2012-12-23) +------------------------- +- Fixed incorrect hash issue with Chrome x64 v25 (Dev channel), also provides + stable patch to v1.4 Safari issue. + +1.4 (2012-12-08) +------------------------- +- Added new input type, TEXT, that is functionally identical to ASCII* +- Added new input type, B64, for base-64 encoded strings +- Added new input and output formatting parameters + - `getHash` and `getHMAC` take an optional parameter, outputFormatOpts, + that is a hash list containing the keys "outputUpper" (boolean, only + applicable to HEX output) and "b64Pad" (string, only applicable to Base-64 + output) that have default values of false and "=", respectively + - jsSHA constructor takes an optional parameter, charSize (8 or 16) that + specifies the character width of the input (TEXT and ASCII input only) +- Modified comments to be Google Closure Compiler compliant +- Added a SUPPORTED_ALGS flag that, when used with the Google Closure Compiler, + will remove unused functions/function portions + - Removed all src/*_nice.js files as the SUPPORTED_ALGS flag renders them + obsolete +- All production-ready files are now produced using the Google Closure Compiler + with ADVANCED_OPTIMIZATIONS resulting in further reduced filesizes +- The SHA-1 only implementation now requires that that "SHA-1" be specified as + the variant when using getHash and getHMAC +- Removed test/HMAC.py as new NIST tests made the need for it obsolete +- Significantly changed the test/test.html to make it easier to understand and + to allow for easier adding of test cases +- Replaced previous error returning code with thrown exceptions +- Fix for 64-bit Safari issue (thanks Ron Garret and Chris Warren-Smith!) + - NOTE: While this fix works, it is merely a workaround for a WebKit JavaScript + optimizer bug, see https://bugs.webkit.org/show_bug.cgi?id=88673 for more detail + +\* This library misused the term ASCII so input type of TEXT was added with the + intention of deprecating ASCII + +1.31 (2012-07-21) +------------------------- +- Updated project URL to point to new GitHub repository +- Added a compressed version of sha.js + +1.3 (2010-09-01) +------------------------- +- Changed method of declaring objects/classes +- Moved non-instance specific variables and methods to class scope +- Removed logically correct but unneeded conditionals + +1.2 (2009-07-22) +------------------------- +- Added the HMAC algorithm for all supported hashes (using both ASCII and hex + keys) +- As a result of adding HMAC, added support for hash input text to be hex + (ASCII representation of hex) +- Added multiple variants of safeAdd functions, resulting in a significant + performance gain +- Removed wrapper.js file +- Used a different JavaScript compressor resulting in smaller file sizes + +1.11 (2008-12-07) +------------------------- +- Fixed a base-64 encoding issue resulting from a missing capital 'X' + +1.1 (2008-09-25) +------------------------- +- Fixed an issue with incorrect hashes being generated when jsSHA ojbects were + used to generate multiple hashes + +1.0 (2008-09-25) +------------------------- +- Made all functions/variables follow an object-orientated methodology +- Removed support for string hash output as the hash is rarely ASCII friendly +- Changed the interface to calculate hashes (see README) +- Made sha.js validate against [JSLint](http://www.jslint.com/) using + "Recommended" settings + +0.1 (2008-02-21) +------------------------- +- Initial public release diff --git a/frontend/jsSHA/LICENSE b/frontend/jsSHA/LICENSE new file mode 100755 index 0000000..b7a6907 --- /dev/null +++ b/frontend/jsSHA/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2008-2018 Brian Turek, 1998-2009 Paul Johnston & Contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/frontend/jsSHA/README.md b/frontend/jsSHA/README.md new file mode 100755 index 0000000..b49da5b --- /dev/null +++ b/frontend/jsSHA/README.md @@ -0,0 +1,125 @@ +# jsSHA +A pure JavaScript streaming implementation of the complete Secure Hash Standard +family (SHA-1, SHA-224, SHA3-224, SHA-256, SHA3-256, SHA-384, SHA3-384, SHA-512, +SHA3-512, SHAKE128, and SHAKE256) as well as HMAC. + +[![Build Status](https://travis-ci.org/Caligatio/jsSHA.svg?branch=master)](https://travis-ci.org/Caligatio/jsSHA) + +## Usage + +### Installation +#### Browser +Include the desired JavaScript file (sha.js, sha1.js, sha256.js, sha512.js, or +sha3.js) in your header (sha.js used below): + + + +#### Node.js +jsSHA is available through NPM and be installed by simply doing + + npm install jssha + +To use the module, first require it using: + + jsSHA = require("jssha"); + + +### Hashing +Instantiate a new jsSHA object with the desired hash type, input type, and +options as parameters. The hash type can be one of SHA-1, SHA-224, SHA3-224, +SHA-256, SHA3-256, SHA-384, SHA3-384, SHA-512, SHA3-512, SHAKE128, or SHAKE256. +The input type can be one of HEX, TEXT, B64, BYTES, or ARRAYBUFFER. You can +then stream in input using the `update` object function, calling it multiple +times if needed. Finally, simply call `getHash` with the output type as a +parameter (B64, HEX, BYTES, or ARRAYBUFFER). Example to calculate the SHA-512 +of "This is a test": + + var shaObj = new jsSHA("SHA-512", "TEXT"); + shaObj.update("This is a "); + shaObj.update("test"); + var hash = shaObj.getHash("HEX"); + +The constructor takes a hashmap as a optional third argument with possible +properties of `numRounds` and `encoding`. `numRounds` controls the number of +hashing iterations/rounds performed and defaults to a value of 1 if not +specified. `encoding` specifies the encoding used to encode TEXT-type inputs. +Valid options are "UTF8", "UTF16BE", and "UTF16LE", it defaults to "UTF8". + +`getHash` also takes a hashmap as an optional second argument. By default the +hashmap is `{"outputUpper" : false, "b64Pad" : "="}`. These options are +intelligently interpreted based upon the chosen output format. **Important**: +SHAKE128 and SHAKE256 require `shakeLen` to be included in the hashmap where +`shakeLen` is the desired output length of the SHAKE algorithm in a multiple +of 8 bits. + +### HMAC +Instantiate a new jsSHA object the same way as for hashing. Then set the HMAC +key to be used by calling `setHMACKey` with the key and its input type (this +MUST be done before calling update). You can stream in the input using the +`update` object function just like hashing. Finally, get the HMAC by calling +the `getHMAC` function with the output type as its argument. Example to +calculate the SHA-512 HMAC of the string "This is a test" with the key "abc": + + var shaObj = new jsSHA("SHA-512", "TEXT"); + shaObj.setHMACKey("abc", "TEXT"); + shaObj.update("This is a "); + shaObj.update("test"); + var hmac = shaObj.getHMAC("HEX"); + +`setHMACKey` takes the same input types as the constructor and `getHMAC` takes the +same inputs as `getHash` as described above. + +Note: You cannot calculate both the hash and HMAC using the same object. + +## Files +**src/sha\_dev.js** + +A commented implementation of the entire SHA family of hashes. Not to be used +in production. + +**src/sha.js** + +A Google Closure Compiler optimized version of the entire library. + +**src/sha1.js** + +A Google Closure Compiler optimized version the library with non SHA-1 +functionality removed. + +**src/sha256.js** + +A Google Closure Compiler optimized version the library with non SHA-224/SHA-256 +functionality removed. + +**src/sha3.js** + +A Google Closure Compiler optimized version the library with non SHA-3 +functionality removed. + +**src/sha512.js** + +A Google Closure Compiler optimized version the library with non SHA-384/SHA-512 +functionality removed. + +## Compiling +This library makes use of the [Google Closure Compiler](https://developers.google.com/closure/compiler) +to both boost performance and reduce filesizes. To compile sha\_dev.js into a customized output file, +use a command like the following: + + java -jar compiler.jar --define="SUPPORTED_ALGS=" \ + --externs /path/to/build/externs.js --warning_level VERBOSE \ + --compilation_level ADVANCED_OPTIMIZATIONS \ + --js /path/to/sha_dev.js --js_output_file /path/to/sha.js + +where FLAG is a bitwise OR of the following values: + +* 8 for SHA3 +* 4 for SHA-384/SHA-512 +* 2 for SHA-224/256 +* 1 for SHA-1 + +## Contact Info +The project's website is located at [https://caligatio.github.com/jsSHA/](https://caligatio.github.com/jsSHA/) + +## Donations +Feel like donating? We're now accepting donations through [Bitcoin](bitcoin:12VMZgRAP2jCP1YCR3vFNAtLR9MvzHzJZb?message=jsSHA%20Donation)! diff --git a/frontend/jsSHA/bower.json b/frontend/jsSHA/bower.json new file mode 100755 index 0000000..efd981a --- /dev/null +++ b/frontend/jsSHA/bower.json @@ -0,0 +1,51 @@ +{ + "name" : "jsSHA", + "version" : "2.3.1", + "description" : "jsSHA is a JavaScript implementation of the complete Secure Hash Standard family (SHA-1, SHA-224, SHA3-224, SHA-256, SHA3-256, SHA-384, SHA3-384, SHA-512, SHA3-512, SHAKE128, and SHAKE256) as well as HMAC", + "main" : "src/sha.js", + "repository" : { + "type" : "git", + "url" : "https://github.com/Caligatio/jsSHA.git" + }, + "keywords" : [ + "SHA-1", + "SHA-224", + "SHA3-224", + "SHA-256", + "SHA3-256", + "SHA-384", + "SHA3-384", + "SHA-512", + "SHA3-512", + "SHAKE-128", + "SHAKE-256", + "SHAKE128", + "SHAKE256", + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "SHA-2", + "SHA2", + "SHA-3", + "SHA3", + "SHAKE", + "HMAC", + "hash" + ], + "license" : "BSD-3-Clause", + "authors" : [ + "Brian Turek " + ], + "homepage" : "http://caligatio.github.com/jsSHA/", + "ignore": [ + "build", + "test", + "src/sha_dev.js" + ], + "devDependencies": { + "chai": "^3.5.0", + "mocha": "^2.5.3" + } +} diff --git a/frontend/jsSHA/build/externs.js b/frontend/jsSHA/build/externs.js new file mode 100755 index 0000000..cd26d0a --- /dev/null +++ b/frontend/jsSHA/build/externs.js @@ -0,0 +1,5 @@ +/* This file is needed so that the Google Closure Compiler does not complain + * about the module, define, and exports variables being undefined */ +var module = null; +var define = null; +var exports = null; diff --git a/frontend/jsSHA/build/make-release b/frontend/jsSHA/build/make-release new file mode 100755 index 0000000..fca720a --- /dev/null +++ b/frontend/jsSHA/build/make-release @@ -0,0 +1,10 @@ +#!/bin/bash + +declare -A releases +releases=(["sha"]=15 ["sha1"]=1 ["sha256"]=2 ["sha512"]=4 ["sha3"]=8) +CLOSURE_COMPILER=${CLOSURE_COMPILER-"../compiler.jar"} + +for i in "${!releases[@]}" +do + java -jar ${CLOSURE_COMPILER} --define="SUPPORTED_ALGS=${releases[$i]}" --externs externs.js --warning_level VERBOSE --compilation_level ADVANCED_OPTIMIZATIONS --language_in=ECMASCRIPT5_STRICT --js ../src/sha_dev.js --js_output_file ../src/$i.js +done diff --git a/frontend/jsSHA/externs/sha.js b/frontend/jsSHA/externs/sha.js new file mode 100755 index 0000000..56f30e1 --- /dev/null +++ b/frontend/jsSHA/externs/sha.js @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Brian Turek, Ivan Ridao Freitas + * + * Distributed under the BSD License + * See http://caligatio.github.com/jsSHA/ for more information + */ + +/* + * Ensure projects don't execute this file. + */ +if (Math.random() < 1) { // always true but the compiler doesn't know that + throw 'Externs file "sha.js" should not be executed'; +} + + +/** + * @constructor + * @param {string} variant The desired SHA variant (SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA3-224, SHA3-256, SHA3-384, or SHA3-512) + * @param {string} inputFormat The format of srcString: HEX, TEXT, B64, BYTES, or ARRAYBUFFER + * @param {{encoding: (string|undefined), numRounds: (number|undefined)}=} options Optional values + * @return {!jsSHA} + */ +function jsSHA(variant, inputFormat, options) {}; + +/** + * @param {string|ArrayBuffer} key The key used to calculate the HMAC + * @param {string} inputFormat The format of key, HEX, TEXT, B64, BYTES, or ARRAYBUFFER + * @param {{encoding : (string|undefined)}=} options Associative array of input format options + */ +jsSHA.prototype.setHMACKey = function(key, inputFormat, options) {}; + +/** + * @param {string|ArrayBuffer} srcString The string to be hashed + */ +jsSHA.prototype.update = function(srcString) {}; + +/** + * @param {string} format The desired output formatting (B64, HEX, BYTES, or ARRAYBUFFER) + * @param {{outputUpper : (boolean|undefined), b64Pad : (string|undefined), shakeLen : (number|undefined)}=} options Hash list of output formatting options + * @return {string|ArrayBuffer} The string representation of the hash in the format specified. + */ +jsSHA.prototype.getHash = function(format, options) {}; + +/** + * @param {string} format The desired output formatting (B64, HEX, BYTES, or ARRAYBUFFER) + * @param {{outputUpper : (boolean|undefined), b64Pad : (string|undefined), shakeLen : (number|undefined)}=} options associative array of output formatting options + * @return {string|ArrayBuffer} The string representation of the hash in the format specified. + */ +jsSHA.prototype.getHMAC = function(format, options) {}; \ No newline at end of file diff --git a/frontend/jsSHA/package.json b/frontend/jsSHA/package.json new file mode 100755 index 0000000..e050c64 --- /dev/null +++ b/frontend/jsSHA/package.json @@ -0,0 +1,54 @@ +{ + "name": "jssha", + "version": "2.3.1", + "description": "jsSHA is a JavaScript implementation of the complete Secure Hash Standard family (SHA-1, SHA-224, SHA3-224, SHA-256, SHA3-256, SHA-384, SHA3-384, SHA-512, SHA3-512, SHAKE128, and SHAKE256) as well as HMAC", + "main": "src/sha.js", + "repository": { + "type": "git", + "url": "https://github.com/Caligatio/jsSHA.git" + }, + "keywords": [ + "SHA-1", + "SHA-224", + "SHA3-224", + "SHA-256", + "SHA3-256", + "SHA-384", + "SHA3-384", + "SHA-512", + "SHA3-512", + "SHAKE-128", + "SHAKE-256", + "SHAKE128", + "SHAKE256", + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "SHA-2", + "SHA2", + "SHA-3", + "SHA3", + "SHAKE", + "HMAC", + "hash" + ], + "license": "BSD-3-Clause", + "author": "Brian Turek ", + "bugs": { + "url": "https://github.com/Caligatio/jsSHA/issues" + }, + "engines": { + "node": "*" + }, + "homepage": "https://github.com/Caligatio/jsSHA", + "dependencies": {}, + "devDependencies": { + "chai": "^3.5.0", + "mocha": "^2.5.3" + }, + "scripts": { + "test": "mocha --reporter spec" + } +} diff --git a/frontend/jsSHA/src/sha.js b/frontend/jsSHA/src/sha.js new file mode 100755 index 0000000..1ecd2e5 --- /dev/null +++ b/frontend/jsSHA/src/sha.js @@ -0,0 +1,43 @@ +/* + A JavaScript implementation of the SHA family of hashes, as + defined in FIPS PUB 180-4 and FIPS PUB 202, as well as the corresponding + HMAC implementation as defined in FIPS PUB 198a + + Copyright 2008-2018 Brian Turek, 1998-2009 Paul Johnston & Contributors + Distributed under the BSD License + See http://caligatio.github.com/jsSHA/ for more information +*/ +'use strict';(function(Y){function C(c,a,b){var e=0,h=[],n=0,g,l,d,f,m,q,u,r,I=!1,v=[],w=[],t,y=!1,z=!1,x=-1;b=b||{};g=b.encoding||"UTF8";t=b.numRounds||1;if(t!==parseInt(t,10)||1>t)throw Error("numRounds must a integer >= 1");if("SHA-1"===c)m=512,q=K,u=Z,f=160,r=function(a){return a.slice()};else if(0===c.lastIndexOf("SHA-",0))if(q=function(a,b){return L(a,b,c)},u=function(a,b,h,e){var k,f;if("SHA-224"===c||"SHA-256"===c)k=(b+65>>>9<<4)+15,f=16;else if("SHA-384"===c||"SHA-512"===c)k=(b+129>>>10<< +5)+31,f=32;else throw Error("Unexpected error in SHA-2 implementation");for(;a.length<=k;)a.push(0);a[b>>>5]|=128<<24-b%32;b=b+h;a[k]=b&4294967295;a[k-1]=b/4294967296|0;h=a.length;for(b=0;be;e+=1)c[e]=a[e].slice();return c};x=1;if("SHA3-224"=== +c)m=1152,f=224;else if("SHA3-256"===c)m=1088,f=256;else if("SHA3-384"===c)m=832,f=384;else if("SHA3-512"===c)m=576,f=512;else if("SHAKE128"===c)m=1344,f=-1,F=31,z=!0;else if("SHAKE256"===c)m=1088,f=-1,F=31,z=!0;else throw Error("Chosen SHA variant is not supported");u=function(a,c,e,b,h){e=m;var k=F,f,g=[],n=e>>>5,l=0,d=c>>>5;for(f=0;f=e;f+=n)b=D(a.slice(f,f+n),b),c-=e;a=a.slice(f);for(c%=e;a.length>>3;a[f>>2]^=k<=h)break;g.push(a.a);l+=1;0===64*l%e&&D(null,b)}return g}}else throw Error("Chosen SHA variant is not supported");d=M(a,g,x);l=A(c);this.setHMACKey=function(a,b,h){var k;if(!0===I)throw Error("HMAC key already set");if(!0===y)throw Error("Cannot set HMAC key after calling update");if(!0===z)throw Error("SHAKE is not supported for HMAC");g=(h||{}).encoding||"UTF8";b=M(b,g,x)(a);a=b.binLen;b=b.value;k=m>>>3;h=k/4-1;if(ka/8){for(;b.length<=h;)b.push(0);b[h]&=4294967040}for(a=0;a<=h;a+=1)v[a]=b[a]^909522486,w[a]=b[a]^1549556828;l=q(v,l);e=m;I=!0};this.update=function(a){var c,b,k,f=0,g=m>>>5;c=d(a,h,n);a=c.binLen;b=c.value;c=a>>>5;for(k=0;k>>5);n=a%m;y=!0};this.getHash=function(a,b){var k,g,d,m;if(!0===I)throw Error("Cannot call getHash after setting HMAC key");d=N(b);if(!0===z){if(-1===d.shakeLen)throw Error("shakeLen must be specified in options"); +f=d.shakeLen}switch(a){case "HEX":k=function(a){return O(a,f,x,d)};break;case "B64":k=function(a){return P(a,f,x,d)};break;case "BYTES":k=function(a){return Q(a,f,x)};break;case "ARRAYBUFFER":try{g=new ArrayBuffer(0)}catch(p){throw Error("ARRAYBUFFER not supported by this environment");}k=function(a){return R(a,f,x)};break;default:throw Error("format must be HEX, B64, BYTES, or ARRAYBUFFER");}m=u(h.slice(),n,e,r(l),f);for(g=1;g>>24-f%32),m=u(m,f, +0,A(c),f);return k(m)};this.getHMAC=function(a,b){var k,g,d,p;if(!1===I)throw Error("Cannot call getHMAC without first setting HMAC key");d=N(b);switch(a){case "HEX":k=function(a){return O(a,f,x,d)};break;case "B64":k=function(a){return P(a,f,x,d)};break;case "BYTES":k=function(a){return Q(a,f,x)};break;case "ARRAYBUFFER":try{k=new ArrayBuffer(0)}catch(v){throw Error("ARRAYBUFFER not supported by this environment");}k=function(a){return R(a,f,x)};break;default:throw Error("outputFormat must be HEX, B64, BYTES, or ARRAYBUFFER"); +}g=u(h.slice(),n,e,r(l),f);p=q(w,A(c));p=u(g,f,m,p,f);return k(p)}}function b(c,a){this.a=c;this.b=a}function O(c,a,b,e){var h="";a/=8;var n,g,d;d=-1===b?3:0;for(n=0;n>>2]>>>8*(d+n%4*b),h+="0123456789abcdef".charAt(g>>>4&15)+"0123456789abcdef".charAt(g&15);return e.outputUpper?h.toUpperCase():h}function P(c,a,b,e){var h="",n=a/8,g,d,p,f;f=-1===b?3:0;for(g=0;g>>2]:0,p=g+2>>2]:0,p=(c[g>>>2]>>>8*(f+g%4*b)&255)<<16|(d>>>8*(f+(g+1)%4*b)&255)<<8|p>>>8*(f+ +(g+2)%4*b)&255,d=0;4>d;d+=1)8*g+6*d<=a?h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(p>>>6*(3-d)&63):h+=e.b64Pad;return h}function Q(c,a,b){var e="";a/=8;var h,d,g;g=-1===b?3:0;for(h=0;h>>2]>>>8*(g+h%4*b)&255,e+=String.fromCharCode(d);return e}function R(c,a,b){a/=8;var e,h=new ArrayBuffer(a),d,g;g=new Uint8Array(h);d=-1===b?3:0;for(e=0;e>>2]>>>8*(d+e%4*b)&255;return h}function N(c){var a={outputUpper:!1,b64Pad:"=",shakeLen:-1};c=c||{}; +a.outputUpper=c.outputUpper||!1;!0===c.hasOwnProperty("b64Pad")&&(a.b64Pad=c.b64Pad);if(!0===c.hasOwnProperty("shakeLen")){if(0!==c.shakeLen%8)throw Error("shakeLen must be a multiple of 8");a.shakeLen=c.shakeLen}if("boolean"!==typeof a.outputUpper)throw Error("Invalid outputUpper formatting option");if("string"!==typeof a.b64Pad)throw Error("Invalid b64Pad formatting option");return a}function M(c,a,b){switch(a){case "UTF8":case "UTF16BE":case "UTF16LE":break;default:throw Error("encoding must be UTF8, UTF16BE, or UTF16LE"); +}switch(c){case "HEX":c=function(a,c,d){var g=a.length,l,p,f,m,q,u;if(0!==g%2)throw Error("String of HEX type must be in byte increments");c=c||[0];d=d||0;q=d>>>3;u=-1===b?3:0;for(l=0;l>>1)+q;for(f=m>>>2;c.length<=f;)c.push(0);c[f]|=p<<8*(u+m%4*b)}return{value:c,binLen:4*g+d}};break;case "TEXT":c=function(c,h,d){var g,l,p=0,f,m,q,u,r,t;h=h||[0];d=d||0;q=d>>>3;if("UTF8"===a)for(t=-1=== +b?3:0,f=0;fg?l.push(g):2048>g?(l.push(192|g>>>6),l.push(128|g&63)):55296>g||57344<=g?l.push(224|g>>>12,128|g>>>6&63,128|g&63):(f+=1,g=65536+((g&1023)<<10|c.charCodeAt(f)&1023),l.push(240|g>>>18,128|g>>>12&63,128|g>>>6&63,128|g&63)),m=0;m>>2;h.length<=u;)h.push(0);h[u]|=l[m]<<8*(t+r%4*b);p+=1}else if("UTF16BE"===a||"UTF16LE"===a)for(t=-1===b?2:0,l="UTF16LE"===a&&1!==b||"UTF16LE"!==a&&1===b,f=0;f>>8);r=p+q;for(u=r>>>2;h.length<=u;)h.push(0);h[u]|=g<<8*(t+r%4*b);p+=2}return{value:h,binLen:8*p+d}};break;case "B64":c=function(a,c,d){var g=0,l,p,f,m,q,u,r,t;if(-1===a.search(/^[a-zA-Z0-9=+\/]+$/))throw Error("Invalid character in base-64 string");p=a.indexOf("=");a=a.replace(/\=/g,"");if(-1!==p&&pv)throw Error("numRounds must a integer >= 1");if("SHA-1"===d)l=512,p=z,q=H,e=160,t=function(a){return a.slice()};else throw Error("Chosen SHA variant is not supported");k=A(b,g);m=x(d);this.setHMACKey=function(a,f,b){var c;if(!0===w)throw Error("HMAC key already set");if(!0===r)throw Error("Cannot set HMAC key after calling update"); +g=(b||{}).encoding||"UTF8";f=A(f,g)(a);a=f.binLen;f=f.value;c=l>>>3;b=c/4-1;if(ca/8){for(;f.length<=b;)f.push(0);f[b]&=4294967040}for(a=0;a<=b;a+=1)n[a]=f[a]^909522486,u[a]=f[a]^1549556828;m=p(n,m);h=l;w=!0};this.update=function(b){var e,g,c,d=0,q=l>>>5;e=k(b,a,f);b=e.binLen;g=e.value;e=b>>>5;for(c=0;c>>5);f=b%l;r=!0};this.getHash=function(b,g){var c,k,l,p;if(!0=== +w)throw Error("Cannot call getHash after setting HMAC key");l=B(g);switch(b){case "HEX":c=function(a){return C(a,e,l)};break;case "B64":c=function(a){return D(a,e,l)};break;case "BYTES":c=function(a){return E(a,e)};break;case "ARRAYBUFFER":try{k=new ArrayBuffer(0)}catch(I){throw Error("ARRAYBUFFER not supported by this environment");}c=function(a){return F(a,e)};break;default:throw Error("format must be HEX, B64, BYTES, or ARRAYBUFFER");}p=q(a.slice(),f,h,t(m),e);for(k=1;k>>2]>>>8*(3+a%4*-1),h+="0123456789abcdef".charAt(f>>>4&15)+"0123456789abcdef".charAt(f&15);return c.outputUpper?h.toUpperCase():h}function D(d,b,c){var h="",a=b/8,f,g,m;for(f=0;f>>2]:0,m=f+2>>2]:0,m=(d[f>>>2]>>>8*(3+f%4*-1)&255)<<16|(g>>>8*(3+(f+1)%4*-1)&255)<<8|m>>>8*(3+(f+2)%4*-1)&255,g=0;4>g;g+=1)8*f+6*g<=b?h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(m>>> +6*(3-g)&63):h+=c.b64Pad;return h}function E(d,b){var c="",h=b/8,a,f;for(a=0;a>>2]>>>8*(3+a%4*-1)&255,c+=String.fromCharCode(f);return c}function F(d,b){var c=b/8,h,a=new ArrayBuffer(c),f;f=new Uint8Array(a);for(h=0;h>>2]>>>8*(3+h%4*-1)&255;return a}function B(d){var b={outputUpper:!1,b64Pad:"=",shakeLen:-1};d=d||{};b.outputUpper=d.outputUpper||!1;!0===d.hasOwnProperty("b64Pad")&&(b.b64Pad=d.b64Pad);if("boolean"!==typeof b.outputUpper)throw Error("Invalid outputUpper formatting option"); +if("string"!==typeof b.b64Pad)throw Error("Invalid b64Pad formatting option");return b}function A(d,b){var c;switch(b){case "UTF8":case "UTF16BE":case "UTF16LE":break;default:throw Error("encoding must be UTF8, UTF16BE, or UTF16LE");}switch(d){case "HEX":c=function(b,a,f){var g=b.length,c,d,e,l,p;if(0!==g%2)throw Error("String of HEX type must be in byte increments");a=a||[0];f=f||0;p=f>>>3;for(c=0;c>>1)+p;for(e=l>>>2;a.length<=e;)a.push(0);a[e]|=d<<8*(3+l%4*-1)}return{value:a,binLen:4*g+f}};break;case "TEXT":c=function(c,a,f){var g,d,k=0,e,l,p,q,t,n;a=a||[0];f=f||0;p=f>>>3;if("UTF8"===b)for(n=3,e=0;eg?d.push(g):2048>g?(d.push(192|g>>>6),d.push(128|g&63)):55296>g||57344<=g?d.push(224|g>>>12,128|g>>>6&63,128|g&63):(e+=1,g=65536+((g&1023)<<10|c.charCodeAt(e)&1023),d.push(240|g>>>18,128|g>>>12&63,128|g>>>6&63,128|g&63)),l=0;l>>2;a.length<=q;)a.push(0);a[q]|=d[l]<<8*(n+t%4*-1);k+=1}else if("UTF16BE"===b||"UTF16LE"===b)for(n=2,d="UTF16LE"===b&&!0||"UTF16LE"!==b&&!1,e=0;e>>8);t=k+p;for(q=t>>>2;a.length<=q;)a.push(0);a[q]|=g<<8*(n+t%4*-1);k+=2}return{value:a,binLen:8*k+f}};break;case "B64":c=function(b,a,f){var c=0,d,k,e,l,p,q,n;if(-1===b.search(/^[a-zA-Z0-9=+\/]+$/))throw Error("Invalid character in base-64 string");k=b.indexOf("=");b=b.replace(/\=/g, +"");if(-1!==k&&ku)throw Error("numRounds must a integer >= 1");if(0===c.lastIndexOf("SHA-",0))if(q=function(b,a){return A(b,a,c)},y=function(b,a,l,f){var g,e;if("SHA-224"===c||"SHA-256"===c)g=(a+65>>>9<<4)+15,e=16;else throw Error("Unexpected error in SHA-2 implementation");for(;b.length<=g;)b.push(0);b[a>>>5]|=128<<24-a%32;a=a+l;b[g]=a&4294967295; +b[g-1]=a/4294967296|0;l=b.length;for(a=0;a>>3;g=e/4-1;if(eb/8){for(;a.length<=g;)a.push(0);a[g]&=4294967040}for(b=0;b<=g;b+=1)t[b]=a[b]^909522486,r[b]=a[b]^1549556828;n=q(t,n);l=h;m=!0};this.update=function(a){var c,f,e,d=0,p=h>>>5;c=k(a,b,g);a=c.binLen;f=c.value;c=a>>>5;for(e=0;e>> +5);g=a%h;z=!0};this.getHash=function(a,f){var d,h,k,q;if(!0===m)throw Error("Cannot call getHash after setting HMAC key");k=C(f);switch(a){case "HEX":d=function(a){return D(a,e,k)};break;case "B64":d=function(a){return E(a,e,k)};break;case "BYTES":d=function(a){return F(a,e)};break;case "ARRAYBUFFER":try{h=new ArrayBuffer(0)}catch(v){throw Error("ARRAYBUFFER not supported by this environment");}d=function(a){return G(a,e)};break;default:throw Error("format must be HEX, B64, BYTES, or ARRAYBUFFER"); +}q=y(b.slice(),g,l,p(n));for(h=1;h>>2]>>>8*(3+b%4*-1),l+="0123456789abcdef".charAt(g>>>4&15)+"0123456789abcdef".charAt(g&15);return d.outputUpper?l.toUpperCase():l}function E(c,a,d){var l="",b=a/8,g,f,n;for(g=0;g>>2]:0,n=g+2>>2]:0,n=(c[g>>>2]>>>8*(3+g%4*-1)&255)<<16|(f>>>8*(3+(g+1)%4*-1)&255)<<8|n>>>8*(3+(g+2)%4*-1)&255,f=0;4>f;f+=1)8*g+6*f<=a?l+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(n>>> +6*(3-f)&63):l+=d.b64Pad;return l}function F(c,a){var d="",l=a/8,b,g;for(b=0;b>>2]>>>8*(3+b%4*-1)&255,d+=String.fromCharCode(g);return d}function G(c,a){var d=a/8,l,b=new ArrayBuffer(d),g;g=new Uint8Array(b);for(l=0;l>>2]>>>8*(3+l%4*-1)&255;return b}function C(c){var a={outputUpper:!1,b64Pad:"=",shakeLen:-1};c=c||{};a.outputUpper=c.outputUpper||!1;!0===c.hasOwnProperty("b64Pad")&&(a.b64Pad=c.b64Pad);if("boolean"!==typeof a.outputUpper)throw Error("Invalid outputUpper formatting option"); +if("string"!==typeof a.b64Pad)throw Error("Invalid b64Pad formatting option");return a}function B(c,a){var d;switch(a){case "UTF8":case "UTF16BE":case "UTF16LE":break;default:throw Error("encoding must be UTF8, UTF16BE, or UTF16LE");}switch(c){case "HEX":d=function(a,b,c){var f=a.length,d,k,e,h,q;if(0!==f%2)throw Error("String of HEX type must be in byte increments");b=b||[0];c=c||0;q=c>>>3;for(d=0;d>>1)+q;for(e=h>>>2;b.length<=e;)b.push(0);b[e]|=k<<8*(3+h%4*-1)}return{value:b,binLen:4*f+c}};break;case "TEXT":d=function(c,b,d){var f,n,k=0,e,h,q,m,p,r;b=b||[0];d=d||0;q=d>>>3;if("UTF8"===a)for(r=3,e=0;ef?n.push(f):2048>f?(n.push(192|f>>>6),n.push(128|f&63)):55296>f||57344<=f?n.push(224|f>>>12,128|f>>>6&63,128|f&63):(e+=1,f=65536+((f&1023)<<10|c.charCodeAt(e)&1023),n.push(240|f>>>18,128|f>>>12&63,128|f>>>6&63,128|f&63)),h=0;h>>2;b.length<=m;)b.push(0);b[m]|=n[h]<<8*(r+p%4*-1);k+=1}else if("UTF16BE"===a||"UTF16LE"===a)for(r=2,n="UTF16LE"===a&&!0||"UTF16LE"!==a&&!1,e=0;e>>8);p=k+q;for(m=p>>>2;b.length<=m;)b.push(0);b[m]|=f<<8*(r+p%4*-1);k+=2}return{value:b,binLen:8*k+d}};break;case "B64":d=function(a,b,c){var f=0,d,k,e,h,q,m,p;if(-1===a.search(/^[a-zA-Z0-9=+\/]+$/))throw Error("Invalid character in base-64 string");k=a.indexOf("=");a=a.replace(/\=/g, +"");if(-1!==k&&kw)throw Error("numRounds must a integer >= 1");if(0===d.lastIndexOf("SHA3-",0)||0===d.lastIndexOf("SHAKE",0)){var C=6;f=B;v=function(c){var a=[],e;for(e=0;5>e;e+=1)a[e]=c[e].slice();return a};t=1;if("SHA3-224"===d)k=1152,g=224;else if("SHA3-256"===d)k=1088,g=256;else if("SHA3-384"===d)k=832,g=384;else if("SHA3-512"===d)k= +576,g=512;else if("SHAKE128"===d)k=1344,g=-1,C=31,x=!0;else if("SHAKE256"===d)k=1088,g=-1,C=31,x=!0;else throw Error("Chosen SHA variant is not supported");p=function(c,a,e,g,d){e=k;var b=C,m,l=[],f=e>>>5,h=0,r=a>>>5;for(m=0;m=e;m+=f)g=B(c.slice(m,m+f),g),a-=e;c=c.slice(m);for(a%=e;c.length>>3;c[m>>2]^=b<=d)break;l.push(c.a);h+=1;0===64*h%e&&B(null,g)}return l}}else throw Error("Chosen SHA variant is not supported"); +r=D(b,e,t);m=y(d);this.setHMACKey=function(a,b,l){var h;if(!0===A)throw Error("HMAC key already set");if(!0===z)throw Error("Cannot set HMAC key after calling update");if(!0===x)throw Error("SHAKE is not supported for HMAC");e=(l||{}).encoding||"UTF8";b=D(b,e,t)(a);a=b.binLen;b=b.value;h=k>>>3;l=h/4-1;if(ha/8){for(;b.length<=l;)b.push(0);b[l]&=4294967040}for(a=0;a<=l;a+=1)n[a]=b[a]^909522486,u[a]=b[a]^1549556828;m=f(n,m); +c=k;A=!0};this.update=function(e){var b,g,d,h=0,p=k>>>5;b=r(e,a,l);e=b.binLen;g=b.value;b=e>>>5;for(d=0;d>>5);l=e%k;z=!0};this.getHash=function(e,b){var h,f,r,k;if(!0===A)throw Error("Cannot call getHash after setting HMAC key");r=E(b);if(!0===x){if(-1===r.shakeLen)throw Error("shakeLen must be specified in options");g=r.shakeLen}switch(e){case "HEX":h=function(a){return F(a,g,t,r)};break;case "B64":h=function(a){return G(a,g,t,r)};break; +case "BYTES":h=function(a){return H(a,g,t)};break;case "ARRAYBUFFER":try{f=new ArrayBuffer(0)}catch(q){throw Error("ARRAYBUFFER not supported by this environment");}h=function(a){return I(a,g,t)};break;default:throw Error("format must be HEX, B64, BYTES, or ARRAYBUFFER");}k=p(a.slice(),l,c,v(m),g);for(f=1;f>>24-g%32),k=p(k,g,0,y(d),g);return h(k)};this.getHMAC=function(e,b){var h,r,n,w;if(!1===A)throw Error("Cannot call getHMAC without first setting HMAC key"); +n=E(b);switch(e){case "HEX":h=function(a){return F(a,g,t,n)};break;case "B64":h=function(a){return G(a,g,t,n)};break;case "BYTES":h=function(a){return H(a,g,t)};break;case "ARRAYBUFFER":try{h=new ArrayBuffer(0)}catch(M){throw Error("ARRAYBUFFER not supported by this environment");}h=function(a){return I(a,g,t)};break;default:throw Error("outputFormat must be HEX, B64, BYTES, or ARRAYBUFFER");}r=p(a.slice(),l,c,v(m),g);w=f(u,y(d));w=p(r,g,k,w,g);return h(w)}}function f(d,b){this.a=d;this.b=b}function F(d, +b,h,c){var a="";b/=8;var l,e,m;m=-1===h?3:0;for(l=0;l>>2]>>>8*(m+l%4*h),a+="0123456789abcdef".charAt(e>>>4&15)+"0123456789abcdef".charAt(e&15);return c.outputUpper?a.toUpperCase():a}function G(d,b,h,c){var a="",l=b/8,e,m,f,g;g=-1===h?3:0;for(e=0;e>>2]:0,f=e+2>>2]:0,f=(d[e>>>2]>>>8*(g+e%4*h)&255)<<16|(m>>>8*(g+(e+1)%4*h)&255)<<8|f>>>8*(g+(e+2)%4*h)&255,m=0;4>m;m+=1)8*e+6*m<=b?a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(f>>> +6*(3-m)&63):a+=c.b64Pad;return a}function H(d,b,h){var c="";b/=8;var a,l,e;e=-1===h?3:0;for(a=0;a>>2]>>>8*(e+a%4*h)&255,c+=String.fromCharCode(l);return c}function I(d,b,h){b/=8;var c,a=new ArrayBuffer(b),l,e;e=new Uint8Array(a);l=-1===h?3:0;for(c=0;c>>2]>>>8*(l+c%4*h)&255;return a}function E(d){var b={outputUpper:!1,b64Pad:"=",shakeLen:-1};d=d||{};b.outputUpper=d.outputUpper||!1;!0===d.hasOwnProperty("b64Pad")&&(b.b64Pad=d.b64Pad);if(!0===d.hasOwnProperty("shakeLen")){if(0!== +d.shakeLen%8)throw Error("shakeLen must be a multiple of 8");b.shakeLen=d.shakeLen}if("boolean"!==typeof b.outputUpper)throw Error("Invalid outputUpper formatting option");if("string"!==typeof b.b64Pad)throw Error("Invalid b64Pad formatting option");return b}function D(d,b,h){switch(b){case "UTF8":case "UTF16BE":case "UTF16LE":break;default:throw Error("encoding must be UTF8, UTF16BE, or UTF16LE");}switch(d){case "HEX":d=function(c,a,b){var e=c.length,d,f,g,k,q,p;if(0!==e%2)throw Error("String of HEX type must be in byte increments"); +a=a||[0];b=b||0;q=b>>>3;p=-1===h?3:0;for(d=0;d>>1)+q;for(g=k>>>2;a.length<=g;)a.push(0);a[g]|=f<<8*(p+k%4*h)}return{value:a,binLen:4*e+b}};break;case "TEXT":d=function(c,a,d){var e,m,f=0,g,k,q,p,v,n;a=a||[0];d=d||0;q=d>>>3;if("UTF8"===b)for(n=-1===h?3:0,g=0;ge?m.push(e):2048>e?(m.push(192|e>>>6),m.push(128|e&63)):55296>e||57344<=e?m.push(224| +e>>>12,128|e>>>6&63,128|e&63):(g+=1,e=65536+((e&1023)<<10|c.charCodeAt(g)&1023),m.push(240|e>>>18,128|e>>>12&63,128|e>>>6&63,128|e&63)),k=0;k>>2;a.length<=p;)a.push(0);a[p]|=m[k]<<8*(n+v%4*h);f+=1}else if("UTF16BE"===b||"UTF16LE"===b)for(n=-1===h?2:0,m="UTF16LE"===b&&1!==h||"UTF16LE"!==b&&1===h,g=0;g>>8);v=f+q;for(p=v>>>2;a.length<=p;)a.push(0);a[p]|=e<<8*(n+v%4*h);f+=2}return{value:a,binLen:8*f+d}};break;case "B64":d= +function(c,a,b){var e=0,d,f,g,k,q,p,n,u;if(-1===c.search(/^[a-zA-Z0-9=+\/]+$/))throw Error("Invalid character in base-64 string");f=c.indexOf("=");c=c.replace(/\=/g,"");if(-1!==f&&fv)throw Error("numRounds must a integer >= 1");if(0===b.lastIndexOf("SHA-",0))if(p=function(a,d){return B(a,d,b)},t=function(a,d,g,e){var c,k;if("SHA-384"===b||"SHA-512"===b)c=(d+129>>>10<<5)+31,k=32;else throw Error("Unexpected error in SHA-2 implementation");for(;a.length<=c;)a.push(0);a[d>>>5]|=128<<24-d%32;d=d+g;a[c]=d&4294967295; +a[c-1]=d/4294967296|0;g=a.length;for(d=0;d>>3;g=k/4-1;if(ka/8){for(;d.length<=g;)d.push(0);d[g]&=4294967040}for(a=0;a<=g;a+=1)u[a]=d[a]^909522486,r[a]=d[a]^1549556828;c=p(u,c);e=l;y= +!0};this.update=function(a){var d,b,n,f=0,h=l>>>5;d=m(a,g,k);a=d.binLen;b=d.value;d=a>>>5;for(n=0;n>>5);k=a%l;A=!0};this.getHash=function(a,d){var f,l,m,p;if(!0===y)throw Error("Cannot call getHash after setting HMAC key");m=D(d);switch(a){case "HEX":f=function(a){return E(a,h,m)};break;case "B64":f=function(a){return F(a,h,m)};break;case "BYTES":f=function(a){return G(a,h)};break;case "ARRAYBUFFER":try{l=new ArrayBuffer(0)}catch(w){throw Error("ARRAYBUFFER not supported by this environment"); +}f=function(a){return H(a,h)};break;default:throw Error("format must be HEX, B64, BYTES, or ARRAYBUFFER");}p=t(g.slice(),k,e,q(c));for(l=1;l>>2]>>>8*(3+g%4*-1),e+="0123456789abcdef".charAt(k>>>4&15)+"0123456789abcdef".charAt(k&15);return d.outputUpper?e.toUpperCase():e}function F(b,a,d){var e="",g=a/8,k,f,c;for(k=0;k>>2]:0,c=k+2>>2]: +0,c=(b[k>>>2]>>>8*(3+k%4*-1)&255)<<16|(f>>>8*(3+(k+1)%4*-1)&255)<<8|c>>>8*(3+(k+2)%4*-1)&255,f=0;4>f;f+=1)8*k+6*f<=a?e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(c>>>6*(3-f)&63):e+=d.b64Pad;return e}function G(b,a){var d="",e=a/8,g,c;for(g=0;g>>2]>>>8*(3+g%4*-1)&255,d+=String.fromCharCode(c);return d}function H(b,a){var d=a/8,e,g=new ArrayBuffer(d),c;c=new Uint8Array(g);for(e=0;e>>2]>>>8*(3+e%4*-1)&255;return g}function D(b){var a={outputUpper:!1, +b64Pad:"=",shakeLen:-1};b=b||{};a.outputUpper=b.outputUpper||!1;!0===b.hasOwnProperty("b64Pad")&&(a.b64Pad=b.b64Pad);if("boolean"!==typeof a.outputUpper)throw Error("Invalid outputUpper formatting option");if("string"!==typeof a.b64Pad)throw Error("Invalid b64Pad formatting option");return a}function C(b,a){var d;switch(a){case "UTF8":case "UTF16BE":case "UTF16LE":break;default:throw Error("encoding must be UTF8, UTF16BE, or UTF16LE");}switch(b){case "HEX":d=function(a,b,d){var f=a.length,c,n,h,l, +p;if(0!==f%2)throw Error("String of HEX type must be in byte increments");b=b||[0];d=d||0;p=d>>>3;for(c=0;c>>1)+p;for(h=l>>>2;b.length<=h;)b.push(0);b[h]|=n<<8*(3+l%4*-1)}return{value:b,binLen:4*f+d}};break;case "TEXT":d=function(b,d,c){var f,n,m=0,h,l,p,t,q,r;d=d||[0];c=c||0;p=c>>>3;if("UTF8"===a)for(r=3,h=0;hf?n.push(f):2048>f?(n.push(192| +f>>>6),n.push(128|f&63)):55296>f||57344<=f?n.push(224|f>>>12,128|f>>>6&63,128|f&63):(h+=1,f=65536+((f&1023)<<10|b.charCodeAt(h)&1023),n.push(240|f>>>18,128|f>>>12&63,128|f>>>6&63,128|f&63)),l=0;l>>2;d.length<=t;)d.push(0);d[t]|=n[l]<<8*(r+q%4*-1);m+=1}else if("UTF16BE"===a||"UTF16LE"===a)for(r=2,n="UTF16LE"===a&&!0||"UTF16LE"!==a&&!1,h=0;h>>8);q=m+p;for(t=q>>>2;d.length<=t;)d.push(0);d[t]|=f<<8*(r+q%4*-1);m+= +2}return{value:d,binLen:8*m+c}};break;case "B64":d=function(a,b,d){var c=0,n,m,h,l,p,t,q;if(-1===a.search(/^[a-zA-Z0-9=+\/]+$/))throw Error("Invalid character in base-64 string");m=a.indexOf("=");a=a.replace(/\=/g,"");if(-1!==m&&m>> 3; + shiftModifier = (bigEndianMod === -1) ? 3 : 0; + + for (i = 0; i < str.length; i += 4) + { + strPart = str.substr(i, 4); + tmpInt = 0; + + for (j = 0; j < strPart.length; j += 1) + { + index = b64Tab.indexOf(strPart[j]); + tmpInt |= index << (18 - (6 * j)); + } + + for (j = 0; j < strPart.length - 1; j += 1) + { + byteOffset = byteCnt + existingByteLen; + intOffset = byteOffset >>> 2; + while (packed.length <= intOffset) + { + packed.push(0); + } + packed[intOffset] |= ((tmpInt >>> (16 - (j * 8))) & 0xFF) << + (8 * (shiftModifier + bigEndianMod * (byteOffset % 4))); + byteCnt += 1; + } + } + + return {"value" : packed, "binLen" : byteCnt * 8 + existingPackedLen}; + } + + /** + * Convert an ArrayBuffer to an array of big-endian words + * + * @private + * @param {ArrayBuffer} arr ArrayBuffer to be converted to binary + * representation + * @param {Array} existingPacked A packed int array of bytes to + * append the results to + * @param {number} existingPackedLen The number of bits in the existingPacked + * array + * @param {number} bigEndianMod Modifier for whether hash function is + * big or small endian + * @return {{value : Array, binLen : number}} Hash list where + * "value" contains the output number array and "binLen" is the binary + * length of "value" + */ + function arraybuffer2packed(arr, existingPacked, existingPackedLen, bigEndianMod) + { + var packed, i, existingByteLen, intOffset, byteOffset, shiftModifier, arrView; + + packed = existingPacked || [0]; + existingPackedLen = existingPackedLen || 0; + existingByteLen = existingPackedLen >>> 3; + shiftModifier = (bigEndianMod === -1) ? 3 : 0; + arrView = new Uint8Array(arr); + + for (i = 0; i < arr.byteLength; i += 1) + { + byteOffset = i + existingByteLen; + intOffset = byteOffset >>> 2; + if (packed.length <= intOffset) + { + packed.push(0); + } + packed[intOffset] |= arrView[i] << (8 * (shiftModifier + bigEndianMod * (byteOffset % 4))); + } + + return {"value" : packed, "binLen" : arr.byteLength * 8 + existingPackedLen}; + } + + /** + * Convert an array of big-endian words to a hex string. + * + * @private + * @param {Array} packed Array of integers to be converted to + * hexidecimal representation + * @param {number} outputLength Length of output in bits + * @param {number} bigEndianMod Modifier for whether hash function is + * big or small endian + * @param {{outputUpper : boolean, b64Pad : string}} formatOpts Hash list + * containing validated output formatting options + * @return {string} Hexidecimal representation of the parameter in string + * form + */ + function packed2hex(packed, outputLength, bigEndianMod, formatOpts) + { + var hex_tab = "0123456789abcdef", str = "", + length = outputLength / 8, i, srcByte, shiftModifier; + + shiftModifier = (bigEndianMod === -1) ? 3 : 0; + + for (i = 0; i < length; i += 1) + { + /* The below is more than a byte but it gets taken care of later */ + srcByte = packed[i >>> 2] >>> (8 * (shiftModifier + bigEndianMod * (i % 4))); + str += hex_tab.charAt((srcByte >>> 4) & 0xF) + + hex_tab.charAt(srcByte & 0xF); + } + + return (formatOpts["outputUpper"]) ? str.toUpperCase() : str; + } + + /** + * Convert an array of big-endian words to a base-64 string + * + * @private + * @param {Array} packed Array of integers to be converted to + * base-64 representation + * @param {number} outputLength Length of output in bits + * @param {number} bigEndianMod Modifier for whether hash function is + * big or small endian + * @param {{outputUpper : boolean, b64Pad : string}} formatOpts Hash list + * containing validated output formatting options + * @return {string} Base-64 encoded representation of the parameter in + * string form + */ + function packed2b64(packed, outputLength, bigEndianMod, formatOpts) + { + var str = "", length = outputLength / 8, i, j, triplet, int1, int2, shiftModifier, + b64Tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + shiftModifier = (bigEndianMod === -1) ? 3 : 0; + + for (i = 0; i < length; i += 3) + { + int1 = ((i + 1) < length) ? packed[(i + 1) >>> 2] : 0; + int2 = ((i + 2) < length) ? packed[(i + 2) >>> 2] : 0; + triplet = (((packed[i >>> 2] >>> (8 * (shiftModifier + bigEndianMod * (i % 4)))) & 0xFF) << 16) | + (((int1 >>> (8 * (shiftModifier + bigEndianMod * ((i + 1) % 4)))) & 0xFF) << 8) | + ((int2 >>> (8 * (shiftModifier + bigEndianMod * ((i + 2) % 4)))) & 0xFF); + for (j = 0; j < 4; j += 1) + { + if (i * 8 + j * 6 <= outputLength) + { + str += b64Tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F); + } + else + { + str += formatOpts["b64Pad"]; + } + } + } + return str; + } + + /** + * Convert an array of big-endian words to raw bytes string + * + * @private + * @param {Array} packed Array of integers to be converted to + * a raw bytes string representation + * @param {number} outputLength Length of output in bits + * @param {number} bigEndianMod Modifier for whether hash function is + * big or small endian + * @return {string} Raw bytes representation of the parameter in string + * form + */ + function packed2bytes(packed, outputLength, bigEndianMod) + { + var str = "", length = outputLength / 8, i, srcByte, shiftModifier; + + shiftModifier = (bigEndianMod === -1) ? 3 : 0; + + for (i = 0; i < length; i += 1) + { + srcByte = (packed[i >>> 2] >>> (8 * (shiftModifier + bigEndianMod * (i % 4)))) & 0xFF; + str += String.fromCharCode(srcByte); + } + + return str; + } + + /** + * Convert an array of big-endian words to an ArrayBuffer + * + * @private + * @param {Array} packed Array of integers to be converted to + * an ArrayBuffer + * @param {number} outputLength Length of output in bits + * @param {number} bigEndianMod Modifier for whether hash function is + * big or small endian + * @return {ArrayBuffer} Raw bytes representation of the parameter in an + * ArrayBuffer + */ + function packed2arraybuffer(packed, outputLength, bigEndianMod) + { + var length = outputLength / 8, i, retVal = new ArrayBuffer(length), shiftModifier, arrView; + arrView = new Uint8Array(retVal); + + shiftModifier = (bigEndianMod === -1) ? 3 : 0; + + for (i = 0; i < length; i += 1) + { + arrView[i] = (packed[i >>> 2] >>> (8 * (shiftModifier + bigEndianMod * (i % 4)))) & 0xFF; + } + + return retVal; + } + + /** + * Validate hash list containing output formatting options, ensuring + * presence of every option or adding the default value + * + * @private + * @param {{outputUpper : (boolean|undefined), b64Pad : (string|undefined), + * shakeLen : (number|undefined)}=} options Hash list of output formatting options + * @return {{outputUpper : boolean, b64Pad : string, shakeLen : number}} Validated + * hash list containing output formatting options + */ + function getOutputOpts(options) + { + var retVal = {"outputUpper" : false, "b64Pad" : "=", "shakeLen" : -1}, + outputOptions; + outputOptions = options || {}; + + retVal["outputUpper"] = outputOptions["outputUpper"] || false; + + if (true === outputOptions.hasOwnProperty("b64Pad")) + { + retVal["b64Pad"] = outputOptions["b64Pad"]; + } + + if ((true === outputOptions.hasOwnProperty("shakeLen")) && ((8 & SUPPORTED_ALGS) !== 0)) + { + if (outputOptions["shakeLen"] % 8 !== 0) + { + throw new Error("shakeLen must be a multiple of 8"); + } + retVal["shakeLen"] = outputOptions["shakeLen"]; + } + + if ("boolean" !== typeof(retVal["outputUpper"])) + { + throw new Error("Invalid outputUpper formatting option"); + } + + if ("string" !== typeof(retVal["b64Pad"])) + { + throw new Error("Invalid b64Pad formatting option"); + } + + return retVal; + } + + /** + * Function that takes an input format and UTF encoding and returns the + * appropriate function used to convert the input. + * + * @private + * @param {string} format The format of the string to be converted + * @param {string} utfType The string encoding to use (UTF8, UTF16BE, + * UTF16LE) + * @param {number} bigEndianMod Modifier for whether hash function is + * big or small endian + * @return {function((string|ArrayBuffer), Array=, number=): {value : + * Array, binLen : number}} Function that will convert an input + * string to a packed int array + */ + function getStrConverter(format, utfType, bigEndianMod) + { + var retVal; + + /* Validate encoding */ + switch (utfType) + { + case "UTF8": + /* Fallthrough */ + case "UTF16BE": + /* Fallthrough */ + case "UTF16LE": + /* Fallthrough */ + break; + default: + throw new Error("encoding must be UTF8, UTF16BE, or UTF16LE"); + } + + /* Map inputFormat to the appropriate converter */ + switch (format) + { + case "HEX": + /** + * @param {string} str String of raw bytes to be converted to binary representation + * @param {Array} existingBin A packed int array of bytes to + * append the results to + * @param {number} existingBinLen The number of bits in the existingBin + * array + * @return {{value : Array, binLen : number}} Hash list where + * "value" contains the output number array and "binLen" is the binary + * length of "value" + */ + retVal = function(str, existingBin, existingBinLen) + { + return hex2packed(str, existingBin, existingBinLen, bigEndianMod); + }; + break; + case "TEXT": + /** + * @param {string} str String of raw bytes to be converted to binary representation + * @param {Array} existingBin A packed int array of bytes to + * append the results to + * @param {number} existingBinLen The number of bits in the existingBin + * array + * @return {{value : Array, binLen : number}} Hash list where + * "value" contains the output number array and "binLen" is the binary + * length of "value" + */ + retVal = function(str, existingBin, existingBinLen) + { + return str2packed(str, utfType, existingBin, existingBinLen, bigEndianMod); + }; + break; + case "B64": + /** + * @param {string} str String of raw bytes to be converted to binary representation + * @param {Array} existingBin A packed int array of bytes to + * append the results to + * @param {number} existingBinLen The number of bits in the existingBin + * array + * @return {{value : Array, binLen : number}} Hash list where + * "value" contains the output number array and "binLen" is the binary + * length of "value" + */ + retVal = function(str, existingBin, existingBinLen) + { + return b642packed(str, existingBin, existingBinLen, bigEndianMod); + }; + break; + case "BYTES": + /** + * @param {string} str String of raw bytes to be converted to binary representation + * @param {Array} existingBin A packed int array of bytes to + * append the results to + * @param {number} existingBinLen The number of bits in the existingBin + * array + * @return {{value : Array, binLen : number}} Hash list where + * "value" contains the output number array and "binLen" is the binary + * length of "value" + */ + retVal = function(str, existingBin, existingBinLen) + { + return bytes2packed(str, existingBin, existingBinLen, bigEndianMod); + }; + break; + case "ARRAYBUFFER": + try { + retVal = new ArrayBuffer(0); + } catch(ignore) { + throw new Error("ARRAYBUFFER not supported by this environment"); + } + /** + * @param {ArrayBuffer} arr ArrayBuffer to be converted to binary + * representation + * @param {Array} existingBin A packed int array of bytes to + * append the results to + * @param {number} existingBinLen The number of bits in the existingBin + * array + * @return {{value : Array, binLen : number}} Hash list where + * "value" contains the output number array and "binLen" is the binary + * length of "value" + */ + retVal = function(arr, existingBin, existingBinLen) + { + return arraybuffer2packed(arr, existingBin, existingBinLen, bigEndianMod); + }; + break; + default: + throw new Error("format must be HEX, TEXT, B64, BYTES, or ARRAYBUFFER"); + } + + return retVal; + } + + /** + * The 32-bit implementation of circular rotate left + * + * @private + * @param {number} x The 32-bit integer argument + * @param {number} n The number of bits to shift + * @return {number} The x shifted circularly by n bits + */ + function rotl_32(x, n) + { + return (x << n) | (x >>> (32 - n)); + } + + /** + * The 64-bit implementation of circular rotate left + * + * @private + * @param {Int_64} x The 64-bit integer argument + * @param {number} n The number of bits to shift + * @return {Int_64} The x shifted circularly by n bits + */ + function rotl_64(x, n) + { + if (n > 32) + { + n = n - 32; + return new Int_64( + x.lowOrder << n | x.highOrder >>> (32 - n), + x.highOrder << n | x.lowOrder >>> (32 - n) + ); + } + else if (0 !== n) + { + return new Int_64( + x.highOrder << n | x.lowOrder >>> (32 - n), + x.lowOrder << n | x.highOrder >>> (32 - n) + ); + } + else + { + return x; + } + } + + /** + * The 32-bit implementation of circular rotate right + * + * @private + * @param {number} x The 32-bit integer argument + * @param {number} n The number of bits to shift + * @return {number} The x shifted circularly by n bits + */ + function rotr_32(x, n) + { + return (x >>> n) | (x << (32 - n)); + } + + /** + * The 64-bit implementation of circular rotate right + * + * @private + * @param {Int_64} x The 64-bit integer argument + * @param {number} n The number of bits to shift + * @return {Int_64} The x shifted circularly by n bits + */ + function rotr_64(x, n) + { + var retVal = null, tmp = new Int_64(x.highOrder, x.lowOrder); + + if (32 >= n) + { + retVal = new Int_64( + (tmp.highOrder >>> n) | ((tmp.lowOrder << (32 - n)) & 0xFFFFFFFF), + (tmp.lowOrder >>> n) | ((tmp.highOrder << (32 - n)) & 0xFFFFFFFF) + ); + } + else + { + retVal = new Int_64( + (tmp.lowOrder >>> (n - 32)) | ((tmp.highOrder << (64 - n)) & 0xFFFFFFFF), + (tmp.highOrder >>> (n - 32)) | ((tmp.lowOrder << (64 - n)) & 0xFFFFFFFF) + ); + } + + return retVal; + } + + /** + * The 32-bit implementation of shift right + * + * @private + * @param {number} x The 32-bit integer argument + * @param {number} n The number of bits to shift + * @return {number} The x shifted by n bits + */ + function shr_32(x, n) + { + return x >>> n; + } + + /** + * The 64-bit implementation of shift right + * + * @private + * @param {Int_64} x The 64-bit integer argument + * @param {number} n The number of bits to shift + * @return {Int_64} The x shifted by n bits + */ + function shr_64(x, n) + { + var retVal = null; + + if (32 >= n) + { + retVal = new Int_64( + x.highOrder >>> n, + x.lowOrder >>> n | ((x.highOrder << (32 - n)) & 0xFFFFFFFF) + ); + } + else + { + retVal = new Int_64( + 0, + x.highOrder >>> (n - 32) + ); + } + + return retVal; + } + + /** + * The 32-bit implementation of the NIST specified Parity function + * + * @private + * @param {number} x The first 32-bit integer argument + * @param {number} y The second 32-bit integer argument + * @param {number} z The third 32-bit integer argument + * @return {number} The NIST specified output of the function + */ + function parity_32(x, y, z) + { + return x ^ y ^ z; + } + + /** + * The 32-bit implementation of the NIST specified Ch function + * + * @private + * @param {number} x The first 32-bit integer argument + * @param {number} y The second 32-bit integer argument + * @param {number} z The third 32-bit integer argument + * @return {number} The NIST specified output of the function + */ + function ch_32(x, y, z) + { + return (x & y) ^ (~x & z); + } + + /** + * The 64-bit implementation of the NIST specified Ch function + * + * @private + * @param {Int_64} x The first 64-bit integer argument + * @param {Int_64} y The second 64-bit integer argument + * @param {Int_64} z The third 64-bit integer argument + * @return {Int_64} The NIST specified output of the function + */ + function ch_64(x, y, z) + { + return new Int_64( + (x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder), + (x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder) + ); + } + + /** + * The 32-bit implementation of the NIST specified Maj function + * + * @private + * @param {number} x The first 32-bit integer argument + * @param {number} y The second 32-bit integer argument + * @param {number} z The third 32-bit integer argument + * @return {number} The NIST specified output of the function + */ + function maj_32(x, y, z) + { + return (x & y) ^ (x & z) ^ (y & z); + } + + /** + * The 64-bit implementation of the NIST specified Maj function + * + * @private + * @param {Int_64} x The first 64-bit integer argument + * @param {Int_64} y The second 64-bit integer argument + * @param {Int_64} z The third 64-bit integer argument + * @return {Int_64} The NIST specified output of the function + */ + function maj_64(x, y, z) + { + return new Int_64( + (x.highOrder & y.highOrder) ^ + (x.highOrder & z.highOrder) ^ + (y.highOrder & z.highOrder), + (x.lowOrder & y.lowOrder) ^ + (x.lowOrder & z.lowOrder) ^ + (y.lowOrder & z.lowOrder) + ); + } + + /** + * The 32-bit implementation of the NIST specified Sigma0 function + * + * @private + * @param {number} x The 32-bit integer argument + * @return {number} The NIST specified output of the function + */ + function sigma0_32(x) + { + return rotr_32(x, 2) ^ rotr_32(x, 13) ^ rotr_32(x, 22); + } + + /** + * The 64-bit implementation of the NIST specified Sigma0 function + * + * @private + * @param {Int_64} x The 64-bit integer argument + * @return {Int_64} The NIST specified output of the function + */ + function sigma0_64(x) + { + var rotr28 = rotr_64(x, 28), rotr34 = rotr_64(x, 34), + rotr39 = rotr_64(x, 39); + + return new Int_64( + rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder, + rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder); + } + + /** + * The 32-bit implementation of the NIST specified Sigma1 function + * + * @private + * @param {number} x The 32-bit integer argument + * @return {number} The NIST specified output of the function + */ + function sigma1_32(x) + { + return rotr_32(x, 6) ^ rotr_32(x, 11) ^ rotr_32(x, 25); + } + + /** + * The 64-bit implementation of the NIST specified Sigma1 function + * + * @private + * @param {Int_64} x The 64-bit integer argument + * @return {Int_64} The NIST specified output of the function + */ + function sigma1_64(x) + { + var rotr14 = rotr_64(x, 14), rotr18 = rotr_64(x, 18), + rotr41 = rotr_64(x, 41); + + return new Int_64( + rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder, + rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder); + } + + /** + * The 32-bit implementation of the NIST specified Gamma0 function + * + * @private + * @param {number} x The 32-bit integer argument + * @return {number} The NIST specified output of the function + */ + function gamma0_32(x) + { + return rotr_32(x, 7) ^ rotr_32(x, 18) ^ shr_32(x, 3); + } + + /** + * The 64-bit implementation of the NIST specified Gamma0 function + * + * @private + * @param {Int_64} x The 64-bit integer argument + * @return {Int_64} The NIST specified output of the function + */ + function gamma0_64(x) + { + var rotr1 = rotr_64(x, 1), rotr8 = rotr_64(x, 8), shr7 = shr_64(x, 7); + + return new Int_64( + rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder, + rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder + ); + } + + /** + * The 32-bit implementation of the NIST specified Gamma1 function + * + * @private + * @param {number} x The 32-bit integer argument + * @return {number} The NIST specified output of the function + */ + function gamma1_32(x) + { + return rotr_32(x, 17) ^ rotr_32(x, 19) ^ shr_32(x, 10); + } + + /** + * The 64-bit implementation of the NIST specified Gamma1 function + * + * @private + * @param {Int_64} x The 64-bit integer argument + * @return {Int_64} The NIST specified output of the function + */ + function gamma1_64(x) + { + var rotr19 = rotr_64(x, 19), rotr61 = rotr_64(x, 61), + shr6 = shr_64(x, 6); + + return new Int_64( + rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder, + rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder + ); + } + + /** + * Add two 32-bit integers, wrapping at 2^32. This uses 16-bit operations + * internally to work around bugs in some JS interpreters. + * + * @private + * @param {number} a The first 32-bit integer argument to be added + * @param {number} b The second 32-bit integer argument to be added + * @return {number} The sum of a + b + */ + function safeAdd_32_2(a, b) + { + var lsw = (a & 0xFFFF) + (b & 0xFFFF), + msw = (a >>> 16) + (b >>> 16) + (lsw >>> 16); + + return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); + } + + /** + * Add four 32-bit integers, wrapping at 2^32. This uses 16-bit operations + * internally to work around bugs in some JS interpreters. + * + * @private + * @param {number} a The first 32-bit integer argument to be added + * @param {number} b The second 32-bit integer argument to be added + * @param {number} c The third 32-bit integer argument to be added + * @param {number} d The fourth 32-bit integer argument to be added + * @return {number} The sum of a + b + c + d + */ + function safeAdd_32_4(a, b, c, d) + { + var lsw = (a & 0xFFFF) + (b & 0xFFFF) + (c & 0xFFFF) + (d & 0xFFFF), + msw = (a >>> 16) + (b >>> 16) + (c >>> 16) + (d >>> 16) + + (lsw >>> 16); + + return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); + } + + /** + * Add five 32-bit integers, wrapping at 2^32. This uses 16-bit operations + * internally to work around bugs in some JS interpreters. + * + * @private + * @param {number} a The first 32-bit integer argument to be added + * @param {number} b The second 32-bit integer argument to be added + * @param {number} c The third 32-bit integer argument to be added + * @param {number} d The fourth 32-bit integer argument to be added + * @param {number} e The fifth 32-bit integer argument to be added + * @return {number} The sum of a + b + c + d + e + */ + function safeAdd_32_5(a, b, c, d, e) + { + var lsw = (a & 0xFFFF) + (b & 0xFFFF) + (c & 0xFFFF) + (d & 0xFFFF) + + (e & 0xFFFF), + msw = (a >>> 16) + (b >>> 16) + (c >>> 16) + (d >>> 16) + + (e >>> 16) + (lsw >>> 16); + + return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); + } + + /** + * Add two 64-bit integers, wrapping at 2^64. This uses 16-bit operations + * internally to work around bugs in some JS interpreters. + * + * @private + * @param {Int_64} x The first 64-bit integer argument to be added + * @param {Int_64} y The second 64-bit integer argument to be added + * @return {Int_64} The sum of x + y + */ + function safeAdd_64_2(x, y) + { + var lsw, msw, lowOrder, highOrder; + + lsw = (x.lowOrder & 0xFFFF) + (y.lowOrder & 0xFFFF); + msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16); + lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); + + lsw = (x.highOrder & 0xFFFF) + (y.highOrder & 0xFFFF) + (msw >>> 16); + msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16); + highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); + + return new Int_64(highOrder, lowOrder); + } + + /** + * Add four 64-bit integers, wrapping at 2^64. This uses 16-bit operations + * internally to work around bugs in some JS interpreters. + * + * @private + * @param {Int_64} a The first 64-bit integer argument to be added + * @param {Int_64} b The second 64-bit integer argument to be added + * @param {Int_64} c The third 64-bit integer argument to be added + * @param {Int_64} d The fouth 64-bit integer argument to be added + * @return {Int_64} The sum of a + b + c + d + */ + function safeAdd_64_4(a, b, c, d) + { + var lsw, msw, lowOrder, highOrder; + + lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF); + msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16); + lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); + + lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (msw >>> 16); + msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16); + highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); + + return new Int_64(highOrder, lowOrder); + } + + /** + * Add five 64-bit integers, wrapping at 2^64. This uses 16-bit operations + * internally to work around bugs in some JS interpreters. + * + * @private + * @param {Int_64} a The first 64-bit integer argument to be added + * @param {Int_64} b The second 64-bit integer argument to be added + * @param {Int_64} c The third 64-bit integer argument to be added + * @param {Int_64} d The fouth 64-bit integer argument to be added + * @param {Int_64} e The fouth 64-bit integer argument to be added + * @return {Int_64} The sum of a + b + c + d + e + */ + function safeAdd_64_5(a, b, c, d, e) + { + var lsw, msw, lowOrder, highOrder; + + lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF) + + (e.lowOrder & 0xFFFF); + msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (e.lowOrder >>> 16) + + (lsw >>> 16); + lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); + + lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + + (e.highOrder & 0xFFFF) + (msw >>> 16); + msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + + (c.highOrder >>> 16) + (d.highOrder >>> 16) + + (e.highOrder >>> 16) + (lsw >>> 16); + highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); + + return new Int_64(highOrder, lowOrder); + } + + /** + * XORs two given arguments. + * + * @private + * @param {Int_64} a First argument to be XORed + * @param {Int_64} b Second argument to be XORed + * @return {Int_64} The XOR of the arguments + */ + function xor_64_2(a, b) + { + return new Int_64( + a.highOrder ^ b.highOrder, + a.lowOrder ^ b.lowOrder + ); + } + + /** + * XORs five given arguments. + * + * @private + * @param {Int_64} a First argument to be XORed + * @param {Int_64} b Second argument to be XORed + * @param {Int_64} c Third argument to be XORed + * @param {Int_64} d Fourth argument to be XORed + * @param {Int_64} e Fifth argument to be XORed + * @return {Int_64} The XOR of the arguments + */ + function xor_64_5(a, b, c, d, e) + { + return new Int_64( + a.highOrder ^ b.highOrder ^ c.highOrder ^ d.highOrder ^ e.highOrder, + a.lowOrder ^ b.lowOrder ^ c.lowOrder ^ d.lowOrder ^ e.lowOrder + ); + } + + /** + * Returns a clone of the given SHA3 state + * + * @private + * @param {Array>} state The state to be cloned + * @return {Array>} The cloned state + */ + function cloneSHA3State(state) { + var clone = [], i; + for (i = 0; i < 5; i += 1) + { + clone[i] = state[i].slice(); + } + + return clone; + } + + /** + * Gets the state values for the specified SHA variant + * + * @param {string} variant The SHA variant + * @return {Array>} The initial state values + */ + function getNewState(variant) + { + var retVal = [], H_trunc, H_full, i; + + if (("SHA-1" === variant) && ((1 & SUPPORTED_ALGS) !== 0)) + { + retVal = [ + 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 + ]; + } + else if ((variant.lastIndexOf("SHA-", 0) === 0) && ((6 & SUPPORTED_ALGS) !== 0)) + { + H_trunc = [ + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 + ]; + H_full = [ + 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, + 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 + ]; + + switch (variant) + { + case "SHA-224": + retVal = H_trunc; + break; + case "SHA-256": + retVal = H_full; + break; + case "SHA-384": + retVal = [ + new Int_64(0xcbbb9d5d, H_trunc[0]), + new Int_64(0x0629a292a, H_trunc[1]), + new Int_64(0x9159015a, H_trunc[2]), + new Int_64(0x0152fecd8, H_trunc[3]), + new Int_64(0x67332667, H_trunc[4]), + new Int_64(0x98eb44a87, H_trunc[5]), + new Int_64(0xdb0c2e0d, H_trunc[6]), + new Int_64(0x047b5481d, H_trunc[7]) + ]; + break; + case "SHA-512": + retVal = [ + new Int_64(H_full[0], 0xf3bcc908), + new Int_64(H_full[1], 0x84caa73b), + new Int_64(H_full[2], 0xfe94f82b), + new Int_64(H_full[3], 0x5f1d36f1), + new Int_64(H_full[4], 0xade682d1), + new Int_64(H_full[5], 0x2b3e6c1f), + new Int_64(H_full[6], 0xfb41bd6b), + new Int_64(H_full[7], 0x137e2179) + ]; + break; + default: + throw new Error("Unknown SHA variant"); + } + } + else if (((variant.lastIndexOf("SHA3-", 0) === 0) || (variant.lastIndexOf("SHAKE", 0) === 0)) && + ((8 & SUPPORTED_ALGS) !== 0)) + { + for (i = 0; i < 5; i += 1) + { + retVal[i] = [new Int_64(0, 0), new Int_64(0, 0), new Int_64(0, 0), new Int_64(0, 0), new Int_64(0, 0)]; + } + } + else + { + throw new Error("No SHA variants supported"); + } + + return retVal; + } + + /** + * Performs a round of SHA-1 hashing over a 512-byte block + * + * @private + * @param {Array} block The binary array representation of the + * block to hash + * @param {Array} H The intermediate H values from a previous + * round + * @return {Array} The resulting H values + */ + function roundSHA1(block, H) + { + var W = [], a, b, c, d, e, T, ch = ch_32, parity = parity_32, + maj = maj_32, rotl = rotl_32, safeAdd_2 = safeAdd_32_2, t, + safeAdd_5 = safeAdd_32_5; + + a = H[0]; + b = H[1]; + c = H[2]; + d = H[3]; + e = H[4]; + + for (t = 0; t < 80; t += 1) + { + if (t < 16) + { + W[t] = block[t]; + } + else + { + W[t] = rotl(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1); + } + + if (t < 20) + { + T = safeAdd_5(rotl(a, 5), ch(b, c, d), e, 0x5a827999, W[t]); + } + else if (t < 40) + { + T = safeAdd_5(rotl(a, 5), parity(b, c, d), e, 0x6ed9eba1, W[t]); + } + else if (t < 60) + { + T = safeAdd_5(rotl(a, 5), maj(b, c, d), e, 0x8f1bbcdc, W[t]); + } else { + T = safeAdd_5(rotl(a, 5), parity(b, c, d), e, 0xca62c1d6, W[t]); + } + + e = d; + d = c; + c = rotl(b, 30); + b = a; + a = T; + } + + H[0] = safeAdd_2(a, H[0]); + H[1] = safeAdd_2(b, H[1]); + H[2] = safeAdd_2(c, H[2]); + H[3] = safeAdd_2(d, H[3]); + H[4] = safeAdd_2(e, H[4]); + + return H; + } + + /** + * Finalizes the SHA-1 hash + * + * @private + * @param {Array} remainder Any leftover unprocessed packed ints + * that still need to be processed + * @param {number} remainderBinLen The number of bits in remainder + * @param {number} processedBinLen The number of bits already + * processed + * @param {Array} H The intermediate H values from a previous + * round + * @param {number} outputLen Unused for this variant + * @return {Array} The array of integers representing the SHA-1 + * hash of message + */ + function finalizeSHA1(remainder, remainderBinLen, processedBinLen, H, outputLen) + { + var i, appendedMessageLength, offset, totalLen; + + /* The 65 addition is a hack but it works. The correct number is + actually 72 (64 + 8) but the below math fails if + remainderBinLen + 72 % 512 = 0. Since remainderBinLen % 8 = 0, + "shorting" the addition is OK. */ + offset = (((remainderBinLen + 65) >>> 9) << 4) + 15; + while (remainder.length <= offset) + { + remainder.push(0); + } + /* Append '1' at the end of the binary string */ + remainder[remainderBinLen >>> 5] |= 0x80 << (24 - (remainderBinLen % 32)); + /* Append length of binary string in the position such that the new + * length is a multiple of 512. Logic does not work for even multiples + * of 512 but there can never be even multiples of 512. JavaScript + * numbers are limited to 2^53 so it's "safe" to treat the totalLen as + * a 64-bit integer. */ + totalLen = remainderBinLen + processedBinLen; + remainder[offset] = totalLen & 0xFFFFFFFF; + /* Bitwise operators treat the operand as a 32-bit number so need to + * use hacky division and round to get access to upper 32-ish bits */ + remainder[offset - 1] = (totalLen / TWO_PWR_32) | 0; + + appendedMessageLength = remainder.length; + + /* This will always be at least 1 full chunk */ + for (i = 0; i < appendedMessageLength; i += 16) + { + H = roundSHA1(remainder.slice(i, i + 16), H); + } + + return H; + } + + /* Put this here so the K arrays aren't put on the stack for every block */ + var K_sha2, K_sha512, r_sha3, rc_sha3; + if ((6 & SUPPORTED_ALGS) !== 0) + { + K_sha2 = [ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 + ]; + + if ((4 & SUPPORTED_ALGS) !== 0) + { + K_sha512 = [ + new Int_64(K_sha2[ 0], 0xd728ae22), new Int_64(K_sha2[ 1], 0x23ef65cd), + new Int_64(K_sha2[ 2], 0xec4d3b2f), new Int_64(K_sha2[ 3], 0x8189dbbc), + new Int_64(K_sha2[ 4], 0xf348b538), new Int_64(K_sha2[ 5], 0xb605d019), + new Int_64(K_sha2[ 6], 0xaf194f9b), new Int_64(K_sha2[ 7], 0xda6d8118), + new Int_64(K_sha2[ 8], 0xa3030242), new Int_64(K_sha2[ 9], 0x45706fbe), + new Int_64(K_sha2[10], 0x4ee4b28c), new Int_64(K_sha2[11], 0xd5ffb4e2), + new Int_64(K_sha2[12], 0xf27b896f), new Int_64(K_sha2[13], 0x3b1696b1), + new Int_64(K_sha2[14], 0x25c71235), new Int_64(K_sha2[15], 0xcf692694), + new Int_64(K_sha2[16], 0x9ef14ad2), new Int_64(K_sha2[17], 0x384f25e3), + new Int_64(K_sha2[18], 0x8b8cd5b5), new Int_64(K_sha2[19], 0x77ac9c65), + new Int_64(K_sha2[20], 0x592b0275), new Int_64(K_sha2[21], 0x6ea6e483), + new Int_64(K_sha2[22], 0xbd41fbd4), new Int_64(K_sha2[23], 0x831153b5), + new Int_64(K_sha2[24], 0xee66dfab), new Int_64(K_sha2[25], 0x2db43210), + new Int_64(K_sha2[26], 0x98fb213f), new Int_64(K_sha2[27], 0xbeef0ee4), + new Int_64(K_sha2[28], 0x3da88fc2), new Int_64(K_sha2[29], 0x930aa725), + new Int_64(K_sha2[30], 0xe003826f), new Int_64(K_sha2[31], 0x0a0e6e70), + new Int_64(K_sha2[32], 0x46d22ffc), new Int_64(K_sha2[33], 0x5c26c926), + new Int_64(K_sha2[34], 0x5ac42aed), new Int_64(K_sha2[35], 0x9d95b3df), + new Int_64(K_sha2[36], 0x8baf63de), new Int_64(K_sha2[37], 0x3c77b2a8), + new Int_64(K_sha2[38], 0x47edaee6), new Int_64(K_sha2[39], 0x1482353b), + new Int_64(K_sha2[40], 0x4cf10364), new Int_64(K_sha2[41], 0xbc423001), + new Int_64(K_sha2[42], 0xd0f89791), new Int_64(K_sha2[43], 0x0654be30), + new Int_64(K_sha2[44], 0xd6ef5218), new Int_64(K_sha2[45], 0x5565a910), + new Int_64(K_sha2[46], 0x5771202a), new Int_64(K_sha2[47], 0x32bbd1b8), + new Int_64(K_sha2[48], 0xb8d2d0c8), new Int_64(K_sha2[49], 0x5141ab53), + new Int_64(K_sha2[50], 0xdf8eeb99), new Int_64(K_sha2[51], 0xe19b48a8), + new Int_64(K_sha2[52], 0xc5c95a63), new Int_64(K_sha2[53], 0xe3418acb), + new Int_64(K_sha2[54], 0x7763e373), new Int_64(K_sha2[55], 0xd6b2b8a3), + new Int_64(K_sha2[56], 0x5defb2fc), new Int_64(K_sha2[57], 0x43172f60), + new Int_64(K_sha2[58], 0xa1f0ab72), new Int_64(K_sha2[59], 0x1a6439ec), + new Int_64(K_sha2[60], 0x23631e28), new Int_64(K_sha2[61], 0xde82bde9), + new Int_64(K_sha2[62], 0xb2c67915), new Int_64(K_sha2[63], 0xe372532b), + new Int_64(0xca273ece, 0xea26619c), new Int_64(0xd186b8c7, 0x21c0c207), + new Int_64(0xeada7dd6, 0xcde0eb1e), new Int_64(0xf57d4f7f, 0xee6ed178), + new Int_64(0x06f067aa, 0x72176fba), new Int_64(0x0a637dc5, 0xa2c898a6), + new Int_64(0x113f9804, 0xbef90dae), new Int_64(0x1b710b35, 0x131c471b), + new Int_64(0x28db77f5, 0x23047d84), new Int_64(0x32caab7b, 0x40c72493), + new Int_64(0x3c9ebe0a, 0x15c9bebc), new Int_64(0x431d67c4, 0x9c100d4c), + new Int_64(0x4cc5d4be, 0xcb3e42b6), new Int_64(0x597f299c, 0xfc657e2a), + new Int_64(0x5fcb6fab, 0x3ad6faec), new Int_64(0x6c44198c, 0x4a475817) + ]; + } + } + if ((8 & SUPPORTED_ALGS) !== 0) + { + rc_sha3 = [ + new Int_64(0x00000000, 0x00000001), new Int_64(0x00000000, 0x00008082), + new Int_64(0x80000000, 0x0000808A), new Int_64(0x80000000, 0x80008000), + new Int_64(0x00000000, 0x0000808B), new Int_64(0x00000000, 0x80000001), + new Int_64(0x80000000, 0x80008081), new Int_64(0x80000000, 0x00008009), + new Int_64(0x00000000, 0x0000008A), new Int_64(0x00000000, 0x00000088), + new Int_64(0x00000000, 0x80008009), new Int_64(0x00000000, 0x8000000A), + new Int_64(0x00000000, 0x8000808B), new Int_64(0x80000000, 0x0000008B), + new Int_64(0x80000000, 0x00008089), new Int_64(0x80000000, 0x00008003), + new Int_64(0x80000000, 0x00008002), new Int_64(0x80000000, 0x00000080), + new Int_64(0x00000000, 0x0000800A), new Int_64(0x80000000, 0x8000000A), + new Int_64(0x80000000, 0x80008081), new Int_64(0x80000000, 0x00008080), + new Int_64(0x00000000, 0x80000001), new Int_64(0x80000000, 0x80008008) + ]; + + r_sha3 = [ + [ 0, 36, 3, 41, 18], + [ 1, 44, 10, 45, 2], + [62, 6, 43, 15, 61], + [28, 55, 25, 21, 56], + [27, 20, 39, 8, 14] + ]; + } + + /** + * Performs a round of SHA-2 hashing over a block + * + * @private + * @param {Array} block The binary array representation of the + * block to hash + * @param {Array} H The intermediate H values from a previous + * round + * @param {string} variant The desired SHA-2 variant + * @return {Array} The resulting H values + */ + function roundSHA2(block, H, variant) + { + var a, b, c, d, e, f, g, h, T1, T2, numRounds, t, binaryStringMult, + safeAdd_2, safeAdd_4, safeAdd_5, gamma0, gamma1, sigma0, sigma1, + ch, maj, Int, W = [], int1, int2, offset, K; + + /* Set up the various function handles and variable for the specific + * variant */ + if ((variant === "SHA-224" || variant === "SHA-256") && + ((2 & SUPPORTED_ALGS) !== 0)) + { + /* 32-bit variant */ + numRounds = 64; + binaryStringMult = 1; + Int = Number; + safeAdd_2 = safeAdd_32_2; + safeAdd_4 = safeAdd_32_4; + safeAdd_5 = safeAdd_32_5; + gamma0 = gamma0_32; + gamma1 = gamma1_32; + sigma0 = sigma0_32; + sigma1 = sigma1_32; + maj = maj_32; + ch = ch_32; + K = K_sha2; + } + else if ((variant === "SHA-384" || variant === "SHA-512") && + ((4 & SUPPORTED_ALGS) !== 0)) + { + /* 64-bit variant */ + numRounds = 80; + binaryStringMult = 2; + Int = Int_64; + safeAdd_2 = safeAdd_64_2; + safeAdd_4 = safeAdd_64_4; + safeAdd_5 = safeAdd_64_5; + gamma0 = gamma0_64; + gamma1 = gamma1_64; + sigma0 = sigma0_64; + sigma1 = sigma1_64; + maj = maj_64; + ch = ch_64; + K = K_sha512; + } + else + { + throw new Error("Unexpected error in SHA-2 implementation"); + } + + a = H[0]; + b = H[1]; + c = H[2]; + d = H[3]; + e = H[4]; + f = H[5]; + g = H[6]; + h = H[7]; + + for (t = 0; t < numRounds; t += 1) + { + if (t < 16) + { + offset = t * binaryStringMult; + int1 = (block.length <= offset) ? 0 : block[offset]; + int2 = (block.length <= offset + 1) ? 0 : block[offset + 1]; + /* Bit of a hack - for 32-bit, the second term is ignored */ + W[t] = new Int(int1, int2); + } + else + { + W[t] = safeAdd_4( + gamma1(W[t - 2]), W[t - 7], + gamma0(W[t - 15]), W[t - 16] + ); + } + + T1 = safeAdd_5(h, sigma1(e), ch(e, f, g), K[t], W[t]); + T2 = safeAdd_2(sigma0(a), maj(a, b, c)); + h = g; + g = f; + f = e; + e = safeAdd_2(d, T1); + d = c; + c = b; + b = a; + a = safeAdd_2(T1, T2); + } + + H[0] = safeAdd_2(a, H[0]); + H[1] = safeAdd_2(b, H[1]); + H[2] = safeAdd_2(c, H[2]); + H[3] = safeAdd_2(d, H[3]); + H[4] = safeAdd_2(e, H[4]); + H[5] = safeAdd_2(f, H[5]); + H[6] = safeAdd_2(g, H[6]); + H[7] = safeAdd_2(h, H[7]); + + return H; + } + + /** + * Finalizes the SHA-2 hash + * + * @private + * @param {Array} remainder Any leftover unprocessed packed ints + * that still need to be processed + * @param {number} remainderBinLen The number of bits in remainder + * @param {number} processedBinLen The number of bits already + * processed + * @param {Array} H The intermediate H values from a previous + * round + * @param {string} variant The desired SHA-2 variant + * @param {number} outputLen Unused for this variant + * @return {Array} The array of integers representing the SHA-2 + * hash of message + */ + function finalizeSHA2(remainder, remainderBinLen, processedBinLen, H, variant, outputLen) + { + var i, appendedMessageLength, offset, retVal, binaryStringInc, totalLen; + + if ((variant === "SHA-224" || variant === "SHA-256") && + ((2 & SUPPORTED_ALGS) !== 0)) + { + /* 32-bit variant */ + /* The 65 addition is a hack but it works. The correct number is + actually 72 (64 + 8) but the below math fails if + remainderBinLen + 72 % 512 = 0. Since remainderBinLen % 8 = 0, + "shorting" the addition is OK. */ + offset = (((remainderBinLen + 65) >>> 9) << 4) + 15; + binaryStringInc = 16; + } + else if ((variant === "SHA-384" || variant === "SHA-512") && + ((4 & SUPPORTED_ALGS) !== 0)) + { + /* 64-bit variant */ + /* The 129 addition is a hack but it works. The correct number is + actually 136 (128 + 8) but the below math fails if + remainderBinLen + 136 % 1024 = 0. Since remainderBinLen % 8 = 0, + "shorting" the addition is OK. */ + offset = (((remainderBinLen + 129) >>> 10) << 5) + 31; + binaryStringInc = 32; + } + else + { + throw new Error("Unexpected error in SHA-2 implementation"); + } + + while (remainder.length <= offset) + { + remainder.push(0); + } + /* Append '1' at the end of the binary string */ + remainder[remainderBinLen >>> 5] |= 0x80 << (24 - remainderBinLen % 32); + /* Append length of binary string in the position such that the new + * length is correct. JavaScript numbers are limited to 2^53 so it's + * "safe" to treat the totalLen as a 64-bit integer. */ + totalLen = remainderBinLen + processedBinLen; + remainder[offset] = totalLen & 0xFFFFFFFF; + /* Bitwise operators treat the operand as a 32-bit number so need to + * use hacky division and round to get access to upper 32-ish bits */ + remainder[offset - 1] = (totalLen / TWO_PWR_32) | 0; + + appendedMessageLength = remainder.length; + + /* This will always be at least 1 full chunk */ + for (i = 0; i < appendedMessageLength; i += binaryStringInc) + { + H = roundSHA2(remainder.slice(i, i + binaryStringInc), H, variant); + } + + if (("SHA-224" === variant) && ((2 & SUPPORTED_ALGS) !== 0)) + { + retVal = [ + H[0], H[1], H[2], H[3], + H[4], H[5], H[6] + ]; + } + else if (("SHA-256" === variant) && ((2 & SUPPORTED_ALGS) !== 0)) + { + retVal = H; + } + else if (("SHA-384" === variant) && ((4 & SUPPORTED_ALGS) !== 0)) + { + retVal = [ + H[0].highOrder, H[0].lowOrder, + H[1].highOrder, H[1].lowOrder, + H[2].highOrder, H[2].lowOrder, + H[3].highOrder, H[3].lowOrder, + H[4].highOrder, H[4].lowOrder, + H[5].highOrder, H[5].lowOrder + ]; + } + else if (("SHA-512" === variant) && ((4 & SUPPORTED_ALGS) !== 0)) + { + retVal = [ + H[0].highOrder, H[0].lowOrder, + H[1].highOrder, H[1].lowOrder, + H[2].highOrder, H[2].lowOrder, + H[3].highOrder, H[3].lowOrder, + H[4].highOrder, H[4].lowOrder, + H[5].highOrder, H[5].lowOrder, + H[6].highOrder, H[6].lowOrder, + H[7].highOrder, H[7].lowOrder + ]; + } + else /* This should never be reached */ + { + throw new Error("Unexpected error in SHA-2 implementation"); + } + + return retVal; + } + + /** + * Performs a round of SHA-3 hashing over a block + * + * @private + * @param {Array|null} block The binary array representation of the + * block to hash + * @param {Array>} state The binary array representation of the + * block to hash + * @return {Array>} The resulting state value + */ + function roundSHA3(block, state) + { + var round, x, y, B, C = [], D = []; + + if (null !== block) + { + for (x = 0; x < block.length; x+=2) + { + state[(x >>> 1) % 5][((x >>> 1) / 5) | 0] = xor_64_2( + state[(x >>> 1) % 5][((x >>> 1) / 5) | 0], + new Int_64(block[x + 1], block[x]) + ); + } + } + + for (round = 0; round < 24; round += 1) + { + /* getNewState doesn't care about variant beyond SHA3 so feed it a + value that triggers the getNewState "if" statement + */ + B = getNewState("SHA3-"); + + /* Perform theta step */ + for (x = 0; x < 5; x += 1) + { + C[x] = xor_64_5(state[x][0], state[x][1], state[x][2], + state[x][3], state[x][4]); + } + for (x = 0; x < 5; x += 1) + { + D[x] = xor_64_2(C[(x + 4) % 5], rotl_64(C[(x + 1) % 5], 1)); + } + for (x = 0; x < 5; x += 1) + { + for (y = 0; y < 5; y += 1) + { + state[x][y] = xor_64_2(state[x][y], D[x]); + } + } + + /* Perform combined ro and pi steps */ + for (x = 0; x < 5; x += 1) + { + for (y = 0; y < 5; y += 1) + { + B[y][(2 * x + 3 * y) % 5] = rotl_64( + state[x][y], + r_sha3[x][y] + ); + } + } + + /* Perform chi step */ + for (x = 0; x < 5; x += 1) + { + for (y = 0; y < 5; y += 1) + { + state[x][y] = xor_64_2( + B[x][y], + new Int_64( + ~(B[(x + 1) % 5][y].highOrder) & B[(x + 2) % 5][y].highOrder, + ~(B[(x + 1) % 5][y].lowOrder) & B[(x + 2) % 5][y].lowOrder + ) + ); + } + } + + /* Perform iota step */ + state[0][0] = xor_64_2(state[0][0], rc_sha3[round]); + } + + return state; + } + + /** + * Finalizes the SHA-3 hash + * + * @private + * @param {Array} remainder Any leftover unprocessed packed ints + * that still need to be processed + * @param {number} remainderBinLen The number of bits in remainder + * @param {number} processedBinLen The number of bits already + * processed + * @param {Array>} state The state from a previous round + * @param {number} blockSize The block size/rate of the variant in bits + * @param {number} delimiter The delimiter value for the variant + * @param {number} outputLen The output length for the variant in bits + * @return {Array} The array of integers representing the SHA-3 + * hash of message + */ + function finalizeSHA3(remainder, remainderBinLen, processedBinLen, state, blockSize, delimiter, outputLen) + { + var i, retVal = [], binaryStringInc = blockSize >>> 5, state_offset = 0, + remainderIntLen = remainderBinLen >>> 5, temp; + + + /* Process as many blocks as possible, some may be here for multiple rounds + with SHAKE + */ + for (i = 0; i < remainderIntLen && remainderBinLen >= blockSize; i += binaryStringInc) + { + state = roundSHA3(remainder.slice(i, i + binaryStringInc), state); + remainderBinLen -= blockSize; + } + + remainder = remainder.slice(i); + remainderBinLen = remainderBinLen % blockSize; + + /* Pad out the remainder to a full block */ + while (remainder.length < binaryStringInc) + { + remainder.push(0); + } + + /* Find the next "empty" byte for the 0x80 and append it via an xor */ + i = remainderBinLen >>> 3; + remainder[i >> 2] ^= delimiter << (8 * (i % 4)); + + remainder[binaryStringInc - 1] ^= 0x80000000; + state = roundSHA3(remainder, state); + + while (retVal.length * 32 < outputLen) + { + temp = state[state_offset % 5][(state_offset / 5) | 0]; + retVal.push(temp.lowOrder); + if (retVal.length * 32 >= outputLen) + { + break; + } + retVal.push(temp.highOrder); + state_offset += 1; + + if (0 === ((state_offset * 64) % blockSize)) + { + roundSHA3(null, state); + } + } + + return retVal; + } + + /** + * jsSHA is the workhorse of the library. Instantiate it with the string to + * be hashed as the parameter + * + * @constructor + * @this {jsSHA} + * @param {string} variant The desired SHA variant (SHA-1, SHA-224, SHA-256, + * SHA-384, SHA-512, SHA3-224, SHA3-256, SHA3-384, or SHA3-512) + * @param {string} inputFormat The format of srcString: HEX, TEXT, B64, + * BYTES, or ARRAYBUFFER + * @param {{encoding: (string|undefined), numRounds: (number|undefined)}=} + * options Optional values + */ + var jsSHA = function(variant, inputFormat, options) + { + var processedLen = 0, remainder = [], remainderLen = 0, utfType, + intermediateState, converterFunc, shaVariant = variant, outputBinLen, + variantBlockSize, roundFunc, finalizeFunc, stateCloneFunc, + hmacKeySet = false, keyWithIPad = [], keyWithOPad = [], numRounds, + updatedCalled = false, inputOptions, isSHAKE = false, bigEndianMod = -1; + + inputOptions = options || {}; + utfType = inputOptions["encoding"] || "UTF8"; + numRounds = inputOptions["numRounds"] || 1; + + if ((numRounds !== parseInt(numRounds, 10)) || (1 > numRounds)) + { + throw new Error("numRounds must a integer >= 1"); + } + + if (("SHA-1" === shaVariant) && ((1 & SUPPORTED_ALGS) !== 0)) + { + variantBlockSize = 512; + roundFunc = roundSHA1; + finalizeFunc = finalizeSHA1; + outputBinLen = 160; + stateCloneFunc = function(state) { return state.slice();}; + } + else if ((shaVariant.lastIndexOf("SHA-", 0) === 0) && ((6 & SUPPORTED_ALGS) !== 0)) + { + roundFunc = function (block, H) { + return roundSHA2(block, H, shaVariant); + }; + finalizeFunc = function (remainder, remainderBinLen, processedBinLen, H, outputLen) + { + return finalizeSHA2(remainder, remainderBinLen, processedBinLen, H, shaVariant, outputLen); + }; + stateCloneFunc = function(state) { return state.slice(); }; + + if (("SHA-224" === shaVariant) && ((2 & SUPPORTED_ALGS) !== 0)) + { + variantBlockSize = 512; + outputBinLen = 224; + } + else if (("SHA-256" === shaVariant) && ((2 & SUPPORTED_ALGS) !== 0)) + { + variantBlockSize = 512; + outputBinLen = 256; + } + else if (("SHA-384" === shaVariant) && ((4 & SUPPORTED_ALGS) !== 0)) + { + variantBlockSize = 1024; + outputBinLen = 384; + } + else if (("SHA-512" === shaVariant) && ((4 & SUPPORTED_ALGS) !== 0)) + { + variantBlockSize = 1024; + outputBinLen = 512; + } + else + { + throw new Error("Chosen SHA variant is not supported"); + } + } + else if (((shaVariant.lastIndexOf("SHA3-", 0) === 0) || (shaVariant.lastIndexOf("SHAKE", 0) === 0)) && + ((8 & SUPPORTED_ALGS) !== 0)) + { + var delimiter = 0x06; + + roundFunc = roundSHA3; + stateCloneFunc = function(state) { return cloneSHA3State(state);}; + bigEndianMod = 1; + + if ("SHA3-224" === shaVariant) + { + variantBlockSize = 1152; + outputBinLen = 224; + + } + else if ("SHA3-256" === shaVariant) + { + variantBlockSize = 1088; + outputBinLen = 256; + } + else if ("SHA3-384" === shaVariant) + { + variantBlockSize = 832; + outputBinLen = 384; + } + else if ("SHA3-512" === shaVariant) + { + variantBlockSize = 576; + outputBinLen = 512; + } + else if ("SHAKE128" === shaVariant) + { + variantBlockSize = 1344; + outputBinLen = -1; + delimiter = 0x1F; + isSHAKE = true; + } + else if ("SHAKE256" === shaVariant) + { + variantBlockSize = 1088; + outputBinLen = -1; + delimiter = 0x1F; + isSHAKE = true; + } + else + { + throw new Error("Chosen SHA variant is not supported"); + } + finalizeFunc = function (remainder, remainderBinLen, processedBinLen, state, outputLen) + { + return finalizeSHA3(remainder, remainderBinLen, processedBinLen, state, variantBlockSize, delimiter, outputLen); + }; + } + else + { + throw new Error("Chosen SHA variant is not supported"); + } + converterFunc = getStrConverter(inputFormat, utfType, bigEndianMod); + intermediateState = getNewState(shaVariant); + + /** + * Sets the HMAC key for an eventual getHMAC call. Must be called + * immediately after jsSHA object instantiation + * + * @expose + * @param {string|ArrayBuffer} key The key used to calculate the HMAC + * @param {string} inputFormat The format of key, HEX, TEXT, B64, BYTES, + * or ARRAYBUFFER + * @param {{encoding : (string|undefined)}=} options Associative array + * of input format options + */ + this.setHMACKey = function(key, inputFormat, options) + { + var keyConverterFunc, convertRet, keyBinLen, keyToUse, blockByteSize, + i, lastArrayIndex, keyOptions; + + if (true === hmacKeySet) + { + throw new Error("HMAC key already set"); + } + + if (true === updatedCalled) + { + throw new Error("Cannot set HMAC key after calling update"); + } + + if ((isSHAKE === true) && ((8 & SUPPORTED_ALGS) !== 0)) + { + throw new Error("SHAKE is not supported for HMAC"); + } + + keyOptions = options || {}; + utfType = keyOptions["encoding"] || "UTF8"; + + keyConverterFunc = getStrConverter(inputFormat, utfType, bigEndianMod); + + convertRet = keyConverterFunc(key); + keyBinLen = convertRet["binLen"]; + keyToUse = convertRet["value"]; + + blockByteSize = variantBlockSize >>> 3; + + /* These are used multiple times, calculate and store them */ + lastArrayIndex = (blockByteSize / 4) - 1; + + /* Figure out what to do with the key based on its size relative to + * the hash's block size */ + if (blockByteSize < (keyBinLen / 8)) + { + + keyToUse = finalizeFunc(keyToUse, keyBinLen, 0,getNewState(shaVariant), outputBinLen); + /* For all variants, the block size is bigger than the output + * size so there will never be a useful byte at the end of the + * string */ + while (keyToUse.length <= lastArrayIndex) + { + keyToUse.push(0); + } + keyToUse[lastArrayIndex] &= 0xFFFFFF00; + } + else if (blockByteSize > (keyBinLen / 8)) + { + /* If the blockByteSize is greater than the key length, there + * will always be at LEAST one "useless" byte at the end of the + * string */ + while (keyToUse.length <= lastArrayIndex) + { + keyToUse.push(0); + } + keyToUse[lastArrayIndex] &= 0xFFFFFF00; + } + + /* Create ipad and opad */ + for (i = 0; i <= lastArrayIndex; i += 1) + { + keyWithIPad[i] = keyToUse[i] ^ 0x36363636; + keyWithOPad[i] = keyToUse[i] ^ 0x5C5C5C5C; + } + + intermediateState = roundFunc(keyWithIPad, intermediateState); + processedLen = variantBlockSize; + + hmacKeySet = true; + }; + + /** + * Takes strString and hashes as many blocks as possible. Stores the + * rest for either a future update or getHash call. + * + * @expose + * @param {string|ArrayBuffer} srcString The string to be hashed + */ + this.update = function(srcString) + { + var convertRet, chunkBinLen, chunkIntLen, chunk, i, updateProcessedLen = 0, + variantBlockIntInc = variantBlockSize >>> 5; + + convertRet = converterFunc(srcString, remainder, remainderLen); + chunkBinLen = convertRet["binLen"]; + chunk = convertRet["value"]; + + chunkIntLen = chunkBinLen >>> 5; + for (i = 0; i < chunkIntLen; i += variantBlockIntInc) + { + if (updateProcessedLen + variantBlockSize <= chunkBinLen) + { + intermediateState = roundFunc( + chunk.slice(i, i + variantBlockIntInc), + intermediateState + ); + updateProcessedLen += variantBlockSize; + } + } + processedLen += updateProcessedLen; + remainder = chunk.slice(updateProcessedLen >>> 5); + remainderLen = chunkBinLen % variantBlockSize; + updatedCalled = true; + + }; + + /** + * Returns the desired SHA hash of the string specified at instantiation + * using the specified parameters + * + * @expose + * @param {string} format The desired output formatting (B64, HEX, + * BYTES, or ARRAYBUFFER) + * @param {{outputUpper : (boolean|undefined), b64Pad : (string|undefined), + * shakeLen : (number|undefined)}=} options Hash list of output formatting options + * @return {string|ArrayBuffer} The string representation of the hash + * in the format specified. + */ + this.getHash = function(format, options) + { + var formatFunc, i, outputOptions, finalizedState; + + if (true === hmacKeySet) + { + throw new Error("Cannot call getHash after setting HMAC key"); + } + + outputOptions = getOutputOpts(options); + + if ((isSHAKE === true) && ((8 & SUPPORTED_ALGS) !== 0)) + { + if (outputOptions["shakeLen"] === -1) + { + throw new Error("shakeLen must be specified in options"); + } + outputBinLen = outputOptions["shakeLen"]; + } + + /* Validate the output format selection */ + switch (format) + { + case "HEX": + formatFunc = function(binarray) {return packed2hex(binarray, outputBinLen, bigEndianMod, outputOptions);}; + break; + case "B64": + formatFunc = function(binarray) {return packed2b64(binarray, outputBinLen, bigEndianMod, outputOptions);}; + break; + case "BYTES": + formatFunc = function(binarray) {return packed2bytes(binarray, outputBinLen, bigEndianMod);}; + break; + case "ARRAYBUFFER": + try { + i = new ArrayBuffer(0); + } catch (ignore) { + throw new Error("ARRAYBUFFER not supported by this environment"); + } + formatFunc = function(binarray) {return packed2arraybuffer(binarray, outputBinLen, bigEndianMod);}; + break; + default: + throw new Error("format must be HEX, B64, BYTES, or ARRAYBUFFER"); + } + + finalizedState = finalizeFunc(remainder.slice(), remainderLen, processedLen, stateCloneFunc(intermediateState), outputBinLen); + for (i = 1; i < numRounds; i += 1) + { + /* This weird fix-up is only for the case of SHAKE algorithms + * and outputBinLen is not a multiple of 32. In this case, the + * very last block of finalizedState has data that needs to be + * ignored because all the finalizeFunc calls need to have + * unneeded bits set to 0. + */ + if (((8 & SUPPORTED_ALGS) !== 0) && (isSHAKE === true) && (outputBinLen % 32 !== 0)) + { + finalizedState[finalizedState.length - 1] &= 0x00FFFFFF >>> 24 - (outputBinLen % 32); + } + finalizedState = finalizeFunc(finalizedState, outputBinLen, 0, getNewState(shaVariant), outputBinLen); + } + + return formatFunc(finalizedState); + }; + + /** + * Returns the the HMAC in the specified format using the key given by + * a previous setHMACKey call. + * + * @expose + * @param {string} format The desired output formatting + * (B64, HEX, BYTES, or ARRAYBUFFER) + * @param {{outputUpper : (boolean|undefined), b64Pad : (string|undefined), + * shakeLen : (number|undefined)}=} options associative array of output + * formatting options + * @return {string|ArrayBuffer} The string representation of the hash in the + * format specified. + */ + this.getHMAC = function(format, options) + { + var formatFunc, firstHash, outputOptions, finalizedState; + + if (false === hmacKeySet) + { + throw new Error("Cannot call getHMAC without first setting HMAC key"); + } + + outputOptions = getOutputOpts(options); + + /* Validate the output format selection */ + switch (format) + { + case "HEX": + formatFunc = function(binarray) {return packed2hex(binarray, outputBinLen, bigEndianMod, outputOptions);}; + break; + case "B64": + formatFunc = function(binarray) {return packed2b64(binarray, outputBinLen, bigEndianMod, outputOptions);}; + break; + case "BYTES": + formatFunc = function(binarray) {return packed2bytes(binarray, outputBinLen, bigEndianMod);}; + break; + case "ARRAYBUFFER": + try { + formatFunc = new ArrayBuffer(0); + } catch(ignore) { + throw new Error("ARRAYBUFFER not supported by this environment"); + } + formatFunc = function(binarray) {return packed2arraybuffer(binarray, outputBinLen, bigEndianMod);}; + break; + default: + throw new Error("outputFormat must be HEX, B64, BYTES, or ARRAYBUFFER"); + } + + firstHash = finalizeFunc(remainder.slice(), remainderLen, processedLen, stateCloneFunc(intermediateState), outputBinLen); + finalizedState = roundFunc(keyWithOPad, getNewState(shaVariant)); + finalizedState = finalizeFunc(firstHash, outputBinLen, variantBlockSize, finalizedState, outputBinLen); + + return formatFunc(finalizedState); + }; + }; + + if (("function" === typeof define) && (define["amd"])) /* AMD Support */ + { + define(function() + { + return jsSHA; + }); + } else if ("undefined" !== typeof exports) /* Node Support */ + { + if (("undefined" !== typeof module) && module["exports"]) + { + module["exports"] = jsSHA; + exports = jsSHA; + } + else { + exports = jsSHA; + } + } else { /* Browsers and Web Workers*/ + global["jsSHA"] = jsSHA; + } +}(this)); diff --git a/frontend/jsSHA/test/genHashRounds.py b/frontend/jsSHA/test/genHashRounds.py new file mode 100755 index 0000000..12f3845 --- /dev/null +++ b/frontend/jsSHA/test/genHashRounds.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python2 +import binascii +import hashlib + +import sha3 + +def main(): + hash_funcs = [ + ('SHA-1', hashlib.sha1), + ('SHA-224', hashlib.sha224), + ('SHA-256', hashlib.sha256), + ('SHA-384', hashlib.sha384), + ('SHA-512', hashlib.sha512)] + + for (sha_type, sha_func) in hash_funcs: + digest = sha_func('abc').digest() + + # Only loop 4 times since an iteration was done above + for x in xrange(0, 4): + digest = sha_func(digest).digest() + print('{} with 5 Rounds: {}'.format(sha_type, digest.encode('hex'))) + + # Loop another 5 times to get to 10 + for x in xrange(0, 5): + digest = sha_func(digest).digest() + print('{} with 10 Rounds: {}'.format(sha_type, digest.encode('hex'))) + + # SHA3 is handled differently as it's not in hashlib. + # Use the SHA3 creators' version + hash3_funcs = [ + ('SHA3-224', sha3.SHA3_224), + ('SHA3-256', sha3.SHA3_256), + ('SHA3-384', sha3.SHA3_384), + ('SHA3-512', sha3.SHA3_512)] + + for (sha_type, sha_func) in hash3_funcs: + digest = sha_func([ord(c) for c in 'abc']) + + # Only loop 4 times since an iteration was done above + for x in xrange(0, 4): + digest = sha_func(digest) + print('{} with 5 Rounds: {}'.format(sha_type, binascii.hexlify(digest))) + + # Loop another 5 times to get to 10 + for x in xrange(0, 5): + digest = sha_func(digest) + print('{} with 10 Rounds: {}'.format(sha_type, binascii.hexlify(digest))) + + hash3_funcs = [ + ('SHAKE128', sha3.SHAKE128), + ('SHAKE256', sha3.SHAKE256)] + + for (sha_type, sha_func) in hash3_funcs: + digest = sha_func([ord(c) for c in 'abc'], 31) + + # Only loop 4 times since an iteration was done above + for x in xrange(0, 4): + digest = sha_func(digest, 31) + print('{} with 5 Rounds: {}'.format(sha_type, binascii.hexlify(digest))) + + # Loop another 5 times to get to 10 + for x in xrange(0, 5): + digest = sha_func(digest, 31) + print('{} with 10 Rounds: {}'.format(sha_type, binascii.hexlify(digest))) + +if ('__main__' == __name__): + main() diff --git a/frontend/jsSHA/test/genShake.py b/frontend/jsSHA/test/genShake.py new file mode 100755 index 0000000..f4be6d5 --- /dev/null +++ b/frontend/jsSHA/test/genShake.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python2 +import binascii + +import sha3 + +def main(): + test_vectors = { + 'Short': 'abc', + 'Medium': 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu', + 'Long': 'a' * 1000000 + } + + hash_funcs = {'SHAKE128': sha3.SHAKE128, 'SHAKE256': sha3.SHAKE256} + output_lens = [31, 63] + + for hash_name, hash_func in hash_funcs.items(): + for vector_name, vector_value in test_vectors.items(): + for output_len in output_lens: + print('%s with %s UTF-8 Input and %d bit Output: %s' % ( + hash_name, + vector_name, + output_len * 8, + binascii.hexlify(hash_func(vector_value.encode(), output_len)).decode() + ) + ) + print('%s with %s UTF-16BE Input and %d bit Output: %s' % ( + hash_name, + vector_name, + output_len * 8, + binascii.hexlify(hash_func(vector_value.encode('UTF-16BE'), output_len)).decode() + ) + ) + print('%s with %s UTF-16LE Input and %d bit Output: %s' % ( + hash_name, + vector_name, + output_len * 8, + binascii.hexlify(hash_func(vector_value.encode('UTF-16LE'), output_len)).decode() + ) + ) + +if ('__main__' == __name__): + main() diff --git a/frontend/jsSHA/test/hash-file.html b/frontend/jsSHA/test/hash-file.html new file mode 100755 index 0000000..acc1121 --- /dev/null +++ b/frontend/jsSHA/test/hash-file.html @@ -0,0 +1,114 @@ + + + + jsSHA (http://caligatio.github.com/jsSHA/) - File Test + + + + + + + Drop this project's LICENSE file to test, or any other file to find its hashes: +

+ +

+ NOTE: This may not work in Internet Explorer +
+ + diff --git a/frontend/jsSHA/test/sha3.py b/frontend/jsSHA/test/sha3.py new file mode 100755 index 0000000..c54b183 --- /dev/null +++ b/frontend/jsSHA/test/sha3.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +# Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, +# Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby +# denoted as "the implementer". +# +# For more information, feedback or questions, please refer to our websites: +# http://keccak.noekeon.org/ +# http://keyak.noekeon.org/ +# http://ketje.noekeon.org/ +# +# To the extent possible under law, the implementer has waived all copyright +# and related or neighboring rights to the source code in this file. +# http://creativecommons.org/publicdomain/zero/1.0/ + +def ROL64(a, n): + return ((a >> (64-(n%64))) + (a << (n%64))) % (1 << 64) + +def KeccakF1600onLanes(lanes): + R = 1 + for round in range(24): + # θ + C = [lanes[x][0] ^ lanes[x][1] ^ lanes[x][2] ^ lanes[x][3] ^ lanes[x][4] for x in range(5)] + D = [C[(x+4)%5] ^ ROL64(C[(x+1)%5], 1) for x in range(5)] + lanes = [[lanes[x][y]^D[x] for y in range(5)] for x in range(5)] + # ρ and π + (x, y) = (1, 0) + current = lanes[x][y] + for t in range(24): + (x, y) = (y, (2*x+3*y)%5) + (current, lanes[x][y]) = (lanes[x][y], ROL64(current, (t+1)*(t+2)//2)) + # χ + for y in range(5): + T = [lanes[x][y] for x in range(5)] + for x in range(5): + lanes[x][y] = T[x] ^((~T[(x+1)%5]) & T[(x+2)%5]) + # ι + for j in range(7): + R = ((R << 1) ^ ((R >> 7)*0x71)) % 256 + if (R & 2): + lanes[0][0] = lanes[0][0] ^ (1 << ((1<> (8*i)) % 256 for i in range(8)) + +def KeccakF1600(state): + lanes = [[load64(state[8*(x+5*y):8*(x+5*y)+8]) for y in range(5)] for x in range(5)] + lanes = KeccakF1600onLanes(lanes) + state = bytearray(200) + for x in range(5): + for y in range(5): + state[8*(x+5*y):8*(x+5*y)+8] = store64(lanes[x][y]) + return state + +def Keccak(rate, capacity, inputBytes, delimitedSuffix, outputByteLen): + outputBytes = bytearray() + state = bytearray([0 for i in range(200)]) + rateInBytes = rate//8 + blockSize = 0 + if (((rate + capacity) != 1600) or ((rate % 8) != 0)): + return + inputOffset = 0 + # === Absorb all the input blocks === + while(inputOffset < len(inputBytes)): + blockSize = min(len(inputBytes)-inputOffset, rateInBytes) + for i in range(blockSize): + state[i] = state[i] ^ inputBytes[i+inputOffset] + inputOffset = inputOffset + blockSize + if (blockSize == rateInBytes): + state = KeccakF1600(state) + blockSize = 0 + # === Do the padding and switch to the squeezing phase === + state[blockSize] = state[blockSize] ^ delimitedSuffix + if (((delimitedSuffix & 0x80) != 0) and (blockSize == (rateInBytes-1))): + state = KeccakF1600(state) + state[rateInBytes-1] = state[rateInBytes-1] ^ 0x80 + state = KeccakF1600(state) + # === Squeeze out all the output blocks === + while(outputByteLen > 0): + blockSize = min(outputByteLen, rateInBytes) + outputBytes = outputBytes + state[0:blockSize] + outputByteLen = outputByteLen - blockSize + if (outputByteLen > 0): + state = KeccakF1600(state) + return outputBytes + +def SHAKE128(inputBytes, outputByteLen): + return Keccak(1344, 256, inputBytes, 0x1F, outputByteLen) + +def SHAKE256(inputBytes, outputByteLen): + return Keccak(1088, 512, inputBytes, 0x1F, outputByteLen) + +def SHA3_224(inputBytes): + return Keccak(1152, 448, inputBytes, 0x06, 224//8) + +def SHA3_256(inputBytes): + return Keccak(1088, 512, inputBytes, 0x06, 256//8) + +def SHA3_384(inputBytes): + return Keccak(832, 768, inputBytes, 0x06, 384//8) + +def SHA3_512(inputBytes): + return Keccak(576, 1024, inputBytes, 0x06, 512//8) diff --git a/frontend/jsSHA/test/test.html b/frontend/jsSHA/test/test.html new file mode 100755 index 0000000..22142af --- /dev/null +++ b/frontend/jsSHA/test/test.html @@ -0,0 +1,38 @@ + + + + jsSHA (http://caligatio.github.com/jsSHA/) Tests + + + + + + + + + + + + +

jsSHA Hash Test Page

+

Hash Tests

+

+ These tests implement the test vectors found on the NIST Examples page. +

+ +

+ Note that the "Long" test involves hashing a 1,000,000 character string and can take quite a while depending on the browser and machine. +

+ +

Custom Tests

+

+ Values for SHAKE tests can be generated using the included genShake.py. Similarly, values for the multiple round tests can be generated using the included getHashRounds.py. +

+ +
+ + diff --git a/frontend/jsSHA/test/test_hashes.js b/frontend/jsSHA/test/test_hashes.js new file mode 100755 index 0000000..1a9ab98 --- /dev/null +++ b/frontend/jsSHA/test/test_hashes.js @@ -0,0 +1,1213 @@ +/* Kind of hack to get the tests working both in the browser and node.js */ + +/*jslint + bitwise: true, multivar: true, for: true, this: true, sub: true, esversion: 3 +*/ +if (("undefined" !== typeof module) && module["exports"]) +{ + mocha = require("mocha"); + chai = require("chai"); + jsSHA = require("../src/sha_dev.js"); +} + +String.prototype.repeat = function(times) { + return (new Array(times + 1)).join(this); +}; + +function hexToArrayBuffer(hexStr) +{ + var arrayBuffer = new ArrayBuffer(hexStr.length / 2), arrView = new Uint8Array(arrayBuffer), i; + + for (i = 0; i < hexStr.length; i += 2) + { + num = parseInt(hexStr.substr(i, 2), 16); + if (!isNaN(num)) + { + arrView[i >>> 1] = num; + } + else + { + throw new Error("String of HEX type contains invalid characters"); + } + } + + return arrayBuffer; +} + +function arrayBufferToHex(arrayBuffer) +{ + var hex_tab = "0123456789abcdef", arrView = new Uint8Array(arrayBuffer), i, str = ""; + + for (i = 0; i < arrView.length; i += 1) + { + str += (hex_tab.charAt((arrView[i] >>> 4) & 0xF) + + hex_tab.charAt(arrView[i] & 0xF)); + } + + return str; +} + +/* These are used often so make a global copy that everything can reference */ +var millionaAscii = "a".repeat(1000000), millionaHex = "61".repeat(1000000), millionaB64 = "YWFh".repeat(333333) + "YQ=="; + +/* ============================================================================ + * Begin Basic Hash Tests + * ============================================================================ + */ +var hashTests = [ + { + "hash": "SHA-1", + "tests" : [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF8"}, + {"type": "HEX", "value": "616263"}, + {"type": "B64", "value": "YWJj"} + ], + "outputs" : [ + {"type": "HEX", "value": "a9993e364706816aba3e25717850c26c9cd0d89d"}, + {"type": "B64", "value": "qZk+NkcGgWq6PiVxeFDCbJzQ2J0="} + ] + }, + { + "name": "Medium", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF8"}, + {"type": "HEX", "value": "6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071"}, + {"type": "B64", "value": "YWJjZGJjZGVjZGVmZGVmZ2VmZ2hmZ2hpZ2hpamhpamtpamtsamtsbWtsbW5sbW5vbW5vcG5vcHE="} + ], + "outputs" : [ + {"type": "HEX", "value": "84983e441c3bd26ebaae4aa1f95129e5e54670f1"}, + {"type": "B64", "value": "hJg+RBw70m66rkqh+VEp5eVGcPE="} + ] + }, + { + "name": "Long", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF8"}, + {"type": "HEX", "value": millionaHex}, + {"type": "B64", "value": millionaB64} + ], + "outputs" : [ + {"type": "HEX", "value": "34aa973cd4c4daa4f61eeb2bdbad27316534016f"}, + {"type": "B64", "value": "NKqXPNTE2qT2Husr260nMWU0AW8="} + ] + }, + { + "name": "Short UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "af68535cb6d1af8b6e3c60305cf0bfae6c57de36"} + ] + }, + { + "name": "Medium UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "bef8f6cd143d7fa6d9f726eef2ff444391fe76ac"} + ] + }, + { + "name": "Long UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "94359e86fb2a95ceed60bd0b58bcffd7192d9c16"} + ] + }, + { + "name": "Short UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "9f04f41a848514162050e3d68c1a7abb441dc2b5"} + ] + }, + { + "name": "Medium UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "51d7d8769ac72c409c5b0e3f69c60adc9a039014"} + ] + }, + { + "name": "Long UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "c4609560a108a0c626aa7f2b38a65566739353c5"} + ] + } + ] + }, + { + "hash": "SHA-224", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF8"}, + {"type": "HEX", "value": "616263"}, + {"type": "B64", "value": "YWJj"} + ], + "outputs" : [ + {"type": "HEX", "value": "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"}, + {"type": "B64", "value": "Iwl9IjQF2CKGQqR3vaJVsyqtvOS9oLP342ydpw=="} + ] + }, + { + "name": "Medium", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF8"}, + {"type": "HEX", "value": "6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071"}, + {"type": "B64", "value": "YWJjZGJjZGVjZGVmZGVmZ2VmZ2hmZ2hpZ2hpamhpamtpamtsamtsbWtsbW5sbW5vbW5vcG5vcHE="} + ], + "outputs" : [ + {"type": "HEX", "value": "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525"}, + {"type": "B64", "value": "dTiLFlEndsxdul2h/YkBULDGRVy09YsZUlIlJQ=="} + ] + }, + { + "name": "Long", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF8"}, + {"type": "HEX", "value": millionaHex}, + {"type": "B64", "value": millionaB64} + ], + "outputs" : [ + {"type": "HEX", "value": "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67"}, + {"type": "B64", "value": "IHlGVZgMkdi7tMHql2GKS/A/QlgZSLLuTuetZw=="} + ] + }, + { + "name": "Short UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "4751f7e6ffd48fd96549183745ed3b51517cf79479475670299dcaa1"} + ] + }, + { + "name": "Medium UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "1591f5aa2b329fa3cd3645ca52e62cb859fee74922e4495783e17213"} + ] + }, + { + "name": "Long UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "3bd39fdaa867ff89948d8699c179b79ece1eb8a78d2413481824397a"} + ] + }, + { + "name": "Short UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "57ba76af9d4846f1e08697d79422ea3f516fe3145ad7fc4c93ba85ac"} + ] + }, + { + "name": "Medium UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "2d30dab9655cd28a84790ae02e742d28b02c1d5d2e7196cee1732ca5"} + ] + }, + { + "name": "Long UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "11bb18d73d725c7d104e1ca15ee9b5094c3703ac152ffb2484b45a78"} + ] + } + ] + }, + { + "hash": "SHA3-224", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF8"}, + {"type": "HEX", "value": "616263"}, + {"type": "B64", "value": "YWJj"} + ], + "outputs" : [ + {"type": "HEX", "value": "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf"}, + {"type": "B64", "value": "5kKCTD+M8krQkjTufTx2b8mjpRaNDJStc7Rv3w=="} + ] + }, + { + "name": "Medium", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF8"}, + {"type": "HEX", "value": "6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071"}, + {"type": "B64", "value": "YWJjZGJjZGVjZGVmZGVmZ2VmZ2hmZ2hpZ2hpamhpamtpamtsamtsbWtsbW5sbW5vbW5vcG5vcHE="} + ], + "outputs" : [ + {"type": "HEX", "value": "8a24108b154ada21c9fd5574494479ba5c7e7ab76ef264ead0fcce33"}, + {"type": "B64", "value": "iiQQixVK2iHJ/VV0SUR5ulx+erdu8mTq0PzOMw=="} + ] + }, + { + "name": "Long", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF8"}, + {"type": "HEX", "value": millionaHex}, + {"type": "B64", "value": millionaB64} + ], + "outputs" : [ + {"type": "HEX", "value": "d69335b93325192e516a912e6d19a15cb51c6ed5c15243e7a7fd653c"}, + {"type": "B64", "value": "1pM1uTMlGS5RapEubRmhXLUcbtXBUkPnp/1lPA=="} + ] + }, + { + "name": "Short UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "d5c49292551814f4dd267d4b9f3e10bc12d97ae01a75688fc94973c6"} + ] + }, + { + "name": "Medium UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "e8d8ae12828497d89f36e573ab18f6237028e063f0bc1e8dce812a54"} + ] + }, + { + "name": "Long UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "ea9658eb20be9aaeb24ced54c9e9688dd127d249e92b3e3e9b47bbe8"} + ] + }, + { + "name": "Short UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "bcaf706ac4a322d3b95f7fcd33e623a82b83ffa5b4044df21fb970de"} + ] + }, + { + "name": "Medium UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "5e3d1dc2dc50b3d3bf03beac724d6d3203231eea900449fd4f542540"} + ] + }, + { + "name": "Long UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "116fbbbb67efdb66c257763918ff03c2daca1a726a2559d0d5c31dc1"} + ] + } + ] + }, + { + "hash": "SHA-256", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF8"}, + {"type": "HEX", "value": "616263"}, + {"type": "B64", "value": "YWJj"} + ], + "outputs" : [ + {"type": "HEX", "value": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"}, + {"type": "B64", "value": "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0="} + ] + }, + { + "name": "Medium", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF8"}, + {"type": "HEX", "value": "6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071"}, + {"type": "B64", "value": "YWJjZGJjZGVjZGVmZGVmZ2VmZ2hmZ2hpZ2hpamhpamtpamtsamtsbWtsbW5sbW5vbW5vcG5vcHE="} + ], + "outputs" : [ + {"type": "HEX", "value": "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"}, + {"type": "B64", "value": "JI1qYdIGOLjlwCaTDD5gOaM85Flk/yFn9uzt1BnbBsE="} + ] + }, + { + "name": "Long", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF8"}, + {"type": "HEX", "value": millionaHex}, + {"type": "B64", "value": millionaB64} + ], + "outputs" : [ + {"type": "HEX", "value": "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"}, + {"type": "B64", "value": "zcduXJkU+5KBocfihNc+Z/GAmkiklyAOBG05zMcRLNA="} + ] + }, + { + "name": "Short UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "e265e98c934ff1ff7d55359eed484c4581b3c372bac922350c645fb5fd937280"} + ] + }, + { + "name": "Medium UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "1d04116da99940f5eb149d21c7a556e1625839dd7fd74bcf4c3028b97b9da57f"} + ] + }, + { + "name": "Long UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "b21c3efa2f1a0075d566f7354aa51f0156e66ed209ee708902aa5953a7eb8140"} + ] + }, + { + "name": "Short UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "13e228567e8249fce53337f25d7970de3bd68ab2653424c7b8f9fd05e33caedf"} + ] + }, + { + "name": "Medium UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "fa84fa96dd6f1a0fda1769cacec9bac12efadad72ab60ff68ec5ae1a4d3fab8e"} + ] + }, + { + "name": "Long UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "a0bc50078623514a87e96de81d8d200527a1b1150acd92252d88aa109dfa0aa4"} + ] + } + ] + }, + { + "hash": "SHA3-256", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF8"}, + {"type": "HEX", "value": "616263"}, + {"type": "B64", "value": "YWJj"} + ], + "outputs" : [ + {"type": "HEX", "value": "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"}, + {"type": "B64", "value": "Ophdp0/iJbIEXBcta9OQvYVfCG4+nVJbRr/iRRFDFTI="} + ] + }, + { + "name": "Medium", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF8"}, + {"type": "HEX", "value": "6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071"}, + {"type": "B64", "value": "YWJjZGJjZGVjZGVmZGVmZ2VmZ2hmZ2hpZ2hpamhpamtpamtsamtsbWtsbW5sbW5vbW5vcG5vcHE="} + ], + "outputs" : [ + {"type": "HEX", "value": "41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376"}, + {"type": "B64", "value": "QcDboqnWJAhJEAN2qCNeLILhuZmKmZ4h2zLdl0ltM3Y="} + ] + }, + { + "name": "Long", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF8"}, + {"type": "HEX", "value": millionaHex}, + {"type": "B64", "value": millionaB64} + ], + "outputs" : [ + {"type": "HEX", "value": "5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1"}, + {"type": "B64", "value": "XIh1rkdKNjS6T9VeyFv/1mHzKsp1xtaZ0M3LbBFYkcE="} + ] + }, + { + "name": "Short UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "a3198ab574d5b50d1a9aa1e34dbdaaa50ed6df67031bf66838e9c8b902a05feb"} + ] + }, + { + "name": "Medium UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "5cbbd5115111f239eaa31c106c3497e785bfe49dcae896642aa6e21f631bd4d5"} + ] + }, + { + "name": "Long UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "a9cd30fe7649d1c0d8ba700d01fde163a95e2bccb68c3faae8cc300c44264725"} + ] + }, + { + "name": "Short UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "a7fc119e08d5dbcdbd7f69d7bba10866c62ba2a3e31577a7d7c582f4ec20b78b"} + ] + }, + { + "name": "Medium UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "86037e690b1baa71450a0c2314cacbb08e0c571019f7f1f98aac1921c2d53889"} + ] + }, + { + "name": "Long UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "73b713b341e839a18e5ad439771ab52a71656662a0c019d9d1dcf9b001819a57"} + ] + } + ] + }, + { + "hash": "SHA-384", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF8"}, + {"type": "HEX", "value": "616263"}, + {"type": "B64", "value": "YWJj"} + ], + "outputs" : [ + {"type": "HEX", "value": "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"}, + {"type": "B64", "value": "ywB1P0WjXou1oD1pmsZQBycsMqsO3tFjGotgWkP/W+2AhgcroefMI1i67KE0yCWn"} + ] + }, + { + "name": "Medium", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF8"}, + {"type": "HEX", "value": "61626364656667686263646566676869636465666768696A6465666768696A6B65666768696A6B6C666768696A6B6C6D6768696A6B6C6D6E68696A6B6C6D6E6F696A6B6C6D6E6F706A6B6C6D6E6F70716B6C6D6E6F7071726C6D6E6F707172736D6E6F70717273746E6F707172737475"}, + {"type": "B64", "value": "YWJjZGVmZ2hiY2RlZmdoaWNkZWZnaGlqZGVmZ2hpamtlZmdoaWprbGZnaGlqa2xtZ2hpamtsbW5oaWprbG1ub2lqa2xtbm9wamtsbW5vcHFrbG1ub3Bxcmxtbm9wcXJzbW5vcHFyc3Rub3BxcnN0dQ=="} + ], + "outputs" : [ + {"type": "HEX", "value": "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039"}, + {"type": "B64", "value": "CTMMM/cRR+g9GS/Hgs0bR1MRGxc7OwXSL6CAhuOw9xL8x8caVX4tuWbD6fqRdGA5"} + ] + }, + { + "name": "Long", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF8"}, + {"type": "HEX", "value": millionaHex}, + {"type": "B64", "value": millionaB64} + ], + "outputs" : [ + {"type": "HEX", "value": "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985"}, + {"type": "B64", "value": "nQ4YCXFkdMsIboNOMQpKHO0UnpwA8khSeXLOxXBMKlsHuLPcOOzE666X3dh/PYmF"} + ] + }, + { + "name": "Short UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "46591d403db207914d0cc5b58ad3c665e79fd957753594cf815d28b7115fe776395643a49d15ab8f4e24c13a36cdb9ec"} + ] + }, + { + "name": "Medium UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "71a48b0abb2245253c2bb9fcebb4e7149a9b214b8598d11352b9a3e07de1f35c059c8153545070229d19880af122aa48"} + ] + }, + { + "name": "Long UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "e26cb55351464f57b23def3b2447281dc8ba4e38f543b20bf7ba026f1f2bea57d54d3a721dd97337a8022a26bbef2c49"} + ] + }, + { + "name": "Short UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "9b7ce7c7af46e400a37c8099cb4bbb5d0408061dd74cdb5dac7661bed1e53724bd07f299e265f400802a48d2e0b2092c"} + ] + }, + { + "name": "Medium UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "3c5fbafef52900a32840433c972999429d5c157426fdfb5c4968278f25bd4fe4f3b7aee8ae060695b05f61e595609637"} + ] + }, + { + "name": "Long UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "85056c62b9b2eba33a1ea69d06e32e71715188b25d3f7a2bc37be377890c4b0c08e7f55bc83550f0fe27a209088bc671"} + ] + } + ] + }, + { + "hash": "SHA3-384", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF8"}, + {"type": "HEX", "value": "616263"}, + {"type": "B64", "value": "YWJj"} + ], + "outputs" : [ + {"type": "HEX", "value": "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25"}, + {"type": "B64", "value": "7AFJgohRb8kmRZ9Y4satjfm0c8sPwIwlltp88OSb5LKY2IzqknrH9Tnx7fIoN20l"} + ] + }, + { + "name": "Medium", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF8"}, + {"type": "HEX", "value": "61626364656667686263646566676869636465666768696A6465666768696A6B65666768696A6B6C666768696A6B6C6D6768696A6B6C6D6E68696A6B6C6D6E6F696A6B6C6D6E6F706A6B6C6D6E6F70716B6C6D6E6F7071726C6D6E6F707172736D6E6F70717273746E6F707172737475"}, + {"type": "B64", "value": "YWJjZGVmZ2hiY2RlZmdoaWNkZWZnaGlqZGVmZ2hpamtlZmdoaWprbGZnaGlqa2xtZ2hpamtsbW5oaWprbG1ub2lqa2xtbm9wamtsbW5vcHFrbG1ub3Bxcmxtbm9wcXJzbW5vcHFyc3Rub3BxcnN0dQ=="} + ], + "outputs" : [ + {"type": "HEX", "value": "79407d3b5916b59c3e30b09822974791c313fb9ecc849e406f23592d04f625dc8c709b98b43b3852b337216179aa7fc7"}, + {"type": "B64", "value": "eUB9O1kWtZw+MLCYIpdHkcMT+57MhJ5AbyNZLQT2JdyMcJuYtDs4UrM3IWF5qn/H"} + ] + }, + { + "name": "Long", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF8"}, + {"type": "HEX", "value": millionaHex}, + {"type": "B64", "value": millionaB64} + ], + "outputs" : [ + {"type": "HEX", "value": "eee9e24d78c1855337983451df97c8ad9eedf256c6334f8e948d252d5e0e76847aa0774ddb90a842190d2c558b4b8340"}, + {"type": "B64", "value": "7uniTXjBhVM3mDRR35fIrZ7t8lbGM0+OlI0lLV4OdoR6oHdN25CoQhkNLFWLS4NA"} + ] + }, + { + "name": "Short UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "1f7807100bfb7293a3f94c1b410b9d413497ad81ec7032442f72c832891a251632dcda5c5b3b63233b71c6305379fe3d"} + ] + }, + { + "name": "Medium UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "b43e4a80f5ac9cf4f555dcca7b5a0cc0c7bf6f14ea30dbef4c7db98d18f159536a4211b31aaca5157f4fbae599ced799"} + ] + }, + { + "name": "Long UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "91f1c447390dd54913eceab5d1036b55d6cedd2a1cee7f99627d7183a6f3125632689aa3e4716a8e96a57b2da1fef69a"} + ] + }, + { + "name": "Short UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "3f41b737dcc1e28410b9ad759f3687b31703247d36e98f3e1d96b1725d798d4e9c58a50e6217d4410d0ea81bc788f7b8"} + ] + }, + { + "name": "Medium UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "4bb8558d278d4e5b3b26e4173acc2c55a840f74ceb5ae0d9533eee416c3d3b1b4772ab0f0499e47fd03e0b4d579790f6"} + ] + }, + { + "name": "Long UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "ea60905cf5146f377d87be1e7774d9dfdf9500722023efbf5602b511417e44b69a5518b26f944eff8a97cfa662adfa01"} + ] + } + ] + }, + { + "hash": "SHA-512", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF8"}, + {"type": "HEX", "value": "616263"}, + {"type": "B64", "value": "YWJj"} + ], + "outputs" : [ + {"type": "HEX", "value": "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"}, + {"type": "B64", "value": "3a81oZNherrMQXNJriBBMRLm+k6JqX6iCp7u5ktV05ohkpkqJ0/BqDa6PCOj/uu9RU1EI2Q86A4qmslPpUyknw=="} + ] + }, + { + "name": "Medium", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF8"}, + {"type": "HEX", "value": "61626364656667686263646566676869636465666768696A6465666768696A6B65666768696A6B6C666768696A6B6C6D6768696A6B6C6D6E68696A6B6C6D6E6F696A6B6C6D6E6F706A6B6C6D6E6F70716B6C6D6E6F7071726C6D6E6F707172736D6E6F70717273746E6F707172737475"}, + {"type": "B64", "value": "YWJjZGVmZ2hiY2RlZmdoaWNkZWZnaGlqZGVmZ2hpamtlZmdoaWprbGZnaGlqa2xtZ2hpamtsbW5oaWprbG1ub2lqa2xtbm9wamtsbW5vcHFrbG1ub3Bxcmxtbm9wcXJzbW5vcHFyc3Rub3BxcnN0dQ=="} + ], + "outputs" : [ + {"type": "HEX", "value": "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"}, + {"type": "B64", "value": "jpWbddrjE9qM9PcoFPwUP493ecbrn3+hcpmurbaIkBhQHSieSQD35DMbmd7EtUM6x9Mp7rbdJlReluVbh0vpCQ=="} + ] + }, + { + "name": "Long", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF8"}, + {"type": "HEX", "value": millionaHex}, + {"type": "B64", "value": millionaB64} + ], + "outputs" : [ + {"type": "HEX", "value": "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"}, + {"type": "B64", "value": "5xhIPQznaWROLkLHvBW0Y44fmLE7IEQoVjKoA6+pc+veD/JEh36mCkywQyzld8Mb6wCcXCxJqi5OrbIXrYzAmw=="} + ] + }, + { + "name": "Short UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "cec00c412e5fe0ab4ff6ee7da097cce9b9ee67c8eeb3e99e11aec89dff1b8a2e417e37369c9c1bd65ce70f1b6be1ebf4ddbcaf2312fded40260fd55cf2ffe097"} + ] + }, + { + "name": "Medium UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "8f56290fb4a9cabfc427c0998abbef6527112db8c6916a9908421d97c820880b7a4137b29b7f6449b8f92a7666d85741faa01bdadb9b5d588570227b9be83360"} + ] + }, + { + "name": "Long UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "c89b6863e6568833664c449879f42fbe3e72b8054a43af61885904f72cebcc1a49b0d776b571cbf44530a291b5f5e2e26d8daa50047e5f0efc0b8e01a2ae6a08"} + ] + }, + { + "name": "Short UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "add8b8154df7a734d2947a981f4e61c5366710d610040e5b54894d1006e89283cba082287ed5dd4c25cdaa5af56d24ab9fbedc56897130b0b5f3e50c7f9ee6df"} + ] + }, + { + "name": "Medium UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "d14cbc5ecfd355acf9d181ee878b91db4f30a7b03f7904388f252a77b1fffa9feb96803698294556ff7ce87ad0ab3ae748df979603733105ff3ac038e51483a3"} + ] + }, + { + "name": "Long UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "5e6b9aa02688b69fe5ebe842aeab69b22144d815ca603051f2e61ab752d202f85dc54252d19f9d62381a2d5e88ab391b7c6565d5e0d39925a4ad5b07e99925bd"} + ] + } + ] + }, + { + "hash": "SHA3-512", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF8"}, + {"type": "HEX", "value": "616263"}, + {"type": "B64", "value": "YWJj"} + ], + "outputs" : [ + {"type": "HEX", "value": "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"}, + {"type": "B64", "value": "t1GFCxpXFopWk82SS2sJbgj2IYJ0RPcNiE9dAkDScS4Q4RbpGSrzyRp+xXZH45NAVzQLTPQI1aVlkvgnTuxT8A=="} + ] + }, + { + "name": "Medium", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF8"}, + {"type": "HEX", "value": "61626364656667686263646566676869636465666768696A6465666768696A6B65666768696A6B6C666768696A6B6C6D6768696A6B6C6D6E68696A6B6C6D6E6F696A6B6C6D6E6F706A6B6C6D6E6F70716B6C6D6E6F7071726C6D6E6F707172736D6E6F70717273746E6F707172737475"}, + {"type": "B64", "value": "YWJjZGVmZ2hiY2RlZmdoaWNkZWZnaGlqZGVmZ2hpamtlZmdoaWprbGZnaGlqa2xtZ2hpamtsbW5oaWprbG1ub2lqa2xtbm9wamtsbW5vcHFrbG1ub3Bxcmxtbm9wcXJzbW5vcHFyc3Rub3BxcnN0dQ=="} + ], + "outputs" : [ + {"type": "HEX", "value": "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185"}, + {"type": "B64", "value": "r+uy71QuZXnFDK0G0uV4+fjdaIHX3IJNJjYP7r8YpPpz4yYRIpSO/P1JLnToLiGJ7Q+0QNGH84InDLRV8h3RhQ=="} + ] + }, + { + "name": "Long", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF8"}, + {"type": "HEX", "value": millionaHex}, + {"type": "B64", "value": millionaB64} + ], + "outputs" : [ + {"type": "HEX", "value": "3c3a876da14034ab60627c077bb98f7e120a2a5370212dffb3385a18d4f38859ed311d0a9d5141ce9cc5c66ee689b266a8aa18ace8282a0e0db596c90b0a7b87"}, + {"type": "B64", "value": "PDqHbaFANKtgYnwHe7mPfhIKKlNwIS3/szhaGNTziFntMR0KnVFBzpzFxm7mibJmqKoYrOgoKg4NtZbJCwp7hw=="} + ] + }, + { + "name": "Short UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "e056f3f5c960c7adb4d8c45e6b91604ecd0d98e7f082dc63ace7da388fb9908ccf8a548cbcf8de7b069aa5c1005f09a4d8a28dcec324801b565673342e74caf1"} + ] + }, + { + "name": "Medium UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "b10dd0b98cbd73190e06b5720404cfb0f122a0ff7f063ad4a6ed6ed609eb5e1d3c87260ecc7b877fdf6592dc521c845ae06a5e106928e90f4021bac16c030a8d"} + ] + }, + { + "name": "Long UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "5f0b393b1a9bc521289a721291a860d95af6c420a1a16b0810d203870a1b37a0d047e000de95208d63fb373d2207dfd0cde5024692aebfd947e78c6c3ddd5ed8"} + ] + }, + { + "name": "Short UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "115fbb697dc2dcbcb61888d910a34d01162842f5329ead230870e98bcb75afb516b6440241f51192b7a67f6788b6396201dab5f205d6cd940312bcfe958b8aaa"} + ] + }, + { + "name": "Medium UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "ebe4b4d745a02d3fe56f23d38b6cf2674b4684696704586fc95f7be033c1140a9bdd530f80b867f3e927d1eb24969c8a2bb385ba0596e4ae1e0c2d84eff7266c"} + ] + }, + { + "name": "Long UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "b17e56d64e29cbe22943719ff00912b9866e6d372a6fe19130e7e2bb6d8572d002f8be5a547b1774c542e1089131a64106f5b687da295a3a92ec941301622596"} + ] + } + ] + }, + { + "hash": "SHAKE128", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF8"}, + {"type": "HEX", "value": "616263"}, + {"type": "B64", "value": "YWJj"} + ], + "outputs" : [ + {"type": "HEX", "value": "5881092dd818bf5cf8a3ddb793fbcba74097d5c526a6d35f97b83351940f2c", "shakeLen": 248}, + {"type": "B64", "value": "WIEJLdgYv1z4o923k/vLp0CX1cUmptNfl7gzUZQPLA==", "shakeLen": 248}, + {"type": "HEX", "value": "5881092dd818bf5cf8a3ddb793fbcba74097d5c526a6d35f97b83351940f2cc844c50af32acd3f2cdd066568706f509bc1bdde58295dae3f891a9a0fca5783", "shakeLen": 504}, + {"type": "B64", "value": "WIEJLdgYv1z4o923k/vLp0CX1cUmptNfl7gzUZQPLMhExQrzKs0/LN0GZWhwb1Cbwb3eWCldrj+JGpoPyleD", "shakeLen": 504} + ] + }, + { + "name": "Medium", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF8"}, + {"type": "HEX", "value": "61626364656667686263646566676869636465666768696A6465666768696A6B65666768696A6B6C666768696A6B6C6D6768696A6B6C6D6E68696A6B6C6D6E6F696A6B6C6D6E6F706A6B6C6D6E6F70716B6C6D6E6F7071726C6D6E6F707172736D6E6F70717273746E6F707172737475"}, + {"type": "B64", "value": "YWJjZGVmZ2hiY2RlZmdoaWNkZWZnaGlqZGVmZ2hpamtlZmdoaWprbGZnaGlqa2xtZ2hpamtsbW5oaWprbG1ub2lqa2xtbm9wamtsbW5vcHFrbG1ub3Bxcmxtbm9wcXJzbW5vcHFyc3Rub3BxcnN0dQ=="} + ], + "outputs" : [ + {"type": "HEX", "value": "7b6df6ff181173b6d7898d7ff63fb07b7c237daf471a5ae5602adbccef9ccf", "shakeLen": 248}, + {"type": "B64", "value": "e232/xgRc7bXiY1/9j+we3wjfa9HGlrlYCrbzO+czw==", "shakeLen": 248}, + {"type": "HEX", "value": "7b6df6ff181173b6d7898d7ff63fb07b7c237daf471a5ae5602adbccef9ccf4b37e06b4a3543164ffbe0d0557c02f9b25ad434005526d88ca04a6094b93ee5", "shakeLen": 504}, + {"type": "B64", "value": "e232/xgRc7bXiY1/9j+we3wjfa9HGlrlYCrbzO+cz0s34GtKNUMWT/vg0FV8AvmyWtQ0AFUm2IygSmCUuT7l", "shakeLen": 504} + ] + }, + { + "name": "Long", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF8"}, + {"type": "HEX", "value": millionaHex}, + {"type": "B64", "value": millionaB64} + ], + "outputs" : [ + {"type": "HEX", "value": "9d222c79c4ff9d092cf6ca86143aa411e369973808ef97093255826c5572ef", "shakeLen": 248}, + {"type": "B64", "value": "nSIsecT/nQks9sqGFDqkEeNplzgI75cJMlWCbFVy7w==", "shakeLen": 248}, + {"type": "HEX", "value": "9d222c79c4ff9d092cf6ca86143aa411e369973808ef97093255826c5572ef58424c4b5c28475ffdcf981663867fec6321c1262e387bccf8ca676884c4a9d0", "shakeLen": 504}, + {"type": "B64", "value": "nSIsecT/nQks9sqGFDqkEeNplzgI75cJMlWCbFVy71hCTEtcKEdf/c+YFmOGf+xjIcEmLjh7zPjKZ2iExKnQ", "shakeLen": 504} + ] + }, + { + "name": "Short UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "40f2bdd295c3208f7f2f3436d2cab325ac0e7f204e04430853fdc217db767b", "shakeLen": 248}, + {"type": "HEX", "value": "40f2bdd295c3208f7f2f3436d2cab325ac0e7f204e04430853fdc217db767b9bb579eb6534f387de5c79544d0761849870d332aad8bf94d4ffc2c1e638ea47", "shakeLen": 504} + ] + }, + { + "name": "Medium UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "d8ccc8505c54a81ddafd0db03b7eb8c2f309655b980781629b04bc4e9d7dbf", "shakeLen": 248}, + {"type": "HEX", "value": "d8ccc8505c54a81ddafd0db03b7eb8c2f309655b980781629b04bc4e9d7dbf4a708b19fa12e434749880492d6c2dfd3deda5ae42c44c760f0faaf1b2ee31aa", "shakeLen": 504} + ] + }, + { + "name": "Long UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "29d48c0b789a3039977b97ebe61c8e963e2a1128acefd2301b476f7625630e", "shakeLen": 248}, + {"type": "HEX", "value": "29d48c0b789a3039977b97ebe61c8e963e2a1128acefd2301b476f7625630e0fb6660aaaa4103ef05246d4a5e52dbd08c8fa5fcc61e9c05aedbdc3289d91d1", "shakeLen": 504} + ] + }, + { + "name": "Short UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "6a426b1cd7f9cc84a2194ca196cff2642a730356065484756827a5c9615659", "shakeLen": 248}, + {"type": "HEX", "value": "6a426b1cd7f9cc84a2194ca196cff2642a730356065484756827a5c96156591c195572879ae4c2c2a4345b20cee264c18188c3033a45238d01fb6fcbfb2b44", "shakeLen": 504} + ] + }, + { + "name": "Medium UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "c589c37bdd19b37c96b650ce2622a7914d8b0d5ecb7855c77bd9b723a0c73b", "shakeLen": 248}, + {"type": "HEX", "value": "c589c37bdd19b37c96b650ce2622a7914d8b0d5ecb7855c77bd9b723a0c73be880392931a248a5ce89338d0f46e837adde144d8a0780625599477adff6a124", "shakeLen": 504} + ] + }, + { + "name": "Long UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "fe68432164f01f9b90a715299126d6b50787e50691a0c4b1af01243bcbf283", "shakeLen": 248}, + {"type": "HEX", "value": "fe68432164f01f9b90a715299126d6b50787e50691a0c4b1af01243bcbf2837f94a8275fcd414c244505ad9709c78ff53578fe06ef69ba1195394a50d1b4f7", "shakeLen": 504} + ] + } + ] + }, + { + "hash": "SHAKE256", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF8"}, + {"type": "HEX", "value": "616263"}, + {"type": "B64", "value": "YWJj"} + ], + "outputs" : [ + {"type": "HEX", "value": "483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b57", "shakeLen": 248}, + {"type": "B64", "value": "SDNmYBNgqHccaGMIDMQRTY20RTD48eHuT5TqN+eLVw==", "shakeLen": 248}, + {"type": "HEX", "value": "483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739d5a15bef186a5386c75744c0527e1faa9f8726e462a12a4feb06bd8801e751", "shakeLen": 504}, + {"type": "B64", "value": "SDNmYBNgqHccaGMIDMQRTY20RTD48eHuT5TqN+eLVznVoVvvGGpThsdXRMBSfh+qn4cm5GKhKk/rBr2IAedR", "shakeLen": 504} + ] + }, + { + "name": "Medium", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF8"}, + {"type": "HEX", "value": "61626364656667686263646566676869636465666768696A6465666768696A6B65666768696A6B6C666768696A6B6C6D6768696A6B6C6D6E68696A6B6C6D6E6F696A6B6C6D6E6F706A6B6C6D6E6F70716B6C6D6E6F7071726C6D6E6F707172736D6E6F70717273746E6F707172737475"}, + {"type": "B64", "value": "YWJjZGVmZ2hiY2RlZmdoaWNkZWZnaGlqZGVmZ2hpamtlZmdoaWprbGZnaGlqa2xtZ2hpamtsbW5oaWprbG1ub2lqa2xtbm9wamtsbW5vcHFrbG1ub3Bxcmxtbm9wcXJzbW5vcHFyc3Rub3BxcnN0dQ=="} + ], + "outputs" : [ + {"type": "HEX", "value": "98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf", "shakeLen": 248}, + {"type": "B64", "value": "mL4EUWwEzHNZP+8+0DUuqfZEOULWlQ4po3KmgcPerw==", "shakeLen": 248}, + {"type": "HEX", "value": "98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf4535423709b02843948684e029010badcc0acd8303fc85fdad3eabf4f78cae16", "shakeLen": 504}, + {"type": "B64", "value": "mL4EUWwEzHNZP+8+0DUuqfZEOULWlQ4po3KmgcPer0U1QjcJsChDlIaE4CkBC63MCs2DA/yF/a0+q/T3jK4W", "shakeLen": 504} + ] + }, + { + "name": "Long", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF8"}, + {"type": "HEX", "value": millionaHex}, + {"type": "B64", "value": millionaB64} + ], + "outputs" : [ + {"type": "HEX", "value": "3578a7a4ca9137569cdf76ed617d31bb994fca9c1bbf8b184013de8234dfd1", "shakeLen": 248}, + {"type": "B64", "value": "NXinpMqRN1ac33btYX0xu5lPypwbv4sYQBPegjTf0Q==", "shakeLen": 248}, + {"type": "HEX", "value": "3578a7a4ca9137569cdf76ed617d31bb994fca9c1bbf8b184013de8234dfd13a3fd124d4df76c0a539ee7dd2f6e1ec346124c815d9410e145eb561bcd97b18", "shakeLen": 504}, + {"type": "B64", "value": "NXinpMqRN1ac33btYX0xu5lPypwbv4sYQBPegjTf0To/0STU33bApTnufdL24ew0YSTIFdlBDhRetWG82XsY", "shakeLen": 504} + ] + }, + { + "name": "Short UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "a8e58b37e3dab187c7c20123870900aa11fee5f0c3bbba8af2edc6e892b429", "shakeLen": 248}, + {"type": "HEX", "value": "a8e58b37e3dab187c7c20123870900aa11fee5f0c3bbba8af2edc6e892b42984543e4ba39cd6661a22a785dcf6531f7275be0b47d6c9690475ce347e00da58", "shakeLen": 504} + ] + }, + { + "name": "Medium UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "262903200110b573ba851475488f5b751dcba77579d436180d9efccfc93b91", "shakeLen": 248}, + {"type": "HEX", "value": "262903200110b573ba851475488f5b751dcba77579d436180d9efccfc93b912c4d70f115c9bf3fdbb133e34f23768fa57151f54135d7c681a5e2cf1b5129d0", "shakeLen": 504} + ] + }, + { + "name": "Long UTF16-BE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16BE"} + ], + "outputs" : [ + {"type": "HEX", "value": "25444b2108287ee102e524a9499103bd87f9ae7e82b18777e8c84e2834ce0b", "shakeLen": 248}, + {"type": "HEX", "value": "25444b2108287ee102e524a9499103bd87f9ae7e82b18777e8c84e2834ce0b4d38350f3c0536fb12ec9f0109397b520abf249a17dcbe33421c5abf21f23cdb", "shakeLen": 504} + ] + }, + { + "name": "Short UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abc", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "d94f7da7db99cfbb32bc5fa89917a60dc1c12f46c924bcac76b05bb9eefa70", "shakeLen": 248}, + {"type": "HEX", "value": "d94f7da7db99cfbb32bc5fa89917a60dc1c12f46c924bcac76b05bb9eefa705f909795f964f22e2036ccb560d952f1485d75127b060d680e19efb0bf852cf9", "shakeLen": 504} + ] + }, + { + "name": "Medium UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "cade3014570c222dc6aa327be04ac8088f85fe0a177f08e48b24b6a30dc078", "shakeLen": 248}, + {"type": "HEX", "value": "cade3014570c222dc6aa327be04ac8088f85fe0a177f08e48b24b6a30dc0783fd4bdef46fddd440dba74b8dd5b524b9530d85e2a30e2e35a1bee69f7c7ed9a", "shakeLen": 504} + ] + }, + { + "name": "Long UTF16-LE", + "ptInputs": [ + {"type": "TEXT", "value": millionaAscii, "encoding": "UTF16LE"} + ], + "outputs" : [ + {"type": "HEX", "value": "295697f761094a339fc6626b97f10d89912839d276ab7a1bf330eb3c40baad", "shakeLen": 248}, + {"type": "HEX", "value": "295697f761094a339fc6626b97f10d89912839d276ab7a1bf330eb3c40baad9d21210c4847df516ec630ae7077a9a17f0d6792561d7708068a3d32850c8cca", "shakeLen": 504} + ] + } + ] + } +]; + +/* Dynamically build ArrayBuffer tests if the environment supports them */ +try +{ + hashTests.forEach(function(testSuite) { + testSuite["tests"].forEach(function(test) { + var clonedOutputs = []; + test["ptInputs"].forEach(function(ptInput) { + if (ptInput["type"] === "HEX") + { + test["ptInputs"].push({"type": "ARRAYBUFFER", "value": hexToArrayBuffer(ptInput["value"])}); + } + }); + test["outputs"].forEach(function(output) { + if (output["type"] === "HEX") + { + /* Can't compare ARRAYBUFFERs so actually use the HEX output directly and convert in the unit test */ + if (output.hasOwnProperty("shakeLen")) + { + clonedOutputs.push({"type": "ARRAYBUFFER", "value": output["value"], "shakeLen": output["shakeLen"]}); + } + else + { + clonedOutputs.push({"type": "ARRAYBUFFER", "value": output["value"]}); + } + } + }); + test["outputs"] = test["outputs"].concat(clonedOutputs); + }); + }); +} +catch (ignore) +{ + /* ArrayBuffers may not be supported by the environment */ +} + +hashTests.forEach(function(testSuite) { + describe("Basic " + testSuite["hash"] + " Tests", function() { + try + { + testSuite["tests"].forEach(function(test) { + test["ptInputs"].forEach(function(ptInput) { + var inOptions = {}, hash = null; + if (ptInput.hasOwnProperty("encoding")) + { + inOptions["encoding"] = ptInput["encoding"]; + } + hash = new jsSHA(testSuite["hash"], ptInput["type"], inOptions); + hash.update(ptInput["value"]); + + test["outputs"].forEach(function(output) { + var outOptions = {}; + if (output.hasOwnProperty("shakeLen")) + { + outOptions["shakeLen"] = output["shakeLen"]; + } + + if (output["type"] != "ARRAYBUFFER") + { + it(test["name"] + " " + ptInput["type"] + " Input - " + output["type"] + " Output", function() { + chai.assert.equal(hash.getHash(output["type"], outOptions), output["value"]); + }); + } + else /* Matching the dynamic build of ArrayBuffer tests, need to use HEX as a comparison medium */ + { + it(test["name"] + " " + ptInput["type"] + " Input - " + output["type"] + " Output", function() { + chai.assert.equal(arrayBufferToHex(hash.getHash(output["type"], outOptions)), output["value"]); + }); + } + }); + }); + }); + } + catch(e) + { + if (e.message != "Chosen SHA variant is not supported") + { + throw new Error("Testing of " + testSuite["hash"] + " failed"); + } + } + }); +}); +/* ============================================================================ + * End Basic Hash Tests + * ============================================================================ + */ diff --git a/frontend/jsSHA/test/test_hmac.js b/frontend/jsSHA/test/test_hmac.js new file mode 100755 index 0000000..91ee5e8 --- /dev/null +++ b/frontend/jsSHA/test/test_hmac.js @@ -0,0 +1,533 @@ +/* Kind of hack to get the tests working both in the browser and node.js */ +if (("undefined" !== typeof module) && module["exports"]) +{ + mocha = require("mocha"); + chai = require("chai"); + jsSHA = require("../src/sha_dev.js"); +} + +String.prototype.repeat = function(times) { + return (new Array(times + 1)).join(this); +} + +/* These are used often so make a global copy that everything can reference */ +var millionaAscii = "a".repeat(1000000), millionaHex = "61".repeat(1000000), millionaB64 = "YWFh".repeat(333333) + "YQ=="; + +/* ============================================================================ + * Begin HMAC Tests + * ============================================================================ + */ +var hmacTests = [ + { + "hash": "SHA-1", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "Sample message for keylenblocklen"}, + {"type": "HEX", "value": "53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e"}, + {"type": "B64", "value": "U2FtcGxlIG1lc3NhZ2UgZm9yIGtleWxlbj5ibG9ja2xlbg=="} + ], + "keyInputs": [ + {"type": "HEX", "value": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaab"}, + {"type": "B64", "value": "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqqw=="} + ], + "outputs": [ + {"type": "HEX", "value": "078695eecc227c636ad31d063a15dd05a7e819a66ec6d8de1e193e59"}, + {"type": "B64", "value": "B4aV7swifGNq0x0GOhXdBafoGaZuxtjeHhk+WQ=="} + ], + } + ] + }, + { + "hash": "SHA-256", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "Sample message for keylenblocklen"}, + {"type": "HEX", "value": "53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e"}, + {"type": "B64", "value": "U2FtcGxlIG1lc3NhZ2UgZm9yIGtleWxlbj5ibG9ja2xlbg=="} + ], + "keyInputs": [ + {"type": "HEX", "value": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7"}, + {"type": "B64", "value": "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaan"} + ], + "outputs": [ + {"type": "HEX", "value": "9bcf2c238e235c3ce88404e813bd2f3a97185ac6f238c63d6229a00b07974258"}, + {"type": "B64", "value": "m88sI44jXDzohAToE70vOpcYWsbyOMY9YimgCweXQlg="} + ] + } + ] + }, + { + "hash": "SHA-384", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "Sample message for keylenblocklen"}, + {"type": "HEX", "value": "53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e"}, + {"type": "B64", "value": "U2FtcGxlIG1lc3NhZ2UgZm9yIGtleWxlbj5ibG9ja2xlbg=="} + ], + "keyInputs": [ + {"type": "HEX", "value": "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F9091929394959697"}, + {"type": "B64", "value": "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpc="} + ], + "outputs": [ + {"type": "HEX", "value": "e5ae4c739f455279368ebf36d4f5354c95aa184c899d3870e460ebc288ef1f9470053f73f7c6da2a71bcaec38ce7d6ac"}, + {"type": "B64", "value": "5a5Mc59FUnk2jr821PU1TJWqGEyJnThw5GDrwojvH5RwBT9z98baKnG8rsOM59as"} + ] + } + ] + }, + { + "hash": "SHA-512", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "Sample message for keylenblocklen"}, + {"type": "HEX", "value": "53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e"}, + {"type": "B64", "value": "U2FtcGxlIG1lc3NhZ2UgZm9yIGtleWxlbj5ibG9ja2xlbg=="} + ], + "keyInputs": [ + {"type": "HEX", "value": "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F8081828384858687"}, + {"type": "B64", "value": "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGhw=="} + ], + "outputs": [ + {"type": "HEX", "value": "5f464f5e5b7848e3885e49b2c385f0694985d0e38966242dc4a5fe3fea4b37d46b65ceced5dcf59438dd840bab22269f0ba7febdb9fcf74602a35666b2a32915"}, + {"type": "B64", "value": "X0ZPXlt4SOOIXkmyw4XwaUmF0OOJZiQtxKX+P+pLN9RrZc7O1dz1lDjdhAurIiafC6f+vbn890YCo1ZmsqMpFQ=="} + ] + } + ] + } +] + +hmacTests.forEach(function(testSuite) { + describe("HMAC " + testSuite["hash"] + " Tests", function() { + try + { + testSuite["tests"].forEach(function(test) { + test["ptInputs"].forEach(function(ptInput) { + test["keyInputs"].forEach(function(keyInput) { + var hash = new jsSHA(testSuite["hash"], ptInput["type"]); + hash.setHMACKey(keyInput["value"], keyInput["type"]) + hash.update(ptInput["value"]); + test["outputs"].forEach(function(output) { + it(ptInput["type"] + " Input - " + test["name"] + " " + keyInput["type"] + " Key - " + output["type"] + " Output", function() { + chai.assert.equal(hash.getHMAC(output["type"]), output["value"]); + }); + }); + }); + }); + }); + } + catch(e) + { + if (e.message != "Chosen SHA variant is not supported") + { + throw new Error("Testing of HMAC " + testSuite["hash"] + " failed"); + } + } + }); +}); +/* ============================================================================ + * End HMAC Tests + * ============================================================================ + */ diff --git a/frontend/jsSHA/test/test_multi.js b/frontend/jsSHA/test/test_multi.js new file mode 100755 index 0000000..9e616f9 --- /dev/null +++ b/frontend/jsSHA/test/test_multi.js @@ -0,0 +1,220 @@ +/* Kind of hack to get the tests working both in the browser and node.js */ +if (("undefined" !== typeof module) && module["exports"]) +{ + mocha = require("mocha"); + chai = require("chai"); + jsSHA = require("../src/sha_dev.js"); +} + +String.prototype.repeat = function(times) { + return (new Array(times + 1)).join(this); +} + +/* These are used often so make a global copy that everything can reference */ +var millionaAscii = "a".repeat(1000000), millionaHex = "61".repeat(1000000), millionaB64 = "YWFh".repeat(333333) + "YQ=="; + +/* ============================================================================ + * Begin Multi-Round Hash Tests + * ============================================================================ + */ +var multiRoundTests = [ + { + "hash": "SHA-1", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc"} + ], + "outputs": [ + {"type": "HEX", "rounds": 5, "value": "b5c64925eb9940259be55c005c9cecc7d9897ef9"}, + {"type": "HEX", "rounds": 10, "value": "94ebc0d3c81b61eb98670666f5fde68560c4e165"} + ] + } + ] + }, + { + "hash": "SHA-224", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc"} + ], + "outputs": [ + {"type": "HEX", "rounds": 5, "value": "5b4b17f720d52c6a864229e784fb636184ca48ce7dd848fdad986239"}, + {"type": "HEX", "rounds": 10, "value": "5230eb37afcc115f4f380a9f50c4743d457bbe586e6faa6bf21696f9"} + ] + } + ] + }, + { + "hash": "SHA3-224", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc"} + ], + "outputs": [ + {"type": "HEX", "rounds": 5, "value": "7d208060760d239d9e9b041b5c30ac992b83ff1df658263953c9eff0"}, + {"type": "HEX", "rounds": 10, "value": "a1b668748fd69b8b6a6453d3bada2b9eb9a06a29b78fbcff5ab530ae"} + ] + } + ] + }, + { + "hash": "SHA-256", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc"} + ], + "outputs": [ + {"type": "HEX", "rounds": 5, "value": "184f6d6e82554c051b33f15e7ffffecb0cc0f461a29096c41c214e168e34c21d"}, + {"type": "HEX", "rounds": 10, "value": "10e286f907c0fe9f02cea3864cbaec04ae47e2c0a13b60473bc9968a4851b219"} + ] + } + ] + }, + { + "hash": "SHA3-256", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc"} + ], + "outputs": [ + {"type": "HEX", "rounds": 5, "value": "fd5ad48a1abf3fd8211ecd2a6a0b0503e745d953def260541fa5db7dc1b3b84f"}, + {"type": "HEX", "rounds": 10, "value": "5b814fc96d03918994939bccb796945d9683fa90a22f99350d6a964de78a7980"} + ] + } + ] + }, + { + "hash": "SHA-384", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc"} + ], + "outputs": [ + {"type": "HEX", "rounds": 5, "value": "a4aa4cd8534aecb2d07765f928303d1d2609835ea85d14312bcee264e99dc5d7dc08bb18ec694053fd7fe6906706d55f"}, + {"type": "HEX", "rounds": 10, "value": "b80c82979453f2f3dcf89ec4cef5c71e89837537de170e3942af8b37757cc790d4cc4ebe16a52164ad19f3a02d192f1c"} + ] + } + ] + }, + { + "hash": "SHA3-384", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc"} + ], + "outputs": [ + {"type": "HEX", "rounds": 5, "value": "be2f2365cecd5df751f3ab7d23cabfb60491ce28bdf80b121f7941ee33227ce86d5d62d6633f5654a4f3ae5381cf1825"}, + {"type": "HEX", "rounds": 10, "value": "4cb125e919d39ab283964e06ce58dd8923fa599046b533958c9353317ab368066b9902c2e1a9c9376d66f321fcc2c0a1"} + ] + } + ] + }, + { + "hash": "SHA-512", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc"} + ], + "outputs": [ + {"type": "HEX", "rounds": 5, "value": "299b2e3ce932e4d0e9005345e37af5a4cc6be21e6b6e21231ce71ccde2a7aba4a6822cd7a9aaf9b13918db05ede70d3f1e6af65f8ad0bda1c4c4fa263e3cabdd"}, + {"type": "HEX", "rounds": 10, "value": "4c3ead8c83442fff47d4386702044f2a6c19730a806de541964b0fa9987cac08641611e02b2e0742ef2600ff82bfe3a711567c8e76dda16b4948f4c76e3c6e9c"} + ] + } + ] + }, + { + "hash": "SHA3-512", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc"} + ], + "outputs": [ + {"type": "HEX", "rounds": 5, "value": "8c74189ca608ad188bb96c8c374fb717ce982500dc2c0ce90ad8e5888b498ce9fda0e4bf256feeaaf1674b69e9ea80cf5ed444dfdd5d3eb05cfebd597b4aab67"}, + {"type": "HEX", "rounds": 10, "value": "0e3c0126a211563fdedc96149f1c2334aa5f5b2afcf5590cb71fec0ab348ba522e56c1136f165f525b22890e2546d2f9edbea6b6f5e929237b6c0f395e1b2e9b"} + ] + } + ] + }, + { + "hash": "SHAKE128", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc"} + ], + "outputs": [ + {"type": "HEX", "rounds": 5, "value": "99d5aa0763f5bd9464ed4bbc631ecdac6f67e77cbf61c7f7171dd2ffa892ba", "shakeLen": 248}, + {"type": "HEX", "rounds": 10, "value": "5a5aeb2022e0e92ef4da3dc3e261a9303224b65cf6666f87a4d395a4ab94fe", "shakeLen": 248} + ] + } + ] + }, + { + "hash": "SHAKE256", + "tests": [ + { + "name": "Short", + "ptInputs": [ + {"type": "TEXT", "value": "abc"} + ], + "outputs": [ + {"type": "HEX", "rounds": 5, "value": "70368c73548e76dd6405ea6c1b4358eb0aeb4c0efe73526c7c6e1d9a9e4e0a", "shakeLen": 248}, + {"type": "HEX", "rounds": 10, "value": "d706c35b6642f39a27635c61c85ab13e76827de8fde4557e25bfc96b445f10", "shakeLen": 248} + ] + } + ] + } +] + +multiRoundTests.forEach(function(testSuite) { + describe("Multiround " + testSuite["hash"] + " Tests", function() { + try + { + testSuite["tests"].forEach(function(test) { + test["ptInputs"].forEach(function(ptInput) { + test["outputs"].forEach(function(output) { + var options = {}, hash = new jsSHA(testSuite["hash"], ptInput["type"], {"numRounds": output["rounds"]}); + hash.update(ptInput["value"]); + it(test["name"] + " " + ptInput["type"] + " Input - " + output["type"] + " Output - " + output["rounds"] + " Rounds ", function() { + if (output.hasOwnProperty("shakeLen")) + { + options["shakeLen"] = output["shakeLen"] + } + chai.assert.equal(hash.getHash(output["type"], options), output["value"]); + }); + }); + }); + }); + } + catch(e) + { + if (e.message != "Chosen SHA variant is not supported") + { + throw new Error("Testing of multi-round " + testSuite["hash"] + " failed"); + } + } + }); +}); +/* ============================================================================ + * End Multi-Round Hash Tests + * ============================================================================ + */ diff --git a/frontend/thumbnail.png b/frontend/thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..514fc3e27c6d4a80b412ff00b3d6cec51373f78f GIT binary patch literal 47333 zcmd3OcTiJb6s8>&r3$Dt3y5@;CS8$^fP(a<^j-s@M@5I?#}GY?i+{E_uf7C+*7{u-E$vCKG9OSc>e17W52H8x( zlTS}j1};XGyG&qAJ@=;~yX9MsBGn+Opkvn{YM^6v!K-SHuQfo&fR(*eq&fyHbx|Hz zIUt+jDBv|=cJpoKz}91C{q1iPcr(yXE));{|stS6n^_>ncNNky{7ta zq|m?Dr2ZTEzbWgYoC;6iiVSM&gbS4s)ZYxl-$iyEUa!N?uy0OggzCtz)kLOk-v%i0h! ziK>#%Rc-gM3}dpF`~9nYcX*KR-1iu#`2$S)-So2WkoU33XtUjD?d2x4G__-!6M-2b zvMY>z(}cs5TFI|Wvv0NDa#Be)ecIQ`LYiwVPlrGRto3wEpHKCi1nXE<#OGEHhT3G% zsKp{aG!TfoYr%f@li-d;JQpR0RY44hoM6MlkO-F@hFo#;7Ee)J@-0tTsi#K zEuK6V5uZlHoeO)RRzIT)B3I^Kl@I2T-X1mVezH6)Ib4!w+j(&D1Nykz>F`p`o+iU7 zooQJ)DOii^V!GJ9`{v|N3&xghSxWibskUyfT3a9;ZZU5lpe==U;(YP)HuXA|gM%|Q zBekMu>@zUO&56Pz5%%aH7_JDV9y6VGD;fGt#;Kco(SUCvy{Tu$De+hJCAM}K@*D+mMLUa%XA_9oscr>IM-~IG@QT(EofrFMNWa0}3Tgjf9(^5_-V0y|b z)W<$(l!ZpPoHP@(MIk5!Q;<>(UFX$unR)?KSfwZVyKsEH2sK`zmYntd|$EF91Qj=ugh1t5-60 zU)%cjGhuuEyVq1PyNbZ!{zKGOL4kcD=OiWnj&U^z^Wb}aNjr|en|YH^^2r(^%z*Hq zp1tobmh;@vQ`ygYYBiu{K+}B|%;Ue1nCg&TVQ(!hJ026F9L|%#bW>Ze-!Be;px*}2 zj$Y44{R($h1J#518XNr@&hX^noMgP$#aKQCrlnOc)HSGV^g`o!1gzao{8Bxf#?KY{cy2|B6PHm86}s5M)_42vv;FreLoem9xk>X-2*@oz_?6B+z-(SkT6l} zawN&-hFl9889vQ^KS%I7I!TxtpP1_hj53o+$Q8)sQHu7=WB(U19BJbXS)H@zx#99y z=by42Pby!;IJYi|L~`uIPmjkeSk`{xD_VYxHv3OE38Umb)m^g3X2>NmC)+@fy4DF? zv|{ojxRG>ByxGabF%emt>CN<;0B`~DsRf0!(GQI1id2+Tt#gaZN?KJ;nt6X5t?`TG z!nXzLKDw(T3i;JhU+!|8#yD2$?xB5Hw61E_nDPo@NF8@4p9PYN2y*1a<(5mk zTf*~;TrP*oA<7i8(no{( z5DtyqXuA7D7MhWEQ@Ye71+B9%q@F%9zawv!DFAr=0)d(q^`YpQzUKGUPyF56j(jGl zGsQaUS9RJANgpe|WK}Qh);p2$^xEL*mu$nq&J)p^tEqadhkN(ao9EsGKwpyzGu#eqvmD1}Ou*%@Kz0?$5lDcileD z2iB)MbKH%JpbxF|5xAy(@ebi*QI}1HrUs?r3!g;uT=vi`AKt4K(rBY zVD0+4$XwQO!3HKW!9X2&7swyx_kD&d@0@wHq0+Q}W~)7#OBqhhTQ&<$K}Ql?`7`5u zy*6m39|h(1&aF7E;QmZEI6UGX@hFDtzq&T+)>bWNDJv@}vJATh(b%2p6^DszU#fDN zeXzO}2os5F*(wmeCFRt80zAmX8=gO>M)gnCyzk~C>UMHRe(x-}8x~7nNF;RVW*Mw) z;c8qmbPkXUL`rBLzrXs(9(*wNm6>%@-uOk<2eByw`5j4kW!k(5Mp^x|g$ z)MnKf?mb$r+^4v9o$9~Pw#kN+rQ<2XcAlDY6x*~)-D-C*fRwQt=l)vmU^ zkh=^Bs___Cq{>E|LUQegQj-5|+JrD*WdT>qM&PPyYB@bNTHfaQ` zg6nc5hS90pKgg`3cg~1VdHKI(s>zo@N(rrAeRG^O2-d>QI1m7|DAJ zJ^1bCXyx$IR-D>j=wxFc0xZqA)d`oah_zqUMN0DQ&)$LuJ>Rf5+QgII>#1E~QLom5 zPy96m?ihott5e!wv?WSDQcg-Hr^)L>Zlx;7%}g490(oAJGfwi}{nBFAe`XWB|3jlo zn;{6O+pvNrQ0c8p@6pIwpIyPgg_nWtfpw6_E3|(ic1W44L558O3PBEI-|&`Y2Jmuo zHQ-9viQZi4m-vX+f8)jOWRxO6Dg+`)erv(rs(u@bv%ZSZfRQOU*t&ZUsNlnw84ykY zvH-S`ifr+kQ$tnjy06`h#1useakjk|(!2Ty8X);6)_LG4dwVfL7yt$~Lq4#(z;r-d zQrHfISxalL6VHy$l}Jpy6OSj68zw;sy_d9oFGOS6=gF*#a3^ zY1iR`XZ{dHu7=B;nL0E>xl|Xq8VFx}UK?Z?;H@sJ%Qdzf1Aaz>bn5#7p6al#$KZ?hpct8~}Ae(hKwRG^I~o$OY??bcDp zVH8fw-@>^iW|8_YnHYkmn-pOp0KS`eswG$(@Mj*P5rzy1c0=ikFgOwj_VIm%{9B6`U{soWPE-i#(p*}w2 z@y|+h)o|(&Ypg0L-cWj}R>|HCowzakpIi~PiX+0Dx}EsZQUrIh;#ZS4pT-=vthhE0 zwVMoxYC~x+^Yg<}Fd5!^BXD7@zwjd!DHJZkpE)Tm(N)x7#zD3pK_wMyFFu!+8ljWW$gQ6(b4?!Lar`Q z3wR?je8rixv(b7|j8*7&WG;V9wR&aQ*}t)Z9~hxc=&(vJ7be+$)??}7@nTF^vNq%8 zfoneBNSQL<+N^Oh&qUJ>XY+;U-`=U8G&uEFLs>a=lDT)F=UBT_ZcU-4!(e%)geu73 z#l~ap!Q0^~3=>6+vO7Adp1x^?jr}b*fQ12sF&_OeYUp+*Z(m6wq|Zb=IzEoLX?@d` z0l{r3ExU0wQ|7LC^{+i5G93-n&4iAdCQAJQHf52?|0N;$vt7rN=_Mnd#e*XQ+{L|U zzJV)fj&m7|+R*gwDc)Y+JkS!rb+MYepT0kaiM-%6yR-Kem>WoaEof9254*bE)okzH zSF8GF9F(F$#+p9_ivdwP5tBjx zymB&e5G1zaKA6yi%jaVp6tV8A=hdR)j-)6 z(ut?N)xCgC%i@&b=9C;(9aPUPCwaF7WNYm%W9zk=!IByD6qp*=UGTt_OdgdDXTx(M z6H=V(y^m~KZ(0Dmc677>S0wk-(d8uvkN6R{`yiLM_wI(}@NKUxN(*H_1-r-cuM`37 z^=hq{AXYi?sC|q@(>PEr60_s93{=tHg1EqD@1-`No^2&5vS`1(nn)Uzb)2o={1h(? zbdi4B6kq@4f{o=O(iehL9oZ?h;~q#ny*JcnZ0y+Bt$eF>KdffP42+l6IOI2Y$F`3g z8@AXpdem0Zy|Nrtnti+JYIe4d40-Sn3hbb{C&wt8XngmD9(-B)hhoQUZGa{oJQ&!m^EV<3S+hu>CV2<_UAJZX zy0*7L4QXPPDBA9$>j2rTs15+gt2`Gz%z{&VJ?x%@odR~XS?FI5R&1GAEWh9Wb%FL> zqxH`6&fFD8pLfnP8$6MNQ%0m__roU*Lp%+tF}*rVOJBFW{Qq-T!+Z8Z>v$ein-Q+> zk&xeVg?E$lll)?i$x#G^A+!3XbTd$-4g;ZmL-4ovvUnM9%9BQd&Hja1Xhy*25|+7ZvU0AA`mROJC|<)Rt-zfbZdg-i!QP_X*jUp_qAB zn1caP;zLGN5jf^E(=vKmx9peO<6ZrCSRnzQ1oFG?$kZkW=)EB3d@b?}%!B~U*=|td zp-PQKd}K}?WjmGLG9itW-a2@3bGrU7QH|`svvp-O!aF%DQGD9j2lX~i#T?e( zA>VL2KP})FQJA>jmZE9kS!NJ@A%jdY_0`MT*EZTqPLZdhhomkJ z1dPaTg!oAmGT;y-fYcosXwF!RgTqDKwF1>2`*BB3^nI-^hE(}DsZJipnUt( zknd1{A2x56Q?_O;Y=#HxjLA+dFAz>U$v@b*Mj;aK(O;Vk_Js(pDKpB`Oz!spfT`bn zm!8i#BWVCy4vZUBUEMm0r^37`)r`BAOvPrMTwrvdVYrD8_G9qf;fx6_R{xOA{ymms z+f}CUdr^_V=j3qT>`P+3^jn^_7QvD_dq9T^YZ0uKl_9Z1C;ercir%xQCmK`twd&LN zepViNfLf(_*FVOK6VwkkDrr$F@^&2`{{`2gHkvx($0?g!LF z;BX*%N_=6orhQ5s__Tjk~-7t$I6rzw#%^75(TR*Pwmqz5k{_|J9RIs4jI=4{6u=IBf*kV9vG z<^YmoJ)w~K&&#}fUP9T;^rQ)1p|{pHmjZE5J}jKjI1g-{^VO|I2Wd5AsVl@K%X_Jk zE&;aa;2gr$d!V!oSI@ovvMd~*!AgZYC z8@s>d>%N3WaUYt5d#52*Lta$xmsJM)@yVWT_k3(S(xZP?fENgi=Bn|*X~yxGdT^ut z@>H(TmD7->ANl(1Pm{4-p{TT@SAAq!@EHMz+zF~Y@$UneO6!h!B8!%JAM2OEv0}4s zT&8fhJo^d2j1!xRZ*z;5*D-kFfw8CJhCC-zl2gUK^Tl+dhup-4P`OAR&^ry|I?ts+ z-EiT=OG@qJJAha9W3ZfngU$Ju7Tcn%`~?qC1-ogoP)-ib$jG*K*mA_2_qAO~97|3v5#!U8DyHQyqXIUxRb|Tb7#FCGM*DL?4Mv>4po1!m{R} zs!_P`DbCN88hk*$a5X4uKc;(g+Rr37_+AM92X)Y~mshXB zoyev#LCpkh#=^tmv?ek8<+R*6NG3H;*&g0|xV7cn6PBc^eIClmP%`=<-M58@0#{>| zEziY$Fci3|5vXM-$oMV9k5T-{aKp{6PP>v9h%W4O;5McNYBGUA)_LY{YHdXlS@ip7 zB*h(GNCwM2xF}En5cl_J?`v>^X!i1S0Wx+PkpQEG!ULS&wpn!D5>suW8*!Vp_$=m)4q4OV483H)<`%wYhj$ygnj_k z*zLXBuzY0C#hm0czjbW|=gh)FfffccsKFF}3o3Y#FllAb0=YklI1PXs#jc6DaHo?o z7&(?Cr>jx?USo5MG#Rdpo#xPrRBL@YzZj3EkNjJs~+Dg=?L}} zg>A8(l!l1ZSVR@vY#h?OJmS>$o<@YRXLOsG(<+~QxDn#LIzd>l;)Te}F4x-K3-*`U z!*U+(=X^>d@)GfnmE$F-s)-+_3pJTAkjl=@w`Hb>cH=Bk zq=SR7vy}{L7Dd!YTdiNfG^P~-MwdvBtfp)1N?oQgPC%`ooGcUZ{pLkob-FzK{FP8U z?4GOvSW(ZWD=O3D3yV1p{Z@rmTLq?kX->9A0*u35h`A6AJpnyRUW0%ZZ#L!SR0zrz z9;}3>h_Ggtk%>wve)5_OVQjRDS!VA99~W_;S#_8^6dfX=yQ{Ue@xrczNRqB^&YYn#J~oD+jTo38De!J4c=wtI6_GtQ&`I zh0t3^S!89O!1`qyX}g(CoL#VMpT>}3XQ~)yiq1^B=}@10!&&f`t#b7=T{;!9u9`RF_@btAiR2GpznIVTKWn%6+y^yR~Ew}sldbE(X zpXcuV*_{f%S($dTvws$L5)RcqQheg76N)@@mWF8~tz(af?Q|MTsQDaxSmbmLN>39{ zB&HS#TrqcUl_bM?*Wn(Qg=!q#pC4@1+Z$+kczkHJ!??(}@%4UgJ6?BS;hW#`*tdgI z=taHNC&QLmqv)8N8 zRcIQ9{X2;Ehf?>3PtHO+`1kiNyj6aC*;ck&UydQV=5do{U)_jYEw(e!ca)w^<(UBz znqHq3@01;LA@;3?f|4w?molt2sX@y_|8AM5z~e+_L`tX<*(k^Pc5kHM zdt?&`IxIeIBrk3IY^AL&qSlKPKn z4_kP)d4!(k9tM8LL+$(NFXQ|%%m`8_3})BfjnGz{U@E;yF@m6!U_;a*x4~N-aLk)4 zOW{x3AEhm1^BX`BtD+^ktr163Fn=ozZpB${f>9 zp-8nsV1??kB4W-*%|Iybd&7*l5EUG_XZ4g%u;OO~f{d`5gTgmDa!3bn7-yHGCKOIO zT69S@t-m_;4j&NyBX`<2s)6X%^Wm(Vp>D`#(uj+Y<~vC3?YWiP z<%Km}LYLRQOw89)f~^jm?VQilV+MUdcUt|$m3IF3ez{UZiYuZQp#O-4GMsgBfOYi;Rt}vz+SBa3@Xs|z( z?o!`stmhGrQm{Xpmx7;cCT~d$k*2O!IVqI3bh_hQ%4Vw3?hBzSV?)B-?52SbB35|* zzDIjE*~?Sdwd-UQR<`-F$p`%k;uF{n1-NRCqlWc%XbX%$wLS*gQ9`zp6KGgrAk$>tiP zG*L_c`pY9ROI&Pof&C@?odM(!v+U|Or{As=u_9HlmDjej6;Jr(<{fSY zkE@P+rs_EXg%jiHYu-gY4~O7cWvkHm(9TekV>8kmrPMUrr#2ZWvHSy?ZV7)%rIFD4 zj+ZjWFBd(<+k<8PUD)?xnE(RYMhbt^*kQ?q$wEfKJA*w*>_dw`xjI? zM7E51UxZ@HjH}Q|%*X-)Pu-?E7be5oqJt;sX0OugCJ%N%Z)lwfDOw z(^6d5FPbzl7xrr6M_s9NXQVFOP)Eqmjr43F55Zks8AGZPU!gabOhu4A>pnf8|eyv5aqP1!=9de{z-LzLtj)#4(MPbQb}(b`d%pY7XAwjcN-(bIY63xgql zV0y_2^ocu4hq~3PKLR1|m>8-2Im)$9Me5O&oj}_KFDkwaiD%VqV?VbsRdFnzXT&jr zQc};?DwSpch$s&|t@JBXTTw;&q_#5+rPiGlYo2DSyaKN7R$+dVuH!zmr*rySY5+1 zU<#a+fqZZH)CccsUd#1#$EogSC4=ggzPJ3jN)l7ho4m@R{yw~ebBep^RIlqd{u()s znLTJwiFbEI+y>V=hht&a%IG>2S9sj%gpgx!e33A`E@j5uG;8(+SMdr(7i}Aa`gKr) z{w|@<&He+*>H<$D?^Zpa(dYbe3tDzKCh02uH^M(D$ydzh+z!2O7ve*%wh?^$W#{h0 zR#A&E=`ROae7)>`B~#a*gSSH7_Amd`Aqe(rYppc)-er+}!hT7xfkS3+BzPf)8!9p3 z<39B84~FUr;s;YDltx{uE=&<~2U6@oeiN(~VNt$myypB81?{i$`Fxw@OWE{f57Vh0 zb=4}#*B*x2U-Fa(s_1h7s@F)HpaiQ(w3{2Z$N!WmmG&x1XJWra#2(kWNX4U9(p1h= zBQyR@`;<3$m!HGOImqF~r8?;?t7n4CvIqE`TT~0cPvB=K7HMXuZGdE; zdTsRMl@9z4^m9+X;%>0g4gVj`YbZ*t9HllB++*g|3BF_&KgM)0ySSf4D>CCam9y15 zmwVKgtsdXG!hP=sRs5UpAHF|5M|UFO?AufHT<_nU=uKNDt>T-7X3Z3`)zXq$w1XTq zs$p4}6^FS)@9Z76ml0ZuSQ}%yJ~oZ$h@-s?vN1_;#}r{Ei{EAsy?!op!wgIEeMlEj z4=Iv6BNbnNQM*p}@S~f`Zf&dlP(gZfVL8boLiR)ix_PZw!%8(VFI@4(4gA8APm&4H z9a99&DuZxBiiKh#B7krUDrcc;=WXQe;wBgt_i){E)GawhW5wC2NLBS}@~Y^Xd1@i8 z3aCf+nPtq_@TfSp!$mF{t+;!d(@jF}O~9iDEyW>8L#XBv&@`rlN1{t-@9Fi)BbLkD z$d4e*`CG`P`t2ACYD?jh76(vFu+=Blg+`xWu`~9olAO+WlXbvBvnrr)j^i{i(&+}p zAQnJGNUQ9$!`?%|Z*(&;qRd?~6CWZ2swf`;SlpDNH}jij(|Gy~Y{ZZK=DlNjwY=D) zue32`yR3StK8>^5(R)j^HdmLI(E0r!$_RUCElH#spDrqJ{qnJ}y53B~Mf!1|`vb+; z#LoQ_$4Ac7&}T*<5$x+S>_CS|5p=`9IFJQg?AK9?7joi`(G*L5%b7V}L){H)kA*E# z;gp54ghYnMo=g{O-cXEEt>ExhPdw0HX2;J z`rz!3TR>+>E(S0ff?s5y-1frcVq-CkCu0?AoyEWNAZJYoqc1BuB(_mL0QhlNZ&xW7VSJNB*?^HnbdiqXTYhBfZ!JsS2_jhe( zM9C52z#`<76?veXlSy_lVi;T>F{N4y(_)=fR1NEJC?;4ZhdWe{T|8-VcH3;G(a4S@ zAYU@Z@;XO8b_6NN1`A*1(Gd<7w`Zr9O}dFsI_nbvoP|FyG>vn*QD{{ z?4V5qaQ+7Eey&K~WKolqJ-%alC4JBzvh_l^i%O=|*Sqti3(&JWiUwj|Sh>NY7&A zQ^`?E^_gI&B;D@4BV8EM!YIE}CV3o6+Ykb}_FS%nxaNshQ%t6BHCh+lYSZwp0%syk zHY1&^0&n;)nho+v48d+~t{!8F^vNQO+d45GJNC;8@G<^9=b!=AbFTs?7PmuDXp|1r zuM|_tanX2xyJA((HLGa5xA|i%gT8Hfr9Cojb981=xcr;%QQPe~#y0)1Cu zEhAM!aJT7~C1#F)sUAdA4Fu@sUBE&?`vi+LtAf}x$W8pWR<3l7lGN0>FLcI>1j%Uf z!ucH+n|u~rP6UPyS@ktb=_3a5S>tM}(=TepU1WY&@T&QXthE_<5r@ivubbzjA^HAj zBk)x<1rl%%rNQA>I!WJ+)5h2CSYIP2C7W-RWVI?g4Hn+wqYBy_nMK;Slw^c(6YoHy z^ra1O$F(&~8V&sBGU*HquR&E>S#1pLYL(G%YJ<88nv;KPECFat>5z8 zok-4_edGBE2!c0vrT?=8aR588;*7nQJp9dDP-$r`g0xk}BI#{9odlYn6ixvjrTGbo zLC&Loc@Lzxt$i!i2oi)gvTo-dt}U~9u5v9mr{mtpmvBLGNw0+K1S1TMJaP49e)-$4 z{E7x+T=(QCdG)nB0>~=|H|uqb*=| zprC6`&07e`)nK+Hw_)yOx0Gf4Znl$xyl?)6CxNAJBRB{N;s!&itw8qAeNO5Um(Aja zc9VjJ!lsrUYGd0qexH-y35=6@}6J(vG(fU{s7nh249*(e~t}iS_PB3XG#=69>pes?|`s0=&QXYtL#&3#d{cZ%V{OOsy?A&gfXq7o72n8QWm6cp|$f> z%=%>nMmWtdF7qkdyy)KI5G@@%Ak_Fm%5tyl?xGFNyh{H4T~AI8VK5*x1`ui?vG%b( znHh!AFwzM5`ecO!y|05I0rHzi#wpZ1ba$wq+2g zCZERKO$fC~#bj1FOCFXi(&M?v~r2b z+LO3}0a~{Kks&dZg;Ph$WIwE8Bq|c!vOoT^-htI?pm|%%6bGN=*lE=mfGHD)bX=Iy zMT$K|`+b4ipQYpc&N1%iA1FTCcN5q;HCWnOWOct64V7HDWjZ8Xk zMb~YSupy3}3B=hM)6BC?-2t3rZ-6;a;`Gs@>i*dJI4Rd5I(3_HEo^yR+x8UIH7Kfc z)O>!JR&Vgs)rND>`1B;xQvH5$@9-_16qA+aRNbE@+MJWYZKmoSpCZvgFUOzq3w{<) zHkMxdXfaqrdIeyMy}JujrE*ilPlu|$cjU4wcEfegc1#^Z$}|Dk6s8CGM1X-^YJh|D z#;4Yj)ea+m*F~BgQ*SZN^9=ay4dNsrM{v0#xPSH7ved6bBFjP~nzWoW`%F4Hb00p5 zSx1WxRSRy_iAUNj$C!%^d6Rxtlc!fBCQ3MFJly7hBm>AqTtrLo{zGiRaE{p*a%IvD zTt`6kQa$s#pDh74d48o^5JUQXD~^2~1pt2Q6I_4L!3oN1_p!Mj^}=hi07sYB1B^~v zcYQd-W5?8gQEq#TdsP$;N7^7AXQ!OWW*vVDfI;i$_y8f3CothCPNL(}>>*=mW@!N{ zAIZuYLSXQKK*W!`c2eff#-fJClKpewco6jfF|)y^EHP#SrJLKEm4+>7;bDaII4S#x~9~k zp`;pu*B&4C++xP4n_-Xz{2w$Io;h|?vJA*BeG|klcly%%3%Qjg-1DYxHyw*E*E*rD zL_LTOb}670GNAa92U;}u{;Hw_O?~K-wDm&2J|e%9pNaE~!zIk71()*f%h>}=Mppx~ zmw@J{?0fEl^oab?pdY4=1N|2`GhK*1DH^9wh;_+_?xxZ!UB@-e~QS_S6ifvx%^9nj|%yX6X_GJKS%BfxJgXzvQ}+=;~8dHe529^M*wZ zugj;EC7%Y4SfSmDiV$+=L0z15m5jDc4}wEhgw~>3ycV*J8zUZiptJOhmY&`H!j|Cq z{0Ep>YPvB7+jJkGsE-~mrOlQuk%4b(?o~E1PPF15>Y@lHime~O9sMU{UnO)K~1dw5pF#sYGF7M}Dq;COHDP))#*ndinYtFIRTaeA#9Ym{1!h)Q9)`GB z0r!3Nz1kC0m=~tM7qouT&Lnzv^p;3({$Nh3#g`b^qRAIj%RKNI=`niQFpZ$F5AyPx zGv(ciph;lsSD&1==`?Nlad51G#j4rNaTTd8l)mETR(1Jv+G-d;mDWV;0)VZ({Qz~8 zWi*#26wyAhJ3r96lNbKzdIz`T>M(o}ZazH9dzhK$oQYo`$_+8xa2?B-y zpdNq>It~x_qIYOo3Gtz&Zf_!l2otCj4L$Sv{1VG(W$J9C0Ua84_a{>)n9yT0(kOUr zlsuDD{bqJ>AAnr*UV+-r3Hn#wwU6DySHlnp*;2-YD#wuN7(nF+v@wkeZN(G^*icx{ zKm}~{V(-pPr#b^^@>~d}zc~do zI$lO_yn6*eCzxO%_a(M{;euCHq0AoG*2}YQ!mN9&=~DIxq}XI_pQE6q zp2alCe(mteBk>iBbkdGWp;x+SaI$NNzwfDy0+6&`kEw)cF8QUg;K>X;^{P;M&2M{$ z53tT==3eg}LC$=!Z^sCp>!xv)%ntbc=~^RncYDLcrW)rq&c7h*|6_P`vkq3SX?1n4 z6<=RoifYSLsa1C>Ma?$2&o|^HV9heCUtn_To=S_>2KJMM#u6MRZXQoq%e!EjUa|Yk z;i0$67hLR#S1&o{n3wc1Mu{-`Q)C3}LYhj6h?g}Xw6F*_Z6YoBX82`HqaN+hy6|W# z2j1>m&X%vmr|P!li?f9RAC1vMzwX~xj1seku{faH>_Wy@vTZCLzZ-_!!uN&$F7wBb z0A>z-yZO9-qOj-syM1M*m7aJKFP_!0lJwHLY2Je_9d=xpi0qO6sA8q4sj z2SNBDF{uD2+dQYi%55KHu40J0DyMqWboZv)$974V{)hEzFvwsDux za0OSDkNR;9BG#kJvkw?vh-i%+|F&=?eaOM^V9v#_!BQ;aA@TmaGVJzyC-)I)d2>2x zm0-!DnWnLAUc$jg3YB6%_EObbXcOuBKmvZ>iV`j~0IXbEdX`c<>>o@oNy*_Gz=uf| zO|_Fvdb-4gh^h*JUta@0bN+aXX7$Jp=}3Sw(o0_W`(6S6U`nl{gJYB`{DzbMpV>by%ns7dhN>+uJl>n4YD@2~d7Vgfh`8KF=FF;Kd!SadGD^aE}i7 zz{3}tPpu&=y|^=9srN$ep9n@$Mqp)C7r^MiLkIGuzS~8>f+(+F2Ef3A{L4F@b8xm% zs;IH3+td;4xuk0W5c%Kh^YPz`cEZ(u<81V8STEwt+Ak(VV+T{W_PYSmT3hRrW(D+5 z?xIa9v-~duDkuWFam@Hxll1^9Ay&)Ud%h^jlYd7$$-LQJH}hwJ{|V-2Vlwvn6S#a1 zz&5{)3h*UsdZE()>j-lG-U92l6(ZP=ijD% zqW{Dtj#sd}25@v1gkoEY4nS;8yqFVB_TT+tgWN31q5&qOtmkW0t+?SSKK>GW^w2^R z$8XpL{0bx!!019JnPX<=eEzNDo_OX(gJ~bZ?5sPs%fH-)XqHp~=@GzJ8}G;+Z`q@? znX`*lSJ%b69o^OhBq3IS-RfoqX{WFMwQW@l0odeMDI4SSDuEpkkb+k^L?y(k#K+`a zUG4PtBlYwO|q=k48PR$L>>fz^|B%~;^x7#s=v)*`rd@Ts*F zKh*qpg^-;9FJ=IKudgw80_^N*?a5o@pz1#>Jaz-m!k^D!UkGt-HjpTrKwk!>f6O-b zqo@Kri!fkeu{JPteio!T0;KJkmam~_DNoSa^k!2QInjBIWf5iW3!flPjIf@ztQ=tYD9V-!Dg?ug(TLVr`;&937kkyuQx- z&j;N)+k*OQKazHc^HRT8K?h$@$u~SGtjs0AJCdeW!vLVfB0d+DxeQxv#?+KPxc2B?r>&l$&hc*u7-VmjBImj+kiX0W{3&2HrbS}8^5NR}kYqxl{_Zc# z%^l{SebiX{=@#IZ+9+eSjXZl_mvrH~8{Pc7%K2D>x*#sIo&KF;UV3 zh@&FL^!kZJYKd@?jLA@%!Eb z#j+;PA=APGXT6lz-?9OY$$Uqm+gRoWIED7NjRAk7Cz8@M_I6Ln2$V1Vb~JEr*{xV2 zSqF>T-aAQ+VOHDy_eREN+NhPbmbM0cF15F%kX7vWzkw77>KN<o%~yC1 zknQehb;&sYr=03e8sV~Kz@`Z3;W(c3dmc2%f_2gVw9E!f33S+Kc{Q|CH4>Sg5pV-B zenCb{uM~QuJ(`z%I!1u%x&r1}f2uohxLffd^XbvMli#I-HCu1ylI$E5MGpJH;s6uZ zdv6Bc{3uEH#Xa!`5y9#$MXIi(i3#-X5sA6(-FbzWHq&Ij^Nvv`MYmvOJ8E+vP7Kw0LV!D@{#Hn^WjwWcE3mrkISRd`h+Ylr=o}kkBt^TA)+T&%)?sS z1dhEsGwsGeg~8tsJF;&fTt8f56zDGz9U3zvr>Gq-2lj(6BeISTk9!qhFj)_S(_cMS zgaAF-s%PedZ69j7*_jc;XE*HFQnCutG=MGDgnrx(DQZhA_nZ%pT^R0|+>z2SoSo%{ zKkid`sSSV|l(Va?pMjg_R%sGkA5r?7&!8oil#q)+Q_CS;W5g&2X#OFJyFmK|(88Q1pQR;|-z+a$Exr0*( z@>c_G?Fs$6z%Tm%QOkRBBF!pO+J8*N?R`Xx2kFHcZ1}j3Nf0CjP%Xn+hh}uOVhB)V{#}u`_##Q$21?u{Kh6fo8+Y#q#3`byyE7!^$mgPW*g>7 zNz}hY%?NiYWUW$jrlcf&&?eZH>aKkK;!*UnoIDrMcf}R=Zi^D9VZz3bTq+ zrd+z2EoZ7PT|@I=r1z{~?b7a%k>-KI%tF!|t5+{O6$)HF?Q8*JwD8k~=HxZ~lS(d3 zUcXm5VW8(FtQ4iW6H7U^%#k<)980vDI%*u^ii7RBo#o z6^!;pew+sqmLt|3=>81A-VW7wFSvtm(Qc7OQznwD9l>o$U0oJZx=9s_qiLxt{>NGz zji<5}``>ExL17+Y-EI%xi2KVT*XOqiTplG{oIpk0eP(xIW{ zv|i81uqjgYZ1!{TP@}xj&nQOti1-rFR0EO<0AYW1Dg|HC_#~3jK9w4xhZ8yAoJc1& zayZlZ#kS5*k{vbuWc%p}dEeRn@B7qCIv%+?ReF~<%rb4V)?CLrp6n<3ef%*~RGP;N zbZmvo%G9=j6T>rGie|L?2xh0VbBxcjWn7qqvRliMrjEdWx==+SLlNlmwS&PZW@8{( zEe;NH>d;Zs`_KLb{}T(GAjjmiPTU`~AOrf7~DT7v#6R)?72^%$#u?#|$@{ zjbmJy=$=xZ{k8|7!l#)&aH;v^`&_)@4@g);9&lY2Vw?9P6dR(t{;YW0;y3@ZYWih} zAU2fKt!b`1k!1l5Fa+DJ$%sRFcH7dA@KW%WAZ$|=1#A$GzPFfNZ+NoG5{i1tXXY z8c!xQSfM}3q6;5DKO{XYv~huAb>IFCHA4`i@P@Bw;I7h$`mY_T z{q&=QE8@|^otWylFPx>?altY#d7qb7%oUi}l$!=zlQ#`C7S7YfhBbeiE~mX2FgTm4 z`APOtTeuURSgo(HeSYf_*CxPn2mjD=L1VDxwHxGE3e>dHJtXNEVRS%JNMn2|B*d&e zb#1>Ex_qK^8GIqaJ@_1D0RJo3SC7YlKz>dbtfZ{4oGXN_UxLq#76@8l)cqHB z^TH{aZ=ng2=~m~Pzz@g+oH#=M{$@w{y+X6l{FJLjrnOvG)$#{*1NXkN=Zj04!I$%l zXlZiWI_M^BrUr)QtgeTW`tfuSr9b1cw*PDpw(Y0&*0sncXI`2*v2Z8=fM+E#UYUqd z-pvoLZbo?VjW5axvpg$M(9ISw{Z5)5e;yJa+$>$5C64=iu`o9;41)qL|M%Y@;Nr*i zS@-(qV$)63vlYg{vUFYxeW4hzjLKe`v({ZiL@Ix9a~d`~)$7?R4xEd4#>t*Eb||$v z&wKu5spZJR<+=%^R=ifYqnN%PiZFHzWD{QYetwy4GJHcg)&f0P>ylu&(TY%gG}ExPjob)<$9t)IvG@18 zoRkXU_WMBRU=2-zfhZt!34$DJZ6aIFTI4NtNlmNua4~a!ye}b`G$)paL>Mifxooa5 zFzCj`r=NI;IJbOsUj||isFAAJMOPHfjf0qtP~)k-oCuHUl8t%D+uh&gCqyzQ-OE!nUZRkm(_PHXe;9{%+|`u& z!HUC1+H6depU(ws6|CcHXRdk!HASvuJaPklE(^lmyUW?W4&3W1?EH)qg_{{aV0K)pva(rmqv z5^_nzGOwZH?FMqn%PhdNDuLpe6<>(A$CW^F_anL7Pt5C9J$`-j%#xgMJWlU52GW8Z zG#9*A8@}Ix{h;TT6UM&T_*c?$2dlHNN#WZ$<<=~nF%w)qxV-%%%OtVu=pz&cm>Djl zK@eY0^-_>f_1zrncXB++0ZWg3-5UQ)JxvaQ>g}fLK;hog4Y8L03RxBo6S-a5=U_sX z?diYPuJv1Dzx>?hp_{yOwixJ(16vqQmo%q(Wh|tMrVDh<{A*=pc7%UKkL<;nD3XQb z{Mtc$2BlO=B@_>t<?A4-m{t+rg&QF1qdt^=ByYf)_hNfnjWXdTl zw^r!3f&3m2on=E)w4gN#$QlZ1CeX=fBWuL#&XU7CD;{=6B6NHnm5r@La$~cRv10z| z1`C=OL#MYghQdj@MaFCAqTo!eZvz6}KooO-lywcxZ-JI-r01qSt^tkMGaHsa?p}Vd zSQ3>Cmi+72-M09(KkA-mo` zAQ8;&uWdf7Aeg(AOB?RQe_1|#LFRhIIHJMwP)Hg zl8K+YcXj<>O)u_#gO~o>>*}fxwsEL5dg4If_AQ%>`1btPwHV!#5txQq9ZQy`IBiWh*` zDN(WSGRWB|AeZGaeyu->7Jh%r!yWeRY+0KgbS|QM8`>uXAljjN7=X`Sd*{_@JKNYF z*F5Yq#Fv0MsO$Q{1@j8TcGzI4cw3^MOgWf1mx4`_i!~b39w#k+=xT)pb+|RF8y0*Z zlC@nd-glIOZYx>`r7X$r(tf?nB+<^oO;mDNYw6xpeYhX*f8X*OR%&iFxfBfUTl`&l zeE{L#G}xhewjEl|4tBUJD1QE*$`Ltdapxl3A`HIsr%{qB;|&fh7vBK%iX0sT`UYkq zsEt!jsYk)=mso0s{CywMbTe?D2A80E{>tE{4QKH4ig>e8@NO%$lB8XYmqk!3U*S44 z$T0J-T8$sNEif}l(b1BS7=>(J4)eXCP-%b#knGOKmWXhCeVsJMcp!eJy<98oxp3D@ z$69?pT0v4!r{$rIv5<@8MxL@Y#&$Wm_*qc^VH17n`up_g1iXTV!!=#k^S_P#0irGd z&2Oq|vCgAG_%a$NN^=ZxMoj~DTN7Ytov8DlKc?k!r6Cd^@q!6Ltb}#X1wgHv@>c<3 zesY|vM&j8RgZ?cEhH!>L8$4GE8YePjx7e?MC}LApj`n~O(uW-N2(t?RYG{{pv+TDn zU&t-Jjcv!NQbMX+l#fpeD74MnAM$~ysKjeE{OtV&L2CWj&ZQ3g(lNz9PT(fVKB2fM zhcmR5TcAWq-|Xzs4?v04cH)(Qag?xIh_mFM)%|@bKo%o;ajUMy#Au0#Xf-{hRf`C-0;S#A8(4UpV zB%X_dt?vo31rRM#4wiNBEjpa#Ow&A=6i6`-jZ3;y#`_<@sR@U}pIRKXoi|81Ixo#0 zxVWZSULPI{<~hUaPAcBoK*#kLO}fLypq>?XdH8@p4umB^gw*Yxo}M!?w||8jS?$=H z`AHZmGoWr1=Y)wB>+j2`%Ye~&~k|Z6ZFFbG$^;9pF zH%B3ly?)FqrmEhLooz3~=iLp0b5U(n5%FzsM%BnN{rY8-U8JMHb6jusM)=ZI%@IWO!RPg5!053Jgi$2iQAb$fYtY*$K7^@ z4p!*$PhXi%-`khGFsS!**ovJSf~^^>QS9sA>Hu2=DI-9x*^?OAn#9CoNWcnUa$WTa@m zW6gJ6bE&iF7L@riNc!o{{)hf6#~6=t89#meu@x|QfU4$a?Q!;jlu6X#W^Bz(t+8TQ zUOWbYyk+l5oOgN5kk!$~Y8~SSz%IE@40dzAo;qDgeA40O!hezAnxroL;<&R_=&R&gZx_IC&-kHJbyuHVe18V1mjd2nwE@Nn8$ z1iyce*)hIGK#4+}c7sYEdIAoJGje{O$$0RW@BmpL-$v2fFg-1R=hh&t;rfk{=Fg}5dt})}Q zwk!O}_Cu+!Z6Y>(yzj)~g}wt(3g3LrDf^WKeBfF2Kh(;#RJ#tIyMdynX<_8h7M^L> zn35b@wUwuizQPv--QWCY-9KhrrUHwZJh%j}ZmfV*a1QvDE)_F`$x(irsIQpUn}K#X zq)Q%-^M^?x$%C%?mW_X4j`=O%wG8jFi%v!#uR2Sw%aV^s9Srre>kj$d7L714NDfqWBKVyN&xwpEgZ{6zELh8g69$R*m7mv zuXObHufhvGT1dzM$az(B?VmQDHHu&TI1e$RRHrZkN%*xkr_{n4GJ&h|wABg_eJ3Rt zOpMK#D>0(;#oUK*-zIzqz|~W!Z6$d&s6FTr1!Re_1f7@8qQ7Y>mhngN4@EY?KO2pp z$fou46%L@Y^tM`UP`@jE*g9K;%fAMJSRl&s(jmrZaCe~Vd=aU!6El%O)a+#QM>N1WwSka+?8%0{A}{ z#%P;?ak1??>zd25pMotcY(RjWh+EO*sg!HfQi_@7S6!}LZ^|_>az1*OG>F%EEzkoSrLFwdNsfz86J9I2TF>+`h`g*srw7e&4g#_y37d>--`5bKvb<)76f&# z6SRYU3hH|xkiII!uoXBo4sA|TY1coAcWei{XM`K$>9=?^QliS>G#xUlrjI@HMRdXD zxo7=F+%QqXR{%Rv3Y~f6!a#AXQ6wMhM9HgEC9CQF*Vw$6J9kqPBRk_Txg@`FJ%TRX z2mPJ%c9AH>`sAXY7(Q6t+iQkwW2jI6su4ukR{xm->lB((F$B18miMutnc*mYic{YD z5jj*4K4z@!PwSofT0m1n^=vV)z+Rgza&2KzDr9H+GXV1L zP1OXggPu*|QQ4cqOMK{k{JEqC-sR?)8GssgnnqgfhQ4yO{o52~>hXmn%k(YOIO1H@ zGOt9_DVjWEta)n%D49nEp4NqZTm1Ta2a$yqgw7_Qg1MbyrfMPpV!YUKc1v{Tn2q|^ zfb}8@Ax9Rs|1PUyw-L^8-HPtzZ1hSNz2MA^R$YTlpKcRmu7~dP>^<=T)@q5Fj4WRdEOybr1r5UJ*iW6ATxqPa0=gV*+TPx| z0?J!J{7w+eR4DXr8c6S_;XnAaYw2)%ty=+=7yvA+nidzQii~?bZ_oYCAMUg1j!5_Q zJ)e|?xB|(KVY|!C-U<`IaA+eJih6A@#2QTP6DoiZT@e7jZx3x1GZPEkfJnk)!Fq&n zLCuTRdVL>Ao#qI#=GiZg0JrB7B=%(oKctJ(^qISJhaURgv}+wG?SaOew^ERfskMQk z1j1fe4X|k@j|WV?%Lx(%q7KJ1+_L?J-8yiV+_nXrD37+C>ou}H&*K$T%2 zjmy)&x|uSwF>pT%SsJg%)W5%nKh0{k8q4Mn^TEp7V?j=a3f=mm_k&W_UmR&U#Oo3K zg@?1xO<7@!{mV!GBH)5N={Z9}_R%fxmL9zz*mV-{M;8mua2FoBYK2*-Kn<9f?GH{pxG`e5t^EpkA4AZ;K-KuC*6cKhsO2f@w%&964 z^fWT4NAl_Oznz|CqD$DEL_9o|roKMgz}>qT{(Gg0Tl(<|xe&@~^tg~7kC}a*5RuY4 zb5?EN?*~-aC@SssC1n(cT9oQ(_xm5NzW8~S-Xwlm^g6wG%cq%l=5pSH%l}qN){gg{ z)cS!5)*)dZvw@|Ero!fmZ!J7RWmI>k0 zt?;{#5*&*N3VpoOb^G<^+z)oU$RqFj^)ZqCQ*CC!jUm?$_W<|+R&lMtz}Q*a!Zk3k zU4KA=jq`_68DXAaj5x$lux7C90e1U1yu&WTq11J5(C8KmIw?6n`%+f`?6T8G2JN<+ zMrT)xb=#NeH(?&Y`rti-H#XJ{j=-YV$GH(`X@D#R7QLQD>Ta^}x(GRiI0Tury}&^^d=!%8X6iA z2LJiN;t78H`=bsDe*635?=zDS(Hi0PY`*00QhZ%~61{DMmJ@l^$ z(coCEzp|N^dw$~&W;ALKZ zsy1)ZK)V(k{TojA&gHW*x78G1Pt}_@I{aGn@^sVEnx57-{#|R?C?#+q+o7cg7WBdKJ zH7fcWLJ6*LyDY0egc3r~?4WA?%5`;X#8j>&?^Azxj30rWJr3vOezz(W8U?ZAF-mFd z#$6o&@O-X26NO6T&JEI7h(X4igDIj*WbVrWrJi*sU%x2wGN6YWJl;T~Trv(Jt!CeA zSc_Ij<=CFCSPI8yiue3EC6x=69Njm?TcGzmH@d&QV$uCJ*x$uam~L{hWcUR#Zgh;= zes`f8xX(d|mWYs{E-z}hLZ#K4dwqGxmf8K-$qG+jgGUa&h}i`?Vmy{7gUSM+8~P>{ zmmAn<4DbnGn-BitJ4{bNb{>8c9vxDs;u6$Zsc-b-Go`3utZ3szNcQT^WJ%ISj$#Jy zlFy~S6&~qEI;{i&_sw1nkCmc~yp0b>xEL__kz~kE7F6?o7|h;l5i`76JU>oC2_-NEosabK7_E0Eif9A^#zt0A4qHy6 zRa~ZporXRs3EjmL2FyQer?{a0@*37Ey{GxVBV*J3W)mZD;qba6wpc)~@X@7L5X@3W z(o5E8{rYiZi`Esb)%<()OTJEgbM#FFy7hLg=To{1XwJY+!(;h!QIOrP|JprMQ2KQ9 z?Y%Ue@@Hb9iG6W!`918FHwi}SShC&J3M`C zn33oDVC_)NYnJH*Urce{HK>cTd1sc$8BB;q2~miA}HJbAPSdf-3BX{z=+{D8()h@$g6N3%1rXRTK1R-W~eYJI~95J7{hU>)UGT%7UjtQCgG;r{&ED zyarc))?&7JZtLFK(nwC3dolSJD!m?V;z7X;*_)Dnubll4md zq0juk`E4X}W}yt}2QF#?G)0d`V3FL9?U49OKo-&*xW5lc}? zPGqMy9;=qMx8<2)5lPg?sJQ5dD+V7GW_qG>iu7t#T{KwCRIcdSw3Qt{Yx6oQh5u02G}7+-!i*2AvK>O~ z!FQ(W?Y?(JeW6?F-X}jdio8TgB<6FGTX!c*v}A}A+MH zRb;gCK7Pic1D>bLp_P6_*pEc+&HiBE#E_&SpZB} zVXNET;JI8~8~T?v5kjSZd}WimalkUxC(^p~-b?r(wt9Uc_~`amNH#_NyAY+*kNv0q zB$cszBP0s%JdApZ%U*Wf_Ow^!sm;&Xx9hig>0LDeyNQ(+k?9|9e}!$Fr|{xQWsar! zIyq3IiLWYGmrjYv2?&Z=R%Y5VuObIa!mHTD+2KT+G92EDe^oCebmB74f8_i1s15s7 zVzKH1Yb`Hrfy3g3wVd#aV2KijCR8GB6DfGv7sUm^4m^t165U40-W5ysM0om)Tj9zs zBudg-tVFLpPS%N9aVS#WJ{k!JHpZ=I(k7A>!)iZ}8zBy0LMS}Dem%`LdHqKI8Zqau zL!X8~QMpeCU;BZ*C{2vOm5CN=MoWg>`q)@55+Yamh4f^K_>B$Lrc;aLW`nQ|#LK@g zwa{b9_r_Kel{@q+YdC8_QAo;Hx?X>jh#ciH)Tk}v>*Q z!J1O8@$3FWJd_jC)e7jN8Y3OYSaZ0`VC$A2v+@V@=u_#4wKqLX49Q#kF}%rPf&{fWHub9vkF$8saCbw zK;pfC%CmEU%lR+x=)MSaO@Wym$6F{MdRMvA=IMt)B6@I;7!?No3YR`_6pbk(XBzVaWDP7RX1%{W`O^`Du`XyBd| zDkP$kv|#e>u`BLlB@^2>~t(c3C;JXm4 zS5VfnY?0D+yattHa~bRLN(lLZ=ds9W0?a+dslu#l*y>qFX!y&Pe|k9OwG_uA!R)^) z22T7_1YOpL-5J^eo1lP&|?U1b3Zm2{S|~MIO8l3y>W0$<&H%A z#%6}S7CmKUq0av!(KVicFEZY=k4ZDCr(F$}Q3{q!G`wHh8(VGXd<&0RW}%_=p3~cp zxQa)^^X^5O28Lr?$nZuW2sWvl{fJDW9}lGEw7M+J^2M(@cQv_x2(w^TNAtj z8PTW;b*aHPs^%^Qgr zzv{)Nc9R~|H_3Wiq+QbsMV(6UP_wAlNiBJ3hJOa5lB|Z#X?%i|v;K|6BOt+ZG^=V6 znd#iC4I|~o!EV(0R1qplQ28TY8S(-loYgb4)p+!@t44*Ji_GZ-e*2_gEM5d%cN%&Bt5Ppa;^ZKzV-r;UQ3Nf3_*%wQH2%fOmr)Jt_H~YofiYbhT3mwOfK)je2T+vC6NO&Pb3~U_t0c0MZsg zxhx1%+06t8gUs&)bGsIGrV6%g;*Zz==0r7bBA5hxW$D!%kH?jS^uOKzZtR6IL-pW+ZuryL)71>=-{q zEwg4MokHsR04eF`n4NH@a^x%u@tOXJGlr(}NSbVQ-02;%r!ndKJ>eZF)3R~W+YzwY zeY6$sBDyTX)J)ekj*kEl+IV2ZBPDkoRo|%!Zoy_{T*)CJQ7=#$<(%?qL8EF>!85n} z_`gO0@BI{hAD)@>^t02E@~0Prc50-i6MoIx|(SFXu>F)jbq3T}~KLE7^h|^&Gw8I7kqvIAqc{p4HTbo;zVGt#Y1xM8W-T zrXBFHrnuUr3ghLoRL$%>Rw|CzPzATA{01|~D5rQgVFaeV$iLZ49@ZruQ&z0?Mme+P za+EYgHau#ZE`)-`maMAqw&W(mbW}R8{R5j=n3;z^1(=^yFhB220#@3nARpHaY^CTaNS;{-4Kn7DtP?-VaK$+6QFW4pJDEQVQD_A31PSV~wz4=Rw6rf5 z%P8&J%6l0Q#GT_6A1~KnU6oC zcb~1b9Ou`Fr{a9YGRWf_5iddLyw@1t`SGW*qCY$yTs_xiRXTzUfgUH*h+!$Rv08Ys zgQ=U>8B`_0M4q~`A@;VMGK7qBBm0NVVSk#S#B@^CS-jP69sNKeq5HEZ+yZ7E*%z2d zg4d9eqJS3^WEj~T_vaYK1>ZC7<10MFSuJDy@IblDGi`Sq6zjA*L#Hr`KjouEEAV{a z3D{Ys>bw7ke`sE@Wu6T1$f?>l8Pg9}!}D+A3MW&|K*no{OmAJSzB=8KvU(Tm`J}zb zL?bCoghm0o;KPruPp=Dg`6ha@{K6F-*|_B3=n!S`G7fMO#)=&EBTV?6)_b)i`kPxO!?39v-s=i!2SX`pnJnh zsi8=BQ^mH}`Pw((2TCjl<3HAS&JI1lTffsQT>kvl(ZOF*|G5xD!WRBdWtUe)%36{i zF;4nZ8&UGvNL(weR3byri8rysj)F!uhtfinT|NmSgp;wE7BNho)io_yrz&sF8}i)a z(<#pMff=X>cp?1krQ^NiorID!`{Evc^2wy!C<+%AQf4T9?3RSq4Dw*60H04dS^I&M z4z2L?hw#rkf6i$vgGT88T}syJ{2&|LR&(i!ipz%{T%k<)f0EpE4`_M8lh%8F*NxDW zeED5NOFw~US>?N$ibNvWT6^iGvYAgf>l`h{$=YYw{Jc%E5I zf4Lo2BDg&2#*EndEG*sac@*N0LBv6S^3yk#kne-dkCeEE-3c`%bQ#GgG1DFf&z8vN z5-~`&SnuPkr%G46MsmbLm@(gtO%W_iFkG{>-%{NU@_pD#meZn4$FPt`DDc)$JIfUC z@;piLP(8*z*!8P!%g<37&7JnCUy|-g`d_0sOJLG6$M}()iYMXsaCf;tSp1HmsoCA= z-pcx&CT(=jhdEoW<8)eu)P{&D2?Bj;*0n!WBk<|!Oq2+Tk2lSquVhovrke`$N~J+e zL&9`J$s@e04XL@`F|A3Iw_Wc9hA^(a(lce08pVG%Nbe~ws;qJfAe2M5wQ|ZVWo4gH zg=C0ag}MyR$O=_u7XKW6%8Bo*-2C)&2Ht|uwA~22Ysv(R+q5|RN{+Kn6ebI9H4xR* zmpS3iS`n&w29%d$%nOA3sGNcNC};$#TLku?ByruHDEf7Rz+%aD+k_o@uk8vZzpoms6NZj=m7yw3=p0p3#5Mg+|yx z@D`$YwnF0^Dv!D~HhjOllgta#gmrqs)gZeW6yWN6o}()2b2{~Q`rbEdEa>Nyq1u<7 zAfT}FdK|CzFsQlY@m8HnEKvY>jU0vo-r)uFKKnwar1%lkRV|@3DSFL6RnK6Rs$N+4 zw;#QEd9mBij_Iw~u5Lo+d5#B&XWeAc8*u6)g0Ma18+I7pVrtJlKO$$8jCfi2a&<9+ zt*s$%*Kwce!!dA2yVDhib`E%Wjb*y^uU>F4{4*Jk82YODU3MlI2E@h-6!O!-xcc!H z%1q_Wxu0hnY%?5MvD{i-8Hn)gs=CB`11RDZ5;vRsf#>yhVb3}BWwb>@d47)2lQ!2S za)Ky$QC_?SP_ORFdH!3ka)tjo@Xg?LeT7uN=*jd;g+bZHYNo+h9jq;feulyZm0$}4 z+o-)%IA+Y%RAT!U6`Q`#UbIdgYqtR`9KSWB7rPjZ4NblijscJUV7Z%UsUjNsDS@wnjxxBh#c$@E?ryFh#$SSa6I2f)0 zz8iYuq-2`yXJ-A*TT@0-b{nr+82{;(B)?UphqJT)i=XOAVQ&{ZQr>57n@i(Z3t_CQ zzrm@yyy{I;7D$Ac5rw7ciUWWuroR5tOSs=s~mq8 z7-ZkWz?l2%xKfdSqGuE&sQI9Yi3!fi>$BJaC@N^*y2OwPaG%;NwF#J$Pqp((Bt5Pl z`!4=4mU*zyT*I#>6Iz2@3JF(p>DY7;X{!Z5?<%7V*J_{i+>AmYofyX}2~DSvL3+3F zT%0Z`Q7zOaG*Vu?OPfzW_2E%nGSCRAdz(tEm!?f?$AQ%LCb>@K1+cg zV|Lvh3l1DiPgKsCIL9-4+q2`kVY`$nJofuBJfeGu#sxq6a^cGaZkZpm-yyi#vI+FO zgxn5BoBoNP>0$!K2)z-C@NmfDrZS7@x-4iw(pC(dR#K?+*)lEKG=aVkdTD!+$n#3^ z0{*Il1FIj59mkd}PSM#=r~YxqMFL@!?_+y#8-tlDvnh6ug#tEnyoPzUND`&-6am2V zmd%Mk`o6;6QXE6%tcfjvQp>?-o##)?h`s-6^T&>(2=8Gbbyxud92>*)|2Q^Y0O6xq zu}1ilNzjo;O0R8;!Qo|e6*425;9quE#1_S-CBU_`httrT7`BuKJmZw0VUGlVR(ToE zoHe`-QA|UFHO5XqEJ0ge)>)|1;X?L7U;A2 zCCZT=jbP&AEr19%Kk-=+DIw#8sy^`vGm`<2l=9gtkw+MtArDt}7#Mo1H8_;RAJ18$ zeo%%QUM{#$H;Q5gbf_4bZAwbJ-d@MG{da}PE%AT5_>u!1oA2CU2FXXi=2{~`MeOn8 zQ#H2B>`#-w440*J_DAtZ-}5|q_4LsoKLc@#MH!~b_QVh zCdkvO6{T(Yt2Un-a}4C2Fs)yHv=Up~sqn_qMjo_}+tg`B$yRpD!Q7w)bTwtcYk1wh zVmKY%9oB1yO~?NoXPRbmzWd{Lz9#F2^J8gg|9T1%VB_70!Fq0<_ZWH=bR@M7wC{R~ zO9P~%pQ-+GkR~28e}^W;H@%P=^0^mWXog78(B{nT8JzynX1?J#QP<9RT;S;=I%yI( z`E>5l2l>F=BZPAsd))g406GL7+;fCSTSNMubv7$e3rzzPVy1_suMM*vc@2_oOPTB* z{&+xK5_+4%a_@6)29g6b>1Xu6#c~Sz!+|F!#hTox;LPZXm-1VkWY#}kOK^T`l=9*e za+J;*Rq)|Ut?IF%G%hyZJk4^wpQ4Aotc}H)J9;Lz8uc7hpM;GUlB!fn5qw|A6gWl3 z=!UEgMt!!rJExKPPXel~I3qyQI`j=W#e66gJG#e8MDNs~ReP6UhO#+Zrpsm0%MQKblFCiTTwZy0f~9itDV=6sE>XQHR)DV%*K`YGQl-;)MjG7iuMCqIl4_SCWAzgGr;qifE%p8D_hBVS5{t_}^`B#7-R% zn#=P7Wp(he?&~^9A~Zm4838H`qzaRmL7ntX0Sca@LNCeA|9(yw`7cxj9>UXa5^>@` zxbA7ZT9lACEzv9+J9-4@L)e3V3!V}<@GJc_fLw!ac()zCR?G2T@;GlQ$I>UMm`oOH z;Bh$N{)|KM0CeQ!DE$9yAJ&7+CqI0(DktC=jC-mYO(5K`ZV{sWn}s#Oo&ex|ZmGC3 z&DU_fdGvq2{T?Cu9F)@%(b|U$zd^K1bAJ) zU;@K7@2gPk7xak(yN7kt1`Q2caKEmWf-rbPh4cZjMecK^5;w&4KN>0_0PhqIbThg$ z`fB(0^S||y+&__}{Po{YS+m7y8ft z{AXhD7GQSx&u6fN?%%Qhzr7FG>+g8~`-=blJ{VNM_OI>#`-Z!vhx<#A=K{8i%j;tA ze0Ta`%kO^6P~;u}!IkfR;w*CA6~I=?O8fn8d)uGYhB$P5JpU_bcbxU9WFFquK)Z} z){OSa9me?)7`Ph;A)-5#OiGdayjy@whwS|}1QkLQ5of>tZGHRQ(DjJXk!~ErF6;Tv z@(1l2;*u;_xAyCoKBN2`By|Bi@Ac--VWEfg4I@0C<}NKmpYzN12cOw$vjp4T<<6jB zO!-}?Rt6hOFy*iHvcnZiQl|(Xnv!+Vls`a!gXuanll$bsg`*76L1Lmio z^EUC_M9a9LUOZj%z3I7@a}6<*JeZl9_s)QlHGfRVVewhTMGUngxYT;OypfV`HS|Ry zo1q<^K-(qS_T?6+9LMVImu%m2@&Owl0BX&0ykOqY9#F%8504Vsuk6O4%W%O-EFT@n z6P_Rh`&XKzpc5w>x)Twha)#>C09!{Z?%-vwkm&n-E@rnn;4!}w7Xm)T8-CG!4Luk7 z39kc=O>!S(R^{rZN6I)+vki`GZ-%*!?|}N?F4Kt_kqykW|6}-HU_%4y?HEjk^-`M; zDAi(kHj@Ez+p1Mz;0Cz;`9|kiO|=~XvFkezP^Ly?H3Q=J4_V9o_3o+?V0b^Nob{Xh zO6TF`08~nJkIS^aTYizz7Qm;$w=sdhf>pn1nViphirKvxSml}>y+CpFoPYpeex#Y7 z7yf`?3^Kp#03mkU-yAq3>X<-*p!n_6-Nl>|vUrxDk22R)5{pi)1rSN>xe!Tk<@x8v z2255Z}#gW9&aYII%Ib97^T(Bh+*(TvrGRYy_l0YOyPj&eot6`%y7Q- z34@f8Y^>(JQX7(z;8orq+IPDKRxNqM_A zG3eIN`F<~e>?KEs0l34A$z5+R#|ZlJ`IX?^nVKxx`X`%;){CxzT-7L#(;==J{=N2x z`$nNUt4YRz?$^WoYF>Ey*CtgtY3`smfm9LM;D&f%w08{^#proLYm>ACK7neO|4?WFL3+R5}>4J=k5P*GQs1O7AnQSA!g zQ+?K=xZ2LfB~?yh%k}FDGP3u z)h|+UBZ$7To97Ns&UBr6`!RQml@?w?)CXo9f5e)|1JsB*6_<@ky(PO+Ux1gBzUPm# z>UE!e4m`Wy!|f?ECS8`d)5}5zj3=V>O?}NVdK7yn7l%va5kk(7s_0VE+v^ZbfdYe* zasjUss3E#V*HA3JpC^TPf{X>Yf4l__Z9%}Z0-cE;D|9XjV2n`^n8!15G4$H6Qw9B9 zFtUDqHCHY4$nV$P_GX$rK&)B6N{455gCdJTagA&WyQJD>do2767Qj_pti;1Usf=?x zmcj?Yq(>15kdP!tUH2t(p>yYjRJgq$L<#>I-oyO-_4Vc5Q?{1RH@-kHvYEym&U(D) zbr^d)p8v!%nCova@nZMAbswz+;*bW^Yk&}T^3KvXkxPyyz?uW#g}*}!kW{Eg^8iW3 z3L%hGw1P=P;lc?kl|^{I_l#AK8=PfvI$B1THfIk1pqw6rlM0|R6c0Eacj+u?N1bpv zHS^Q!-HNS6`?f1YT3ne?OX6~*C(p?qVDgQAEdviTkUHRdyoIa(WBKfnm30i^%Rrsn z`G^>r#$bjycC&uG2;S&;8l|7LdzdY!zxWyt8QjvdJOw^MytJFV67N9;UodsLtwer6 z!wx{;SPK>_Gg8+H6*MMWud`99B<8oG+RD6$thgzmhz(1w)B1f+$6RX@AL0m8*m!;@ z{M?MTXoQoPCNry-MmKsm=4fyS6i(kL(n0sl4x*o28~3 zxFb2>1x)#=Ud*oR!K4K|A9rSi$~D+$KkHKbx*}L6mk3!V1;J)t88J zY1eD%a|yfT+umlQCocyYUbTQfjL<|LiaWQ1P>5rI!};qBfLfoUWEM-us4=N@%7sTw zC3#5pl-~go#lpI z5d9ql6DdTC_OBdP6Bd9a;Z*$a%c;AWBNNiCQvY0$2ToLH2vls0RuXrUdfj#(A_bh3)+#9l1`# z#pGeaPhAgD9k??u@1hS0l%H4)m@!_dXJQsW#ScY?hepBJu zy5ZqOFR+H&){Xm(mmz>4N{Cg+jHXw*l%I15$A^XglDm&KzcEm=6fs<}Hh6}<$QY0(8c{=2%ABR zb_;DR!^?;fkX7_NS)uM6e570Qe4h+0@JZQT)02))cprC9%)Wk7F zyE1z@>CoY-ce&3!9un~A8kEdK@cZQO!BB0axp)OJ`ZRhaq^^rL zZ}`6Ea*BTuM#dN5_Hx`MI zG|~XQw<+)^v!S0>1fy8j@Vgjz{hX}z!c4x|;NbRc9LQL=*!-a=*J~V$%A@L3nsrXN z2!$dpHZ3PGX_o#VsZ@NTBg9SH6KePFl2(4y?4}C;ds;Om>FZAb z=w{G%Ek~HOY`*&e?r2q3wYO<;g4$t>EQ3(yjsDh!b2X9t^pmlAY7GWnqTU5s)6Ax0 zTJ9hU{0?+MSHE~|iFL+mxx2%_W!JqKmCv>~6Wi7>_k#}Ahz)?rI?o=0KYJD6%J88Y zG+K;Oo%DyQA>d?La73P7iDB@F+uTPze_b$h4vG?uY!ezLlst7CQ3Ac6BW6_MPd=}| zxi>Sldp~QAq;7-wuxt3h=+$K4ecVGy=`Ag>`N+e8Q*fDHZ~(scOEC3j*^6c_<8W3H zUbEu@@w=Wg6sFIgpDFn$>X}#bFB^WjKcmzZD?L!1(W7qvI__n{{OBSD5WQ9&A5(Up zn=KFoL=nifgyVdA>)}-W6?h-@fOyLu*3FqOFZglPg|vYHcmG~5+KRbckY0>a`XBAEN5By_9Sr`qDV^7{-WIX%Y^O$m-Ctw z56(JDpEVa#G$=`N;QCQwTGafuM{`l{L&V6`rRXGq-)WRq2x3SRzD~@$Z&`c9)1{_b zC3hFovj)H9bxh|STU%#>515B-d}$m@SRDB=(g8tOJCQmMrNFhz88Ip2lILE;`XD;l zucK00S-_0>ec|ddCpZl8s+3#e0Z7HgKRnVrNG8hZ(ryHai~f5??5FD}A3DZm+#_0# zx}Hjo!iz*{9v6HRlDI%2UZ<==lYg#q66LcCVn*UeFBeS&Jkmb7VwbVIMB$w_IzvZaenMpSzfaK<8Y=P?bO zT{gR~Psyv>svnp#Sl=(d$2qiq(=3GxSDZpi(F4hzii>ItGNVMPT$Gzg{r6$)_c#me zjoAL9Ynl6fOj96l&(5vkSALj!SpUCT`^vbex~_d%Km-SdPRRjALPDgKK_mr1x?7YO z1PSSoVFoD$31MI;6{J+UQv^W-l_g;I&wXU^J zw`ij|G}-=g30&0&lb7(D$FT#qTL)3}+`fZwJhYH7ww8&xg61Gc4^?xxAp^N5cv8)I zb-hJZ(0~+gQfi@vrJ&IJxc?tJ_G_TH{nPf-^c6R>#I|Z!2zui3iJJm;^-u(%;^a!Bd-R1<;5T? zBw8o40!{;_S=9dZK1{oZ<+eclIjQ{(5VKk2zRwQvNRH~wklW7F+xdk{Bv=ni2%OD7 zFT(^qAok0)}Kie8LyqN;iNSM7fwfN1& zFE^D{>C;w|KYwvzoh_gR5O7nceprf?Ru#xDT2tUqlGOnES%+KvLjFDc5j))0aU}67 zoG}=EoBK`V`0nO&b*HmelyO!nct591dIkP zqHjMA6th=jl;oPW`;YxqsypwT<85lcLM<3#2os(qvk$;&eCZZW+xQ(Cw3Qt(UC#tC?D}!fNcj|Ea4*=s z2v91Rjb{*^o2bNh^HslmgJ#{6Pj?{qLN{r4=BM~iiB#kv=-yoe&BUSblP^lDMy`H! zsjO0;D6Pr#o|wj8G@;ZC#!p3=n|8&IRYBGtzfXG)HCVI;@U~%hi9KxT_LLd2@Q&iQ znc++w9gpNZ<^C=^?yC-Xkc?CMK}uD^<>4!jUZ-Dmx2(OuvyeYlYTPcA$rd{D&dKN{ zZVLFeThIv}s@>Hgo_lJ|&o@9x3Ss@z;94`iZ@Z}iL%IiMtf~SIn9_q034TlAn%nc= zqCd_=-4{`sk4Vo~3d}W|1H~#S^yko+?LM&EMNTWi35u#dX2m-F^k84?Ap#>Q&cyF1 zTJ`MK4I*%OLae90qQBP;-qrrG^jtC}lOoqe{Y_sjN_x%v^;ubF5u1L#7SdhoA$~66 z6(ge`E6V`(sQRM4u=RF7;0wcqNtW3*FzQSt#)3=J9mpYJQiS0ggQW%3!haN{*r_Mh zXulwR!dLDC@So?Rgs&Hm3)Gun{=OgRsfX@sIs%yX*#hBt(S3n1NV&W&RjL%v*2ge-17yy;h@z#&uT8XW}~J%E>&S zE$@1s4XgeUw+{Anxo+YdHYM3N|Ll?wi&heD4S$?^-_l08Cd;TgWm$~mpwp|wKbs`q z${zy!iesfdeSEa5t|aWnhUbA?$5vrXQKJ{;xUSwT^S?3=c?-R?I;7GcdMjMgcXQhH zgUEKq$grF!69VzLqPh)3jONo!W>Te5>&sL)d2MTZI1fNAMo@SCU#yX&rS6@AxO0G5 zi;JgtokV#U2C6a&?_gx_u3HQw^V+*r6bycCZ~u2zwBuPCi{+=|{dvpPc23Ci?{(e1 zX8HbXR)l1V5O`zcKXSK-(SC_jVS@!Ne#*S%mb3`hjKE1q4G*Z#%kMm+WO5i2o;cr|@YrM`|vbY#)iM2iQ2mTZRp5GM)xr~2w=b+2 zzW=ydvi~_wM1sYF9`r+2hr*Mb5yFkm6%2zq!Q$r)Op1{ z+Z7vbM}*sA7%m?qrZt&x^vcXpA&rCv1h^SB0hh6Tn_>`Ndx7mfN*Hq5)bZYROuCzx zsP)AbnVZ(L9W##GpaHK5JAl#|7X`QfF~dw@W@IM+?$TIam$TSibg{eoYMTGGyzUE9vXa=L?~u7GN6oU>fTM%U2f4S7E}Tq~tzU z>J~dov5hoy0;3=Zjto*R+s>O@ZqqDZk*&l&>$e_-T7aMd>%%)jpWHOtjsXNXg5-vu zx@z+r9a3B)CJYjc1~zy{sVId;1YpaF#hq*FIX3QfTTiN9kcd5~ZWsOrXyUTO${j{P zkJw!Mea!a7n?oS)*o!el!lqap%`uxbTw>MOL+EBl$t@7bDeJxZd?6cP6In`0((+T_bm!S zcLDq8YO%JBmjPbWEiaKsrbz#DcrsXT^o@7|_Iu}7RS}yetz5f-mk#0&uQTFvEX1## z50|wj)u-@CDjKvzNAh^(J<0I=Bv_1Wl8-Yea(4O-33<q1!vaw#ibF0>Af`RB0x$%~MWfq*%}ybhF9f%wx&nM`S|k3E>PLt9eo?u>vr zU|PGFctHEXZNk(%Tr>X^K4A6PTN&pN zYrlCr`wIC=tyDpoOovEakexU-Cm!qGu~Fb*75d=v5ps8v=nZYv9qs#eqaKT?PBou&mwNzA z=r~@51oej>&k}ps&EXLwH<<2CcSv^83?p_;zyr;W|_QmbiNie zs9&6Tz*Q-7*b;eu2rtAu{4ABVYBnKmdMV+ie=Nbf1~ScfT<0IhDl97o2pJcYA6A7$ z?JLI0C*>`-v?mhPi)`s2lUGDDg2V!RcTltxJz#Ne_Mb5lpQG+!Q~ucXQG0>uIE}LS zAIIFw7Ne0t$W)3iZ4~DjY63NfT0$RDbj6L zmGUbE!epM`CwRiBq;0L#^)z~vN!AO-oIUP|FlQJcOI`(u-f4>(uWWLOOi1;eGH0PO zD;?458#jFLX-<3Nw$uDA`$t@hsN)q z%e|EWCs6oWq-fkzO%2JKEIA#g*iga7ZOS4YRj2?H}jNLM_@>2ZWjhK^`n~90;PU zrVzF0c{7mDK~oPjfQ(Z4oe(R|Bm2<{If|ELCt6)d08~KXURqgB+pOp?r0*3YMjh*$ z<>7b)OlvD6tt~JGFDM^4l+oZM8*g=Te|_bT9tJp+2UWKQVM|YXMCzcUNczl!h%FwR_h)Xm@?WY+SP`^Rda{K-8|K{k^^LrvX3SnBF5+jLI~p zI%R8_KMJ|l##*(dO&Mj`eYE#8olxLjd<*Oxp&?HT4{qy}^_1G>0HUKX$CvQq81Qb(*b0d+jXuzwWt08cD}|onOlh zFaCMLJfT{}Yo63q0X=C_nk6=w$IJ#!d`8-fP2N>u{1zaKLBbU&@3-(NNoKp&X3xz- zs$JE0(JB;2cbhM)NIqO=Go6X?M|C4yRZT;EC+s~rqbQ>tovl0lG4wM3*&9| z&sUM6n!$%z%(o~oGYgNZ)+(RS<&P7^-6x)LX^o=UXM^d{5jHxv439rnul4S}T8wTv_o;29~5D_Tw*AF z&v#nED?3%b7bO;wUl&q>t+pVP8IETRt#`6j`tl~CwrQ;YU<=1gv&eh-x(#TN!^?Nf zD2#3qV><>B8OMcoorivt6XzM=T-MR?yqVG67g&Er6lT90ZifoWQa!mCjf2aZv7-2{ zC3E=ALl8UFOPQ^*yp+l;x4U>wR#dpiNOi=SYkf9iInSA5w2`L@&R@9pMz1mECHPB~ zF&omdV|^z5c&jg=W8(E<^j3Kyo{#g~hg_b2GzhO(`@Y3y&bCprRt(54Up+HRhH}ZB z-?K@hBpB6Pb8bGJ-9y|=&A3l3YkZMHyDc&)R~MQRA-L7>Tr&VyT zK$t!uK0@4X<5w;GHT-Z#K%s}4RJ!n#ZSV!KLFz800CULmGujiUUnJ3y&26<#q$RtZ zjxY9|4C{G*JOoFhOBTg3g1w}5D`%zd=NK-A*|0^u@Vy_aJ0N*ePEwsj`Fw)JEmia+11cHAr z{55|%Tl{kg`RD$BFaOVvh0xqgq^VY@6S`o9r+knTr4DYX{s^O);jj9A4@Ajv+)~HxRqzXU>hr8Gj!_yx>*WC}w=@ z)I5K)++juu+4&$Y)yB7{r{__MIQR*A(mrr>TvP-9W|;NYM<$G7S@Yap&nKE%3@u^Y zx0uUK6IBGZ7wcn|r-4fc%I+C4AQ)phR~LBn?c$A>Tk8{YbflZ&JD({xChH5&F0BHF zdm?7}`5g_xyyp;htE@tU*W3(%kstK?S6(!RPCzGy^=fh8(O#0!-4@YSKO;bp&`gHo z>rYNkjzI8pG+buqM%0Qg-;1h!q9;!y=@TeuaB0~RhwI@;PJ6%u z9|uN)VIl2+T#{&rDERYzW0o~vh|squUpCVsIQ!ify!yRFlp55UcY--#<^611mH>`3 zOYMzOtlKjH6$bRAhPJk!<1eWokQN@Swd2ba5L$}OFoDF)oKdHA6n5W#?E09;!k1^~KK%G;?`3-&hivgPY! ztR|si!}rfNo^_%)Ampp;WEWVT%lmmE$!GnlG=5DD)!xh^Qf@0vyIvH_p-=;epyW&3U#pOI+t=kE?-kj}O!rtp zt34O|cUO}rq5$G@-Wn0d7PDLfCp9QEbOojWEcX$>k+u@5eYdz{Bav6lpa;*h`@<T-8ni&R8a--5};P69b5xnzTrWlw5#ckorE&-47{;7RRS{$nk9fWa{gYNVH~hK zWCW-(+bA9U=o-xZ-ATd%49=@=A+x|p}ZuZzD+G&P)BJNC(PuGh&}kc}%EGxw7sITk~TA6}xCzm79gx zBNhbDf;!o#601}&dwR;Zn?}!ZK=Icya^V!0<(4+^Y`%h z=pu#q7#=S5N)f^>Y7C%2FG@ud2NZnYerZ|fYr_^Uda|LWd?fn?RHIW3-K@}*9EbINr5Ziu8$90d<;MaHZw7i(atV3X4 z!BX0XJ1e{Si4>$2VqOA|jxW~Lw$%A;uYQ&ZzWMi;638JvqH&*}HhmKvysJN(7 zepbG)b4>&d_BKU#TICYujwyH%@Ywr%JPgZX8-0HdMidRF2m`Z(W1GW|_}y0o#Lwb? zYHPi|TbSHSMgE{e92|`IKG$ceyss;AOWC>;BFKl1fX^Py#xI1Opd-^+4g0b3ZQ9*uEC>l&Q%&^FKruFZ(0fD{D0NlPSTj7g6tBP+j`V^0-w!hx};0L`P zESlR)BgZ;k?tn1{9W7czcDwSeFOWzhU9< z@l}YQ^&!I{NFF=B3@vl{{cC{^5;C@HRBW#90%2d6+AAAc=U&4GpGGr~+4h5;dQ7T2 z%S!Ih;;c1JcE#uvzQwwNnxK8M5korCG;&}6NYEamf9Yq?f4ms)MjYNQAPE+&_t(DP z4)m!Ew{e8H7v-rLuT6S8+c~m@m+abx(kT%q8Y9m6dbbhHj0D=hHF=kBY*1pUun3tr z+2+?$?2LX76T?iB<(;!jym=6tF?fCgef}(qR4A5$am;Y)mGntVxyC@`8@sl6` zzpWORuzQ&|2A?%VOESgtqXC$}xj7zi2u@`yNC;ATi!9xyY()8_K}+Uz61@|Dp1( z<(yTU-ZVPXm6qV@XTzLSI7BGbJuFt;`o#NV)@SRf9{RGtJ}o-*ZC>E0&4)1zO$B#+0l_N)+U z#_fVgkoj*DU%#D19B#71Xj-OfPV#g}o=a%n4Zw;mt+H;e*wW5ipHl9j+5j2GZLZ!b# zkhJ?GoN}kL#x0cY2*KK4Rsl>ohP#=2ZD(bGP7&9+={KRp-Lw}E`(n}eJAJj2GZ@LD|91 zz-=&o;wRY~KBW020==kMm0q9$Nu+3>A?;(h?rziY6BTg%sdWh|XA z4XiPpDxh^~^D5uC`IWlR#faw7FE_--c=bCN(K-E%(GQx?1HtT^Q_#RH=E9KTRTcTGD8)_KE`)Os5JwxlWT;UlOyHnYP;*tw_=t->#n7 zarWPh^3W@?YMcbkn8EtagJ1yHR0y<;=Jxfhhv~3l%lg#-r#CjOPbMucHJwn8b6&+22Di^$yTN(-52XKOl(F}`^Z(fdEP)dq@e%w`Ug2P|I;9goYgxYQ> zOf2{FKZE6hc5=1}zz?~*#3@~2`2@r#Qd{9~FCLYFtRK?>rr&S!KSrU%tWpQ++y%;I zSt}=Tsu)y^869bd9A5$|Hq)$v!nj$&6+}WnR>CXgo1WTAZa(Dbw>zj?2Oc}-*~is7 z4ibnd{1=d!Ddg1-%Edmc6};48Z@!DJ@2zh5eHq&XQ7c8_W5)kII)}iYe8#8A&j2Jw zf-sA8KblS;Mgp&`KwUiAwj+i)G-DpgE4?Gv-5u1F!v#Fs#QZ{*Lr#Usj%M_RMAif=1!gl z^NUwl`%P{l^Dh@ki`{*FB10=#zZ6bk|C-0OD@G?1S3Sm&k(Bgb-mq(@hu^k%WB4}B zRpbynI=u4eMu$W;zBAmZgx)FpHY)Z#91R?&R1afN@^NM*(j;>z!?^_LdWR_x5I6Bn zDrtloQPv7Y3*nT4j%9#TSm6n308Yn{e?;P3XG?EXkld91z|+rjOlG-WpJuQK{JLORKYLvd$eRvvicP!TF)ppipMZ7IMTW3MfKrQMi&};fgM6)2T16bOy{8@l zl$i_8@A~Ik!k?rj@vQl%&*sN|Ay;*AigiO>{Kh)5kcrBF!=AZ2?=u}^-kFcJ717)>l&N78wspJNZ3(zYhY|etvmf2*b%biu076%@lw~>$L{Gc zVfnL_>1EN$;h_5HmPSp7-2CS|MQTt$c-N!?p2$e(-R0ivu4iBaT)r2-osD82tT8Gw zhP?Qiv0smsymtr05PUEgM)~%G_iJN-u->BTC8bbk-5hqQ($`}vXmh$5_B3{7y9PVY z8A(vY|B_zF;1=|-;}eKW14?g*IrcCG3X=U4W9knS`Lhu`vQMlXx)N349dVqTyq9@e zr_rLbAWF+%k#ZT#*Jj=E=*W0@eAf5!+BPUpp9`6&^_ja3!h9%q*%rTl4xu-pzY+I1 z=PAe?323E+&^h)zcK@17k+x^UN~GPtV;TK$lh(Y>7xJP^+?gd9ZmB))uGXj^Nv({L z)2cU|Sh4K@Mc*DqY-4Q39P8xP-xzUnM85%H0qMeWw6se-tk?=#I;~HD68{(odAVVP&s z*&6<6c}P2Tw{WO?0W=IH(72A9a;r3byVv)k@G?Ah&cl3QWiZsZ?A_A#h_j?;G4?nQ zpn)L>8rHbZ5z!)@f@ilrj?Hb6Gfo%@C9UnQY84HG`#xEkA{DWk&jF@*Yv<@Bvwl=T zJ+W>IGwSl;Q#J8a59RQq+6&mQ$g!1AiGS|#z?eNBu`P?IR080jhelLub7%^E)&5aN z{a)jQTfse39BAdLjEe#VT|dT*lq?O_1fJbtN@Gi8TGQwz)KB0pFmwz2T^>(I_!S{hO?pD literal 0 HcmV?d00001 diff --git a/index.js b/index.js index 8567388..7398776 100644 --- a/index.js +++ b/index.js @@ -15,11 +15,7 @@ const { sendInitialStats } = require('./stats.js') const fs = require('fs') const ObjectId = require('mongodb').ObjectId // just to check ObjectIDs -const static_files_path = path.join(__dirname, - isDevEnvironment - ? '../volt.link-frontend/build/' - : '../volt.link-frontend/' -) +const static_files_path = path.join(__dirname, './frontend/') function checkOrigin(origin){ return (