Weakish character switching, truncate-able obfuscation with a-z cypher text for niche uses
Edit: some people have gone spack that this is more obfuscation and ranted that I might unintentionally cause people to use this for something other than vaguely making trivial strings hard to read, so, if you don’t know what you’re doing, don’t use this ever. Also, try and use standard encryption libraries, this is for a very niche use in my work which I found vaguely interesting. Sorry for any confusion.
Most of the time if you want something securely transmitted or stored and you’re reasonably on the ball, you’d use something like the industry standard AES-256 or other rijndael-based cyphers. They have libraries in almost all known languages, are NSA-approved, and offer fairly trivial processing overheads these days on modern computers.
However, there are some occasions when something a little more basic or flexible is required. I work in a heterogeneous environment where the projects are written in Python, some legacy applications are in PHP, there’s a bit of C and the reporting is done by the analysts in Excel (natch…). This was actually written some two years ago, but yaknow, lazy and so on.
In one recent example we required data to be stored in a cookie which would be passed via a third party and sent back to us in a report. The catches being:
- The cookie could sometimes be randomly truncated
- The cookie was randomly force-lowercased
- We didn’t want anyone to see what was in the cookie
- We didn’t have any control over the third party to make them not be insane with cookies
- The cookie must be reasonably secure (not crazy standard, but above the ‘too much effort to bother to crack’ level and readable in Python, PHP and Excel
- Given the Excel reports might run into the 10million row region, it must be pretty fast
- It must handle all the characters in the standard ASCII range, including \n and so on
Ruh-roh. So, normal options such as UU or B64 encoding an AES encrypted string was right out, plus I’m not aware of any non-terrible and free ways to decrypt AES encrypted strings in Excel (not that I looked very hard) given that lowercasing it was going to break B64 and friends. We could have written a basic alphanumeric parser ourselves, but that would still probably be too slow in Excel to decrypt. Additionally, truncating the B64 encoded AES encrypted string would possibly make it unusable, if not awkward to decode. Requiring the cypher text to be truncate-able largely rules out anything that uses typical encryption methods.
After a few minutes getting angry at Excel, I went back to basics. The cookies were all going to be about 0-128 chars in length so I decided on the old fashioned and pretty secure one time pad cypher which comes from the WWII spy era with some tweaks with a key about the same length as the cookie would provide ample security. While true that if enough encrypted cookies were disclosed it might be possible to reverse engineer the data eventually as is the bane of all switched based cyphers, it’s certainly a computational challenge. Obviously those with any minor background in cryptography will spot the flaws in using such a simple cypher are that while OTP encryption is considered near unbreakable if used once (hence the ‘one time’ part) if you re-use the key repeatedly as we do in this example it’s possible to reverse engineer the key with enough samples of encrypted data.
This cypher is useful for anyone wishing to pass snippets of data over 3rd party networks where security is beneficial but not critical and the data might be truncated, off-the-top-of-head examples would include:
- Tracking data in cookies where the cookie gets mangled
- Affiliate network based information (links, IDs, so on, where the cookie gets mangled).
- Twitter, IRC etc. or other communication mediums with a maximum message length and/or truncation for fun (note: purely fun, it’s not safe for secure communication)
- Medium where the data is restricted to a very limited set of characters, in our example the cypher text is purely a-z lowercase and the message is trivial
Anyway, on to the very basic GCSE-level maths! Our example code accepts any standard ASCII characters as input. It represents any ASCII character as a number from 0-255 (the standard ASCII range), this of course can be represented by 16^2, which is what the cypher uses. This means that any ASCII character after the pad switch is represented by exactly two characters in the a-p range representing 0-15 (a = 0, p = 15). Two of these 0-15 characters together can easily be reversed into the full 0-255 representation of the ASCII character, and then displayed as the former character it represents, anyone with any coding background should of course see that this is what ord() and chr() do or their equivalents in your language of choice. In the middle of this process after the conversion from ASCII to a 0-255 integer has taken place, we just add the value of the relevant position of the key, which ‘shifts’ the value upwards, wrapping around to 0 if the shift takes the count past 255. The key is also represented as a-z the same as the cypher text. For example:
[h] [i] [ ] [t] [h] [e] [r] [e] is represented as the ASCII values 104 105 32 116 104 101 114 101 lets say we have a key of [b] [i] [s] [c] [u] [t] [s] [!] 98 105 115 99 117 116 115 33 some simple addition 104 105 32 116 104 101 114 101 98 105 115 99 117 116 115 33 + --------------------------------- 202 210 247 215 221 217 229 134 And so on...
As you should be able to see, it’s not possible to get the original “hi there” out of the cypher’d 202 210 247 215 221 217 229 134 without the key “biscuits!”, which would be used in the reverse (subtracting the values) to get the original values back out again. The only stage missing from this is the conversion of the 0-255 integers into two a-z characters, but this again is trivial. So anyway, there you have it. It’s all incredibly simple, but if you have a long enough key (as long as the data you’re encoding) it’s actually surprisingly secure. Insanely secure if you only use the key once. If the cypher text is truncated at all you just round the length to the nearest even positioned character and off you go, you lose some data but it doesn’t destroy the whole message. I also randomise the letters in the cypher text if g-p range with a 50% chance of adding 10 to the position (g becomes q, p becomes z, and so on) - this adds nothing to the security, it just makes the cypher text look more random than it is, because, well, shut up.
On to the code itself, you can grab a copy here, all three versions are BSD licensed, please respect the licence. If you use the code it would be really nice to have a link back to this post :) Note that this code uses /dev/urandom on *NIX for the seed and key genration, you can happily port this to Windows by editing the seed generation method, or just mashing the keyboard.
Just to wrap this massive post up, here’s some examples of using the PHP class, if you need help using the Python or Excel macros, this probably isn’t the code for you ;) Example in PHP:
1. Key (pad) generation:
// import the class
require_once('otpcrypto.php');
// create the instance
$crypto = new otpcrypto();
// generate a key (pad) of a set length (bytes)
// you only normally do this ONCE, and save the key
$key = $crypto->genkey(128);
echo "my random key is: {$key}";
2. Encrypting
// import the class
require_once('otpcrypto.php');
// create the instance
$crypto = new otpcrypto();
// set the key, stored somewhere (see step 1)
$crypto->setkey($key);
// set what we want encrypted
$crypto->setmessage('my quote securely encoded string!');
// perform the encryption
$crypto->encrypt();
// get the cypher text
echo $crypto->getcypher();
3. Decrypting:
// import the class
require_once('otpcrypto.php');
// create the instance
$crypto = new otpcrypto();
// set the key, stored somewhere (see step 1)
$crypto->setkey($key);
// set the encrypted cypher text
$crypto->setcypher('jguihgraehuogra.... etc.');
// perform the encryption
$crypto->decrypt();
// get the clear text message
echo $crypto->getmessage();
Example in Python:
Encrypting
from otpcrypto import otpcrypto
crypto = otpcrypto()
crypto.setkey(key)
crypto.setmessage('my quote securely encoded string!')
crypto.encrypt()
print crypto.getcypher()
… yeah you get the idea…
That about wraps it up, all the libraries work in much the same way, there’s no key generation in the Excel macro one, but that’s about it. There’s no real error throwing as such, but it’s trivial to add to the existing passive error trapping.
Hope you enjoy this very basic waddle into the world of very basic obfuscation of messages, and hope you find it useful if you’re in a similar situation to me.
@2 months ago#cookies #cypher #excel #one time pad #otp #php #python #affiliate

