因为研究GOOGLE的SSO DEMO,里面提到了XML DIGITAL SIGNATURE(JSR-105),然后又涉及到java security本身的一些东西,特此记录一下。
首先来说java security包含的几类
1.Message Digest(消息摘要),主要的算法有MD5和SHA1(算法本身为不可逆的),jdk本身都有支持,可以当作加密来用,举例比如说密码保存,当前用户A的设定密码123456,然后保存到数据库是用MD5加密过的字符串,当用户登录时,把输入的密码同样用MD5加密,然后与数据库中的比较,相同的话就认为密码是正确的。而在JSR-105中,主要的作用是对xml的信息进行摘要,然后摘要进行数字签名,这样比对整体xml的信息进行签名速度上要快很多。
2.Digital Signature(数字签名),一般采用的比较多的是非对称算法的公密钥体系,典型的是DSA和RSA,jdk本身也都有支持,基本过程如下,有字符串“ABC”要签名,先生成公密钥对,然后把用私钥签名,当需要验证签名时,使用公钥对字符串“ABC”进行处理后比对签名,来确认字符串“ABC”是否被修改过。在JSR-105中,一般公钥是放在saml中的,客户端接收到xml信息后,拿出xml信息的摘要和公钥进行签名,然后与xml里面本身的签名比对。
3.单钥密码,主要的算法有DES和AES(算法本身是可逆的),具体的例子就不多说了。
4.证书体系,这个东西比较复杂,不是三言两语能够说清楚的,这里就不讲了。
以上所有的详细内容可以看JAVA.2核心技术.卷II:高级特性7th。
5.Diffie-Hellman密钥一致协议(其他文章上看来的,也写在这里),公开密钥密码体制的奠基人Diffie和Hellman所提出的 "指数密钥一致协议" (Exponential Key Agreement Protocol),该协议不要求别的安全性先决条件,允许两名用户在公开媒体上交换信息以生成 "一致"的,可以共享的密钥。
大概过程如下:如 A 和 B 之间,A 现生成DH类型的密钥对,然后把公钥给B,B从A发送来的公钥中读出DH密钥对的初始参数生成bob的DH密钥对,B根据A的公钥生成本地的DES密钥,B已经生成了他的DES密钥,他现把他的公钥发给A,A根据B的公钥生成本地的DES密钥,通过这个过程就生成了相同的DES密钥,在这种基础就可进行安全能信。
import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.*;
import java.security.interfaces.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.crypto.interfaces.*;
import com.sun.crypto.provider.SunJCE;
public class testDHKey {
public static void main(String argv[]) {
try {
testDHKey my= new testDHKey();
my.run();
} catch (Exception e) {
System.err.println(e);
}
}
private void run() throws Exception {
Security.addProvider (new com.sun.crypto.provider.SunJCE());
System.out.println("ALICE: 产生 DH 对 ...");
KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");
aliceKpairGen.initialize (512);
KeyPair aliceKpair = aliceKpairGen.generateKeyPair(); //生成时间长
// 张三(Alice)生成公共密钥 alicePubKeyEnc 并发送给李四(Bob) ,
//比如用文件方式,socket.....
byte[] alicePubKeyEnc = aliceKpair.getPublic ().getEncoded();
//bob接收到alice的编码后的公钥,将其解码
KeyFactory bobKeyFac = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec (alicePubKeyEnc);
PublicKey alicePubKey = bobKeyFac.generatePublic(x509KeySpec);
System.out.println("alice公钥bob解码成功");
// bob必须用相同的参数初始化的他的DH KEY对,所以要从Alice发给他的公开密钥,
//中读出参数,再用这个参数初始化他的 DH key对
//从alicePubKye中取alice初始化时用的参数
DHParameterSpec dhParamSpec = ((DHPublicKey)alicePubKey).getParams();
KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
bobKpairGen.initialize(dhParamSpec);
KeyPair bobKpair = bobKpairGen.generateKeyPair();
System.out.println("BOB: 生成 DH key 对成功");
KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
bobKeyAgree.init(bobKpair.getPrivate());
System.out.println("BOB: 初始化本地key成功");
//李四(bob) 生成本地的密钥 bobDesKey
bobKeyAgree.doPhase(alicePubKey, true);
SecretKey bobDesKey = bobKeyAgree.generateSecret("DES");
System.out.println("BOB: 用alice的公钥定位本地key,生成本地DES密钥成功");
// Bob生成公共密钥 bobPubKeyEnc 并发送给Alice,
//比如用文件方式,socket.....,使其生成本地密钥
byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded();
System.out.println("BOB向ALICE发送公钥");
// alice接收到 bobPubKeyEnc后生成bobPubKey
// 再进行定位,使aliceKeyAgree定位在bobPubKey
KeyFactory aliceKeyFac = KeyFactory.getInstance("DH");
x509KeySpec = new X509EncodedKeySpec(bobPubKeyEnc);
PublicKey bobPubKey = aliceKeyFac.generatePublic(x509KeySpec);
System.out.println("ALICE接收BOB公钥并解码成功");
;
KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
aliceKeyAgree.init(aliceKpair.getPrivate());
System.out.println("ALICE: 初始化本地key成功");
aliceKeyAgree.doPhase(bobPubKey, true);
// 张三(alice) 生成本地的密钥 aliceDesKey
SecretKey aliceDesKey = aliceKeyAgree.generateSecret("DES");
System.out.println("ALICE: 用bob的公钥定位本地key,并生成本地DES密钥");
if (aliceDesKey.equals(bobDesKey)) System.out.println ("张三和李四的密钥相同");
//现在张三和李四的本地的deskey是相同的所以,完全可以进行发送加密,接收后解密,达到
//安全通道的的目的
/*
* bob用bobDesKey密钥加密信息
*/
Cipher bobCipher = Cipher.getInstance("DES");
bobCipher.init(Cipher.ENCRYPT_MODE, bobDesKey);
String bobinfo= "这是李四的机密信息";
System.out.println("李四加密前原文:"+bobinfo);
byte[] cleartext =bobinfo.getBytes();
byte[] ciphertext = bobCipher.doFinal(cleartext);
/*
* alice用aliceDesKey密钥解密
*/
Cipher aliceCipher = Cipher.getInstance("DES");
aliceCipher.init(Cipher.DECRYPT_MODE, aliceDesKey);
byte[] recovered = aliceCipher.doFinal(ciphertext);
System.out.println("alice解密bob的信息:"+(new String(recovered)));
if (!java.util.Arrays.equals(cleartext, recovered))
throw new Exception("解密后与原文信息不同");
System.out.println("解密后相同");
}
}