{"id":3223,"date":"2008-12-27T10:00:00","date_gmt":"2008-12-27T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/2008\/12\/27\/sshhh-its-a-secret-matt-gertz\/"},"modified":"2024-07-05T13:34:27","modified_gmt":"2024-07-05T20:34:27","slug":"sshhh-its-a-secret-matt-gertz","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/sshhh-its-a-secret-matt-gertz\/","title":{"rendered":"Sshhh&#8230; it&#8217;s a secret (Matt Gertz)"},"content":{"rendered":"<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">Back in seventh grade, I had a pretty heavy crush on a girl named Melissa.<span>&nbsp; <\/span>She was a good friend of mine, and so I had no problems talking to her.<span>&nbsp; <\/span>However, being painfully shy back then, I was far too nervous to ever ask her to \u201cgo with\u201d me.<span>&nbsp; <\/span>(For those not steeped in American traditions, to \u201cgo with\u201d a girl or boy in junior high school meant that you were publicly asserting that the two of you were somehow romantically involved, whatever that actually meant when you were only twelve years old.<span>&nbsp; <\/span>It was always unclear to me why the term \u201cgo with\u201d was used, since, being seventh graders, you never actually <i>went<\/i> anywhere.<span>&nbsp; <\/span>By the time you had access to a car and could actually go somewhere together, you were \u201cdating,\u201d not \u201cgoing with.\u201d<span>&nbsp; <\/span>In practice, what \u201cgoing with\u201d <i>really<\/i> meant was that the girl felt obliged to call the boy on the phone on a daily basis, and if the boy didn\u2019t muster up the courage to ask the girl out onto the floor in front of all of her friends at the next school dance, she would cry and break up with him.)<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">Anyway, I was able to reconcile my cowardice by writing notes to her expressing my affections.<span>&nbsp; <\/span>Well, in <b><i>code<\/i><\/b>, anyway \u2013 I was somewhat insensitive as well as shy.<span>&nbsp; <\/span>I used a simple 1:1 cipher where I mapped invented hieroglyphs to letters of the alphabet (essentially identical to writing a love letter using the WingDings font, though we didn\u2019t have PCs back then).<span>&nbsp; <\/span>This allowed me to feel good that I had done *something* to tell her how I felt about her, without actually putting me in emotional danger.<span>&nbsp;&nbsp; <\/span>You see, I never gave her the solution key!<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">This worked fairly well for my ego for a couple of weeks, until I learned from a friend that she had deciphered at least half of my invented alphabet, using letter frequency to figure them out (it turned out that she liked puzzles of this sort).<span>&nbsp; <\/span>Mortified, I immediately stopped sending her any new notes, and so, alas, she never learned how the depths of my feelings for her.<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">That junior high memory came back to me on Christmas Day, as I was reading through a book that my wife (apparently, I did overcome my shyness at some point) had given me as a gift.<span>&nbsp; <\/span>It\u2019s a fascinating book entitled \u201cThe Six Unsolved Ciphers\u201d by Richard Belfield.<span>&nbsp; <\/span>In it, Mr. Belfield walks the readers through such confounding puzzles as the Kryptos puzzle at the new CIA headquarters and the Shepherd\u2019s monument.<span>&nbsp; <\/span>The book really struck a chord with me.<span>&nbsp; <\/span>As a kid, I was motivated to create all sorts of codes, alphabets, and languages, but in recent years, while I\u2019ve certainly <i>used<\/i> cryptology \u2013 heck, we all do on a daily basis, whether we realize it or not \u2013 I hadn\u2019t really done much with it other than to leverage functionality that was already there.<span>&nbsp; <\/span>However, in reading Mr. Belfield \u2018s description of the Vigen\u00e8re encoding scheme, I realized that I had to try that one out, and I started working out the code.<span>&nbsp; <\/span>Ultimately, I realized that this would make a fun blog topic (and for all I know, this has already been blogged somewhere, but I\u2019ll press on nonetheless and see where we come out).<\/font><\/p>\n<h2><font color=\"#4f81bd\" size=\"4\" face=\"Cambria\">The Vigen\u00e8re method<\/font><\/h2>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">Before I jump into the coding, I\u2019d better briefly describe the Vigen\u00e8re method .<span>&nbsp; <\/span>The method (and I\u2019m borrowing heavily from Mr. Belfield here) involves both a key and an alphabet, and the encrypted letters result from a mathematical relation leveraging both of those.<span>&nbsp; <\/span>The key can be any word \u2013 let\u2019s say \u201cMICROSOFT\u201d \u2013 and the alphabet would be something like the letters A-Z &#8212; they might be in a different order known only to the sender and the receiver, but let\u2019s assume for the purpose of this example that they are in normal English alphabetical order.<span>&nbsp; <\/span>First thing I need to do is to create a grid with the alphabet offset by one each row (or column):<\/font><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">ABCDEFGHIJKLMNOPQRSTUVWXYZ<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">BCDEFGHIJKLMNOPQRSTUVWXYZA<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">CDEFGHIJKLMNOPQRSTUVWXYZAB<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">DEFGHIJKLMNOPQRSTUVWXYZABC<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">EFGHIJKLMNOPQRSTUVWXYZABCD<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">FGHIJKLMNOPQRSTUVWXYZABCDE<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">GHIJKLMNOPQRSTUVWXYZABCDEF<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">HIJKLMNOPQRSTUVWXYZABCDEFG<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">IJKLMNOPQRSTUVWXYZABCDEFGH<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">JKLMNOPQRSTUVWXYZABCDEFGHI<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">KLMNOPQRSTUVWXYZABCDEFGHIJ<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">LMNOPQRSTUVWXYZABCDEFGHIJK<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">MNOPQRSTUVWXYZABCDEFGHIJKL<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">NOPQRSTUVWXYZABCDEFGHIJKLM<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">OPQRSTUVWXYZABCDEFGHIJKLMN<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">PQRSTUVWXYZABCDEFGHIJKLMNO<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">QRSTUVWXYZABCDEFGHIJKLMNOP<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">RSTUVWXYZABCDEFGHIJKLMNOPQ<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">STUVWXYZABCDEFGHIJKLMNOPQR<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">TUVWXYZABCDEFGHIJKLMNOPQRS<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">UVWXYZABCDEFGHIJKLMNOPQRST<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">VWXYZABCDEFGHIJKLMNOPQRSTU<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">WXYZABCDEFGHIJKLMNOPQRSTUV<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">XYZABCDEFGHIJKLMNOPQRSTUVW<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">YZABCDEFGHIJKLMNOPQRSTUVWX<\/font><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><font size=\"3\">ZABCDEFGHIJKLMNOPQRSTUVWXY<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">So, let\u2019s say I want to encode the phrase \u201cERIC KNOX SHOULD POST MORE BLOGS\u201d.<span>&nbsp; <\/span>The first letter in the keyword (MICROSOFT) is <b>M<\/b>, the first letter in the sentence is <b>E,<\/b> so I find the <b>M<\/b> row and the <b>E<\/b> column and note where they intersect \u2013 this gives us the letter <b>Q<\/b>.<span>&nbsp; <\/span>The next letter in the keyword is I and the next letter in the sentence is R, and that yields <b>Z<\/b>.<span>&nbsp; <\/span>We ignore spaces, and when we run out of keyword letters, we just start again at the beginning of the keyword.<span>&nbsp; <\/span>This ultimately yields the encoded phrase \u201cQZKTYFCCLTWWCRHCXMYWTVPDCLL\u201d.<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">To decode the phrase, I work backwards \u2013 I find the Q in the M row, and ascend the column to find the E at the top, then find the Z in the I row and ascend to find the R at the top, and repeat this until I get back to \u201cERICKNOXSHOULDPOSTMOREBLOGS\u201d.<span>&nbsp; <\/span>It\u2019s pretty simple, though tedious work for messages of any meaningful length when doing it by hand.<span>&nbsp; <\/span>According to Mr. Belfield, this sort of code apparently was all but unbreakable for hundreds of years \u2013 nowadays, people have to change keywords at random times, throw in random junk in the text, or alter the alphabet ordering, to make it tougher to decode.<\/font><\/p>\n<h2><font color=\"#4f81bd\" size=\"4\" face=\"Cambria\">Creating a Vigen\u00e8re encode\/decode application<\/font><\/h2>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">In coding up the Vigen\u00e8re method, I knew that I\u2019d want to make provision for code which used a non-standard alphabet (as does the Kryptos cipher that Mr. Belfield writes about) \u2013 for example, to make decoding trickier, I might make an alphabet that leverages an additional code word such as my last name:<\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">GERTZABCDFHIJKLMNOPQSUVWXY<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">All 26 letters are still there; I\u2019ve just pushed a few up to the front.<span>&nbsp; <\/span>The advantage is that not knowing the alphabet ordering makes it tougher for others to crack my code.<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">The other thing I immediately decided was that creating a 2-dimensional array to hold the offsets of the alphabet would be incredibly inelegant as well as wasteful of memory.<span>&nbsp; <\/span>Since the ordering of each row is deterministic, being offset by one each time, a simple index into the alphabet should suffice, wrapping around to the front of the alphabet when needed. (Think of the alphabet as being a circular list if that helps visualize what I mean).<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">I\u2019ll start out the project as usual:<span>&nbsp; <\/span>I\u2019ll create a Visual Basic Windows Forms application (\u201cVBEncrypt\u201d).<span>&nbsp; <\/span>Now, on the form, I\u2019ll drag out labels and edit boxes for the Key, the Alphabet, the Clear Text, and the Encoded Text (the latter two boxes set to both \u201cMultiline=True\u201d and \u201cScroll bars=Vertical\u201d in the properties).<span>&nbsp; <\/span>I\u2019ll also added some checkboxes to handle niceties \u2013 \u201cCase-Insensitive\u201d to allow the user to ignore casing, and \u201cGroup Letters When Encoding\u201d (with an accompanying edit box) to cause spaces to be inserted every <i>n<\/i> characters when emitting the encrypted characters \u2013 i.e.,<span>&nbsp; <\/span>\u201cQZKT YFCC LTWW CRHC XMYW TVPD CLL\u201d vs \u201cQZKTYFCCLTWWCRHCXMYWTVPDCLL\u201d.<span>&nbsp; <\/span>Finally, I\u2019ll add a couple of buttons to do the actual encoding or decoding.<span>&nbsp; <\/span>My final layout is in a JPG in the ZIP file attached to this post.<\/font><\/p>\n<p class=\"MsoNormal\"><span><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">The idea is that the user specifies the Key and the Alphabet (note that I\u2019ll default to a normal alphabet in the interest of helping the user if they don\u2019t want to type all 26 characters every time).<span>&nbsp; <\/span>To encode, the user pastes text into the left pane and presses the \u201c&#8211;&gt;\u201d button to encode it.<span>&nbsp; <\/span>To decode, the user pastes encrypted text in the right pane and presses the \u201c&lt;&#8211;\u201c arrow.<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">Before we get to the guts of the code, I\u2019m going to do a little housekeeping first.<span>&nbsp; <\/span>I\u2019m going to need to do validation on the Key, Alphabet, and the \u201cLetters per group.\u201d<span>&nbsp; <\/span>For the Key, there are three issues \u2013 it must be non-empty, it must have no spaces (these are forbidden, since spaces are equivalent to NULLs and are used to simply make outputs more readable), and it must not use any characters not in the Alphabet.<span>&nbsp; <\/span>The first two cases are easy to code:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> <span>Function<\/span> VerifyKey() <span>As<\/span> <span>Boolean<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> Key <span>As<\/span> <span>String<\/span> = <span>Me<\/span>.edtKey.Text<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> <span>String<\/span>.IsNullOrEmpty(Key) <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>MsgBox(<span>&#8220;The Key contains no characters.&#8221;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> <span>False<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> Key.IndexOf(<span>&#8221; &#8220;<\/span>) &lt;&gt; -1 <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/span>MsgBox(<span>&#8220;The key contains one or more space characters.&#8221;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> <span>False<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> <span>True<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Function<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">Whereas the third case (alphabet validation) is more complicated and, since I expect it to be rare, I\u2019ll defer checking for it until I\u2019m actually doing the encoding\/decoding so as not to penalize the typical case performance-wise.<span>&nbsp; <\/span>(Note , by the way,that I am hard-coding my MsgBox strings \u2013 this is just for blog clarity, and normally I\u2019d put the strings into resources so that they could be localized into non-English languages.)<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">For the Alphabet verification, it\u2019s nearly identical \u2013 I need the alphabet to be non-empty and to not contain spaces.<span>&nbsp; <\/span>However, I also want to make sure that the Alphabet contains no duplicate characters, because that will make coding or decoding problematic.<span>&nbsp; <\/span>To check for duplicate characters in a string, people usually sort the string using a selection sort and then walk through it looking for multiples step-by-step.<span>&nbsp; <\/span>I\u2019m lazy, though, and so I\u2019m going to leverage the \u201cDistinct()\u201d method on the String class \u2013 this will do the sort for me and return an IEnumerable containing the unique characters in the string.<span>&nbsp; <\/span>If its count of that IEnumerable isn\u2019t identical to the length of the original string, then I know there\u2019s a problem, and all it\u2019ll cost me is just an IEnumerable object that I otherwise won\u2019t use:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> <span>Function<\/span> VerifyAlphabet() <span>As<\/span> <span>Boolean<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> Alphabet <span>As<\/span> <span>String<\/span> = <span>Me<\/span>.edtAlphabet.Text<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> <span>String<\/span>.IsNullOrEmpty(Alphabet) <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>MsgBox(<span>&#8220;The Alphabet contains no characters.&#8221;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> <span>False<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> Alphabet.IndexOf(<span>&#8221; &#8220;<\/span>) &lt;&gt; -1 <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>MsgBox(<span>&#8220;The alphabet contains a space character.&#8221;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> <span>False<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> distinctLetters <span>As<\/span> IEnumerable(<span>Of<\/span> <span>Char<\/span>) = Alphabet.Distinct()<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> distinctLetters.Count &lt;&gt; Alphabet.Length <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>MsgBox(<span>&#8220;The alphabet contains duplicates.&#8221;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> <span>False<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> <span>True<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Function<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">For the GroupSize box, I want to enforce having only non-negative integers.<span>&nbsp; <\/span>I\u2019ll do this on the validation.<span>&nbsp; <\/span>At the top of the editor, I\u2019ll select the edtGroupSize control in the left dropdown, then in the right dropdown I\u2019ll choose \u201cValidating.\u201d<span>&nbsp; <\/span>I\u2019ll then fill in the resulting code thusly:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> <span>Sub<\/span> edtGroupSize_Validating(<span>ByVal<\/span> sender <span>As<\/span> <span>Object<\/span>, _<\/span><\/p>\n<p class=\"MsoNormal\"><span>ByVal<\/span><span> e <span>As<\/span> System.ComponentModel.CancelEventArgs) <span>Handles<\/span> edtGroupSize.Validating<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> <span>Not<\/span> IsNumeric(edtGroupSize.Text.ToString) <span>OrElse<\/span> <span>CInt<\/span>(edtGroupSize.Text) &lt; 0 _<\/span><\/p>\n<p class=\"MsoNormal\"><span>OrElse<\/span><span> edtGroupSize.Text.IndexOf(<span>&#8220;.&#8221;<\/span>) &lt;&gt; -1 <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; Cancel the event and select the text to be corrected by the user.<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>e.Cancel = <span>True<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>edtGroupSize.Select(0, edtGroupSize.Text.Length)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>MsgBox(<span>&#8220;Only non-negative whole numbers are allowed in this field.&#8221;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Sub<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">One last detail before we get to the meat of the code:<span>&nbsp; <\/span>I need to link the availability of the GroupSize box to the state of the Group checkbox:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> <span>Sub<\/span> Form1_Load(<span>ByVal<\/span> sender <span>As<\/span> System.Object, <span>ByVal<\/span> e _<\/span><\/p>\n<p class=\"MsoNormal\"><span>As<\/span><span> System.EventArgs) <span>Handles<\/span> <span>MyBase<\/span>.Load<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>edtGroupSize.Enabled = (chkGroup.CheckState = CheckState.Checked)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Sub<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> <span>Sub<\/span> chkGroup_CheckedChanged(<span>ByVal<\/span> sender <span>As<\/span> System.Object, _<\/span><\/p>\n<p class=\"MsoNormal\"><span>ByVal<\/span><span> e <span>As<\/span> System.EventArgs) <span>Handles<\/span> chkGroup.CheckedChanged<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>edtGroupSize.Enabled = (chkGroup.CheckState = CheckState.Checked)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Sub<\/span><\/span><\/p>\n<h2><font color=\"#4f81bd\" size=\"4\" face=\"Cambria\">The Encrypting Code<\/font><\/h2>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">We\u2019ll now dig into the encoding. <span>&nbsp;<\/span>By double-clicking on the Encode button, I\u2019ll generate the boilerplate header:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> <span>Sub<\/span> btnEncode_Click(<span>ByVal<\/span> sender <span>As<\/span> System.Object, <span>ByVal<\/span> e <span>As<\/span> System.EventArgs) <span>Handles<\/span> btnEncode.Click<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Next, I\u2019ll call the Validation methods I set up in the previous session:<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> VerifyKey() <span>AndAlso<\/span> VerifyAlphabet() <span>AndAlso<\/span> <span>Not<\/span> <span>String<\/span>.IsNullOrEmpty(<span>Me<\/span>.edtClearText.Text) <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">I\u2019m going to pull out all of my string values from the form <i>a priori<\/i>, since I know I\u2019m going to be in a loop and I detest dereferencing controls or string lengths more than necessary.<span>&nbsp; <\/span>Note that, when I pull in the text to encode (ClearText), I\u2019m also stripping out any spaces from it using the Replace() method:<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> Alphabet <span>As<\/span> <span>String<\/span> = <span>Me<\/span>.edtAlphabet.Text<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> Key <span>As<\/span> <span>String<\/span> = <span>Me<\/span>.edtKey.Text<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> ClearText <span>As<\/span> <span>String<\/span> = <span>Me<\/span>.edtClearText.Text.Replace(<span>&#8221; &#8220;<\/span>, <span>&#8220;&#8221;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> ClearTextLength <span>As<\/span> <span>Integer<\/span> = ClearText.Length<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> AlphabetLength <span>As<\/span> <span>Integer<\/span> = Alphabet.Length<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;<\/span><span>Dim<\/span> KeyLength <span>As<\/span> <span>Integer<\/span> = Key.Length<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">The user might have selected \u201cCase Insensitive,\u201d and if that\u2019s the case, I\u2019ll upper-case everything in all of the strings to make the comparisons work:<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; Push everything to uppercase if we are being case-insensitive:<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> chkCaseInsensitive.CheckState = CheckState.Checked <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Alphabet = Alphabet.ToUpper<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Key = Key.ToUpper<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>ClearText = ClearText.ToUpper<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Now, I need a place for the encrypted code to go.<span>&nbsp; <\/span>I\u2019ll <span>&nbsp;<\/span>use a StringBuilder for this, because (as I\u2019ve mentioned in earlier posts) it is a lot less wasteful than concatenating strings.<span>&nbsp; <\/span>In fact, in this case, I already know the size of the text buffer I\u2019ll need \u2013 the encoded text will be the same size as the clear text:<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;<\/span><span>Dim<\/span> EncodedText <span>As<\/span> <span>New<\/span> StringBuilder(ClearTextLength)<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">As I mentioned above, I\u2019m going to have to cycle through the Key, so I\u2019ll need an index into it:<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> KeyIndex <span>As<\/span> <span>Integer<\/span> = 0<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">And I\u2019ll proactively determine if the user wants me to add spaces between groups of letters:<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> GroupSize <span>As<\/span> <span>Integer<\/span> = -1<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> <span>Me<\/span>.chkGroup.CheckState = CheckState.Checked <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>GroupSize = <span>CInt<\/span>(edtGroupSize.Text)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Now, we come to the place where the work gets done.<span>&nbsp; <\/span>I will step through each letter of the ClearText and mathematically determine its corresponding encoded value.<span>&nbsp; <\/span>The first thing to do is to determine the \u201crow.\u201d<span>&nbsp; <\/span>I\u2019ll get the current letter pointed to in the Key, and figure out where that letter lives in the Alphabet.<span>&nbsp; <\/span>In a normal alphabet, I could simply calculate its offset from the letter \u201cA\u201d, but I mentioned earlier I want to support arbitrary alphabets and so I use \u201cIndexOf()\u201d instead.<span>&nbsp; <\/span>(If IndexOf() returns a -1, then I know that the Key uses a letter not in the Alphabet, and will abort the operation with an appropriate message.)<span>&nbsp; <\/span>The code is:<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>For<\/span> i <span>As<\/span> <span>Integer<\/span> = 0 <span>To<\/span> ClearTextLength &#8211; 1<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> RowOffset <span>As<\/span> <span>Integer<\/span> = Alphabet.IndexOf(Key(KeyIndex))<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> RowOffset = -1 <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>MsgBox(<span>&#8220;Key contains character&#8221;<\/span> &amp; Key(KeyIndex) &amp; <span>&#8220;not in the alphabet.&#8221;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Knowing the row offset, I don\u2019t need a 2-D array \u2013 I\u2019ll just pretend that the Alphabet starts <i>RowOffset<\/i> characters later than it does, wrapping around if necessary \u2013 but I\u2019ll get to that later.<span>&nbsp; <\/span><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Now, let\u2019s track down the column.<span>&nbsp; <\/span>I\u2019ll get that from the current ClearText letter itself, locating it within the Alphabet via IndexOf().<span>&nbsp; <\/span>Again, I can report &amp; abort if the text to encode contains characters that are not in the Alphabet:<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> ColOffset <span>As<\/span> <span>Integer<\/span> = Alphabet.IndexOf(ClearText(i))<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> ColOffset = -1 <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>MsgBox(<span>&#8220;ClearText contains character&#8221;<\/span> &amp; ClearText(i) &amp; _<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>&#8220;not in the alphabet.&#8221;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Now, the encoding is easy. Moving along rows or along columns just changes the letter by one index on each step.<span>&nbsp; <\/span>To select the \u201crow\u201d is <i>identical<\/i> to just advancing through the Alphabet by <i>RowOffset<\/i> characters and pretending that the Alphabet starts there.<span>&nbsp; <\/span>I then add <i>ColOffset<\/i> to that value in order to account for the horizontal displacement, following the same logic.<span>&nbsp; <\/span>Because the sum might \u201cwrap around\u201d back to the front of the Alphabet, I need to perform a modulus on the sum before using it as an index to Alphabet, so I won\u2019t reference an illegal index:<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> EncodedChar <span>As<\/span> <span>Char<\/span> = Alphabet((RowOffset + ColOffset) <span>Mod<\/span> AlphabetLength)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>EncodedText.Append(EncodedChar)<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">It\u2019s just that simple!<span>&nbsp; <\/span>Now I\u2019ll add any spaces if requested (again using a modulus to see if we\u2019ve reached the <i>n<\/i>-1 point where a space needs to go), move to the next letter in the Key (again, modulus will help me wrap around to the beginning if needed), and throw the encoded letter into the buffer:<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; Add spaces if requested:<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> GroupSize &gt; 0 <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> i <span>Mod<\/span> GroupSize = GroupSize &#8211; 1 <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>EncodedText.Append(<span>&#8221; &#8220;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; On to the next character in the key&#8230;<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>KeyIndex = (KeyIndex + 1) <span>Mod<\/span> KeyLength<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Next<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">After the final loop, I\u2019ll update the text in the right-hand pane, and we\u2019re done:<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Me<\/span>.edtEncodedText.Text = EncodedText.ToString<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Sub<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">Decoding is very similar to encoding, except that I use the EncodedText instead of the ClearText and, once I\u2019ve found the \u201crow\u201d based on the current letter in the Key, I need to <i>subtract<\/i> the \u201ccolumn\u201d instead of adding it \u2013 this means I also have to add the length of the alphabet to the result before taking a modulus, because modulus doesn\u2019t work on negative numbers and I still need to account for wrap-around in the leftward direction.<span>&nbsp; <\/span>The result looks like this:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> <span>Sub<\/span> btnDecode_Click(<span>ByVal<\/span> sender <span>As<\/span> System.Object, <span>ByVal<\/span> e _<\/span><\/p>\n<p class=\"MsoNormal\"><span>As<\/span><span> System.EventArgs) <span>Handles<\/span> btnDecode.Click<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> VerifyKey() <span>AndAlso<\/span> VerifyAlphabet() <span>AndAlso<\/span> _<\/span><\/p>\n<p class=\"MsoNormal\"><span>Not<\/span><span> <span>String<\/span>.IsNullOrEmpty(<span>Me<\/span>.edtEncodedText.Text) <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> Alphabet <span>As<\/span> <span>String<\/span> = <span>Me<\/span>.edtAlphabet.Text<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> Key <span>As<\/span> <span>String<\/span> = <span>Me<\/span>.edtKey.Text<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> EncodedText <span>As<\/span> <span>String<\/span> = <span>Me<\/span>.edtEncodedText.Text.Replace(<span>&#8221; &#8220;<\/span>, <span>&#8220;&#8221;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> EncodedTextLength <span>As<\/span> <span>Integer<\/span> = EncodedText.Length<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> AlphabetLength <span>As<\/span> <span>Integer<\/span> = Alphabet.Length<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> KeyLength <span>As<\/span> <span>Integer<\/span> = Key.Length<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; Push everything to uppercase if we are being case-insensitive:<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> chkCaseInsensitive.CheckState = CheckState.Checked <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Alphabet = Alphabet.ToUpper<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Key = Key.ToUpper<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>EncodedText = EncodedText.ToUpper<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> ClearText <span>As<\/span> <span>New<\/span> StringBuilder(EncodedTextLength)<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> KeyIndex <span>As<\/span> <span>Integer<\/span> = 0<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>For<\/span> i <span>As<\/span> <span>Integer<\/span> = 0 <span>To<\/span> EncodedTextLength &#8211; 1<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> RowOffset <span>As<\/span> <span>Integer<\/span> = Alphabet.IndexOf(Key(KeyIndex))<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> RowOffset = -1 <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>MsgBox(<span>&#8220;Key contains character&#8221;<\/span> &amp; Key(KeyIndex) &amp; <span>&#8220;not in the alphabet.&#8221;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> ColOffset <span>As<\/span> <span>Integer<\/span> = Alphabet.IndexOf(EncodedText(i))<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> ColOffset = -1 <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>MsgBox(<span>&#8220;ClearText contains character&#8221;<\/span> &amp; EncodedText(i) _<\/span><\/p>\n<p class=\"MsoNormal\"><span>&amp; <span>&#8220;not in the alphabet.&#8221;<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> DecodedChar <span>As<\/span> <span>Char<\/span> = Alphabet((AlphabetLength + (ColOffset &#8211; RowOffset)) _<\/span><\/p>\n<p class=\"MsoNormal\"><span>Mod<\/span><span> AlphabetLength)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>ClearText.Append(DecodedChar)<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>KeyIndex = (KeyIndex + 1) <span>Mod<\/span> KeyLength<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Next<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Me<\/span>.edtClearText.Text = ClearText.ToString<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Sub<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">And that\u2019s it!<span>&nbsp; <\/span>The final application is attached to this post.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">This was code I particularly enjoyed writing \u2013 I like the simple elegance of a good mathematical model. For me, though, the most poignant part of this whole exercise was remembering that APTNW WBOIA DLMJV RDATM QSOVU YJWLP ZJALN APZJL DNXRO VFUVA RQYOY ZFMAR CLDBZ XJJYY PBZQO IUWRN AOZHP NYIZW MSWMU YJWNO MQATD YRKUY RINRZ NDADP MMGIV BUPRQ.<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\" face=\"Calibri\">\u2018Til next time,<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\"><span>&nbsp; <\/span>&#8211;Matt&#8211;*<\/font><\/font><\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/MSDNBlogsFS\/prod.evol.blogs.msdn.com\/CommunityServer.Components.PostAttachments\/00\/09\/25\/43\/87\/VBEncrypt.zip\">VBEncrypt.zip<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Back in seventh grade, I had a pretty heavy crush on a girl named Melissa.&nbsp; She was a good friend of mine, and so I had no problems talking to her.&nbsp; However, being painfully shy back then, I was far too nervous to ever ask her to \u201cgo with\u201d me.&nbsp; (For those not steeped in [&hellip;]<\/p>\n","protected":false},"author":258,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[22,195],"tags":[62,63,101,166],"class_list":["post-3223","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-matt-gertz","category-visual-basic","tag-encoding","tag-encryption","tag-matt-gertz","tag-vb2008"],"acf":[],"blog_post_summary":"<p>Back in seventh grade, I had a pretty heavy crush on a girl named Melissa.&nbsp; She was a good friend of mine, and so I had no problems talking to her.&nbsp; However, being painfully shy back then, I was far too nervous to ever ask her to \u201cgo with\u201d me.&nbsp; (For those not steeped in [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/3223","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/258"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=3223"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/3223\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=3223"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=3223"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=3223"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}