加密算法:JAVA上加密算法的实现用例



MD5/SHA1DSADESede/DESDfie-Hellman使用
王辉([email protected])
2001年7月

第1章基础知识

1.1.单钥密码体制
单钥密码体制是种传统加密算法是指信息发送方和接收方共同使用同把密钥进行加解密

通常,使用加密算法比较简便高效,密钥简短加解密速度快破译极其困难但是加密安全性依靠密钥保管安全性,在公开计算机网络上安全地传送和保管密钥是个严峻问题并且如果在多用户情况下密钥保管安全性也是个问题

单钥密码体制代表是美国DES

1.2.消息摘要
个消息摘要就是个数据块数字指纹即对个任意长度个数据块进行计算产生个唯指印(对于SHA1是产生个20字节 2进制)

消息摘要有两个基本属性:

两个区别报文难以生成相同摘要
难以对指定摘要生成个报文而由该报文反推算出该指定摘要
代表:美国国家标准技术研究所SHA1和麻省理工学院RonaldRivest提出MD5


1.3.Dfie-Hellman密钥致协议
密钥致协议是由公开密钥密码体制奠基人Dfie和Hellman所提出种思想

先决条件,允许两名用户在公开媒体上交换信息以生成\"致\",可以共享密钥

代表:指数密钥致协议(ExponentialKeyAgreementProtocol)

1.4.非对称算法和公钥体系
1976年Dittie和Hellman为解决密钥管理问题在他们奠基性工作\"密码学新方向\"文中提出种密钥交换协议允许在不安全媒体上通过通讯双方交换信息安全地传送秘密密钥在此新思想基础上很快出现了非对称密钥密码体制即公钥密码体制在公钥体制中加密密钥区别于解密密钥加密密钥公的于众谁都可以使用;解密密钥只有解密人自己知道它们分别称为公开密钥(Publickey)和秘密密钥(Privatekey)

迄今为止所有公钥密码体系中RSA系统是最著名、最多使用RSA公开密钥密码系统是由R.Rivest、A.Shamir和L.Adleman俊教授于1977年提出RSA取名就是来自于这 3位发明者个字母

1.5.数字签名
所谓数字签名就是信息发送者用其私钥对从所传报文中提取出特征数据(或称数字指纹)进行RSA算法操作以保证发信人无法抵赖曾发过该信息(即不可抵赖性)同时也确保信息报文在经签名后末被篡改(即完整性)当信息接收者收到报文后就可以用发送者公钥对数字签名进行验证 

在数字签名中有重要作用数字指纹是通过类特殊散列(HASH)生成对这些HASH特殊要求是:

接受输入报文数据没有长度限制;
对任何输入报文数据生成固定长度摘要(数字指纹)输出
从报文能方便地算出摘要;
难以对指定摘要生成个报文而由该报文反推算出该指定摘要;
两个区别报文难以生成相同摘要



代表:DSA

第2章在JAVA中实现

2.1.相关
Dfie-Hellman密钥致协议和DES需要JCE工具库支持,可以到java.sun.com/security/index.html\">http://java.sun.com/security/index.html下载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.MessageDigestalga=java.security.MessageDigest.getInstance(\"SHA-1\");

添加要进行计算摘要信息

alga.update(myinfo.getBytes);

计算出摘要

digesta=alga.digest;

发送给其他人你信息和摘要

其他人用相同思路方法化,添加信息,最后进行比较摘要是否相同

algb.isEqual(digesta,algb.digest)

相关AIP

java.security.MessageDigest类

getInstance(Stringalgorithm)

返回个MessageDigest对象,它实现指定算法

参数:算法名,如SHA-1或MD5

voidupdate(input)

voidupdate(input)

voidupdate(input,off,len)

添加要进行计算摘要信息

digest

完成计算,返回计算得到摘要(对于MD5是16位,SHA是20位)

voidre

复位

booleanisEqual(digesta,digestb)

比效两个摘要是否相同

代码:

importjava.security.*;
publicmyDigest{
publicvoid(Stringargs){

myDigestmy=myDigest;
my.testDigest;

}
publicvoidtestDigest
{
try{
Stringmyinfo=\"我测试信息\";

//java.security.MessageDigestalg=java.security.MessageDigest.getInstance(\"MD5\");
java.security.MessageDigestalga=java.security.MessageDigest.getInstance(\"SHA-1\");
alga.update(myinfo.getBytes);
digesta=alga.digest;
.out.prln(\"本信息摘要是:\"+2hex(digesta));
//通过某中方式传给其他人你信息(myinfo)和摘要(digesta)对方可以判断是否更改或传输正常


java.security.MessageDigestalgb=java.security.MessageDigest.getInstance(\"SHA-1\");
algb.update(myinfo.getBytes);
(algb.isEqual(digesta,algb.digest)){
.out.prln(\"信息检查正常\");
}

{
.out.prln(\"摘要不相同\");
}

}
catch(java.security.NoSuchAlgorithmExceptionex){
.out.prln(\"非法摘要算法\");
}

}
publicString2hex(b)// 2行制转
{
Stringhs=\"\";
Stringstmp=\"\";
for(n=0;n<b.length;n)
{
stmp=(java.lang.Integer.toHexString(b[n]&0XFF));
(stmp.length1)hs=hs+\"0\"+stmp;
hs=hs+stmp;
(n<b.length-1)hs=hs+\":\";
}
hs.toUpperCase;
}

}





2.3.数字签名DSA

对于个用户来讲首先要生成他密钥对,并且分别保存
生成个KeyPairGenerator例子

java.security.KeyPairGeneratorkeygen=java.security.KeyPairGenerator.getInstance(\"DSA\");
如果设定随机产生器就用如相代码
SecureRandomsecrand=SecureRandom;
secrand.Seed(\"tttt\".getBytes);//化随机产生器
keygen.initialize(512,secrand);//化密钥生成器
否则
keygen.initialize(512);
生成密钥公钥pubkey和私钥prikey
KeyPairkeys=keygen.generateKeyPair;//生成密钥组
PublicKeypubkey=keys.getPublic;
PrivateKeyprikey=keys.getPrivate;
分别保存在myprikey.dat和mypubkey.dat中,以便下次不在生成
(生成密钥对时间比较长
java.io.ObjectOutputStreamout=java.io.ObjectOutputStream(java.io.FileOutputStream(\"myprikey.dat\"));
out.writeObject(prikey);
out.close;
out=java.io.ObjectOutputStream(java.io.FileOutputStream(\"mypubkey.dat\"));
out.writeObject(pubkey);
out.close;






用他私人密钥(prikey)对他所确认信息(info)进行数字签名产生个签名
从文件中读入私人密钥(prikey)

java.io.ObjectInputStreamin=java.io.ObjectInputStream(java.io.FileInputStream(\"myprikey.dat\"));
PrivateKeymyprikey=(PrivateKey)in.readObject;
in.close;
个Signature对象,并用私钥对信息签名
java.security.Signaturesignet=java.security.Signature.getInstance(\"DSA\");
signet.initSign(myprikey);
signet.update(myinfo.getBytes);
signed=signet.sign;
把信息和签名保存在个文件中(myinfo.dat)
java.io.ObjectOutputStreamout=java.io.ObjectOutputStream(java.io.FileOutputStream(\"myinfo.dat\"));
out.writeObject(myinfo);
out.writeObject(signed);
out.close;
把他公钥信息及签名发给其它用户






其他用户用他公共密钥(pubkey)和签名(signed)和信息(info)进行验证是否由他签名信息
读入公钥
java.io.ObjectInputStreamin=java.io.ObjectInputStream(java.io.FileInputStream(\"mypubkey.dat\"));
PublicKeypubkey=(PublicKey)in.readObject;
in.close;

读入签名和信息
in=java.io.ObjectInputStream(java.io.FileInputStream(\"myinfo.dat\"));


Stringinfo=(String)in.readObject;
signed=()in.readObject;
in.close;

个Signature对象,并用公钥和签名进行验证
java.security.Signaturesignetcheck=java.security.Signature.getInstance(\"DSA\");
signetcheck.initVery(pubkey);
signetcheck.update(info.getBytes);
(signetcheck.very(signed)){.out.prln(\"签名正常\");}

对于密钥保存本文是用对象流方式保存和传送,也可可以用编码方式保存.注意要
importjava.security.spec.*
importjava.security.*

具休介绍说明如下

publickey是用X.509编码,例码如下:bobEncodedPubKey=mypublic.getEncoded;//生成编码
//传送 2进制编码
//以下代码转换编码为相应key对象
X509EncodedKeySpecbobPubKeySpec=X509EncodedKeySpec(bobEncodedPubKey);
KeyFactorykeyFactory=KeyFactory.getInstance(\"DSA\");
PublicKeybobPubKey=keyFactory.generatePublic(bobPubKeySpec);




对于Privatekey是用PKCS#8编码,例码如下:bPKCS=myprikey.getEncoded;
//传送 2进制编码
//以下代码转换编码为相应key对象
PKCS8EncodedKeySpecpriPKCS8=PKCS8EncodedKeySpec(bPKCS);
KeyFactorykeyf=KeyFactory.getInstance(\"DSA\");
PrivateKeyotherprikey=keyf.generatePrivate(priPKCS8);







常用API
java.security.KeyPairGenerator密钥生成器类
publicKeyPairGeneratorgetInstance(Stringalgorithm)throwsNoSuchAlgorithmException
以指定算法返回个KeyPairGenerator对象
参数:algorithm算法名.如:\"DSA\",\"RSA\"

publicvoidinitialize(keysize)


以指定长度化KeyPairGenerator对象,如果没有化系统以1024长度默认设置


参数:keysize算法位长.其范围必须在512到1024的间且必须为64倍数

publicvoidinitialize(keysize,SecureRandomrandom)
以指定长度化和随机发生器化KeyPairGenerator对象
参数:keysize算法位长.其范围必须在512到1024的间且必须为64倍数
random个随机位来源(对于initialize(keysize)使用了默认随机器

publicabstractKeyPairgenerateKeyPair
产生新密钥对

java.security.KeyPair密钥对类
publicPrivateKeygetPrivate
返回私钥

publicPublicKeygetPublic
返回公钥

java.security.Signature签名类
publicSignaturegetInstance(Stringalgorithm)throwsNoSuchAlgorithmException
返回个指定算法Signature对象
参数algorithm如:\"DSA\"

publicfinalvoidinitSign(PrivateKeyprivateKey)
throwsInvalidKeyException
用指定私钥
参数:privateKey所进行签名时用私钥

publicfinalvoidupdate(data)
throwsSignatureException
publicfinalvoidupdate(data)
throwsSignatureException
publicfinalvoidupdate(data,off,len)
throwsSignatureException
添加要签名信息

publicfinalsign
throwsSignatureException
返回签名,前提是initSign和update

publicfinalvoidinitVery(PublicKeypublicKey)
throwsInvalidKeyException
用指定公钥
参数:publicKey验证时用公钥

publicfinalbooleanvery(signature)
throwsSignatureException
验证签名是否有效,前提是已经initVery
参数:signature签名

*/
importjava.security.*;
importjava.security.spec.*;
publictestdsa{
publicvoid(Stringargs)throwsjava.security.NoSuchAlgorithmException,java.lang.Exception{
testdsamy=testdsa;
my.run;
}
publicvoidrun
{

//数字签名生成密钥
//第步生成密钥对,如果已经生成过,本过程就可以跳过,对用户来讲myprikey.dat要保存在本地
//而mypubkey.dat给发布给其它用户
((java.io.File(\"myprikey.dat\")).existsfalse){
(generatekeyfalse){
.out.prln(\"生成密钥对败\");
;
};
}


//第 2步,此用户
//从文件中读入私钥,对串进行签名后保存在个文件(myinfo.dat)中
//并且再把myinfo.dat发送出去
//为了方便数字签名也放进了myno.dat文件中,当然也可分别发送
try{
java.io.ObjectInputStreamin=java.io.ObjectInputStream(java.io.FileInputStream(\"myprikey.dat\"));
PrivateKeymyprikey=(PrivateKey)in.readObject;
in.close;

//java.security.spec.X509EncodedKeySpecpubX509=java.security.spec.X509EncodedKeySpec(bX509);

//java.security.spec.X509EncodedKeySpecpubkeyEncode=java.security.spec.X509EncodedKeySpec
Stringmyinfo=\"这是我信息\";//要签名信息
//用私钥对信息生成数字签名
java.security.Signaturesignet=java.security.Signature.getInstance(\"DSA\");
signet.initSign(myprikey);
signet.update(myinfo.getBytes);
signed=signet.sign;//对信息数字签名
.out.prln(\"signed(签名内容)=\"+2hex(signed));
//把信息和数字签名保存在个文件中
java.io.ObjectOutputStreamout=java.io.ObjectOutputStream(java.io.FileOutputStream(\"myinfo.dat\"));
out.writeObject(myinfo);
out.writeObject(signed);
out.close;
.out.prln(\"签名并生成文件成功\");
}
catch(java.lang.Exceptione){
e.prStackTrace;
.out.prln(\"签名并生成文件失败\");
};

//第 3步
//其他人通过公共方式得到此户公钥和文件
//其他人用此户公钥,对文件进行检查,如果成功介绍说明是此用户发布信息.
//
try{

java.io.ObjectInputStreamin=java.io.ObjectInputStream(java.io.FileInputStream(\"mypubkey.dat\"));
PublicKeypubkey=(PublicKey)in.readObject;
in.close;
.out.prln(pubkey.getFormat);

in=java.io.ObjectInputStream(java.io.FileInputStream(\"myinfo.dat\"));
Stringinfo=(String)in.readObject;
signed=()in.readObject;
in.close;

java.security.Signaturesignetcheck=java.security.Signature.getInstance(\"DSA\");
signetcheck.initVery(pubkey);
signetcheck.update(info.getBytes);
(signetcheck.very(signed)){
.out.prln(\"info=\"+info);
.out.prln(\"签名正常\");
}
.out.prln(\"非签名正常\");
}
catch(java.lang.Exceptione){e.prStackTrace;};


}

//生成对文件myprikey.dat和mypubkey.dat---私钥和公钥,
//公钥要用户发送(文件,网络等思路方法)给其它用户,私钥保存在本地
publicbooleangeneratekey
{
try{
java.security.KeyPairGeneratorkeygen=java.security.KeyPairGenerator.getInstance(\"DSA\");
//SecureRandomsecrand=SecureRandom;
//secrand.Seed(\"tttt\".getBytes);//化随机产生器
//keygen.initialize(576,secrand);//化密钥生成器
keygen.initialize(512);
KeyPairkeys=keygen.genKeyPair;
//KeyPairkeys=keygen.generateKeyPair;//生成密钥组
PublicKeypubkey=keys.getPublic;
PrivateKeyprikey=keys.getPrivate;

java.io.ObjectOutputStreamout=java.io.ObjectOutputStream(java.io.FileOutputStream(\"myprikey.dat\"));
out.writeObject(prikey);
out.close;
.out.prln(\"写入对象prikeysok\");
out=java.io.ObjectOutputStream(java.io.FileOutputStream(\"mypubkey.dat\"));
out.writeObject(pubkey);
out.close;
.out.prln(\"写入对象pubkeysok\");
.out.prln(\"生成密钥对成功\");
true;
}
catch(java.lang.Exceptione){
e.prStackTrace;
.out.prln(\"生成密钥对失败\");
false;
};

}

publicString2hex(b)
{
Stringhs=\"\";
Stringstmp=\"\";


for(n=0;n<b.length;n)
{
stmp=(java.lang.Integer.toHexString(b[n]&0XFF));
(stmp.length1)hs=hs+\"0\"+stmp;
hs=hs+stmp;
(n<b.length-1)hs=hs+\":\";
}
hs.toUpperCase;
}

}





2.4.DESede/DES对称算法
首先生成密钥,并保存(这里并没保存代码,可参考DSA中思路方法)

KeyGeneratorkeygen=KeyGenerator.getInstance(Algorithm);


SecretKeydeskey=keygen.generateKey;

用密钥加密明文(myinfo),生成密文(cipherByte)

Cipherc1=Cipher.getInstance(Algorithm);

c1.init(Cipher.ENCRYPT_MODE,deskey);

cipherByte=c1.doFinal(myinfo.getBytes);

传送密文和密钥,本文没有相应代码可参考DSA

.............

用密钥解密密文

c1=Cipher.getInstance(Algorithm);

c1.init(Cipher.DECRYPT_MODE,deskey);

clearByte=c1.doFinal(cipherByte);

相对来说对称密钥使用是很简单,对于JCE来讲支技DES,DESede,Blowfish 3种加密术

对于密钥保存各传送可使用对象流或者用 2进制编码,相关参考代码如下

SecretKeydeskey=keygen.generateKey;
desEncode=deskey.getEncoded;
javax.crypto.spec.SecretKeySpecdestmp=javax.crypto.spec.SecretKeySpec(desEncode,Algorithm);
SecretKeymydeskey=destmp;





相关API

KeyGenerator在DSA中已经介绍说明,在添加JCE后在instance进可以如下参数

DES,DESede,Blowfish,HmacMD5,HmacSHA1

javax.crypto.Cipher加/解密器

publicfinalCiphergetInstance(java.lang.Stringtransformation)
throwsjava.security.NoSuchAlgorithmException,
NoSuchPaddingException





返回个指定思路方法Cipher对象

参数:transformation思路方法名(可用DES,DESede,Blowfish)

publicfinalvoidinit(opmode,java.security.Keykey)
throwsjava.security.InvalidKeyException


用指定密钥和模式化Cipher对象

参数:opmode方式(ENCRYPT_MODE,DECRYPT_MODE,WRAP_MODE,UNWRAP_MODE)

key密钥

publicfinaldoFinal(input)
throwsjava.lang.IllegalStateException,
IllegalBlockSizeException,
BadPaddingException





对input内串,进行编码处理,返回处理后 2进制串,是返回解密文还是加解文由init时opmode决定


注意:本思路方法执行前如果有update,是对updat和本次input全部处理,否则是本inout内容

/*
安全DESede/DES测试
*/
importjava.security.*;
importjavax.crypto.*;
publictestdes{
publicvoid(Stringargs){
testdesmy=testdes;
my.run;
}
publicvoidrun{
//添加新安全算法,如果用JCE就要把它添加进去
Security.addProvider(com.sun.crypto.provider.SunJCE);
StringAlgorithm=\"DES\";//定义加密算法,可用DES,DESede,Blowfish
Stringmyinfo=\"要加密信息\";
try{
//生成密钥
KeyGeneratorkeygen=KeyGenerator.getInstance(Algorithm);
SecretKeydeskey=keygen.generateKey;

//加密
.out.prln(\"加密前 2进串:\"+2hex(myinfo.getBytes));
.out.prln(\"加密前信息:\"+myinfo);
Cipherc1=Cipher.getInstance(Algorithm);
c1.init(Cipher.ENCRYPT_MODE,deskey);
cipherByte=c1.doFinal(myinfo.getBytes);


.out.prln(\"加密后 2进串:\"+2hex(cipherByte));
//解密
c1=Cipher.getInstance(Algorithm);
c1.init(Cipher.DECRYPT_MODE,deskey);
clearByte=c1.doFinal(cipherByte);
.out.prln(\"解密后 2进串:\"+2hex(clearByte));
.out.prln(\"解密后信息:\"+(String(clearByte)));

}
catch(java.security.NoSuchAlgorithmExceptione1){e1.prStackTrace;}
catch(javax.crypto.NoSuchPaddingExceptione2){e2.prStackTrace;}
catch(java.lang.Exceptione3){e3.prStackTrace;}
}
publicString2hex(b)// 2行制转
{
Stringhs=\"\";
Stringstmp=\"\";
for(n=0;n<b.length;n)
{
stmp=(java.lang.Integer.toHexString(b[n]&0XFF));
(stmp.length1)hs=hs+\"0\"+stmp;
hs=hs+stmp;
(n<b.length-1)hs=hs+\":\";
}
hs.toUpperCase;
}

}





2.5.Dfie-Hellman密钥致协议
公开密钥密码体制奠基人Dfie和Hellman所提出\"指数密钥致协议\"(ExponentialKeyAgreementProtocol),该协议不要求别安全性先决条件,允许两名用户在公开媒体上交换信息以生成\"致\",可以共享密钥在JCE中实现用户alice生成DH类型密钥对,如果长度用1024生成时间请,推荐第次生成后保存DHParameterSpec,以便下次使用直接化.使其速度加快

.out.prln(\"ALICE:产生DH对...\");
KeyPairGeneratoraliceKpairGen=KeyPairGenerator.getInstance(\"DH\");
aliceKpairGen.initialize(512);
KeyPairaliceKpair=aliceKpairGen.generateKeyPair;





alice生成公钥发送组bob

alicePubKeyEnc=aliceKpair.getPublic.getEncoded;





bob从alice发送来公钥中读出DH密钥对参数生成bobDH密钥对

注意这定要做,要保证每个用户用相同参数生成

DHParameterSpecdhParamSpec=((DHPublicKey)alicePubKey).getParams;
KeyPairGeneratorbobKpairGen=KeyPairGenerator.getInstance(\"DH\");
bobKpairGen.initialize(dhParamSpec);
KeyPairbobKpair=bobKpairGen.generateKeyPair;





bob根据alice公钥生成本地DES密钥

KeyAgreementbobKeyAgree=KeyAgreement.getInstance(\"DH\");
bobKeyAgree.init(bobKpair.getPrivate);
bobKeyAgree.doPhase(alicePubKey,true);
SecretKeybobDesKey=bobKeyAgree.generateSecret(\"DES\");





bob已经生成了他DES密钥,他现把他公钥发给alice,

bobPubKeyEnc=bobKpair.getPublic.getEncoded;





alice根据bob公钥生成本地DES密钥

,,,,,,解码
KeyAgreementaliceKeyAgree=KeyAgreement.getInstance(\"DH\");
aliceKeyAgree.init(aliceKpair.getPrivate);
aliceKeyAgree.doPhase(bobPubKey,true);
SecretKeyaliceDesKey=aliceKeyAgree.generateSecret(\"DES\");





bob和alice能过这个过程就生成了相同DES密钥,在这种基础就可进行安全能信

常用API

java.security.KeyPairGenerator密钥生成器类
publicKeyPairGeneratorgetInstance(Stringalgorithm)
throwsNoSuchAlgorithmException
以指定算法返回个KeyPairGenerator对象
参数:algorithm算法名.如:原来是DSA,现在添加了DfieHellman(DH)

publicvoidinitialize(keysize)
以指定长度化KeyPairGenerator对象,如果没有化系统以1024长度默认设置
参数:keysize算法位长.其范围必须在512到1024的间且必须为64倍数
注意:如果用1024生长时间很长,最好生成次后就保存,下次就不用生成了

publicvoidinitialize(AlgorithmParameterSpecparams)
throwsInvalidAlgorithmParameterException
以指定参数

javax.crypto.erfaces.DHPublicKey
publicDHParameterSpecgetParams
返回
java.security.KeyFactory



publicKeyFactorygetInstance(Stringalgorithm)
throwsNoSuchAlgorithmException
以指定算法返回个KeyFactory
参数:algorithm算法名:DSH,DH

publicfinalPublicKeygeneratePublic(KeySpeckeySpec)
throwsInvalidKeySpecException
根据指定key介绍说明,返回个PublicKey对象

java.security.spec.X509EncodedKeySpec
publicX509EncodedKeySpec(encodedKey)
根据指定 2进制编码字串生成个key介绍说明
参数:encodedKey 2进制编码字串(般能过PublicKey.getEncoded生成)
javax.crypto.KeyAgreement密码至类

publicfinalKeyAgreementgetInstance(java.lang.Stringalgorithm)
throwsjava.security.NoSuchAlgorithmException
返回个指定算法KeyAgreement对象
参数:algorithm算法名,现在只能是DfieHellman(DH)

publicfinalvoidinit(java.security.Keykey)
throwsjava.security.InvalidKeyException
用指定私钥
参数:key个私钥

publicfinaljava.security.KeydoPhase(java.security.Keykey,
booleanlastPhase)
throwsjava.security.InvalidKeyException,
java.lang.IllegalStateException
用指定公钥进行定位,lastPhase确定这是否是最后个公钥,对于两个用户
情况下就可以多次定次,最后确定
参数:key公钥
lastPhase是否最后公钥

publicfinalSecretKeygenerateSecret(java.lang.Stringalgorithm)
throwsjava.lang.IllegalStateException,
java.security.NoSuchAlgorithmException,
java.security.InvalidKeyException
根据指定算法生成密钥
参数:algorithm加密算法(可用DES,DESede,Blowfish)

*/
importjava.io.*;
importjava.math.BigInteger;
importjava.security.*;
importjava.security.spec.*;
importjava.security.erfaces.*;
importjavax.crypto.*;
importjavax.crypto.spec.*;
importjavax.crypto.erfaces.*;
importcom.sun.crypto.provider.SunJCE;

publictestDHKey{


publicvoid(Stringargv){
try{
testDHKeymy=testDHKey;
my.run;
}catch(Exceptione){
.err.prln(e);

}
}

privatevoidrunthrowsException{
Security.addProvider(com.sun.crypto.provider.SunJCE);

.out.prln(\"ALICE:产生DH对...\");
KeyPairGeneratoraliceKpairGen=KeyPairGenerator.getInstance(\"DH\");
aliceKpairGen.initialize(512);
KeyPairaliceKpair=aliceKpairGen.generateKeyPair;//生成时间长

//张 3(Alice)生成公共密钥alicePubKeyEnc并发送给李 4(Bob),
//比如用文件方式,.....
alicePubKeyEnc=aliceKpair.getPublic.getEncoded;

//bob接收到alice编码后公钥,将其解码
KeyFactorybobKeyFac=KeyFactory.getInstance(\"DH\");
X509EncodedKeySpecx509KeySpec=X509EncodedKeySpec(alicePubKeyEnc);
PublicKeyalicePubKey=bobKeyFac.generatePublic(x509KeySpec);
.out.prln(\"alice公钥bob解码成功\");
//bob必须用相同参数DHKEY对,所以要从Alice发给他公开密钥,
//中读出参数,再用这个参数化他DHkey对

//从alicePubKye中取alice化时用参数
DHParameterSpecdhParamSpec=((DHPublicKey)alicePubKey).getParams;
KeyPairGeneratorbobKpairGen=KeyPairGenerator.getInstance(\"DH\");
bobKpairGen.initialize(dhParamSpec);
KeyPairbobKpair=bobKpairGen.generateKeyPair;
.out.prln(\"BOB:生成DHkey对成功\");
KeyAgreementbobKeyAgree=KeyAgreement.getInstance(\"DH\");
bobKeyAgree.init(bobKpair.getPrivate);
.out.prln(\"BOB:化本地key成功\");


//李 4(bob)生成本地密钥bobDesKey
bobKeyAgree.doPhase(alicePubKey,true);
SecretKeybobDesKey=bobKeyAgree.generateSecret(\"DES\");
.out.prln(\"BOB:用alice公钥定位本地key,生成本地DES密钥成功\");
//Bob生成公共密钥bobPubKeyEnc并发送给Alice,
//比如用文件方式,.....,使其生成本地密钥
bobPubKeyEnc=bobKpair.getPublic.getEncoded;
.out.prln(\"BOB向ALICE发送公钥\");

//alice接收到bobPubKeyEnc后生成bobPubKey
//再进行定位,使aliceKeyAgree定位在bobPubKey
KeyFactoryaliceKeyFac=KeyFactory.getInstance(\"DH\");
x509KeySpec=X509EncodedKeySpec(bobPubKeyEnc);
PublicKeybobPubKey=aliceKeyFac.generatePublic(x509KeySpec);
.out.prln(\"ALICE接收BOB公钥并解码成功\");
;
KeyAgreementaliceKeyAgree=KeyAgreement.getInstance(\"DH\");
aliceKeyAgree.init(aliceKpair.getPrivate);
.out.prln(\"ALICE:化本地key成功\");

aliceKeyAgree.doPhase(bobPubKey,true);
//张 3(alice)生成本地密钥aliceDesKey
SecretKeyaliceDesKey=aliceKeyAgree.generateSecret(\"DES\");
.out.prln(\"ALICE:用bob公钥定位本地key,并生成本地DES密钥\");

(aliceDesKey.equals(bobDesKey)).out.prln(\"张 3和李 4密钥相同\");
//现在张 3和李 4本地deskey是相同所以,完全可以进行发送加密,接收后解密,达到
//安全通道

/*
*bob用bobDesKey密钥加密信息
*/
CipherbobCipher=Cipher.getInstance(\"DES\");
bobCipher.init(Cipher.ENCRYPT_MODE,bobDesKey);
Stringbobinfo=\"这是李 4机密信息\";
.out.prln(\"李 4加密前原文:\"+bobinfo);
cleartext=bobinfo.getBytes;
ciphertext=bobCipher.doFinal(cleartext);

/*
*alice用aliceDesKey密钥解密
*/
CipheraliceCipher=Cipher.getInstance(\"DES\");
aliceCipher.init(Cipher.DECRYPT_MODE,aliceDesKey);
recovered=aliceCipher.doFinal(ciphertext);
.out.prln(\"alice解密bob信息:\"+(String(recovered)));
(!java.util.Arrays.equals(cleartext,recovered))
throwException(\"解密后和原文信息区别\");
.out.prln(\"解密后相同\");

}

}





第3章小结
在加密术中生成密钥对时密钥对当然是越长越好但费时也越多请从中从实际出发选取合适长度大部分例码中密钥是每次运行就从新生成在实际情况中是生成后在段时间保存在文件中再次运行直接从文件中读入从而加快速度当然定时更新和加强密钥保管安全性也是必须

有关作者
王辉具有 8年编程及系统管理经验所使用语言为C和Java编程语言目前在深圳家公司做使用C和JAVA为DB2数据库编程.可通过[email protected]联系




Tags:  des加密算法 md5加密算法 java算法 加密算法

延伸阅读

最新评论

发表评论