Java安全密碼學-(三)常見加密方式

對稱加密

採用單鑰密碼系統的加密方法,同一個密鑰可以同時用作信息的加密和解密,這種加密方法稱爲對稱加密,也稱爲單密鑰加密。

示例

我們現在有一個原文3要發送給B

設置密鑰爲108, 3 * 108 = 324, 將324作爲密文發送給B

B拿到密文324後, 使用324/108 = 3 得到原文

 

常見加密算法

DES : Data Encryption Standard,即數據加密標準,是一種使用密鑰加密的塊算法,1977年被美國聯邦政府的國家標準局確定爲聯邦資料處理標準(FIPS),並授權在非密級政府通信中使用,隨後該算法在國際上廣泛流傳開來。

AES : Advanced Encryption Standard, 高級加密標準 .在密碼學中又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣爲全世界所使用。

特點

  • 加密速度快, 可以加密大文件
  • 密文可逆, 一旦密鑰文件泄漏, 就會導致數據暴露
  • 加密後編碼表找不到對應字符, 出現亂碼
  • 一般結合Base64使用

 

DES加密

示例代碼 des加密算法

Cipher :文檔 https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html#getInstance-java.lang.String-

package com.atguigu.desaes;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

/**
 * DesAesDemo
 *
 * @Author: 尚硅谷
 * @CreateTime: 2020-03-17
 * @Description:
 */
public class DesAesDemo {
    public static void main(String[] args) throws Exception{
        // 原文
        String input = "硅谷";
        // des加密必須是8位
        String key = "12345678";
        // 算法
        String algorithm = "DES";

        String transformation = "DES";
        // Cipher:密碼,獲取加密對象
        // transformation:參數表示使用什麼類型加密
        Cipher cipher = Cipher.getInstance(transformation);
        // 指定祕鑰規則
        // 第一個參數表示:密鑰,key的字節數組
        // 第二個參數表示:算法
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        // 對加密進行初始化
        // 第一個參數:表示模式,有加密模式和解密模式
        // 第二個參數:表示祕鑰規則
        cipher.init(Cipher.ENCRYPT_MODE,sks);
        // 進行加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        // 打印字節,因爲ascii碼有負數,解析不出來,所以亂碼
//        for (byte b : bytes) {
//            System.out.println(b);
//        }
        // 打印密文
        System.out.println(new String(bytes));
    }
}

出現亂碼是因爲對應的字節出現負數,但負數,沒有出現在 ascii 碼錶裏面,所以出現亂碼,需要配合base64進行轉碼 

使用 base64 進行編碼

base64 導包的時候,需要注意 ,別導錯了,需要導入 apache 包

 

DES解密

package com.atguigu.desaes;

import com.sun.org.apache.xml.internal.security.utils.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class DesDemo {
    // DES加密算法,key的大小必須是8個字節

    public static void main(String[] args) throws Exception {
        String input ="硅谷";
        // DES加密算法,key的大小必須是8個字節
        String key = "12345678";

        String transformation = "DES"; // 9PQXVUIhaaQ=
        // 指定獲取密鑰的算法
        String algorithm = "DES";
        String encryptDES = encryptDES(input, key, transformation, algorithm);
        System.out.println("加密:" + encryptDES);
        String s = decryptDES(encryptDES, key, transformation, algorithm);
        System.out.println("解密:" + s);

    }

    /**
     * 使用DES加密數據
     *
     * @param input          : 原文
     * @param key            : 密鑰(DES,密鑰的長度必須是8個字節)
     * @param transformation : 獲取Cipher對象的算法
     * @param algorithm      : 獲取密鑰的算法
     * @return : 密文
      * @throws Exception
      */
    private static String encryptDES(String input, String key, String transformation, String algorithm) throws Exception {
        // 獲取加密對象
        Cipher cipher = Cipher.getInstance(transformation);
        // 創建加密規則
        // 第一個參數key的字節
        // 第二個參數表示加密算法
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        // ENCRYPT_MODE:加密模式
        // DECRYPT_MODE: 解密模式
        // 初始化加密模式和算法
        cipher.init(Cipher.ENCRYPT_MODE,sks);
        // 加密
        byte[] bytes = cipher.doFinal(input.getBytes());

        // 輸出加密後的數據
        String encode = Base64.encode(bytes);

         return encode;
     }

    /**
     * 使用DES解密
     *
     * @param input          : 密文
     * @param key            : 密鑰
     * @param transformation : 獲取Cipher對象的算法
     * @param algorithm      : 獲取密鑰的算法
     * @throws Exception
     * @return: 原文
     */
    private static String decryptDES(String input, String key, String transformation, String algorithm) throws Exception {
        // 1,獲取Cipher對象
        Cipher cipher = Cipher.getInstance(transformation);
        // 指定密鑰規則
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        cipher.init(Cipher.DECRYPT_MODE, sks);
        // 3. 解密,上面使用的base64編碼,下面直接用密文
        byte[] bytes = cipher.doFinal(Base64.decode(input));
        //  因爲是明文,所以直接返回
        return new String(bytes);
    }
}

 

Base64 算法簡介

Base64是網絡上最常見的用於傳輸8Bit字節碼的可讀性編碼算法之一
可讀性編碼算法不是爲了保護數據的安全性,而是爲了可讀性
可讀性編碼不改變信息內容,只改變信息內容的表現形式
所謂Base64,即是說在編碼過程中使用了64種字符:大寫A到Z、小寫a到z、數字0到9、“+”和“/”
Base58是Bitcoin(比特幣)中使用的一種編碼方式,主要用於產生Bitcoin的錢包地址
相比Base64,Base58不使用數字"0",字母大寫"O",字母大寫"I",和字母小寫"i",以及"+"和"/"符號

原理

base64 是 3個字節爲一組,一個字節 8位,一共 就是24位 ,然後,把3個字節轉成4組,每組6位,

3 * 8 = 4 * 6 = 24 ,每組6位,缺少的2位,會在高位進行補0 ,這樣做的好處在於 ,base取的是後面6位,去掉高2位 ,那麼base64的取值就可以控制在0-63位了,所以就叫base64,111 111 = 32 + 16 + 8 + 4 + 2 + 1 =

 

構成

① 小寫 a - z = 26個字母

② 大寫 A - Z = 26個字母

③ 數字 0 - 9 = 10 個數字

④ + / = 2個符號

大家可能發現一個問題,咱們的base64有個 = 號,但是在映射表裏面沒有發現 = 號 , 這個地方需要注意,等號非常特殊,因爲base64是三個字節一組 ,如果當我們的位數不夠的時候,會使用等號來補齊

 

base64補等號測試

package com.atguigu;

import com.sun.org.apache.xml.internal.security.utils.Base64;


public class TestBase64 {
    public static void main(String[] args) {
        //  1:MQ== 表示一個字節,不夠三個字節,所以需要後面通過 == 號補齊
        System.out.println(Base64.encode("1".getBytes()));
//        System.out.println(Base64.encode("12".getBytes()));
//        System.out.println(Base64.encode("123".getBytes()));
//        // 硅谷:中文佔6個字節,6 * 8 = 48 ,剛剛好被整除,所以沒有等號
//        System.out.println(Base64.encode("硅谷".getBytes()));
    }
}

 

AES加密解密

AES 加密解密和 DES 加密解密代碼一樣,只需要修改加密算法就行,拷貝 ESC 代碼

AES 加密的密鑰key , 需要傳入16個字節

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章