summaryrefslogtreecommitdiffstats
path: root/comm/mail/extensions/openpgp/content/modules/zbase32.jsm
blob: c5587fde3fc60a77ac75cd8fe7b8d364871297b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/* eslint no-invalid-this: 0 */
/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

"use strict";

var EXPORTED_SYMBOLS = ["EnigmailZBase32"];

const ZBase32Alphabet = "ybndrfg8ejkmcpqxot1uwisza345h769";

var EnigmailZBase32 = {
  a: ZBase32Alphabet,
  pad: "=",

  /**
   * Encode a string in Z-Base-32 encoding
   *
   * @param str   String - input string
   *
   * @returns String - econded string
   */
  encode(str) {
    let a = this.a;
    let pad = this.pad;
    let len = str.length;
    let o = "";
    let w,
      c,
      r = 0,
      sh = 0;

    for (let i = 0; i < len; i += 5) {
      // mask top 5 bits
      c = str.charCodeAt(i);
      w = 0xf8 & c;
      o += a.charAt(w >> 3);
      r = 0x07 & c;
      sh = 2;

      if (i + 1 < len) {
        c = str.charCodeAt(i + 1);
        // mask top 2 bits
        w = 0xc0 & c;
        o += a.charAt((r << 2) + (w >> 6));
        o += a.charAt((0x3e & c) >> 1);
        r = c & 0x01;
        sh = 4;
      }

      if (i + 2 < len) {
        c = str.charCodeAt(i + 2);
        // mask top 4 bits
        w = 0xf0 & c;
        o += a.charAt((r << 4) + (w >> 4));
        r = 0x0f & c;
        sh = 1;
      }

      if (i + 3 < len) {
        c = str.charCodeAt(i + 3);
        // mask top 1 bit
        w = 0x80 & c;
        o += a.charAt((r << 1) + (w >> 7));
        o += a.charAt((0x7c & c) >> 2);
        r = 0x03 & c;
        sh = 3;
      }

      if (i + 4 < len) {
        c = str.charCodeAt(i + 4);
        // mask top 3 bits
        w = 0xe0 & c;
        o += a.charAt((r << 3) + (w >> 5));
        o += a.charAt(0x1f & c);
        r = 0;
        sh = 0;
      }
    }
    // Calculate length of pad by getting the
    // number of words to reach an 8th octet.
    if (r != 0) {
      o += a.charAt(r << sh);
    }
    var padlen = 8 - (o.length % 8);

    if (padlen === 8) {
      return o;
    }

    if (padlen === 1 || padlen === 3 || padlen === 4 || padlen === 6) {
      return o + pad.repeat(padlen);
    }

    throw new Error(
      "there was some kind of error:\npadlen:" +
        padlen +
        " ,r:" +
        r +
        " ,sh:" +
        sh +
        ", w:" +
        w
    );
  },
};