Visual Basic Algorithms
Pure VB: Providing Weak Encryption using ROT-39
Posted:   Friday December 27, 1996
Updated:   Monday December 26, 2011
Applies to:   VB4-32, VB5, VB6
Developed with:   VB6, Windows XP
OS restrictions:   None
Author:   VBnet - Randy Birch, Dag Sunde

Lets get something straight at the start. By providing this code I am not implying that using ROT-39 will in any way assure the secure protection of information.  Its purpose is to simply provide a narrative into designing a weak encryption system, with the possible goal of providing a method for encrypting small sets of data in such a way to possibly discourage casual deciphering. This page was prompted by a submission by Dag Sunde.

Formally, cryptography is the art of encoding data in a way that only the intended recipient can decode it, and know that the message is authentic and unchanged. Cryptography means different things to different people. Small children play with simple ciphers and substitution secret languages, bigger children play with crypto puzzles. Some people are concerned with privacy for various reasons and use different methods to encrypt sensitive data, with standard UNIX "crypt" or "rot-13" variants. None of these have anything to do with strong encryption and real data security.

Possibly the most famous (or is that infamous) encryption technique is the 'Caesar Cipher' - also known as ROT-13, purportedly used by Julius Caesar to keep his messages a secret should they fall into Brutus' hand. Some web pages I've read in researching this material have also implied that ROT-13 is the encryption mechanism used in Netscape and Eudora. With the ROT-13 cipher, the alphabet is shifted 13 characters and wrapped around to form a one-to-one correspondence between a real letter and a fake letter (the 'code'):

ROT-13 Legend



Thus, to encode my name using ROT-13, one finds each letter in my name in the black letters in the table, and substitutes the letter in blue .. my 'encrypted' name becomes FOBRK PWFQV, which actually sounds like a European hockey player in the NHL. But I digress.

While ROT-13 was successful in fooling Brutus, ROT-13 can't stop a child from decrypting material. You can read more on the history and mechanics behind ROT-13 from

ROT-39 follows the same theme, but introduces additional characters (the full ASCII set from chr 48  to chr 125. Because it encompasses more characters, a ROT-39 message appears 'more cryptic', i.e. my ROT-39-encrypted name is "y:G=R iBK<A".

ASCII Legend used by ROT-39

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
0 1 2 3 4 5 6 7 8 9 : ; < = > ?

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
@ A B C D E F G H I J K L M N O

80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
P Q R S T U V W X Y Z [ \ ] ^ _

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
` a b c d e f g h i j k l m n o

112 113 114 115 116 117 118 119 120 121 122 123 124 125    
p q r s t u v w x y z { | }    













Here's a real-life example of applying ROT-39 encryption to sensitive data. Consider the following block of XML data that an end-client wants encrypted before transmission between machines:

With the ROT-13 weak encryption applied, although the tag-names are encoded, the numeric data within the tags are not:

The same data encoded with ROT-39 encodes both the tags and the data, making the resulting XML block more difficult to decipher:

The rot39 is, in principle, a ring-buffer, containing the characters from ASCII(LOWER_LIMIT) to ASCII(UPPER_LIMIT) in this case from 48 to 125 providing a character-set of 78 characters.

To encrypt data in ROT-39:

  • First the input string is converted to a byte-array to enable working directly with the character's ASCII values.
  • If the ASCII value is between and including LOWER_LIMIT and UPPER_LIMIT, we add exactly half the character buffer-size. This is held in constant CHARMAP (value 39).
  • If the new value is larger than UPPER_LIMIT, it wraps around to the beginning (LOWER_LIMIT), and adds the rest of CHARMAP creating, in effect, a circle.
  • The new shifted value is added back into the byte-array, where the next value is returned and the process repeats for the remainder of the string.
  • Where the current ASCII value is outside the range specified by LOWER_LIMIT and UPPER_LIMIT, it is left unchanged.
  • Finally, once the loop is done the now-encrypted byte-array is converted back into a string and returned from the encryption method.

Since the encryption mechanism is a circle, and to perform the encryption half the buffer-size is added to the value, passing the encrypted data back through the same routine will restore the string's original value.

As a rule, you could make any ROTxx you wanted, as long as the buffer-size is an even number that, when divided by 2 produces an odd number. In addition, you can also slide LOWER_LIMIT and UPPER_LIMIT up or down the ASCII table by equal values.

 BAS Module Code

 Form Code
On a form, add two command buttons (Command1, Command2) and three text boxes (Text1, Text2, Text3), along with the following code:

Option Explicit
' Copyright 1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
Private Const LOWER_LIMIT As Long = 48   'ascii for 0
Private Const UPPER_LIMIT As Long = 125  'ascii for {
Private Const CHARMAP     As Long = 39

Private Sub Form_Load()

   Dim buff As String
   buff = "Meeting tonight midnight will "
   buff = buff & "have merchandise bring funds. "
   buff = buff & "Plans in place for tomorrow 7pm. "
   buff = buff & "Vehicles secured."
   Text1.Text = buff
   Text2.Text = ""
   Text3.Text = ""
   Command1.Caption = "String to ROT39"
   Command2.Caption = "ROT39 to String"
End Sub

Private Sub Command1_Click()

  'encode the contents of Text1
   Text2.Text = Rot39(Text1.Text)

End Sub

Private Sub Command2_Click()

  'decode Text2
   Text3.Text = Rot39(Text2.Text)

End Sub

Private Function Rot39(ByVal sData As String) As String

  'ROT39 (a variation of the ROT13 function) by Dag Sunde

   Dim sReturn As String
   Dim nCode As Long
   Dim nData As Long
   Dim bData() As Byte
   On Error GoTo Rot39_error
  'initialize the byte array to the
  'size of the string passed.
   ReDim bData(Len(sData)) As Byte
  'cast string into the byte array
   bData = StrConv(sData, vbFromUnicode)
   For nData = 0 To UBound(bData)
     'with the ASCII value of the character
      nCode = bData(nData)
     'assure the ASCII value is between
     'the lower and upper limits
      If ((nCode >= LOWER_LIMIT) And (nCode <= UPPER_LIMIT)) Then
        'shift the ASCII value by the
        'CHARMAP const value
         nCode = nCode + CHARMAP
        'perform a check against the upper
        'limit. If the new value exceeds the
        'upper limit, rotate the value to offset
        'from the beginning of the character set.
         If nCode > UPPER_LIMIT Then
            nCode = nCode - UPPER_LIMIT + LOWER_LIMIT - 1
         End If
      End If
     'reassign the new shifted value to
     'the current byte
      bData(nData) = nCode
   Next nData
  'convert the byte array back
  'to a string and exit
   sReturn = StrConv(bData, vbUnicode)

  'assign the return string
   Rot39 = sReturn
   Exit Function
  'error! Return an empty string
   sReturn = ""
   Resume Rot39_exit:
End Function


PayPal Link
Make payments with PayPal - it's fast, free and secure!


Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy



Hit Counter