« Little League | Main| "Quick and dirty" field maps with LotusScript lists »

ASCII and Atbash Ciphers

Category domino
A while back I read The Da Vinci Code, primarily to see what all the fuss was about. Although a few elements become a bit repetitive as the story unfolds, on the whole it's fairly well written. I failed to see why it was so controversial, being fiction, even if it did portray the Catholic Church in a rather negative light. Then again, I've always found it odd that the more convinced someone claims to be about the absolute truth of a given belief, the more likely they are to feel threatened by the slightest implication that their belief is untrue.

I read the book again recently, and for grins, thought I'd try programming a variation on one of the ciphers discussed - namely, the Atbash substitution. For those of you who haven't read the book (and haven't already encountered this cipher elsewhere), a quick summary is that it's encoded / decoded by splitting the Hebrew alphabet in half, reversing the order of the second half, and replacing each character with its equivalent in the other half. In other words, by applying the same rule to the English alphabet, A = Z, B = Y, C = X, and so on.

When I started designing a LotusScript version of Atbash using the English alphabet, it became obvious that the "easiest" approach would be a simple Select Case block with 26 cases (i.e. Case "A": strEncodedChar = Z), but I immediately saw two limitations of this approach:
  1. The string comparison would either have to be case insensitive (i.e. A = a) or would in fact have to have 52 possibilities... yes I know, English homonyms make this particular limitation ironic.
  2. It's not as efficient as it could be; a given character would require up to 52 string comparisons before the substitution character could be determined.
This reminded me of some code I'd written about four years ago for incrementing ASCII characters. Originally I was going to use the approach above, but a friend of mine suggested a far more efficient one. Obviously you can't just add 1 to A... that's a type mismatch. But you can add 1 to 65, which is where the Asc() and Chr() functions come in handy. At the time, I had long since gotten used to using Chr(9) and Chr(13) to insert tabs and carriage returns, respectively, but had never needed to know that you can also convert a character back to a number using Asc(). Every ASCII character has a corresponding Long value between 0 and 255. Asc("A"), for example, returns 65. And, of course, you can add 1 to 65. Because Asc("B") returns 66, Chr(66) returns "B". Problem solved. This breaks after "Z", because Chr(91) returns a left bracket. So we expanded the function to account for remainders - if incrementing the original character caused the limit to be exceeded, then a new character is prepended to the string and the current character resets to "A". Benchmarking of this approach showed it took less time to increment "TRIPCONY" twice (to "TRIPCONZ", then to "TRIPCOOA") than to increment "Y" to "Z" using the 26-condition @If that the previous author's formula code had used. Simultaneously more efficient and more scalable.

So I decided to apply that approach to my little Atbash experiment, but figured while I'm at it, why settle for using only the alphabet? If I did, I'd have to include all sorts of logic for retaining punctuation and other special characters. So instead I chose the first character that should be encoded (an exclamation point) and the last (a tilde) and determined a halfway point between the two. The code simply ignores any characters that fall outside of that range (i.e. spaces, tabs, carriage returns) and encodes the rest. The result is complete gibberish. And the convenient thing about this style of cypher is that there's no need to write a different script to reverse the process: encoding the encoded string returns the decoded string.

Offhand, I can't think of a practical use for this, but it was a fun brain exercise (I find I often need those on weekends to keep the ol' neurons limber), and I'm donating it in case any of you have a need for something like this. A link to the code is available below. You'll also need to download Julian's StringBuffer class if you haven't already, because I opted to use that to store the encoded string instead of using less efficient traditional string concatenation.

And so I leave you with a bit of sentimentality... happy ciphering.

F0* 2*,+ -:2:2=:- +76,e
^ 46,, 6, ,+633 > 46,,s
^ ,687 6, 5*,+ > ,687q
K7: 9*1;>2:1+>3 +7618, >//3&
^, +62: 80:, =&q

^1; (7:1 +(0 30):-, (00s
K7:& ,+633 ,>&s }V 30): &0*}q
P1 +7>+ &0* <>1 -:3&s
Q0 2>++:- (7>+ +7: 9*+*-: =-618,
^, +62: 80:, =&q

R0013687+ >1; 30): ,018,
Q:):- 0*+ 09 ;>+:
W:>-+, 9*33 09 />,,601
U:>30*,& >1; 7>+:
H02>1 1::;, 2>1
^1; 2>1 2*,+ 7>): 76, 2>+:
K7>+ 10 01: <>1 ;:1&

V+x, ,+633 +7: ,>2: 03; ,+0-&s
^ 9687+ 90- 30): >1; 830-&s
^ <>,: 09 ;0 0- ;6:q
K7: (0-3; (633 >3(>&, (:3<02: 30):-,
^, +62: 80:, =&q

AsciiAtbash.lss

Contact Me

Hire Me

Elsewhere

What the Quote?

"Genome. And special sauce (primordial soup)."

Laura Tripcony

"Two wrongs don't make a right, but three rights make a left."

Michael Nurre

"You're not talking about the software, right? You're talking about the disease?"

David Bradshaw

"Generic candy corn will give you AIDS."

Brent Bowers

"I wonder if there's ever been a dog like that, and natural selection said, '...No'."

Laura Tripcony

Apparel

Lotus Rocks

I write the code that makes the young girls cry

Current Terror Alert Level

Assorted Linkage

ClustrMap