天天看点

加密算法、DES、IDEA、RSA、DSA

转载于 http://desert3.iteye.com/blog/743713

加密技术是对信息进行编码和解码的技术,编码是把原来可读信息(又称明文)译成代码形式(又称密文),其逆过程就是解码(解密)。加密技术的要点是加密算法,加密算法可以分为对称加密、不对称加密和不可逆加密三类算法。 

对称加密算法:对称加密算法是应用较早的加密算法,技术成熟。在对称加密算法中,数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。对称加密算法的特点是算法公开、计算量小、加密速度快、加密效率高。不足之处是,交易双方都使用同样钥匙,安全性得不到保证。此外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的惟一钥匙,这会使得发收信双方所拥有的钥匙数量成几何级数增长,密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。在计算机专网系统中广泛使用的对称加密算法有DES(Data Encryption Standard)和IDEA等。美国国家标准局倡导的AES即将作为新标准取代DES。 

不对称加密算法:不对称加密算法使用两把完全不同但又是完全匹配的一对钥匙—公钥和私钥。在使用不对称加密算法加密文件时,只有使用匹配的一对公钥和私钥,才能完成对明文的加密和解密过程。加密明文时采用公钥加密,解密密文时使用私钥才能完成,而且发信方(加密者)知道收信方的公钥,只有收信方(解密者)才是唯一知道自己私钥的人。不对称加密算法的基本原理是,如果发信方想发送只有收信方才能解读的加密信息,发信方必须首先知道收信方的公钥,然后利用收信方的公钥来加密原文;收信方收到加密密文后,使用自己的私钥才能解密密文。显然,采用不对称加密算法,收发信双方在通信之前,收信方必须将自己早已随机生成的公钥送给发信方,而自己保留私钥。由于不对称算法拥有两个密钥,因而特别适用于分布式系统中的数据加密。广泛应用的不对称加密算法有RSA算法和美国国家标准局提出的DSA(Digital Signature Algorithm)。以不对称加密算法为基础的加密技术应用非常广泛。 

不可逆加密算法:不可逆加密算法的特征是加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,只有重新输入明文,并再次经过同样不可逆的加密算法处理,得到相同的加密密文并被系统重新识别后,才能真正解密。显然,在这类加密过程中,加密是自己,解密还得是自己,而所谓解密,实际上就是重新加一次密,所应用的“密码”也就是输入的明文。不可逆加密算法不存在密钥保管和分发问题,非常适合在分布式网络系统上使用,但因加密计算复杂,工作量相当繁重,通常只在数据量有限的情形下使用,如广泛应用在计算机系统中的口令加密,利用的就是不可逆加密算法。近年来,随着计算机系统性能的不断提高,不可逆加密的应用领域正在逐渐增大。在计算机网络中应用较多不可逆加密算法的有RSA公司发明的MD5算法和由美国国家标准局建议的不可逆加密标准SHS(Secure Hash Standard:安全杂乱信息标准)等。 

DEA(Data Encryption Algorithm、DES)数据加密算法:是一种对称加密算法,很可能是使用最广泛的密钥系统,特别是在保护金融数据的安全中,最初开发的DEA是嵌入硬件中的。通常,自动取款机(Automated Teller Machine,ATM)都使用DEA。它出自IBM的研究工作,IBM也曾对它拥有几年的专利权,但是在1983年已到期后,处于公有范围中,允许在特定条件下可以免除专利使用费而使用。1977年被美国政府正式采纳。 

DES算法的安全性: 一.安全性比较高的一种算法,目前只有一种方法可以破解该算法,那就是穷举法. 二.采用64位密钥技术,实际只有56位有效,8位用来校验的.譬如,有这样的一台PC机器,它能每秒计算一百万次,那么256位空间它要穷举的时间为2285年.所以这种算法还是比较安全的一种算法. 

TripleDES: 该算法被用来解决使用 DES 技术的 56 位时密钥日益减弱的强度,其方法是:使用两个独立密钥对明文运行 DES 算法三次,从而得到 112 位有效密钥强度。TripleDES 有时称为 DESede(表示加密、解密和加密这三个阶段)。 

IDEA 国际数据加密算法:是旅居瑞士中国青年学者来学家和著名密码专家J.Massey于1990年提出的。它在1990年正式公布并在以后得到增强。这种算法是在DES算法的基础上发展出来的,类似于三重DES,和DES一样IDEA也是属于对称密钥算法。发展IDEA也是因为感到DES具有密钥太短等缺点,已经过时。IDEA的密钥为128位,这么长的密钥在今后若干年内应该是安全的。 

RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。 为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。 

加密算法、DES、IDEA、RSA、DSA

RSA 加密算法的缺点: 1)产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。 2)安全性,RSA的安全性依赖于大数的因子分解,但并没有从理论上证明破译RSA的难度与大数分解难度等价,而且密码学界多数人士倾向于因子分解不是NPC问题。 3)速度太慢,由于RSA 的分组长度太大,为保证安全性,n 至少也要 600 bitx以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。 

DSA(Digital Signature Algorithm):被美国国家标准局用来做DSS数据签名标准(Digital Signature Standard)。DSA是基于整数有限域离散对数难题的,其安全性与RSA相比差不多。DSA的一个重要特点是两个素数公开,这样,当使用别人的p和q时,即使不知道私钥,你也能确认它们是否是随机产生的,还是作了手脚。RSA算法却做不到。DSA只是一种算法,和RSA不同之处在于它不能用作加密和解密,也不能进行密钥交换,只用于签名,它比RSA要快很多.

————————————————————————————————————————————————————————————

java实现

第1章基础知识 

1.1. 单钥密码体制 

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

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

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

1.2. 消息摘要 

一个消息摘要就是一个数据块的数字指纹。即对一个任意长度的一个数据块进行计算,产生一个唯一指印(对于SHA1是产生一个20字节的二进制数组)。 

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

两个不同的报文难以生成相同的摘要  

难以对指定的摘要生成一个报文,而由该报文反推算出该指定的摘要  

代表:美国国家标准技术研究所的SHA1和麻省理工学院Ronald Rivest提出的MD5 

1.3. Diffie-Hellman密钥一致协议 

密钥一致协议是由公开密钥密码体制的奠基人Diffie和Hellman所提出的一种思想。 

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

代表:指数密钥一致协议(Exponential Key Agreement Protocol) 

1.4. 非对称算法与公钥体系 

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

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

1.5. 数字签名 

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

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

接受的输入报文数据没有长度限制;  

对任何输入报文数据生成固定长度的摘要(数字指纹)输出  

从报文能方便地算出摘要;  

难以对指定的摘要生成一个报文,而由该报文反推算出该指定的摘要;  

两个不同的报文难以生成相同的摘要  

代表:DSA 

第2章在JAVA中的实现 

2.1. 相关 

Diffie-Hellman密钥一致协议和DES程序需要JCE工具库的支持,可以到 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.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1"); 

添加要进行计算摘要的信息 

alga.update(myinfo.getBytes()); 

计算出摘要 

byte[] digesta=alga.digest(); 

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

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

algb.isEqual(digesta,algb.digest()) 

相关AIP 

java.security.MessageDigest 类 

static getInstance(String algorithm) 

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

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

void update (byte input) 

void update (byte[] input) 

void update(byte[] input, int offset, int len) 

添加要进行计算摘要的信息 

byte[] digest() 

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

void reset() 

复位 

static boolean isEqual(byte[] digesta, byte[] digestb) 

比效两个摘要是否相同 

代码: 

import java.security.*; 

public class myDigest { 

  public static void main(String[] args)  { 

    myDigest my=new myDigest(); 

    my.testDigest(); 

  } 

  public void testDigest() 

  { 

   try { 

     String myinfo="我的测试信息"; 

    //java.security.MessageDigest alg=java.security.MessageDigest.getInstance("MD5"); 

      java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1"); 

      alga.update(myinfo.getBytes()); 

      byte[] digesta=alga.digest(); 

      System.out.println("本信息摘要是:"+byte2hex(digesta)); 

 //通过某中方式传给其他人你的信息(myinfo)和摘要(digesta) 对方可以判断是否更改或传输正常 

      java.security.MessageDigest algb=java.security.MessageDigest.getInstance("SHA-1"); 

      algb.update(myinfo.getBytes()); 

      if (algb.isEqual(digesta,algb.digest())) { 

         System.out.println("信息检查正常"); 

       } 

       else 

        { 

          System.out.println("摘要不相同"); 

         } 

   } 

   catch (java.security.NoSuchAlgorithmException ex) { 

     System.out.println("非法摘要算法"); 

   } 

  } 

  public String byte2hex(byte[] b) //二行制转字符串 

    { 

     String hs=""; 

     String stmp=""; 

     for (int n=0;n<b.length;n++) 

      { 

       stmp=(java.lang.Integer.toHexString(b[n] & 0XFF)); 

       if (stmp.length()==1) hs=hs+"0"+stmp; 

       else hs=hs+stmp; 

       if (n<b.length-1)  hs=hs+":"; 

      } 

     return hs.toUpperCase(); 

    } 

2.3. 数字签名DSA 

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

生成一个KeyPairGenerator实例 

   java.security.KeyPairGenerator  keygen=java.security.KeyPairGenerator.getInstance("DSA"); 

    如果设定随机产生器就用如相代码初始化 

     SecureRandom secrand=new SecureRandom(); 

     secrand.setSeed("tttt".getBytes()); //初始化随机产生器 

     keygen.initialize(512,secrand);     //初始化密钥生成器 

    否则 

     keygen.initialize(512); 

    生成密钥公钥pubkey和私钥prikey 

      KeyPair keys=keygen.generateKeyPair(); //生成密钥组 

      PublicKey pubkey=keys.getPublic(); 

      PrivateKey prikey=keys.getPrivate(); 

    分别保存在myprikey.dat和mypubkey.dat中,以便下次不在生成 

    (生成密钥对的时间比较长 

     java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat")); 

     out.writeObject(prikey); 

     out.close(); 

     out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat")); 

     out.writeObject(pubkey); 

     out.close(); 

用他私人密钥(prikey)对他所确认的信息(info)进行数字签名产生一个签名数组  

从文件中读入私人密钥(prikey) 

   java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat")); 

    PrivateKey myprikey=(PrivateKey)in.readObject(); 

    in.close(); 

    初始一个Signature对象,并用私钥对信息签名 

     java.security.Signature signet=java.security.Signature.getInstance("DSA"); 

     signet.initSign(myprikey); 

     signet.update(myinfo.getBytes()); 

     byte[] signed=signet.sign(); 

    把信息和签名保存在一个文件中(myinfo.dat) 

      java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat")); 

      out.writeObject(myinfo); 

      out.writeObject(signed); 

      out.close(); 

    把他的公钥的信息及签名发给其它用户 

其他用户用他的公共密钥(pubkey)和签名(signed)和信息(info)进行验证是否由他签名的信息  

读入公钥 

java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat")); 

PublicKey pubkey=(PublicKey)in.readObject(); 

in.close(); 

读入签名和信息 

in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat")); 

String info=(String)in.readObject(); 

byte[] signed=(byte[])in.readObject(); 

in.close(); 

初始一个Signature对象,并用公钥和签名进行验证 

java.security.Signature signetcheck=java.security.Signature.getInstance("DSA"); 

signetcheck.initVerify(pubkey); 

signetcheck.update(info.getBytes()); 

if (signetcheck.verify(signed)) { System.out.println("签名正常");} 

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

import java.security.spec.* 

import java.security.* 

具休说明如下 

public key是用X.509编码的,例码如下:   byte[] bobEncodedPubKey=mypublic.getEncoded(); //生成编码 

   //传送二进制编码 

   //以下代码转换编码为相应key对象 

   X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey); 

   KeyFactory keyFactory = KeyFactory.getInstance("DSA"); 

   PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec); 

对于Private key是用PKCS#8编码,例码如下:  byte[] bPKCS=myprikey.getEncoded(); 

  //传送二进制编码 

  //以下代码转换编码为相应key对象 

  PKCS8EncodedKeySpec priPKCS8=new PKCS8EncodedKeySpec(bPKCS); 

  KeyFactory keyf=KeyFactory.getInstance("DSA"); 

  PrivateKey otherprikey=keyf.generatePrivate(priPKCS8); 

常用API  

java.security.KeyPairGenerator 密钥生成器类 

public static KeyPairGenerator getInstance(String algorithm) throws NoSuchAlgorithmException 

以指定的算法返回一个KeyPairGenerator 对象 

参数: algorithm 算法名.如:"DSA","RSA" 

public void initialize(int keysize) 

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

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

public void initialize(int keysize, SecureRandom random) 

以指定的长度初始化和随机发生器初始化KeyPairGenerator对象 

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

random 一个随机位的来源(对于initialize(int keysize)使用了默认随机器 

public abstract KeyPair generateKeyPair() 

产生新密钥对 

java.security.KeyPair 密钥对类 

public PrivateKey getPrivate() 

返回私钥 

public PublicKey getPublic() 

返回公钥 

java.security.Signature 签名类 

public static Signature getInstance(String algorithm) throws NoSuchAlgorithmException 

返回一个指定算法的Signature对象 

参数 algorithm 如:"DSA" 

public final void initSign(PrivateKey privateKey) 

throws InvalidKeyException 

用指定的私钥初始化 

参数:privateKey 所进行签名时用的私钥 

public final void update(byte data) 

throws SignatureException 

public final void update(byte[] data) 

throws SignatureException 

public final void update(byte[] data, int off, int len) 

throws SignatureException 

添加要签名的信息 

public final byte[] sign() 

throws SignatureException 

返回签名的数组,前提是initSign和update 

public final void initVerify(PublicKey publicKey) 

throws InvalidKeyException 

用指定的公钥初始化 

参数:publicKey 验证时用的公钥 

public final boolean verify(byte[] signature) 

throws SignatureException 

验证签名是否有效,前提是已经initVerify初始化 

参数: signature 签名数组 

 */ 

 import java.security.*; 

 import java.security.spec.*; 

public class testdsa { 

  public static void main(String[] args) throws java.security.NoSuchAlgorithmException,java.lang.Exception { 

        testdsa my=new testdsa(); 

        my.run(); 

  } 

  public void run() 

  { 

  //数字签名生成密钥 

  //第一步生成密钥对,如果已经生成过,本过程就可以跳过,对用户来讲myprikey.dat要保存在本地 

//而mypubkey.dat给发布给其它用户 

   if ((new java.io.File("myprikey.dat")).exists()==false) { 

       if (generatekey()==false) { 

           System.out.println("生成密钥对败"); 

           return; 

          }; 

        } 

//第二步,此用户 

//从文件中读入私钥,对一个字符串进行签名后保存在一个文件(myinfo.dat)中 

//并且再把myinfo.dat发送出去 

//为了方便数字签名也放进了myifno.dat文件中,当然也可分别发送 

  try { 

  java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat")); 

  PrivateKey myprikey=(PrivateKey)in.readObject(); 

  in.close(); 

 // java.security.spec.X509EncodedKeySpec pubX509=new java.security.spec.X509EncodedKeySpec(bX509); 

 //java.security.spec.X509EncodedKeySpec pubkeyEncode=java.security.spec.X509EncodedKeySpec 

  String myinfo="这是我的信息";    //要签名的信息 

  //用私钥对信息生成数字签名 

  java.security.Signature signet=java.security.Signature.getInstance("DSA"); 

  signet.initSign(myprikey); 

  signet.update(myinfo.getBytes()); 

  byte[] signed=signet.sign();  //对信息的数字签名 

  System.out.println("signed(签名内容)="+byte2hex(signed)); 

 //把信息和数字签名保存在一个文件中 

  java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat")); 

  out.writeObject(myinfo); 

  out.writeObject(signed); 

  out.close(); 

  System.out.println("签名并生成文件成功"); 

  } 

  catch (java.lang.Exception e) { 

    e.printStackTrace(); 

    System.out.println("签名并生成文件失败"); 

  }; 

  //第三步 

  //其他人通过公共方式得到此户的公钥和文件 

  //其他人用此户的公钥,对文件进行检查,如果成功说明是此用户发布的信息. 

  // 

  try { 

   java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat")); 

   PublicKey pubkey=(PublicKey)in.readObject(); 

   in.close(); 

   System.out.println(pubkey.getFormat()); 

   in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat")); 

   String info=(String)in.readObject(); 

   byte[] signed=(byte[])in.readObject(); 

   in.close(); 

  java.security.Signature signetcheck=java.security.Signature.getInstance("DSA"); 

  signetcheck.initVerify(pubkey); 

  signetcheck.update(info.getBytes()); 

  if (signetcheck.verify(signed)) { 

  System.out.println("info="+info); 

   System.out.println("签名正常"); 

  } 

  else  System.out.println("非签名正常"); 

  } 

  catch (java.lang.Exception e) {e.printStackTrace();}; 

  } 

  //生成一对文件myprikey.dat和mypubkey.dat---私钥和公钥, 

  //公钥要用户发送(文件,网络等方法)给其它用户,私钥保存在本地 

  public boolean generatekey() 

  { 

    try { 

  java.security.KeyPairGenerator  keygen=java.security.KeyPairGenerator.getInstance("DSA"); 

 // SecureRandom secrand=new SecureRandom(); 

 // secrand.setSeed("tttt".getBytes()); //初始化随机产生器 

 // keygen.initialize(576,secrand);     //初始化密钥生成器 

  keygen.initialize(512); 

  KeyPair keys=keygen.genKeyPair(); 

//  KeyPair keys=keygen.generateKeyPair(); //生成密钥组 

  PublicKey pubkey=keys.getPublic(); 

  PrivateKey prikey=keys.getPrivate(); 

  java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat")); 

  out.writeObject(prikey); 

  out.close(); 

  System.out.println("写入对象 prikeys ok"); 

  out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat")); 

   out.writeObject(pubkey); 

out.close(); 

   System.out.println("写入对象 pubkeys ok"); 

   System.out.println("生成密钥对成功"); 

   return true; 

  } 

  catch (java.lang.Exception e) { 

   e.printStackTrace(); 

   System.out.println("生成密钥对失败"); 

   return false; 

   }; 

  } 

  public String byte2hex(byte[] b) 

    { 

     String hs=""; 

     String stmp=""; 

     for (int n=0;n<b.length;n++) 

      { 

       stmp=(java.lang.Integer.toHexString(b[n] & 0XFF)); 

       if (stmp.length()==1) hs=hs+"0"+stmp; 

       else hs=hs+stmp; 

       if (n<b.length-1)  hs=hs+":"; 

      } 

     return hs.toUpperCase(); 

    } 

2.4. DESede/DES对称算法 

首先生成密钥,并保存(这里并没的保存的代码,可参考DSA中的方法) 

KeyGenerator keygen = KeyGenerator.getInstance(Algorithm); 

SecretKey deskey = keygen.generateKey(); 

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

Cipher c1 = Cipher.getInstance(Algorithm); 

c1.init(Cipher.ENCRYPT_MODE,deskey); 

byte[] cipherByte=c1.doFinal(myinfo.getBytes()); 

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

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

用密钥解密密文 

c1 = Cipher.getInstance(Algorithm); 

c1.init(Cipher.DECRYPT_MODE,deskey); 

byte[] clearByte=c1.doFinal(cipherByte); 

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

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

   SecretKey deskey = keygen.generateKey(); 

   byte[] desEncode=deskey.getEncoded(); 

   javax.crypto.spec.SecretKeySpec destmp=new javax.crypto.spec.SecretKeySpec(desEncode,Algorithm); 

   SecretKey mydeskey=destmp; 

相关API 

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

DES,DESede,Blowfish,HmacMD5,HmacSHA1 

javax.crypto.Cipher 加/解密器 

public static final Cipher getInstance(java.lang.String transformation) 

                                throws java.security.NoSuchAlgorithmException, 

                                       NoSuchPaddingException 

返回一个指定方法的Cipher对象 

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

public final void init(int opmode, java.security.Key key) 

throws java.security.InvalidKeyException 

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

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

key 密钥 

public final byte[] doFinal(byte[] input) 

                     throws java.lang.IllegalStateException, 

                            IllegalBlockSizeException, 

                            BadPaddingException 

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

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

import java.security.*; 

import javax.crypto.*; 

public class testdes { 

public static void main(String[] args){ 

    testdes my=new testdes(); 

    my.run(); 

  } 

public  void run() { 

//添加新安全算法,如果用JCE就要把它添加进去 

 Security.addProvider(new com.sun.crypto.provider.SunJCE()); 

String Algorithm="DES"; //定义 加密算法,可用 DES,DESede,Blowfish 

String myinfo="要加密的信息"; 

   try { 

   //生成密钥 

   KeyGenerator keygen = KeyGenerator.getInstance(Algorithm); 

   SecretKey deskey = keygen.generateKey(); 

   //加密 

   System.out.println("加密前的二进串:"+byte2hex(myinfo.getBytes())); 

   System.out.println("加密前的信息:"+myinfo); 

   Cipher c1 = Cipher.getInstance(Algorithm); 

   c1.init(Cipher.ENCRYPT_MODE,deskey); 

   byte[] cipherByte=c1.doFinal(myinfo.getBytes()); 

    System.out.println("加密后的二进串:"+byte2hex(cipherByte)); 

   //解密 

   c1 = Cipher.getInstance(Algorithm); 

   c1.init(Cipher.DECRYPT_MODE,deskey); 

   byte[] clearByte=c1.doFinal(cipherByte); 

   System.out.println("解密后的二进串:"+byte2hex(clearByte)); 

   System.out.println("解密后的信息:"+(new String(clearByte))); 

  } 

   catch (java.security.NoSuchAlgorithmException e1) {e1.printStackTrace();} 

   catch (javax.crypto.NoSuchPaddingException e2) {e2.printStackTrace();} 

   catch (java.lang.Exception e3) {e3.printStackTrace();} 

  } 

 public String byte2hex(byte[] b) //二行制转字符串 

    { 

     String hs=""; 

     String stmp=""; 

     for (int n=0;n<b.length;n++) 

      { 

       stmp=(java.lang.Integer.toHexString(b[n] & 0XFF)); 

       if (stmp.length()==1) hs=hs+"0"+stmp; 

       else hs=hs+stmp; 

       if (n<b.length-1)  hs=hs+":"; 

      } 

     return hs.toUpperCase(); 

    } 

2.5. Diffie-Hellman密钥一致协议 

公开密钥密码体制的奠基人Diffie和Hellman所提出的 "指数密钥一致协议"(Exponential Key Agreement Protocol),该协议不要求

原文地址:http://www.zaoxue.com/article/tech-54324.htm