From 430a04837f95b12d3a6229049a663045969df45d Mon Sep 17 00:00:00 2001 From: "petre.rosioru" Date: Fri, 7 Mar 2025 18:15:22 +0200 Subject: [PATCH] first commit --- app/.gitattributes | 2 + app/.gitignore | 33 + app/.mvn/wrapper/maven-wrapper.properties | 19 + app/class-names.txt | 1000 +++++++ app/eclipse-formatter.xml | 399 +++ app/mvnw | 259 ++ app/mvnw.cmd | 149 + app/obf-names.txt | 2500 +++++++++++++++++ app/pom.xml | 104 + app/proguard.cfg | 108 + .../java/com/example/app/AppApplication.java | 14 + .../com/example/app/StartupValidator.java | 101 + ...DeterministicHexSequenceWithTimestamp.java | 82 + .../java/com/example/app/utils/KeyUtils.java | 231 ++ .../com/example/app/utils/LicenseUtils.java | 76 + .../example/app/utils/StringObfuscator.java | 31 + app/src/main/resources/application.properties | 11 + app/src/main/resources/license-trust.jks | Bin 0 -> 950 bytes .../com/example/app/AppApplicationTests.java | 13 + license/.gitattributes | 2 + license/.gitignore | 33 + license/.mvn/wrapper/maven-wrapper.properties | 19 + license/mvnw | 259 ++ license/mvnw.cmd | 149 + license/pom.xml | 60 + .../example/license/LicenseApplication.java | 13 + .../com/example/license/rest/LicenseRest.java | 86 + ...DeterministicHexSequenceWithTimestamp.java | 89 + .../com/example/license/utils/KeyUtils.java | 182 ++ .../src/main/resources/application.properties | 8 + license/src/main/resources/server.jks | Bin 0 -> 893 bytes .../license/LicenseApplicationTests.java | 13 + 32 files changed, 6045 insertions(+) create mode 100644 app/.gitattributes create mode 100644 app/.gitignore create mode 100644 app/.mvn/wrapper/maven-wrapper.properties create mode 100644 app/class-names.txt create mode 100644 app/eclipse-formatter.xml create mode 100755 app/mvnw create mode 100644 app/mvnw.cmd create mode 100644 app/obf-names.txt create mode 100644 app/pom.xml create mode 100644 app/proguard.cfg create mode 100644 app/src/main/java/com/example/app/AppApplication.java create mode 100644 app/src/main/java/com/example/app/StartupValidator.java create mode 100644 app/src/main/java/com/example/app/utils/DeterministicHexSequenceWithTimestamp.java create mode 100644 app/src/main/java/com/example/app/utils/KeyUtils.java create mode 100644 app/src/main/java/com/example/app/utils/LicenseUtils.java create mode 100644 app/src/main/java/com/example/app/utils/StringObfuscator.java create mode 100644 app/src/main/resources/application.properties create mode 100644 app/src/main/resources/license-trust.jks create mode 100644 app/src/test/java/com/example/app/AppApplicationTests.java create mode 100644 license/.gitattributes create mode 100644 license/.gitignore create mode 100644 license/.mvn/wrapper/maven-wrapper.properties create mode 100755 license/mvnw create mode 100644 license/mvnw.cmd create mode 100644 license/pom.xml create mode 100644 license/src/main/java/com/example/license/LicenseApplication.java create mode 100644 license/src/main/java/com/example/license/rest/LicenseRest.java create mode 100644 license/src/main/java/com/example/license/utils/DeterministicHexSequenceWithTimestamp.java create mode 100644 license/src/main/java/com/example/license/utils/KeyUtils.java create mode 100644 license/src/main/resources/application.properties create mode 100644 license/src/main/resources/server.jks create mode 100644 license/src/test/java/com/example/license/LicenseApplicationTests.java diff --git a/app/.gitattributes b/app/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/app/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/app/.mvn/wrapper/maven-wrapper.properties b/app/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/app/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/app/class-names.txt b/app/class-names.txt new file mode 100644 index 0000000..ecef760 --- /dev/null +++ b/app/class-names.txt @@ -0,0 +1,1000 @@ +videogames +significantly +grange +complimentary +jeddah +hooker +virology +monorail +tenure +stroll +talon +thinkin +shove +screwdrivers +crucified +caracas +phnom +divers +fitter +warned +endemic +uunet +endogenous +needy +hamburger +buren +crooks +okidata +awakened +firing +pamphlets +undivided +loading +indebted +alumnae +attack +prominent +experimenting +headlines +researcher +disciple +prefecture +transsexuals +electrification +wearer +editing +francaise +moderated +kurosawa +dressed +selfe +panic +irresistible +underwriting +partitioning +disappear +reassessment +reconstructing +emulators +nackt +primarily +graduated +thessaloniki +mcdonough +mccartney +apartment +madsen +unternehmen +obnoxious +entire +slurry +fulfills +cartoonists +explanations +proved +geico +webstatistics +preterm +fugitives +spylog +pliner +month +precautions +barbershop +sleazydream +strategy +toskana +furnishings +damage +someone +bhopal +thunderstorm +eliot +datsun +mosley +catholics +bundesliga +jurisdictional +erred +foosball +versions +cracker +thehun +scents +kiddie +cedars +livingstone +actresses +macross +patriot +mailboxes +southward +replace +inverse +sunnyside +nguyen +ubiquitous +scarica +arranging +deceived +vibrators +publicati +pleasant +getname +sexuality +client +interconnect +encouraged +containment +farina +nikon +belgrade +trademanager +bizwiz +unfavorable +repetitive +abuse +higgs +tobago +crema +earliest +gamepro +report +antenatal +boardhost +juneau +israeli +crass +protons +lymph +esoteric +harvester +drowned +hangar +years +magnifiers +unregistered +investing +discounted +boucheron +artest +dimlist +spencer +narrower +responsive +maturity +goddesses +damascus +changes +statically +unreachable +roald +environnement +symphonies +fixing +skelaxin +attic +trouser +immunities +lockhart +destruction +telefono +outlawed +complained +publishes +pitfalls +montevideo +koeln +orton +wading +tenement +bridget +handspring +uranium +fluff +sheridan +morphism +indepth +extremities +absent +surpass +evaluation +drowning +prehistoric +theorem +impress +adherents +presenter +franchised +clientele +tetanus +emirates +burning +likewise +woody +pathologists +wigan +cyber +gwendolyn +carcasses +december +candlelight +dislikes +cordoba +somehow +filled +wastes +exchangers +bretton +interconnected +hartland +monument +continua +rooter +knuckles +multichannel +romenesko +summarise +tolerate +barker +agnew +buyer +principally +dispatch +dolls +conferences +repurchase +dragged +vocation +centerfold +tajik +trails +gilchrist +granular +accessibility +allusion +personne +girdle +babbitt +pelosi +cryptic +grunt +goldfields +danvers +lovejoy +teenager +gallaries +rover +vague +mohali +gestion +freely +shelter +attrition +barron +drives +latvian +apnea +colossus +colorful +epidural +kindness +boaters +midway +joking +subtitles +blogarama +xoops +gervais +stockholders +longview +jacket +demonic +ezekiel +governments +bosch +swung +graphite +dialog +roaring +adversary +aidable +slump +unpublished +judeo +wanders +favoring +unreliable +indra +discussed +coroner +sconce +painkiller +realistically +chapter +instantiated +breather +molecule +arrivals +endocrinology +faithful +defaulted +probation +despite +handjob +motherwell +gymnastics +kinetic +proverbial +cemented +bangla +ladyboy +precarious +geoscience +escapes +apologizes +inject +kiran +pittsburg +traversed +microtubule +stirlingshire +dalai +softness +eroding +nicolas +jonesboro +informatik +autism +fournier +manta +intensifying +privatisation +deactivate +norwalk +aliso +voila +beene +proposed +subroutine +quinn +tires +elijah +theorists +stefani +fours +childcare +lenses +lalique +brutal +mcfarland +iwork +gower +differed +stillman +modulo +optical +reinhardt +alexey +multimode +tasted +plenary +norsk +lofts +delaware +imported +centrist +kahuna +serum +flying +seqres +hertford +joanna +seminars +krusell +leith +starfleet +cotswolds +deepwater +apical +pacer +sarkar +duration +water +muslims +plead +capitalize +workman +dataport +intermediary +surprising +november +configures +correctional +projets +parade +proverbs +homeschooling +convenor +disaster +american +looted +misrepresentation +latch +ginsberg +jerome +charitable +crowding +booming +intersection +romance +disciplined +knudsen +kilograms +guestrooms +theodor +similarities +dewpoint +coasters +seaside +jennings +contentious +revolutionize +donkeys +lisinopril +romper +felix +mirroring +successes +laughing +extender +equip +superscript +suzanne +extracted +dunkirk +mcnally +drill +weblist +gestalt +seldom +decorating +serial +vital +gadsden +sorter +articles +blower +hentai +shrek +underlies +stewardship +moped +fascism +krugman +absinthe +epiphone +hardened +andersson +fighters +defied +qlogic +candy +earthquake +purify +alignments +bosses +kabbalah +shocked +geile +keepsakes +souvenirs +provinces +morissette +roxanne +bragging +zipcode +checkboxes +salzburg +battled +unread +miraculous +isomers +ketchikan +muscat +deseret +farnborough +ripped +camden +spartan +brake +hippocampal +strasse +refinance +physics +coleridge +acdbentity +killing +blasphemy +sissy +quick +cranston +quaker +cancelling +unincorporated +recollection +leaves +harmonized +nigeria +campagnolo +nucleic +rockies +prevailing +cogent +nervosa +liberate +coexist +critiquer +stabilisation +netmask +plight +unfolding +mixers +illiteracy +reputable +generations +kosovo +replicator +stateroom +corsair +chameleon +clogs +jessie +intervention +untimely +fontana +luster +railroads +dagenham +hernando +philippine +shred +inbound +sidebar +chesterton +diaries +situations +peacekeeping +completeness +begun +fibrosis +menswear +baldwin +ashamed +suspicion +ridgeway +inquiry +suggestions +quench +lowest +swans +lewisham +vitesse +poison +anathema +prerogative +philosophers +endothelial +restraining +bearers +mayer +foolishly +ported +portlet +vanished +featurette +breville +steadfast +wanderlust +hiroshi +napoleonic +polyphonics +plage +stretchy +radiating +levine +attitude +rejection +oakley +salient +gloucester +willi +pyobject +complete +microwarehouse +expressed +mining +leiter +pretended +taxation +franchise +reunite +handle +nonattainment +piedmont +significance +tripping +duets +rainey +maddy +angling +claire +recognizes +kingsley +outlay +cerruti +amici +astonished +reimburse +hampden +classics +todos +nforce +anaesthetic +tshirt +frost +homie +servlet +chronicles +reagan +movements +reject +applied +ainsworth +profound +misplaced +slaves +coconuts +gaithersburg +pelle +bullish +counters +defendants +accents +westfield +imputation +surat +hadith +hallowed +stdin +vinton +motifs +regimens +granted +prototypes +worded +orville +decimal +relies +uncommon +exponent +widened +expression +adjournment +picnic +qualified +shaman +angled +contributes +taker +memos +phyto +anion +walkin +plaintiff +conclusive +according +penticton +attention +chill +trader +perennial +armstrong +suppressed +retribution +orthotics +habitat +hiroyuki +autoblog +contributed +maturing +teleconferencing +cloning +sawyer +convoluted +inundated +curbside +aroma +beyonce +accra +lipoic +recurrent +jeweled +further +profit +respective +postmark +manhunt +landscapes +impossibility +shrewsbury +digress +centrelink +shiva +protect +calcutta +shimizu +classify +clement +coolermaster +languages +cookie +interfering +juniper +gabbana +carousel +disapprove +dieses +lewes +spartanburg +codec +valerian +playstation +postponement +geronimo +stance +gilmour +heathen +reddish +williams +agrarian +zimmermann +armoire +reunion +uppers +partisans +powerhouse +ovary +mendelssohn +moments +return +vazquez +madrid +bungie +logistical +handwritten +cavan +combating +terrorist +torpedo +antisocial +skirmish +cantilever +assaults +universiteit +accretion +russian +emancipation +pecans +calais +optimal +archiver +maximized +bahamian +ultrastructure +helios +invocation +tabby +contains +splices +mechanically +comoros +screwing +biodiesel +prequel +healed +kaffe +exploit +modulated +shoebuy +protocol +withdrawing +matrimonial +rollo +telephones +tourmaline +headlamp +lagged +menstruation +raquel +weaning +governmental +tiers +kategorie +pimpin +reasoning +senha +clarita +langdon +pianos +providing +convalescent +keeling +courseware +platoon +hannity +brainer +straightforward +command +feeling +umatilla +piazza +injector +brokerage +rhinoceros +galilee +cajun +tiscover +silly +woodwork +external +eucalyptus +motif +psychiatry +quantization +cunha +cockroaches +uterine +cdrom +broom +underscore +faust +putnam +groupwise +madagascar +played +huron +rolla +overture +vampires +backhoe +fires +lamented +subsections +lifted +meditations +logged +hereunder +allergen +winzip +borland +hippo +abuser +reseal +photocopies +caramel +granite +viewer +perthshire +gryphon +onstage +hears +change +spock +pacific +unheard +minox +microscopic +calvin +determinant +scares +nears +bypass +break +photovoltaic +mathml +depended +affects +naturally +letzte +shangri +authorised +allegra +villages +cohomology +mammary +locksmiths +rasmus +prospect +categorised +copland +distressing +bluff +busts +reforming +accurately +quickstart +frontman +lasso +commas +separator +funerals +woodard +institutes +deferral +rediscovered +sympathy +biomed +peyton +downgraded +sooner +quadruple +webactive +walkers +superconductors +reuters +kubrick +promos +nitride +tattered +aquinas +kirkland +communist +bitmaps +carsten +nannies +transcendental +winnings +celtic +bausch +undef +imprint +entered +refinancing +style +halts +magda +atlassian +fibrillation +cordless +specialization +beltway +calloway +heathrow +overdrive +garrison +retreats +snowshoes +superstars +purified +litchfield +tempus +meshes +bluetooth +cretaceous +suchen +devon +media +breyer +werden +nissan +barren +patriotism +contre +hoodwinked +mnemonic +wallingford +critique +vista +marin \ No newline at end of file diff --git a/app/eclipse-formatter.xml b/app/eclipse-formatter.xml new file mode 100644 index 0000000..636e595 --- /dev/null +++ b/app/eclipse-formatter.xml @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/mvnw b/app/mvnw new file mode 100755 index 0000000..19529dd --- /dev/null +++ b/app/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/app/mvnw.cmd b/app/mvnw.cmd new file mode 100644 index 0000000..249bdf3 --- /dev/null +++ b/app/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/app/obf-names.txt b/app/obf-names.txt new file mode 100644 index 0000000..34b5d81 --- /dev/null +++ b/app/obf-names.txt @@ -0,0 +1,2500 @@ +allstar +flicker +nucleotides +mumford +disambiguation +smoother +edwards +elliptical +danes +firma +unclean +tsunami +racecourse +exhilarating +openssl +vocabulary +football +defensive +upgrade +wheatley +ergonomic +thrilling +alison +notably +cinch +native +republics +waterproof +zoomed +sunfire +mocked +hempstead +traced +numbered +operatic +marquis +riddles +pavilions +heroism +rangemaster +assigned +baring +centerline +burundi +meridia +membre +horrid +cozumel +boots +objectionable +remotes +ascap +hannah +smiling +kristi +xforms +steel +lovingly +galen +speaks +granule +byron +ascension +whosoever +rentals +contraband +blunders +preach +sandler +sheep +aggregation +kinshasa +adopts +enacting +pleasure +clutches +rounder +sevenfold +visit +descending +canal +pulsar +toowoomba +notts +comparability +cyclical +primedia +rohan +fleshy +brandt +cylinder +execs +timing +germination +darlin +metlife +legislative +blick +atrocities +undocumented +germplasm +sympathy +parcel +sanford +catalunya +glides +recklessly +yonder +ancient +chanson +quarterly +elsevier +pipers +invitations +usepa +histoire +licensor +assists +macosx +jupitermedia +troll +gunners +kerberos +zambezi +officials +angebote +orbis +complaining +umbria +midori +gromit +astrology +plank +devonport +yorkers +homotopy +griggs +movado +respond +confronted +island +castilla +tightness +merritt +heinemann +inequality +mommy +pronto +contemporaries +recipes +grantham +plugin +beaker +uninstalling +timeouts +anesthesiology +receivable +uncorrected +honoured +unprocessed +crafty +cheaply +newscast +snitz +reliever +kensington +fabrics +decorate +justification +wineries +cruiser +collab +voices +organisational +fooled +rabbis +fanclub +archaic +gravy +earls +interactives +dauphin +realnetworks +casket +spank +rainforests +proposing +fitch +loadavg +matting +franchisees +proliant +enforceable +mosaics +mateo +listening +recruits +informer +recount +epitaph +serine +crepe +erickson +halter +tresor +rootsweb +immigration +sugars +whichever +covers +rapport +dancewear +paradoxical +reconcile +shepherds +maarten +triple +darth +calmly +vertically +narrow +councillor +recommend +marcy +derivation +pyjamas +addicted +roxbury +exponentially +secrets +grosse +accomplishing +padilla +frankfort +suitcase +dreary +hopper +cloths +burden +careers +obtains +expanded +raffles +protesting +pinter +momma +verbs +pathologic +champs +sprawling +jordi +msnshopping +multiprocessor +bookmakers +incesto +stiles +mavis +forensics +anonymity +rests +mobipocket +embryo +presidio +focusing +lymphoid +neocon +idealism +feedbacks +stored +speaking +smelled +hazardous +erection +difficult +oldman +bonaventure +greenwald +support +santorum +eroded +insta +exotic +sisyphus +hasten +sensational +ludwig +organ +according +watersports +sermons +plaza +misha +realization +unprepared +stance +adjourned +tualatin +corrigan +cultivar +calendars +among +telekom +ramen +rhiannon +michigan +compromise +garber +terribly +disgraceful +viacom +factoring +tourisme +imbalances +maine +annes +emptying +allstars +denial +lunatic +amassed +metastases +quercus +wholly +equip +utterance +murals +ragged +wrestle +feingold +foggy +railroad +walkthrough +embarrassment +leading +transcends +porno +feedback +norco +iberia +assessed +casters +formality +parkside +payer +spent +scotia +mutilation +legislation +hepatitis +structure +namespaces +essays +wilbur +sbjct +reliable +organizational +endearing +prius +aquatic +outlet +discontinue +crouch +richland +ominous +impeach +python +directors +respondent +recreated +carnage +shading +workstation +mcmanus +consultative +exposure +indecent +unfettered +slant +torres +unwise +forme +endorsed +permission +yushchenko +freeing +outside +tenor +gabba +adress +burnett +collectable +representing +proves +carrot +residential +destroy +confuses +private +oemig +friction +cheri +stumps +midwestern +dyeing +filipinos +boulders +ginny +biologists +regimen +mentally +greenery +computerized +comedian +titre +laurel +converging +enthusiastically +discontinued +interpretative +quattro +replies +marty +uship +woken +loser +remodeling +ballast +estuaries +inadmissible +expedient +mistreatment +faerie +anecdotes +chicco +hamburger +ahmed +geometrical +muskogee +publis +impact +razor +categorically +contaminant +hypertext +nordsee +caterpillars +townsend +candice +typhimurium +weblog +compete +adjectives +access +hypocrite +otolaryngology +wayne +globes +rogues +janet +succinctly +narrated +hypertrophy +territorial +hunters +coronal +harmful +disparate +lantern +aureus +ambush +biomechanics +implementation +panda +einer +chilliwack +witten +distinctions +exorcism +nucleic +curricular +infection +drifts +viewpoints +involved +basildon +laconia +metastatic +numeral +filet +trevor +redcar +highest +recommending +mubarak +remortgage +subsidiaries +sounding +stacker +skool +ischemia +plots +driveway +ordinators +beach +subcommittee +inputting +shania +gunther +accent +slovak +achievements +whatsoever +dietz +crashing +expansions +checksums +albania +beaten +harbors +gemstones +playgrounds +preps +condi +volts +babble +companions +selenium +dipped +opponents +nudists +wears +brawl +elizabeth +barrister +mcgovern +remoting +lockhart +multiples +eternally +darmowe +defaulted +mccain +gloucestershire +nathan +ballpoint +eyelash +jbuilder +coworker +matter +connector +bristow +warden +ophelia +physiotherapy +divergent +schnauzer +poolside +murine +geared +dominated +motorized +dopamine +prosper +precautions +xviewg +ljubljana +hammond +flanagan +yesterday +footballs +welfare +wellness +patriarchal +janelle +cashing +foxboro +scrubs +tucked +condiments +caspian +switchable +mangrove +meghan +cents +palsy +complexes +varying +blackhawk +deliverance +atapi +stakes +poorly +invite +slums +receptors +acquisitions +maybach +apportionment +hutchinson +warning +healed +northerner +heels +established +molecules +hollander +machiavelli +hydrodynamic +givenchy +suffrage +nicaraguan +piety +immunological +learners +allahabad +maricopa +mallory +midget +saffron +tabloid +projectile +brash +depart +consumables +ruled +awkwardly +nickelodeon +complex +illustrated +howler +marge +keyspan +assyrian +nylons +widctlpar +learning +salve +kayla +sheik +streamlines +kiribati +considerate +lyons +pharmaceutical +ankle +twikivariables +emusic +chimpanzees +crusade +whatever +krabi +polygraph +bristle +surfacing +bruner +mammography +tablespoon +edmond +bowles +loosen +turbines +perfect +selects +vertebral +deceased +sault +customs +arcana +signoff +guardian +ashley +zapata +viability +dispatched +tainted +backbone +vermont +formative +greenfield +wilds +sibelius +skillet +explosive +chong +pembrokeshire +persians +locator +flemington +stallions +biosynthesis +embellished +travelmate +paltz +recording +tunnels +kissing +equipped +protections +handley +kicked +yeager +biologics +tribulation +ejection +download +hydroelectric +oddly +federal +cabaret +struggling +bedford +broadening +chewy +lanai +corsica +curvy +american +vernon +clooney +immaculate +moraine +format +megadeth +loathing +nameserver +minerva +chatrooms +waking +blowjobs +asheville +lanarkshire +alyson +options +fargo +hurdles +absences +instinctive +junebug +malignancies +bonaire +announcer +relais +burma +attributable +mister +reelection +acces +nitrogen +barcelo +irish +rationale +wheelers +martin +remembered +defying +pluggable +chunk +exams +passwd +woodbury +ribosomal +brantley +fraud +solidworks +deletions +squirrelmail +cranfield +acquaintances +afghani +visors +biologic +lofty +kerri +longing +elisabeth +rodrigues +edits +relaxes +resigned +hides +tapety +midnight +biocompare +toute +coupler +johnny +irwin +observes +begotten +accuracy +blown +washable +hurricanes +comparing +fogdog +knack +bytecode +billet +kiowa +endpoint +twikiaccesscontrol +konami +hearn +sideshow +noticeably +nursery +depending +cutting +world +bountiful +dietary +promissory +picasso +deliberate +raceway +melbourne +upbeat +teletext +wonwinglo +flickering +plantronics +girardeau +sakura +chopard +calvary +tradeoffs +keenly +splits +haifa +favorites +installations +scriptures +flagler +progra +civilization +periwinkle +profound +jeter +jumpstart +prioritize +belated +iteration +unmanned +graphite +abate +barnyard +parted +relinquish +urging +scrolls +gizmo +colder +overseas +leagues +mahjong +atkinson +gunman +brush +purse +savoir +graffiti +insistence +eventual +antineoplastic +catheters +lehmann +contactos +cyborg +alizee +oneworld +nixon +claims +radii +earmarked +genevieve +mentoring +titan +tweak +damien +tonga +suzie +secretive +haulage +thumb +echoing +convent +cougars +mirago +mingw +grouped +tenement +prentice +dilemmas +throughout +mania +amerisuites +tshirt +intestine +schiavo +hyperlinked +alloc +nikki +model +heraklion +conway +mckinley +piosenek +columbine +catwoman +microsano +grime +splitting +professionalism +canlii +sugar +depths +cursed +cuttings +lynda +femdom +hotfix +abrams +spectacle +gardening +thinks +annuncio +espace +hemoglobin +buscar +baguette +signer +vaults +zebra +latent +likes +wreck +maximus +electric +tittens +vagabond +cards +unpacking +decomposed +upton +creeping +johanna +systemax +raiders +workgroups +congrats +bosch +interferometer +exploded +speed +formulas +palmone +diffraction +embroidered +westchester +smalley +monotonous +resets +kitsch +dansguardian +ichiro +retreated +vandals +correspondence +chloe +simulated +mcelroy +bondi +saxton +seaton +terrell +energies +starts +autocorrelation +gangbang +paired +brooke +rheims +singleton +annotate +meditating +structuring +finishes +inertial +clarks +cooker +oldmedline +seller +fedex +glyph +ventral +ferguson +refresh +plated +manned +mandeville +geary +caveman +phantom +consonants +gibraltar +evident +formulary +backpacker +financier +jackass +knapp +wound +alchemy +screamed +glacier +dragostea +reforming +boces +complementing +sandro +bumble +cocoon +pharmacological +charging +cafepress +advanced +seychelles +pippin +ocala +yummy +slips +chargers +constabulary +avent +opensolaris +furnished +compusa +cushioning +steffen +vintage +remotely +tokens +annotated +disposal +chine +oxides +intestinal +empowered +hotly +battalion +conversions +ample +grossman +restriction +rochelle +kinases +conducive +follando +flannel +poland +paulus +dogwood +berserk +staunch +quinta +sedgwick +although +preventable +syrian +mounted +sigma +boyfriends +comprar +succeed +reconnaissance +immunities +wholeness +preached +varies +hagen +unequal +reproduction +retrieves +bledsoe +minimize +fringes +catered +clustered +called +creamer +corpo +condition +honestly +advisories +duxbury +bilder +ratify +accurately +donuts +infrared +fruitless +desolation +soundtracks +telecoms +forever +fredericksburg +gericom +interpolation +lapis +persecution +arnaud +riverwalk +drenched +httpwww +downer +indented +individualism +transcription +study +compound +dietetic +prolactin +buckle +momentary +counted +noonan +expand +effect +weighting +inspections +formidable +referrers +summit +amsterdam +proclaimed +banbury +holes +spilling +becomes +trellis +insurance +taxation +sleek +rafael +minis +dosages +autoblog +pillars +incoherent +rogue +nicks +gulls +prado +grades +philadelphia +unctad +attraction +jewellery +hahaha +uproar +heads +medicare +autoresponder +alkaloids +squad +smelling +underwire +mischa +svensk +synopses +pounder +misplaced +descendant +revitalizing +etoile +threaded +inaccessible +adventurous +zipper +firearm +chamomile +monoxide +pariah +trample +husbands +sprayer +crimp +violating +firth +depress +maintained +reassignment +ricochet +biases +italic +ambitions +waved +adsense +proposals +hinds +temples +ignite +waller +bacteria +juicers +penrose +queued +finchley +kaiser +treasury +paducah +sagebrush +prodotti +galvin +fails +trunks +energized +edited +iframe +dancer +olympiad +lynyrd +correspondents +miniatures +disappeared +appreciation +exchanges +trooper +admittedly +cleary +phyllis +thorough +delightful +contracting +orchids +poplar +alcoholics +spitting +ciencias +aggression +unpatched +violation +colloquium +dissonance +madden +lemma +harder +accreditations +tasked +timely +spinner +pushes +antarctic +assertive +adopt +botswana +generosity +harassed +breathtaking +recieve +orthopaedics +adderall +unworthy +scroll +amsoil +kharagpur +assam +biscuit +concurrency +bushel +weill +dominatrix +annette +preside +haunt +cocaine +revere +compressive +admins +cancelled +havana +salty +lightwave +mystery +nphase +brentford +cordoba +freaky +bulldog +domino +niven +dodgers +acknowledges +schafer +walling +pursuit +dreamers +chemin +seating +pinoy +multifaceted +fagan +actuary +bulge +walpole +manuale +analytical +counterfeiting +macintosh +expats +freenet +announce +rencontre +ventures +exchanged +wakeboarding +subdir +insatiable +catching +lasso +dimming +therese +fleischer +texmacs +canoga +popup +techs +hilltop +suffice +tenkaichi +coyle +nakamura +backlit +verve +arouse +greatness +earlier +sailboats +salvatore +betty +jitter +danni +vikings +entert +dinner +andersen +bundesliga +blessed +honeycomb +incisive +bridgestone +shipley +doubly +derechos +trivandrum +shuttles +thermostats +contracts +relieved +encoded +hobbes +harlequin +tetris +precast +counterfeit +editor +bratz +connects +coldest +fiona +zambia +legalize +valentine +lathes +fairhaven +bowflex +dominique +unpublished +northwood +biographical +beecher +actors +metros +woody +rotors +rollins +ensign +halen +minerals +teaspoons +averted +reginald +dated +skull +compatability +limoges +tentatively +williamsburg +duquesne +trouble +easterly +distressing +catchers +houghton +newbie +sumner +powerful +fully +wonderwall +overrides +bugfixes +bedlam +straining +tooltip +necks +powerpuff +unveils +converters +magdalene +freud +tamil +extremetech +argentinian +redskins +seeking +tapestry +perturbations +adjustment +surged +clumps +allan +concave +dispatcher +teaspoon +arranges +linea +mapped +cordial +pappas +cesarean +marek +molokai +hampers +sherbrooke +dries +marcus +showtimes +solely +radiologic +manipulating +insults +confounded +dressed +democratization +versione +farber +breeder +breaching +visalia +gooseneck +alleviating +dispersal +battled +attest +couriers +orbison +locust +disappointed +vengeance +manicure +embarrassed +wobble +subgroup +protocol +battery +equiv +guggenheim +apocalypse +cynthia +gloryhole +sayings +lonesome +outlandish +thesis +supervises +sights +accommodations +hydrate +unforgiven +distinctive +followings +bushing +loftus +hatchback +cardiol +adolph +unleaded +deletes +vasquez +enumerate +suggest +miscategorized +tracey +secured +conscious +pretreatment +metropolis +plaque +liberty +homology +mutations +plugged +compute +polling +iceland +improv +fruit +bretagne +inpatient +protective +rhone +empowers +archiver +comparatively +subcategories +millwork +straps +edict +behaviour +rwandan +https +enters +sangre +techwr +excuses +terry +belly +endpoints +dulcimer +smoke +postal +topical +hellman +bengals +pullout +papaya +abysmal +wants +intercepts +kanawha +environmentalists +stuttgart +wideband +photopost +cadets +consideration +comprise +janesville +veranda +pneumoniae +horribly +evidentiary +myoplex +schmidt +turbidity +burners +morale +enforcer +bleaching +arthritis +waterloo +scents +overlap +trapped +customize +blissful +poultry +buysafe +trudeau +meningitis +plaid +inefficiencies +roommates +snorkel +bumped +vdata +mcleod +today +chrome +confocal +lasagna +shocker +mccabe +celebration +ramallah +report +precedent +woman +dream +classics +keystrokes +monroeville +perfor +cloned +inest +intelligently +marengo +crusoe +bugtraq +impede +vitara +bellacor +kochi +alamitos +america +sectional +frustrations +organising +united +youngblood +dooley +inflatable +darkside +guild +cookbooks +payout +dreaded +shannon +embolism +homegrown +stinking +duchy +piping +mosul +honed +multipass +gastonia +marinated +supply +mechanistic +cautionary +incredible +arbitrary +accordance +spacetime +concat +veneers +femur +cyngor +inactivated +barney +disrupts +secularism +poorer +jarrow +merchandising +figaro +dolce +retrospective +bridal +clanlib +movies +regiment +argento +trados +screenname +liabilities +sunbelt +organiser +marshall +avaya +winsor +mcdonalds +kennedy +schubert +felony +recoup +stole +trembling +bangalore +immunisation +hitler +anime +countermeasures +purge +harcore +burning +vicky +birthing +wands +genbank +atomki +billy +debconf +interconnects +fundraising +consignment +towering +welsh +strengthens +gwent +harrisonburg +colony +lycos +arrival +temperatura +quicksearch +baghdad +berlusconi +leaved +biotechnology +brokering +kettler +susan +sprinkling +metamorphosis +suffolk +complained +telus +towing +breastfeeding +chula +political +paths +repeatedly +discounts +managed +expensive +commemorate +galaxie +licensees +garfield +craven +burdick +anthropological +daddies +kaufmann +excited +sadness +stagnation +trailed +bangkok +arial +garrett +childish +withdrew +rectal +annuals +mandel +phenterminecheap +mellitus +sealy +backup +devolution +slows +timeshare +emule +drinker +unplug +nieuws +drafted +clashes +newswire +invision +midlife +carolyn +fanciful +scrapbook +chasers +cosmetic +exploding +joystiq +bowel +meteo +lagrange +backer +fiche +freshly +polycom +captioned +profil +telemetry +dividend +astrophysics +testing +iupui +tanker +bandwidth +pneumococcal +inexpensively +avion +cordova +turner +aimee +academie +undermine +districts +oceana +itself +prudential +webform +reclaim +handlebars +regiments +subsection +moser +peeps +swallows +wingate +adbrite +tenders +sandal +objet +inductance +masturbate +select +batting +trike +turkeys +racetrack +extenders +wisely +oilers +polycarbonate +novak +flied +stover +makoto +rafters +arsenic +steamed +regimental +blessing +seams +demonstrator +harmonic +promoted +adept +whence +rebels +citrix +bastille +cloak +sandwich +quantitative +lamentations +joaquin +colorectal +gatherings +underwater +pinocchio +everybody +lodged +boson +everyday +restraining +mainboard +nairn +dildoes +cyber +sulfur +cartoons +pizzeria +harvests +sharapova +toner +schematic +birkenhead +expedia +decreased +realist +publishes +clones +liszt +unmet +reiterate +skirmish +goethe +stills +jimmy +queues +denver +fourteenth +authoritarian +intercontinental +dobson +matchup +wilcox +differently +mexican +symlinks +stripping +koontz +deafness +intruder +inning +cookers +clumsy +paramedic +cellulose +brava +vulcan +accomplishes +biochim +celular +raider +gauges +autonomic +mesquite +consolidating +lompoc +maclaren +peter +marbella +patently +mentioning +softgels +blanks +pastry +larson +zombie +provides +photographing +yeast +mildura +extensibility +jurisdictional +concert +multiplexer +transcripts +refillable +shane +acetate +continuously +precip +foray +induction +corridor +abscess +parke +clyde +monitored +screensaver +shakespeare +autre +guestrooms +redeemable +banished +interpreted +vente +slugs +tiers +bernice +hydroxy +cornucopia +westlaw +tuesdays +weathering +substitution +mamma +khaki +graphic +jesus +focal +unmarried +incompetence +brussel +logging +dispersion +anyways +marseille +teleconferencing +ethics +samson +sakaiproject +polymeric +disturbing +dinghy +unfounded +unanimous +doberman +damon +acdsee +kicker +tricare +whooping +transitioning +linwood +straw +engle +jennie +campaigners +specifier +bharat +ledger +nicklaus +homocysteine +southgate +bernard +telecommuting +coenzyme +danbury +rages +receiving +radiative +biohazard +summons +carving +disappearance +snowshoe +fulfillment +leopold +booktitle +unravel +militarism +universally +scandal +findlay +werbung +tithe +cricketer +feeders +linguists +bereaved +itinerant +humbly +trimmed +countertops +oblivious +snooper +customizable +forgotten +staffs +sible +helga +galleria +infact +associating +affinity +angela +macromedia +neohapsis +stones +excelled +anodized +branched +ceramic +austrian +ansel +undetectable +vertebrates +northfield +rooney +watertight +interview +laity +disjoint +unbound +advocated +betsy +convince +juelz +baptists +wolfpack +metropole +surgically +mariners +teammates +happen +rhinestone +geraldton +exhausting +hemodialysis +valid +drivetrain +gallatin +import +wrongly +pitchfork +pasture +question +canucks +suomi +definition +wagons +photographs +allston +fleck +consequently +immensely +partial +leatherman +quintet +someplace +eastenders +travels +hoskins +phytoplankton +welcome +pedersen +dotnet +knockers +snacks +melodic +mater +extends +tronic +keypads +ladysmith +coppola +britannica +webhome +oddity +eater +orthopedics +staind +repose +wander +specialization +removing +specializations +pours +busts +birthstone +privatisation +consecutively +brooch +dvorak +gwyneth +overtaken +tracer +sinister +filtered +grounds +balloon +precarious +reise +warlord +tarmac +mario +mauve +oxidoreductase +bravo +animated +portage +treatments +styles +barbershop +painless +oxidase +schwartz +becoming +longoria +algae +lucent +artisans +hybrid +timberlake +boiler +purity +agatha +rangefinder +vbulletin +cutout +springdale +vocals +orderly +ephedra +settler +improperly +thrusts +permissive +cinematography +hoodia +roadstar +memos +broke +disulfide +sever +tuition +passionately +ramps +faeroe +oblivion +dairy +transom +buffering +procurement +devotionals +airmen +aborigines +unattractive +masterbating +proteus +ebcdic +hogtied +defense +hooking +yankovic +crease +resumed +publish +starlight +dorian +belkin +retinopathy +breathes +popper +costco +issue +galeon +desperation +pedagogy +objection +winders +republished +incite +lifecycle +aramaic +unrivalled +palmos +kailua +immediacy +analgesic +jacqui +sensibilities +spreadsheets +painting +mccullagh +reputation +hyper +separated +preliminaries +lettuce +royce +deferred +confines +inaugurated +applet +tailoring +sixty +sporadic +gatti +deity +salud +gabriel +viaduct +contextual +vauxhall +bachelors +buyers +mechanized +centralized +jammed +citibank +neighbor +whisper +platelets +disposable +zakynthos +knotted +tones +employment +lovin +underoath +fascinated +ignorance +minors +huntsville +twisting +galloway +dismantling +fleur +suonerie +unbearable +machines +sweden +usgenweb +summits +wares +rosenberg +lesen +songwriter +controls +entropy +redesigned +vaccinated +copley +grated +oxygen +brain +invited +centerpieces +brandi +whyte +melamine +precept +lifespan +tackling +counselor +pixmania +choreography +yogurt +climbers +infirmary +punctuation +makeshift +handler +goodies +coffs +orgasm +sikhs +segfault +aisles +starving +homosexuality +seaman +captain +involuntarily +tirana +striving +amazing +deployed +container +corsets +repairs +hospital +dressage +hurled +welcoming +parasol +waterfront +inequalities +macos +oceanview +bongo +norfolk +racial +bushels +constantine +senators +clarified +antimicrobial +outline +stopper +durham +something +farsi +arnett +cuffs +salon +shuffling +praise +semen +learned +rulemaking +grabbing +revolver +truncated +caseiro +avenida +remanded +cajon +magnus +umbrellas +packs +pronunciation +camaro +phosphorus +oxford +brodie +citation +bolted +cobra +quake +benzodiazepines +levee +tantric +absolutly +bakers +stopwatch +recreating +phoning +reunion +protestants +aslan +talks +elsif +aware +antagonism +borealis +sponsor +embracing +abingdon +upskirt +similarity +nijmegen +electra +promulgate +cirrus +minded +ranked +crotch +hesperia +haggai +patching +sched +mainpage +shiite +halston +motorsports +battleground +reincarnation +spices +legend +niche +relocatable +prevailing +userpics +widths +poised +volokh +carved +demanded +lyndhurst +srivastava +payday +steamy +slovakia +target +mifflin +trench +smashing +surcharges +versed +nouveau +thinner +stumble +seldom +raiser +patient +sherpa +dancing +chatting +ceramics +carousel +villeneuve +helps +rubella +commemoration +folic +marseilles +darla +acrylics +paperless +schell +risen +mistake +polices +cusack +redhill +seasonal +sneeze +scofield +galilee +hatchery +sears +intersecting +cyclone +ninja +gustafson +celeste +carbondale +lucasarts +verifiable +kazakhstan +springville +margin +disposals +topsites +caustic +gymnastics +tifton +retransmission +defaults +substandard +researchers +sensibly +samir +anonymous +beforehand +llamas +faust +inconsistency +impartiality +terror +constr +inferred +recoil +dizzy \ No newline at end of file diff --git a/app/pom.xml b/app/pom.xml new file mode 100644 index 0000000..804b425 --- /dev/null +++ b/app/pom.xml @@ -0,0 +1,104 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.3 + + + com.example + app + 0.0.1-SNAPSHOT + app + Demo project for Spring Boot + + + + + + + + + + + + + + + 17 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + ${project.name} + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + proguard + + + + com.github.wvengen + proguard-maven-plugin + 2.6.1 + + + package + + proguard + + + + + ${project.build.finalName}.jar + ${project.build.finalName}.jar + true + ${project.basedir}/proguard.cfg + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + com.example.app.AppApplication + + + + + + + + + + diff --git a/app/proguard.cfg b/app/proguard.cfg new file mode 100644 index 0000000..9c3defb --- /dev/null +++ b/app/proguard.cfg @@ -0,0 +1,108 @@ +# Avoid shrinking and optimization to ensure the app works as expected +-dontshrink +-dontoptimize + +# Enable unique class member names and adapt class strings +-useuniqueclassmembernames +-adaptclassstrings + +# Suppress warnings (for reduced clutter) +-dontnote +-ignorewarnings +-dontwarn + +# Enable control flow obfuscation to scramble the logic and confuse decompilers +-optimizations !code/simplification/arithmetic,!method/inline,!class/merging + +# Add dead code to confuse decompilers and make reverse engineering harder +-assumenosideeffects class ** { public void set*(***); } + +# Repackage obfuscated classes into a specific package +-repackageclasses org.test.guarded # Move obfuscated classes to this package + +# Use a dictionary for class, method, and field renaming to randomize names +-classobfuscationdictionary class-names.txt # Class names using proguard.txt dictionary +-obfuscationdictionary obf-names.txt # Method/field names using proguard.txt dictionary + +# Keep necessary Spring classes for reflection and DI to avoid breaking functionality +-keep class * extends org.springframework.boot.web.support.SpringBootServletInitializer { *; } +-keep class * extends org.springframework.boot.loader.** { *; } + +# Keep main method for the application entry point +-keepclasseswithmembers public class * { public static void main(java.lang.String[]); } + +# Keep only the necessary Spring annotations for DI and related functionality +-keepclassmembers class * { + @org.springframework.beans.factory.annotation.Autowired *; + @org.springframework.beans.factory.annotation.Qualifier *; + @org.springframework.beans.factory.annotation.Value *; + @org.springframework.beans.factory.annotation.Required *; + @org.springframework.context.annotation.Bean *; + @org.springframework.context.annotation.Primary *; + @org.springframework.boot.context.properties.ConfigurationProperties *; + @org.springframework.boot.context.properties.EnableConfigurationProperties *; +} + +# Spring-specific classes for caching and configuration +-keep @org.springframework.cache.annotation.EnableCaching class * +-keep @org.springframework.context.annotation.Configuration class * +-keep @org.springframework.boot.context.properties.ConfigurationProperties class * +-keep @org.springframework.boot.autoconfigure.SpringBootApplication class * +-keep @org.springframework.stereotype.Repository class * + +# Allow method and field name obfuscation +-allowaccessmodification + +# Keep specific attributes for debugging (e.g., Exceptions, Signature, etc.) +-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod,RuntimeVisibleAnnotations + +# Keep specific directories used by Spring Boot (e.g., auto-configuration) +-keepdirectories org.springframework.boot.autoconfigure + +# Keep specific methods for class loading (used by Spring) +-keepclassmembernames class * { + java.lang.Class class$(java.lang.String); + java.lang.Class class$(java.lang.String, boolean); +} + +# Keep Serializable classes from obfuscation +-keep class * implements java.io.Serializable + +# Keep enum members +-keepclassmembers enum * { *; } + +# Keep critical response classes and DTOs +-keep class org.test.api.response.CustomResponse { *; } +-keep class org.test.model.** { *; } #DTO +-keep class org.test.repository.** { *; } #Spring Data +-keep class org.test.entity.** { *; } #Database entities + +# Keep specific classes and members for your app based on reflection and DI needs +-keeppackagenames org.test.api.controllers +-keepnames class org.test.api.controllers + +# Keep specific classes and members for security configurations +-keepclassmembernames class org.test.api.auth.** { *; } # Spring Security +-keepclassmembernames class org.test.api.configs.WebFluxSecurityConfig { *; } # Spring Security +-keepclassmembernames @interface * { *; } +-keepclassmembernames class org.test.api.repository.** { *; } +-keepclassmembernames class org.test.api.entity.** { *; } +-keepclassmembernames class org.test.api.model.** { *; } + +# Enable more aggressive optimizations where applicable +-optimizations !method/inlining + +# Keep all fields in org.test.guarded if they're serialized (for persistence) +-keepclassmembers class org.test.guarded.** { *; } + +# Minimize side effects and avoid unnecessary warnings +-dontskipnonpubliclibraryclasses +-dontusemixedcaseclassnames + +# Additional configurations to make code harder to understand after obfuscation +-dontwarn com.example.app.** +-optimizationpasses 5 +-optimizations !code/simplification/arithmetic,!method/inlining,!class/merging +-overloadaggressively +-flattenpackagehierarchy +-keepattributes !SourceFile,!LineNumberTable \ No newline at end of file diff --git a/app/src/main/java/com/example/app/AppApplication.java b/app/src/main/java/com/example/app/AppApplication.java new file mode 100644 index 0000000..6631f60 --- /dev/null +++ b/app/src/main/java/com/example/app/AppApplication.java @@ -0,0 +1,14 @@ +package com.example.app; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AppApplication { + + public static void main(String[] args) { + final var app = new SpringApplication(AppApplication.class); + app.addInitializers(new StartupValidator()); + app.run(args); + } +} diff --git a/app/src/main/java/com/example/app/StartupValidator.java b/app/src/main/java/com/example/app/StartupValidator.java new file mode 100644 index 0000000..9c21480 --- /dev/null +++ b/app/src/main/java/com/example/app/StartupValidator.java @@ -0,0 +1,101 @@ +package com.example.app; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.time.Instant; +import java.util.Base64; +import java.util.Properties; + +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.io.ResourceLoader; + +import com.example.app.utils.KeyUtils; +import com.example.app.utils.LicenseUtils; + +public class StartupValidator implements ApplicationContextInitializer { + + // receiverKeyPair.getPublic() (Base64): + // MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE9G-hgHLHNDCEB3Tb38CDt_SipIGMthS7kewBDod58m7G0xGh3TNa5a8Q45rG37NFFT83hkwykWGGfxk8g9LA5yQpl4QLYUXSfiM8T8GkanEEeLJpX2d0Ch3QC6Sjuo2j + // receiverKeyPair.getPrivate() (Base64): + // ME4CAQAwEAYHKoZIzj0CAQYFK4EEACIENzA1AgEBBDDkCCqT2feXZ2OnzXBZjF8v1alWB9NghkF63nQyh9neDiA4B3f40gS2bnltoYmGjyY= + // senderKeyPair.getPublic() (Base64): + // MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE-Rmq7HbsQ_mYXvGBZMAQgV4NMDPaY0aXyoFg4u0ti7VKodKgr4WaWIRzXSb_Ohy_ZJTyICvvEMtVTNBdsietapKjY198Q5C8WCOwsYYhP5-rSb2PAqtM0XS_Hodr-Fqj + // senderKeyPair.getPrivate() (Base64): + // ME4CAQAwEAYHKoZIzj0CAQYFK4EEACIENzA1AgEBBDAzcFt4LKWxHYqSRIr527iGRjd_WFUSIruQ7POuKQ9ONTnnye3hYKAaDK5d-GjLzK4= + + @Override + public void initialize(ConfigurableApplicationContext context) { + + final ResourceLoader resourceLoader = context; + + final var env = context.getEnvironment(); + final var filePath = env.getProperty("my-folder") + File.separator + env.getProperty("my-id"); + final var properties = new Properties(); + + checkProperties(properties, filePath); + final var resource = resourceLoader.getResource(env.getProperty("license-server-trust")); + + if (!resource.exists()) { + throw new IllegalStateException("No trust store for license server!"); + } + int responseCode = 0; + try { + + final var message = properties.getProperty("index") + ":" + Instant.now() + .toEpochMilli() * 1_000_000; + final var encryptedData = KeyUtils.encryptDataWithAESGCM(message, KeyUtils.generateSharedSecret( + KeyUtils.stringToPrivateKey(env.getProperty("my-private-key")), + KeyUtils.stringToPublicKey(env.getProperty("license-server-public-key")))); + + final var encrypted = Base64.getUrlEncoder() + .encodeToString(encryptedData); + final var signature = KeyUtils.signMessage(message, + KeyUtils.stringToPrivateKey(env.getProperty("my-private-key"))); + + responseCode = LicenseUtils.request(env.getProperty("license-server-endpoint"), resource.getInputStream(), + env.getProperty("license-server-trust-password"), + env.getProperty("my-id") + "." + encrypted + "." + signature); + } catch (IOException e) { + throw new IllegalStateException("IO exception for trust store!", e); + } + + if (responseCode != 200) { + throw new IllegalStateException("License not valid!"); + } + } + + private void checkProperties(Properties properties, + String filePath) { + try { + File file = new File(filePath); + if (!file.exists()) { + createDefaultProperties(properties, filePath); + } else { + loadProperties(properties, filePath); + } + } catch (IOException e) { + throw new RuntimeException("IO Exception!", e); + } + } + + private void createDefaultProperties(Properties properties, + String filePath) throws IOException { + properties.setProperty("index", ""); + saveProperties(properties, filePath); + } + private void saveProperties(Properties properties, + String filePath) throws IOException { + try (FileOutputStream fos = new FileOutputStream(filePath)) { + properties.store(fos, "Updated properties file"); + } + } + private void loadProperties(Properties properties, + String filePath) throws IOException { + try (FileInputStream fis = new FileInputStream(filePath)) { + properties.load(fis); + } + } +} diff --git a/app/src/main/java/com/example/app/utils/DeterministicHexSequenceWithTimestamp.java b/app/src/main/java/com/example/app/utils/DeterministicHexSequenceWithTimestamp.java new file mode 100644 index 0000000..f37cb3e --- /dev/null +++ b/app/src/main/java/com/example/app/utils/DeterministicHexSequenceWithTimestamp.java @@ -0,0 +1,82 @@ +package com.example.app.utils; + +import java.math.BigInteger; +import java.time.Instant; + +public class DeterministicHexSequenceWithTimestamp { + + // Deterministic function f(x, t) incorporating timestamp using BigInteger + private static BigInteger f(BigInteger x, + long timestamp) { + x = x.xor(x.shiftLeft(5)); // XOR shift and addition + x = x.add(x.shiftRight(3)); // Addition + x = x.multiply(BigInteger.valueOf(2654435761L)) + .and(BigInteger.valueOf(0xFFFFFFFFFFFFFFFFL)); // Multiply by + // golden ratio, + // keep within 64 + // bits + x = x.xor(x.shiftRight(11)) + .and(BigInteger.valueOf(0xFFFFFFFFFFFFFFFFL)); // More scrambling + + // Mix timestamp into the transformation + BigInteger t_part = BigInteger.valueOf(timestamp) + .xor(BigInteger.valueOf(timestamp) + .shiftRight(32)); // Reduce + // to 64 + // bits + x = x.add(t_part) + .xor(x.shiftLeft(7) + .or(t_part.shiftRight(3))); // More bit-mixing + return x.and(BigInteger.valueOf(0xFFFFFFFFFFFFFFFFL)); // Keep within + // 64-bit range + } + + // Calculate the next value based on prev (hex string), f(prev, timestamp), + // and + // the fixed bit-length mask (hardcoded here) + private static BigInteger nextValue(String prevHex, + long timestamp) { + // Convert the prev hex string to BigInteger + BigInteger prev = new BigInteger(prevHex, 16); + + // Mask for a fixed bit length (e.g., 64 bits) + BigInteger mask = BigInteger.valueOf(1) + .shiftLeft(64) + .subtract(BigInteger.ONE); // 64-bit mask + + // Calculate next value using prev and timestamp, then apply mask + return prev.add(f(prev, timestamp)) + .and(mask); // Calculate next and apply mask + } + + public static void generateSequence(String startHex, + int length, + long timestamp, + int fixedBitLength) { + String prevHex = startHex; + + for (int i = 0; i < length; i++) { + // Use nextValue method to get the next value + BigInteger next = nextValue(prevHex, timestamp); + prevHex = next.toString(16) + .toUpperCase(); // Convert next value to hex string + + // Print next value in BigInteger and its fixed-length hexadecimal + // representation + System.out.println("Next value (BigInteger): " + next); + System.out.println("Next value (Hex, fixed length): 0x" + prevHex); + } + } + + public static void main(String[] args) { + // Initial seed value as a hex string + String startHex = "1A3F"; // Initial seed value in hex + int sequenceLength = 10; // Number of elements + long requestTimestamp = Instant.now() + .toEpochMilli() * 1_000_000; // Nanoseconds timestamp + int fixedBitLength = 64; // Fixed length of 64 bits for BigInteger and + // hex output + + generateSequence(startHex, sequenceLength, requestTimestamp, fixedBitLength); + } +} diff --git a/app/src/main/java/com/example/app/utils/KeyUtils.java b/app/src/main/java/com/example/app/utils/KeyUtils.java new file mode 100644 index 0000000..451193c --- /dev/null +++ b/app/src/main/java/com/example/app/utils/KeyUtils.java @@ -0,0 +1,231 @@ +package com.example.app.utils; + +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.Signature; +import java.security.SignatureException; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.KeyAgreement; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +public final class KeyUtils { + public static void main(String[] args) throws Exception { + // Simulating two separate entities: Sender and Receiver + + // 1. Receiver generates ECC key pair and shares the public key + KeyPair receiverKeyPair = generateECCKeyPair(); + + // 2. Sender generates its own ECC key pair + KeyPair senderKeyPair = generateECCKeyPair(); + + String receiverPublicKeyToString = publicKeyToString(receiverKeyPair.getPublic()); + String receiverPrivateKeyToString = privateKeyToString(receiverKeyPair.getPrivate()); + System.out.println("receiverKeyPair.getPublic() (Base64): " + receiverPublicKeyToString); + System.out.println("receiverKeyPair.getPrivate() (Base64): " + receiverPrivateKeyToString); + + String senderPublicKeyToString = publicKeyToString(senderKeyPair.getPublic()); + String senderPrivateKeyToString = privateKeyToString(senderKeyPair.getPrivate()); + System.out.println("senderKeyPair.getPublic() (Base64): " + senderPublicKeyToString); + System.out.println("senderKeyPair.getPrivate() (Base64): " + senderPrivateKeyToString); + + // 3. Exchange public keys (Simulated here, but in real-world, sender & + // receiver + // send them over network) + // Sender now has receiver's public key, and receiver has sender's + // public key + + // 4. Both compute the shared secret using ECDH + SecretKey senderSharedSecret = generateSharedSecret(stringToPrivateKey(senderPrivateKeyToString), + stringToPublicKey(receiverPublicKeyToString)); + + // 5. Encrypt data (Sender side) + String originalMessage = "Hello, secure world!"; + byte[] encryptedData = encryptDataWithAESGCM(originalMessage, senderSharedSecret); + + // 6. Send encrypted data to receiver (Simulated here) + // Receiver now decrypts using the shared secret + SecretKey receiverSharedSecret = generateSharedSecret(stringToPrivateKey(receiverPrivateKeyToString), + stringToPublicKey(senderPublicKeyToString)); + String decryptedMessage = decryptDataWithAESGCM(encryptedData, receiverSharedSecret); + + // Print Results + System.out.println("Original Message: " + originalMessage); + System.out.println("Encrypted (Base64): " + Base64.getUrlEncoder() + .encodeToString(encryptedData)); + System.out.println("Decrypted Message: " + decryptedMessage); + + String signature = signMessage(originalMessage, stringToPrivateKey(senderPrivateKeyToString)); + System.out.println("Signature: " + signature); + + // 3. Verify the signature + boolean isVerified = verifySignature(originalMessage, signature, stringToPublicKey(senderPublicKeyToString)); + System.out.println("Signature Verified: " + isVerified); + + } + + // Generate ECC key pair + private static KeyPair generateECCKeyPair() throws Exception { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC"); + ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp384r1"); + keyPairGenerator.initialize(ecSpec); + return keyPairGenerator.generateKeyPair(); + } + + // Generate shared secret using ECDH + public static SecretKey generateSharedSecret(PrivateKey privateKey, + PublicKey publicKey) { + try { + KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH"); + keyAgreement.init(privateKey); + keyAgreement.doPhase(publicKey, true); + byte[] sharedSecretBytes = keyAgreement.generateSecret(); + return new SecretKeySpec(sharedSecretBytes, 0, 16, "AES"); + } catch (InvalidKeyException e) { + throw new RuntimeException("Invalid key!", e); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("No such algorithm!", e); + } + } + + // Encrypt data using AES-GCM + public static byte[] encryptDataWithAESGCM(String data, + SecretKey sharedSecret) { + + try { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + + // Generate random 12-byte IV + SecureRandom random = new SecureRandom(); + byte[] iv = new byte[12]; + random.nextBytes(iv); + + GCMParameterSpec spec = new GCMParameterSpec(128, iv); + cipher.init(Cipher.ENCRYPT_MODE, sharedSecret, spec); + byte[] encryptedData = cipher.doFinal(data.getBytes()); + + // Combine IV and encrypted data + byte[] encryptedDataWithIv = new byte[iv.length + encryptedData.length]; + System.arraycopy(iv, 0, encryptedDataWithIv, 0, iv.length); + System.arraycopy(encryptedData, 0, encryptedDataWithIv, iv.length, encryptedData.length); + + return encryptedDataWithIv; + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("NoSuchAlgorithmException!", e); + } catch (NoSuchPaddingException e) { + throw new RuntimeException("NoSuchPaddingException!", e); + } catch (InvalidKeyException e) { + throw new RuntimeException("InvalidKeyException!", e); + } catch (InvalidAlgorithmParameterException e) { + throw new RuntimeException("InvalidAlgorithmParameterException!", e); + } catch (IllegalBlockSizeException e) { + throw new RuntimeException("IllegalBlockSizeException!", e); + } catch (BadPaddingException e) { + throw new RuntimeException("BadPaddingException!", e); + } + } + + // Decrypt data using AES-GCM + private static String decryptDataWithAESGCM(byte[] encryptedDataWithIv, + SecretKey sharedSecret) throws Exception { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + + // Extract IV + byte[] iv = new byte[12]; + System.arraycopy(encryptedDataWithIv, 0, iv, 0, iv.length); + byte[] encryptedData = new byte[encryptedDataWithIv.length - iv.length]; + System.arraycopy(encryptedDataWithIv, iv.length, encryptedData, 0, encryptedData.length); + + // Decrypt + GCMParameterSpec spec = new GCMParameterSpec(128, iv); + cipher.init(Cipher.DECRYPT_MODE, sharedSecret, spec); + byte[] decryptedData = cipher.doFinal(encryptedData); + + return new String(decryptedData); + } + + private static String privateKeyToString(PrivateKey privateKey) { + return Base64.getUrlEncoder() + .encodeToString(privateKey.getEncoded()); + } + + private static String publicKeyToString(PublicKey publicKey) { + return Base64.getUrlEncoder() + .encodeToString(publicKey.getEncoded()); + } + + public static PrivateKey stringToPrivateKey(String privateKeyStr) { + try { + byte[] keyBytes = Base64.getUrlDecoder() + .decode(privateKeyStr); + KeyFactory keyFactory = KeyFactory.getInstance("EC"); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); + return keyFactory.generatePrivate(keySpec); + } catch (InvalidKeySpecException e) { + throw new RuntimeException("Invalid key!", e); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("No such algorithm!", e); + } + } + + public static PublicKey stringToPublicKey(String publicKeyStr) { + try { + byte[] keyBytes = Base64.getUrlDecoder() + .decode(publicKeyStr); + KeyFactory keyFactory = KeyFactory.getInstance("EC"); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); + return keyFactory.generatePublic(keySpec); + } catch (InvalidKeySpecException e) { + throw new RuntimeException("Invalid key!", e); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("No such algorithm!", e); + } + } + + public static String signMessage(String message, + PrivateKey privateKey) { + try { + Signature signature = Signature.getInstance("SHA256withECDSA"); + signature.initSign(privateKey); + signature.update(message.getBytes()); + byte[] signedBytes = signature.sign(); + return Base64.getUrlEncoder() + .encodeToString(signedBytes); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("NoSuchAlgorithmException!", e); + } catch (InvalidKeyException e) { + throw new RuntimeException("InvalidKeyException!", e); + } catch (SignatureException e) { + throw new RuntimeException("SignatureException!", e); + } + } + + // Verify the signature + private static boolean verifySignature(String message, + String signatureStr, + PublicKey publicKey) throws Exception { + Signature signature = Signature.getInstance("SHA256withECDSA"); + signature.initVerify(publicKey); + signature.update(message.getBytes()); + byte[] signatureBytes = Base64.getUrlDecoder() + .decode(signatureStr); + return signature.verify(signatureBytes); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/app/utils/LicenseUtils.java b/app/src/main/java/com/example/app/utils/LicenseUtils.java new file mode 100644 index 0000000..208fa17 --- /dev/null +++ b/app/src/main/java/com/example/app/utils/LicenseUtils.java @@ -0,0 +1,76 @@ +package com.example.app.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; + +public final class LicenseUtils { + + public static int request(String endpoint, InputStream trustInput, String trustPassword, String payload) { + try { + + KeyStore trustStore = KeyStore.getInstance("JKS"); + trustStore.load(trustInput, trustPassword.toCharArray()); + TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustFactory.init(trustStore); + + // Create and initialize an SSLContext with the custom TrustManager + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, trustFactory.getTrustManagers(), new java.security.SecureRandom()); + + // Define the target URL + URL url = new URL(endpoint); + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + + connection.setSSLSocketFactory(sslContext.getSocketFactory()); + connection.setHostnameVerifier((hostname, session) -> true); + + + // Set request method to POST + connection.setRequestMethod("POST"); + connection.setDoOutput(true); // Enables writing to the connection + + // Set headers for plain text with UTF-8 encoding + connection.setRequestProperty("Content-Type", "text/plain; charset=UTF-8"); + + // Write data to request body + try (OutputStream os = connection.getOutputStream()) { + byte[] input = payload.getBytes(StandardCharsets.UTF_8); + os.write(input, 0, input.length); + } + + // Read response + int responseCode = connection.getResponseCode(); + System.out.println("Response Code: " + responseCode); + + // Close connection + connection.disconnect(); + return responseCode; + } catch (MalformedURLException e) { + throw new RuntimeException("Malformed URL!", e); + } catch (IOException e) { + throw new RuntimeException("IOException!", e); + } catch (KeyStoreException e) { + throw new RuntimeException("KeyStoreException!", e); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("NoSuchAlgorithmException!", e); + } catch (CertificateException e) { + throw new RuntimeException("CertificateException!", e); + } catch (KeyManagementException e) { + throw new RuntimeException("KeyManagementException!", e); + } + } + +} diff --git a/app/src/main/java/com/example/app/utils/StringObfuscator.java b/app/src/main/java/com/example/app/utils/StringObfuscator.java new file mode 100644 index 0000000..9df6309 --- /dev/null +++ b/app/src/main/java/com/example/app/utils/StringObfuscator.java @@ -0,0 +1,31 @@ +package com.example.app.utils; + +import java.util.Base64; + +public final class StringObfuscator { + + private StringObfuscator() { + throw new AssertionError("Cannot instantiate class " + StringObfuscator.class + "!"); + } + + private static final char XOR_KEY = 42; // Secret key (can be any character) + + // Encrypts a string using XOR and encodes it in Base64 + public static String encrypt(String input) { + char[] chars = input.toCharArray(); + for (int i = 0; i < chars.length; i++) { + chars[i] ^= XOR_KEY; // XOR each character + } + return Base64.getEncoder().encodeToString(new String(chars).getBytes()); + } + + // Decrypts a Base64-encoded XOR string + public static String decrypt(String encrypted) { + byte[] decodedBytes = Base64.getDecoder().decode(encrypted); + char[] chars = new String(decodedBytes).toCharArray(); + for (int i = 0; i < chars.length; i++) { + chars[i] ^= XOR_KEY; // XOR back to original + } + return new String(chars); + } +} diff --git a/app/src/main/resources/application.properties b/app/src/main/resources/application.properties new file mode 100644 index 0000000..b8ac1d0 --- /dev/null +++ b/app/src/main/resources/application.properties @@ -0,0 +1,11 @@ +spring.application.name=app +sever.port=8080 + +license-server-endpoint=https://localhost:8443/license +## can RE a License server anc change the trust store. +license-server-trust=classpath:license-trust.jks +license-server-trust-password=test +license-server-public-key=MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE9G-hgHLHNDCEB3Tb38CDt_SipIGMthS7kewBDod58m7G0xGh3TNa5a8Q45rG37NFFT83hkwykWGGfxk8g9LA5yQpl4QLYUXSfiM8T8GkanEEeLJpX2d0Ch3QC6Sjuo2j +my-id=my-server-id +my-private-key=ME4CAQAwEAYHKoZIzj0CAQYFK4EEACIENzA1AgEBBDAzcFt4LKWxHYqSRIr527iGRjd_WFUSIruQ7POuKQ9ONTnnye3hYKAaDK5d-GjLzK4= +my-folder=${user.home}/test/license/client \ No newline at end of file diff --git a/app/src/main/resources/license-trust.jks b/app/src/main/resources/license-trust.jks new file mode 100644 index 0000000000000000000000000000000000000000..e7ce60376d47d8195f18165cff4eb9878a2cac9d GIT binary patch literal 950 zcmXqLV&25W$ZXKW9K*(`)#lOmotKfFaX}NaFG~}%Cs5cGh#e79Y(Oa^ppYIDBLk39 zN60W5q`^6?yatg576>knfi{cCll?3A%FeSc%l>0s`{lKw`tn#yB_<|y0VYNT10FUG zh~-S2tPBRSY@7*g9*n8XER0$#0zaFNiYV#tHFh^LNO@_fEZWe-wBhHR7xQQQ-O6Mz zSA1^weW$YuwFL_-nrinp?)Q3itVO`5OTssSOYI$#)06#8t3{{JxuSZ`d8+b* zje82OEBt+?HCJi3OLoJ-YPtH}riEVv^cie8fB4@1WXf%PjDfdmp6JEDKTa;Nlwbe; z-PN*>izFUN{-1d?c(V^3Np@RskMhGLX5rT{0kA4ss8&4 z)%~`A|IA}hG&i!Fr!#DyWQgPUm*uDYSAKY5_^kL*L5)Gqu5+K>I(heb2{Q^To0fZF zUcgzl;C&A{BFzsTI(2xn70V4)>0c&2@7X`}{8Q#mXYqMCQ!?E7$=3kJj4AUz9ZWj< zZk=1zl#u6LjAo}6%gH)siu{M2Xd|z%8?Et^Nnt#(n*&-~MmsrntBE*H*Il=Koy$(`i~T|DIiY0!v~to-NN~ z3tZh4lX>y6{f2ca83ykrKj>->cz(8r|HsMl$G=RRR(+4C*}qWKz}LXgfES*unHX6a zSQO4Ei+oiPcoyXm#cQ@>w`}-k{+9Lojox>;rnpF#@SoFV5jmLHVfg&$vcFPu|AoxX OdZ&{*+kHAH%K!jk8mSZj literal 0 HcmV?d00001 diff --git a/app/src/test/java/com/example/app/AppApplicationTests.java b/app/src/test/java/com/example/app/AppApplicationTests.java new file mode 100644 index 0000000..6e9518b --- /dev/null +++ b/app/src/test/java/com/example/app/AppApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.app; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class AppApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/license/.gitattributes b/license/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/license/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/license/.gitignore b/license/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/license/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/license/.mvn/wrapper/maven-wrapper.properties b/license/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/license/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/license/mvnw b/license/mvnw new file mode 100755 index 0000000..19529dd --- /dev/null +++ b/license/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/license/mvnw.cmd b/license/mvnw.cmd new file mode 100644 index 0000000..249bdf3 --- /dev/null +++ b/license/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/license/pom.xml b/license/pom.xml new file mode 100644 index 0000000..d6c7dfe --- /dev/null +++ b/license/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.3 + + + com.example + license + 0.0.1-SNAPSHOT + license + Demo project for Spring Boot + + + + + + + + + + + + + + + 17 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/license/src/main/java/com/example/license/LicenseApplication.java b/license/src/main/java/com/example/license/LicenseApplication.java new file mode 100644 index 0000000..edce056 --- /dev/null +++ b/license/src/main/java/com/example/license/LicenseApplication.java @@ -0,0 +1,13 @@ +package com.example.license; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class LicenseApplication { + + public static void main(String[] args) { + SpringApplication.run(LicenseApplication.class, args); + } + +} diff --git a/license/src/main/java/com/example/license/rest/LicenseRest.java b/license/src/main/java/com/example/license/rest/LicenseRest.java new file mode 100644 index 0000000..59e492f --- /dev/null +++ b/license/src/main/java/com/example/license/rest/LicenseRest.java @@ -0,0 +1,86 @@ +package com.example.license.rest; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.example.license.utils.DeterministicHexSequenceWithTimestamp; + +@RestController +@RequestMapping("/license") +public class LicenseRest { + + private final String licenseDirectory; + + public LicenseRest(@Value("${license-folder}") String licenseDirectory) { + this.licenseDirectory = licenseDirectory; + } + + @PostMapping + public String check(@RequestBody String payload) throws IOException { + System.out.println(payload); + String[] split = payload.split("\\."); + File directory = new File(licenseDirectory); + + //TODO: extract ID, encrypted message and signature + final var id = split[0]; + final var encrypted = split[1]; + final var signature = split[2]; + System.out.println("Encrypted: " + encrypted); + System.out.println("Signature: " + signature); + + if (directory.isDirectory()) { + String[] fileNames = directory.list(); + + if (fileNames != null) { + for (String fileName : fileNames) { + if (fileName.equals(id)) { + final var filePath = licenseDirectory + File.separator + fileName; + final var props = loadProperties(filePath); + + //TODO: decrypt + + //TODO: verify signature + + //TODO: veryfy current index match, increment index using timestamp then send new index in response. + System.out.println("Props: " + props); + System.out.println(props.getProperty("index")); + if(!StringUtils.hasText(props.getProperty("index"))){ + props.setProperty("index", "1A3F"); + saveProperties(filePath, props); + } else { + props.setProperty("index", DeterministicHexSequenceWithTimestamp.nextValueString(props.getProperty("index"), 0)); + } + } + } + } + } else { + System.out.println("Provided path is not a directory."); + } + return "OK"; + } + + private Properties loadProperties(String filePath) throws IOException { + try (FileInputStream fis = new FileInputStream(filePath)) { + final var properties = new Properties(); + properties.load(fis); + return properties; + } + } + + private void saveProperties(String filePath, Properties properties) throws IOException { + try (FileOutputStream fos = new FileOutputStream(filePath)) { + properties.store(fos, "Updated properties file"); + } + } + +} diff --git a/license/src/main/java/com/example/license/utils/DeterministicHexSequenceWithTimestamp.java b/license/src/main/java/com/example/license/utils/DeterministicHexSequenceWithTimestamp.java new file mode 100644 index 0000000..a272d9b --- /dev/null +++ b/license/src/main/java/com/example/license/utils/DeterministicHexSequenceWithTimestamp.java @@ -0,0 +1,89 @@ +package com.example.license.utils; + +import java.math.BigInteger; +import java.time.Instant; + +public class DeterministicHexSequenceWithTimestamp { + + // Deterministic function f(x, t) incorporating timestamp using BigInteger + private static BigInteger f(BigInteger x, + long timestamp) { + x = x.xor(x.shiftLeft(5)); // XOR shift and addition + x = x.add(x.shiftRight(3)); // Addition + x = x.multiply(BigInteger.valueOf(2654435761L)) + .and(BigInteger.valueOf(0xFFFFFFFFFFFFFFFFL)); // Multiply by + // golden ratio, + // keep within 64 + // bits + x = x.xor(x.shiftRight(11)) + .and(BigInteger.valueOf(0xFFFFFFFFFFFFFFFFL)); // More scrambling + + // Mix timestamp into the transformation + BigInteger t_part = BigInteger.valueOf(timestamp) + .xor(BigInteger.valueOf(timestamp) + .shiftRight(32)); // Reduce + // to 64 + // bits + x = x.add(t_part) + .xor(x.shiftLeft(7) + .or(t_part.shiftRight(3))); // More bit-mixing + return x.and(BigInteger.valueOf(0xFFFFFFFFFFFFFFFFL)); // Keep within + // 64-bit range + } + + // Calculate the next value based on prev (hex string), f(prev, timestamp), + // and + // the fixed bit-length mask (hardcoded here) + public static BigInteger nextValue(String prevHex, + long timestamp) { + // Convert the prev hex string to BigInteger + BigInteger prev = new BigInteger(prevHex, 16); + + // Mask for a fixed bit length (e.g., 64 bits) + BigInteger mask = BigInteger.valueOf(1) + .shiftLeft(64) + .subtract(BigInteger.ONE); // 64-bit mask + + // Calculate next value using prev and timestamp, then apply mask + return prev.add(f(prev, timestamp)) + .and(mask); // Calculate next and apply mask + } + + public static String nextValueString(String prevHex, + long timestamp) { + BigInteger next = nextValue(prevHex, timestamp); + return next.toString(16) + .toUpperCase(); + } + + public static void generateSequence(String startHex, + int length, + long timestamp, + int fixedBitLength) { + String prevHex = startHex; + + for (int i = 0; i < length; i++) { + // Use nextValue method to get the next value + BigInteger next = nextValue(prevHex, timestamp); + prevHex = next.toString(16) + .toUpperCase(); // Convert next value to hex string + + // Print next value in BigInteger and its fixed-length hexadecimal + // representation + System.out.println("Next value (BigInteger): " + next); + System.out.println("Next value (Hex, fixed length): 0x" + prevHex); + } + } + + public static void main(String[] args) { + // Initial seed value as a hex string + String startHex = "1A3F"; // Initial seed value in hex + int sequenceLength = 10; // Number of elements + long requestTimestamp = Instant.now() + .toEpochMilli() * 1_000_000; // Nanoseconds timestamp + int fixedBitLength = 64; // Fixed length of 64 bits for BigInteger and + // hex output + + generateSequence(startHex, sequenceLength, requestTimestamp, fixedBitLength); + } +} diff --git a/license/src/main/java/com/example/license/utils/KeyUtils.java b/license/src/main/java/com/example/license/utils/KeyUtils.java new file mode 100644 index 0000000..1393e4d --- /dev/null +++ b/license/src/main/java/com/example/license/utils/KeyUtils.java @@ -0,0 +1,182 @@ +package com.example.license.utils; + +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.Signature; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; + +import javax.crypto.Cipher; +import javax.crypto.KeyAgreement; +import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +public final class KeyUtils { + public static void main(String[] args) throws Exception { + // Simulating two separate entities: Sender and Receiver + + // 1. Receiver generates ECC key pair and shares the public key + KeyPair receiverKeyPair = generateECCKeyPair(); + + // 2. Sender generates its own ECC key pair + KeyPair senderKeyPair = generateECCKeyPair(); + + String receiverPublicKeyToString = publicKeyToString(receiverKeyPair.getPublic()); + String receiverPrivateKeyToString = privateKeyToString(receiverKeyPair.getPrivate()); + System.out.println("receiverKeyPair.getPublic() (Base64): " + receiverPublicKeyToString); + System.out.println("receiverKeyPair.getPrivate() (Base64): " + receiverPrivateKeyToString); + + String senderPublicKeyToString = publicKeyToString(senderKeyPair.getPublic()); + String senderPrivateKeyToString = privateKeyToString(senderKeyPair.getPrivate()); + System.out.println("senderKeyPair.getPublic() (Base64): " + senderPublicKeyToString); + System.out.println("senderKeyPair.getPrivate() (Base64): " + senderPrivateKeyToString); + + // 3. Exchange public keys (Simulated here, but in real-world, sender & + // receiver + // send them over network) + // Sender now has receiver's public key, and receiver has sender's + // public key + + // 4. Both compute the shared secret using ECDH + SecretKey senderSharedSecret = generateSharedSecret(stringToPrivateKey(senderPrivateKeyToString), + stringToPublicKey(receiverPublicKeyToString)); + + // 5. Encrypt data (Sender side) + String originalMessage = "Hello, secure world!"; + byte[] encryptedData = encryptDataWithAESGCM(originalMessage, senderSharedSecret); + + // 6. Send encrypted data to receiver (Simulated here) + // Receiver now decrypts using the shared secret + SecretKey receiverSharedSecret = generateSharedSecret(stringToPrivateKey(receiverPrivateKeyToString), + stringToPublicKey(senderPublicKeyToString)); + String decryptedMessage = decryptDataWithAESGCM(encryptedData, receiverSharedSecret); + + // Print Results + System.out.println("Original Message: " + originalMessage); + System.out.println("Encrypted (Base64): " + Base64.getEncoder() + .encodeToString(encryptedData)); + System.out.println("Decrypted Message: " + decryptedMessage); + + String signature = signMessage(originalMessage, stringToPrivateKey(senderPrivateKeyToString)); + System.out.println("Signature: " + signature); + + // 3. Verify the signature + boolean isVerified = verifySignature(originalMessage, signature, stringToPublicKey(senderPublicKeyToString)); + System.out.println("Signature Verified: " + isVerified); + + } + + // Generate ECC key pair + private static KeyPair generateECCKeyPair() throws Exception { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC"); + ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp384r1"); + keyPairGenerator.initialize(ecSpec); + return keyPairGenerator.generateKeyPair(); + } + + // Generate shared secret using ECDH + private static SecretKey generateSharedSecret(PrivateKey privateKey, + PublicKey publicKey) throws Exception { + KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH"); + keyAgreement.init(privateKey); + keyAgreement.doPhase(publicKey, true); + byte[] sharedSecretBytes = keyAgreement.generateSecret(); + return new SecretKeySpec(sharedSecretBytes, 0, 16, "AES"); + } + + // Encrypt data using AES-GCM + private static byte[] encryptDataWithAESGCM(String data, + SecretKey sharedSecret) throws Exception { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + + // Generate random 12-byte IV + SecureRandom random = new SecureRandom(); + byte[] iv = new byte[12]; + random.nextBytes(iv); + + GCMParameterSpec spec = new GCMParameterSpec(128, iv); + cipher.init(Cipher.ENCRYPT_MODE, sharedSecret, spec); + byte[] encryptedData = cipher.doFinal(data.getBytes()); + + // Combine IV and encrypted data + byte[] encryptedDataWithIv = new byte[iv.length + encryptedData.length]; + System.arraycopy(iv, 0, encryptedDataWithIv, 0, iv.length); + System.arraycopy(encryptedData, 0, encryptedDataWithIv, iv.length, encryptedData.length); + + return encryptedDataWithIv; + } + + // Decrypt data using AES-GCM + private static String decryptDataWithAESGCM(byte[] encryptedDataWithIv, + SecretKey sharedSecret) throws Exception { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + + // Extract IV + byte[] iv = new byte[12]; + System.arraycopy(encryptedDataWithIv, 0, iv, 0, iv.length); + byte[] encryptedData = new byte[encryptedDataWithIv.length - iv.length]; + System.arraycopy(encryptedDataWithIv, iv.length, encryptedData, 0, encryptedData.length); + + // Decrypt + GCMParameterSpec spec = new GCMParameterSpec(128, iv); + cipher.init(Cipher.DECRYPT_MODE, sharedSecret, spec); + byte[] decryptedData = cipher.doFinal(encryptedData); + + return new String(decryptedData); + } + + private static String privateKeyToString(PrivateKey privateKey) { + return Base64.getEncoder() + .encodeToString(privateKey.getEncoded()); + } + + private static String publicKeyToString(PublicKey publicKey) { + return Base64.getEncoder() + .encodeToString(publicKey.getEncoded()); + } + + private static PrivateKey stringToPrivateKey(String privateKeyStr) throws Exception { + byte[] keyBytes = Base64.getDecoder() + .decode(privateKeyStr); + KeyFactory keyFactory = KeyFactory.getInstance("EC"); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); + return keyFactory.generatePrivate(keySpec); + } + + private static PublicKey stringToPublicKey(String publicKeyStr) throws Exception { + byte[] keyBytes = Base64.getDecoder() + .decode(publicKeyStr); + KeyFactory keyFactory = KeyFactory.getInstance("EC"); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); + return keyFactory.generatePublic(keySpec); + } + + private static String signMessage(String message, + PrivateKey privateKey) throws Exception { + Signature signature = Signature.getInstance("SHA256withECDSA"); + signature.initSign(privateKey); + signature.update(message.getBytes()); + byte[] signedBytes = signature.sign(); + return Base64.getEncoder() + .encodeToString(signedBytes); + } + + // Verify the signature + private static boolean verifySignature(String message, + String signatureStr, + PublicKey publicKey) throws Exception { + Signature signature = Signature.getInstance("SHA256withECDSA"); + signature.initVerify(publicKey); + signature.update(message.getBytes()); + byte[] signatureBytes = Base64.getDecoder() + .decode(signatureStr); + return signature.verify(signatureBytes); + } +} diff --git a/license/src/main/resources/application.properties b/license/src/main/resources/application.properties new file mode 100644 index 0000000..93efb91 --- /dev/null +++ b/license/src/main/resources/application.properties @@ -0,0 +1,8 @@ +spring.application.name=license +server.port=8443 +server.ssl.key-store=classpath:server.jks +server.ssl.key-store-password=test +server.ssl.key-store-type=JKS +server.ssl.key-alias=torsim-license-server + +license-folder=${user.home}/test/license/server \ No newline at end of file diff --git a/license/src/main/resources/server.jks b/license/src/main/resources/server.jks new file mode 100644 index 0000000000000000000000000000000000000000..e9ef8c4d87df5c279e288f5c48447aae2318b404 GIT binary patch literal 893 zcmezO_TO6u1_mY|W&~r=lKi6L%v{}^%;eO(;#A$@)S|M~BB1QlwE0s$f>aqa{x#rZ zGB^T>M5BO2YxmxtUfNh?%P#1&$ku|yI$S6KhI~&O|I&A>CMyS zjwU*#3u!Z!YrYq3Tl8RUn1I5}UQ@%}yVIVP+|{lZf68oJBjYja#g0$Gm(r7^_8Q2R z#d-SNQ`}e4tSurTb$HjkJJaQY7Dl@NEHCQgexS;AZDz*?u1>a<-JCD~EZ%$7V`23Q zql^iYj&oEWo3v!&`sLq_2_$X*#u;3=eaFM2hB{LY$WM4_)hT<8+b$_(=7On(9aB|I z4rWgQ2NP?Ao~eN)FyPb;nwXRgniy9uU}j=uVq!@@5xLKRi;Y98&EuRc3p0~JwIR0w zCmVAp3!5-gkiVgjfdGiZ!NciPnw*hXlv-Q@6Jtjf6ExrlspI0|2u@5(ElEwzFoX(m zBMHeF$beKa^I(rQ137VCBU1xo15-m217j1TC?MAii94{4D+2}vJ2;$}7};308(A2X zn3EV-I<)^)vCo}nUu96a=w4)&9>?A@%~@JKE7naa`EpX>r-tvom_MqI`?p?RQ20;D zYnq3wy~**O{KNT8mM6chZHuuG^#6T+`|C#L)&r|nEKf>w{&|1TuJx{JobkpR_)g1q z6eGtDa|VM!Dw9FMl9fSudaAsuGyfd(XyjeQ5-_*@fuqj~9l>Yf?CIaXe0!`_@uv0N zs_WApKiw%H(#T}U@K8P6$MVF7$k|l^#RayjmgX>aubk5;t9>M4YEUTiwYbe?6Ve_` kl?f8oo!RjwFM2zdpG6kSrtEu8C+~dvdap+39!vWa066wQYXATM literal 0 HcmV?d00001 diff --git a/license/src/test/java/com/example/license/LicenseApplicationTests.java b/license/src/test/java/com/example/license/LicenseApplicationTests.java new file mode 100644 index 0000000..7539e58 --- /dev/null +++ b/license/src/test/java/com/example/license/LicenseApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.license; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class LicenseApplicationTests { + + @Test + void contextLoads() { + } + +}