Android数据安全之Base64编码

来源:互联网 发布:centos7 安装python 编辑:程序博客网 时间:2024/06/05 06:29

Base64在平常开发中很常用,有些人认为Base64也算是一种加密算法,但我觉得严格意义上讲算是一种编码方式。只不过将明文按照特定的字节划分转换成暗文,并算不上是加密。因为如果真的拿来作为重要数据的加密方式的话,破解起来容易。当然这个见仁见智,以上仅仅是个人的理解。

定义

Base64是一种将二进制数据转成文本数据的方案,Base64编码本质上就是一种基于64个可打印字符来表示二进制数据的表示方法。
对于非二进制数据,是先将其转换成二进制形式,然后再转成文本数据。之所以叫base64,是因为无论明文是什么(比如汉字,特殊符号等),编码后只会变成字母A-Z、a-z和0-9 和+和/这64个字符,同时体积一般也会变成原来的4/3。

背景

在计算机中任何数据都是按ascll码存储的,而ascll码的128~255之间的值是不可见字符。比如图片二进制流的每个字节不可能全部是可见字符。而且在网络上交换数据时(以传统的邮件传送为例,它只支持可见字符的传送),比如说从A地传到B地,往往要经过多个路由设备,由于不同的设备对字符的处理方式有一些不同,这样那些不可见字符就有可能被处理错误,这是不利于传输的。所以就先把数据先做一个Base64编码,统统变成可见字符,这样出错的可能性就大降低了。

应用场景

1.把一些对象转换成String形式保存或者传输,比如上传图片,上传语音2.传输的数据不希望明文传输3.配合加密,即将加密后的字节数组转换成String形式

编码原理

 通过查看Base64的索引表,字符选用了”A-Z、a-z、0-9、+、/” 64个可打印字符。数值代表字符的索引,这个是标准Base64协议规定的,不能更改。64个字符用6个bit位就可以全部表示,需要注意的是一个Base64字符是8个bit,但是有效部分只有右边的6个bit,左边两个永远是0。
 
Base64编码表

下面举个例子,简单而言,对AST这个字符进行Base64编码:


1.首先先将每个字符换成10进制ASCII码,然后转成2进制,少位用0补齐,保证8位。

2.因为ASCII码大小是一字节也就是8位,3个8位。又因为3*8=4*6,我们给他分成4分,每份6位。如果少位都用0补齐。

3.把6位码前2位加两个0,比如010000转完后就是00010000,查找对于的十进制数,同时这个也是上表中的索引值。

4.根据索引值按照RFC里的BASE64标准查找换算,这样我们就得到了QVNU,也就是AST加密的结果。

代码实现

1.)字符串进行Base64编码

String encodedString = Base64.encodeToString("Base64编码".getBytes(), Base64.DEFAULT);Log.e("Base64", "Base64---->" + encodedString);

2.)字符串进行Base64解码

String decodedString =new String(Base64.decode(encodedString,Base64.DEFAULT));Log.e("Base64", "Base64---->" + decodedString);

3.)对文件进行Base64编码

File file = new File("/storage/emulated/0/pimsecure_debug.txt");FileInputStream inputFile = null;try {    inputFile = new FileInputStream(file);    byte[] buffer = new byte[(int) file.length()];    inputFile.read(buffer);    inputFile.close();    encodedString = Base64.encodeToString(buffer, Base64.DEFAULT);    Log.e("Base64", "Base64---->" + encodedString);} catch (Exception e) {    e.printStackTrace();}

4.)对文件进行Base64解码

File desFile = new File("/storage/emulated/0/pimsecure_debug_1.txt");FileOutputStream  fos = null;try {    byte[] decodeBytes = Base64.decode(encodedString.getBytes(), Base64.DEFAULT);    fos = new FileOutputStream(desFile);    fos.write(decodeBytes);    fos.close();} catch (Exception e) {    e.printStackTrace();}

5.)对图片进行Base64处理

//将图片Base64编码为字符串 private void saveIconData() {     //1. 准备图片,获取图片的bitmap对象     Bitmap iconBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);     //2. 把bitmap图片压缩输出     /**bitmap压缩输出 * format:压缩格式* quality:压缩的质量  0-100* stream:输出流*/     ByteArrayOutputStream baos = new ByteArrayOutputStream();     iconBitmap.compress(Bitmap.CompressFormat.PNG, 50, baos);     //3. 通过base64 byte[]转成String     String iconBase64Str = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);     Log.d("TAG:" + TAG, "----图片经base64编码后 :" + iconBase64Str);     tvEncodeStr.setText(iconBase64Str);     //4. 通过SharedPreferences保存icon的字符串     sp.edit().putString("icon", iconBase64Str).apply(); } //解码还原图片 private void showIconData(String iconStr) {     //5. 通过Base64解码icon的字符串     byte[] decodeIcon = Base64.decode(iconStr, Base64.DEFAULT);     //6. 把字节数组解码为bitmap位图对象     Bitmap iconBitmap = BitmapFactory.decodeByteArray(decodeIcon, 0, decodeIcon.length);     ivIcon.setImageBitmap(iconBitmap); }

6.)针对Base64.DEFAULT参数说明

无论是编码还是解码都会有一个参数Flags,Android提供了以下几种DEFAULT 这个参数是默认,使用默认的方法来加密NO_PADDING 这个参数是略去加密字符串最后的”=”NO_WRAP 这个参数意思是略去所有的换行符(设置后CRLF就没用了)CRLF 这个参数看起来比较眼熟,它就是Win风格的换行符,意思就是使用CR LF这一对作为一行的结尾而不是Unix风格的LFURL_SAFE 这个参数意思是加密时不使用对URL和文件名有特殊意义的字符来作为加密字符,具体就是以-和_取代+和/

Base64使用类

  • 使用sun.misc包下的BASE64Encoder及BASE64Decoder类。这两个类是sun公司的内部方法,并没有在java api中公开过。网上也有相关的这两个类,也许写法不同,但效果一样,可以拷到项目中做工具类使用。

  • Android2.2版本的源代码中提供的android.util包下的Base64类,以上的实现就是采用这个类。(我所采用)

  • 此外网上还有org.apache.commons.codec.binary.Base64类作为替代sun.misc包下的Base64类。

总结

大多数的编码都是由字符转化成二进制的过程,而从二进制转成字符的过程称为解码。而Base64的概念就恰好反了,由二进制转到字符称为编码,由字符到二进制称为解码。
当然,正因为如此,Base64也常常在加解密中使用到,因为加密后字节数组不属于任何字符集,如果字节用StringAPI转换成字符只能得到乱码,这时候就可以利用Base64了,这个在后面的加解密中有更详细的描述。

0 0
原创粉丝点击