Java加解密密和数字签名

来源:互联网 发布:网络安全法是为了维护 编辑:程序博客网 时间:2024/05/18 01:31

最近初步接触了下Java加密和数字签名的相关内容,目前学习的主要内容如下:

1)消息摘要

2)私钥加密

3)公钥加密

4)数字签名

5)数字证书 


以下是对这几步的代码实例,代码就是我们的语言  哈

1. 消息摘要
        String beforeDegist = "asdf";          System.out.println("摘要前:"+beforeDegist);                      //初始信息要转换成字节流的形式          byte[] plainText = beforeDegist.getBytes("UTF8");           //使用getInstance("算法")来获得消息摘要,这里使用SHA-1的160位算法或者MD5算法//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); 
              
2. 私钥加密
  /**    * 此例子是对一个字符串信息,用一个私钥(key)加密,然后在用该私钥解密,验证是否一致    * 私钥加密,是对称加密    * 使用对称算法。比如:A用一个密钥对一个文件加密,而B读取这个文件的话,则需要和A一样的密钥,双方共享一    * 个私钥(而在web环境下,私钥在传递时容易被侦听)    *     * 附:主要对称算法有:DES(实际密钥只用到56 位)    * AES(支持三种密钥长度:128、192、256位),通常首先128位,其他的还有DESede等    */ 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.     
        //使用私钥对刚才加密的信息进行解密,看看是否一致,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  //System.out.println(sig.getProvider().getInfo());          String after1 = new String(signature, "UTF8");          System.out.println("/n用私钥签名后:"+after1);           //使用公钥验证        key = keyGen.generateKeyPair();         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();          }     }   

原创粉丝点击