<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>Snipplr - weilawei</title>
<link>http://snipplr.com/users/weilawei/tags/hashing</link>
<description>Recent snippets posted on Snipplr.com</description>
<language>en-us</language>
<pubDate>Fri, 24 May 2013 07:24:44 GMT</pubDate>
<item>
<title>(Python) All-Or-Nothing Transform</title>
<link>http://snipplr.com/view/64825/allornothing-transform/</link>
<description><![CDATA[ <p>Performs an all-or-nothing transform on a stream of chunks. The data can only be decrypted if every block is present to generate an HMAC for. The list of HMACs is then XOR'd against the final block from the transform, yielding the decryption key for the blocks.

Reports a hash of the encrypted chunk for storage/retrieval without needing to calculate HMAC until decryption.

Needs a lot of cleanup and some fixes. Makes a lot of assumptions, for instance, that `current_block`, `total_blocks`, and `data_size` only occupy 1 byte apiece. Currently doesn't strip padding after decoding, and doesn't convert original integers for `current_block`, `total_blocks`, and `data_size` back from `bytes`. Does a ton of extra work (conversions between `bytes` and `bytearray`).

**NOTE**: I removed code that verified the HMACs of the final block and each encrypted block to simplify the code, because you already need the correct HMACs to get the block key from the final block, and the block hashes are taken of the blocks encrypted with the block key.

**NOTE 2**: The incrementing counter typically XOR'd with the plaintext blocks is actually prepended (`chunk() `returns blocks of the format `[current_block, total_blocks, data_size, data[a_block] (and for the last data block, + (padding_size * padding))]`.

**NOTE 3**: In this scheme, if you scatter the encrypted blocks, final blocks, lists of hashes of encrypted blocks and final blocks,  and HMAC secret keys amongst a minimum of 4 parties, no single party can possibly decrypt the content, short of attacks on the encryption and hashing algorithms themselves, eavesdropping on other communications, impersonating another node (to acquire the other pieces illegitimately), etc.. Additionally, each node should be able to plausibly deny knowledge of the contents of their node, if they restrict their own access to the other necessary pieces.

The encrypted block server node has neither of the necessary keys to either decrypt the blocks or to derive their decryption key by generating their HMACs--even if it did, it would have no final blocks from which to recover the decryption key. 

The final block server node has no encrypted blocks to decrypt, no awareness of which encrypted blocks belong to which final blocks, no HMAC secret key to derive the decryption key for the final block--and no encrypted blocks to perform an HMAC on. 

The "location" server node has the regular hashes of the encrypted blocks and their corresponding final blocks (unless the file is secret). It has no HMAC secret key, nor the encrypted blocks, nor the final block or inner key. It could recover all but the HMAC secret key, so caution should be exercised with this node, for it should never come into possession of the HMAC secret key.

Finally, the one person who can recover the plaintext content should have the HMAC secret key and the hash of the list of hashes (of all blocks). To recover the plaintext, this person asks the location node for the list of hashes matching their hash. They then ask the encrypted block nodes for the blocks matching all but the last hash in the list. They perform an HMAC, using their secret key, on each of the blocks. They request the final block by its hash from the final block node, and XOR each HMAC with the final block, producing the block decryption key. Finally, they decrypt each block.

__This module does **not** demonstrate scattering the parts of an AONT.__ In this example, everything resides within the local machine, in the currently running process.

**NOTE 4**: I seem unable to swap any blocks (excluding the last blocks) and still maintain correct decryption. However, the block key decrypts correctly, so the HMACs must be generated correctly, despite not verifying them explicitly. From my  understanding of the algorithm, I should be able to swap or shuffle the blocks (as they are encrypted separately) and still decrypt them. Ideas/corrections welcome.

**NOTE 5**: Dependencies:

- [PyCrypto](https://www.dlitz.net/software/pycrypto/)
- [`hmac`](http://snipplr.com/view/64824/hmac/)
- [`stream`](http://snipplr.com/view/64823/chunk-data-for-streaming/)</p> ]]></description>
<pubDate>Wed, 09 May 2012 05:10:32 GMT</pubDate>
<guid>http://snipplr.com/view/64825/allornothing-transform/</guid>
</item>
<item>
<title>(Python) A Clueless Agent Generator for Python 3.2</title>
<link>http://snipplr.com/view/64801/a-clueless-agent-generator-for-python-32/</link>
<description><![CDATA[ <p>This is an implementation of a clueless agent generator which creates self-decrypting clueless agents as described in "Environmental Key Generation towards Clueless Agents" by  J. Riordan and B. Schneier.

It requires Python 3.2 and PyCrypto of a recent build (tested with 2.4 and higher).

To use, pass a python file (or other file) to be encrypted, followed by a series of "observations" on the command line. These observations are hashed to yield the encryption key. A signature is generated by hashing the key, and this signature will be expected to be present in the target environment. Pipe the resulting agent to a file or see the agent code directly on stdout.  Additionally, there is an is_debug flag that can be specified (see the source) or tweaked in the resulting agent, to be more verbose.

To attempt decryption/execution of a clueless agent, simply run the generated python script (agent) and pass a set of observations on the command line. If the hash of the hash of the observations match the signature, the hash of the observations will be used as the decryption key. If the signature does not match, the agent will exit with no output.

The code previously directly exec()'d the resulting code, however, it simply outputs to stdout now. The resulting code would otherwise execute directly in-line, at that location in the program, which has many undesirable consequences. Piping it to a file and executing, piping it to a memory-backed temporary file and executing it, or placing the resulting code directly in memory afterward and then executing it, are all ways to run the code contained within. This makes it fundamentally little different from encrypting a file directly, except that the key is environmentally generated, perhaps by a daemon that feeds environmental observations on the command line to the agent.

Note, you can encrypt more than Python scripts, and agents can be made to contain themselves.

$ ./agent_generator.py plaincode.py 0 > cipheragent.py

$ ./agent_generator.py cipheragent.py some more observations > double_agent.py

$ ./double_agent.py wrong observations

--nothing here--

$ ./double_agent.py some more observations > cipheragent_2.py

--cipheragent_2.py now holds the same content as cipheragent.py--

$ ./cipheragent.py 0 > plaincode_2.py

--plaincode_2.py now holds the same content as plaincode.py--

$ ./plaincode_2.py

--should yield the same as--

$ ./plaincode.py</p> ]]></description>
<pubDate>Mon, 07 May 2012 00:01:14 GMT</pubDate>
<guid>http://snipplr.com/view/64801/a-clueless-agent-generator-for-python-32/</guid>
</item>
</channel>
</rss>