Open sirex opened 9 years ago
It looks, like this should be implemented as asynchronous single thread process, that performs incremental signing and hashing, because we need to handle concurrent requests.
So I would say, that a daemon should be created for this task. This daemon would be responsible for single task - to do incremental hashing.
I think this daemon could communicate over a socket or inet port and should be associated with a file, where <data>\t<hash>\n
will be written.
Also, this can be implemented in some different way, but you need to keep in mind, that it should be able to handle concurrency.
tai kaip aš įsivaizduoju, kad klientas (balsuotojas) per socket'ą (socket prisijungimą padariau per standartinę built-in python socket biblioteką) prisijungia prie serverio (VRK), o serveryje jau veikia visa programa, visos funkcijos kiek tik įmanoma, išskyrus tik pasirašymą kliento privačiu raktu. Tai mano funkcija turėtų sukurti naują thread serverio pusėje.
Ši dalis visiškai neliečia kliento ir kalba eina apie serverio dalį. Užduotis aprašyta kliento/bibliotekos dalyje, todėl, kad tas dalykas turės būti panaudotas tie Django serverio dalyje, tiek microframewrok serverio dalyje, todėl tai turi eiti į biblioteką, kurią naudos abu serverio įgyvendinimai.
Ar konkrečiai reikia naudoti socketus, nežinau, tai yra vienas iš galimų įgyvendinimo variantų. Gal būt socketai yra per daug žemas lygis ir galime naudoti tiesiog kokį aiohttp. Arba galima naudoti kažką visai kitą.
ir šituos griaučius naudosim visi mes savo funkcijų įgyvendinimui kaip suprantu, ar nereikia to įkelti į githubą, kad galėtume kelti savo funkcijas į vieną bendrą schemą, į serverio ar kliento kodo dalį. Nes dabar aš nežinau kaip tiksliai ištestuoti savo funkcijos veikimą, kaip ji atrodys šalia kitų funkcijų, į ką integruojasi.
Tai turi keliauti į kliento/bibliotekos repozitoriją [1].
[1] https://github.com/python-dirbtuves/internet-voting
Dėl pačios funkcijos esmės, tai skaičiau daug kartų tą tavo duotą funkcijos aprašymą, bandžiau suprasti, bet vis tik perėjau prie tų trijų punktų, kuriuos minėjau, kad išmokau (vieši privatūs raktai, threading ir sockets) ir pačios funkcijos kaip ji turėtų atrodyti neįsivaizduoju vis dar.
pavyzdžiui Here hash is SHA-1 hash, signature is a hash of hash signature made with CEC private key.
kas yra šitas hash? balsuotojo balsas pasirašytas su jo private key?
taip pat paties incremental veikimo principo nesuprantu.
kiekvienas balsas turi būti pasirašytas balsuotojo privačiu ir VRK viešu raktais, tą procedūrą įsivaizduoju kaip funkciją, kuri vykdoma kiekvienam balsui, o ką būtent tas incremental reiškia? yra dar hash vertė visiem balsuotojų balsam kaip vienam duomenų vienetui ar kaip?
Pabandysiu į visus šiuos klausimus atsakyti vienu paaiškinimu.
Visų pirma štai kaip veikia hash funkcija:
>>> import hashlib
>>> h = hashlib.sha1()
>>> h.update(b'data')
>>> h.hexdigest()
'a17c9aaa61e80a1bf71d0d850af4e5baa9800bbd'
>>> h.update(b'more data')
>>> h.hexdigest()
'8e8c2113851f57816d57a1f2fb8b012c9d89ff3a'
>>> h.update(b'even more date')
>>> h.hexdigest()
'25edf74e9fe7230d7f5ec3198c04709d9bd9cede'
Iš šio pavyzdžio matyti, kad hash funkcija, kuri šiuo atveju yra SHA-1, buvo paduoti tokie duomenys:
data
more data
even more date
Iš kiekvieno gauto duomenų gabalo buvo progresyviai (incremental) generuojama hash reikšmė:
'data' -> 'a17c9aaa61e80a1bf71d0d850af4e5baa9800bbd'
'data' + 'more data' -> '8e8c2113851f57816d57a1f2fb8b012c9d89ff3a'
'data' + 'more data' + 'even more date' -> '25edf74e9fe7230d7f5ec3198c04709d9bd9cede'
Jei kas nors pakartotų hash reikšmių generavimą, tokia pačia tvarka ir tokiais pat gabalais, jis gautų identiškai tas pačias hash reikšmes.
Tuo pačiu, visų duomenų galutinę hash reikšmę galima gauti tik sumaitinus visus duomenis, pavyzdžiui:
>>> hashlib.sha1(b'data' + b'more data' + b'even more date').hexdigest()
'25edf74e9fe7230d7f5ec3198c04709d9bd9cede'
Čia gavom identiškai tą pačią hash funkciją.
O viso to esmė yra ta, kad kiekvienas balsuojantis gauna hash reikšmę toje vietoje, kai jo pateikti duomenys buvo įtraukti į bendrą duomenų srautą. Galiausiai, kai VRK paskelbia galutinius duomenis ir galutinę hash reikšmę, kiekvienas balsuojantysis, žinodamas kokius duomenis padavė, kokia buvo tų duomenų hash reikšmė ir kokia yra galutinių duomenų hash reikšmė, gali įsitikinti ar duomenys nebuvo pakeisti.
Todėl tavo užduotis - padaryti galimybę prie esamų duomenų pridėti naują duomenų bloką ir grąžinto galutinę hash reikšmę.
Pats paprasčiausias būdas tai padaryti - kiekvieną kartą perskaičiuoti hash reikšmę iš visų turimų duomenų.
Tačiau, reikia atkreipti dėmesį, kad duomenų integralumui užtikrinti, pridėti naujus duomenis gali tik viena gija, visos kitos turi laukti. Jei darytum šį paprasčiausią variantą, tai sistema greičiausiai stabdytų, kadangi kiekvieną kartą reikėtų perskaičiuoti hash reikšmę. Žinoma, stabdymas pasijaustų, tik turint didelį skaičių balsuojančiųjų.
Žodžiu, aš matau du variantus:
h.update(data)
.Su pasirašymu yra lygiai taip pat, galima generuoti progresyvų parašą, paduodant vis daugiau naujų duomenų.
Tikiuosi pasidarė aiškiau, galėsime pasiaiškinti rytoj.
There are several places, where CEC has to sign something. For this, we need a function that can incrementally sign data stream.
Function signature could look something like this:
Here
hash
is SHA-1 hash,signature
is a hash ofhash
signature made with CEC private key.hash
andsignature
both have to be incremental, meaning that if you will hash alldata
you will gethash
from the lastsign
call with last passeddata
.data
is an iterable of strings.state
is an optional argument and ifstate
is given, then it should continue hashing from where it left. I'm not sure how to implement this, if will have to find-out it yourself. But the idea, that it should be enough to hash only new items, not everything from the beginning.