频道栏目
首页 > 程序开发 > 移动开发 > Android > 正文
Android开发之常用的加密算法讲解
2018-05-14 11:29:20      个评论    来源:NervousDing的博客  
收藏   我要投稿

> 古典加密算法:凯撒加密

> ascii编码

> Byte和bit:二进制字节和位关系

> base64编码和解密

> 对称加密算法:DES、AES

> 非对称加密RSA

> 消息摘要:md5、sha1、sha256

> 数字签名:避免黑客抓包篡改参数

> 只有是一家公司,有能力,必须使用加密算法

> 目标:独立封装对称加密算法、非对称加密算法、使用md5加密用户登录/注册信息

![](img/usage.png)

### 02.ascii编码

> ASCII编码:美国信息标准交互码,就是用来显示西欧字符

![](img/ascii.png)

> 获取字符ascii编码

//获取单个字符ascii

char ch = 'A';

int ascii = ch;

//System.out.println(ascii);

//获取字符串ascii

String str = "Hello";

char[] charArray = str.toCharArray();

for (char c : charArray) {

int value = c;

System.out.println(value);

}

### 03.凯撒加密解密

> 古罗马大帝凯撒发明:对字符串偏移

![](img/kaiser.png)

public static String encrypt(String input, int key) {

StringBuilder stringBuilder = new StringBuilder();

//获取每一个字符ascii编码

char[] arr = input.toCharArray();

for (char c : arr) {

int ascii = c;

//偏移一位

ascii = ascii + key;

//获取ascii对应的字符

char result = (char) ascii;

//System.out.print(result);

stringBuilder.append(result);

}

return stringBuilder.toString();

}

public static String decrypt(String input, int key) {

StringBuilder stringBuilder = new StringBuilder();

//获取每一个字符ascii编码

char[] arr = input.toCharArray();

for (char c : arr) {

int ascii = c;

//偏移一位

ascii = ascii - key;

//获取ascii对应的字符

char result = (char) ascii;

//System.out.print(result);

stringBuilder.append(result);

}

return stringBuilder.toString();

}

### 04.频度分析法破解凯撒加密算法

> 根据统计学破解凯撒算法:一篇英文文章字母e出现的概率很高

### 05.Byte和bit

> Byte:字节,一个Byte有8位,1Byte=8bit

> bit:位

> 示例代码

String input = "A";//一个英文字母占1个字节(Byte)

String input2 = "我爱你";//一个中文utf-8编码表中占3个字节,一个中文gbk编码表中占2个字节

byte[] bytes = input.getBytes();//获取字符对应的Byte数组

System.out.println(bytes.length);

byte[] bytes2 = input2.getBytes();

byte[] bytes3 = input2.getBytes("GBK");

System.out.println(bytes2.length);

System.out.println("gbk编码:"+bytes3.length);

char[] charArray = input.toCharArray();

for (char c : charArray) {

int ascii = c;

System.out.println(ascii);

//转成二进制

String binaryString = Integer.toBinaryString(ascii);

System.out.println(binaryString);

}

### 06.常见对称加密算法介绍

> DES:企业级开发使用频率很高,Data Encryption Standard数据加密标准

> AES:Advanced Encryption Standard,高级数据加密标准,比DES破解难度大

> 底层机制:操作的不是字符,操作的是二进制(字符二进制显示成矩阵,矩阵变化)

### 07.DES加密

> DES:Data Encryption Standard数据加密标准

> 掌握参考api文档实现加密算法

> 对称加密三部曲:

* 1.创建cipher对象,cipher加密算法核心类

* 2.初始化加密/解密模式

* 3.加密/解密

> 加密算法、安全领域大量使用getInstance(参数) 方法

public static void main(String[] args) {

String input = "我爱你";

String password = "12345678";//秘钥:des秘钥长度是64个bit(位)

try {

//  1.创建cipher对象,cipher加密算法核心类

Cipher cipher = Cipher.getInstance("DES");

Key key = new SecretKeySpec(password.getBytes(), "DES");

//  2.初始化加密/解密模式:以后只要是对象参数是int,说明有常量

cipher.init(Cipher.ENCRYPT_MODE, key);//加密模式

//  3.加密

byte[] encrypt = cipher.doFinal(input.getBytes());

System.out.println("DES加密="+new String(encrypt));

} catch (Exception e) {

e.printStackTrace();

}

}

### 08.DES解密

public static byte[] encrypt(String input, String password) {

try {

//  1.创建cipher对象,cipher加密算法核心类

Cipher cipher = Cipher.getInstance("DES");

Key key = new SecretKeySpec(password.getBytes(), "DES");

//  2.初始化加密/解密模式:以后只要是对象参数是int,说明有常量

cipher.init(Cipher.ENCRYPT_MODE, key);//加密模式

//  3.加密

byte[] encrypt = cipher.doFinal(input.getBytes());

return encrypt;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

/**

* DES解密

*/

public static byte[] decrypt(byte[] input, String password) {

try {

//  1.创建cipher对象,cipher加密算法核心类

Cipher cipher = Cipher.getInstance("DES");

Key key = new SecretKeySpec(password.getBytes(), "DES");

//  2.初始化加密/解密模式:以后只要是对象参数是int,说明有常量

cipher.init(Cipher.DECRYPT_MODE, key);//解密模式

//  3.加密

byte[] decrypt = cipher.doFinal(input);

return decrypt;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

### 09.Base64编码和解码

> DES加密后密文长度是8个整数倍

> 加密后比明文长度变长,所以编码表找不到对应字符,乱码

> 使用Base64编码和解密:从Apache现在

> 1.加密后密文使用Base64编码

> 2.解密前对密文解码

public static String encrypt(String input, String password) {

try {

//  1.创建cipher对象,cipher加密算法核心类

Cipher cipher = Cipher.getInstance("DES");

Key key = new SecretKeySpec(password.getBytes(), "DES");

//  2.初始化加密/解密模式:以后只要是对象参数是int,说明有常量

cipher.init(Cipher.ENCRYPT_MODE, key);//加密模式

//  3.加密

byte[] encrypt = cipher.doFinal(input.getBytes());

return Base64.encode(encrypt);

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

/**

* DES解密

*/

public static String decrypt(String input, String password) {

try {

//  1.创建cipher对象,cipher加密算法核心类

Cipher cipher = Cipher.getInstance("DES");

Key key = new SecretKeySpec(password.getBytes(), "DES");

//  2.初始化加密/解密模式:以后只要是对象参数是int,说明有常量

cipher.init(Cipher.DECRYPT_MODE, key);//解密模式

//  3.加密

byte[] decrypt = cipher.doFinal(Base64.decode(input));

return new String(decrypt);

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

### 10.AES加密解密

public static String encrypt(String input, String password) {

try {

//对称加密三部曲

//1.创建cipher对象

Cipher cipher = Cipher.getInstance(TRANSFORMATION);

//SecretKeySpec:秘钥规范 -> 将字符串秘钥转成对象

Key key = new SecretKeySpec(password.getBytes(), TRANSFORMATION);

//2.初始化加密/解密模式

cipher.init(Cipher.ENCRYPT_MODE, key);

//3.加密

byte[] encrypt = cipher.doFinal(input.getBytes());

String encode = Base64.encode(encrypt);

return encode;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

/**

* AES解密

*/

public static String decrypt(String input, String password) {

try {

//对称加密三部曲

//1.创建cipher对象

Cipher cipher = Cipher.getInstance(TRANSFORMATION);

//SecretKeySpec:秘钥规范 -> 将字符串秘钥转成对象

Key key = new SecretKeySpec(password.getBytes(), TRANSFORMATION);

//2.初始化加密/解密模式

cipher.init(Cipher.DECRYPT_MODE, key);

//3.加密

byte[] encrypt = cipher.doFinal(Base64.decode(input));//解密前对密文解码

//String encode = Base64.encode(encrypt);

return new String(encrypt);

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

### 11.对称加密密钥长度分析

> DES秘钥长度:8个字符

> AES秘钥长度:16个字符

> DES加密后密文长度是8的整数倍

> AES加密后密文长度是16的整数倍

### 12.工作模式和填充模式

> IOS加密,android没有解密:工作模式和填充模式不一致

> 工作模式:如何加密(ECB:并行加密,分段加密,每一段不相互影响;CBC只能串行加密)

> 填充模式:加密后密文长度如果达不到指定整数倍(8个字节、16个字节),填充对应字符

### 13.工作模式填充模式的使用

> 默认工作模式/填充模式:ECB/PKCS5Padding

> CBC工作模式:报错Parameters missing,CBC模式需求额外参数

> NoPadding不填充模式:DES原文长度必须是8个字节整数倍,AES原文长度必须是16个字节整数倍

### 14.对称加密应用实战

> 算法:DES、AES,企业级开发使用DES足够安全,如果要求高使用AES

> 特点:可逆(加密后可以解密)

> 需求:从服务器获取数据,缓存到本地,加密

### 15.非对称加密算法RSA介绍

> RSA:到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式

> 秘钥对:公钥和私钥,秘钥对不能手动指定,必须有系统生成

> 加密速度慢:必须分段加密,不能加密大文件

> 公钥加密私钥解密;私钥加密公钥解密

> 公钥互换:连个商家合作需要交互公钥,但是私钥不能别人

### 16.非对称加密RSA生成秘钥对

> 不能手动指定,必须由系统生成:公钥和私钥

//非对称加密三部曲

//1.创建cipher对象

Cipher cipher = Cipher.getInstance(TRANSFORMATION);

//秘钥对生成器

KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGORITHM);

//秘钥对

KeyPair keyPair = generator.generateKeyPair();

PrivateKey privateKey = keyPair.getPrivate();

PublicKey publicKey = keyPair.getPublic();

//获取公钥和私钥字符串

String priateKeyStr = Base64.encode(privateKey.getEncoded());

String publicKeyStr = Base64.encode(publicKey.getEncoded());

### 17.非对称加密RSA加密

> 公钥加密和私钥加密

public static String encryptByPrivateKey(String input, PrivateKey privateKey) {

String encode;

try {

//非对称加密三部曲

//1.创建cipher对象

Cipher cipher = Cipher.getInstance(TRANSFORMATION);

//2.初始化加密/解密模式

cipher.init(Cipher.ENCRYPT_MODE, privateKey);//私钥加密

//3.加密/解密 

byte[] encryptByPrivateKey = cipher.doFinal(input.getBytes());

encode = Base64.encode(encryptByPrivateKey);

return encode;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

public static String encryptByPublicKey(String input, PublicKey publicKey) {

String encode;

try {

//非对称加密三部曲

//1.创建cipher对象

Cipher cipher = Cipher.getInstance(TRANSFORMATION);

//2.初始化加密/解密模式

cipher.init(Cipher.ENCRYPT_MODE, publicKey);//私钥加密

//3.加密/解密 

byte[] encryptByPrivateKey = cipher.doFinal(input.getBytes());

encode = Base64.encode(encryptByPrivateKey);

return encode;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

### 18.非对称加密RSA分段加密

> RSA每次最大只能加密117个字节

> 超过117字节,分段加密

public static String encryptByPrivateKey(String input, PrivateKey privateKey) {

String encode;

try {

byte[] bytes = input.getBytes();

//非对称加密三部曲

//1.创建cipher对象

Cipher cipher = Cipher.getInstance(TRANSFORMATION);

//2.初始化加密/解密模式

cipher.init(Cipher.ENCRYPT_MODE, privateKey);//私钥加密

//3.分段加密

int offset = 0;//当前加密位置

//缓冲区

byte[] buffer = new byte[1024];

ByteArrayOutputStream baos = new ByteArrayOutputStream();

while(bytes.length - offset > 0){

if(bytes.length - offset >= MAX_ENCRYPT_SIZE){

//加密完整块

buffer = cipher.doFinal(bytes, offset, MAX_ENCRYPT_SIZE);//加密117字节

offset += MAX_ENCRYPT_SIZE;

}else{

//最后一块

buffer = cipher.doFinal(bytes, offset, bytes.length - offset);

offset = bytes.length;

}

baos.write(buffer);

}

encode = Base64.encode(baos.toByteArray());

return encode;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

### 19.非对称加密RSA分段解密

public static String decryptByPrivateKey(String input, PrivateKey privateKey) {

String encode;

try {

byte[] bytes = Base64.decode(input);

//非对称加密三部曲

//1.创建cipher对象

Cipher cipher = Cipher.getInstance(TRANSFORMATION);

//2.初始化加密/解密模式

cipher.init(Cipher.DECRYPT_MODE, privateKey);//私钥解密

//3.分段加密

int offset = 0;//当前加密位置

//缓冲区

byte[] buffer = new byte[1024];

ByteArrayOutputStream baos = new ByteArrayOutputStream();

while(bytes.length - offset > 0){

if(bytes.length - offset >= MAX_DECRYPT_SIZE){

//加密完整块

buffer = cipher.doFinal(bytes, offset, MAX_DECRYPT_SIZE);//加密117字节

offset += MAX_DECRYPT_SIZE;

}else{

//最后一块

buffer = cipher.doFinal(bytes, offset, bytes.length - offset);

offset = bytes.length;

}

baos.write(buffer);

}

encode = baos.toString();

return encode;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

### 20.非对称加密保存秘钥对

> 每次都生成秘钥对:安卓加密有肯能IOS不能解密

> 第一次生成存储起来

KeyFactory kf = KeyFactory.getInstance(ALGORITHM);

//字符串秘钥转成对象类型

PrivateKey privateKey = kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.decode(PRIVATE_KEY)));

PublicKey publicKey = kf.generatePublic(new X509EncodedKeySpec(Base64.decode(PUBLIC_KEY)));

### 21.消息摘要介绍

> MessageDigest:消息摘要,摘要信息(唯一的),软件用判断正版盗版软件

> 三个算法:md5、sha1、sha256

> 特点:

* 不可逆(通过密文不能推出明文,只能撞库)

* 加密后密文长度固定,1kb字符串和1G字符串加密结果长度一样

### 22.消息摘要md5的使用

public static String md5(String input) {

try {

StringBuilder stringBuilder = new StringBuilder();

//获取消息摘要对象

MessageDigest md5 = MessageDigest.getInstance(ALGORITHM);

byte[] digest = md5.digest(input.getBytes());

String hex = HexUtils.toHex(digest);

//System.out.println(hex);

return hex;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

### 23.获取文件md5值

public static String md5File(String filePath){

FileInputStream fis = null;

try {

fis = new FileInputStream(filePath);

MessageDigest md5 = MessageDigest.getInstance(ALGORITHM);

byte[] buffer = new byte[1024];

int len = 0;

while((len = fis.read(buffer)) != -1){

md5.update(buffer, 0, len);

}

byte[] digest = md5.digest();

//转成16进制

String hex = HexUtils.toHex(digest);

return hex;

} catch (Exception e) {

e.printStackTrace();

} finally{

IoUtils.close(fis);

}

return null;

}

### 24.消息摘要sha1和sha256的使用

> md5:16(加密后密文长度16个字节),32(密文转成16进制32个字节)

> sha1:20(加密后密文长度20个字节),40(密文转成16进制40个字节)

> sha256:32(加密后密文长度32个字节),64(密文转成16进制64个字节)

### 25.消息摘要应用实战

> 开发中使用哪个算法:常用md5

> 应用场景:用户登录/注册,用户密码必须加密传输

> 只要是用户密码必须使用md5(不可逆的),服务器存储的是密文

InputStream ins = null;

String usrename = "heima104";

String password = "123456";

try {

String url = "https://120.77.241.119/EncryptServer/login?username=" 

+ usrename + "&password=" + MD5Utils.md5(password);

URL url2 = new URL(url);

HttpURLConnection conn = (HttpURLConnection) url2.openConnection();

System.out.println(url2.toURI().toString());

ins = conn.getInputStream();

String result = IoUtils.convertStreamToString(ins);

System.out.println(result);

} catch (Exception e) {

e.printStackTrace();

} finally {

IoUtils.close(ins);

}

> 撞库破解md5:不可能穷尽所有密文,加密多次,加盐

### 26.数字签名

> RSA数字签名:消息摘要和非对称加密的组合(SHA256withRSA)

> 作用:校验参数是否被篡改,保证数据传输安全

public static boolean verity(String input, PublicKey publicKey, String sign) {

try {

//1.获取数字签名对象

Signature signature = Signature.getInstance(ALGORITHM);

//2.初始化校验方法:必须使用公钥

signature.initVerify(publicKey);

signature.update(input.getBytes());

//3.开始校验

boolean verify = signature.verify(Base64.decode(sign));

//System.out.println("校验结果:"+verify);

return verify;

} catch (Exception e) {

e.printStackTrace();

}

return false;

}

public static String sign(String input, PrivateKey privateKey) {

try {

//1.获取数字签名对象

Signature signature = Signature.getInstance(ALGORITHM);

//2.初始化签名:必须使用使用

signature.initSign(privateKey);

signature.update(input.getBytes());

//3.开始签名

byte[] sign = signature.sign();

String encode = Base64.encode(sign);

//System.out.println("sign="+encode);

return encode;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

### 27.数字签名流程图分析

> RSA数字签名流程图:借鉴设计公司加密系统

![](img/rsa-sign.png)

### 28.数字签名应用实战-时间戳

> 登录url,抓包可以重复登录

> 如何避免抓包重复登录:添加时间戳

> 设置登录超时时间:比如20秒钟

点击复制链接 与好友分享!回本站首页
上一篇:Android开发之自定义View2学习
下一篇:Android开发学习之加密总结+支付集成问题
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站