Skip to content

Commit 98c5fa1

Browse files
authored
Base64编解码库 (#81)
1 parent 00318d8 commit 98c5fa1

File tree

3 files changed

+171
-0
lines changed

3 files changed

+171
-0
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
pragma solidity ^0.4.25;
2+
3+
library LibBase64 {
4+
5+
bytes constant private base64stdchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
6+
7+
/**
8+
* 字符串 base64 编码
9+
*
10+
* @ param data 要解码的数据
11+
* @ return 经 base64 返回的编码数据
12+
*
13+
**/
14+
function encode(string memory data) internal pure returns(string memory) {
15+
uint i = 0;
16+
uint j = 0;
17+
18+
uint padlen = bytes(data).length;
19+
if (padlen % 3 != 0)
20+
padlen += (3 - (padlen % 3));
21+
22+
bytes memory _bs = bytes(data);
23+
bytes memory _ms = new bytes(padlen);
24+
25+
for (i = 0; i < _bs.length; i++) {
26+
_ms[i] = _bs[i];
27+
}
28+
29+
// 计算编码后的字符长度
30+
uint res_length = (padlen / 3) * 4;
31+
bytes memory res = new bytes(res_length);
32+
for (i = 0; i < padlen; i += 3) {
33+
// 取第一字符 _ms[i] 的前 6 比特位作为 base64 字符 0 的索引
34+
uint c0 = uint(uint8(_ms[i])) >> 2;
35+
// 取 _ms[i] 的后2位,在末尾补 _ms[i+1] 的前 4 位作为 base64 字符 1 的索引
36+
uint c1 = (uint(uint8(_ms[i])) & 3) << 4 | uint(uint8(_ms[i+1])) >> 4;
37+
// 取 _ms[i+1] 的后 4 位,在末尾补 _ms[i+2] 的前 2 位作为 base64 字符 2 的索引
38+
uint c2 = (uint(uint8(_ms[i+1])) & 15) << 2 | uint(uint8(_ms[i+2])) >> 6;
39+
// 取 _ms[i+2] 的后 6 位作为 base64 字符 3 的索引
40+
uint c3 = (uint(uint8(_ms[i+2])) & 63);
41+
42+
res[j] = base64stdchars[c0];
43+
res[j+1] = base64stdchars[c1];
44+
res[j+2] = base64stdchars[c2];
45+
res[j+3] = base64stdchars[c3];
46+
47+
j += 4;
48+
}
49+
50+
// 判断是否要补位,即 + 0 ,补位则设置索引为 64,对应 ‘=’ 字符
51+
if ((padlen - bytes(data).length) >= 1) {
52+
res[j-1] = base64stdchars[64];
53+
}
54+
if ((padlen - bytes(data).length) >= 2) {
55+
res[j-2] = base64stdchars[64];
56+
}
57+
58+
return string(res);
59+
}
60+
61+
/**
62+
* 字符串 base64 解码
63+
*
64+
* @ param data 要解码的数据
65+
* @ return 返回的解码数据
66+
*
67+
**/
68+
function decode(string memory data) internal pure returns(string memory) {
69+
require((bytes(data).length % 4) == 0, "Length not multiple of 4");
70+
bytes memory _bs = bytes(data);
71+
72+
uint i = 0;
73+
uint j = 0;
74+
uint dec_length = (_bs.length / 4) * 3;
75+
bytes memory dec = new bytes(dec_length);
76+
77+
for (; i< _bs.length; i+=4) {
78+
(dec[j], dec[j+1], dec[j+2]) = dencode4(
79+
bytes1(_bs[i]),
80+
bytes1(_bs[i+1]),
81+
bytes1(_bs[i+2]),
82+
bytes1(_bs[i+3])
83+
);
84+
j += 3;
85+
}
86+
while (dec[--j]==0) {}
87+
88+
bytes memory res = new bytes(j+1);
89+
for (i=0; i<=j; i++)
90+
res[i] = dec[i];
91+
92+
return string(res);
93+
}
94+
95+
// 将4个base64编码字符解码为原3个字符
96+
function dencode4 (
97+
bytes1 b0,
98+
bytes1 b1,
99+
bytes1 b2,
100+
bytes1 b3
101+
)
102+
private
103+
pure
104+
returns (bytes1 a0, bytes1 a1, bytes1 a2)
105+
{
106+
uint pos0 = charpos(b0);
107+
uint pos1 = charpos(b1);
108+
uint pos2 = charpos(b2) % 64;
109+
uint pos3 = charpos(b3) % 64;
110+
111+
// 取 b0 + b1 的前2位组成 8 比特位即 1 字节
112+
a0 = bytes1(uint8((pos0 << 2 | pos1 >> 4)));
113+
// 取 b1 后 4 位 + b2 的前 4 位组成 8 比特位即 1 字节
114+
a1 = bytes1(uint8(((pos1 & 15) << 4 | pos2 >> 2)));
115+
// 取 b2 前 2 位 + b3 组成 8 比特位即 1 字节
116+
a2 = bytes1(uint8(((pos2 & 3) << 6 | pos3)));
117+
}
118+
119+
// 检查是否是 base64 字符,返回字符索引
120+
function charpos(bytes1 char) private pure returns (uint pos) {
121+
for (; base64stdchars[pos] != char; pos++) {}
122+
require (base64stdchars[pos] == char, "Illegal char in string");
123+
return pos;
124+
}
125+
126+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
pragma solidity ^0.4.25;
2+
import "./LibBase64.sol";
3+
4+
contract LibBase64 {
5+
function test_encode() public pure returns (string memory) {
6+
string memory _str = "hello world";
7+
return LibBase64.encode(_str);
8+
}
9+
10+
function test_decode() public pure returns (string memory) {
11+
string memory _str = "aGVsbG8gd29ybGQ=";
12+
return LibBase64.decode(_str);
13+
}
14+
}

docs/common_tools/LibBase64.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# LibBase64.sol
2+
3+
LibBase64 提供Base64编解码
4+
5+
6+
## 接口说明
7+
1. function encode(string memory data) returns(string memory):Base64编码
8+
- data:要编码的数据
9+
10+
2. function decode(string memory data) returns(string memory):Base64解码
11+
- data:要解码的数据
12+
13+
## 使用方法
14+
15+
```
16+
pragma solidity ^0.4.25;
17+
import "./LibBase64.sol";
18+
19+
contract LibBase64 {
20+
function test_encode() public pure returns (string memory) {
21+
string memory _str = "hello world";
22+
return LibBase64.encode(_str);
23+
}
24+
25+
function test_decode() public pure returns (string memory) {
26+
string memory _str = "aGVsbG8gd29ybGQ=";
27+
return LibBase64.decode(_str);
28+
}
29+
}
30+
31+
```

0 commit comments

Comments
 (0)