def __init__(self, seed=None): if not seed: seed = urandom(56) elif len(seed) < 4 * 8 + 3 * 8: raise Exception('Seed value too short') self.key_words = [ littleendian2int(seed[i * 4:i * 4 + 4]) for i in range(8) ] self.nonce_words = [ littleendian2int(seed[32 + i * 4:32 + i * 4 + 4]) for _ in range(3) ] self.counter = 1 self.buf = ""
def chacha20_decrypt(data, key, counter=1): "Decrypt a string using a key" key = fixed_length_key(key, 32) key_words = [littleendian2int(key[i:i + 4]) for i in range(0, 32, 4)] nonce_words = [littleendian2int(data[i:i + 4]) for i in range(0, 12, 4)] ciphertext = data[12:] plaintext = "" for i in range(0, len(ciphertext), 64): j = _i32(i // 64) key_stream = chacha20_block(key_words, [_i32(counter + j)], nonce_words) block = ciphertext[i:i + 64] plaintext += xor_str(block, key_stream) return plaintext
def chacha20_encrypt(plaintext, key, counter=1): "Encrypt a string using a key" key = fixed_length_key(key, 32) key_words = [littleendian2int(key[i:i + 4]) for i in range(0, 32, 4)] nonce_words = [littleendian2int(urandom(4)) for _ in range(3)] ciphertext = "".join([int2littleendian(n, 4) for n in nonce_words]) for i in range(0, len(plaintext), 64): j = _i32(i // 64) key_stream = chacha20_block(key_words, [_i32(counter + j)], nonce_words) block = plaintext[i:i + 64] ciphertext += xor_str(block, key_stream) return ciphertext
def poly1305(data, key): "Poly1305 message authentication code" r = littleendian2int(key[:16]) r = clamp(r) s = littleendian2int(key[16:]) accumulator = 0 p = (1 << 130) - 5 for i in range(0, len(data), 16): block = data[i:i + 16] n = littleendian2int(block) onebit = 2**(len(block) * 8) n = n + onebit accumulator += n accumulator = (r * accumulator) % p accumulator += s tag = int2littleendian(accumulator, 16)[:16] return tag
def poly1305_key_gen(key, nonce): counter = 0 key_words = [littleendian2int(key[i:i + 4]) for i in range(0, 32, 4)] nonce_words = [littleendian2int(nonce[i:i + 4]) for i in range(0, 12, 4)] block = crypturd.chacha20_block(key_words, [counter], nonce_words) return block[:32]