java中的數據加密


記錄

一、java中的數據加密

  • Java提供的安全模型和API
  • 加密基礎知識
  • 使用JAVA實現加密

二、Java提供的安全模型和API

 2.1、Java語言本身的安全性

  • 自動內存管理:對於生成的對象在生命周期結束后會自動銷毀
  • 自動數組溢出檢查等:如數組下標越界
  • 字節代碼的驗證機制:轉化為class字節碼文件運行
  • 獨特的安全類加載:編譯成class類后,加class類進行加載

2.2、Java加密體系

JCA和JCE兩個重要框架

JCA:-JCA-java Cryptography Architecture

  • 數字簽名
  • 信息摘要

JCE:JCE-Java Cryptography Extension

  • MD5(消息摘要算法)
  • SHA(安全散列算法)
  • DES(數據加密算法)

JCA與JCE都實現算法和實現的獨立性,在JDK1.4以后已經捆綁發行,它們都通過provide框架提供加密服務,在使用時,不需要關心相映的算法只需要調用相應的類就行了

其它的一些如圖:

 2.3、Java的認證和授權

  •  基於配置文件的認證和授權:

只需要配置配置文件,方便修改

應用場合,一般適用於B/S開發

安全控制粒度:一般只能到某個頁面

  • 基於源碼的認證和授權:

安全控件粒度:可以控制到某個類甚至方法

應用場合:C/S或者B/S開發均可

JAAS-Java Authentication and Authorization Service

 2.4、安全通信

  • SSL-Secure Socket Layer(安全套接層協議)
  • TLS-Transport Layer Security(安全傳輸協議)
  • Kerberos(一種網絡認證協議)

但一些網站仍然沒有使用安全協議,是因為這些安全帶來的代價就是造成性能的損耗

 2.5、PKI體系

PKI-Public Key Infrastructure

Java的PKI規范提供了管理key和證書的API

實現協議:

  • x.509(最常用)
  • CRL(證書撤銷列表)
  • PKCS等

PKI的核心是數字證書

  • 提供Certifficate數字證書對象等

管理證書的工具:

  • keytool:用來生成證書
  • jarSigner:可用對當前的jar進行簽名保證給指定的人來使用

三、加密基礎知識

 3.1、對稱加密(私鑰體系)

缺點:對稱加密是可逆的

3.2、非對稱加密(公鑰體系)

特點:

  • 加密用公鑰,解密用私鑰
  • 安全性較高。加密/解密慢,適用於分布式網絡
  • 典型應用:數字證書

典型算法:

  • RSA:RSA算法中,每個通信主體都有兩個鑰匙,一個公鑰(Public Key)用來對數據進行加密; 一個私鑰(Private Key)用來對數據進行解密
  • DSA:DSA-Digital Signature Algorithm

3.3、單向散列函數加密

  • h=H(m)返回長度為m的散列值h
  • 特點:加密快,不可逆,破解困難

典型算法:

  • MD5(128位,安全性不夠高)碰撞法破解
  • SHA或者SHA1(160位)

四、使用JAVA實現加密

 4.1、MD5加密實現

 

package com.pb;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;

/*
 * 驗證MD5
 * 1.初始化MessageDigest信息摘要對象
 * 2.傳入需要計算的字符串更新摘要信息
 * 3.計算信息摘要
 * 4.將byte[] 轉換為找度為32位的16進制字符串
 */
public class MD5 {
    /*
     * 生成md5 有傳入參數字符串
     */
    public void generateMD5(String input){
        
        try {
            //1.初始化MessageDigest信息摘要對象,並指定為MD5不分大小寫都可以
            MessageDigest md=MessageDigest.getInstance("md5");
             //2.傳入需要計算的字符串更新摘要信息,傳入的為字節數組byte[],
            //將字符串轉換為字節數組使用getBytes()方法完成
            //指定時其字符編碼 為utf-8
            md.update(input.getBytes("utf-8"));
             //3.計算信息摘要digest()方法
            //返回值為字節數組
            byte [] hashCode=md.digest();
             //4.將byte[] 轉換為找度為32位的16進制字符串
                //聲明StringBuffer對象來存放最后的值
            StringBuffer sb=new StringBuffer();
            //遍歷字節數組
            for(byte b:hashCode){
                //對數組內容轉化為16進制,
                sb.append(Character.forDigit(b>>4&0xf, 16));
                //換2次為32位的16進制
                sb.append(Character.forDigit(b&0xf, 16));
            }
            System.out.println("加密后的結果是:"+sb.toString());
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        //聲明加密MD5類的對象
        MD5 md5=new MD5();
        //使用Scanner來輸入一個字符
        Scanner scanner=new Scanner(System.in);
        System.out.println("請輸入要加密的內容:");
        String input = scanner.nextLine();
        //調用加密方法
        md5.generateMD5(input);

    }
   
}

 結果:

請輸入要加密的內容:
學習MD5加密過程
加密后的結果是:b826cdac46f01dcc8ccc60a76cebf858

 4.2、對稱加密實現

package demo.security;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Scanner;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/*
 * AES對稱加密
 */
public class SymmetricEncoder {
  /*
   * 加密
   * 1.構造密鑰生成器
   * 2.根據ecnodeRules規則初始化密鑰生成器
   * 3.產生密鑰
   * 4.創建和初始化密碼器
   * 5.內容加密
   * 6.返回字符串
   */
    public static String AESEncode(String encodeRules,String content){
        try {
            //1.構造密鑰生成器,指定為AES算法,不區分大小寫
            KeyGenerator keygen=KeyGenerator.getInstance("AES");
            //2.根據ecnodeRules規則初始化密鑰生成器
            //生成一個128位的隨機源,根據傳入的字節數組
            keygen.init(128, new SecureRandom(encodeRules.getBytes()));
              //3.產生原始對稱密鑰
            SecretKey original_key=keygen.generateKey();
              //4.獲得原始對稱密鑰的字節數組
            byte [] raw=original_key.getEncoded();
            //5.根據字節數組生成AES密鑰
            SecretKey key=new SecretKeySpec(raw, "AES");
              //6.根據指定算法AES自成密碼器
            Cipher cipher=Cipher.getInstance("AES");
              //7.初始化密碼器,第一個參數為加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二個參數為使用的KEY
            cipher.init(Cipher.ENCRYPT_MODE, key);
            //8.獲取加密內容的字節數組(這里要設置為utf-8)不然內容中如果有中文和英文混合中文就會解密為亂碼
            byte [] byte_encode=content.getBytes("utf-8");
            //9.根據密碼器的初始化方式--加密:將數據加密
            byte [] byte_AES=cipher.doFinal(byte_encode);
          //10.將加密后的數據轉換為字符串
            //這里用Base64Encoder中會找不到包
            //解決辦法:
            //在項目的Build path中先移除JRE System Library,再添加庫JRE System Library,重新編譯后就一切正常了。
            String AES_encode=new String(new BASE64Encoder().encode(byte_AES));
          //11.將字符串返回
            return AES_encode;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        //如果有錯就返加nulll
        return null;         
    }
    /*
     * 解密
     * 解密過程:
     * 1.同加密1-4步
     * 2.將加密后的字符串反紡成byte[]數組
     * 3.將加密內容解密
     */
    public static String AESDncode(String encodeRules,String content){
        try {
            //1.構造密鑰生成器,指定為AES算法,不區分大小寫
            KeyGenerator keygen=KeyGenerator.getInstance("AES");
            //2.根據ecnodeRules規則初始化密鑰生成器
            //生成一個128位的隨機源,根據傳入的字節數組
            keygen.init(128, new SecureRandom(encodeRules.getBytes()));
              //3.產生原始對稱密鑰
            SecretKey original_key=keygen.generateKey();
              //4.獲得原始對稱密鑰的字節數組
            byte [] raw=original_key.getEncoded();
            //5.根據字節數組生成AES密鑰
            SecretKey key=new SecretKeySpec(raw, "AES");
              //6.根據指定算法AES自成密碼器
            Cipher cipher=Cipher.getInstance("AES");
              //7.初始化密碼器,第一個參數為加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二個參數為使用的KEY
            cipher.init(Cipher.DECRYPT_MODE, key);
            //8.將加密並編碼后的內容解碼成字節數組
            byte [] byte_content= new BASE64Decoder().decodeBuffer(content);
            /*
             * 解密
             */
            byte [] byte_decode=cipher.doFinal(byte_content);
            String AES_decode=new String(byte_decode,"utf-8");
            return AES_decode;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        
        //如果有錯就返加nulll
        return null;         
    }
    
    public static void main(String[] args) {
        SymmetricEncoder se=new SymmetricEncoder();
        Scanner scanner=new Scanner(System.in);
        /*
         * 加密
         */
        System.out.println("使用AES對稱加密,請輸入加密的規則");
        String encodeRules=scanner.next();
        System.out.println("請輸入要加密的內容:");
        String content = scanner.next();
        System.out.println("根據輸入的規則"+encodeRules+"加密后的密文是:"+se.AESEncode(encodeRules, content));
       
        /*
         * 解密
         */
        System.out.println("使用AES對稱解密,請輸入加密的規則:(須與加密相同)");
         encodeRules=scanner.next();
        System.out.println("請輸入要解密的內容(密文):");
         content = scanner.next();
        System.out.println("根據輸入的規則"+encodeRules+"解密后的明文是:"+se.AESDncode(encodeRules, content));
    }

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM