Example #1
0
def keyed_homomorphic_permutation(state, key, rounds=4): 
    """ Ultimately, xors together random groups of state bits,
        such that each bit is made up of bit_i XOR bit_j XOR bit_k ... for
        a large enough number of random terms. """
    a, b, c, d = bytes_to_words(state, 4)
    key = key[:]
    for i in range(rounds):        
        key_schedule(key)
        # randomize the position of bits                    
        a, b, c, d = bit_permutation((a, b, c, d), bytes_to_words(key, 4))    
        
        # stack lots of bits on top of each other
        a, b, c, d = mix_columns(a, b, c, d)
        b = rotate_left(b, 1, 32)
        c = rotate_left(c, 2, 32)
        d = rotate_left(d, 3, 32)
        
        a, b, c, d = mix_columns(a, b, c, d)
        b = rotate_left(b, 4, 32)
        c = rotate_left(c, 8, 32)
        d = rotate_left(d, 12, 32)
        
        a, b, c, d = mix_columns(a, b, c, d)
        b = rotate_left(b, 8, 32)
        c = rotate_left(c, 12, 32)
        d = rotate_left(d, 16, 32)
        
        a, b, c, d = mix_columns(a, b, c, d)      
    key_schedule(key)
    a, b, c, d = bit_permutation((a, b, c, d), bytes_to_words(key, 4))    
    state[:] = words_to_bytes((a, b, c, d), 4)
Example #2
0
def invert_keyed_homomorphic_permutation(state, key, rounds=4):
    assert isinstance(state, bytearray), type(state)
    a, b, c, d = bytes_to_words(state, 4)
    
    key = key[:]
    for round in range(rounds + 1):
        key_schedule(key)
        
    a, b, c, d = invert_bit_permutation((a, b, c, d), bytes_to_words(key, 4))    
    invert_key_schedule(key)  
    
    for round in reversed(range(rounds)):            
        a, b, c, d = invert_mix_columns(a, b, c, d)
        b = rotate_right(b, 8, 32)
        c = rotate_right(c, 12, 32)
        d = rotate_right(d, 16, 32)
        
        a, b, c, d = invert_mix_columns(a, b, c, d)
        b = rotate_right(b, 4, 32)
        c = rotate_right(c, 8, 32)
        d = rotate_right(d, 12, 32)
        
        a, b, c, d = invert_mix_columns(a, b, c, d)
        b = rotate_right(b, 1, 32)
        c = rotate_right(c, 2, 32)
        d = rotate_right(d, 3, 32)
        
        a, b, c, d = invert_mix_columns(a, b, c, d)
                
        a, b, c, d = invert_bit_permutation((a, b, c, d), bytes_to_words(key, 4))
        invert_key_schedule(key)        
    state[:] = words_to_bytes((a, b, c, d), 4)
Example #3
0
def generate_public_key(private_key):
    """ Generate a public key, given the secret key of a symmetric homomorphic cryptosystem. 
        
        A public key consists of encryptions of the range of numbers 0-255, in order. 
        Encryption consists of (randomly) selecting numbers that sum to the value of the message (represented as an 8-bit byte)
        
        First, the integers 0-255 are encrypted using a linear secret key cipher to produce the pre-public key. 
        Then, the pre-public key is used to generate a second set of encryptions of the integers 0-255, using public key encryption.
        This second set is released as the public key.
        
        The pre-public key functions as a public key, but the ciphertexts provide a known plaintext attack on a linear cipher.
        The public key encryption technique is more secure then the linear cipher, and the resulting ciphertexts also 
         carry the homomorphic property. So they are suitable for use as a public key.
         
        - You can generate a new, random, valid public key from any other public key. """

    pre_public_key = []
    for byte in range(256):
        ciphertext = homomorphic_encrypt(byte, private_key)
        pre_public_key.append(bytes_to_words(ciphertext, 4))

    public_key = []
    for byte in range(256):
        message = bytearray()
        message.append(byte)
        ciphertext = encrypt(message, pre_public_key)[0]
        public_key.append(bytes_to_words(ciphertext, 4))
    return public_key
Example #4
0
def derive_public_key(private_key):  
    pre_public_key = []
    for byte in range(256):
        message = bytearray(8)
        message[0] = byte
        ciphertext = homomorphic_encrypt(message, private_key, bytearray(sha256(private_key + message + "pre_public").digest()))
        pre_public_key.append(bytes_to_words(ciphertext, 4))
        
    public_key = []
    for byte in range(256):
        message = bytearray()
        message.append(byte)        
        ciphertext = encrypt(message, pre_public_key, prng=lambda amount: random(amount, private_key, chr(byte)))[0] # encrypt returns a list with 1 ciphertext in it    
        public_key.append(bytes_to_words(ciphertext, 4))    
    return public_key
Example #5
0
def test_encrypt_decrypt():
    byte_size = 8
    data = bytearray(16 * byte_size)    
    key = bytearray(16 * byte_size)
    data[-1] = 1
    rounds = 16
    
    bit_size = byte_size * 8
    size = (bit_size, ((2 ** bit_size) - 1), bit_size - (3 * byte_size))
    data = bytes_to_words(data, byte_size)    
    key = bytes_to_words(key, byte_size)
    plaintext = data[:]

    encrypt(data, key, rounds, size)        
    print ''.join(bytes(integer_to_bytes(block, byte_size)) for block in data)
    print [byte for byte in data]
Example #6
0
 def encrypt(self, data, key, iv, size=(64, (2 ** 64) - 1, 40)):
     word64 = lambda _data: bytes_to_words(bytearray(_data), 8)
     output = word64(data)
     key += "\x00" * (128 - len(key))        
     key = word64(key)
     assert len(key) == 16, len(key)
     iv += "\x00" * (128 - len(iv))
     assert len(iv) == 128, len(iv)
     iv = word64(iv)
     assert len(iv) == 16, len(iv)
     encrypt(output, key, iv, size)
     return bytes(words_to_bytes(output, 8))
Example #7
0
def derive_public_key(private_key):
    pre_public_key = []
    for byte in range(256):
        message = bytearray(8)
        message[0] = byte
        ciphertext = homomorphic_encrypt(
            message, private_key,
            bytearray(sha256(private_key + message + "pre_public").digest()))
        pre_public_key.append(bytes_to_words(ciphertext, 4))

    public_key = []
    for byte in range(256):
        message = bytearray()
        message.append(byte)
        ciphertext = encrypt(
            message,
            pre_public_key,
            prng=lambda amount: random(amount, private_key, chr(byte)))[
                0]  # encrypt returns a list with 1 ciphertext in it
        public_key.append(bytes_to_words(ciphertext, 4))
    return public_key
Example #8
0
def generate_public_key(encryption_function, key):
    """ Generate a public key, given an encryption function and key that outputs ciphertexts that are partially homomorphic. 
        
        A public key consists of encryptions of the range of numbers 0-255, in order. 
        Encryption consists of (randomly) selecting numbers that sum to the value of the message (represented as an 8-bit byte)
 """
    public_key = []
    for byte in range(256):
        message = bytearray(
            8)  # we only need to encrypt 8 bits, but the data block is 64 bits
        message[0] = byte
        ciphertext = encryption_function(message, key)
        public_key.append(bytes_to_words(ciphertext, 4))
    return public_key
Example #9
0
def test_stream_cipher_diffusion():
    wordsize = 1
    size = generate_params_for_wordsize(wordsize)    
    seed = bytes_to_words(bytearray(16 * wordsize), wordsize)
    
    key = seed[:]
    seed2 = key[:]  
    seed3 = key[:]
    
    seed2[-2] = 1 
    seed3[-2] = 2
    data = seed[:]
    data2 = data[:]
    data3 = data[:]
        
    stream_cipher(data, seed, key, size)
    stream_cipher(data2, seed2, key[:15] + [1], size)
    stream_cipher(data3, seed3, key[:14] + [1, 0], size)
    
    _bytes = lambda _data: words_to_bytes(_data, wordsize)
    bits = lambda _data: ''.join(format(byte, 'b').zfill(8) for byte in _bytes(_data))
    
    print _bytes(data)
Example #10
0
def load_ciphertext(saved_ciphertext):
    output = []
    for entry in slide(bytearray(saved_ciphertext), BLOCKSIZE * 2):
        output.extend(bytes_to_words(entry, 2))
    return output
Example #11
0
def load_private_key(saved_private_key):
    return bytearray(bytes_to_words(bytearray(saved_private_key), 2))
Example #12
0
def load_public_key(saved_key):
    output = []
    for entry in slide(bytearray(saved_key), BLOCKSIZE * 2):
        output.extend(bytes_to_words(entry, 2))
    return output
Example #13
0
def load_ciphertext(saved_ciphertext):
    output = []
    for entry in slide(bytearray(saved_ciphertext), BLOCKSIZE * 2):
        output.extend(bytes_to_words(entry, 2))
    return output  
Example #14
0
def load_private_key(saved_private_key):           
    return bytearray(bytes_to_words(bytearray(saved_private_key), 2))
Example #15
0
def load_public_key(saved_key):
    public_key = []
    for line in slide(saved_key, 16):
        public_key.append(bytes_to_words(line, 4))
    return public_key
Example #16
0
def blockcipher32(key, m, rounds=1):
    key = bytes_to_words(bytearray(key), 4)
    m = bytes_to_words(bytearray(m), 4)[0]
    return words_to_bytes([_cic_blockcipher32_encrypt(key, m, rounds)], 4)
Example #17
0
def load_public_key(saved_key):    
    output = []
    for entry in slide(bytearray(saved_key), BLOCKSIZE * 2):
        output.extend(bytes_to_words(entry, 2))
    return output    
Example #18
0
def iv_generator(key, seed, wordsize=8, mask=(2 ** 64) - 1):
    state = bytes_to_words(seed, wordsize)    
    bit_width = wordsize * 8
    while True:
        permutation(state, key, mask, bit_width)          
        yield words_to_bytes(state, wordsize)