加解密的技术分类
- 哈希函数 - SHA256、MD5
- 对称加密 - <font color=red>AES</font>、DES
- 非堆成加密 - <font color=red>RSA</font>、ECC、Elgamal
- 交换密钥 - <font color=red>DH</font>、ECDH
对称加密算法 —— AES
AES:Advanced Encryption Standard ,高级加密标准
-
加密:C= E(K,P),
- 其中P为明文,K为密钥,C为密文
-
解密:P = D(K,C),
- 其中C为密文,K为密钥,P为明文
特点:加密解密用同一个密钥。即用同样的方式还原明文。
优点:
- 加密效率高
- 计算量小
- 使用方便
缺点:
- 双方需要协商密钥
- 一旦密钥泄露则加密系统崩塌
- 密钥更新和维护困难
流程: 加密解密过程使用相同的密钥
public class AES {
private SecretKey mKey;
public AES() {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
//创建随机密码,并设置种子
SecureRandom secureRandom = new SecureRandom();
secureRandom.setSeed(System.currentTimeMillis());
//初始化密钥对象
keyGenerator.init(128, secureRandom);
//生成AES密钥并保存
mKey = keyGenerator.generateKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
public AES(byte[] key) {
mKey = new SecretKeySpec(key, "AES");
}
public byte[] getmKey() {
return mKey.getEncoded();
}
public void setmKey(byte[] key) {
this.mKey = new SecretKeySpec(key,"AES");
}
public byte[] encrpty(String content) {
if (mKey == null) {
return new byte[]{-1};
}
try {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, mKey);
return cipher.doFinal(content.getBytes());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return new byte[]{-1};
}
public byte[] decrypt(byte[] content) {
if (mKey == null) {
return new byte[]{-1};
}
try {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, mKey);
return cipher.doFinal(content);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return new byte[]{-1};
}
}
非对称加密算法 - RSA
RSA是一种公开密钥密码机制
-
RSA算法的可靠性基础
- 大质数相乘计算很容易
- 对极大质数做因数分解很困难
- 1111 x 3331 = 3700741
- 3700741 = ? x ?
特点:加密解密用不同的密钥。即用不同样的方式还原明文
优点:
- 公钥可以开放
- 密钥方便管理
- 安全性高
缺点:
- 性能差,加密时间长
- 使用相对复杂
流程:使用公钥加密,私钥解密(也有使用私钥加密,使用公钥解密的情况)
public class RSA {
private static final String RSA_ALOGORITHM = "RSA/ECB/PKCS1Padding";
//加密函数,传入明文、公钥;返回密文
@RequiresApi(api = Build.VERSION_CODES.O)
public static String encrypt(int data, String pubKey) {
//由于dh参数均为int类型,这里设计成对int加密
String message = String.valueOf(data);
byte[] decoded = DataUtils.base64Decode(pubKey);
byte[] result = new byte[0];
try {
try {
RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(decoded));
Cipher cipher = Cipher.getInstance(RSA_ALOGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
result = cipher.doFinal(message.getBytes("UTF-8"));
} catch (InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | UnsupportedEncodingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return DataUtils.base64Encode(result);
}
//传入密文及私钥,返回明文
@RequiresApi(api = Build.VERSION_CODES.O)
public static String decypt(String encrypted, String privateKey) {
byte[] decode = DataUtils.base64Decode(privateKey);
byte[] content = DataUtils.base64Decode(encrypted);
byte[] result = new byte[]{0};
//初始工作完成,开始进行解密
try {
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA")
.generatePrivate(new PKCS8EncodedKeySpec(decode));
Cipher cipher = Cipher.getInstance(RSA_ALOGORITHM);
cipher.init(Cipher.DECRYPT_MODE, priKey);
result = cipher.doFinal(content);
} catch (InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return new String(result);
}
}
密钥交换算法 - DH
DH:Diffie-Hellman,一种确保共享KEY安全的穿越不安全网络的方法
特点:
- 不需要保证信道安全
- 计算公式可完全公开
- 双方不需要知道对方的私钥
- 可协商出一个其他人都不知道的密钥
三个概念:
- PubKey:公钥(可公开)
- PriKey:私钥(不可公开)
- Sercet:密钥(加密用)
公钥公式:A|B = g exp (a|b) % p
密钥公式:s = B|A exp(a|b) % p
注: A,B是公钥,a,b是私钥,p,g是双方协定使用的,s是双方协商使用的密钥
public class DH {
private static final int dhP = 23;
private static final int dhG = 5;
private int mPriKey;
//在构造器中初始化好需要的参数,私钥
public DH(){
Random r = new Random();
mPriKey = r.nextInt(10);
System.out.println("dh prikey is : "+mPriKey);
}
public int getPublic(){
//使用公钥计算公式计算出自己的公钥,用以交换
return (int) (Math.pow(dhG, mPriKey) % dhP);
}
//接收对方的公钥,与自己的私钥通过密钥公式产生密钥
//因为需要作为AES的密钥,那么需要转换成byte[]
public byte[] getSecretKey(long publicKey){
int buf = (int) (Math.pow(publicKey, mPriKey) % dhP);
return sha256(buf);
}
public byte[] getSecretKey(byte[] publicKey){
int buf = (int) (Math.pow(DataUtils.byte2Int(publicKey), mPriKey) % dhP);
return sha256(buf);
}
//将DH交换之后的双方相同的密钥(int)做一个hash转换
//目的是转换成byte[128]类型,用做AES密钥
private byte[] sha256(int data){
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(DataUtils.int2Byte(data));
return messageDigest.digest();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return new byte[]{-1};
}
}
C/S网络模型
网络模型设计-C/S三次握手
- ClientHello 发送客户端DH公钥
- ServerHello 发送服务器DH公钥
- 确认收到,完成握手
客户端平台搭建
Android Http必备技能 - okHttp
- okHttp自带连接池,可减少请求延迟
- 支持GZIP压缩
- 有相应缓存可减少重复请求
万能的开放加密库-OpenSSL
OpenSSL:生成私钥命令:
genrsa -out rsa_private_key.pem 1024(该数值越大保密性越强,效率越低)
OpenSSL:生成RSA公钥命令:
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
AES对称加密
AES加密库的使用:
- 根据AES密钥创建Secret密钥向量
- 生成初始化参数向量
- 获取AES Cipher
- 执行加密
- Base64编码(建议)
DH密钥交换
- DH密钥交换主要是两个公式的编写,即:
- 公钥计算公式
- 密钥计算公式
- 生成随机数作为私钥
- 预置质数原根对
网友评论