Java的安全学习(包括加密,数字签名,证书和认证)

(1)消息摘要: java

 

消息摘要(Message Digest)又称为数字摘要(Digital Digest)。它是一个惟一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行做用而产生。若是消息在途中改变了,则接收者经过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了。所以消息摘要保证了消息的完整性。       消息摘要采用单向Hash 函数将需加密的明文"摘要"成一串128bit的密文,这一串密文亦称为数字指纹(Finger Print),它有固定的长度,且不一样的明文摘要成密文,其结果老是不一样的,而一样的明文其摘要一定一致。这样这串摘要即可成为验证实文是不是"真身"的"指纹"了。 git

    这是一种与消息认证码结合使用以确保消息完整性的技术。主要使用单向散列函数算法,可用于检验消息的完整性,和经过散列密码直接以文本形式保存等,目前普遍使用的算法有MD四、MD五、SHA-1,在java中进行消息摘要很简单:下面举一个简单的例子 算法

/**
*MessageDigestTest.java
*/
import java.security.MessageDigest;
/**
*单一的消息摘要算法,不使用密码.能够用来对明文消息(如:密码)隐藏保存
*/
public class MessageDigestTest{
 public static void main(String[] args) throws Exception{ 编程


  String str="123";
  byte[] plainText=str.getBytes("UTF8");

  //使用getInstance("算法")来得到消息摘要,这里使用SHA-1的160位算法
  MessageDigest messageDigest=MessageDigest.getInstance("SHA-1");

  System.out.println("/n"+messageDigest.getProvider().getInfo());
  //开始使用算法
  messageDigest.update(plainText);
  System.out.println("/nDigest:");
  //输出算法运算结果
  System.out.println(new String(messageDigest.digest(),"UTF8"));
 }
} 

(还能够经过消息认证码来进行加密实现,javax.crypto.Mac提供了一个解决方案,有兴趣者能够参考相关API文档,本文只是简单介绍什么是摘要算法。) windows

(2)私公钥和私钥: 浏览器

 

公钥和私钥就是俗称的不对称加密方式,是从之前的对称加密(使用用户名与密码)方式的提升。用电子邮件的方式说明一下原理。 安全

  使用公钥与私钥的目的就是实现安全的电子邮件,必须实现以下目的: 服务器

  1.我发送给你的内容必须加密,在邮件的传输过程当中不能被别人看到。 网络

  2.必须保证是我发送的邮件,不是别人冒充个人。 app

  要达到这样的目标必须发送邮件的两人都有公钥和私钥。

  公钥,就是给你们用的,你能够经过电子邮件发布,能够经过网站让别人下载,公钥实际上是用来加密/验章用的。私钥,就是本身的,必须很是当心保存,最好加上密码,私钥是用来解密/签章,首先就Key的全部权来讲,私钥只有我的拥有。公钥与私钥的做用是:用公钥加密的内容只能用私钥解密,用私钥加密的内容只能用公钥解密。

  好比说,我要给你发送一个加密的邮件。首先,我必须拥有你的公钥,你也必须拥有个人公钥。

  首先,我用你的公钥给这个邮件加密,这样就保证这个邮件不被别人看到,并且保证这个邮件在传送过程当中没有被修改。你收到邮件后,用你的私钥就能够解密,就能看到内容。

  其次我用个人私钥给这个邮件加密,发送到你手里后,你能够用个人公钥解密。由于私钥只有我手里有,这样就保证了这个邮件是我发送的。

  当A->B资料时,A会使用B的公钥加密,这样才能确保只有B能解开,不然普罗大众都能解开加密的讯息,就是去了资料的保密性。验证方面则是使用签验章的机制,A传资料给你们时,会以本身的私钥作签章,如此全部收到讯息的人均可以用A的公钥进行验章,即可确认讯息是由A发出来的了。

 

I.私匙加密解密实例:

/**
*PrivateTest.java
*/
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import java.security.Key;

/**
*私鈅加密,保证消息机密性
*/
public class PrivateTest{
 public static void main(String[] args) throws Exception{

       String str="123";
   byte[] plainText=str.getBytes("UTF8");
    
  //经过KeyGenerator造成一个key
  System.out.println("/nStart generate AES key");
  KeyGenerator keyGen=KeyGenerator.getInstance("AES");
  keyGen.init(128);
  Key key=keyGen.generateKey();
  System.out.println("Finish generating DES key");

  //得到一个私鈅加密类Cipher,ECB是加密方式,PKCS5Padding是填充方法
  Cipher cipher=Cipher.getInstance("AES/ECB/PKCS5Padding");
  System.out.println("/n"+cipher.getProvider().getInfo());

  //使用私鈅加密
  System.out.println("/nStart encryption:");
  cipher.init(Cipher.ENCRYPT_MODE,key);
  byte[] cipherText=cipher.doFinal(plainText);
  System.out.println("Finish encryption:");
  System.out.println(new String(cipherText,"UTF8"));

 

     //使用私鈅解密

  System.out.println("/nStart decryption:");
  cipher.init(Cipher.DECRYPT_MODE,key);
  byte[] newPlainText=cipher.doFinal(cipherText);
  System.out.println("Finish decryption:");

  System.out.println(new String(newPlainText,"UTF8"));

 }
} 

II.公匙加密,私匙解密实例:

 

/**
*PublicTest.java
*/
import java.security.Key;
import javax.crypto.Cipher;
import java.security.KeyPairGenerator;
import java.security.KeyPair;
/**
*一个简单的公鈅加密例子,Cipher类使用KeyPairGenerator生成的公鈅和私鈅
*/
public class PublicTest{
 public static void main(String[] args) throws Exception{
     String str="123";
   byte[] plainText=str.getBytes("UTF8");
  //构成一个RSA密钥
  System.out.println("/nStart generating RSA key");
  KeyPairGenerator keyGen=KeyPairGenerator.getInstance("RSA");
  keyGen.initialize(1024);
  KeyPair key=keyGen.generateKeyPair();
  System.out.println("Finish generating RSA key");

  //得到一个RSA的Cipher类,使用公鈅加密
  Cipher cipher=Cipher.getInstance("RSA/ECB/PKCS1Padding");
  System.out.println("/n"+cipher.getProvider().getInfo());

  System.out.println("/nStart encryption");
  cipher.init(Cipher.ENCRYPT_MODE,key.getPublic());
  byte[] cipherText=cipher.doFinal(plainText);
  System.out.println("Finish encryption:");
  System.out.println(new String(cipherText,"UTF8"));

  //使用私鈅解密
  System.out.println("/nStart decryption");
  cipher.init(Cipher.DECRYPT_MODE,key.getPrivate());
  byte[] newPlainText=cipher.doFinal(cipherText);
  System.out.println("Finish decryption:");
  System.out.println(new String(newPlainText,"UTF8"));
 }
}

 

 (3)数字签名:
I.电子商务中数据传输的几个安全性需求

     1. 数据的保密性:用于防止非法用户进入系统及合法用户对系统资源的非法使用;经过对一些敏感的数据文件进行加密来保护系统之间的数据交换,防止除接收方以外的第三方截获数据及即便获取文件也没法获得其内容。如在电子交易中,避免遭到黑客的袭击使信用卡信息丢失的问题。

  2. 数据的完整性:防止非法用户对进行交换的数据进行无心或恶意的修改、插入,防止交换的数据丢失等。

  3. 数据的不能否认性:对数据和信息的来源进行验证,以确保数据由合法的用户发出;防止数据发送方在发出数据后又加以否定;同时防止接收方在收到数据后又否定曾收到过此数据及篡改数据。

  上述需求对应于防火墙、加密、数字签名、身份认证等技术,但其关键在于数字签名技术。

II. 数字签名的含义

  数字签名是经过一个单向函数对要传送的报文进行处理获得的用以认证报文来源并核实报文是否发生变化的一个字母数字串。

III.数字签名的实现方法

    实现数字签名有不少方法,目前数字签名采用较多的是公钥加密技术,如基于RSA Date Security 公司的PKCS( Public Key Cryptography Standards )、Digital Signature Algorithm、x.50九、PGP(Pretty Good Privacy). 1994年美国标准与技术协会公布了数字签名标准(DSS)而使公钥加密技术普遍应用。&127;公钥加密系统采用的是非对称加密算法 
IIII.实例

**
*DigitalSignatureTest.java
*/
import java.security.Signature;
import java.security.KeyPairGenerator;
import java.security.KeyPair;
import java.security.SignatureException;

/**
*数字签名,使用RSA私钥对对消息摘要签名,而后使用公鈅验证 测试
*/
public class DigitalSignatureTest{
 public static void main(String[] args) throws Exception{
     String str="123";
   byte[] plainText=str.getBytes("UTF8");
  //造成RSA公钥对
  System.out.println("/nStart generating RSA key");
  KeyPairGenerator keyGen=KeyPairGenerator.getInstance("RSA");
  keyGen.initialize(1024);

  KeyPair key=keyGen.generateKeyPair();
  System.out.println("Finish generating RSA key");
  //使用私鈅签名
  Signature sig=Signature.getInstance("SHA1WithRSA");
  sig.initSign(key.getPrivate());
  sig.update(plainText);
  byte[] signature=sig.sign();
  System.out.println(sig.getProvider().getInfo());
  System.out.println("/nSignature:");
  System.out.println(new String(signature,"UTF8"));

  //使用公鈅验证
  System.out.println("/nStart signature verification");
  sig.initVerify(key.getPublic());
  sig.update(plainText);
  try{
   if(sig.verify(signature)){
    System.out.println("Signature verified");
   }else System.out.println("Signature failed");
   }catch(SignatureException e){
    System.out.println("Signature failed");
   }
  }
} 
(4)数字证书

I.概念:是数字形式的标识,与护照或驾驶员执照十分类似。数字证书是数字凭据,它提供有关实体标识的信息以及其余支持信息。数字证书是由成为证书颁发机构(CA)的权威机构颁发的。因为数字证书有证书权威机构颁发,所以由该权威机构担保证书信息的有效性。此外,数字证书只在特定的时间段内有效。

  数字证书包含证书中所标识的实体的公钥(就是说你的证书里有你的公钥),因为证书将公钥与特定的我的匹配,而且该证书的真实性由颁发机构保证(就是说可让你们相信你的证书是真的),所以,数字证书为如何找到用户的公钥并知道它是否有效这一问题提供了解决方案。

II.数字证书的原理

     数字证书采用公钥体制,即利用一对互相匹配的密钥进行加密、解密。每一个用户本身设定一把特定的仅为本人所知的私有密钥(私钥),用它进行解密和签名;同时设定一把公共密钥(公钥)并由本人公开,为一组用户所共享,用于加密和验证签名。当发送一份保密文件时,发送方使用接收方的公钥对数据加密,而接收方则使用本身的私钥解密,这样信息就能够安全无误地到达目的地了。经过数字的手段保证加密过程是一个不可逆过程,即只有用私有密钥才能解密.在公开密钥密码体制中,经常使用的一种是RSA体制。

  用户也能够采用本身的私钥对信息加以处理,因为密钥仅为本人全部,这样就产生了别人没法生成的文件,也就造成了数字签名。采用数字签名,可以确认如下两点:

  (1)保证信息是由签名者本身签名发送的,签名者不可否认或难以否定;

  (2)保证信息自签发后到收到为止不曾做过任何修改,签发的文件是真实文件。
III.java实例操做:

 

     密钥库:java平台为你提供了密钥库,用做密钥和证书的资源库。从物理上讲,密钥库是缺省名称为 .keystore 的文件(有一个选项使它成为加密文件)。密钥和证书能够拥有名称(称为别名),每一个别名都由惟一的密码保护。密钥库自己也受密码保护;您能够选择让每一个别名密码与主密钥库密码匹配。 

  使用工具keytool,进行自我认证:

  一、建立密钥库keytool -genkey -v -alias YourKeyName -keyalg RSA 默认在本身的home目录下(windows系统是c:/documents and settings/<你的用户名> 目录下的.keystore文件),建立咱们用 RSA 算法生成别名为 feiUserKey 的自签名的证书,若是使用了-keystore mm 就在当前目录下建立一个密钥库mm文件来保存密钥和证书。

  二、查看证书:keytool -list 列举了密钥库的全部的证书 

  也能够在dos下输入keytool -help查看帮助。


(5)JAR的签名

    前面咱们已将讲了怎样建立本身的证书了,如今能够开始了解怎样对JAR文件签名,JAR文件在Java中至关于 ZIP 文件,容许将多个 Java 类文件打包到一个具备 .jar 扩展名的文件中,而后能够对这个jar文件进行数字签名,以证明其来源和真实性。该 JAR 文件的接收方能够根据发送方的签名决定是否信任该代码,并能够确信该内容在接收以前没有被篡改过。同时在部署中,能够经过在策略文件中放置访问控制语句根据签名者的身份分配对机器资源的访问权。这样,有些Applet的安全检验访问就得以进行。

  使用jarsigner工具能够对jar文件进行签名:

  如今假设咱们有个Test.jar文件(可使用jar命令行工具生成):

  jarsigner Test.jar YourKeyName (这里咱们上面建立了该别名的证书) ,详细信息能够输入jarsigner查看帮助

  验证其真实性:jarsigner -verify Test.jar(注意,验证的是jar是否被修改了,但不检验减小的,若是增长了新的内容,也提示,但减小的不会提示。)

  使用Applet中::<applet code="Test.class" archive="Test.jar" width="150" height="100"></applet>而后浏览器就会提示你:准许这个会话-拒绝-始终准许-查看证书等。

(6)安全套接字层(SSL Secure Sockets Layer)和传输层安全性(TLS Transport Layer Security)  

I.简介:      

 安全套接字层 (SSL):一种由 Netscape Communications 开发的提议开放式标准,用以创建安全通信通道,以防止如信用卡号等这样的重要信息被截获。

安全套接字层是用于服务器之上的一个加密系统,它能够确保在客户机与服务器之间传输的数据仍然是安全与隐密的。要使服务器和客户机使用 SSL 进行安全的通讯,服务器必须有两样东西:

  密钥对(Key pair) —— 一个密钥对包括一个公钥和一个私钥。这两个密钥用来对消息进行加密和解密,以确保在因特网上传输时的隐密性和机密性。

  证书(Certificate) —— 证书用来进行身份验证或者身份确认。证书能够是自签(self-signed)证书,也能够是颁发(issued)证书。自签证书是为本身私有的 Web 网络建立的证书。颁发证书是认证中心(certificate authority,CA)或者证书签署者提供(颁发)给您的证书。

  SSL 使用安全握手来初始化客户机与服务器之间的安全链接。在握手期间,客户机和服务器对它们将要为此会话使用的密钥及加密方法达成一致。客户机使用服务器证书验证服务器。握手以后,SSL 被用来加密和解密 HTTPS(组合 SSL 和 HTTP 的一个独特协议)请求和服务器响应中的全部信息,包括:

  客户机正在请求的 URL。

  提交的表单的内容。

  访问受权信息(好比用户名和密码)。

  全部在客户机与服务器之间发送的数据。

 

 II.总结:

安全套接字层和传输层安全性是用于在客户机和服务器之间构建安全的通讯通道的协议。它也用来为客户机认证服务器,以及(不太经常使用的)为服务器认证客户机。该协议在浏览器应用程序中比较常见,浏览器窗口底部的锁代表 SSL/TLS 有效:   1)当使用 SSL/TLS(一般使用 https:// URL)向站点进行请求时,从服务器向客户机发送一个证书。客户机使用已安装的公共 CA 证书经过这个证书验证服务器的身份,而后检查 IP 名称(机器名)与客户机链接的机器是否匹配。   2)客户机生成一些能够用来生成对话的私钥(称为会话密钥)的随机信息,而后用服务器的公钥对它加密并将它发送到服务器。服务器用本身的私钥解密消息,而后用该随机信息派生出和客户机同样的私有会话密钥。一般在这个阶段使用 RSA 公钥算法。   3)客户机和服务器使用私有会话密钥和私钥算法(一般是 RC4)进行通讯。使用另外一个密钥的消息认证码来确保消息的完整性。   java中javax.net.ssl.SSLServerSocketFactory类提供了一个很好的SSLServerSocker的工厂类,熟悉Socket编程的读者能够去练习。当编写完服务器端以后,在浏览器上输入https://主机名:端口 就会经过SSL/TLS进行通话了。注意:运行服务端的时候要带系统环境变量运行:javax.net.ssl.keyStore=密钥库(建立证书时,名字应该为主机名,好比localhost)和javax.net.ssl.keyStorePassword=你的密码

相关文章
相关标签/搜索