Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Short & Sweet Encryption?

by inblosam (Monk)
on Jul 29, 2006 at 12:40 UTC ( [id://564520]=perlquestion: print w/replies, xml ) Need Help??

inblosam has asked for the wisdom of the Perl Monks concerning the following question:

I have a short string (8-12 characters) that I need encrypted, but I want the encrypted string to be as short as possible. It does not need to be secure, just needs to essentially hide the original string from the user. I've tried several different encryption algorithms like Crypt::Blowfish and Crypt::Simple, but they all create a huge and long encrypted string (like this: zL3BCn5IdDCkG8eCDhESvadH92FNoMbbCTB2Fu4Cq4ynsNHL+m+h8lbCa1NshUMf==).

I would also prefer it to be rather simple to implement.

Any ideas? Thanks!


Michael

Replies are listed 'Best First'.
Re: Short & Sweet Encryption?
by syphilis (Archbishop) on Jul 29, 2006 at 13:45 UTC
    If you need to be able to decrypt the the encrypted string back to to its original form you could just xor the string against a passphrase:
    use strict; use warnings; my $string = 'hello world!!'; my $passphrase = 'my passphrase'; my $encrypted_string = $string ^ $passphrase; print $encrypted_string, "\n"; my $decrypted_string = $encrypted_string ^ $passphrase; print $decrypted_string, "\n";
    Note: I'm assuming that when you said "it does not need to be secure" you really meant "it does not need to be secure".

    Cheers,
    Rob
      xor-ing is the method used by the One-Time pad, so to say that it's inherintly insecure is somewhat unfair. Also, you'd probably want to do something to bring the characters back into printable range, which you don't do above.

      thor

      The only easy day was yesterday

        To encode a high quality 4MP image, XOR requires a 17,000,000 bit (non-reusable) key. Other top ciphers require a 64 or 128 bit (reusable) key. XOR requires extra bits to compensate for its inherent insecurity.

        If your key management system is secure enough to exchange and store a key as big as the data to encrypt, why don't you the system to protect the plaintext instead of the key?

        xor-ing is the method used by the One-Time pad, so to say that it's inherintly insecure is somewhat unfair

        I would never say that. The only shortcoming of a properly constructed one-time pad is that it (or a copy of it) may fall into the wrong hands.

        Also, you'd probably want to do something to bring the characters back into printable range, which you don't do above

        I don't see any need to do that. (Apologies if I'm being dumb :-)

        Cheers,
        Rob
Re: Short & Sweet Encryption?
by rodion (Chaplain) on Jul 29, 2006 at 13:49 UTC
    It does not need to be secure,
    If it really doesn't need to be secure, merely a little obscure to discourage the curious and minimally motivated, you can get a quick and easy result in the same number of charactes, using just a little scrambling. Transform each character to a different character using tr///, and scramble the characters using an array slice. It should be fairly fast as well.

    Update: Here's a very simple code implementation if that's helpful.

    use warnings; use strict; my $in = 'Simpletestxy'; my $tr_ed = $in; $tr_ed =~ tr/A-Za-z1-9/1-9a-zA-Z/; #complicate and add chars to the tr/// as you wish # 0 1 2 3 4 5 6 7 8 9 10 11 my $out = join '',(split '',$tr_ed)[qw(5 6 4 2 9 10 3 7 11 1 8 0)]; my $back = join '',(split '',$out )[qw(11 9 3 6 2 0 1 7 10 4 5 8)]; $back =~ tr/1-9a-zA-Z/A-Za-z1-9/; print "in=$in, tr_ed=$tr_ed, out=$out, back=$back\n";

    2nd Update: Xor with a pass phrase as syphilis uses can be used instead of the tr/// step in the code above, it's another way of doing and expressing the translation. Use of tr/// has an advantage if you want the $output confined to printable characters, otherwise, just decide which is easier for you to read.

Re: Short & Sweet Encryption?
by jcoxen (Deacon) on Jul 29, 2006 at 13:28 UTC
    You might want to try Bruce Schneier's Solitaire cryptosystem - you'll find a link to perl sourcecode near the top of the page. It's not totally secure as you'll read on his site but it does do fairly good encryption and doesn't add appreciably to the length of the encrypted string. On a quick test run, plain text was 439 characters long and encrypted text was 457 characters long. A shorter 16 character plain text was encrypted into a 19 character string. The program does spit out the encrypted text in 5 character groups but a simple join statement will fix that.

    BTW, you'll also find reference to Neal Stephenson's novel Cryptonomicon. If you haven't read it (and the prequel System of the World series), do yourself an favor and get them. You won't be sorry.

    Hope this helps,

    Jack

    UPDATE Since Solitaire is emulating a standard deck of 52 cards, this gives you double the 26 letter English alphabet. Because of this, the program as written doesn't handle numbers, punctuation or special characters. Those characters are dropped/ignored.

Re: Short & Sweet Encryption?
by shmem (Chancellor) on Jul 29, 2006 at 16:19 UTC
    You could use Crypt::Twofish2. The produced encrypted strings are multiple of 16 Bytes of length.

    To convert the encrypted text to printable chars, you have to uuencode (or base64 encode) it. Example:

    use Crypt::Twofish2; use MIME::Base64; $cipher = new Crypt::Twofish2 "a" x 32, Crypt::Twofish2::MODE_CBC; my $text = "random text!"; print length($text),": $text\n"; # make text a multiple of 128 bit $text .= " " x (16 - length($text) % 16); $crypted = encode_base64($cipher->encrypt($text)); print length($crypted),": $crypted\n"; __END__ 12: random text! 25: ZA5yODJpIrGnOXpzt3hDVQ==
    Short enough and (somewhat)secure (well, the above aa.. cipher is silly :-)

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

      In case someone thinks "It's Twofish, so it must be secure.", the parent's solution doesn't use salting, so you don't get the full security of Twofish. In fact, it's severly weakened. (Also, you might want to use a key other than "a" x 32.) My Blowfish solution has the same limitation.

Re: Short & Sweet Encryption?
by ikegami (Patriarch) on Jul 29, 2006 at 17:40 UTC

    The following will encrypt strings of up to 15 bytes in length into strings of 22 URL-safe bytes.

    There is no salting and no chaining, so a lot of security is missing. Do not use this to hide any critical information. Do no use the key used here for anything else.

    It is, however, as strong as any other solution in this thread, results in two fewer bytes than the other equally strong contender, and can encode arbitrary data (including nuls and spaces).

    # Encrypter use Crypt::Blowfish (); use MIME::Base64 qw( encode_base64 ); my $key = ...; my $plaintext = ...; die("Text to encrypt must be less than 16 bytes long\n") if length($plaintext) >= 16; my $cipher = Crypt::Blowfish->new($key); my $padded_plaintext = pack('Ca15', length($plaintext), $plaintext); my $ciphertext1 = $cipher->encrypt(substr($plaintext, 0 +, 8)); my $ciphertext2 = $ciphertext1 ^ $cipher->encrypt(substr($plaintext, 8 +, 8)); my $ciphertext = $ciphertext1 . $ciphertext2; my $websafe_ciphertext = substr(encode_base64($ciphertext, ''), 0, -2) +;
    # Decrypter use Crypt::Blowfish (); use MIME::Base64 qw( decode_base64 ); my $key = ...; my $websafe_ciphertext = ...; die("Text to decrypt must be exactly 22 bytes long\n") if length($plaintext) != 22; my $cipher = Crypt::Blowfish->new($key); my $ciphertext = decode_base64($websafe_ciphertext.'=='); my $ciphertext1 = substr($plaintext, 0, 8); my $ciphertext2 = substr($plaintext, 8, 8); my $padded_plaintext = $cipher->decrypt( $cyphertext1) . $cipher->decrypt($ciphertext1 ^ $cyphertext2); my $plaintext = unpack('C/a*', $padded_plaintext);

    Untested.

    Update: Now uses chaining.

      Above code contained a couple of spelling misstakes, which I've taken the liberty of correcting.

      Also, is there a way to get this approach to work with an arbitrary length plaintext? I.e. with plaintexts more than 16 character in length?

      # Encrypter use Crypt::Blowfish (); use MIME::Base64 qw( encode_base64 ); my $key = ...; my $plaintext = ...; die("Text to encrypt must be less than 16 bytes long\n") if length($plaintext) >= 16; my $cipher = Crypt::Blowfish->new($key); my $padded_plaintext = pack('Ca15', length($plaintext), $plaintext); my $ciphertext1 = $cipher->encrypt(substr($padded_plain +text, 0, 8)); my $ciphertext2 = $ciphertext1 ^ $cipher->encrypt(substr($padded_plain +text, 8, 8)); my $ciphertext = $ciphertext1 . $ciphertext2; my $websafe_ciphertext = substr(encode_base64($ciphertext, ''), 0, -2) +; # Decrypter use Crypt::Blowfish (); use MIME::Base64 qw( decode_base64 ); my $key = ...; my $websafe_ciphertext = ...; die("Text to decrypt must be exactly 22 bytes long\n") if length($websafe_ciphertext) != 22; my $cipher = Crypt::Blowfish->new($key); my $ciphertext = decode_base64($websafe_ciphertext.'=='); my $ciphertext1 = substr($ciphertext, 0, 8); my $ciphertext2 = substr($ciphertext, 8, 8); my $padded_plaintext = $cipher->decrypt( $ciphertext1) . $cipher->decrypt($ciphertext1 ^ $ciphertext2); my $plaintext = unpack('C/a*', $padded_plaintext);
        Yes, use Crypt::Blowfish via Crypt::CBC. That's how it should always be done. It's even relatively much more simple. I used Crypt::Blowfish directly above to attain the specific goals requested by the OP at the cost of reduced security, placing limits on the size of the input and having to do some of CBC's job myself.
        spelling misstakes
        s/misstakes/mistakes/
Re: Short & Sweet Encryption?
by planetscape (Chancellor) on Jul 29, 2006 at 13:00 UTC

    Sounds like you want a hash (in the crypto sense). I suggest searching CPAN for hash modules, and focusing on the crypt and digest-type beasties. An alternate search to try would be hash.

    HTH,

    Update: Clarified the wording just a bit...

    planetscape

      It should be noted that a hash would prevent the OP from decrypting the message. If [s]he wants to be able to decrypt it, then a hash isn't suitable for the task.

      Update: s/It/If/; Fixed square brackets.

      --
      David Serrano

        Ack! Indeed, true. I should have inquired further into the OP's requirements before making that suggestion. Kudos to you for catching my oversight.

        planetscape
Re: Short & Sweet Encryption?
by revdiablo (Prior) on Jul 29, 2006 at 15:15 UTC

    Another simple option is to pack the string into UUE. As with some of the other answers, this provides extremely limited security (bordering on none at all), it merely obscures the text. It doesn't seem to add too much length of the messages I tested. Example:

    my $msg = pack "u", "Secret message that is not so secret"; print "Obscured: $msg"; print "Plain: ", unpack("u", $msg), "\n";
Re: Short & Sweet Encryption?
by GrandFather (Saint) on Jul 29, 2006 at 18:54 UTC

    While there are plenty of ideas, you really haven't given enough information for us to provide a good focused answer.

    Some questions you should answer to help get a focused answer:

    1. can you generate and send sufficiently securely unique keys?
    2. does the user have access to your source code?
    3. is the plain text "printable"?
    4. need the cypher text be printable?
    5. does the user need to transcribe the cypher text?
    6. does the cypher text need to be self validating (include a check sum or some such)?

    It may be worth noting that if you have a source of unique keys of the same length as the plain text and a secure way to transmit the keys to the recipient of the encrypted string then you can use a one time pad technique. A one time pad is absolutly unbreakable without the key and is pretty simple to implement - just xor the plain text with the key text. Xor the cypher text with the key text to get the plain text back. The down side is that the cypher text will very likely not be printable.


    DWIM is Perl's answer to Gödel
Re: Short & Sweet Encryption?
by Withigo (Friar) on Jul 30, 2006 at 04:20 UTC
    Since you say true security is not needed, just casual security, and you want to shorten strings, perhaps you might be better off compressing your string. A compressed string obviously will not be human readable, so it is effectively "encrypted" for most intents and purposes.
    Algorithm::Huffman , and Archive::Zip would be good places to start.
      And if you add a junk prefix, people won't be able to decompress the string if they don't remove the junk prefix first.
      Algorithm::Huffman , and Archive::Zip would be good places to start.
      I'd recommend Compress::Zlib, which is the actual compressor behind Archive::Zip.
        I would limit that to "it will take a little work to decompress the string" or "some people won't be able to decompress the string". It would only take a very slightly sophisticated attacker to bypass that, and it's primarily a security-by-obscurity approach. It may be better than nothing, but it certainly shouldn't be regarded as the same level of security as using a modern encryption algorithm.
Re: Short & Sweet Encryption?
by diotalevi (Canon) on Jul 31, 2006 at 15:46 UTC
Re: Short & Sweet Encryption?
by TedPride (Priest) on Jul 30, 2006 at 17:11 UTC
    My guess is that this is just for some sort of email verification system, where 99% of the users won't have the knowledge and/or patience to break your code, and the few that do won't matter because it's easier to get a new bogus email account than break the code. In this case, a one-way digest will probably work fine (I'd use MD5-hex, trimmed to whatever length is necessary), and if you're concerned that this will make things too easy, just store an (expiration) timestamp in your database as well as user name and encrypt on that too. Then if someone fails more than a few times when "clicking" the link, auto-ban his IP.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://564520]
Approved by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (4)
As of 2024-03-29 13:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found