Puncte:2

Clarificare despre funcția iota a SHA-3

drapel cn

Încerc să implementez SHA-3 folosind acest document și aveți o întrebare despre pasul iota.

Acest pas constă într-un singur XOR între banda centrală (0, 0) a stării (ilustrarea stării p.8 dacă este necesar) și o constantă rotundă. În alți termeni:

pentru z în [0, w[:
    fie stare_noua(0, 0, z) = stare(0, 0, z) ^ RC[z]

unde RC este văzut ca un șir de biți.

Constanta primei runde a primei runde este 1, astfel doar un bit va fi schimbat. După cum se poate vedea în aceasta document furnizând vectori de testare, avem în runda #0:

După Chi
    00 00 00 00 00 00 00 00 ...
După Iota
    01 00 00 00 00 00 00 00 ... (următoarele sunt egale cu cele de mai sus)

Totuși, există ceva ce nu înțeleg: bitul care este modificat în acei vectori de test este al optulea, dar constanta noastră rotundă este un 1 scris pe w-biți. Dacă $w=8$ (implicând un mesaj de 200 de biți), totul este în regulă, dar în linkul anterior, avem un mesaj de 1600 de biți, deci $w=64$. Cum poate XOR-ing acest 64 de biți 0...01 schimba al optulea bit al benzii?

EDIT: Îmi voi adăuga codul mai jos (încă este în lucru):

clasa Keccak(obiect):

    def __init__(self):
        sine.l = 6
        self.w = pow(2, self.l)

        self.state = [[[0 pentru x în interval(5)] pentru y în interval (5)] pentru z în interval(self.w)]
        self.tmp_state = [[[0 pentru x în interval (5)] pentru y în interval (5)] pentru z în interval (self.w)]


    def init_state(self, S):
        pentru x în intervalul (5):
            pentru y în intervalul (5):
                pentru z în interval (self.w):
                    self.set_state(x, y, z, int(S[self.w*(5*y + x) + z], 2))

    def init_tmp_state(self):
        pentru x în intervalul (5):
            pentru y în intervalul (5):
                pentru z în interval (self.w):
                    self.set_tmp_state(x, y, z, 0)


    def index_processing(self, x, y, z):
        returnare (z % self.w, (y + 2) % 5, (x + 2) % 5)
        

    def get_state(self, x, y, z):
        x, y, z = self.index_processing(x, y, z)
        returnează starea de sine[x][y][z]

    def set_state(self, x, y, z, v):
        x, y, z = self.index_processing(x, y, z)
        starea de sine[x][y][z] = v


    def get_tmp_state(self, x, y, z):
        x, y, z = self.index_processing(x, y, z)
        returnează self.tmp_state[x][y][z]

    def set_tmp_state(self, x, y, z, v):
        x, y, z = self.index_processing(x, y, z)
        self.tmp_state[x][y][z] = v


    def state_to_string(self):
        șir_biți = []
        pentru y în intervalul (5):
            pentru x în intervalul (5):
                pentru z în interval (self.w):
                    bit_string.append(str(self.get_state(x, y, z)))

        returnează ''.join(bit_string)


    def rc(self, t):
        dacă t % 255 == 0:
            întoarce 1

        R = [1, 0, 0, 0, 0, 0, 0, 0]
        pentru i în domeniul (1, (t % 255) + 1):
            R = [0] + R
            R[0] ^= R[8]
            R[4] ^= R[8]
            R[5] ^= R[8]
            R[6] ^= R[8]
            R = R[:8]

        returnează R[0]


    def iota(self, i):
        RC = [0 pentru j în interval (self.w)]
        pentru j în interval (self.l + 1):
            RC[pow(2, j) - 1] = self.rc(j + 7*i)

        pentru z în interval (self.w):
            self.set_state(0, 0, z, self.get_state(0, 0, z) ^ RC[z])




def test_iota():
    initial_state = "0000000000000000D2D2D2D2D2D2D2D20000000000000000E8E8E8E8E8E8E8E83A3A3A3A3A3A3A3A535353535353535300000000000000001D1D1D1D1D1D1D1D4E4E4E4E4E4E4E4E00000000000000004141414141414141E8E8E8E8E8E8E8E80000000000000000414141414141414126262626262626261D1D1D1D1D1D1D1D0000000000000000474747474747474718181818181818184747474747474747E8E8E8E8E8E8E8E835353535353535350000000000000000AFAFAFAFAFAFAFAF1212121212121212"
    stare_inițială = bin(int(stare_inițială, 16))[2:].zfill(1600)

    keccak = Keccak()
    keccak.init_state(initial_state)
    keccak.iota(0)
    rezultat = keccak.state_to_string()

    correct_result = "0100000000000000D2D2D2D2D2D2D2D20000000000000000E8E8E8E8E8E8E8E83A3A3A3A3A3A3A3A535353535353535300000000000000001D1D1D1D1D1D1D1D4E4E4E4E4E4E4E4E00000000000000004141414141414141E8E8E8E8E8E8E8E80000000000000000414141414141414126262626262626261D1D1D1D1D1D1D1D0000000000000000474747474747474718181818181818184747474747474747E8E8E8E8E8E8E8E835353535353535350000000000000000AFAFAFAFAFAFAFAF1212121212121212"
    rezultat_corect = bin(int(rezultat_corec, 16))[2:].zfill(1600)

    print("\tIota:\t" + str(rezultat == rezultat_correct))
    
    print(rezultat[0:64] + „\n\n” + rezultat_correct[0:64])

Testul se imprimă:

    Iota: Fals
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

0000000100000000000000000000000000000000000000000000000000000000000
kelalaka avatar
drapel in
Figura 2, poziția indicilor nu este standard. [0,0,1] este centrul feliei frontale. Deci, la imprimare, aceasta va fi tipărită.
Katoptriss avatar
drapel cn
De asemenea, m-am gândit că poate am greșit indexarea, dar mi-am testat funcțiile string_to_state și state_to_string folosind secțiunile 3.1.2 și 3.1.3 și mi s-au părut corecte. Dar nici nu cred că problema ar putea veni din altă parte decât acolo. Voi edita pentru a-mi adăuga codul. În plus, în secțiunea 3.1.3, șirul de biți rezultat din stare este mai întâi construit prin concatenarea state(0, 0, 0) cu state(0, 0, 63) : asta nu înseamnă totuși că bitul s-a schimbat și mai târziu tipărit este al optulea, în stare(0, 0, 7) ?
Katoptriss avatar
drapel cn
Un gând care tocmai mi-a trecut prin minte: poate aceasta este doar o problemă proastă de endianness? Dar funcțiile pi și khi pe care le-am scris ambele își trec testele și dau rezultatul așteptat, așa că nu știu despre schimbarea endianității. O sa incerc pentru orice eventualitate.
Katoptriss avatar
drapel cn
Ei bine, se pare că răspunsul a fost că nu a fost endianness în sine, ci mai degrabă "bitwise endianness" unde biții trebuie luați în ordine inversă. Ciudat. Dar ar fi trebuit să citesc standardul mai atent.
kelalaka avatar
drapel in
Ar trebui să citiți întregul document înainte de a începe.
kelalaka avatar
drapel in
Poti sa iti raspunzi la intrebare, e ok!

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.