Android DES加密解密
网上的demo一搜一大堆,但是,基本上都是一知半解(包括我)。为什么呢?我在尝试分别在两个平台加密的时候,竟然发现Android DES 加密和java DES加密的程序不能互通。就是加密的结果不一样,更不要说Android平台的加密输入作为java DES的解密输出了。这样的话,客户端和服务器端就不能进行通信了。我网上之前也发帖子问了不少人,但是回答都不满意。
今天部门的另外一个同事跟我说了一下,才解决了这个不能互通的问题。
调用DES加密算法包最精要的就是下面两句话:
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);
CBC是工作模式,DES一共有电子密码本模式(ECB)、加密分组链接模式(CBC)、加密反馈模式(CFB)和输出反馈模式(OFB)四种模式,
PKCS5Padding是填充模式,还有其它的填充模式:
然后,cipher.init()一共有三个参数:Cipher.ENCRYPT_MODE, key, zeroIv,zeroIv就是初始化向量,一个8为字符数组。
工作模式、填充模式、初始化向量这三种因素一个都不能少。否则,如果你不指定的话,那么就要程序就要调用默认实现。问题就来了,这就与平台有关了。难怪网上一搜"DES加密结果不一致“,出现n多网页结果。(之前我并没有指定IV,被折磨了2周)
源程序如下(从java平台到android平台,我根本没有更改一行代码):
另外,一般情况下,加密后的结果都会用base64编码进行传输。
java平台:
主程序
public class testDES {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
String key = "12345678";
String text = "12345678";
String result1 = DES.encryptDES(text,key);
String result2 = DES.decryptDES(result1, key);
System.out.println(result1);
System.out.println(result2);
}
}
用到的DES加密类
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class DES {
private static byte[] iv = {1,2,3,4,5,6,7,8};
public static String encryptDES(String encryptString, String encryptKey) throws Exception {
// IvParameterSpec zeroIv = new IvParameterSpec(new byte[8]);
IvParameterSpec zeroIv = new IvParameterSpec(iv);
SecretKeySpec key = new SecretKeySpec(encryptKey.getBytes(), "DES");
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);
byte[] encryptedData = cipher.doFinal(encryptString.getBytes());
return Base64.encode(encryptedData);
}
public static String decryptDES(String decryptString, String decryptKey) throws Exception {
byte[] byteMi = new Base64().decode(decryptString);
IvParameterSpec zeroIv = new IvParameterSpec(iv);
// IvParameterSpec zeroIv = new IvParameterSpec(new byte[8]);
SecretKeySpec key = new SecretKeySpec(decryptKey.getBytes(), "DES");
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, zeroIv);
byte decryptedData[] = cipher.doFinal(byteMi);
return new String(decryptedData);
}
}
用到的BASE64工具类:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Base64 {
private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
/**
* data[]进行编码
* @param data
* @return
*/
public static String encode(byte[] data) {
int start = 0;
int len = data.length;
StringBuffer buf = new StringBuffer(data.length * 3 / 2);
int end = len - 3;
int i = start;
int n = 0;
while (i <= end) {
int d = ((((int) data[i]) & 0x0ff) << 16)
| ((((int) data[i + 1]) & 0x0ff) << 8)
| (((int) data[i + 2]) & 0x0ff);
buf.append(legalChars[(d >> 18) & 63]);
buf.append(legalChars[(d >> 12) & 63]);
buf.append(legalChars[(d >> 6) & 63]);
buf.append(legalChars[d & 63]);
i += 3;
if (n++ >= 14) {
n = 0;
buf.append(" ");
}
}
if (i == start + len - 2) {
int d = ((((int) data[i]) & 0x0ff) << 16)
| ((((int) data[i + 1]) & 255) << 8);
buf.append(legalChars[(d >> 18) & 63]);
buf.append(legalChars[(d >> 12) & 63]);
buf.append(legalChars[(d >> 6) & 63]);
buf.append("=");
} else if (i == start + len - 1) {
int d = (((int) data[i]) & 0x0ff) << 16;
buf.append(legalChars[(d >> 18) & 63]);
buf.append(legalChars[(d >> 12) & 63]);
buf.append("==");
}
return buf.toString();
}
private static int decode(char c) {
if (c >= 'A' && c <= 'Z')
return ((int) c) - 65;
else if (c >= 'a' && c <= 'z')
return ((int) c) - 97 + 26;
else if (c >= '0' && c <= '9')
return ((int) c) - 48 + 26 + 26;
else
switch (c) {
case '+':
return 62;
case '/':
return 63;
case '=':
return 0;
default:
throw new RuntimeException("unexpected code: " + c);
}
}
/**
* Decodes the given Base64 encoded String to a new byte array. The byte
* array holding the decoded data is returned.
*/
public static byte[] decode(String s) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
decode(s, bos);
} catch (IOException e) {
throw new RuntimeException();
}
byte[] decodedBytes = bos.toByteArray();
try {
bos.close();
bos = null;
} catch (IOException ex) {
System.err.println("Error while decoding BASE64: " + ex.toString());
}
return decodedBytes;
}
private static void decode(String s, OutputStream os) throws IOException {
int i = 0;
int len = s.length();
while (true) {
while (i < len && s.charAt(i) <= ' ')
i++;
if (i == len)
break;
int tri = (decode(s.charAt(i)) << 18)
+ (decode(s.charAt(i + 1)) << 12)
+ (decode(s.charAt(i + 2)) << 6)
+ (decode(s.charAt(i + 3)));
os.write((tri >> 16) & 255);
if (s.charAt(i + 2) == '=')
break;
os.write((tri >> 8) & 255);
if (s.charAt(i + 3) == '=')
break;
os.write(tri & 255);
i += 4;
}
}
}
adnroid平台的主函数:
public class main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String key = "12345678";
String text = "12345678";
try {
String result1 = DES.encryptDES(text,key);
String result2 = DES.decryptDES(result1, key);
Log.i("DES encode text is ", result1);
Log.i("DES encode text is ", result2);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
通过查看log日志就可以看到结果。
两个平台的结果是一样的,都是:
加密结果:X2p9Uo45Tzk6Ntu6W7Ev+Q==
解密结果:12345678
最近做项目,需要加密Android客户端的一些sql语句,我当时使用的是DES加密的,结果加密出现了
1.javax.crypto.BadPaddingException: Given final block not properly padded
这样的错误,要不就是出现乱码的问题,很纠结!当时查了一些资料,就有可能是密钥的问题或者编码的问题,检查了发现,密钥正确的,就是在创建Key 的时候,得到的byte[]数组有一些处理的,具体完整的代码如下:
1.package com.spring.sky.util;
2.
3.import java.io.BufferedReader;
4.import java.io.BufferedWriter;
5.import java.io.FileInputStream;
6.import java.io.FileNotFoundException;
7.import java.io.FileOutputStream;
8.import java.io.IOException;
9.import java.io.InputStream;
10.import java.io.InputStreamReader;
11.import java.io.OutputStream;
12.import java.security.Key;
13.
14.import javax.crypto.Cipher;
15.import javax.crypto.CipherInputStream;
16.import javax.crypto.spec.SecretKeySpec;
17.
18.import org.apache.http.entity.InputStreamEntity;
19.
20./***
21. * DES文件加密&解密 <br>
22. * 可以实现android和window的文件互通
23. * @author spring.sky
24. * Email:vipa1888@163.com
25. * QQ:840950105
26. *
27. */
28.public class FileDES {
29. /**加密解密的key*/
30. private Key mKey;
31. /**解密的密码*/
32. private Cipher mDecryptCipher;
33. /**加密的密码*/
34. private Cipher mEncryptCipher;
35. public FileDES(String key) throws Exception
36. {
37. initKey(key);
38. initCipher();
39. }
40.
41. /**
42. * 创建一个加密解密的key
43. * @param keyRule
44. */
45. public void initKey(String keyRule) {
46. byte[] keyByte = keyRule.getBytes();
47. // 创建一个空的八位数组,默认情况下为0
48. byte[] byteTemp = new byte[8];
49. // 将用户指定的规则转换成八位数组
50. for (int i = 0; i < byteTemp.length && i < keyByte.length; i++) {
51. byteTemp[i] = keyByte[i];
52. }
53. mKey = new SecretKeySpec(byteTemp, "DES");
54. }
55.
56. /***
57. * 初始化加载密码
58. * @throws Exception
59. */
60. private void initCipher() throws Exception
61. {
62. mEncryptCipher = Cipher.getInstance("DES");
63. mEncryptCipher.init(Cipher.ENCRYPT_MODE, mKey);
64.
65. mDecryptCipher = Cipher.getInstance("DES");
66. mDecryptCipher.init(Cipher.DECRYPT_MODE, mKey);
67. }
68.
69. /**
70. * 加密文件
71. * @param in
72. * @param savePath 加密后保存的位置
73. */
74. public void doEncryptFile(InputStream in,String savePath)
75. {
76. if(in==null)
77. {
78. System.out.println("inputstream is null");
79. return;
80. }
81. try {
82. CipherInputStream cin = new CipherInputStream(in, mEncryptCipher);
83. OutputStream os = new FileOutputStream(savePath);
84. byte[] bytes = new byte[1024];
85. int len = -1;
86. while((len=cin.read(bytes))>0)
87. {
88. os.write(bytes, 0, len);
89. os.flush();
90. }
91. os.close();
92. cin.close();
93. in.close();
94. System.out.println("加密成功");
95. } catch (Exception e) {
96. System.out.println("加密失败");
97. e.printStackTrace();
98. }
99. }
100.
101. /**
102. * 加密文件
103. * @param filePath 需要加密的文件路径
104. * @param savePath 加密后保存的位置
105. * @throws FileNotFoundException
106. */
107. public void doEncryptFile(String filePath,String savePath) throws FileNotFoundException
108. {
109. doEncryptFile(new FileInputStream(filePath), savePath);
110. }
111.
112.
113. /**
114. * 解密文件
115. * @param in
116. */
117. public void doDecryptFile(InputStream in)
118. {
119. if(in==null)
120. {
121. System.out.println("inputstream is null");
122. return;
123. }
124. try {
125. CipherInputStream cin = new CipherInputStream(in, mDecryptCipher);
126. BufferedReader reader = new BufferedReader(new InputStreamReader(cin)) ;
127. String line = null;
128. while((line=reader.readLine())!=null)
129. {
130. System.out.println(line);
131. }
132. reader.close();
133. cin.close();
134. in.close();
135. System.out.println("解密成功");
136. } catch (Exception e) {
137. System.out.println("解密失败");
138. e.printStackTrace();
139. }
140. }
141. /**
142. * 解密文件
143. * @param filePath 文件路径
144. * @throws Exception
145. */
146. public void doDecryptFile(String filePath) throws Exception
147. {
148. doDecryptFile(new FileInputStream(filePath));
149. }
150.
151.
152. public static void main(String[] args)throws Exception {
153. FileDES fileDES = new FileDES("spring.sky");
154. fileDES.doEncryptFile("d:/a.txt", "d:/b"); //加密
155. fileDES.doDecryptFile("d:/b"); //解密
156. }
157.
158.}
上面的代码,我分别在android 1.6和java平台上面测试通过了,没任何问题的,只是根据不同的需求做一下封装,希望对大家有帮忙,让大家少走弯路!
本篇文章来源于 Linux公社网站(www.linuxidc.com) 原文链接:http://www.linuxidc.com/Linux/2012-05/60017.htm
Android DES加密解密相关推荐
- Android平台和java平台 DES加密解密互通程序及其不能互通的原因
为什么80%的码农都做不了架构师?>>> 网上的demo一搜一大堆,但是,基本上都是一知半解(包括我).为什么呢?我在尝试分别在两个平台加密的时候,竟然发现Android DE ...
- Android RSA加密解密的 工具类的使用
RSA 比较特殊,我们首先要生成私钥和公钥,然后在加密的时候,使用私钥加密,在解密的时候使用公钥解密. //RSA 的初始化,获得私钥和密钥public void rsaInit(){try {Key ...
- Java实现DES加密解密
DES(Data Encryption Standard)是一种对称加密算法,所谓对称加密就是加密和解密都是使用同一个密钥. 加密原理: DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位, ...
- Java简单实现DES加密解密算法
Java简单实现DES加密解密算法 文章目录 Java简单实现DES加密解密算法 DES算法介绍 实现相关java类 代码实现 DES算法介绍 DEC加密算法属于对称加密,即利用指定的密钥,按照密码的 ...
- getcoo php_PHP简单实现DES加密解密的方法
本文实例讲述了PHP简单实现DES加密解密的方法.分享给大家供大家参考,具体如下: des加密: function des_encrypt($str, $key) { $block = mcrypt_ ...
- .net实现md5加密 sha1加密 sha256加密 sha384加密 sha512加密 des加密解密
写项目时,后台一直用md5加密,一天群里人问,除了MD5还有其它的加密方法吗?当时只知道还有个SHA,但怎么实现什么的都不清楚,于是当网上找了下,把几种常见的加密方法都整理了下,用winform写了个 ...
- python des解密_python实现DES加密解密方法实例详解
本文实例讲述了python实现DES加密解密方法.分享给大家供大家参考.具体分析如下: 实现功能:加密中文等字符串 密钥与明文可以不等长 这里只贴代码,加密过程可以自己百度,此处python代码没有优 ...
- java 实现 DES加密 解密算法
DES算法的入口参数有三个:Key.Data.Mode.其中Key为8个字节共64位,是DES算法的工作密钥:Data也为8个字节64位,是要被加密或被解密的数据:Mode为DES的工作方式,有两种: ...
- DES加密解密算法Java实现
DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小.这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半.使用子密钥对其中一半应 ...
- DES加密解密与AES加密解密
× 目录 [1]AES加密算法和DES加密算法的效率比较 [2]AES和DES加密解密代码 随着开发时间的变长,当初认为比较难的东西,现在渐渐也就变的不那么难了!特别对于一些经常很少使用的类,时间长了 ...
最新文章
- 原创jQuery移动设备弹出框插件——msgalert.js
- [转]Java加密算法
- C++之字节对齐与结构体大小
- Maverick.Net介绍 (来自http://www.cnblogs.com/RicCC/archive/2006/09/17/506890.html)
- mysql表空间界限_MySQL5.7 import表结构报错超出表空间界限
- 云原生和ServiceMesh主要组件--理解K8s/Istio/Envoy
- 大团圆结局!苹果高通和解:双方撤销全球所有诉讼
- Oracle连接数据库的方式
- JAVA IO - 高效读取大文件的后几行
- C++语言定义的标准转换
- MongoDB 的设计模式策略
- 蘑菇街基于Docker的私有云实践
- python数独解题器_python-2.7 – 数独生成器
- HTML三种对密码加密的方法
- 最全可编辑世界地图中国地图素材
- AspNetPager组件
- Maya---2018up4 Python 开发环境配置(win10x64)
- PXE + KS 实现系统自动部署系统
- Google开源C++单元测试框架gTest 5:死亡测试
- halcon例程学习笔记(11) 一维码、二维码识别
热门文章
- 网站运营手册_分享几款运营必备软件合集,欢迎补充
- lua 函数 默认值_简明lua教程
- sql like N#39;%%#39;,N 是代表什么意思 及Like语句详解
- 安庆集团-冲刺日志(第八天)
- 50个最新TypeScript面试题合集 – TypeScript开发教程
- 胡晓曼:MindSpore 开源运营与治理 | DEV. Together 2021 中国开发者生态峰会
- 项目管理知识体系指南 (六)
- Android获取手机存储空间大小
- Mac-记录一些超好用的快捷键
- 微信小程序tab页面切换