# ASCII to same-length ASCII encryption?

I need to encrypt an ASCII string [a-zA-Z0-9:] to an ASCII [a-zA-Z0-9] string of the same length. It doesn't have to be unbreakable, it's sufficient that it won't be readable at the first sight. The purpose is to encrypt my WiFi hotspot name with a key so that only my friends holding the key can decrypt a message from the hotspot name.

I might need XOR encryption that will guarantee that the output will be ASCII. Or I can simply have a numeric key and add the corresponding key number to each ASCII code of the char of the hotspot name.

What would you suggest?

• That's the job of format-preserving encryption. You won't get recommendation here for weak solutions, and seldom for ready-made tools. As an aside: is the : only in the source set a typo?
– fgrieu
Commented Jan 20, 2014 at 10:21
• I've just came across the Vernam cipher. I'll just shift every letter by random number inside my own "alphabet" [a-zA-Z0-9:] and it should be ok. Please let me know if it's a bad idea. Commented Jan 20, 2014 at 12:29
• Why does it have to preserve the length? Commented Jan 20, 2014 at 23:26
• @fgrieu It seems you will get recommendations here for weak solutions, but we'll downvote them to -10. Commented Jan 21, 2014 at 0:12
• @PetrB I'm having problems understanding the purpose of your approach? You would have to tell your friends the weak key used right? Maybe a dumb question, but your friends using your wifi hotspot should be somewhere quite close to you and why don't you just use a random ASCII string and just tell only them? Commented Jan 21, 2014 at 6:58

I don't really know what the point of this but I think that's already covered in the comments above.

So, about your Vernam cipher resp. One-Time-Pad: The "trick" of the OTP - and we can prove mathematically that it is secure - is that the key has to have the same length as the cipher text and also we assume the key was send over a secure channel (what ever that is), i.e. the attacker does not know anything about the key. The key is usually created using a PRNG/TRNG and needs to have good random properties. Therefore, no assumption about the next bit in the key can be made.

The problem with your ASCII premise is that when you use XOR and for example you have the letter A (0x41) and the corresponding key byte is a (0x61) you encrypted byte is SPACE (0x20). So, XOR will very likely give you a non-printable character or a character that is not in you list.

One thing you could do is security through obscurity. Since you won't find a really secure mechanism for you purpose (and I don't think you need a "really secure" mechanism for your purpose), you think up you own algorithm and write a small script to share it with your friends. But, you need to take care yourself and trust your friends that they won't share the knowledge.

One example I could think off:

1. Make an array with your alphabet

array = {a...z, A..Z, 0...9}


therefore the character relate to some index

a => 0
A => 26

2. Create a key out of these characters and shift each character in the plain-text (inside this alphabet), the number of shifts is the index of the corresponding character in the key.

Maybe add some weird/mixed stuff and you are good to go.

• Ok, that's a great summary. You pointed out exactly the idea I came up with (thank you for explaining STO term) and I think for my purpose it will be sufficient. One would have to decompile my Android code to find out the algorithm and the key. Commented Jan 23, 2014 at 12:07
• You are welcome ;) If you need any more help feel free to write a PM. And please mark my answer resp the thread as answered. Commented Jan 23, 2014 at 22:12

I need to encrypt an ASCII string [a-zA-Z0-9:] to an ASCII [a-zA-Z0-9] string of the same length.

The pigeonhole principle can be used to explain why it is not possible to encrypt every 15-character string from some set of sixty-three characters into an encrypted 15-character string from a set of sixty-two characters.

I need to encrypt an ASCII string [a-zA-Z0-9:] to an ASCII [a-zA-Z0-9] string; it's OK if the encrypted string is slightly longer.

There are a huge variety of ways to do this. Off the top of my head, I might consider:

• replace each ":" in the plaintext with "_"
• decode the plaintext string from "base64url" encoding into a series of octets (which probably include some unprintable octets)
• encrypt the series of octets using practically any implementation of practically any encryption algorithm, using the secret key that you have (somehow) distributed.
• encode the ciphertext octets using any "base32" encoding.
• The result is ciphertext that only uses 32 printable ASCII characters, but is slightly longer -- six-fifths the size of the original text if you pick a "length preserving" algorithms, somewhat longer if you pick an algorithm like salted AES encryption with an authentication code.

I need to encrypt an ASCII string [ A-Za-z0-9-_ ] to an ASCII [ A-Za-z0-9-_ ] string of the same length.

Forcing the ciphertext to be exactly the same length as the plaintext makes a system less secure than one that has room for an initialization vector, an authentication code, etc.

Ah, the "base64url" character set. With a character set that is a power of 2, you can use pretty much any implementation of any "length preserving" algorithm, including the Vernam XOR one-time-pad cipher you mentioned and the Vernam modular addition one-time pad.

To encode a string using a Vernam XOR one-time pad, pull a fresh never-been-used page from your one-time pad. For each character in your message: decode the character into a 6-bit number 0..63, XOR that character with the corresponding 6 bits from your one-time pad, then encode the resulting number (which will also be in the range 0..63), to the corresponding character in the 64-character set. Then eat or burn that page from your one-time pad, forcing you to use a different page for your next message. Other encryption algorithms don't require you to consume your secret key, and so are often easier in practice.

I need to encrypt an ASCII string [A-Za-z0-9] to an ASCII [A-Za-z0-9] string of the same length. I need all these characters in the plaintext, and I can't use any other characters or punctuation in the ciphertext.

Forcing the ciphertext to be exactly the same length as the plaintext makes a system less secure than one that has room for an initialization vector, an authentication code, etc.

Ah, format-preserving encryption with a 62-character set. Most encryption algorithms -- including Vernam XOR -- don't work with such a restriction. However, a few stream ciphers including modular addition one-time pad can handle such a character set.

To encode a string using a Vernam modular addition one-time pad, pull a fresh never-been-used page from your one-time pad (or generate the next derived block from your stream cipher). If your keyblock has been generated by throwing a pair of dice or flipping an array of 6 coins, cross out and ignore any values of 62 or greater, so we have values 0..61 of equal probability.

For each character in your message: decode the character into a number 0..61, add that character to the corresponding number 0..61 from your derived block -- subtracting 62 if the result is too big, so the final result is in the range 0..61. Then encode the final result to the corresponding character in the 62-character set. Then eat or burn that page from your one-time pad, forcing you to use a different page for your next message. Other encryption algorithms don't require you to consume your secret key, and so are often easier in practice.

(The GROMARK and Gronsfeld ciphers resemble Vernam modular addition, except using a smaller range of values of 0..9 rather than 0..25 or 0..61, and so are less secure but much easier to use).

(The ROT13 cipher is even easier to use, but provides practically no cryptographic security).

p.s.: Isn't a SSID typically 32 characters?

• Great answer - covering any possibility of what might actually have been being asked, and helped me a lot :) Commented Aug 3, 2014 at 1:51