欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java加密解密和数字签名完整代码示例

程序员文章站 2023-12-04 11:50:40
常见的加密算法 基本的单向加密算法: base64严格地说,属于编码格式,而非加密算法 md5(messagedigestalgorithm5,信息摘要算法) sh...

常见的加密算法

基本的单向加密算法:

base64严格地说,属于编码格式,而非加密算法
md5(messagedigestalgorithm5,信息摘要算法)
sha(securehashalgorithm,安全散列算法)
hmac(hashmessageauthenticationcode,散列消息鉴别码)

复杂的对称加密(des、pbe)、非对称加密算法:

des(dataencryptionstandard,数据加密算法)
pbe(password-basedencryption,基于密码验证)
rsa(算法的名字以发明者的名字命名:ronrivest,adishamir和leonardadleman)
dh(diffie-hellman算法,密钥一致协议)
dsa(digitalsignaturealgorithm,数字签名)
ecc(ellipticcurvescryptography,椭圆曲线密码编码学)

数字签名

算法简述

数字签名算法可以看做是一种带有密钥的消息摘要算法,并且这种密钥包含了公钥和私钥。也就是说,数字签名算法是非对称加密算法和消息摘要算法的结合体。

特点

数字签名算法要求能够验证数据完整性、认证数据来源,并起到抗否认的作用。

原理

数字签名算法包含签名和验证两项操作,遵循私钥签名,公钥验证的方式。

签名时要使用私钥和待签名数据,验证时则需要公钥、签名值和待签名数据,其核心算法主要是消息摘要算法。

1. 消息摘要

string beforedegist = "asdf";  
system.out.println("摘要前:"+beforedegist);     
//初始信息要转换成字节流的形式  
byte[] plaintext = beforedegist.getbytes("utf8");   
//使用getinstance("算法")来获得消息摘要,这里使用sha-1的160位算法或者md5算法 
gedigest messagedigest = messagedigest.getinstance("sha-1");  
messagedigest messagedigest = messagedigest.getinstance("md5");    
system.out.println("/n" + messagedigest.getprovider().getinfo());    
//开始使用算法  
messagedigest.update(plaintext);    
//输出算法运算结果  
string afterdegist = new string(messagedigest.digest(),"utf8");  
system.out.println("摘要后:"+afterdegist);  

2. 私钥加密

 /** 
  * 此例子是对一个字符串信息,用一个私钥(key)加密,然后在用该私钥解密,验证是否一致 
  * 私钥加密,是对称加密 
  * 使用对称算法。比如:a用一个密钥对一个文件加密,而b读取这个文件的话,则需要和a一样的密钥,双方共享一 
  * 个私钥(而在web环境下,私钥在传递时容易被侦听) 
  *  
  * 附:主要对称算法有:des(实际密钥只用到56 位) 
  * aes(支持三种密钥长度:128、192、256位),通常首先128位,其他的还有desede等 
  */  
<span style="white-space: pre; ">  </span>string before = "asdf";      
    byte[] plaintext = before.getbytes("utf8");        
    // step 1. 
system.out.println("start generate aes key.");
//得到一个使用aes算法的keygenerator的实例  
keygenerator keygen = keygenerator.getinstance("aes");
//定义密钥长度128位  
keygen.init(128);
//通过keygenerator产生一个key(密钥算法刚才已定义,为aes)  
key key = keygen.generatekey();
system.out.println("finish generating aes key="+key);

//step 2.

    //获得一个私钥加密类cipher,定义cipher的基本信息:ecb是加密方式,pkcs5padding是填充方法  
    cipher cipher = cipher.getinstance("aes/ecb/pkcs5padding");  
//system.out.println("/n" + cipher.getprovider().getinfo());  

//step 3.

// 使用私钥加密  
system.out.println("/n用私钥加密...");
// 把刚才生成的key当作参数,初始化使用刚才获得的私钥加密类,cipher.encrypt_mode意思是加密  
cipher.init(cipher.encrypt_mode, key);
//私钥加密类cipher进行加密,加密后返回一个字节流byte[]  
byte[] ciphertext = cipher.dofinal(plaintext);
//以utf8格式把字节流转化为string  
string after1 = new string(ciphertext, "utf8");
system.out.println("用私钥加密完成:"+after1);

// step 4.

[java] view plain copy
//使用私钥对刚才加密的信息进行解密,看看是否一致,cipher.decrypt_mode意思是解密钥  
system.out.println("/n用私钥解密...");
cipher.init(cipher.decrypt_mode, key);
//对刚才私钥加密的字节流进行解密,解密后返回一个字节流byte[]  
byte[] newplaintext = cipher.dofinal(ciphertext);
string after2 = new string(newplaintext, "utf8");
system.out.println("用私钥解密完成:"+after2);

3. 公钥加密

string before = "asdf";
byte[] plaintext = before.getbytes("utf8");
//产生一个rsa密钥生成器keypairgenerator(顾名思义:一对钥匙生成器)  
keypairgenerator keygen = keypairgenerator.getinstance("rsa");
//定义密钥长度1024位  
keygen.initialize(1024);
//通过keypairgenerator产生密钥,注意:这里的key是一对钥匙!!  
keypair key = keygen.generatekeypair();
//获得一个rsa的cipher类,使用公钥加密  
cipher cipher = cipher.getinstance("rsa/ecb/pkcs1padding");
//system.out.println("/n" + cipher.getprovider().getinfo());  
system.out.println("/n用公钥加密...");
//cipher.encrypt_mode意思是加密,从一对钥匙中得到公钥 key.getpublic()  
cipher.init(cipher.encrypt_mode, key.getpublic());
//用公钥进行加密,返回一个字节流  
byte[] ciphertext = cipher.dofinal(plaintext);
//以utf8格式把字节流转化为string  
string after1 = new string(ciphertext, "utf8");
system.out.println("用公钥加密完成:"+after1);
//使用私钥解密  
system.out.println("/n用私钥解密...");
//cipher.decrypt_mode意思是解密模式,从一对钥匙中得到私钥 key.getprivate()  
cipher.init(cipher.decrypt_mode, key.getprivate());
//用私钥进行解密,返回一个字节流  
byte[] newplaintext = cipher.dofinal(ciphertext);
string after2 = new string(newplaintext, "utf8");
system.out.println("用私钥解密完成:"+after2);

4. 数字签名

/** 
 * 此例子是数字签名的例子,使用rsa私钥对消息摘要(这里指的是原始数据)进行签名,然后使用公钥验证签名 
 *  
 * a通过使用b的公钥加密数据后发给b,b利用b的私钥解密就得到了需要的数据(进过b公钥加密的数据只有b的私钥能够 
 * 解开,c没有b的私钥,所以c解不开,但c可以使用b的公钥加密一份数据发给b,这样一来,问题来了,b收到的数据到 
 * 底是a发过来的还是c发过来的呢) 
 * 由于私钥是唯一的,那么a就可以利用a自己的私钥进行加密,然后b再利用a的公钥来解密,就可以确定:一定是a的消 
 * 息,数字签名的原理就基于此 
 *  
 * 总结:a想将目标数据传给b,此时a需要准备1和2两部分 
 * 1:a使用b的公钥将原始信息加密,以起到保密作用(只有b的私钥能解开,其他人使用其他钥匙都解不开,当然就保密咯) 
 * 2:a使用a的私钥将原始信息的摘要进行签名,以起到接收方b确定是a发过来的作用(a用a的私钥对目标数据的摘要进行签 
 * 名,然后传给b,同时,c用c的私钥对任意信息进行签名也传给b,b想接受的是a的数据(比如说一个转帐请求),于是b 
 * 就通过a的公钥对接受到的两个信息进行解密,解开的就是a(a的公钥能且只能解开a的私钥加密的数据)) 
 */
string before = "asdf";
byte[] plaintext = before.getbytes("utf8");
//形成rsa公钥对  
keypairgenerator keygen = keypairgenerator.getinstance("rsa");
keygen.initialize(1024);
keypair key = keygen.generatekeypair();
//使用私钥签名**********************************************************  
signature sig = signature.getinstance("sha1withrsa");
sig.initsign(key.getprivate());
//sig对象得到私钥  
//签名对象得到原始数据  
sig.update(plaintext);
//sig对象得到原始数据(现实中用的是原始数据的摘要,摘要的是单向的,即摘要算法后无法解密)  
byte[] signature = sig.sign();
//sig对象用私钥对原始数据进行签名,签名后得到签名signature  
em.out.println(sig.getprovider().getinfo());
string after1 = new string(signature, "utf8");
system.out.println("/n用私钥签名后:"+after1);
//使用公钥验证  
sig.initverify(key.getpublic());
//sig对象得到公钥  
//签名对象得到原始信息  
sig.update(plaintext);
//sig对象得到原始数据(现实中是摘要)  
try {
	if (sig.verify(signature)) {
		//sig对象用公钥解密签名signature得到原始数据(即摘要),一致则true  
		system.out.println("签名验证正确!!"+new string(plaintext, "utf8"));
	} else {
		system.out.println("签名验证失败!!");
	}
}
catch (signatureexception e) {
	system.out.println("签名验证失败!!");
}

5. 数字证书

/** 
 * 此例是对“数字证书”文件的操作 
  * java平台(在机器上安装jdk)为你提供了密钥库(证书库),cmd下提供了keytool命令就可以创建证书库 
  *  
  * 在运行此例前: 
  * 在c盘目录下创建一个证书,指定证书库为bocsoftkeylib,创建别名为testcertification的一条证书,它指定用  
  * rsa 算法生成,且指定密钥长度为1024,证书有效期为1年 
  * 导出证书文件为tc.cer已存于本地磁盘c:/ 
  * 密码是qazzaq 
  */
try {
	//前提:将证书库中的一条证书导出到证书文件(我写的例子里证书文件叫tc.cer)  
	//从证书文件tc.cer里读取证书信息  
	certificatefactory cf = certificatefactory.getinstance("x.509");
	fileinputstream in = new fileinputstream("c:/tc.cer");
	//将文件以文件流的形式读入证书类certificate中  
	certificate c = cf.generatecertificate(in);
	system.err.println("转换成string后的证书信息:"+c.tostring());
	*/  
	    //或者不用上面代码的方法,直接从证书库中读取证书信息,和上面的结果一摸一样  
	string pass="qazzaq";
	fileinputstream in2=new fileinputstream("c:/bocsoftkeylib");
	keystore ks=keystore.getinstance("jks");
	ks.load(in2,pass.tochararray());
	string alias = "testcertification";
	//alias为条目的别名  
	certificate c=ks.getcertificate(alias);
	system.err.println("转换成string后的证书信息:"+c.tostring());
	//获取获取x509certificate类型的对象,这是证书类获取certificate的子类,实现了更多方法  
	x509certificate t=(x509certificate)c;
	//从信息中提取需要信息  
	system.out.println("版本号:"+t.getversion());
	system.out.println("序列号:"+t.getserialnumber().tostring(16));
	system.out.println("主体名:"+t.getsubjectdn());
	system.out.println("签发者:"+t.getissuerdn());
	system.out.println("有效期:"+t.getnotbefore());
	system.out.println("签名算法:"+t.getsigalgname());
	byte [] sig=t.getsignature();
	//签名值  
	publickey pk = t.getpublickey();
	byte [] pkenc=pk.getencoded();
	system.out.println("公钥:");
	for (int i=0;i<pkenc.length;i++){
		system.out.print(pkenc[i]+",");
	}
	system.err.println();
	//证书的日期有效性检查,颁发的证书都有一个有效性的日期区间  
	date timenow=new date();
	t.checkvalidity(timenow);
	system.out.println("证书的日期有效性检查:有效的证书日期!");
	//验证证书签名的有效性,通过数字证书认证中心(ca)机构颁布给客户的ca证书,比如:caroot.crt文件  
	//我手里没有ca颁给我的证书,所以下面代码执行不了  
	/*fileinputstream in3=new fileinputstream("caroot.crt");   
    //获取ca证书 
    certificate cac = cf.generatecertificate(in3); 
    //获取ca的公钥   
    publickey pbk=cac.getpublickey();   
    //c为本地证书,也就是待检验的证书,用ca的公钥校验数字证书c的有效性 
    c.verify(pbk);        
  } catch(certificateexpiredexception e){//证书的日期有效性检查:过期   
    system.out.println("证书的日期有效性检查:过期");     
  } catch(certificatenotyetvalidexception e){ //证书的日期有效性检查:尚未生效   
    system.out.println("证书的日期有效性检查:尚未生效");   
  } catch (certificateexception ce) {  
    ce.printstacktrace();  
  } catch (filenotfoundexception fe) {  
    fe.printstacktrace();  
  } /*catch (ioexception ioe){ 
  } catch (keystoreexception kse){ 
  }*/
	catch (exception e){
		e.printstacktrace();
	}
}

总结

以上就是本文关于java加密解密和数字签名完整代码示例的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!