JAVA加密算法的实现用例
对象
参数?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("解密后相同");
????}
}