base64加密是我们经常看到的一种加密方法,比如ESMTP的验证过程和二进制文件的网际传输等都会用到这种编码。
base64的加密方法算是比较简单的一种了,其编码过程是将原文按照每 6bit (记住,是以'位'为单位的)为一组对原文进行替换,因为6bit 可以表示的值的范围在0~63(2的6次方,一共64个),所以可以用一个长度为64的字符表对这 6bit 的值进行映射。
这个映射表通常是A-Z、a-z、0-9加上 + 和 / 两个符号,即"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"。
不过,在进行加密之前,我们要先解决一个问题,那就是一个字符通常为一个字节(byte),字节是 8bit 的,可是加密的时候是按照每 6bit 为单位进行的,那要怎么加密呢?
其实,base64编码的时候是以三个字节为一组进行的,这样三个字节就是 24bit ,那么 24bit ÷ 6bit = 4(个字符),所以说,经过base64加密后,每3个字符就会被加密成4个字符。也就是说,如果按照正常情况的话,被base64加密后的原文就比原来长了3/4。
当然,这事"正常"情况下,那么如果出现原文的长度不是3的倍数这种不正常的情况该怎么办呢?
如果原文的长度不够3的整数倍,那么就用"="号来填充。比如,如果最后剩余1个字符,不够3个,那么就在密文末尾加上两个"=",如果最后剩余1个字符,就在密文末尾添加一个"="。
再有,就是要填充位的问题,比如如果最后剩余了1个字符,那么这1个字符只有 8bit,这样将前 6bit 编码后就只剩下 2bit了,加密就办法再继续下去。所以要对不足的位用0来填充,下面举个例子就明白了:
现在要对"abcde"进行base64编码,那么加密完前三个字符后只剩下了"de",这两个字符的2进制表示是
"01100100 01100101",一共16位,如果要进行base64加密,就必须再填充两个0成为"01100100 01100101 00"。
这样就成了6的整数倍了,可以顺利完成加密。加密完后别忘了加上一个"="。
下面是实现代码,如果有错误,请留言指正:
func EncodeBase64(plain string) (cipher string) {
const key string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
var (
length int = len(plain)
loop_time int = length / 3
left int = length % 3
bytes_catnate int32
index int
)
for i := 0; i < loop_time; i++ {
bytes_catnate = int32(plain[index])<<16 + int32(plain[index+1])<<8 + int32(plain[index+2])
index += 3
cipher += string(key[(bytes_catnate>>18)&0x3F])
cipher += string(key[(bytes_catnate>>12)&0x3F])
cipher += string(key[(bytes_catnate>>6)&0x3F])
cipher += string(key[bytes_catnate&0x3F])
}
if left == 1 {
bytes_catnate = int32(plain[index]) << 4
cipher += string(key[(bytes_catnate>>6)&0x3F])
cipher += string(key[bytes_catnate&0x3F])
cipher += "=="
}
if left == 2 {
bytes_catnate = (int32(plain[index])<<8 + int32(plain[index+1])) << 2
cipher += string(key[(bytes_catnate>>12)&0x3F])
cipher += string(key[(bytes_catnate>>6)&0x3F])
cipher += string(key[bytes_catnate&0x3F])
cipher += "="
}
return cipher
}