def _step(hin, m, sbox): """ Step function H_out = f(H_in, m) """ # Generate keys u = hin v = m w = strxor(hin, m) k1 = P(w) u = strxor(A(u), C2) v = A(A(v)) w = strxor(u, v) k2 = P(w) u = strxor(A(u), C3) v = A(A(v)) w = strxor(u, v) k3 = P(w) u = strxor(A(u), C4) v = A(A(v)) w = strxor(u, v) k4 = P(w) # Encipher h4, h3, h2, h1 = hin[0:8], hin[8:16], hin[16:24], hin[24:32] s1 = ns2block(encrypt(sbox, k1[::-1], block2ns(h1[::-1])))[::-1] s2 = ns2block(encrypt(sbox, k2[::-1], block2ns(h2[::-1])))[::-1] s3 = ns2block(encrypt(sbox, k3[::-1], block2ns(h3[::-1])))[::-1] s4 = ns2block(encrypt(sbox, k4[::-1], block2ns(h4[::-1])))[::-1] s = b"".join((s4, s3, s2, s1)) # Permute # H_out = chi^61(H_in XOR chi(m XOR chi^12(S))) x = s for _ in xrange(12): x = _chi(x) x = strxor(x, m) x = _chi(x) x = strxor(hin, x) for _ in xrange(61): x = _chi(x) return x
def _step(hin, m, sbox): """ Step function H_out = f(H_in, m) """ # Generate keys u = hin v = m w = strxor(hin, m) k1 = P(w) u = strxor(A(u), C2) v = A(A(v)) w = strxor(u, v) k2 = P(w) u = strxor(A(u), C3) v = A(A(v)) w = strxor(u, v) k3 = P(w) u = strxor(A(u), C4) v = A(A(v)) w = strxor(u, v) k4 = P(w) # Encipher h4, h3, h2, h1 = hin[0:8], hin[8:16], hin[16:24], hin[24:32] s1 = ns2block(encrypt(sbox, k1[::-1], block2ns(h1[::-1])))[::-1] s2 = ns2block(encrypt(sbox, k2[::-1], block2ns(h2[::-1])))[::-1] s3 = ns2block(encrypt(sbox, k3[::-1], block2ns(h3[::-1])))[::-1] s4 = ns2block(encrypt(sbox, k4[::-1], block2ns(h4[::-1])))[::-1] s = b''.join((s4, s3, s2, s1)) # Permute # H_out = chi^61(H_in XOR chi(m XOR chi^12(S))) x = s for _ in range(12): x = _chi(x) x = strxor(x, m) x = _chi(x) x = strxor(hin, x) for _ in range(61): x = _chi(x) return x
def test_steps(self): """ Check step-by-step operation manually """ key = urandom(32) iv = urandom(8) plaintext = urandom(20) ciphertext = cfb_encrypt(key, plaintext, iv) # First full block step = encrypt(DEFAULT_SBOX, key, block2ns(iv)) step = strxor(plaintext[:8], ns2block(step)) self.assertSequenceEqual(step, ciphertext[:8]) # Second full block step = encrypt(DEFAULT_SBOX, key, block2ns(step)) step = strxor(plaintext[8:16], ns2block(step)) self.assertSequenceEqual(step, ciphertext[8:16]) # Third non-full block step = encrypt(DEFAULT_SBOX, key, block2ns(step)) step = strxor(plaintext[16:] + 4 * b"\x00", ns2block(step)) self.assertSequenceEqual(step[:4], ciphertext[16:])
def digest(self): """ Get MAC tag of supplied data You have to provide at least single byte of data. If you want to produce tag length of 3 bytes, then ``digest()[:3]``. """ if not self.data: raise ValueError("No data processed") data = pad1(self.data, BLOCKSIZE) prev = block2ns(self.iv)[::-1] for i in xrange(0, len(data), BLOCKSIZE): prev = xcrypt( SEQ_MAC, self.sbox, self.key, block2ns(strxor( data[i:i + BLOCKSIZE], ns2block(prev), )), )[::-1] return ns2block(prev)