AES256加解密java語(yǔ)言實(shí)現(xiàn)

v2-6ec14833ba55ec068b0f806c6fa36b95_720w.png

寫在前面

基于項(xiàng)目安全性需要,有時(shí)候我們的項(xiàng)目會(huì)使用AES 256加解密算法。以下,是針對(duì)實(shí)現(xiàn)AES256 Padding7加密算法實(shí)現(xiàn)的關(guān)鍵步驟解析以及此過(guò)程遇到的一些問(wèn)題總結(jié)。

GitHub鏈接地址:https://github.com/zhijunhong/common_utils/tree/master/aes256

一些概念

對(duì)稱加密算法

加密和解密用到的密鑰是相同的,這種加密方式加密速度非常快,適合經(jīng)常發(fā)送數(shù)據(jù)的場(chǎng)合;缺點(diǎn)是密鑰的傳輸比較麻煩。

非對(duì)稱加密算法

加密和解密用的密鑰是不同的,這種加密方式是用數(shù)學(xué)上的難解問(wèn)題構(gòu)造的,通常加密解密的速度比較慢,適合偶爾發(fā)送數(shù)據(jù)的場(chǎng)合;優(yōu)點(diǎn)是密鑰傳輸方便。常見的非對(duì)稱加密算法為RSA、ECC和EIGamal等。

實(shí)際應(yīng)用中,一般是通過(guò)RSA加密AES的密鑰,傳輸?shù)浇邮辗剑邮辗浇饷艿玫紸ES密鑰,然后發(fā)送方和接收方用AES密鑰來(lái)通信。

關(guān)于AES 256

高級(jí)加密標(biāo)準(zhǔn)(AES,Advanced Encryption Standard)為最常見的對(duì)稱加密算法。對(duì)稱加密算法:簡(jiǎn)單來(lái)說(shuō)就是加密和解密過(guò)程中使用的秘鑰(根據(jù)一定的規(guī)則生成)是相同的。

[站外圖片上傳中...(image-eb2b46-1619076938237)]

下面簡(jiǎn)單介紹下各個(gè)部分的作用與意義:

明文P 需要加密的明文
密鑰K 用來(lái)加密明文的密碼,在對(duì)稱加密算法中,加密與解密的密鑰是相同的。密鑰為接收方與發(fā)送方協(xié)商產(chǎn)生,但不可以直接在網(wǎng)絡(luò)上傳輸,否則會(huì)導(dǎo)致密鑰泄漏,通常是通過(guò)非對(duì)稱加密算法加密密鑰,然后再通過(guò)網(wǎng)絡(luò)傳輸給對(duì)方,或者直接面對(duì)面商量密鑰。密鑰是絕對(duì)不可以泄漏的,否則會(huì)被攻擊者還原密文,竊取機(jī)密數(shù)據(jù)
AES加密算法 設(shè)AES加密函數(shù)為E,則 C = E(K, P),其中P為明文,K為密鑰,C為密文。也就是說(shuō),把明文P和密鑰K作為加密函數(shù)的參數(shù)輸入,則加密函數(shù)E會(huì)輸出密文C
密文C 經(jīng)加密函數(shù)處理后,可以在網(wǎng)絡(luò)傳輸中傳遞的密文數(shù)
AES解密算法 設(shè)AES解密函數(shù)為D,則 P = D(K, C),其中C為密文,K為密鑰,P為明文。也就是說(shuō),把密文C和密鑰K作為解密函數(shù)的參數(shù)輸入,則解密函數(shù)會(huì)輸出明文P

AES 256加解密算法實(shí)現(xiàn)

本博客重點(diǎn)講解AES 256加解密算法實(shí)現(xiàn)過(guò)程;有關(guān)AES算法原理部分,網(wǎng)上有很多相關(guān)的博客,這里不再贅述。這里要特別指出的一點(diǎn)是,AES 256中的256指的是秘鑰K的長(zhǎng)度,常見的密鑰長(zhǎng)度還有128位、192位。密鑰的長(zhǎng)度不同,推薦加密輪數(shù)也不同,如下表所示:

AES 密鑰長(zhǎng)度(32位比特字) 分組長(zhǎng)度(32位比特字) 加密輪數(shù)
AES-128 4 4 10
AES-192 6 4 12
AES-256 8 4 14

生成秘鑰

生成秘鑰的方式是需要另一端解密人員一起協(xié)定的,不同的廠商乃至不同的項(xiàng)目,生成秘鑰的方式理論上應(yīng)該都要是不同的。

這里只是為簡(jiǎn)單舉例:

使用用戶名username,密碼password隨機(jī)數(shù)random經(jīng)過(guò)MD5加密后再經(jīng)過(guò)HAS-256 hash后生成一組密鑰,具體代碼如下:

byte[] pkey = generatePkey("zhijunhong", "123456", "1111");
/**
     * 生成秘鑰
     *
     * @param username
     * @param password
     * @param random
     * @return
     * @throws NoSuchAlgorithmException
     */
    private byte[] generatePkey(String username, String password, String random) throws NoSuchAlgorithmException {
        String mD5Str = MD5Utility.getMD5DefaultEncode(username + random + password);                               //MD5加密,加密算法見github代碼
        return Sha256Utils.getSHA256ByteArray(random + mD5Str);                                                                         //經(jīng)過(guò)HAS-256 hash
    }

使用密鑰加密明文

從步驟1獲取的密鑰pkey,還需要指定向量IV,這里隨機(jī)指定IV為一組數(shù)據(jù)串,實(shí)際項(xiàng)目中,需要和解密端協(xié)定統(tǒng)一的IV向量。

 String base64EncryptStr = AESUtils.aesEncryptStr("我是明文 ", pkey, AESUtils.IV);    //密文
/**
     * @param content 加密前原內(nèi)容
     * @param iv
     * @return base64EncodeStr   aes加密完成后內(nèi)容
     * @throws
     * @Title: aesEncryptStr
     * @Description: aes對(duì)稱加密
     */
    public static String aesEncryptStr(String content, byte[] pkey, String iv) {
        byte[] aesEncrypt = aesEncrypt(content, pkey, iv);                                          //具體方法解析,見下文
        System.out.println("加密后的byte數(shù)組:" + Arrays.toString(aesEncrypt));
        String base64EncryptStr = Base64Utils.encode(aesEncrypt);
        System.out.println("加密后 base64EncodeStr:" + base64EncryptStr);
        return base64EncryptStr;
    }

對(duì)上述加密方法,進(jìn)行參數(shù)說(shuō)明:

  • content:待加密的明文
  • pkey:“生成秘鑰”步驟生成的加密秘鑰
  • iv:加密向量IV

其中,具體加密方法aesEncrypt(String content, byte[] pkey, String IV)如下:

/**
     * @param content 需要加密的原內(nèi)容
     * @param pkey    密匙
     * @param
     * @return
     */
    public static byte[] aesEncrypt(String content, byte[] pkey, String IV) {
        try {
            //SecretKey secretKey = generateKey(pkey);
            //byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec skey = new SecretKeySpec(pkey, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");// "算法/加密/填充"
            IvParameterSpec iv = new IvParameterSpec(IV.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, skey, iv);//初始化加密器
            byte[] encrypted = cipher.doFinal(content.getBytes("UTF-8"));
            return encrypted; // 加密
        } catch (Exception e) {
            Log.i(TAG,"aesEncrypt() method error:", e);
        }
        return null;
    }

最后,進(jìn)行一輪base64轉(zhuǎn)碼String base64EncryptStr = Base64Utils.encode(aesEncrypt);操作后,輸出密文字符串base64EncryptStr。

使用密鑰解密密文

秘鑰解密的過(guò)程其實(shí)就是加密的逆過(guò)程,如下:解密方法

  /**
     * @param base64EncryptStr base64處理過(guò)的字符串
     * @param pkey    密匙
     * @param
     * @return String    返回類型
     * @throws Exception
     * @throws
     * @Title: aesDecodeStr
     * @Description: 解密 失敗將返回NULL
     */
    public static String aesDecodeStr3(String base64EncryptStr, byte[] pkey, String IV) throws Exception {
        byte[] base64DecodeStr = Base64Utils.decode(base64EncryptStr);
        byte[] aesDecode = aesDecode(base64DecodeStr, pkey, IV);
        if (aesDecode == null) {
            return null;
        }
        String result;
        result = new String(aesDecode, "UTF-8");
        return result;
    }

對(duì)上述解密方法,進(jìn)行參數(shù)說(shuō)明:

  • base64EncryptStr:base64編碼過(guò)的加密密文
  • pkey:秘鑰(同加密秘鑰)
  • IV:向量

具體解密過(guò)程:先通過(guò)base64還原密文編碼,再通過(guò)aesDecode(byte[] encryptStr, byte[] pkey, String IV)方法進(jìn)行解密

其中,具體解密方法aesDecode(byte[] encryptStr, byte[] pkey, String IV),基本和加密過(guò)程相差不大,如下:

/**
     * 解密
     *
     * @param encryptStr 解密前的byte數(shù)組
     * @param pkey    密匙
     * @param IV
     * @return result  解密后的byte數(shù)組
     * @throws Exception
     */
    public static byte[] aesDecode(byte[] encryptStr, byte[] pkey, String IV) throws Exception {
        //SecretKey secretKey = generateKey(pkey);
        //byte[] enCodeFormat = secretKey.getEncoded();
        SecretKeySpec skey = new SecretKeySpec(pkey, "AES");
        IvParameterSpec iv = new IvParameterSpec(IV.getBytes("UTF-8"));
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");// 創(chuàng)建密碼器
        cipher.init(Cipher.DECRYPT_MODE, skey, iv);// 初始化解密器
        byte[] result = cipher.doFinal(encryptStr);
        return result; // 解密

    }

通過(guò)上述一系列操作后,最后將獲取的字符數(shù)組,通過(guò)new String(aesDecode, "UTF-8")操作,就可以將密文重新解密成明文"我是明文"

這里有一點(diǎn)需要特別說(shuō)明一下: 字符的編碼往往會(huì)影響加解密的結(jié)果。同一個(gè)字符被ASCII、Unicode和UTF-8編碼時(shí),字符編碼的位數(shù)都是有區(qū)別的。很多同學(xué)沒(méi)有注意這個(gè)問(wèn)題,結(jié)果會(huì)導(dǎo)致解密失敗。所以兩端在聯(lián)調(diào)加解密算法的時(shí)候,最好能約定字符編碼統(tǒng)一。

打印明文和解密出的明文日志,如下:

2021-02-24 18:05:33.651 21560-21560/com.example.aes256 I/MainActivity: encryptStr: y9COgiC06V2E1CIuhJbPfg==
2021-02-24 18:05:33.652 21560-21560/com.example.aes256 I/MainActivity: decodeStr: 我是明文 

完整代碼:https://github.com/zhijunhong/common_utils/tree/master/aes256

最后,如果這篇博文對(duì)你有所幫助,別忘了點(diǎn)個(gè)贊喲 _

參考

AES加密算法的詳細(xì)介紹與實(shí)現(xiàn)

SSL在線工具-AES在線加解密|AES在線加密 非常好用的在線驗(yàn)證AES加解密結(jié)果網(wǎng)站

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,963評(píng)論 6 542
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,348評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,083評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,706評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,442評(píng)論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,802評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,795評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,983評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,542評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,287評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,486評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,030評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,710評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,116評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,412評(píng)論 1 294
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,224評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,462評(píng)論 2 378

推薦閱讀更多精彩內(nèi)容