整理下Base64相关的东西(OpenSSL/GO...)

xcltapestry · · 4876 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Base64在不同语言对接时,其实是有些小坑的,之前有碰过。

首先Base64的是啥? 阮一峰有一篇写得很赞的文章说得很明白。

然后是怎么编码?

我用OpenSSL写了个Base64解编码实现:

/*
 用openssl来做Base64加解密.
 Author: xcl
 Date:2015-9-17
*/
#include <cstdio>
#include <cstdlib>
#include <iostream>

#include "openssl/ssl.h"  
#include <openssl/bio.h>
#include <openssl/evp.h>

#if defined(WIN32) || defined(_WIN64)
	#pragma comment(lib, "libeay32.lib")
	#pragma comment(lib, "ssleay32.lib")
#endif

/*
NO_PADDING : 略去加密字符串最后的”=”
NO_WRAP : 略去所有的换行符

Android中的Base64.DEFAULT会在每超过76个字符后,自动加换行符,
并且在字符串最后也会加一个换行符.
所以与其对接时(比如IOS)要注意这点.可建议其选Base64.NO_WRAP类型.

而OpenSSL的命令行进行Base64时,则每超过64个字符就自动加换行符,并且也在最末尾自动加换行.
解编码命令行如下:
echo "Hello"|openssl enc -base64 
echo "SGVsbG8K"|openssl enc -base64 -d

*/
enum Base64{ NO_PADDING = 0, NO_WRAP};

std::string  Decode(std::string data,const int mode) { 
	printf("[Decode] 解密前:%s\r\n", data.c_str());
	size_t length = data.length();
	if (length == 0)return "";

	BIO *b64 = BIO_new(BIO_f_base64());
	if (mode == Base64::NO_WRAP) {
		BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
	}
	 
	BIO *mem = nullptr;
	mem = BIO_new_mem_buf(const_cast<char *>(data.c_str()), -1);
	mem = BIO_push(b64, mem);

	//char inbuf[512];
	//int inlen;
	//while ((inlen = BIO_read(b64, inbuf, 512)) > 0) {
	//	printf("解密后:%s \n\r\n", inbuf);
	//}		
	char * buffer = (char *)malloc(length);
	memset(buffer, 0, length);
	BIO_read(mem, buffer, length);	
	std::string ret(buffer);
	free(buffer);

	BIO_free_all(mem);
	printf("[Decode] 解密后:%s\r\n", ret.c_str());
	return ret;
}


std::string Encode(std::string data,const int mode) {	
	printf("[Encode] 加密前:%s\r\n", data.c_str());
	if (data.length() == 0)return "";

	//写入时,采用base64编码 
	BIO *b64 = BIO_new(BIO_f_base64());

	// 如果打开 BIO_FLAGS_BASE64_NO_NL ,则传入时要带"\n" 即"Hello\n",
	// 否则,还原后会丢失两个字符.
	if (Base64::NO_WRAP == mode) {
		data.append("\n");
		BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
	}

	// Create a memory BIO
	BIO *mem = BIO_new(BIO_s_mem());
	b64 = BIO_push(b64, mem);

	BIO_write(b64, data.c_str(),data.length());
	BIO_flush(b64);
	//BIO_puts(b64, data.c_str());

	//得到base64后的字符串
	BUF_MEM *pBuf = nullptr;
	BIO_get_mem_ptr(mem, &pBuf);
	std::string ret(pBuf->data);	
	free(pBuf);

	BIO_set_close(b64, BIO_NOCLOSE);
	BIO_free_all(b64);

	printf("[Encode] 加密后:%s\r\n", ret.c_str());
	return ret;
}

void main() {
	std::string s = "Hello";

	printf("//////////////////////////////\r\n");
	printf("NO_PADDING:\r\n");
	Base64 mode = Base64::NO_PADDING;
	s = Encode(s,mode);
    Decode(s,mode);

	printf("//////////////////////////////\r\n");
	printf("NO_WRAP:\r\n");
	
	s = "Hello";
	mode = Base64::NO_WRAP;
	s = Encode(s, mode);
	Decode(s, mode);

	system("pause");	
}

/*
//////////////////////////////
NO_PADDING:
[Encode] 加密前:Hello
[Encode] 加密后:SGVsbG8=

[Decode] 解密前:SGVsbG8=

[Decode] 解密后:Hello
//////////////////////////////
NO_WRAP:
[Encode] 加密前:Hello

[Encode] 加密后:SGVsbG8K
[Decode] 解密前:SGVsbG8K
[Decode] 解密后:Hello

请按任意键继续. . .
*/

对于Golang而言,官网就提供了一个很好的例子,有标准的Base64和URL的编码我在这贴下这个例子:

package main

import b64 "encoding/base64"
import "fmt"

func main() {
	data := "abc123!?$*&()'-=@~"

	sEnc := b64.StdEncoding.EncodeToString([]byte(data))
    fmt.Println(sEnc)
	
	
	sDec, _ := b64.StdEncoding.DecodeString(sEnc)
    fmt.Println(string(sDec))
    fmt.Println()
	
   uEnc := b64.URLEncoding.EncodeToString([]byte(data))
    fmt.Println(uEnc)
    uDec, _ := b64.URLEncoding.DecodeString(uEnc)
    fmt.Println(string(uDec))
}


$ go run base64-encoding.go
YWJjMTIzIT8kKiYoKSctPUB+
abc123!?$*&()'-=@~

YWJjMTIzIT8kKiYoKSctPUB-
abc123!?$*&()'-=@~

         如果对Go是怎么实现的感兴趣,这有源码.

 嗯,大致就这些.


BLOG: http://blog.csdn.net/xcl168







版权声明:本文为博主原创文章,未经博主允许不得转载。


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:xcltapestry

查看原文:整理下Base64相关的东西(OpenSSL/GO...)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4876 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传