7

I am trying to implement a simple string encoder to obfuscates some parts of a URL string (to prevent them from getting mucked with by a user). I'm using code nearly identical to the sample in the JCA guide, except:

  • using DES (assuming it's a little faster than AES, and requires a smaller key) and
  • Base64 en/decoding the string to make sure it stays safe for a URL.

For reasons I can't understand, the output string ends up with linebreaks, which I presume won't work. I can't figure out what's causing this. Suggestions on something similar that's easier or pointers to some other resources to read? I'm finding all the cryptography references a bit over my head (and overkill), but a simple ROT13 implementation won't work since I want to deal with a larger character set (and don't want to waste time implementing something likely to have issues with obscure characters i didn't think of).

Sample input (no line break):

http://maps.google.com/maps?q=kansas&hl=en&sll=42.358431,-71.059773&sspn=0.415552,0.718918&hnear=Kansas&t=m&z=7

Sample Output (line breaks as shown below):

GstikIiULcJSGEU2NWNTpyucSWUFENptYk4m5lD8RJl8l1CuspiuXiE9a07fUEAGM/tC7h0Vzus+
jAH6cT4Wtz2RUlBdGf8WtQxVDKZVOzKwi84eQh2kZT9T3KomlnPOu2owJ/2RAEvG+QuGem5UGw==

my encode snippet:

final Key key = new SecretKeySpec(seed.getBytes(), "DES");
final Cipher c = Cipher.getInstance("DES");
c.init(Cipher.ENCRYPT_MODE, key);
final byte[] encVal = c.doFinal(s.getBytes());
return new BASE64Encoder().encode(encVal);
VC.One
  • 14,790
  • 4
  • 25
  • 57
milletron
  • 370
  • 1
  • 5
  • 11
  • 1
    did you try to just revert your encoding op and see if it works ? – Snicolas Apr 23 '12 at 14:34
  • where does that BASE64Encoder class come from? – leonbloy Apr 23 '12 at 14:38
  • 1
    @leonbloy I was importing sun.misc.BASE64Decoder, which I've found thanks to [this post](http://stackoverflow.com/questions/2267036/work-sun-misc-base64encoder-decoder-for-getting-byte) is not a good idea. – milletron Apr 23 '12 at 15:30
  • For reference, if you wish to avoid the apache-commons implementation, there's another lightweight, open source implementation at http://www.source-code.biz/base64coder/java/ – milletron Apr 24 '12 at 19:21

4 Answers4

14

Simply perform base64Str = base64Str.replaceAll("(?:\\r\\n|\\n\\r|\\n|\\r)", "") on the encoded string.

It works fine when you try do decode it back to bytes. I did test it several times with random generated byte arrays. Obviously decoding process just ignores the newlines either they are present or not. I tested this "confirmed working" by using com.sun.org.apache.xml.internal.security.utils.Base64 Other encoders not tested.

PatlaDJ
  • 1,226
  • 2
  • 17
  • 31
8

Base64 encoders usually impose some maximum line (chunk) length, and adds newlines when necessary. You can normally configure that, but that depends on the particular coder implementation. For example, the class from Apache Commons has a linelength attribute, setting it to zero (or negative) disables the line separation.

BTW: I agree with the other answer in that DES is hardly advisable today. Further, are you just "obfuscating" or really encrypting? Who has the key? The whole thing does not smell very well to me.

leonbloy
  • 73,180
  • 20
  • 142
  • 190
  • It really is more obfuscating than encrypting. Just using a hardcoded string as a "key" in the calling class (which is shared by the servlets generating and consuming the obfuscated urls). Thanks for the linelength lead, also pointed out by @Jerry Coffin – milletron Apr 23 '12 at 15:35
  • Since the Apache Commons encoder states "... it is hard-coded to only encode/decode character encodings which are compatible with the lower 127 ASCII chart", this won't work any since I'd have characters outside this range. Going to need to rethink this whole approach, me thinks. – milletron Apr 23 '12 at 15:41
  • "this won't work any since I'd have characters outside this range": read carefully: it works with characters outside ASCII, it's just that the binary encoding cannot be utf-16, but it can be utf-8, or iso-8859-1, etc – leonbloy Apr 23 '12 at 15:45
  • if it's just a matter of obfuscation or urls, I'd consider some simple XOR encryption (followed by base64) – leonbloy Apr 23 '12 at 15:50
4

import android.util.Base64;

...

return new BASE64.encodeToString(encVal, Base64.NO_WRAP);

user2955935
  • 311
  • 3
  • 8
1

Though it's unrelated to your actual question, DES is generally slower than AES (at least in software), so unless you really need to keep the key small, AES is almost certainly a better choice.

Second, it's perfectly normal that encryption (DES or AES) would/will produce new-line characters in its output. Producing output without them will be entirely up to the base-64 encoder, so that's where you clearly need to look.

It's not particularly surprising to see a base-64 insert new-line characters at regular intervals in its output though. The most common use for base-64 encoding is putting raw data into something like the body of an email, where a really long line would cause a problem. To prevent that, the data is broken up into pieces, typically no more than 80 columns (and usually a bit less). In this case, the new-lines should be ignored, however, so you should be able to just delete them, if memory serves.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111