6

I'm trying to find a simple way to record and temporarily obfuscate answers to "quiz" questions I'm writing in Markdown. (I'll tell the students the quiz answers during the presentation, so I'm not looking for any kind of secure encryption.)

I thought I could use atob('message I want to obfuscate') then tell students they can use btoa() in their developer tools panel to reverse the process. However the following does not return 'one':

btoa( atob('one') )

Does anyone know why this doesn't return 'one'? Are there other methods built into JavaScript that will allow one to loosely encrypt and decrypt a message? (I'm working with absolute beginners who might be confused by functions and who would be very confused trying to add libraries to a page).

yuriy636
  • 11,171
  • 5
  • 37
  • 42
duhaime
  • 25,611
  • 17
  • 169
  • 224

3 Answers3

3

That is the reason.

In Base64 encoding, the length of output encoded String must be a multiple of 3. If it's not, the output will be padded with additional pad characters (=). On decoding, these extra padding characters will be discarded.

var string1 = "one",
  string2 = "one2";

console.log("Value of string1", string1)
console.log("Decoded string1", atob(string1))
console.log("Encoded string1", btoa(atob(string1)))
console.log("-------------------------------------")
console.log("Value of string2", string2)
console.log("Decoded string2", atob(string2))
console.log("Encoded string2", btoa(atob(string2)))
George
  • 6,630
  • 2
  • 29
  • 36
David
  • 910
  • 1
  • 12
  • 22
  • Why encoded string is padded to 4 characters and not a multiple of 3. Have you any reference? Can you explain more correct so we can understand? – Dan Froberg Jul 30 '23 at 17:50
  • If you encode with atob then pad to groups of 4. If you encode with btoa then pad to groups of 3. Encoding with atob gives shorter strings than encoding with btoa. – Dan Froberg Aug 17 '23 at 02:42
1

As @george pointed out, one must use btoa() before using atob():

atob( btoa( 'hello' ) )
duhaime
  • 25,611
  • 17
  • 169
  • 224
  • Even that btoa convert Base64 and DataURL into 8 bit binary representation, that is not a good result as btoa("abc") is 4 characters, but atob("abc") compress it to 2 characters. It can further be compressed to 1 character because JS use 16-bit String. – Dan Froberg Jul 30 '23 at 17:23
  • Are you suggesting there are ascii strings for which `atob( btoa( 'hello' ) )` does not return the input string? – duhaime Jul 31 '23 at 14:05
  • I am not suggesting this answer at all, because with correct padding it is meant to do `atob` first. You have a 6-bit ascii string (Base64 with 2 of 8 bits unused) and get a binary string with filled 8-bit bytes. That is the purpose; to get shorter strings to store or send. The `btoa` expand strings; that is not good for anything but decoding back the data. – Dan Froberg Jul 31 '23 at 22:25
  • 1
    @DanFroberg Getting shorter strings is _your_ purpose. No one uses it that way, because it doesn't work. Base64 decoding is not, and cannot be a form of compression on arbitrary strings of Base64 characters. – Mark Adler Aug 01 '23 at 02:37
  • I use it in that way and store DataURI images in localStorage with over 50% lossless compression. – Dan Froberg Aug 01 '23 at 11:44
1

btoa means binary to ascii: input is Binary=any kind of data: text, images, audio. Output is Ascii=its base64 encoding, which is an ascii subset, i.e. a text string containing only upper and lowercase letters, numbers, comma, plus, slash, equal sign (only for padding at end).

atob means ascii to binary: input MUST be a subset of Ascii, i.e. the result of a base64 encoded string. Output is Binary=any type of data (text, image, audio, ...).