I want to know if AFsplit
(random_data_input, stripes, digestmod=sha)
output is indistinguishable from random data.
The attacker only has access to AFsplit
output data.
EDIT: This question is too vague as the answer depends on the randomness hypothesis taken about random_input_data
. Take care of it reading the proposed answers.
The purpose is to use this function in a deniable encryption implementation.
About AFsplit: AFsplit provides a security against forensic attacks on disk bad blocks. AFsplit splits data among several disk blocks so that if a block is put in reserved "bad block" area, it doesn't contain a complete sensitive information (particularly, a revoked key slot). LUKS uses AFsplit to store the key slots.
Note: I'm not speaking of LUKS itself that is, of course, a plain header. I just want to focus on this particular function.
Below is AFsplit Python implementation:
import sha, string, math, struct
from Crypto.Util.randpool import RandomPool
from Crypto.Cipher import XOR
def _xor(a, b):
"""Internal function to performs XOR on two strings a and b"""
xor = XOR.new(a)
return xor.encrypt(b)
def _diffuse(block, size, digest):
"""Internal function to diffuse information inside a buffer"""
# Compute the number of full blocks, and the size of the leftover block
full_blocks = int(math.floor(float(len(block)) / float(digest.digest_size)))
padding = len(block) % digest.digest_size
# hash the full blocks
ret = ""
for i in range(0, full_blocks):
hash = digest.new()
hash.update(struct.pack(">I", i))
hash.update(block[i*digest.digest_size:(i+1)*digest.digest_size])
ret += hash.digest()
# Hash the remaining data
if padding > 0:
hash = digest.new()
hash.update(struct.pack(">I", full_blocks))
hash.update(block[full_blocks * digest.digest_size:])
ret += hash.digest()[:padding]
return ret
def AFSplit(data, stripes, digestmod=sha):
"""AF-Split data using digestmod. Returned data size will be len(data) * stripes"""
blockSize = len(data)
rand = RandomPool()
bufblock = "\x00" * blockSize
ret = ""
for i in range(0, stripes-1):
# Get some random data
rand.randomize()
rand.stir()
r = rand.get_bytes(blockSize)
if rand.entropy < 0:
print "Warning: RandomPool entropy dropped below 0"
ret += r
bufblock = _xor(r, bufblock)
bufblock = _diffuse(bufblock, blockSize, digestmod)
rand.add_event(bufblock)
ret += _xor(bufblock, data)
return ret
not knowing random_data_input
, so one has to assumerandom_data_input
can also be non-random and cryptanalytically check AFSplit output. I hope my edit clarifies the point you're missing in your "yes" conclusion. – e-sushi Aug 18 '17 at 21:56random_data_input
implied input data was indistinguishable from user data, I've made it more clear. If it is not random then AFsplit output isn't and that's what you demonstrate. AFsplit is commonly used (by LUKS) to split a randomly-generated key, hence this hypothesis on random input data. – KrisWebDev Aug 19 '17 at 09:22