- 浏览: 357721 次
- 性别:
- 来自: 阿里巴巴
文章分类
- 全部博客 (207)
- Maven (5)
- Cassandra (2)
- Hadoop (3)
- LDAP (2)
- SOA (7)
- 认证、加密、安全 (6)
- 搜索引擎相关技术 (3)
- REST (7)
- 数据库 (11)
- Java 基础相关 (38)
- UML (1)
- Java NIO 框架 (3)
- javassist (1)
- Bean容器 (4)
- 网络编程 (1)
- NoSQL (4)
- XML、Json (1)
- JS (2)
- Google (6)
- Warp-MVC (2)
- 持久层 (2)
- sitebricks (1)
- MVC (6)
- CSS (2)
- JPA (2)
- RDBMS (5)
- cache (4)
- tomcat (1)
- 其它 (3)
- eclipse (1)
- bigpipe (1)
- RDBMS MySQL (1)
- MySQL (2)
- ant (1)
- 前端 (2)
- Groovy (1)
- linux (3)
- Scala (1)
- zookeeper (1)
- redis (2)
- 测试 (1)
- 监控 (1)
- mac (3)
- 区块链 (3)
- 工具 (1)
最新评论
-
masuweng:
好好好,辛苦了!!
Spring Data JPA 简单介绍 -
masuweng:
Spring Data JPA 简单介绍 -
zhangjianxinjava:
您好,大神本人小白一个最近在研究不知道可否 通过邮箱进行交流, ...
JAVA Metrics度量工具 - Metrics Core -
xzs603:
http://zhengdl126.iteye.com/blo ...
数据库水平切分的实现原理解析---分库,分表,主从,集群,负载均衡器 -
JavaStart:
运行mysql2redis 的install.sh 文件为何提 ...
mysql到redis的复制
最近初步接触了下Java加密和数字签名的相关内容,我学习的过程大概分五步:
1)消息摘要
2)私钥加密
3)公钥加密
4)数字签名
5)数字证书
1)消息摘要
- package security;
- import java.security.MessageDigest;
- /**
- * 消息摘要是一种与消息认证码结合使用以确保消息完整性的技术
- * 目前广泛使用的算法有MD4、MD5、SHA-1
- * 在java中进行消息摘要很简单, java.security.MessageDigest提供了一个简易的操作方法,如下
- * 注意:消息摘要是单向的
- */
- public class MessageDigestExample {
- public static void main(String[] args) throws Exception {
- String beforeDegist = "asdf" ;
- System.out.println( "摘要前:" +beforeDegist);
- //初始信息要转换成字节流的形式
- byte [] plainText = beforeDegist.getBytes( "UTF8" );
- //使用getInstance("算法")来获得消息摘要,这里使用SHA-1的160位算法
- // MessageDigest 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);
- }
- }
- package security;
- import javax.crypto.Cipher;
- import javax.crypto.KeyGenerator;
- import java.security.Key;
- /**
- * 此例子是对一个字符串信息,用一个私钥(key)加密,然后在用该私钥解密,验证是否一致
- * 私钥加密,是对称加密
- * 使用对称算法。比如:A用一个密钥对一个文件加密,而B读取这个文件的话,则需要和A一样的密钥,双方共享一
- * 个私钥(而在web环境下,私钥在传递时容易被侦听)
- *
- * 附:主要对称算法有:DES(实际密钥只用到56 位)
- * AES(支持三种密钥长度:128、192、256位),通常首先128位,其他的还有DESede等
- */
- public class PrivateKey {
- public static void main(String[] args) throws Exception {
- String before = "asdf" ;
- byte [] plainText = before.getBytes( "UTF8" );
- //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);
- //2步**********************************************************************
- //获得一个私钥加密类Cipher,定义Cipher的基本信息:ECB是加密方式,PKCS5Padding是填充方法
- Cipher cipher = Cipher.getInstance( "AES/ECB/PKCS5Padding" );
- // System.out.println("\n" + cipher.getProvider().getInfo());
- //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);
- //4步**********************************************************************
- //使用私钥对刚才加密的信息进行解密,看看是否一致,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);
- }
- }
- package security;
- import java.security.KeyPair;
- import java.security.KeyPairGenerator;
- import javax.crypto.Cipher;
- /**
- * 此例子是一个公钥加密例子,Cipher类使用KeyPairGenerator(顾名思义:一对钥匙生成器)生成的公钥和私钥
- *
- * 公钥加密也叫不对称加密,不对称算法使用一对密钥对,一个公钥,一个私钥,使用公钥加密的数据,只有私钥能
- * 解开(可用于加密);同时,使用私钥加密的数据,只有公钥能解开(签名)。但是速度很慢(比私钥加密慢100到
- * 1000倍),公钥的主要算法有RSA,还包括Blowfish,Diffie-Helman 等
- */
- public class PublicKey {
- public static void main(String[] args) throws Exception {
- 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)数字签名
- package security;
- import java.security.Signature;
- import java.security.KeyPairGenerator;
- import java.security.KeyPair;
- import java.security.SignatureException;
- /**
- * 此例子是数字签名的例子,使用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的私钥加密的数据))
- */
- public class DigitalSignature {
- public static void main(String[] args) throws Exception {
- 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
- // System.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( "签名验证正确!!" );
- } else {
- System.out.println( "签名验证失败!!" );
- }
- } catch (SignatureException e) {
- System.out.println( "签名验证失败!!" );
- }
- }
- }
5)数字证书
下面的代码是第五部分:数字证书
比起前四部分,这部分就稍微麻烦点了,我想我有必要给刚刚接触数字证书的朋友们,把在本地跑通下面代码的前提说一下:
1此例是对“数字证书”文件的操作,所以,你先要在本地建立一个证书库
2建立证书库(密钥库)
cmd中输入:C:/>keytool -genkey -alias TestCertification -keyalg RSA -keysize 1024 -keystore BocsoftKeyLib -validity 365
意思是:在c盘目录下创建一个证书,指定证书库为BocsoftKeyLib,创建别名为TestCertification的一条证书,它指定用 RSA 算法生成,且指定密钥长度为1024,证书有效期为1年
建立库的过程中会询问问题,详见第5条
3将证书导出到证书文件TC.cer
在cmd中输入:C:/>keytool -export -alias TestCertification -file TC.cer -keystore BocsoftKeyLib
意思是:将把证书库BocsoftKeyLib中的别名为TestCertification的证书导出到TC.cer证书文件中,它包含证书主体的信息及证书的公钥,不包括私钥,可以公开
4以上3步就基本上完成了证书的操作,下面操作是可选的
导出的证书文件无法用文本编辑器正确显示,可以输入如下命令,然后在以记事本形式打开TC.cer就能看了,看看传说中的证书里到底写的什么鬼东西~~~
C:\>keytool -export -alias TestCertification -file TC.cer -keystore BocsoftKeyLib -storepass keystore -rfc
5在创建证书库时,系统会询问如下问题:
输入keystore密码: keystore(你证书库的密码)
您的名字与姓氏是什么?
[Unknown]: miaozhuang
您的组织单位名称是什么?
[Unknown]: csii
您的组织名称是什么?
[Unknown]: csii
您所在的城市或区域名称是什么?
[Unknown]: tianjin
您所在的州或省份名称是什么?
[Unknown]: tianjin
该单位的两字母国家代码是什么
[Unknown]: ch
CN=miaozhuang, OU=csii, O=csii, L=tianjin, ST=tianjin, C=ch 正确吗?
[否]:
上面的信息都是随便输入的,无关大局
此时输入: y 回车即可(别像我一样,输个yes……傻死了)
- package security;
- import java.security.*;
- import java.security.PublicKey;
- import java.io.*;
- import java.util.*;
- import java.security.*;
- import java.security.cert.*;
- import sun.security.x509.*;
- import java.security.cert.Certificate;
- import java.security.cert.CertificateFactory;
- /**
- * 此例是对“数字证书”文件的操作
- * java平台(在机器上安装jdk)为你提供了密钥库(证书库),cmd下提供了keytool命令就可以创建证书库
- *
- * 在运行此例前:
- * 在c盘目录下创建一个证书,指定证书库为BocsoftKeyLib,创建别名为TestCertification的一条证书,它指定用
- * RSA 算法生成,且指定密钥长度为1024,证书有效期为1年
- * 导出证书文件为TC.cer已存于本地磁盘C:/
- * 密码是keystore
- */
- public class DigitalCertificate {
- public static void main(String[] args) {
- 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= "keystore" ;
- 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();
- }
- }
- }
keytool -genkey -alias test -keyalg RSA -keystore c:/key.store 生成keyStore
RSA是一个既能用于数据加密也能用于数字签名的算法。
DSA(Digital Signature Algorithm,数字签名算法,用作数字签名标准的一部分),它是另一种公开密钥算法,它不能用作加密,只用作数字签名。DSA使用公开密钥,为接受者验证数据的完整性和数据发送者的身份。
提取证书:通过keytool命令我们可以很轻松的提取证书.证书包括主体信息,公钥.
keytool -export -alias 别名 -keystore 文件名 -file 证书名称
但是我们无法通过KEYTOOL工具来提取私钥的..我们只能通过java的KeyStore类getEntry() 或者getKey()来提取私钥.
String keystoreFilename = "C:/keystore/server.keystore";
char[] password = "123456".toCharArray();
String alias = "Server";
KeyStore ks = KeyStore.getInstance("JKS");
java.io.FileInputStream fis = new java.io.FileInputStream(keystoreFilename);
// 从指定的输入流中加载此 KeyStore
ks.load(fis, password);
// keystore 中的每一项都用“别名”字符串标识。
// 使用指定保护参数获取指定别名的 keystore Entry。
方法1、
// KeyStore.PrivateKeyEntry 保存 PrivateKey 和相应证书链的 KeyStore 项。
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias,
new KeyStore.PasswordProtection(password));
System.out.println(pkEntry.getPrivateKey());
// 返回与给定别名相关联的密钥
方法2、
PrivateKey key = (PrivateKey) ks.getKey(alias, password);
怎么来验证提取的私钥是否正确呢?(因为公钥私钥必须成对出现,我们可以通过证书提取去公钥,然后用公钥加密,使用刚刚获得的私钥解密)
提取证书的方法:
keytool -export -alias 别名 -keystore 文件名 -file 证书名称
//通过证书,获取公钥
CertificateFactory cf = CertificateFactory.getInstance("X.509");
FileInputStream in = new FileInputStream("C:\\server\\server.cer");
//生成一个证书对象并使用从输入流 inStream 中读取的数据对它进行初始化。
Certificate c = cf.generateCertificate(in);
PublicKey publicKey = c.getPublicKey();
//通过下面这段代码提取的私钥是否正确
String before = "asdf";
byte[] plainText = before.getBytes("UTF-8");
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 用公钥进行加密,返回一个字节流
byte[] cipherText = cipher.doFinal(plainText);
cipher.init(Cipher.DECRYPT_MODE, myPrivateKey);
// 用私钥进行解密,返回一个字节流
byte[] newPlainText = cipher.doFinal(cipherText);
System.out.println(new String(newPlainText, "UTF-8"));
发表评论
-
《Java加密与解密的艺术》样章连载
2011-04-03 17:01 1766《Java加密与解密的艺术》样章连载 原创作者: 梁栋 ... -
java 数字证书keytool用法
2010-08-17 14:10 3033Java 中的 keytool.exe (位于 JDK\ ... -
keytool - 密钥和证书管理工具
2010-08-15 22:02 1320keytool - 密钥和证书管理工具 管理由私钥和认证相关 ... -
公钥算法
2010-08-15 21:37 1091http://www.hudong.com/wiki/%E5% ... -
https的实现基本原理
2010-08-15 18:23 1416https的实现原理 (此处参考阿密果同学的博文) ...
相关推荐
数字签名使用的是发送方的密钥对,发送方用自己...另外,数字签名只采用了非对称密钥加密算法,它能保证发送信息的完整性、身份认证和不可否认性,而数字加密采用了对称密钥加密算法和非对称密钥加密算法相结合的方法。
数字签名 数字 签名 wod加密 加密
数据加密与数字签名系统,转发非原创,走过路过不要错过。
java 加密 数字签名java 加密 数字签名java 加密 数字签名java 加密 数字签名
发送数字签名和加密邮件-实验报告.pdf
java关于加密的算法demo代码(Base64加密\数字签名\对称加密算法\非对称加密算法\消息摘要算法) JAVA安全实现三种方式: 1.JDK 2.Commons Codec 3.Bouncy Castle 一。非对称加密算法: 1.DH 2.RSA 3.ELGamal 二。...
PDF文件数字签名和加密使用指南
java通信安全主要包括:md5 密码加密与验证 对称加密与解密 非对称加密以解密 基于MD5信息摘要算法实现密码加密与验证 凯撒加密算法 数字签名与验证 消息验证码 消息摘要 所有程序都经过了测试
详细介绍了区块链使用的不对称加密在数字证书数字签名的应用
所谓"数字签名"就是通过某种密码运算生成一系列符号及代码组成电子密码进行签名,来代替书写签名或印章,对于这种电子式的签名还可进行技术验证,其验证的准确度是一般手工签名和图章的验证而无法比拟的。"数字签名...
加密 RSA 数字签名 数字证书。顾名思义 我这个项目里面 有6个加密方法。自己看着下,绝对金典。分高的是有理由的。
基于linux c openssl 库实现公钥签名私钥验签 公钥加密和私钥解密
计算哈希、创建和校验数字签名操作;实现证书、证书撤销列表、证书请求和证书扩展等编码和解码操作。 • 证书库管理函数:用于数字证书及证书库管理等操作。这组函数用于管理证书、证书撤销列表和证书信任列表的使用...
Java加密和数字签名编程快速入门。只是入门,想学精...
深入理解加密、解密、数字签名和数字证书!!!!!!!!
公钥加密,数字签名,公钥认证,认证授权,基于 PKI 授权.zip
利用数字证书实现电子邮件的数字签名和加密(图解)
发送数字签名和加密邮件 实验报告.docx发送数字签名和加密邮件 实验报告.docx发送数字签名和加密邮件 实验报告.docx发送数字签名和加密邮件 实验报告.docx发送数字签名和加密邮件 实验报告.docx发送数字签名和加密...
Android安全加密:数字签名和数字证书 Android安全加密:Https编程 以上学习所有内容,对称加密、非对称加密、消息摘要、数字签名等知识都是为了理解数字证书工作原理而作为一个预备知识。数字证书是密码学里的...