加密算法
- 密算法分 对称加密 和 非对称加密,其中对称加密算法的加密与解密 密钥相同,非对称加密算法的加密密钥与解密 密钥不同,此外,还有一类 不需要密钥 的 散列算法
- 常见的 对称加密 算法主要有 DES、3DES、AES 等,
- 常见的 非对称算法 主要有 RSA、DSA 等
- 散列算法 主要有 SHA-1、MD5
具体
- MD5加密
1. 散列加密,生成128bit的大整数,返回的字节数组长度 为16,一个字节为8bit
2. 其结果为字节数组,一般将其转换为16进制的字符输出,共32个字符,16进制中,使用4bit表示一个数子(与int 32bit无关),故一个字节可以表示两个十六进制数字
3. 加密后,得到字节数据,但该字节数组不能为如gbk等方式进行编码,因为其不是根据该规则进行节码的,故强行编码会出现乱码,不可映射字符,此时,存在不可映射的字符串无法被转换为原有的字节数据;故将其转换为16进制表示;一个字节的最大表示为256,故可以拆分为两个16进制表示(此种方式与字符编码无关)
4. 对应字节,取其前四位和后四位分别生成两个字符
5. MD5是一种散列算法,没有秘钥的概念
6. 代码
MessageDigest messageDigest=MessageDigest.getInstance("MD5");
byte[] by=messageDigest.digest("abcergdfbchn".getBytes());
StringBuilder builder=new StringBuilder();
for (int i = 0; i < by.length; i++) {
builder.append(Integer.toHexString(by[i]>>4&0x0f));
builder.append(Integer.toHexString(by[i]&0x0f));
}
System.out.println(builder.toString());
- 对称加密
- 使用一种密钥进行加密和解密
- des加密
- 密钥仅支持8个字节 64位;
- 实际的密钥只有56位,另有8位是奇偶校验位,分布于64位密钥中,每8位中有1 位奇偶检验位.
- 使用56位密钥对64位的数据块进行加密,并对64位的数据块进行16轮编码
- 例子:
- 若明文为16字节,则将其前8字节作为明文数据块1,后8字节作为明文数据块2。加密时使用密钥(长度为8字节)依次对数据块1和数据块2进行独立的DES加密运算,分别生成密文数据块1和密文数据块2,最终将两个密文数据块顺序拼接在一起,至此完成DES加密运算。
- 3DES加密
- 就是3重DES加密,通俗的讲就是将明文数据块进行了3次DES运算,安全强度比DES更高。
- 此处仅以8字节明文数据进行举例说明。
- 3DES算法将24字节密钥以8字节长度进行了分组,前八字节为KEY1,中间8字节为KEY2,最后8字节为KEY3。
- 加密的时候,使用KEY1对明文数据块1进行DES加密得到C1,使用KEY2对C1进行DES解密得到C2,再用KEY3对C2进行DES加密得到C3。
- 解密的流程与之相反,先用KEY3对C3进行DES解密得到M3,再用KEY2对M3进行DES加密得到M2,最后用KEY1对M2进行DES解密得到M1。
- 实际使用中 一般为16字节,因为将KEY3设置与KEY1相等
- AES加密
- AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。
- 在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。
- 密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同,如下表所示:
- 加密轮次 128 10次;192 12次;256 14次
- 非对称加密
- 非对称加密分为公钥和私钥,公钥加密后的数据只能通过私钥才能解密,公钥本身不能解密,私钥同理
- 一般私钥自己保存,公钥暴露出去,信息交互时,接受经过公钥加密后的数据,然后用本地的私钥解密,发送数据时,发送私钥加密后的数据,对应端使用暴露出去的公钥进行解密
- 非对称加密安全性更高,但是加密解密的速度较对称加密会慢,一般策略为先将数据使用对称加密算法加密,然后使用非对称算法来传输对称算法的密钥
- RSA详解
- 进行加密是,要求需要加密的数据不能大于117字节(该数值为密钥长度/8-11,一般密钥长度为128字节,1024bit位),解密时,数据长度最大位128字节,一般进行分段加密和解密
- 在使用RSA加密的过程中,显然秘钥长度越长,加密的强度也就越强,同时程序计算的时间也会变长。秘钥长度增加一倍,密钥对生成的时间就增加16倍,公钥加密操作时长增加4倍,私钥解密操作时长增加8倍,所以秘钥长度视情况而定,不宜太大,否则效率低下。
- 通过KeyPairGenerator来生成RSA生成器,生成KeyPair,其中含有公钥和私钥,公钥对应的类为PublicKey,私钥对应的类为PrivateKey;一般会将key转换为二进制,然后将二进制通过base64编码,使用可以在网络间传输
- 进行解密时,得到的密钥要转为key来使用,通过X509EncodedKeySpec来表示公钥规范,PKCS8EncodedKeySpec来表示私钥规范,创建keyfactory,指定对应的算法,通过generatePublic方法,传入对应的规范,可以得到对应的key对象;构建cipher对象,传入对应的算法名称和key,通过其dofinal方法进行解密或者解密以及其他形式(在init时指定对应的模式,加密或解密以及其他)
- 使用cipher时,对应RSA,要使用分段的方式
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
int i = 0;
while (inputLen - offSet > 0) {
byte[] cache;
if (inputLen - offSet > 117) {
cache = cipher.doFinal(data, offSet, 117);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * 117;
}
byte[] encryptedData = out.toByteArray();
out.close();