Android移动开发-Android数据加密与解密的实现
来源:互联网 发布:看板设计软件 编辑:程序博客网 时间:2024/05/29 09:24
数据的安全是非常重要的,现在无论干什么都要账号和密码,一旦账号与密码泄露出去必将造成财产的损失,所以做好数据保密是非常重要的。
Android加密算法有多种多样,常见的有MD5、RSA、AES、3DES四种。
- MD5加密:
MD5是不可逆的加密算法,也就是无法解密,主要用于客户端的用户密码加密。MD5算法加密代码如下:
- 定义工具类MD5Util.java逻辑代码如下:
package com.fukaimei.encryptiontest.util;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;public class MD5Util { //首先初始化一个MessageDigest对象,该对象通过update方法获取原始数据, //并调用digest方法完成哈希计算,然后把字节数组逐位转换为十六进制数,最后拼装加密字符串 public static String encrypBy(String raw) { String md5Str = raw; try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(raw.getBytes()); byte[] encryContext = md.digest(); int i; StringBuffer buf = new StringBuffer(""); for (int offset = 0; offset < encryContext.length; offset++) { i = encryContext[offset]; if (i < 0) { i += 256; } if (i < 16) { buf.append("0"); } buf.append(Integer.toHexString(i)); } md5Str = buf.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return md5Str; }}
无论原始字符串是什么,MD5算法的加密串都是32位的十六进制字符串。
- RSA加密:
RSA算法在客户端使用公钥加密,在服务端使用私钥解密。这样一来,即使加密的公钥被泄露,没有私钥仍然无法解密。(注意:使用RSA加密之前必须在AndroidStudio的libs目录下导入bcprov-jdk的jar包)RSA算法的加密代码如下:
- 定义工具类RSAUtil.java逻辑代码如下:
package com.fukaimei.encryptiontest.util;import com.fukaimei.encryptiontest.util.tool.ConvertBytesToBase64;import java.io.ByteArrayOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.math.BigInteger;import java.net.URLDecoder;import java.net.URLEncoder;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.NoSuchAlgorithmException;import java.security.PrivateKey;import java.security.PublicKey;import java.security.SecureRandom;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.InvalidKeySpecException;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.RSAPrivateKeySpec;import java.security.spec.RSAPublicKeySpec;import java.security.spec.X509EncodedKeySpec;import javax.crypto.Cipher;//RSA 工具类。提供加密,解密,生成密钥对等方法。public class RSAUtil { private static final String TAG = "RSAUtil"; private static final String Algorithm = "RSA";// private static String RSAKeyStore = "E:/RSAKey.txt";//// //生成密钥对// private static KeyPair generateKeyPair() throws Exception {// try {// KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(Algorithm,// new org.bouncycastle.jce.provider.BouncyCastleProvider());// // 这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会降低// final int KEY_SIZE = 1024;// keyPairGen.initialize(KEY_SIZE, new SecureRandom());// KeyPair keyPair = keyPairGen.generateKeyPair();// saveKeyPair(keyPair);// return keyPair;// } catch (Exception e) {// throw new Exception(e.getMessage());// }// }//// private static KeyPair getKeyPair() throws Exception {// FileInputStream fis = new FileInputStream(RSAKeyStore);// ObjectInputStream oos = new ObjectInputStream(fis);// KeyPair kp = (KeyPair) oos.readObject();// oos.close();// fis.close();// return kp;// }//// private static void saveKeyPair(KeyPair kp) throws Exception {// FileOutputStream fos = new FileOutputStream(RSAKeyStore);// ObjectOutputStream oos = new ObjectOutputStream(fos);// oos.writeObject(kp);// oos.close();// fos.close();// }//// //生成公钥// private static RSAPublicKey generateRSAPublicKey(byte[] modulus,// byte[] publicExponent) throws Exception {// KeyFactory keyFac = null;// try {// keyFac = KeyFactory.getInstance(Algorithm,// new org.bouncycastle.jce.provider.BouncyCastleProvider());// } catch (NoSuchAlgorithmException ex) {// throw new Exception(ex.getMessage());// }//// RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(// modulus), new BigInteger(publicExponent));// try {// return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);// } catch (InvalidKeySpecException ex) {// throw new Exception(ex.getMessage());// }// }//// //生成私钥// private static RSAPrivateKey generateRSAPrivateKey(byte[] modulus,// byte[] privateExponent) throws Exception {// KeyFactory keyFac = null;// try {// keyFac = KeyFactory.getInstance(Algorithm,// new org.bouncycastle.jce.provider.BouncyCastleProvider());// } catch (NoSuchAlgorithmException ex) {// throw new Exception(ex.getMessage());// }//// RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(// modulus), new BigInteger(privateExponent));// try {// return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);// } catch (InvalidKeySpecException ex) {// throw new Exception(ex.getMessage());// }// }//// // 通过公钥byte[]将公钥还原,适用于RSA算法// private static PublicKey getPublicKey(byte[] keyBytes)// throws NoSuchAlgorithmException, InvalidKeySpecException {// X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);// KeyFactory keyFactory = KeyFactory.getInstance(Algorithm);// PublicKey publicKey = keyFactory.generatePublic(keySpec);// return publicKey;// }//// // 通过私钥byte[]将公钥还原,适用于RSA算法// private static PrivateKey getPrivateKey(byte[] keyBytes)// throws NoSuchAlgorithmException, InvalidKeySpecException {// PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);// KeyFactory keyFactory = KeyFactory.getInstance(Algorithm);// PrivateKey privateKey = keyFactory.generatePrivate(keySpec);// return privateKey;// } //加密 private static byte[] encrypt(PublicKey pk, byte[] data) throws Exception { try { Cipher cipher = Cipher.getInstance(Algorithm, new org.bouncycastle.jce.provider.BouncyCastleProvider()); cipher.init(Cipher.ENCRYPT_MODE, pk); int blockSize = cipher.getBlockSize(); int outputSize = cipher.getOutputSize(data.length); int leavedSize = data.length % blockSize; int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize; byte[] raw = new byte[outputSize * blocksSize]; int i = 0; while (data.length - i * blockSize > 0) { if (data.length - i * blockSize > blockSize) { cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize); } else { cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize); } i++; } return raw; } catch (Exception e) { throw new Exception(e.getMessage()); } } //解密 private static byte[] decrypt(PrivateKey pk, byte[] raw) throws Exception { try { Cipher cipher = Cipher.getInstance(Algorithm, new org.bouncycastle.jce.provider.BouncyCastleProvider()); cipher.init(cipher.DECRYPT_MODE, pk); int blockSize = cipher.getBlockSize(); ByteArrayOutputStream bout = new ByteArrayOutputStream(64); int j = 0; while (raw.length - j * blockSize > 0) { bout.write(cipher.doFinal(raw, j * blockSize, blockSize)); j++; } return bout.toByteArray(); } catch (Exception e) { throw new Exception(e.getMessage()); } } // 使用N、e值还原公钥 private static PublicKey getPublicKey(String modulus, String publicExponent, int radix) throws NoSuchAlgorithmException, InvalidKeySpecException { BigInteger bigIntModulus = new BigInteger(modulus, radix); BigInteger bigIntPrivateExponent = new BigInteger(publicExponent, radix); RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(keySpec); return publicKey; } // 使用N、d值还原私钥 private static PrivateKey getPrivateKey(String modulus, String privateExponent, int radix) throws NoSuchAlgorithmException, InvalidKeySpecException { BigInteger bigIntModulus = new BigInteger(modulus, radix); BigInteger bigIntPrivateExponent = new BigInteger(privateExponent, radix); RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(bigIntModulus, bigIntPrivateExponent); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); return privateKey; } //加密函数 public static String encodeRSA(RSAKeyData key_data, String src) { if (key_data == null) { //默认的密钥对 key_data = new RSAKeyData(); key_data.public_key = "10001"; key_data.private_key = ""; key_data.modulus = "c7f668eccc579bb75527424c21be31c104bb44c921b4788ebc82cddab5042909eaea2dd706431531392d79890f9091e13714285a7e79e9d1836397f847046ef2519c9b65022b48bf157fe409f8a42155734e65467d04ac844dfa0c2ae512517102986ba9b62d67d4c920eae40b2f11c363b218a703467d342faa81719f57e2c3"; key_data.radix = 16; } try { PublicKey key = getPublicKey(key_data.modulus, key_data.public_key, key_data.radix); String rev = encodeURL(new StringBuilder(src).reverse().toString()); byte[] en_byte = encrypt(key, rev.getBytes()); String base64 = encodeURL(ConvertBytesToBase64.BytesToBase64String(en_byte)); return base64; } catch (Exception e) { e.printStackTrace(); return "RSA加密失败"; } } //URL编码 private static String encodeURL(String str) { String encode_str = str; try { encode_str = URLEncoder.encode(str, "utf-8"); } catch (Exception e) { e.printStackTrace(); } return encode_str; } //URL解码 private static String decodeURL(String str) { String decode_str = str; try { decode_str = URLDecoder.decode(str, "utf-8"); } catch (Exception e) { e.printStackTrace(); } return decode_str; } public static class RSAKeyData { public String modulus; public String public_key; public String private_key; public int radix; public RSAKeyData() { modulus = ""; public_key = ""; private_key = ""; radix = 0; } }}
RSA算法加密结果是经过URL编码的字符串。
- AES加密:
AES是设计用来替换DES的高级加密算法。下面是AES算法加密和解密的代码:
- 定义工具类AesUtil.java逻辑代码如下:
package com.fukaimei.encryptiontest.util;import java.security.SecureRandom;import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import javax.crypto.spec.SecretKeySpec;public class AesUtil { private static final String Algorithm = "AES"; private final static String HEX = "0123456789ABCDEF"; //加密函数,key为密钥 public static String encrypt(String key, String src) throws Exception { byte[] rawKey = getRawKey(key.getBytes()); byte[] result = encrypt(rawKey, src.getBytes()); return toHex(result); } //解密函数。key值必须和加密时的key一致 public static String decrypt(String key, String encrypted) throws Exception { byte[] rawKey = getRawKey(key.getBytes()); byte[] enc = toByte(encrypted); byte[] result = decrypt(rawKey, enc); return new String(result); } private static void appendHex(StringBuffer sb, byte b) { sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); } private static byte[] getRawKey(byte[] seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance(Algorithm); // SHA1PRNG 强随机种子算法, 要区别Android 4.2.2以上版本的调用方法 SecureRandom sr = null; if (android.os.Build.VERSION.SDK_INT >= 17) { sr = SecureRandom.getInstance("SHA1PRNG", "Crypto"); } else { sr = SecureRandom.getInstance("SHA1PRNG"); } sr.setSeed(seed); kgen.init(256, sr); // 256位或128位或192位 SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; } private static byte[] encrypt(byte[] key, byte[] src) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(key, Algorithm); Cipher cipher = Cipher.getInstance(Algorithm); cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal(src); return encrypted; } private static byte[] decrypt(byte[] key, byte[] encrypted) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(key, Algorithm); Cipher cipher = Cipher.getInstance(Algorithm); cipher.init(Cipher.DECRYPT_MODE, skeySpec); byte[] decrypted = cipher.doFinal(encrypted); return decrypted; } private static byte[] toByte(String hexString) { int len = hexString.length() / 2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) { result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue(); } return result; } private static String toHex(byte[] buf) { if (buf == null) { return ""; } StringBuffer result = new StringBuffer(2 * buf.length); for (int i = 0; i < buf.length; i++) { appendHex(result, buf[i]); } return result.toString(); }}
AES算法是可逆算法,支持对加密字符串进行解密,前提是解密时密钥必须与加密时一致。
- 3DES加密:
3DES(Triple DES)是三重数据加密算法,相当于对每个数据块应用3次DES加密算法。因为原先DES算法的密钥长度过短,容易遭到暴力破解,所以3DES算法通过增加密钥的长度防范加密数据被破解。该算法的加密和解密代码如下:
- 定义工具类Des3Util.java逻辑代码如下:
package com.fukaimei.encryptiontest.util;import com.fukaimei.encryptiontest.util.base64.BASE64Decoder;import com.fukaimei.encryptiontest.util.base64.BASE64Encoder;import java.io.IOException;import java.io.UnsupportedEncodingException;import javax.crypto.Cipher;import javax.crypto.SecretKey;import javax.crypto.spec.SecretKeySpec;public class Des3Util { // 定义加密算法,DESede即3DES private static final String Algorithm = "DESede"; //加密函数。key为密钥 public static String encrypt(String key, String raw) { byte[] enBytes = encryptMode(key, raw.getBytes()); BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(enBytes); } //解密函数。key值必须和加密时的key一致 public static String decrypt(String key, String enc) { try { BASE64Decoder decoder = new BASE64Decoder(); byte[] enBytes = decoder.decodeBuffer(enc); byte[] deBytes = decryptMode(key, enBytes); return new String(deBytes); } catch (IOException e) { e.printStackTrace(); return enc; } } private static byte[] encryptMode(String key, byte[] src) { try { SecretKey deskey = new SecretKeySpec(build3DesKey(key), Algorithm); Cipher cipher = Cipher.getInstance(Algorithm); cipher.init(Cipher.ENCRYPT_MODE, deskey); return cipher.doFinal(src); } catch (Exception e) { e.printStackTrace(); return null; } } private static byte[] decryptMode(String key, byte[] src) { try { SecretKey deskey = new SecretKeySpec(build3DesKey(key), Algorithm); Cipher cipher = Cipher.getInstance(Algorithm); cipher.init(Cipher.DECRYPT_MODE, deskey); return cipher.doFinal(src); } catch (Exception e) { e.printStackTrace(); return null; } } //根据字符串生成密钥24位的字节数组 private static byte[] build3DesKey(String keyStr) throws UnsupportedEncodingException { byte[] key = new byte[24]; byte[] temp = keyStr.getBytes("UTF-8"); if (key.length > temp.length) { System.arraycopy(temp, 0, key, 0, temp.length); } else { System.arraycopy(temp, 0, key, 0, key.length); } return key; }}
3DES算法与AES一样是可逆算法,支持对加密字符串进行解密,前提是解密时密钥必须与加密时一致。
- layout/activity_main.xml界面布局代码如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="true" android:focusableInTouchMode="true" android:orientation="vertical" android:padding="5dp"> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:gravity="right" android:text="加密字符串:" android:textColor="#000000" android:textSize="16sp" /> <EditText android:id="@+id/et_raw" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="3" android:hint="请输入要加密的字符串" android:text="" android:textColor="#000000" android:textSize="16sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_md5" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="MD5加密" android:textColor="#000000" android:textSize="14sp" /> <Button android:id="@+id/btn_rsa" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="RSA加密" android:textColor="#000000" android:textSize="14sp" /> <Button android:id="@+id/btn_aes" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="AES加密" android:textColor="#000000" android:textSize="14sp" /> <Button android:id="@+id/btn_3des" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="3DES加密" android:textColor="#000000" android:textSize="14sp" /> </LinearLayout> <TextView android:id="@+id/tv_des" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="left" android:text="" android:textColor="#000000" android:textSize="18sp" /> </LinearLayout> </ScrollView></LinearLayout>
- MainActivity.java逻辑代码如下:
package com.fukaimei.encryptiontest;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.view.View.OnClickListener;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import com.fukaimei.encryptiontest.util.AesUtil;import com.fukaimei.encryptiontest.util.Des3Util;import com.fukaimei.encryptiontest.util.MD5Util;import com.fukaimei.encryptiontest.util.RSAUtil;public class MainActivity extends AppCompatActivity implements OnClickListener { private final static String TAG = "MainActivity"; private EditText et_raw; private TextView tv_des; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_raw = (EditText) findViewById(R.id.et_raw); tv_des = (TextView) findViewById(R.id.tv_des); findViewById(R.id.btn_md5).setOnClickListener(this); findViewById(R.id.btn_rsa).setOnClickListener(this); findViewById(R.id.btn_aes).setOnClickListener(this); findViewById(R.id.btn_3des).setOnClickListener(this); } @Override public void onClick(View v) { String raw = et_raw.getText().toString(); if (raw == null || raw.length() <= 0) { Toast.makeText(this, "请输入待加密字符串", Toast.LENGTH_LONG).show(); return; } if (v.getId() == R.id.btn_md5) { String enStr = MD5Util.encrypBy(raw); tv_des.setText("MD5的加密结果是:" + enStr); } else if (v.getId() == R.id.btn_rsa) { String enStr = RSAUtil.encodeRSA(null, raw); tv_des.setText("RSA加密结果是:" + enStr); } else if (v.getId() == R.id.btn_aes) { try { String seed = "a"; String enStr = AesUtil.encrypt(seed, raw); String deStr = AesUtil.decrypt(seed, enStr); String desc = String.format("AES加密结果是:%s\nAES解密结果是:%s", enStr, deStr); tv_des.setText(desc); } catch (Exception e) { e.printStackTrace(); tv_des.setText("AES加密/解密失败"); } } else if (v.getId() == R.id.btn_3des) { String key = "a"; String enStr = Des3Util.encrypt(key, raw); String deStr = Des3Util.decrypt(key, enStr); String desc = String.format("3DES加密结果是:%s\n3DES解密结果是:%s", enStr, new String(deStr)); tv_des.setText(desc); } }}
- Demo程序运行效果界面截图如下:
Demo程序源码下载地址一(GitHub)
Demo程序源码下载地址二(Gitee)
阅读全文
1 0
- Android移动开发-Android数据加密与解密的实现
- Android开发数据加密之手机端的加密解密
- android开发 文件数据的AES-128方式加密解密
- Android RSA加密与解密开发总结(可以与c#的RSA加密解密互通)
- Android RSA加密解密功能的实现
- Android文件的加密与解密
- 使用3DES加密与解密实习Android端和后台的数据加密传输
- Android开发之加密解密
- Android 对Android客户端与服务端传递的Json数据进行加密、解密操作
- Android RSA加密解密实现
- android AES加密解密实现
- 【Android】DES加密与解密
- Android - Base64加密与解密
- 数据的加密与解密
- Android客户端解密与C#服务端加密实现方法
- AES加密解密的数据和android的不一样效果?
- java实现DES数据加密与解密
- java实现DES数据加密与解密
- 三段式状态机的写法总结
- java练习题4
- 分割符和定长解码
- SPOJ10606 BALNUM
- Android7.0的systemUI的一些文章链接
- Android移动开发-Android数据加密与解密的实现
- 进程间通讯-无名管道
- NGUI与UGUI的区别及其优缺点
- Recyclerview小项目总结:加载妹子图片
- 从零开始学爬虫(一)
- Python常用运算符
- MyBatis学习总结(四)——解决字段名与实体类属性名不相同的冲突
- memset
- 【安全牛学习笔记】初识sql注入漏洞原理