java的MD5withRSA算法可以看到解密的内容么?
您好,
<一> MD5加密算法:
消息摘要算法第五版(Message Digest Algorithm),是一种单向加密算法,只能加密、无法解密。然而MD5加密算法已经被中国山东大学王小云教授成功破译,但是在安全性要求不高的场景下,MD5加密算法仍然具有应用价值。
1 创建md5对象:
<pre name="code" class="java">MessageDigest md5 = MessageDigestgetInstance("md5");
2 进行加密操作:
byte[] cipherData = md5digest(plainTextgetBytes());
3 将其中的每个字节转成十六进制字符串:byte类型的数据最高位是符号位,通过和0xff进行与操作,转换为int类型的正整数。
String toHexStr = IntegertoHexString(cipher & 0xff);
4 如果该正数小于16(长度为1个字符),前面拼接0占位:确保最后生成的是32位字符串。
builderappend(toHexStrlength() == 1 "0" + toHexStr : toHexStr);
5加密转换之后的字符串为:c0bb4f54f1d8b14caf6fe1069e5f93ad
6 完整的MD5算法应用如下所示:
/
功能简述: 测试MD5单向加密
@throws Exception
/
@Test
public void test01() throws Exception {
String plainText = "Hello , world !";
MessageDigest md5 = MessageDigestgetInstance("md5");
byte[] cipherData = md5digest(plainTextgetBytes());
StringBuilder builder = new StringBuilder();
for(byte cipher : cipherData) {
String toHexStr = IntegertoHexString(cipher & 0xff);
builderappend(toHexStrlength() == 1 "0" + toHexStr : toHexStr);
}
Systemoutprintln(buildertoString());
//c0bb4f54f1d8b14caf6fe1069e5f93ad
}
<二> 使用BASE64进行加密/解密:
使用BASE64算法通常用作对二进制数据进行加密,加密之后的数据不易被肉眼识别。严格来说,经过BASE64加密的数据其实没有安全性可言,因为它的加密解密算法都是公开的,典型的防菜鸟不防程序猿的呀。经过标准的BASE64算法加密后的数据,通常包含/、+、=等特殊符号,不适合作为url参数传递,幸运的是Apache的Commons Codec模块提供了对BASE64的进一步封装。 (参见最后一部分的说明)
1使用BASE64加密:
BASE64Encoder encoder = new BASE64Encoder();
String cipherText = encoderencode(plainTextgetBytes());
2使用BASE64解密:
BASE64Decoder decoder = new BASE64Decoder();
plainText = new String(decoderdecodeBuffer(cipherText));
3 完整代码示例:
/
功能简述: 使用BASE64进行双向加密/解密
@throws Exception
/
@Test
public void test02() throws Exception {
BASE64Encoder encoder = new BASE64Encoder();
BASE64Decoder decoder = new BASE64Decoder();
String plainText = "Hello , world !";
String cipherText = encoderencode(plainTextgetBytes());
Systemoutprintln("cipherText : " + cipherText);
//cipherText : SGVsbG8gLCB3b3JsZCAh
Systemoutprintln("plainText : " +
new String(decoderdecodeBuffer(cipherText)));
//plainText : Hello , world !
}
<三> 使用DES对称加密/解密:
数据加密标准算法(Data Encryption Standard),和BASE64最明显的区别就是有一个工作密钥,该密钥既用于加密、也用于解密,并且要求密钥是一个长度至少大于8位的字符串。使用DES加密、解密的核心是确保工作密钥的安全性。
1根据key生成密钥:
DESKeySpec keySpec = new DESKeySpec(keygetBytes());
SecretKeyFactory keyFactory = SecretKeyFactorygetInstance("des");
SecretKey secretKey = keyFactorygenerateSecret(keySpec);
2加密操作:
Cipher cipher = CiphergetInstance("des");
cipherinit(CipherENCRYPT_MODE, secretKey, new SecureRandom());
byte[] cipherData = cipherdoFinal(plainTextgetBytes());
3为了便于观察生成的加密数据,使用BASE64再次加密:
String cipherText = new BASE64Encoder()encode(cipherData);
生成密文如下:PtRYi3sp7TOR69UrKEIicA==
4解密操作:
cipherinit(CipherDECRYPT_MODE, secretKey, new SecureRandom());
byte[] plainData = cipherdoFinal(cipherData);
String plainText = new String(plainData);
5 完整的代码demo:
/
功能简述: 使用DES对称加密/解密
@throws Exception
/
@Test
public void test03() throws Exception {
String plainText = "Hello , world !";
String key = "12345678"; //要求key至少长度为8个字符
SecureRandom random = new SecureRandom();
DESKeySpec keySpec = new DESKeySpec(keygetBytes());
SecretKeyFactory keyFactory = SecretKeyFactorygetInstance("des");
SecretKey secretKey = keyFactorygenerateSecret(keySpec);
Cipher cipher = CiphergetInstance("des");
cipherinit(CipherENCRYPT_MODE, secretKey, random);
byte[] cipherData = cipherdoFinal(plainTextgetBytes());
Systemoutprintln("cipherText : " + new BASE64Encoder()encode(cipherData));
//PtRYi3sp7TOR69UrKEIicA==
cipherinit(CipherDECRYPT_MODE, secretKey, random);
byte[] plainData = cipherdoFinal(cipherData);
Systemoutprintln("plainText : " + new String(plainData));
//Hello , world !
}
<四> 使用RSA非对称加密/解密:
RSA算法是非对称加密算法的典型代表,既能加密、又能解密。和对称加密算法比如DES的明显区别在于用于加密、解密的密钥是不同的。使用RSA算法,只要密钥足够长(一般要求1024bit),加密的信息是不能被破解的。用户通过https协议访问服务器时,就是使用非对称加密算法进行数据的加密、解密操作的。
服务器发送数据给客户端时使用私钥(private key)进行加密,并且使用加密之后的数据和私钥生成数字签名(digital signature)并发送给客户端。客户端接收到服务器发送的数据会使用公钥(public key)对数据来进行解密,并且根据加密数据和公钥验证数字签名的有效性,防止加密数据在传输过程中被第三方进行了修改。
客户端发送数据给服务器时使用公钥进行加密,服务器接收到加密数据之后使用私钥进行解密。
1创建密钥对KeyPair:
KeyPairGenerator keyPairGenerator = KeyPairGeneratorgetInstance("rsa");
keyPairGeneratorinitialize(1024); //密钥长度推荐为1024位
KeyPair keyPair = keyPairGeneratorgenerateKeyPair();
2获取公钥/私钥:
PublicKey publicKey = keyPairgetPublic();
PrivateKey privateKey = keyPairgetPrivate();
3服务器数据使用私钥加密:
Cipher cipher = CiphergetInstance("rsa");
cipherinit(CipherENCRYPT_MODE, privateKey, new SecureRandom());
byte[] cipherData = cipherdoFinal(plainTextgetBytes());
4用户使用公钥解密:
cipherinit(CipherDECRYPT_MODE, publicKey, new SecureRandom());
byte[] plainData = cipherdoFinal(cipherData);
5服务器根据私钥和加密数据生成数字签名:
Signature signature = SignaturegetInstance("MD5withRSA");
signatureinitSign(privateKey);
signatureupdate(cipherData);
byte[] signData = signaturesign();
6用户根据公钥、加密数据验证数据是否被修改过:
signatureinitVerify(publicKey);
signatureupdate(cipherData);
boolean status = signatureverify(signData);
7 RSA算法代码demo:<img src="http://wwwcxyclubcn/Upload/Images/2014081321/99A5FC9C0C628374gif" alt="尴尬" title="尴尬" border="0">
/
功能简述: 使用RSA非对称加密/解密
@throws Exception
/
@Test
public void test04() throws Exception {
String plainText = "Hello , world !";
KeyPairGenerator keyPairGenerator = KeyPairGeneratorgetInstance("rsa");
keyPairGeneratorinitialize(1024);
KeyPair keyPair = keyPairGeneratorgenerateKeyPair();
PublicKey publicKey = keyPairgetPublic();
PrivateKey privateKey = keyPairgetPrivate();
Cipher cipher = CiphergetInstance("rsa");
SecureRandom random = new SecureRandom();
cipherinit(CipherENCRYPT_MODE, privateKey, random);
byte[] cipherData = cipherdoFinal(plainTextgetBytes());
Systemoutprintln("cipherText : " + new BASE64Encoder()encode(cipherData));
//gDsJxZM98U2GzHUtUTyZ/Ir/NXqRWKUJkl6olrLYCZHY3RnlF3olkWPZ35Dwz9BMRqaTL3oPuyVq
//sehvHExxj9RyrWpIYnYLBSURB1KVUSLMsd/ONFOD0fnJoGtIk+T/+3yybVL8M+RI+HzbE/jdYa/+
//yQ+vHwHqXhuzZ/N8iNg=
cipherinit(CipherDECRYPT_MODE, publicKey, random);
byte[] plainData = cipherdoFinal(cipherData);
Systemoutprintln("plainText : " + new String(plainData));
//Hello , world !
Signature signature = SignaturegetInstance("MD5withRSA");
signatureinitSign(privateKey);
signatureupdate(cipherData);
byte[] signData = signaturesign();
Systemoutprintln("signature : " + new BASE64Encoder()encode(signData));
//ADfoeKQn6eEHgLF8ETMXan3TfFO03R5u+cQEWtAQ2lRblLZw1DpzTlJJt1RXjU451I84v3297LhR
//co64p6Sq3kVt84wnRsQw5mucZnY+jRZNdXpcbwh2qsh8287NM2hxWqp4OOCf/+vKKXZ3pbJMNT/4
///t9ewo+KYCWKOgvu5QQ=
signatureinitVerify(publicKey);
signatureupdate(cipherData);
boolean status = signatureverify(signData);
Systemoutprintln("status : " + status);
//true
}
HTTPS其实是有两部分组成:HTTP + SSL / TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。具体是如何进行加密,解密,验证的,且看下图。
1 客户端发起HTTPS请求
这个没什么好说的,就是用户在浏览器里输入一个https网址,然后连接到server的443端口。
2 服务端的配置
采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面(startssl就是个不错的选择,有1年的免费服务)。这套证书其实就是一对公钥和私钥。如果对公钥和私钥不太理解,可以想象成一把钥匙和一个锁头,只是全世界只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。
3 传送证书
这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。
4 客户端解析证书
这部分工作是有客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随机值。然后用证书对该随机值进行加密。就好像上面说的,把随机值用锁头锁起来,这样除非有钥匙,不然看不到被锁住的内容。
5 传送加密信息
这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。
6 服务段解密信息
服务端用私钥解密后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进行对称加密。所谓对称加密就是,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,所以只要加密算法够彪悍,私钥够复杂,数据就够安全。
7 传输加密后的信息
这部分信息是服务段用私钥加密后的信息,可以在客户端被还原。
8 客户端解密信息
客户端用之前生成的私钥解密服务段传过来的信息,于是获取了解密后的内容。整个过程第三方即使监听到了数据,也束手无策。
0条评论