- 浏览: 56288 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
hastune:
收(和谐)藏了。以后当做知识结构吧基本都知道。都没有深入。哈哈 ...
java知识片段 -
geek87:
太有用了
java rss -
geek87:
谢谢LZ太用了。。我用 rsslib4j 其它的兼容太差了。解 ...
java rss -
zwq4166506:
楼主白痴,想用hibernate就用jboss啦
各容器实现持 ...
恶心的glassfish -
darkjune:
没什么好骂的吧
恶心的glassfish
2.1. 相关
Diffie-Hellman密钥一致协议和DES程序需要JCE工具库的支持,可以到 http://java.sun.com/security/index.html 或是www.bt285.cn 下载JCE,并进行安装。简易安装把 jce1.2.1\lib 下的所有内容复制到 %java_home%\lib\ext下,如果没有ext目录自行建立,再把jce1_2_1.jar和sunjce_provider.jar添加到 CLASSPATH内,更详细说明请看相应用户手册
2.2. 消息摘要MD5和SHA的使用
使用方法:
首先用生成一个MessageDigest类,确定计算方法
java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1");
添加要进行计算摘要的信息
alga.update(myinfo.getBytes());
计算出摘要
byte[] digesta=alga.digest();
发送给其他人你的信息和摘要
其他人用相同的方法初始化,添加信息,最后进行比较摘要是否相同
algb.isEqual(digesta,algb.digest())
相关AIP
java.security.MessageDigest 类
static getInstance(String algorithm)
返回一个MessageDigest对象,它实现指定的算法
参数:算法名,如 SHA-1 或MD5
void update (byte input)
void update (byte[] input)
void update(byte[] input, int offset, int len)
添加要进行计算摘要的信息
byte[] digest()
完成计算,返回计算得到的摘要(对于MD5是16位,SHA是20位)
void reset()
复位
static boolean isEqual(byte[] digesta, byte[] digestb)
比效两个摘要是否相同
代码:
import java.security.*;
public class myDigest {
public static void main(String[] args) {
myDigest my=new myDigest();
my.testDigest();
}
public void testDigest()
{
try {
String myinfo="我的测试信息";
//java.security.MessageDigest alg=java.security.MessageDigest.getInstance("MD5");
java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1");
alga.update(myinfo.getBytes());
byte[] digesta=alga.digest();
System.out.println("本信息摘要是:"+byte2hex(digesta));
//通过某中方式传给其他人你的信息(myinfo)和摘要(digesta) 对方可以判断是否更改或传输正常
java.security.MessageDigest algb=java.security.MessageDigest.getInstance("SHA-1");
algb.update(myinfo.getBytes());
if (algb.isEqual(digesta,algb.digest())) {
System.out.println("信息检查正常");
}
else
{
System.out.println("摘要不相同");
}
}
catch (java.security.NoSuchAlgorithmException ex) {
System.out.println("非法摘要算法");
}
}
public String byte2hex(byte[] b) //二行制转字符串
{
String hs="";
String stmp="";
for (int n=0;n<b.length;n++)
{
stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length()==1) hs=hs+"0"+stmp;
else hs=hs+stmp;
if (n<b.length-1) hs=hs+":";
}
return hs.toUpperCase();
}
}
2.3. 数字签名DSA
1. 对于一个用户来讲首先要生成他的密钥对,并且分别保存
生成一个KeyPairGenerator实例
java.security.KeyPairGenerator keygen=java.security.KeyPairGenerator.getInstance("DSA");
如果设定随机产生器就用如相代码初始化
SecureRandom secrand=new SecureRandom();
secrand.setSeed("tttt".getBytes()); //初始化随机产生器
keygen.initialize(512,secrand); //初始化密钥生成器
否则
keygen.initialize(512);
生成密钥公钥pubkey和私钥prikey
KeyPair keys=keygen.generateKeyPair(); //生成密钥组
PublicKey pubkey=keys.getPublic();
PrivateKey prikey=keys.getPrivate();
分别保存在myprikey.dat和mypubkey.dat中,以便下次不在生成
(生成密钥对的时间比较长
java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat"));
out.writeObject(prikey);
out.close();
out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat"));
out.writeObject(pubkey);
out.close();
2. 用他私人密钥(prikey)对他所确认的信息(info)进行数字签名产生一个签名数组
从文件中读入私人密钥(prikey)
java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat"));
PrivateKey myprikey=(PrivateKey)in.readObject();
in.close();
初始一个Signature对象,并用私钥对信息签名
java.security.Signature signet=java.security.Signature.getInstance("DSA");
signet.initSign(myprikey);
signet.update(myinfo.getBytes());
byte[] signed=signet.sign();
把信息和签名保存在一个文件中(myinfo.dat)
java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat"));
out.writeObject(myinfo);
out.writeObject(signed);
out.close();
把他的公钥的信息及签名发给其它用户
3. 其他用户用他的公共密钥(pubkey)和签名(signed)和信息(info)进行验证是否由他签名的信息
读入公钥
java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));
PublicKey pubkey=(PublicKey)in.readObject();
in.close();
读入签名和信息
in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat"));
String info=(String)in.readObject();
byte[] signed=(byte[])in.readObject();
in.close();
初始一个Signature对象,并用公钥和签名进行验证
java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");
signetcheck.initVerify(pubkey);
signetcheck.update(info.getBytes());
if (signetcheck.verify(signed)) { System.out.println("签名正常");}
对于密钥的保存本文是用对象流的方式保存和传送的,也可可以用编码的方式保存.注意要
import java.security.spec.*
import java.security.*
具休说明如下
* public key是用X.509编码的,例码如下:
byte[] bobEncodedPubKey=mypublic.getEncoded(); //生成编码
//传送二进制编码
//以下代码转换编码为相应key对象
X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey);
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);
* 对于Private key是用PKCS#8编码,例码如下:
byte[] bPKCS=myprikey.getEncoded();
//传送二进制编码
//以下代码转换编码为相应key对象
PKCS8EncodedKeySpec priPKCS8=new PKCS8EncodedKeySpec(bPKCS);
KeyFactory keyf=KeyFactory.getInstance("DSA");
PrivateKey otherprikey=keyf.generatePrivate(priPKCS8);
4. 常用API
java.security.KeyPairGenerator 密钥生成器类
public static KeyPairGenerator getInstance(String algorithm) throws NoSuchAlgorithmException
以指定的算法返回一个KeyPairGenerator 对象
参数: algorithm 算法名.如:"DSA","RSA"
public void initialize(int keysize)
以指定的长度初始化KeyPairGenerator对象,如果没有初始化系统以1024长度默认设置
参数:keysize 算法位长.其范围必须在 512 到 1024 之间,且必须为 64 的倍数
public void initialize(int keysize, SecureRandom random)
以指定的长度初始化和随机发生器初始化KeyPairGenerator对象
参数:keysize 算法位长.其范围必须在 512 到 1024 之间,且必须为 64 的倍数
random 一个随机位的来源(对于initialize(int keysize)使用了默认随机器
public abstract KeyPair generateKeyPair()
产生新密钥对
java.security.KeyPair 密钥对类
public PrivateKey getPrivate()
返回私钥
public PublicKey getPublic()
返回公钥
java.security.Signature 签名类
public static Signature getInstance(String algorithm) throws NoSuchAlgorithmException
返回一个指定算法的Signature对象
参数 algorithm 如:"DSA"
public final void initSign(PrivateKey privateKey)
throws InvalidKeyException
用指定的私钥初始化
参数:privateKey 所进行签名时用的私钥
public final void update(byte data)
throws SignatureException
public final void update(byte[] data)
throws SignatureException
public final void update(byte[] data, int off, int len)
throws SignatureException
添加要签名的信息
public final byte[] sign()
throws SignatureException
返回签名的数组,前提是initSign和update
public final void initVerify(PublicKey publicKey)
throws InvalidKeyException
用指定的公钥初始化
参数:publicKey 验证时用的公钥
public final boolean verify(byte[] signature)
throws SignatureException
验证签名是否有效,前提是已经initVerify初始化
参数: signature 签名数组
*/
import java.security.*;
import java.security.spec.*;
public class testdsa {
public static void main(String[] args) throws java.security.NoSuchAlgorithmException,java.lang.Exception {
testdsa my=new testdsa();
my.run();
}
public void run()
{
//数字签名生成密钥
//第一步生成密钥对,如果已经生成过,本过程就可以跳过,对用户来讲myprikey.dat要保存在本地
//而mypubkey.dat给发布给其它用户
if ((new java.io.File("myprikey.dat")).exists()==false) {
if (generatekey()==false) {
System.out.println("生成密钥对败");
return;
};
}
//第二步,此用户
//从文件中读入私钥,对一个字符串进行签名后保存在一个文件(myinfo.dat)中
//并且再把myinfo.dat发送出去
//为了方便数字签名也放进了myifno.dat文件中,当然也可分别发送
try {
java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat"));
PrivateKey myprikey=(PrivateKey)in.readObject();
in.close();
// java.security.spec.X509EncodedKeySpec pubX509=new java.security.spec.X509EncodedKeySpec(bX509);
//java.security.spec.X509EncodedKeySpec pubkeyEncode=java.security.spec.X509EncodedKeySpec
String myinfo="这是我的信息"; //要签名的信息
//用私钥对信息生成数字签名
java.security.Signature signet=java.security.Signature.getInstance("DSA");
signet.initSign(myprikey);
signet.update(myinfo.getBytes());
byte[] signed=signet.sign(); //对信息的数字签名
System.out.println("signed(签名内容)="+byte2hex(signed));
//把信息和数字签名保存在一个文件中
java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat"));
out.writeObject(myinfo);
out.writeObject(signed);
out.close();
System.out.println("签名并生成文件成功");
}
catch (java.lang.Exception e) {
e.printStackTrace();
System.out.println("签名并生成文件失败");
};
//第三步
//其他人通过公共方式得到此户的公钥和文件
//其他人用此户的公钥,对文件进行检查,如果成功说明是此用户发布的信息.
//
try {
java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));
PublicKey pubkey=(PublicKey)in.readObject();
in.close();
System.out.println(pubkey.getFormat());
in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat"));
String info=(String)in.readObject();
byte[] signed=(byte[])in.readObject();
in.close();
java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");
signetcheck.initVerify(pubkey);
signetcheck.update(info.getBytes());
if (signetcheck.verify(signed)) {
System.out.println("info="+info);
System.out.println("签名正常");
}
else System.out.println("非签名正常");
}
catch (java.lang.Exception e) {e.printStackTrace();};
}
//生成一对文件myprikey.dat和mypubkey.dat---私钥和公钥,
//公钥要用户发送(文件,网络等方法)给其它用户,私钥保存在本地
public boolean generatekey()
{
try {
java.security.KeyPairGenerator keygen=java.security.KeyPairGenerator.getInstance("DSA");
// SecureRandom secrand=new SecureRandom();
// secrand.setSeed("tttt".getBytes()); //初始化随机产生器
// keygen.initialize(576,secrand); //初始化密钥生成器
keygen.initialize(512);
KeyPair keys=keygen.genKeyPair();
// KeyPair keys=keygen.generateKeyPair(); //生成密钥组
PublicKey pubkey=keys.getPublic();
PrivateKey prikey=keys.getPrivate();
java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat"));
out.writeObject(prikey);
out.close();
System.out.println("写入对象 prikeys ok");
out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat"));
out.writeObject(pubkey);
out.close();
System.out.println("写入对象 pubkeys ok");
System.out.println("生成密钥对成功");
return true;
}
catch (java.lang.Exception e) {
e.printStackTrace();
System.out.println("生成密钥对失败");
return false;
};
}
public String byte2hex(byte[] b)
{
String hs="";
String stmp="";
for (int n=0;n<b.length;n++)
{
stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length()==1) hs=hs+"0"+stmp;
else hs=hs+stmp;
if (n<b.length-1) hs=hs+":";
}
return hs.toUpperCase();
}
}
2.4. DESede/DES对称算法
首先生成密钥,并保存(这里并没的保存的代码,可参考DSA中的方法)
KeyGenerator keygen = KeyGenerator.getInstance(Algorithm);
SecretKey deskey = keygen.generateKey();
用密钥加密明文(myinfo),生成密文(cipherByte)
Cipher c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.ENCRYPT_MODE,deskey);
byte[] cipherByte=c1.doFinal(myinfo.getBytes());
传送密文和密钥,本文没有相应代码可参考DSA
.............
用密钥解密密文
c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.DECRYPT_MODE,deskey);
byte[] clearByte=c1.doFinal(cipherByte);
相对来说对称密钥的使用是很简单的,对于JCE来讲支技DES,DESede,Blowfish三种加密术
对于密钥的保存各传送可使用对象流或者用二进制编码,相关参考代码如下
SecretKey deskey = keygen.generateKey();
byte[] desEncode=deskey.getEncoded();
javax.crypto.spec.SecretKeySpec destmp=new javax.crypto.spec.SecretKeySpec(desEncode,Algorithm);
SecretKey mydeskey=destmp;
相关API
KeyGenerator 在DSA中已经说明,在添加JCE后在instance进可以如下参数
DES,DESede,Blowfish,HmacMD5,HmacSHA1
javax.crypto.Cipher 加/解密器
public static final Cipher getInstance(java.lang.String transformation)
throws java.security.NoSuchAlgorithmException,
NoSuchPaddingException
返回一个指定方法的Cipher对象
参数:transformation 方法名(可用 DES,DESede,Blowfish)
public final void init(int opmode, java.security.Key key)
throws java.security.InvalidKeyException
用指定的密钥和模式初始化Cipher对象
参数:opmode 方式(ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE,UNWRAP_MODE)
key 密钥
public final byte[] doFinal(byte[] input)
throws java.lang.IllegalStateException,
IllegalBlockSizeException,
BadPaddingException
对input内的串,进行编码处理,返回处理后二进制串,是返回解密文还是加解文由init时的opmode决定
注意:本方法的执行前如果有update,是对updat和本次input全部处理,否则是本inout的内容
/*
安全程序 DESede/DES测试
*/
import java.security.*;
import javax.crypto.*;
public class testdes {
public static void main(String[] args){
testdes my=new testdes();
my.run();
}
public void run() {
//添加新安全算法,如果用JCE就要把它添加进去
Security.addProvider(new com.sun.crypto.provider.SunJCE());
String Algorithm="DES"; //定义 加密算法,可用 DES,DESede,Blowfish
String myinfo="要加密的信息";
try {
//生成密钥
KeyGenerator keygen = KeyGenerator.getInstance(Algorithm);
SecretKey deskey = keygen.generateKey();
//加密
System.out.println("加密前的二进串:"+byte2hex(myinfo.getBytes()));
System.out.println("加密前的信息:"+myinfo);
Cipher c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.ENCRYPT_MODE,deskey);
byte[] cipherByte=c1.doFinal(myinfo.getBytes());
System.out.println("加密后的二进串:"+byte2hex(cipherByte));
//解密
c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.DECRYPT_MODE,deskey);
byte[] clearByte=c1.doFinal(cipherByte);
System.out.println("解密后的二进串:"+byte2hex(clearByte));
System.out.println("解密后的信息:"+(new String(clearByte)));
}
catch (java.security.NoSuchAlgorithmException e1) {e1.printStackTrace();}
catch (javax.crypto.NoSuchPaddingException e2) {e2.printStackTrace();}
catch (java.lang.Exception e3) {e3.printStackTrace();}
}
public String byte2hex(byte[] b) //二行制转字符串
{
String hs="";
String stmp="";
for (int n=0;n<b.length;n++)
{
stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length()==1) hs=hs+"0"+stmp;
else hs=hs+stmp;
if (n<b.length-1) hs=hs+":";
}
return hs.toUpperCase();
}
}
2.5. Diffie-Hellman密钥一致协议
公开密钥密码体制的奠基人Diffie和Hellman所提出的 "指数密钥一致协议"(Exponential Key Agreement Protocol),该协议不要求别的安全性先决条件,允许两名用户在公开媒体上交换信息以生成"一致"的,可以共享的密钥。在JCE的中实现用户 alice生成DH类型的密钥对,如果长度用1024生成的时间请,推荐第一次生成后保存DHParameterSpec,以便下次使用直接初始化.使其速度加快
System.out.println("ALICE: 产生 DH 对 ...");
KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");
aliceKpairGen.initialize(512);
KeyPair aliceKpair = aliceKpairGen.generateKeyPair();
alice生成公钥发送组bob
byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded();
bob从alice发送来的公钥中读出DH密钥对的初始参数生成bob的DH密钥对
注意这一步一定要做,要保证每个用户用相同的初始参数生成的
DHParameterSpec dhParamSpec = ((DHPublicKey)alicePubKey).getParams();
KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
bobKpairGen.initialize(dhParamSpec);
KeyPair bobKpair = bobKpairGen.generateKeyPair();
bob根据alice的公钥生成本地的DES密钥
KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
bobKeyAgree.init(bobKpair.getPrivate());
bobKeyAgree.doPhase(alicePubKey, true);
SecretKey bobDesKey = bobKeyAgree.generateSecret("DES");
bob已经生成了他的DES密钥,他现把他的公钥发给alice,
byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded();
alice根据bob的公钥生成本地的DES密钥
,,,,,,解码
KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
aliceKeyAgree.init(aliceKpair.getPrivate());
aliceKeyAgree.doPhase(bobPubKey, true);
SecretKey aliceDesKey = aliceKeyAgree.generateSecret("DES");
bob和alice能过这个过程就生成了相同的DES密钥,在这种基础就可进行安全能信
常用API
java.security.KeyPairGenerator 密钥生成器类
public static KeyPairGenerator getInstance(String algorithm)
throws NoSuchAlgorithmException
以指定的算法返回一个KeyPairGenerator 对象
参数: algorithm 算法名.如:原来是DSA,现在添加了 DiffieHellman(DH)
public void initialize(int keysize)
以指定的长度初始化KeyPairGenerator对象,如果没有初始化系统以1024长度默认设置
参数:keysize 算法位长.其范围必须在 512 到 1024 之间,且必须为 64 的倍数
注意:如果用1024生长的时间很长,最好生成一次后就保存,下次就不用生成了
public void initialize(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException
以指定参数初始化
javax.crypto.interfaces.DHPublicKey
public DHParameterSpec getParams()
返回
java.security.KeyFactory
public static KeyFactory getInstance(String algorithm)
throws NoSuchAlgorithmException
以指定的算法返回一个KeyFactory
参数: algorithm 算法名:DSH,DH
public final PublicKey generatePublic(KeySpec keySpec)
throws InvalidKeySpecException
根据指定的key说明,返回一个PublicKey对象
java.security.spec.X509EncodedKeySpec
public X509EncodedKeySpec(byte[] encodedKey)
根据指定的二进制编码的字串生成一个key的说明
参数:encodedKey 二进制编码的字串(一般能过PublicKey.getEncoded()生成)
javax.crypto.KeyAgreement 密码一至类
public static final KeyAgreement getInstance(java.lang.String algorithm)
throws java.security.NoSuchAlgorithmException
返回一个指定算法的KeyAgreement对象
参数:algorithm 算法名,现在只能是DiffieHellman(DH)
public final void init(java.security.Key key)
throws java.security.InvalidKeyException
用指定的私钥初始化
参数:key 一个私钥
public final java.security.Key doPhase(java.security.Key key,
boolean lastPhase)
throws java.security.InvalidKeyException,
java.lang.IllegalStateException
用指定的公钥进行定位,lastPhase确定这是否是最后一个公钥,对于两个用户的
情况下就可以多次定次,最后确定
参数:key 公钥
lastPhase 是否最后公钥
public final SecretKey generateSecret(java.lang.String algorithm)
throws java.lang.IllegalStateException,
java.security.NoSuchAlgorithmException,
java.security.InvalidKeyException
根据指定的算法生成密钥
参数:algorithm 加密算法(可用 DES,DESede,Blowfish)
*/
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("解密后相同");
}
}
Diffie-Hellman密钥一致协议和DES程序需要JCE工具库的支持,可以到 http://java.sun.com/security/index.html 或是www.bt285.cn 下载JCE,并进行安装。简易安装把 jce1.2.1\lib 下的所有内容复制到 %java_home%\lib\ext下,如果没有ext目录自行建立,再把jce1_2_1.jar和sunjce_provider.jar添加到 CLASSPATH内,更详细说明请看相应用户手册
2.2. 消息摘要MD5和SHA的使用
使用方法:
首先用生成一个MessageDigest类,确定计算方法
java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1");
添加要进行计算摘要的信息
alga.update(myinfo.getBytes());
计算出摘要
byte[] digesta=alga.digest();
发送给其他人你的信息和摘要
其他人用相同的方法初始化,添加信息,最后进行比较摘要是否相同
algb.isEqual(digesta,algb.digest())
相关AIP
java.security.MessageDigest 类
static getInstance(String algorithm)
返回一个MessageDigest对象,它实现指定的算法
参数:算法名,如 SHA-1 或MD5
void update (byte input)
void update (byte[] input)
void update(byte[] input, int offset, int len)
添加要进行计算摘要的信息
byte[] digest()
完成计算,返回计算得到的摘要(对于MD5是16位,SHA是20位)
void reset()
复位
static boolean isEqual(byte[] digesta, byte[] digestb)
比效两个摘要是否相同
代码:
import java.security.*;
public class myDigest {
public static void main(String[] args) {
myDigest my=new myDigest();
my.testDigest();
}
public void testDigest()
{
try {
String myinfo="我的测试信息";
//java.security.MessageDigest alg=java.security.MessageDigest.getInstance("MD5");
java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1");
alga.update(myinfo.getBytes());
byte[] digesta=alga.digest();
System.out.println("本信息摘要是:"+byte2hex(digesta));
//通过某中方式传给其他人你的信息(myinfo)和摘要(digesta) 对方可以判断是否更改或传输正常
java.security.MessageDigest algb=java.security.MessageDigest.getInstance("SHA-1");
algb.update(myinfo.getBytes());
if (algb.isEqual(digesta,algb.digest())) {
System.out.println("信息检查正常");
}
else
{
System.out.println("摘要不相同");
}
}
catch (java.security.NoSuchAlgorithmException ex) {
System.out.println("非法摘要算法");
}
}
public String byte2hex(byte[] b) //二行制转字符串
{
String hs="";
String stmp="";
for (int n=0;n<b.length;n++)
{
stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length()==1) hs=hs+"0"+stmp;
else hs=hs+stmp;
if (n<b.length-1) hs=hs+":";
}
return hs.toUpperCase();
}
}
2.3. 数字签名DSA
1. 对于一个用户来讲首先要生成他的密钥对,并且分别保存
生成一个KeyPairGenerator实例
java.security.KeyPairGenerator keygen=java.security.KeyPairGenerator.getInstance("DSA");
如果设定随机产生器就用如相代码初始化
SecureRandom secrand=new SecureRandom();
secrand.setSeed("tttt".getBytes()); //初始化随机产生器
keygen.initialize(512,secrand); //初始化密钥生成器
否则
keygen.initialize(512);
生成密钥公钥pubkey和私钥prikey
KeyPair keys=keygen.generateKeyPair(); //生成密钥组
PublicKey pubkey=keys.getPublic();
PrivateKey prikey=keys.getPrivate();
分别保存在myprikey.dat和mypubkey.dat中,以便下次不在生成
(生成密钥对的时间比较长
java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat"));
out.writeObject(prikey);
out.close();
out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat"));
out.writeObject(pubkey);
out.close();
2. 用他私人密钥(prikey)对他所确认的信息(info)进行数字签名产生一个签名数组
从文件中读入私人密钥(prikey)
java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat"));
PrivateKey myprikey=(PrivateKey)in.readObject();
in.close();
初始一个Signature对象,并用私钥对信息签名
java.security.Signature signet=java.security.Signature.getInstance("DSA");
signet.initSign(myprikey);
signet.update(myinfo.getBytes());
byte[] signed=signet.sign();
把信息和签名保存在一个文件中(myinfo.dat)
java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat"));
out.writeObject(myinfo);
out.writeObject(signed);
out.close();
把他的公钥的信息及签名发给其它用户
3. 其他用户用他的公共密钥(pubkey)和签名(signed)和信息(info)进行验证是否由他签名的信息
读入公钥
java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));
PublicKey pubkey=(PublicKey)in.readObject();
in.close();
读入签名和信息
in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat"));
String info=(String)in.readObject();
byte[] signed=(byte[])in.readObject();
in.close();
初始一个Signature对象,并用公钥和签名进行验证
java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");
signetcheck.initVerify(pubkey);
signetcheck.update(info.getBytes());
if (signetcheck.verify(signed)) { System.out.println("签名正常");}
对于密钥的保存本文是用对象流的方式保存和传送的,也可可以用编码的方式保存.注意要
import java.security.spec.*
import java.security.*
具休说明如下
* public key是用X.509编码的,例码如下:
byte[] bobEncodedPubKey=mypublic.getEncoded(); //生成编码
//传送二进制编码
//以下代码转换编码为相应key对象
X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey);
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);
* 对于Private key是用PKCS#8编码,例码如下:
byte[] bPKCS=myprikey.getEncoded();
//传送二进制编码
//以下代码转换编码为相应key对象
PKCS8EncodedKeySpec priPKCS8=new PKCS8EncodedKeySpec(bPKCS);
KeyFactory keyf=KeyFactory.getInstance("DSA");
PrivateKey otherprikey=keyf.generatePrivate(priPKCS8);
4. 常用API
java.security.KeyPairGenerator 密钥生成器类
public static KeyPairGenerator getInstance(String algorithm) throws NoSuchAlgorithmException
以指定的算法返回一个KeyPairGenerator 对象
参数: algorithm 算法名.如:"DSA","RSA"
public void initialize(int keysize)
以指定的长度初始化KeyPairGenerator对象,如果没有初始化系统以1024长度默认设置
参数:keysize 算法位长.其范围必须在 512 到 1024 之间,且必须为 64 的倍数
public void initialize(int keysize, SecureRandom random)
以指定的长度初始化和随机发生器初始化KeyPairGenerator对象
参数:keysize 算法位长.其范围必须在 512 到 1024 之间,且必须为 64 的倍数
random 一个随机位的来源(对于initialize(int keysize)使用了默认随机器
public abstract KeyPair generateKeyPair()
产生新密钥对
java.security.KeyPair 密钥对类
public PrivateKey getPrivate()
返回私钥
public PublicKey getPublic()
返回公钥
java.security.Signature 签名类
public static Signature getInstance(String algorithm) throws NoSuchAlgorithmException
返回一个指定算法的Signature对象
参数 algorithm 如:"DSA"
public final void initSign(PrivateKey privateKey)
throws InvalidKeyException
用指定的私钥初始化
参数:privateKey 所进行签名时用的私钥
public final void update(byte data)
throws SignatureException
public final void update(byte[] data)
throws SignatureException
public final void update(byte[] data, int off, int len)
throws SignatureException
添加要签名的信息
public final byte[] sign()
throws SignatureException
返回签名的数组,前提是initSign和update
public final void initVerify(PublicKey publicKey)
throws InvalidKeyException
用指定的公钥初始化
参数:publicKey 验证时用的公钥
public final boolean verify(byte[] signature)
throws SignatureException
验证签名是否有效,前提是已经initVerify初始化
参数: signature 签名数组
*/
import java.security.*;
import java.security.spec.*;
public class testdsa {
public static void main(String[] args) throws java.security.NoSuchAlgorithmException,java.lang.Exception {
testdsa my=new testdsa();
my.run();
}
public void run()
{
//数字签名生成密钥
//第一步生成密钥对,如果已经生成过,本过程就可以跳过,对用户来讲myprikey.dat要保存在本地
//而mypubkey.dat给发布给其它用户
if ((new java.io.File("myprikey.dat")).exists()==false) {
if (generatekey()==false) {
System.out.println("生成密钥对败");
return;
};
}
//第二步,此用户
//从文件中读入私钥,对一个字符串进行签名后保存在一个文件(myinfo.dat)中
//并且再把myinfo.dat发送出去
//为了方便数字签名也放进了myifno.dat文件中,当然也可分别发送
try {
java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat"));
PrivateKey myprikey=(PrivateKey)in.readObject();
in.close();
// java.security.spec.X509EncodedKeySpec pubX509=new java.security.spec.X509EncodedKeySpec(bX509);
//java.security.spec.X509EncodedKeySpec pubkeyEncode=java.security.spec.X509EncodedKeySpec
String myinfo="这是我的信息"; //要签名的信息
//用私钥对信息生成数字签名
java.security.Signature signet=java.security.Signature.getInstance("DSA");
signet.initSign(myprikey);
signet.update(myinfo.getBytes());
byte[] signed=signet.sign(); //对信息的数字签名
System.out.println("signed(签名内容)="+byte2hex(signed));
//把信息和数字签名保存在一个文件中
java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat"));
out.writeObject(myinfo);
out.writeObject(signed);
out.close();
System.out.println("签名并生成文件成功");
}
catch (java.lang.Exception e) {
e.printStackTrace();
System.out.println("签名并生成文件失败");
};
//第三步
//其他人通过公共方式得到此户的公钥和文件
//其他人用此户的公钥,对文件进行检查,如果成功说明是此用户发布的信息.
//
try {
java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));
PublicKey pubkey=(PublicKey)in.readObject();
in.close();
System.out.println(pubkey.getFormat());
in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat"));
String info=(String)in.readObject();
byte[] signed=(byte[])in.readObject();
in.close();
java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");
signetcheck.initVerify(pubkey);
signetcheck.update(info.getBytes());
if (signetcheck.verify(signed)) {
System.out.println("info="+info);
System.out.println("签名正常");
}
else System.out.println("非签名正常");
}
catch (java.lang.Exception e) {e.printStackTrace();};
}
//生成一对文件myprikey.dat和mypubkey.dat---私钥和公钥,
//公钥要用户发送(文件,网络等方法)给其它用户,私钥保存在本地
public boolean generatekey()
{
try {
java.security.KeyPairGenerator keygen=java.security.KeyPairGenerator.getInstance("DSA");
// SecureRandom secrand=new SecureRandom();
// secrand.setSeed("tttt".getBytes()); //初始化随机产生器
// keygen.initialize(576,secrand); //初始化密钥生成器
keygen.initialize(512);
KeyPair keys=keygen.genKeyPair();
// KeyPair keys=keygen.generateKeyPair(); //生成密钥组
PublicKey pubkey=keys.getPublic();
PrivateKey prikey=keys.getPrivate();
java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat"));
out.writeObject(prikey);
out.close();
System.out.println("写入对象 prikeys ok");
out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat"));
out.writeObject(pubkey);
out.close();
System.out.println("写入对象 pubkeys ok");
System.out.println("生成密钥对成功");
return true;
}
catch (java.lang.Exception e) {
e.printStackTrace();
System.out.println("生成密钥对失败");
return false;
};
}
public String byte2hex(byte[] b)
{
String hs="";
String stmp="";
for (int n=0;n<b.length;n++)
{
stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length()==1) hs=hs+"0"+stmp;
else hs=hs+stmp;
if (n<b.length-1) hs=hs+":";
}
return hs.toUpperCase();
}
}
2.4. DESede/DES对称算法
首先生成密钥,并保存(这里并没的保存的代码,可参考DSA中的方法)
KeyGenerator keygen = KeyGenerator.getInstance(Algorithm);
SecretKey deskey = keygen.generateKey();
用密钥加密明文(myinfo),生成密文(cipherByte)
Cipher c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.ENCRYPT_MODE,deskey);
byte[] cipherByte=c1.doFinal(myinfo.getBytes());
传送密文和密钥,本文没有相应代码可参考DSA
.............
用密钥解密密文
c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.DECRYPT_MODE,deskey);
byte[] clearByte=c1.doFinal(cipherByte);
相对来说对称密钥的使用是很简单的,对于JCE来讲支技DES,DESede,Blowfish三种加密术
对于密钥的保存各传送可使用对象流或者用二进制编码,相关参考代码如下
SecretKey deskey = keygen.generateKey();
byte[] desEncode=deskey.getEncoded();
javax.crypto.spec.SecretKeySpec destmp=new javax.crypto.spec.SecretKeySpec(desEncode,Algorithm);
SecretKey mydeskey=destmp;
相关API
KeyGenerator 在DSA中已经说明,在添加JCE后在instance进可以如下参数
DES,DESede,Blowfish,HmacMD5,HmacSHA1
javax.crypto.Cipher 加/解密器
public static final Cipher getInstance(java.lang.String transformation)
throws java.security.NoSuchAlgorithmException,
NoSuchPaddingException
返回一个指定方法的Cipher对象
参数:transformation 方法名(可用 DES,DESede,Blowfish)
public final void init(int opmode, java.security.Key key)
throws java.security.InvalidKeyException
用指定的密钥和模式初始化Cipher对象
参数:opmode 方式(ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE,UNWRAP_MODE)
key 密钥
public final byte[] doFinal(byte[] input)
throws java.lang.IllegalStateException,
IllegalBlockSizeException,
BadPaddingException
对input内的串,进行编码处理,返回处理后二进制串,是返回解密文还是加解文由init时的opmode决定
注意:本方法的执行前如果有update,是对updat和本次input全部处理,否则是本inout的内容
/*
安全程序 DESede/DES测试
*/
import java.security.*;
import javax.crypto.*;
public class testdes {
public static void main(String[] args){
testdes my=new testdes();
my.run();
}
public void run() {
//添加新安全算法,如果用JCE就要把它添加进去
Security.addProvider(new com.sun.crypto.provider.SunJCE());
String Algorithm="DES"; //定义 加密算法,可用 DES,DESede,Blowfish
String myinfo="要加密的信息";
try {
//生成密钥
KeyGenerator keygen = KeyGenerator.getInstance(Algorithm);
SecretKey deskey = keygen.generateKey();
//加密
System.out.println("加密前的二进串:"+byte2hex(myinfo.getBytes()));
System.out.println("加密前的信息:"+myinfo);
Cipher c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.ENCRYPT_MODE,deskey);
byte[] cipherByte=c1.doFinal(myinfo.getBytes());
System.out.println("加密后的二进串:"+byte2hex(cipherByte));
//解密
c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.DECRYPT_MODE,deskey);
byte[] clearByte=c1.doFinal(cipherByte);
System.out.println("解密后的二进串:"+byte2hex(clearByte));
System.out.println("解密后的信息:"+(new String(clearByte)));
}
catch (java.security.NoSuchAlgorithmException e1) {e1.printStackTrace();}
catch (javax.crypto.NoSuchPaddingException e2) {e2.printStackTrace();}
catch (java.lang.Exception e3) {e3.printStackTrace();}
}
public String byte2hex(byte[] b) //二行制转字符串
{
String hs="";
String stmp="";
for (int n=0;n<b.length;n++)
{
stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length()==1) hs=hs+"0"+stmp;
else hs=hs+stmp;
if (n<b.length-1) hs=hs+":";
}
return hs.toUpperCase();
}
}
2.5. Diffie-Hellman密钥一致协议
公开密钥密码体制的奠基人Diffie和Hellman所提出的 "指数密钥一致协议"(Exponential Key Agreement Protocol),该协议不要求别的安全性先决条件,允许两名用户在公开媒体上交换信息以生成"一致"的,可以共享的密钥。在JCE的中实现用户 alice生成DH类型的密钥对,如果长度用1024生成的时间请,推荐第一次生成后保存DHParameterSpec,以便下次使用直接初始化.使其速度加快
System.out.println("ALICE: 产生 DH 对 ...");
KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");
aliceKpairGen.initialize(512);
KeyPair aliceKpair = aliceKpairGen.generateKeyPair();
alice生成公钥发送组bob
byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded();
bob从alice发送来的公钥中读出DH密钥对的初始参数生成bob的DH密钥对
注意这一步一定要做,要保证每个用户用相同的初始参数生成的
DHParameterSpec dhParamSpec = ((DHPublicKey)alicePubKey).getParams();
KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
bobKpairGen.initialize(dhParamSpec);
KeyPair bobKpair = bobKpairGen.generateKeyPair();
bob根据alice的公钥生成本地的DES密钥
KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
bobKeyAgree.init(bobKpair.getPrivate());
bobKeyAgree.doPhase(alicePubKey, true);
SecretKey bobDesKey = bobKeyAgree.generateSecret("DES");
bob已经生成了他的DES密钥,他现把他的公钥发给alice,
byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded();
alice根据bob的公钥生成本地的DES密钥
,,,,,,解码
KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
aliceKeyAgree.init(aliceKpair.getPrivate());
aliceKeyAgree.doPhase(bobPubKey, true);
SecretKey aliceDesKey = aliceKeyAgree.generateSecret("DES");
bob和alice能过这个过程就生成了相同的DES密钥,在这种基础就可进行安全能信
常用API
java.security.KeyPairGenerator 密钥生成器类
public static KeyPairGenerator getInstance(String algorithm)
throws NoSuchAlgorithmException
以指定的算法返回一个KeyPairGenerator 对象
参数: algorithm 算法名.如:原来是DSA,现在添加了 DiffieHellman(DH)
public void initialize(int keysize)
以指定的长度初始化KeyPairGenerator对象,如果没有初始化系统以1024长度默认设置
参数:keysize 算法位长.其范围必须在 512 到 1024 之间,且必须为 64 的倍数
注意:如果用1024生长的时间很长,最好生成一次后就保存,下次就不用生成了
public void initialize(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException
以指定参数初始化
javax.crypto.interfaces.DHPublicKey
public DHParameterSpec getParams()
返回
java.security.KeyFactory
public static KeyFactory getInstance(String algorithm)
throws NoSuchAlgorithmException
以指定的算法返回一个KeyFactory
参数: algorithm 算法名:DSH,DH
public final PublicKey generatePublic(KeySpec keySpec)
throws InvalidKeySpecException
根据指定的key说明,返回一个PublicKey对象
java.security.spec.X509EncodedKeySpec
public X509EncodedKeySpec(byte[] encodedKey)
根据指定的二进制编码的字串生成一个key的说明
参数:encodedKey 二进制编码的字串(一般能过PublicKey.getEncoded()生成)
javax.crypto.KeyAgreement 密码一至类
public static final KeyAgreement getInstance(java.lang.String algorithm)
throws java.security.NoSuchAlgorithmException
返回一个指定算法的KeyAgreement对象
参数:algorithm 算法名,现在只能是DiffieHellman(DH)
public final void init(java.security.Key key)
throws java.security.InvalidKeyException
用指定的私钥初始化
参数:key 一个私钥
public final java.security.Key doPhase(java.security.Key key,
boolean lastPhase)
throws java.security.InvalidKeyException,
java.lang.IllegalStateException
用指定的公钥进行定位,lastPhase确定这是否是最后一个公钥,对于两个用户的
情况下就可以多次定次,最后确定
参数:key 公钥
lastPhase 是否最后公钥
public final SecretKey generateSecret(java.lang.String algorithm)
throws java.lang.IllegalStateException,
java.security.NoSuchAlgorithmException,
java.security.InvalidKeyException
根据指定的算法生成密钥
参数:algorithm 加密算法(可用 DES,DESede,Blowfish)
*/
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("解密后相同");
}
}
相关推荐
在Java中实现加密算法涉及到多个重要的概念和技术,包括单钥密码体制、消息摘要、Diffie-Hellman密钥一致协议、非对称算法和公钥体系以及数字签名。下面将详细阐述这些知识点。 **1. 单钥密码体制** 单钥密码体制,...
下面将详细介绍RSA加密算法的原理以及如何在Java中进行实现。 **RSA算法简介** RSA是由Ron Rivest、Adi Shamir和Leonard Adleman在1977年提出的,是一种非对称加密算法。它基于两个密钥:公钥和私钥。公钥用于加密...
综上所述,RC4加密算法在Java中的实现主要依赖于`javax.crypto`包提供的功能。虽然它在历史上发挥了重要作用,但出于安全考虑,现在更多地是用于兼容性目的,而不是新开发的加密需求。在现代加密实践中,建议使用...
Java加密狗读取例子主要涉及的是在Java编程环境中与硬件加密设备进行交互的技术。加密狗是一种硬件安全模块,用于保护软件免受非法复制和逆向工程。在这个特定的例子中,我们关注的是ET199型号的加密狗,它通常被...
这个例子中,`Des算法JAVA的实现`文件可能包含了一个完整的Java程序,演示了上述步骤的代码实现。通过运行这个程序,你可以看到DES加密和解密的实际效果。然而,实际应用中,为了安全性,通常会使用更强大的加密算法...
在Java中实现SM2,你需要理解ECC的基本原理,包括椭圆曲线方程、基点、点的加法等。Java提供了一套名为`java.security`的API,可以用于处理ECC相关的操作。你可以创建KeyPairGenerator实例,指定"EC"作为算法,然后...
下面将详细介绍这些算法以及它们在Java中的实现,以及如何进行数字签名和数字证书的验证。 1. **SM2算法**:SM2是一种基于椭圆曲线密码学(ECC)的公钥加密算法,用于非对称加密。它提供了密钥交换、签名和验证的...
为了在Java中实现Diffie-Hellman密钥一致协议和DES加密算法,需要安装Java Cryptography Extension (JCE)工具库。可以在[Java官方网站](http://java.sun.com/security/index.html)下载JCE,并按照指示进行安装。简单...
在Java中实现MD5加密算法需要使用java.security包中的MessageDigest类,通过getInstance方法获取MD5加密算法的实例,然后使用update方法将要加密的数据更新到MessageDigest对象中,最后使用digest方法获取加密后的...
Java中的3DES(Triple Data Encryption Algorithm)是一种强化版的DES(Data Encryption Standard)加密算法,它通过三次应用DES算法来提高安全性。3DES是DES的一个变种,它使用了两个不同的密钥对数据进行三次加密...
RSA加密算法,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息...本资源是通过Android、java实现的RSA加密的例子,可供大家参考学习。
Java中的Blowfish对称密钥加密算法是一种广泛使用的数据加密技术,特别是在网络通信和存储安全领域。Blowfish算法由Bruce Schneier在1993年设计,以其高效和安全著称。它属于对称密钥加密体系,这意味着加密和解密...
本文将详细介绍如何在Java环境中实现DES加密和解密。 DES,全称为数据加密标准,基于Feistel密码结构,采用64位的密钥,但其中只有56位是真正参与加密过程的。DES分为两个主要阶段:加密和解密,这两个过程使用相同...
文件"DataServer"和"DataServer2"可能包含了实现这些加密算法和Servlet逻辑的Java代码,而"Encypher"和"DHCoder"可能分别是对加密和DH密钥交换功能的封装,方便在项目中调用。 总的来说,这个压缩包提供了Java环境...
这个是Java和android通用的代码,工程是Java的,但是类可以直接复制到android工程中使用,本人做过测试的,欢迎下载
常见的加密算法实现--Java语言编写,花费一个多月认真整理出来的可直接运行的源码文件。下载RAR文件后,对压缩包进行解压后,里面有详细的例子,导入IDEA或者ECLIPSE后,运行指定的Java文件,即可以直接使用。压缩包...
标题"DES加密算法(JAVA和C语言描述)结果一致"表明我们将探讨如何在两种不同的编程语言——Java和C中实现DES加密,确保得到相同的加密结果。在跨语言实现加密算法时,一致性至关重要,因为这确保了无论在哪种环境下...
在Java中实现DES加密算法,需要使用Java Cryptography Extension (JCE) 提供的相关类库,主要包括`javax.crypto.Cipher`、`java.security.SecureRandom`以及`java.security.Key`等。以下是一个简单的DESEncryption类...
在Java编程语言中,加密算法是安全通信的关键组成部分,特别是在涉及网络传输敏感数据时。公钥加密和私钥解密是一种非对称加密技术,它允许数据在不安全的环境中安全传输。本主题将深入探讨Java如何实现这种机制,...
Java 异或加密算法是一种基于异或操作的简单加密技术,通常用于保护数据的隐私,尤其是在简单的通信或存储中。异或加密算法的核心是异或(XOR)运算,其特性是“相同为0,不同为1”,即任何数字与0进行异或运算结果...