1. 程式人生 > >java中常用的對稱加密演算法

java中常用的對稱加密演算法

一 常用的對稱加密演算法

對稱加密演算法簡單來講就是加密和解密使用同一個金鑰,並且加密解密互為逆運算,如加法和減法,先加密再解密 與先解密後加密都能得到原結果,常用的加密演算法有DES;3DES(二倍長,三倍長);AES;

3DES是DES擴充套件,3DES使用DES轉換:
3DES 2倍長金鑰長度16個位元組,使用前八個位元組對資料des加密,後八個位元組對資料des解密,再用前八個位元組對資料des加密
3DES 3倍長金鑰長度24個位元組,使用前八個位元組對資料des加密,中間八個位元組對資料des解密,再用後八個位元組對資料des加密
演算法具體實現推薦文章:
DES演算法簡介


AES演算法簡介

1>分組模式與填充

1:分組模式

<1>ECB模式:
這裡寫圖片描述

對資料按照block長度(des,3DES為8個位元組,AES16位元組)分成多組b1,b2……bn(不足按設定的填充模式填充),再用金鑰對每組分別加密

<2>CBC模式:
這裡寫圖片描述

對資料按照block長度(des,3DES為8個位元組,AES 16位元組)分成多組b1,b2……bn(不足按設定的填充模式填充),用給定IV向量與第一組異或運算,對異或結果加密生成密文塊1,再用密文塊與第二明文塊異或運算對異或結果加密生成密文塊2,以此類推

兩種分組模式比較:
1》ECB模式速度比CBC模式塊。—>ECB不用等上一個塊的計算結果,可以多執行緒計算
2》ECB模式不會傳遞誤差。—>一組計算錯誤不會影響其他組
3》ECB模式容易被攻擊。—>每組加密因子一樣,加密例項多,易被破解

2: 填充

<1>NoPadding:
資料不填充,需要滿足條件(n*block)
<2>PKCS5Padding:

如:des/3des block 長度為8個位元組
資料長度為8n末尾填充808
資料長度為8n+m(0<m<8)末尾填充8-m個8-m 如:0102030405060708 09 --->0102030405060708 0907070707070707

<3>ISO10126Padding

如:aes block 長度為16個位元組
資料長度為16n末尾填充15個隨機位元組和一個長度1016進位制10十進位16)
資料長度為16n+m(0<m<16
)末尾填充16-m個位元組,16-m-1個隨機位元組和一個長度位元組 如:0102030405060708 0910 --->0102030405060708 0910+ 5個隨機位元組+06

JCE中AES支援五中模式:CBC,CFB,ECB,OFB,PCBC;支援三種填充:NoPadding,PKCS5Padding,ISO10126Padding。不支援SSL3Padding。不支援“NONE”模式。

2>具體實現與應用

     /**
     * 對稱加密解密
     *
     * @param alg    演算法
     *               "DES/ECB/NoPadding" "DES/ECB/PKCS5Padding" "DES/CBC/NoPadding" "DES/CBC/NoPadding"
     *               "DESede/ECB/NoPadding" "DESede/ECB/PKCS5Padding" "DESede/CBC/PKCS5Padding"  "DESede/CBC/PKCS5Padding"
     *               "AES/ECB/NOPADDING" "AES/ECB/PKCS5Padding" "AES/CBC/NOPADDING" "AES/CBC/PKCS5Padding"
     *               "AES/ECB/ISO10126Padding"
     * @param key    金鑰 長度需要按照對應加密演算法
     * @param opMode 模式,加密還是解密 {@link  Cipher#ENCRYPT_MODE }{@link Cipher#DECRYPT_MODE}
     * @param data   待加密的資料
     * @param iv     CBC模式向量
     * @return 加密後的資料
     */
    public static byte[] SymmetricAlg(String alg, byte[] key, int opMode, byte[] data, byte[] iv) throws Exception {
        IvParameterSpec ivParameterSpec = null;
        if (iv != null && iv.length != 0) {
            ivParameterSpec = new IvParameterSpec(iv);
        }
        SecretKey secretKey = new SecretKeySpec(key, alg);
        Cipher cipher = Cipher.getInstance(alg);
        cipher.init(opMode, secretKey, ivParameterSpec);
        return cipher.doFinal(data);
    }

alg 上面的不全還有其他的分組模式和填充

注意點:
1》加密解密需要對應的分組模式和填充要一致
2》alg 傳 “des”等不傳分組模式和填充時都有一個預設值,不同平臺預設值可能不同,最好是顯示傳引數
3》金鑰長度問題:des 的金鑰長度為8位元組;DESede(3des) 的金鑰長度為16個位元組或者24個位元組(2倍長或者3倍長);AES的金鑰長度為16個位元組,24個位元組或者32個位元組都可以(AES-128,AES-192或者AE-256)
4》資料長度 NoPadding時,des/3des 為8n,aes 為16n

二 字元編碼

1>常用的字元編碼有Unicode、ASCII、GBK、GB2312、UTF-8 還有一個特殊的編碼 base64 ,區別 如UTF-8等編碼都是與字符集對應的,如果不在編碼表內就會亂碼,而Base64編碼是從二進位制到字元的過程,還都是可列印字元,不會出現亂碼,所以常在加密後使用Base64處理顯示文字,還有一種是直接顯示對應位元組陣列的16進位制字串

2>加密和base64

        String test = "對稱加密AES";
        byte[] input = test.getBytes("utf-8");
        byte[] key = BytesUtils.hexStr2Bytes("111111111111111111111111111222221111111111122222");
        byte[] result = SymmetricAlg("AES/ECB/PKCS5Padding", key, Cipher.ENCRYPT_MODE, input, null);
        String base64Out = Base64.encodeToString(result, Base64.DEFAULT);
        Log.e(TAG, "base64:" + base64Out);
        input = Base64.decode(base64Out, Base64.DEFAULT);
        result = SymmetricEncryptionAlgUtils.SymmetricAlg("AES/ECB/PKCS5Padding", key, Cipher.DECRYPT_MODE, input, null);
        Log.e(TAG, "base64:" + new String(result, "utf-8"));

列印結果:
base64:gMb8YHWx8mfaAKYzvkROEA==
原資料:對稱加密AES

3>加密和顯示16進位制字串

        String test = "對稱加密AES";
        byte[] input = test.getBytes("utf-8");
        byte[] key = BytesUtils.hexStr2Bytes("111111111111111111111111111222221111111111122222");
        byte[] result = SymmetricAlg("AES/ECB/PKCS5Padding", key, Cipher.ENCRYPT_MODE, input, null);
        String hexOut = BytesUtils.byte2HexStr(result);
        Log.e(TAG, "hex:" + hexOut);
        input = BytesUtils.hexStr2Bytes(hexOut);
        result = SymmetricEncryptionAlgUtils.SymmetricAlg("AES/ECB/PKCS5Padding", key, Cipher.DECRYPT_MODE, input, null);
        Log.e(TAG, "原資料:" + new String(result, "utf-8"));

列印結果:
hex:80C6FC6075B1F267DA00A633BE444E10
原資料:對稱加密AES

4>對金鑰的處理
上面金鑰都是二進位制的不利於記憶,一般處理是對字串金鑰做摘要(md5)當做計算金鑰

        String keyStr = "我的金鑰";
        String test = "對稱加密AES";
        byte[] input = test.getBytes("utf-8");
        byte[] key = MessageDigestUtils.MD5(keyStr.getBytes());
        byte[] result = SymmetricAlg("AES/ECB/PKCS5Padding", key, Cipher.ENCRYPT_MODE, input, null);
        String base64Out = Base64.encodeToString(result, Base64.DEFAULT);
        Log.e(TAG, "base64:" + base64Out);
        input = Base64.decode(base64Out, Base64.DEFAULT);
        result = SymmetricEncryptionAlgUtils.SymmetricAlg("AES/ECB/PKCS5Padding", key, Cipher.DECRYPT_MODE, input, null);
        Log.e(TAG, "原資料:" + new String(result, "utf-8"));
    }

列印結果:
base64:cfnxIg2ngoORziek5SX/kA==
原資料:對稱加密AES

BytesUtils 工具類將16進位制字串裝換成對應位元組陣列,和位元組陣列轉化成對應16進位制字串

public class BytesUtils {
    /**
     * 位元組陣列轉換成十六進位制大寫字串
     *
     * @param b
     * @return
     */
    public static String byte2HexStr(byte[] b) {
        StringBuilder hexSb = new StringBuilder();
        String stmp = "";
        int len = b.length;
        for (int n = 0; n < len; n++) {
            stmp = (Integer.toHexString(b[n] & 0xFF));
            if (stmp.length() == 1)
                hexSb.append("0" + stmp);
            else
                hexSb.append(stmp);
        }
        return hexSb.toString().toUpperCase();
    }

    /**
     * 十六進位制字串轉換成位元組陣列
     *
     * @param hexStr
     * @return
     */
    public static byte[] hexStr2Bytes(String hexStr) {
        int len = hexStr.length();
        if (len % 2 != 0) {
            throw new RuntimeException("十六進位制字串長度不對");
        }
        byte[] b = new byte[hexStr.length() / 2];
        int bLen = b.length;
        int j = 0;
        for (int i = 0; i < bLen; i++) {
            char c0 = hexStr.charAt(j++);
            char c1 = hexStr.charAt(j++);
            b[i] = (byte) ((parse(c0) << 4) | parse(c1));
        }
        return b;
    }
    /**
     * 十六進位制字串轉換成位元組陣列
     *
     * @param hexStr
     * @return
     */
    public static byte[] hexStr2Bytes1(String hexStr) {
        int len = hexStr.length();
        if (len % 2 != 0) {
            throw new RuntimeException("十六進位制字串長度不對");
        }
        byte[] b = new byte[hexStr.length() / 2];
        int bLen = b.length;
        int j = 0;
        String tem="";
        for (int i = 0; i < bLen; i++) {
            tem=hexStr.substring(2*i,2*i+2);
            b[i]= (byte) Integer.parseInt(tem,16);
        }
        return b;
    }
    private static int parse(char c) {
        if (c >= 'a')
            return (c - 'a' + 10) & 0x0f;
        if (c >= 'A')
            return (c - 'A' + 10) & 0x0f;
        return (c - '0') & 0x0f;
    }

}

三 總結

金鑰:自己生成,與伺服器協商,對使用者輸入密碼做摘要(md5),需要注意長度
加密演算法:選取其中一種加密演算法,分組模式和填充 (具體選擇看需求)
需要加密資料:獲取對應加密資料的編碼,需要注意長度,加密的分組模式和填充
加密後的資料顯示:base64編碼顯示和16進位制顯示
解密回原資料:將加密後顯示的資料轉換成對應加祕資料,對加密後資料解密(注意分組和填充模式),解密後轉換成原來編碼資料(注意編碼字符集)

相關推薦

Java常用對稱加密演算法-DES

直接上程式碼import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import java.security.SecureRandom; impo

Java常用對稱加密演算法-AES

import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import java.security.SecureRandom; import jav

Java常用加密算法小結

單向 安全 加密算法 對稱 digest iges 公鑰加密 非對稱加密 algorithm 散列算法(單向散列,不可逆) MD5(Message Digest Algorithm 5) SHA(Secure Hash Algorithm) 對稱加密(加密解密

Java常用的排序演算法(動態演示)

1.前言 這篇文章講解的是Java中或者面試中常用的**排序演算法**。 文章中例項  [linhaojian的Github](https://github.com/linhaojian 2.複雜度 相關概率

關於JAVA一些簡單加密演算法的思考

import java.util.Scanner; public class JiaMiDemo { public static void main(String[] args){

Java的各種加密演算法

                   JAVA中為我們提供了豐富的加密技術,可以基本的分為單向加密和非對稱

Java常用加密與解密方法

加密,是以某種特殊的演算法改變原有的資訊資料,使得未授權的使用者即使獲得了已加密的資訊,但因不知解密的方法,仍然無法瞭解資訊的內容。大體上分為雙向加密和單向加密,而雙向加密又分為對稱加密和非對稱加密(有些資料將加密直接分為對稱加密和非對稱加密)。 雙向加密大體意思就是明文加

常用對稱加密演算法(DES/AES)類(PHP)

看註釋,啥也不說了,歡迎各種跨平臺測試! /** * 常用對稱加密演算法類 * 支援金鑰:64/128/256 bit(位元組長度8/16/32) * 支援演算法:DES/AES(根據金鑰長度自動匹配使用:DES:64bit AES:128/256bit) * 支

開發常用加密演算法大全初步總結

   為什麼要使用加密演算法:在開發的過程中,為了能夠保證程式能夠安全高效執行,資料資訊不被洩露,我們通常都會對要操作的資料就行加解密,從而提高程式的安全性。比如常見的客戶端和後臺伺服器的資料互動傳輸,

Java常用加密與解密方法《轉載》

加密,是以某種特殊的演算法改變原有的資訊資料,使得未授權的使用者即使獲得了已加密的資訊,但因不知解密的方法,仍然無法瞭解資訊的內容。大體上分為雙向加密和單向加密,而雙向加密又分為對稱加密和非對稱加密(有些資料將加密直接分為對稱加密和非對稱加密)。 雙向加密大體意思就是明文加密

Java常用的查詢演算法——順序查詢和二分查詢

import java.util.Scanner; /* * 順序查詢 */ public class SequelSearch { public static void main(String[] arg) { int[] a={4,6,2,8,1,9,0,3}; Scann

Java常用加密方式

加密,是以某種特殊的演算法改變原有的資訊資料,使得未授權的使用者即使獲得了已加密的資訊,但因不知解密的方法,仍然無法瞭解資訊的內容。 加密大體上分為雙向加密和單向加密,雙向加密又分為對稱加密和非對稱加密 ------------------------------

C#開發常用加密演算法總結

相信很多人在開發過程中經常會遇到需要對一些重要的資訊進行加密處理,今天給大家分享我個人總結的一些加密演算法: 常見的加密方式分為可逆和不可逆兩種方式     可逆:RSA,AES,DES等     不可逆:常見的MD5,SH

java常用對稱加密演算法

一 常用的對稱加密演算法 對稱加密演算法簡單來講就是加密和解密使用同一個金鑰,並且加密解密互為逆運算,如加法和減法,先加密再解密 與先解密後加密都能得到原結果,常用的加密演算法有DES;3DES(二倍長,三倍長);AES; 3DES是DES擴充套件,3D

JAVA 常用加密演算法對稱加密DES、3DES和AES

1、對稱加密演算法 1.1 定義 對稱加密演算法是應用較早的加密演算法,技術成熟。在對稱加密演算法中,資料發信方將明文(原始資料)和加密金鑰一起經過特殊加密演算法處理後,使其變成複雜的加密密文傳送出去。收信方收到密文後,若想解讀原文,則需要使用加密用過的金鑰

DES/3DES/AES 三種對稱加密演算法Java 的實現

有兩句話是這麼說的:1)演算法和資料結構就是程式設計的一個重要部分,你若失掉了演算法和資料結構,你就把一切都失掉了。2)程式設計就是演算法和資料結構,演算法和資料結構是程式設計的靈魂。注意,這可不是我說的,是無數程式設計師總結的,話說的很實在也很精闢,若想長久可持續發展,多研

RSA非對稱加密演算法(表單提交時,前端js加密,後端java解密)

RSA非對稱加密演算法(表單提交時,前端js加密,後端java解密 非對稱加密演算法 需要的工具 前端jsp頁面 js程式碼 加密解密的工具類 產生公鑰的類 處理登陸請求的類 加密成功的密碼 非對稱加密演算

對稱加密演算法常用的五種分組模式(ECB/CBC/CFB/OFB/CTR)

版權宣告:本文為作者原創,如需轉載,請註明出處 https://blog.csdn.net/weixin_42940826 注:以下圖片來自於《圖解密碼學》,這本書講的更全面細緻,建議閱讀,在我資源庫中有此書,還有使用go語言具體實現和解釋此書中的各種加密演算法的文件,有需要的可以自

JAVA密碼加密演算法.RSA演算法(非對稱加密演算法)和密碼加鹽MD5

密碼加鹽MD5 Message Digest Algorithm MD5(中文名為訊息摘要演算法第五版)為電腦保安領域廣泛使用的一種雜湊函式,用以提供訊息的完整性保護。 是計算機廣泛使用的雜湊演算法之一(又譯摘要演算法、雜湊演算法),主流程式語言普遍已有MD5實現。將資料(如漢字)運

Java對稱加密演算法RSA

流程分析:  甲方構建金鑰對兒,將公鑰公佈給乙方,將私鑰保留。 甲方使用私鑰加密資料,然後用私鑰對加密後的資料簽名,傳送給乙方簽名以及加密後的資料;乙方使用公鑰、簽名來驗證待解密資料是否有效,如果有效使用公鑰對資料解密。 乙方使用公鑰加密資料,向甲方傳送經過加密後的資料