1、数字摘要
是指通过算法将长数据变为短数据,通常用来标识数据的唯一性,是否被修改,常用的加密算法有md5和sha1两种,如Android的App签名也是用的这两种算法。
md5具有不可逆性,也可用来作为密码加密,并且通常情况下为了让加密过程变得不可预测,我们会进行加盐操作,如下代码:
/**
* 使用md5方式进行加密
* @return
*/
public static String digest(String content){
StringBuilder builder = new StringBuilder();
try {
MessageDigest msgDitest = MessageDigest.getInstance("MD5");
msgDitest.update(content.getBytes());
byte[] digests = msgDitest.digest();
//将每个字节转为16进制
for (int i=0;i<digests.length;i++){
builder.append(Integer.toHexString(digests[i] & 0xff +8));//+8为加盐操作
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return builder.toString();
}
sha1也具有不可逆性,比md5长度更长,所以更安全,但是机密的效率md5要慢一些,如文件的秒传功能,以及相同的v4包冲突都是可以根据sha1值进行比对的。
/**
* 使用sha-1方式进行加密
* @return
*/
public static String digest(String content){
StringBuilder builder = new StringBuilder();
try {
MessageDigest msgDitest = MessageDigest.getInstance("SHA-1");
msgDitest.update(content.getBytes());
byte[] digests = msgDitest.digest();
//将每个字节转为16进制
for (int i=0;i<digests.length;i++){
builder.append(Integer.toHexString(digests[i] & 0xff +8));//+8为加盐操作
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return builder.toString();
}
不过呢,由于以上两种生成数字摘要的算法都是不可逆的,对于可逆的加密算法中,按照密钥的数量和加密规则一半分为对称加密和非对称加密两类:
对称加密:
密钥可以自己指定,只有一把密钥,如果密钥泄漏数据就会暴漏;
常用的对称加密算法有DES和AES两种;
特点是加密速度快,但是缺点是安全性低,因为只要密钥暴漏,数据就可以被解密。
非对称加密的特点:
常见的非对称加密算法是RSA;
他有两把密钥,且是由程序生成的,不能自己指定;
特点是加密速度比较慢,但是安全性比较高;
加密和解密的规则是:公钥加密只能私钥解密,私钥加密只能公钥解密;
应用场景举例:在集成支付宝支付SDK时,需要生成私钥和公钥,公钥需要设置到支付宝网站的管理后台,在程序中调用支付接口的时候,使用我们自己的私钥进行加密,这样支付宝在收到订单信息之后就可以通过公钥进行解密,其他人即时劫持了数据,但是没有公钥,也是无法解密的。
代码实践:使用AndroidUtils的工具类(工具类地址:https://github.com/zhaoyasong/ToolUtils)进行操作:
DES加密和解密的代码如下:
String data = "我是俊哥";
String desKey = "青龙偃月刀";// 密钥,口号
boolean isDesEncrypt = false;
private void useDes() {
try {
if(isDesEncrypt){
//解密
text.setText(Des.decrypt(text.getText().toString(), desKey));
}else {
//加密
text.setText(Des.encrypt(data, desKey));
}
isDesEncrypt = !isDesEncrypt; } catch (Exception e) {
e.printStackTrace();
}
}
RSA加密和解密的代码如下:
//1.生成密钥对,设计口号
try {
Map<String, Object> genKeyPair = RSACrypt.genKeyPair();
//2.获取公钥
publicKey = RSACrypt.getPublicKey(genKeyPair);
//3.获取私钥
privateKey = RSACrypt.getPrivateKey(genKeyPair);
} catch (Exception e) {
e.printStackTrace();
}
private boolean isRSAEncrypt = false;
protected void useRSA() {
try {
if(isRSAEncrypt){
//公钥解密
String str = text.getText().toString();
byte[] bs = RSACrypt.decryptByPublicKey(RSACrypt.decode(str), publicKey);
text.setText(new String(bs));
}else {
//私钥加密
byte[] bs = RSACrypt.encryptByPrivateKey(data.getBytes(), privateKey);
text.setText(RSACrypt.encode(bs));
}
isRSAEncrypt = !isRSAEncrypt;
} catch (Exception e) {
e.printStackTrace();
}
}