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

常见的加密算法

基本的单向加密算法:

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

(0)

相关推荐

  • Java 方法签名详解及实例代码

    java 方法签名,我想做java 开发的朋友也知道,方法签名的重要性,是方法重载的一个比较好的解释,尤其是在后续优化方面,这里记录下,有看到的朋友也可看下, 方法签名的意义 对于同名不同类.同类不同名的方法,方法签名的意义并不是很大,但是对于重载方法来说,方法签名的意义就十分巨大了.由于重载方法之间的方法名是相同的,那么我们势必要从构成方法的其他几个要素中找到另一个要素与方法名组成能够唯一标示方法的签名,方法体当然不予考虑.那么就是形参列表和返回值了,但是由于对于调用方法的人来说,方法的形参数

  • 微信开发之使用java获取签名signature

    一.前言 微信接口调用验证最终需要用到的三个参数noncestr.timestamp.signature: 接下来将会给出获取这三个参数的详细代码 本文的环境eclipse + maven 本文使用到的技术HttpClient.Json字符串转map.sha1加密 二.需要用到的jar包 maven依赖的包有: 1.HttpClient包依赖 <dependency> <groupId>org.apache.httpcomponents</groupId> <ar

  • 使用数字签名实现数据库记录防篡改(Java实现)

    本文大纲 一.提出问题 二.数字签名 三.实现步骤 四.参考代码 五.后记 六.参考资料 一.提出问题 最近在做一个项目,需要对一个现成的产品的数据库进行操作,增加额外的功能.为此,需要对该产品对数据库有什么操作进行研究(至于怎么监控一个产品的操作会引发什么数据库操作,以后会详细解说).本来已经对数据库的操作了如指掌的,无意中发现数据库表里的每条记录都会有这样一个字段: 这感觉不妙了,字段名叫signature,顾名思义,就是签名的意思呀.难道数据库表中的每条记录都会有签名?也就是说如果我不能正

  • Java使用DSA密钥对生成XML签名的方法

    本文实例讲述了Java使用DSA密钥对生成XML签名的方法.分享给大家供大家参考.具体实现方法如下: MainClass.java代码如下: 复制代码 代码如下: import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.SecureRandom; import java.util.Collections; import javax.xml.crypto.dsig.Canon

  • 常用数字签名算法RSA与DSA的Java程序内实现示例

    RSA加密算法 我们来回顾一下RSA的加密算法.我们从公钥加密算法和签名算法的定义出发,用比较规范的语言来描述这一算法. RSA公钥加密体制包含如下3个算法:KeyGen(密钥生成算法),Encrypt(加密算法)以及Decrypt(解密算法). 密钥生成算法以安全常数作为输入,输出一个公钥PK,和一个私钥SK.安全常数用于确定这个加密算法的安全性有多高,一般以加密算法使用的质数p的大小有关.越大,质数p一般越大,保证体制有更高的安全性.在RSA中,密钥生成算法如下:算法首先随机产生两个不同大质

  • java结合keytool如何实现非对称签名和验证详解

    前言 本文主要介绍了关于java结合keytool实现非对称签名和验证的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧 参考 还有姊妹篇:java结合keytool实现非对称加密和解密 keytool的使用 keytool是JDK自带的一个密钥库管理工具.这里只用到了keytool的部分功能,包括生成密钥对,导出公钥等.keytool生成的公钥/私钥对存放到一个到了一个文件中,这个文件有密码保护,通称为keystore. 生成密钥对 $ keytool -genkey

  • 纯Java实现数字证书生成签名的简单实例

    package com.ylsoft.cert; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator;

  • Java加密和数字签名编程

    本文主要谈一下密码学中的加密和数字签名,以及其在java中如何进行使用.对密码学有兴趣的伙伴,推荐看Bruce Schneier的著作:Applied Crypotography.在jdk1.5的发行版本中安全性方面有了很大的改进,也提供了对RSA算法的直接支持,现在我们从实例入手解决问题(本文仅是作为简单介绍): 一.密码学上常用的概念 1)消息摘要: 这是一种与消息认证码结合使用以确保消息完整性的技术.主要使用单向散列函数算法,可用于检验消息的完整性,和通过散列密码直接以文本形式保存等,目前

  • jdk中密钥和证书管理工具keytool常用命令详解

    -genkey      在用户主目录中创建一个默认文件".keystore",还会产生一个mykey的别名,mykey中包含用户的公钥.私钥和证书 -alias       产生别名-keystore    指定密钥库的名称(产生的各类信息将不在.keystore文件中-keyalg      指定密钥的算法    -validity    指定创建的证书有效期多少天-keysize     指定密钥长度-storepass   指定密钥库的密码-keypass     指定别名条目

  • Java2下Applet数字签名

    我的项目是使用APPLET制作一个实时消息队列监控程序,由于涉及到了本地资源,对APPLET一定要进行数字签名和认证.我使用的环境是WINDOWS2000,应用服务器是WEBLOGIC6.0,开发环境是JBUILDER4.0.之前我提醒大家一定要注意服务器端和客户端的概念.那些文件应该在服务器端,那些文件应该在客户端. 首先在客户端使用JRE1.3.0_01(JAVA运行环境1.3.0.1版本)以取代IE的JVM(JAVA虚拟机),可以到WWW.JAVA.SUN.COM网站上去下载,下载好了先在

随机推荐