y
=
des(kl)[des-1(kr)[des(kl[x])]]
解密方式为:
x
=
des-1
(kl)[des
(kr)[
des-1
(kl[y])]]
其中,des(kl[x])表示用密钥k对数据x进行des加密,des-1
(kl[y])表示用密钥k对数据y进行解密。
sessionkey的计算采用3des算法,计算出单倍长度的密钥。表示法为:sk
=
session(dk,data)
3des加密算法为:
void
3des(byte
doublekeystr[16],
byte
data[8],
byte
out[8])
{
byte
buf1[8],
buf2[8]
des
(&doublekeystr[0],
data,
buf1)
udes(&doublekeystr[8],
buf1,
buf2)
des
(&doublekeystr[0],
buf2,
out)
}
java DES 加密 解密 生成随机密钥举例说明:
//保存生成的key
public static void saveDesKey() {
try {
SecureRandom sr = new SecureRandom()
// 选择的DES算法生成一个KeyGenerator对象
KeyGenerator kg = KeyGenerator.getInstance("DES")
kg.init(sr)
// 相对路径 需要新建 conf 文件夹
// String fileName = "conf/DesKey.xml"
// 绝对路径
String fileName = "d:/DesKey.xml"
FileOutputStream fos = new FileOutputStream(fileName)
ObjectOutputStream oos = new ObjectOutputStream(fos)
// 生成密钥
Key key = kg.generateKey()
oos.writeObject(key)
oos.close()
} catch (Exception e) {
e.printStackTrace()
}
}
//获取生成的key
public static Key getKey() {
Key kp = null
try {
// 相对路径 需要新建 conf 文件夹
// String fileName = "conf/DesKey.xml"
// InputStream is = Encrypt.class.getClassLoader().getResourceAsStream(fileName)
// 绝对路径
String fileName = "d:/DesKey.xml"
FileInputStream is = new FileInputStream(fileName)
ObjectInputStream oos = new ObjectInputStream(is)
kp = (Key) oos.readObject()
oos.close()
} catch (Exception e) {
e.printStackTrace()
}
return kp
}
//加密开始
public static void encrypt(String file, String dest) throws Exception {
Cipher cipher = Cipher.getInstance("DES")
cipher.init(Cipher.ENCRYPT_MODE, getKey())
InputStream is = new FileInputStream(file)
OutputStream out = new FileOutputStream(dest)
CipherInputStream cis = new CipherInputStream(is, cipher)
byte[] buffer = new byte[1024]
int r
while ((r = cis.read(buffer)) >0) {
out.write(buffer, 0, r)
}
cis.close()
is.close()
out.close()
}
//解密开始
public static void decrypt(String file, String dest) throws Exception {
Cipher cipher = Cipher.getInstance("DES")
cipher.init(Cipher.DECRYPT_MODE, getKey())
InputStream is = new FileInputStream(file)
OutputStream out = new FileOutputStream(dest)
CipherOutputStream cos = new CipherOutputStream(out, cipher)
byte[] buffer = new byte[1024]
int r
while ((r = is.read(buffer)) >= 0) {
cos.write(buffer, 0, r)
}
cos.close()
out.close()
is.close()
}
}
//des加密主方法
public class DES {
public static void main(String[] args) throws Exception {
Encrypt.saveDesKey()
System.out.println("生成key")
Encrypt.getKey()
System.out.println("获取key")
Encrypt.encrypt("d:\\hello.txt", "d:\\encrypt.txt")
System.out.println("加密")
Encrypt.decrypt("d:\\encrypt.txt", "d:\\decrypt.txt")
System.out.println("解密")
}
以上方法亲测可用。
JAVA和.NET的系统类库里都有封装DES对称加密的实现方式,但是对外暴露的接口却各不相同,甚至有时会让自己难以解决其中的问题,比如JAVA加密后的结果在.NET中解密不出来等,由于最近项目有跨JAVA和.NET的加解密,经过我的分析调试,终于让它们可以互相加密解密了。
DES加密
DES是一种对称加密(Data Encryption Standard)算法,以前我写过一篇文章:.NET中加密解密相关知识,有过简单描述。
DES算法一般有两个关键点,第一个是加密算法,第二个是数据补位。
加密算法常见的有ECB模式和CBC模式:
ECB模式:电子密本方式,这是JAVA封装的DES算法的默认模式,就是将数据按照8个字节一段进行DES加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,则补足8个字节(注意:这里就涉及到数据补位了)进行计算,之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。
CBC模式:密文分组链接方式,这是.NET封装的DES算法的默认模式,它比较麻烦,加密步骤如下:
1、首先将数据按照8个字节一组进行分组得到D1D2......Dn(若数据不是8的整数倍,就涉及到数据补位了)
2、第一组数据D1与向量I异或后的结果进行DES加密得到第一组密文C1(注意:这里有向量I的说法,ECB模式下没有使用向量I)
3、第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2
4、之后的数据以此类推,得到Cn
5、按顺序连为C1C2C3......Cn即为加密结果。
数据补位一般有NoPadding和PKCS7Padding(JAVA中是PKCS5Padding)填充方式,PKCS7Padding和PKCS5Padding实际只是协议不一样,根据相关资料说明:PKCS5Padding明确定义了加密块是8字节,PKCS7Padding加密快可以是1-255之间。但是封装的DES算法默认都是8字节,所以可以认为他们一样。数据补位实际是在数据不满8字节的倍数,才补充到8字节的倍数的填充过程。
NoPadding填充方式:算法本身不填充,比如.NET的padding提供了有None,Zeros方式,分别为不填充和填充0的方式。
PKCS7Padding(PKCS5Padding)填充方式:为.NET和JAVA的默认填充方式,对加密数据字节长度对8取余为r,如r大于0,则补8-r个字节,字节为8-r的值;如果r等于0,则补8个字节8。比如:
加密字符串为为AAA,则补位为AAA55555加密字符串为BBBBBB,则补位为BBBBBB22;加密字符串为CCCCCCCC,则补位为CCCCCCCC88888888。