1. 程式人生 > >[CTF]base64編碼

[CTF]base64編碼

[CTF]base64編碼

 --------------------- 
作者:adversity` 
來源:CSDN 
原文:https://blog.csdn.net/qq_40836553/article/details/79383488 

https://baike.baidu.com/item/base64

關於base64

Base64是網路上最常見的用於傳輸8Bit位元組碼的編碼方式之一,base64就是一種基於64個可列印字元來表示二進位制資料的表示方法。由於2的6次方等於64,所以每6個位元為一個單元,對應某個可列印字元。三個位元組有24個位元,對應4個base64單元,即3個位元組可表示4個可列印字元。它可用來作為電子郵件的傳輸編碼。在base64中的可列印字元包括字母A-Z、a-z、數字0-9,這樣共有62個字元,此外兩個可列印符號在不同系統中而不同。


例如:編碼‘Man'
 

 

在此例中,base64演算法將3個字元編碼轉為4個字元

base64索引表:

如果要編碼的位元組數不能被3整除,最後會多出1個或2個位元組,那麼可以使用下面的方法進行處理:先使用0位元組值在末尾補足,使其能夠被3整除,然後再進行base64的編碼。在編碼後的base64文字後加上一個或兩個“=”號,代表補足的位元組數。也就是說,當最後剩餘一個八位位元組(一個byte)時,最後6位的base64位元組塊有四位是0值,最後附加上兩個等號;如果最後剩餘兩個八位位元組(2byte)時,最後一個6位的base位元組塊有兩位是0值,最後附加一個等號
例如:

 

當看到==號的加密方式時,可以考慮base64。例:cTZ1NQ==解碼之後為q5u5。

關於base32:

 base32中只有大寫字母(A-Z)和數字234567 

 

關於base16:

base16中只有數字0-9以及大寫字母ABCDEF

用python3使用base64、base32、base16編碼

base64線上解密   摘自: CTF中Crypty(密碼類)入門必看

 

 

Base64是網路上最常見的用於傳輸8Bit

位元組碼的編碼方式之一,Base64就是一種基於64個可列印字元來表示二進位制資料的方法。可檢視RFC2045~RFC2049,上面有MIME的詳細規範。

Base64編碼是從二進位制到字元的過程,可用於在HTTP環境下傳遞較長的標識資訊。例如,在Java Persistence系統Hibernate中,就採用了Base64來將一個較長的唯一識別符號(一般為128-bit的UUID)編碼為一個字串,用作HTTP表單和HTTP GET URL中的引數。在其他應用程式中,也常常需要把二進位制資料編碼為適合放在URL(包括隱藏表單域)中的形式。此時,採用Base64編碼具有不可讀性,需要解碼後才能閱讀。

 

原理

編輯

轉碼過程例子:

3*8=4*6

記憶體1個位元組佔8位

轉前: s 1 3

先轉成ascii:對應 115 49 51

2進位制: 01110011 00110001 00110011

6個一組(4組) 011100110011000100110011

然後才有後面的 011100 110011 000100 110011

然後計算機是8位8位的存數 6不夠,自動就補兩個高位0了

所有有了 高位補0

科學計算器輸入 00011100 00110011 00000100 00110011

得到 28 51 4 51

查對下照表 c z E z


  先以“迅雷下載”為例: 很多下載類網站都提供“迅雷下載”的連結,其地址通常是加密的迅雷專用下載地址。

其實迅雷的“專用地址”也是用Base64"加密"的,其過程如下:

一、在地址的前後分別新增AA和ZZ

二、對新的字串進行Base64編碼

另: Flashget的與迅雷類似,只不過在第一步時加的“料”不同罷了,Flashget在地址前後加的“料”是[FLASHGET]

而QQ旋風的乾脆不加料,直接就對地址進行Base64編碼了

應用

編輯

Base64編碼可用於在HTTP環境下傳遞較長的標識資訊。例如,在Java Persistence系統Hibernate中,就採用了Base64來將一個較長的唯一識別符號(一般為128-bit的UUID)編碼為一個字串,用作HTTP表單和HTTP GET URL中的引數。在其他應用程式中,也常常需要把二進位制資料編碼為適合放在URL(包括隱藏表單域)中的形式。此時,採用Base64編碼不僅比較簡短,同時也具有不可讀性,即所編碼的資料不會被人用肉眼所直接看到。

然而,標準的Base64並不適合直接放在URL裡傳輸,因為URL編碼器會把標準Base64中的“/”和“+”字元變為形如“%XX”的形式,而這些“%”號在存入資料庫時還需要再進行轉換,因為ANSI SQL中已將“%”號用作萬用字元。

為解決此問題,可採用一種用於URL的改進Base64編碼,它不僅在末尾去掉填充的'='號,並將標準Base64中的“+”和“/”分別改成了“-”和“_”,這樣就免去了在URL編解碼和資料庫儲存時所要作的轉換,避免了編碼資訊長度在此過程中的增加,並統一了資料庫、表單等處物件識別符號的格式。

另有一種用於正則表示式的改進Base64變種,它將“+”和“/”改成了“!”和“-”,因為“+”,“/”以及前面在IRCu中用到的“[”和“]”在正則表示式中都可能具有特殊含義。

此外還有一些變種,它們將“+/”改為“_-”或“._”(用作程式語言中的識別符號名稱)或“.-”(用於XML中的Nmtoken)甚至“_:”(用於XML中的Name)。

其他應用

Mozilla Thunderbird和Evolution用Base64來保密電子郵件密碼

Base64 也會經常用作一個簡單的“加密”來保護某些資料,而真正的加密通常都比較繁瑣。

垃圾訊息傳播者用Base64來避過反垃圾郵件工具,因為那些工具通常都不會翻譯Base64的訊息。

在LDIF檔案,Base64用作編碼字串。

簡介

編輯

標準的Base64並不適合直接放在URL裡傳輸,因為URL編碼器會把標準Base64中的“/”和“+”字元變為形如“%XX”的形式,而這些“%”號在存入資料庫時還需要再進行轉換,因為ANSI SQL中已將“%”號用作萬用字元

為解決此問題,可採用一種用於URL的改進Base64編碼,它在末尾填充'='號,並將標準Base64中的“+”和“/”分別改成了“-”和“_”,這樣就免去了在URL編解碼和資料庫儲存時所要作的轉換,避免了編碼資訊長度在此過程中的增加,並統一了資料庫、表單等處物件識別符號的格式。

另有一種用於正則表示式的改進Base64變種,它將“+”和“/”改成了“!”和“-”,因為“+”,“*”以及前面在IRCu中用到的“[”和“]”在正則表示式中都可能具有特殊含義。

此外還有一些變種,它們將“+/”改為“_-”或“._”(用作程式語言中的識別符號名稱)或“.-”(用於XML中的Nmtoken)甚至“_:”(用於XML中的Name)。

Base64要求把每三個8Bit的位元組轉換為四個6Bit的位元組(3*8 = 4*6 = 24),然後把6Bit再添兩位高位0,組成四個8Bit的位元組,也就是說,轉換後的字串理論上將要比原來的長1/3。

規則

關於這個編碼的規則:

①.把3個字元變成4個字元。

②每76個字元加一個換行符。

③.最後的結束符也要處理。

例子(1)

轉換前 11111111, 11111111, 11111111 (二進位制)

轉換後 00111111, 00111111, 00111111, 00111111 (二進位制)

上面的三個位元組是原文,下面的四個位元組是轉換後的Base64編碼,其前兩位均為0。

轉換後,我們用一個碼錶來得到我們想要的字串(也就是最終的Base64編碼),這個表是這樣的:(摘自RFC2045)

轉換表

Table 1: The Base64 Alphabet

索引

對應字元

索引

對應字元

索引

對應字元

索引

對應字元

0

A

17

R

34

i

51

z

1

B

18

S

35

j

52

0

2

C

19

T

36

k

53

1

3

D

20

U

37

l

54

2

4

E

21

V

38

m

55

3

5

F

22

W

39

n

56

4

6

G

23

X

40

o

57

5

7

H

24

Y

41

p

58

6

8

I

25

Z

42

q

59

7

9

J

26

a

43

r

60

8

10

K

27

b

44

s

61

9

11

L

28

c

45

t

62

+

12

M

29

d

46

u

63

/

13

N

30

e

47

v

   

14

O

31

f

48

w

   

15

P

32

g

49

x

   

16

Q

33

h

50

y

   

例子(2)

轉換前 10101101,10111010,01110110

轉換後 00101011, 00011011 ,00101001 ,00110110

十進位制 43 27 41 54

對應碼錶中的值 r b p 2

所以上面的24位編碼,編碼後的Base64值為 rbp2

解碼同理,把 rbq2 的二進位制位連線上再重組得到三個8位值,得出原碼。

(解碼只是編碼的逆過程,有關MIME的RFC還有很多,如果需要詳細情況請自行查詢。)

第一個位元組,根據源位元組的第一個位元組處理。

規則:源第一位元組右移兩位,去掉低2位,高2位補零。

既:00 + 高6位

第二個位元組,根據源位元組的第一個位元組和第二個位元組聯合處理。

規則如下,第一個位元組高6位去掉然後左移四位,第二個位元組右移四位

即:源第一位元組低2位 + 源第2位元組高4位

第三個位元組,根據源位元組的第二個位元組和第三個位元組聯合處理,

規則第二個位元組去掉高4位並左移兩位(得高6位),第三個位元組右移6位並去掉高6位(得低2位),相加即可

第四個位元組,規則,源第三位元組去掉高2位即可

//用更接近於程式設計的思維來說,編碼的過程是這樣的:

//第一個字元通過右移2位獲得第一個目標字元的Base64表位置,根據這個數值取到表上相應的字元,就是第一//個目標字元。

//然後將第一個字元與0x03(00000011)進行與(&)操作並左移4位,接著第二個字元右移4位與前者相或(|),即獲得第二個目標字元。

//再將第二個字元與0x0f(00001111)進行與(&)操作並左移2位,接著第三個字元右移6位與前者相或(|),獲得第三個目標字元。

//最後將第三個字元與0x3f(00111111)進行與(&)操作即獲得第四個目標字元。

//在以上的每一個步驟之後,再把結果與 0x3F 進行 AND 位操作,就可以得到編碼後的字元了。

可是等等……聰明的你可能會問到,原文的位元組數量應該是3的倍數啊,如果這個條件不能滿足的話,那該怎麼辦呢?

我們的解決辦法是這樣的:原文剩餘的位元組根據編碼規則繼續單獨轉(1變2,2變3;不夠的位數用0補全),再用=號補滿4個位元組。這就是為什麼有些Base64編碼會以一個或兩個等號結束的原因,但等號最多隻有兩個。因為:

一個原位元組至少會變成兩個目標位元組

所以餘數任何情況下都只可能是0,1,2這三個數中的一個。如果餘數是0的話,就表示原文位元組數正好是3的倍數(最理想的情況)。如果是1的話,轉成2個Base64編碼字元,為了讓Base64編碼是4的倍數,就要補2個等號;同理,如果是2的話,就要補1個等號。

程式碼實現

編輯

JavaScript版

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

if (!Shotgun)

    var Shotgun = {};

if (!Shotgun.Js)

    Shotgun.Js = {};

Shotgun.Js.Base64 = {

    _table: [

        'A''B''C''D''E''F''G''H''I''J''K''L''M''N''O''P',

        'Q''R''S''T''U''V''W''X''Y''Z''a''b''c''d''e''f',

        'g''h''i''j''k''l''m''n''o''p''q''r''s''t''u''v',

        'w''x''y''z''0''1''2''3''4''5''6''7''8''9''+''/'

    ],

  

    encode: function (bin) {

        var codes = [];

        var un = 0;

        un = bin.length % 3;

        if (un == 1)

            bin.push(0, 0);

        else if (un == 2)

            bin.push(0);

        for (var i = 2; i < bin.length; i += 3) {

            var c = bin[i - 2] << 16;

            c |= bin[i - 1] << 8;

            c |= bin[i];

            codes.push(this._table[c >> 18 & 0x3f]);

            codes.push(this._table[c >> 12 & 0x3f]);

            codes.push(this._table[c >> 6 & 0x3f]);

            codes.push(this._table[c & 0x3f]);

        }

        if (un >= 1) {

            codes[codes.length - 1] = "=";

            bin.pop();

        }

        if (un == 1) {

            codes[codes.length - 2] = "=";

            bin.pop();

        }

        return codes.join("");

    },

    decode: function (base64Str) {

        var i = 0;

        var bin = [];

        var x = 0, code = 0, eq = 0;

        while (i < base64Str.length) {

            var c = base64Str.charAt(i++);

            var idx = this._table.indexOf(c);

            if (idx == -1) {

                switch (c) {

                    case '=': idx = 0; eq++; break;

                    case ' ':

                    case '\n':

                    case "\r":

                    case '\t':

                        continue;

                    default:

                        throw "message""\u0062\u0061\u0073\u0065\u0036\u0034\u002E\u0074\u0068\u0065\u002D\u0078\u002E\u0063\u006E\u0020\u0045\u0072\u0072\u006F\u0072\u003A\u65E0\u6548\u7F16\u7801\uFF1A" + c };

                }

            }

            if (eq > 0 && idx != 0)

                throw "message""\u0062\u0061\u0073\u0065\u0036\u0034\u002E\u0074\u0068\u0065\u002D\u0078\u002E\u0063\u006E\u0020\u0045\u0072\u0072\u006F\u0072\u003A\u7F16\u7801\u683C\u5F0F\u9519\u8BEF\uFF01" };

  

            code = code << 6 | idx;

            if (++x != 4)

                continue;

            bin.push(code >> 16);

            bin.push(code >> 8 & 0xff);

            bin.push(code & 0xff)

            code = x = 0;

        }

        if (code != 0)

            throw "message""\u0062\u0061\u0073\u0065\u0036\u0034\u002E\u0074\u0068\u0065\u002D\u0078\u002E\u0063\u006E\u0020\u0045\u0072\u0072\u006F\u0072\u003A\u7F16\u7801\u6570\u636E\u957F\u5EA6\u9519\u8BEF" };

        if (eq == 1)

            bin.pop();

        else if (eq == 2) {

            bin.pop();

            bin.pop();

        else if (eq > 2)

            throw "message""\u0062\u0061\u0073\u0065\u0036\u0034\u002E\u0074\u0068\u0065\u002D\u0078\u002E\u0063\u006E\u0020\u0045\u0072\u0072\u006F\u0072\u003A\u7F16\u7801\u683C\u5F0F\u9519\u8BEF\uFF01" };

  

        return bin;

    }

};

BASH版

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

base64Table=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /);

 

function str2binary() {

    idx=0;

    for((i=0; i<${#str}; i++)); do

        dividend=$(printf "%d" "'${str:i:1}");

        for((j=0;j<8;j++)); do

            let idx=8*i+7-j;

            let bin[$idx]=$dividend%2;

            dividend=$dividend/2;

        done;

    done;

    let idx=${#str}*8;

    for((i=0; i<appendEqualCnt*2; i++)); do

        let bin[$idx]=0;

        let idx++;

    done;

}

function calcBase64() {

    for((i=0; i<${#bin[*]}/6; i++)); do

        sum=0;

        for((j=0; j<6; j++)); do

            let idx=i*6+j;

            let n=6-1-j;

            let sum=sum+${bin[$idx]}*2**n;

        done;

        echo -n ${base64Table[$sum]};

    done

}

 

declare -a bin

function base64Encode() {

    read -p "please enter ASCII string:" str;

    let appendZero=${#str}*8%6;

    let bits=${#str}*8;

    appendEqualCnt=0;

    if [[ $appendZero -ne 0 ]]; then

        let appendEqualCnt=(6-$appendZero)/2;

    fi

    str2binary;

    calcBase64;

    if [[ $appendEqualCnt -eq 2 ]]; then

        echo -n "==";

    elif [[ $appendEqualCnt -eq 1 ]]; then

        echo -n "=";

    fi

    echo;

     

}

Java版

1

2

3

4

5

6

7

import java.util.Base64;

對於標準的Base64:

加密為字串使用Base64.getEncoder().encodeToString();

加密為位元組陣列使用Base64.getEncoder().encode();

解密使用Base64.getDecoder().decode();

對於URL安全或MIME的Base64,只需將上述getEncoder()getDecoder()更換為getUrlEncoder()getUrlDecoder()

或getMimeEncoder()和getMimeDecoder()即可。

PHP版

[下列程式碼僅在GBK中實現,UTF8程式碼請把 if($button=="迅雷地址->普通地址") echo substr(base64_decode(str_ireplace("thunder://","",$txt1)),2,-2); 這句改為if($button=="迅雷地址->普通地址") echo substr(mb_convert_encoding(base64_decode(str_ireplace("thunder://","",$txt1))),2,-2); 並把charset=gb2312改為charset=utf-8]

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

<?php

$txt1=trim($_POST['text1']);

$txt2=trim($_POST['text2']);

$txt3=trim($_POST['text3']);

$button=$_POST['button'];

?>

<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.0Transitional//EN">

<html>

<head>

<title>迅雷和FlashGet,QQ旋風地址地址轉換工具</title>

<metahttp-equiv="Content-Type"content="text/html;charset=gb2312">

<metacontent="迅雷,FlashGet,地址轉換,"name="keywords">

</head>

<body>

<formname="form1"method="post"action="">

<hrsize="1">

<h3>迅雷轉換</h3>

<P>轉換地址:

<inputname="text1"value="<?phpecho$txt1;?>"type="text"style="width:516px;"/></P>

<P>轉換後的:

<inputtype="text"value="<?php

if($button=="普通地址->迅雷地址")echo"thunder://".base64_encode("AA".$txt1."ZZ");

if($button=="迅雷地址->普通地址")echosubstr(base64_decode(str_ireplace("thunder://","",$txt1)),2,-2);

?>"style="width:516px;"/></P>

<P>

<inputtype="submit"name="button"value="普通地址->迅雷地址"/>

<inputtype="submit"name="button"value="迅雷地址->普通地址"/></P>

<h3>FlashGet轉換</h3>

<P>FlashGet地址:

<inputname="text2"value="<?phpecho$txt2;?>"type="text"style="width:516px;"/></P>

<P>轉換後地址:

<inputtype="text"value="<?php

if($button=="普通地址->FlashGet地址")echo"flashget://".base64_encode($txt2);

if($button=="FlashGet地址->普通地址")echostr_ireplace("[FLASHGET]","",base64_decode(str_ireplace("flashget://","",$txt2)));

?>"style="width:516px;"/></P>

<P>

<inputtype="submit"value="普通地址->FlashGet地址"name="button"/>

<inputtype="submit"value="FlashGet地址->普通地址"name="button"/></P>

<h3>QQ旋風轉換</h3>

<P>QQ旋風地址:

<inputname="text3"value="<?phpecho$txt3;?>"type="text"style="width:516px;"/></P>

<P>轉換後地址:

<inputtype="text"value="<?php

if($button=="普通地址->QQ旋風")echo"qqdl://".base64_encode($txt3);

if($button=="QQ旋風->普通地址")echobase64_decode(str_ireplace("qqdl://","",$txt3));

?>"style="width:516px;"/></P>

<P>

<inputtype="submit"value="普通地址->QQ旋風"name="button"/>

<inputtype="submit"value="QQ旋風->普通地址"name="button"/></P>

</form>

</body>

</html>

VB版

注:其中DigestStrToHexStr為可在程式外部呼叫加密函式

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

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

Option Explicit

'B as e64Encoding/DecodingAlgorithm

'By:DavidMidkif f([email protected])

'

'Thisalgorithmsencodes and decodesdatain to B as e64

'for mat.Thisfor matisextremelymoreefficientthan

'Hexadecimalencoding.

Private m_bytIndex(0 To 63) As Byte

Private m_bytReverseIndex(0 To 255) As Byte

Private Const k_bytEqualSign As Byte = 61

Private Const k_bytmask1 As Byte = 3

Private Const k_bytmask2 As Byte = 15

Private Const k_bytmask3 As Byte = 63

Private Const k_bytmask4 As Byte = 192

Private Const k_bytmask5 As Byte = 240

Private Const k_bytmask6 As Byte = 252

Private Const k_bytShift2 As Byte = 4

Private Const k_bytShift4 As Byte = 16

Private Const k_bytShift6 As Byte = 64

Private Const k_lMaxBytesPerLine As Long = 152

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As LongByVal Source As LongByVal Length As Long)

Public Function Decode64(sInput As StringAs String

If sInput = "" Then Exit Function

Decode64 = StrConv(DecodeArray64(sInput), vbUnicode)

End Function

Private Function DecodeArray64(sInput As StringAs Byte()

Dim bytInput() As Byte

Dim bytWorkspace() As Byte

Dim bytResult() As Byte

Dim lInputCounter As Long

Dim lWorkspaceCounter As Long

bytInput = Replace(Replace(sInput, vbCrLf, ""), "=""")

ReDim bytWorkspace(LBound(bytInput) To (UBound(bytInput) * 2)) As Byte

lWorkspaceCounter = LBound(bytWorkspace)

For lInputCounter = LBound(bytInput) To UBound(bytInput)

    bytInput(lInputCounter) = m_bytReverseIndex(bytInput(lInputCounter))

Next lInputCounter

For lInputCounter = LBound(bytInput) To (UBound(bytInput) - ((UBound(bytInput) Mod 8) + 8)) Step 8

    bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2) \ k_bytShift4)

    bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytmask2) * k_bytShift4) + (bytInput(lInputCounter + 4) \ k_bytShift2)

    bytWorkspace(lWorkspaceCounter + 2) = ((bytInput(lInputCounter + 4) And k_bytmask1) * k_bytShift6) + bytInput(lInputCounter + 6)

    lWorkspaceCounter = lWorkspaceCounter + 3

Next lInputCounter

Select Case (UBound(bytInput) Mod 8):

    Case 3:

        bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2) \ k_bytShift4)

    Case 5:

        bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2) \ k_bytShift4)

        bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytmask2) * k_bytShift4) + (bytInput(lInputCounter + 4) \ k_bytShift2)

        lWorkspaceCounter = lWorkspaceCounter + 1

    Case 7:

        bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2) \ k_bytShift4)

        bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytmask2) * k_bytShift4) + (bytInput(lInputCounter + 4) \ k_bytShift2)

        bytWorkspace(lWorkspaceCounter + 2) = ((bytInput(lInputCounter + 4) And k_bytmask1) * k_bytShift6) + bytInput(lInputCounter + 6)

        lWorkspaceCounter = lWorkspaceCounter + 2

End Select

ReDim bytResult(LBound(bytWorkspace) To lWorkspaceCounter) As Byte

If LBound(bytWorkspace) = 0 Then lWorkspaceCounter = lWorkspaceCounter + 1

    CopyMemoryVarPtr (bytResult(LBound(bytResult))), VarPtr(bytWorkspace(LBound(bytWorkspace))), lWorkspaceCounter

    DecodeArray64 = bytResult

End Function

Public Function Encode64(ByRefsInput As StringAs String

If sInput = "" Then Exit Function

Dim bytTemp() As Byte

bytTemp = StrConv(sInput, vbFromUnicode)

Encode64 = EncodeArray64(bytTemp)

End Function

Private Function EncodeArray64(ByRefbytInput() As ByteAs String

On Error GoTo ErrorHandler

Dim bytWorkspace() As Byte, bytResult() As Byte

Dim bytCrLf(0 To 3) As Byte, lCounter As Long

Dim lWorkspaceCounter As Long, lLineCounter As Long

Dim lCompleteLines As Long, lBytesRemaining As Long

Dim lpWorkSpace As Long, lpResult As Long

Dim lpCrLf As Long

If UBound(bytInput) < 1024 Then

    ReDim bytWorkspace(LBound(bytInput) To (LBound(bytInput) + 4096)) As Byte

Else

    ReDim bytWorkspace(LBound(bytInput) To (UBound(bytInput) * 4)) As Byte

End If

lWorkspaceCounter = LBound(bytWorkspace)

For lCounter = LBound(bytInput) To (UBound(bytInput) - ((UBound(bytInput) Mod 3) + 3)) Step 3

    bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter) \ k_bytShift2))

    bytWorkspace(lWorkspaceCounter + 2) = m_bytIndex(((bytInput(lCounter) And k_bytmask1) * k_bytShift4) + ((bytInput(lCounter + 1)) \ k_bytShift4))

    bytWorkspace(lWorkspaceCounter + 4) = m_bytIndex(((bytInput(lCounter + 1) And k_bytmask2) * k_bytShift2) + (bytInput(lCounter + 2) \ k_bytShift6))

    bytWorkspace(lWorkspaceCounter + 6) = m_bytIndex(bytInput(lCounter + 2) And k_bytmask3)

    lWorkspaceCounter = lWorkspaceCounter + 8

Next lCounter

Select Case (UBound(bytInput) Mod 3):

    Case 0:

        bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter)