Java實現(xiàn)AES ECP PKCS5Padding加解密工具類

Java 實現(xiàn)一個AES/ECB/PKCS5Padding 加解密算法工具類

  • 加密算法: AES
  • 模式: ECB
  • 補碼方式: PKCS5Padding

1. 工具類

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;

/**
 * Created by @author yihui in 19:12 20/1/2.
 */
@Slf4j
public class EncryptUtil {
    private static final String KEY_ALGORITHM = "AES";
    /**
     * 算法/模式/補碼方式
     */
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
    private static final String CODE = "utf-8";

    @Setter
    @Getter
    public static String encryptKey;

    public static String encrypt(String content) {
        return encrypt(content, encryptKey);
    }

    /**
     * 加密
     *
     * @param content
     * @param key
     * @return
     * @throws Exception
     */
    public static String encrypt(String content, String key) {
        try {
            byte[] encrypted = encrypt2bytes(content, key);
            return Base64Utils.encodeToString(encrypted);
        } catch (Exception e) {
            log.error("failed to encrypt: {} of {}", content, e);
            return null;
        }
    }

    public static byte[] encrypt2bytes(String content, String key) {
        try {
            byte[] raw = key.getBytes(CODE);
            SecretKeySpec secretKeySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            return cipher.doFinal(content.getBytes(CODE));
        } catch (Exception e) {
            log.error("failed to encrypt: {} of {}", content, e);
            return null;
        }
    }

    public static String decrypt(String content) {
        try {
            return decrypt(content, encryptKey);
        } catch (Exception e) {
            log.error("failed to decrypt: {}, e: {}", content, e);
            return null;
        }
    }

    /**
     * 解密
     *
     * @param content
     * @param key
     * @return
     * @throws Exception
     */
    public static String decrypt(String content, String key) throws Exception {
        return decrypt(Base64Utils.decodeFromString(content), key);
    }

    public static String decrypt(byte[] content, String key) throws Exception {
        if (key == null) {
            log.error("AES key should not be null");
            return null;
        }

        byte[] raw = key.getBytes(CODE);
        SecretKeySpec keySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
        Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        try {
            byte[] original = cipher.doFinal(content);
            return new String(original, CqODE);
        } catch (Exception e) {
            log.error("failed to decrypt content: {}/ key: {}, e: {}", content, key, e);
            return null;
        }
    }
}

請注意上面的實現(xiàn),提供了兩種方式

  • 一個是AES加密之后使用base64編碼輸出,對應的是解密base64編碼的數(shù)據(jù)
  • 一個是AES加密之后筏勒,直接返回字節(jié)數(shù)組偿渡;也是直接解碼字節(jié)數(shù)組

2. 測試case

我們提供了兩個加密的文件牵寺,用于解密使用绰更;

base64加解密

@Test
public void testEncrypt() throws Exception {
    String abc = "Hello, 一灰灰Blog!";
    String key = "JC66fRd3wj85k8Hr";
    String out = EncryptUtil.encrypt(abc, key);
    System.out.println(out);

    System.out.println(EncryptUtil.decrypt(out, key));
}

輸出結(jié)果如:

TKrN7VKrqsAQ4JqygeHOlG21Sd3IRJ3Y11k4kOdOG4s=
Hello, 一灰灰Blog!

字節(jié)數(shù)組加解密

@Test
public void testEncryptByte() throws Exception {
    String abc = "Hello, 一灰灰Blog!";
    String key = "JC66fRd3wj85k8Hr";
    byte[] out = EncryptUtil.encrypt2bytes(abc, key);
    System.out.println(new String(out));

    System.out.println(EncryptUtil.decrypt(out, key));
}

輸出結(jié)果如:

// 加密的字節(jié)數(shù)組惰帽,就是亂碼... 你沒看錯
L???R?????????Δm?I??D???Y8??N??
Hello, 一灰灰Blog!

為什么有上面兩種區(qū)別?

如果我們將加密后的字節(jié)數(shù)組与殃,直接 new String() 獲得一個字符串,然后解密這個字符串碍现,會發(fā)現(xiàn)解密失敗哦

簡單修改一下上面的測試用例

@Test
public void testEncryptByte() throws Exception {
    String abc = "Hello, 一灰灰Blog!";
    String key = "JC66fRd3wj85k8Hr";
    byte[] out = EncryptUtil.encrypt2bytes(abc, key);
    String enc = new String(out, "utf-8");
    System.out.println(enc);

    System.out.println(EncryptUtil.decrypt(enc.getBytes("utf-8"), key));
}

執(zhí)行之后幅疼,發(fā)現(xiàn)解密失敗

image

為啥會出現(xiàn)這樣情況呢?

  • enc = new String(out, "utf-8")enc.getBytes("utf-8") 字節(jié)數(shù)組轉(zhuǎn)字符串昼接; 字符串轉(zhuǎn)字節(jié)數(shù)組這兩個過程會導致最終生成的字節(jié)數(shù)組爽篷,與原始的不一致!!!

解密遠程資源的case

最后給一個解密遠程加密的二進制文件的實例case

private void binKey(String uri, String key) throws Exception {
    // 這個文件是沒有base64編碼,直接上傳的二進制
    URL url = new URL(uri);
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    InputStream stream = connection.getInputStream();
    int lenth = connection.getContentLength();
    byte[] out = new byte[lenth];
    stream.read(out);
    stream.close();
    String ans = decrypt(out, key);
    System.out.println(ans);
}

public void testDe() throws Exception {
    String key = "5JRHMJn8xHnMDRXa";
    binKey("http://q8rnsprw0.bkt.clouddn.com/mwzz/b0001", key);
}

II. 其他

1. 一灰灰Bloghttps://liuyueyi.github.io/hexblog

一灰灰的個人博客慢睡,記錄所有學習和工作中的博文逐工,歡迎大家前去逛逛

2. 聲明

盡信書則不如,以上內(nèi)容漂辐,純屬一家之言泪喊,因個人能力有限,難免有疏漏和錯誤之處髓涯,如發(fā)現(xiàn)bug或者有更好的建議袒啼,歡迎批評指正,不吝感激

3. 掃描關注

一灰灰blog

QrCode
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蚓再,隨后出現(xiàn)的幾起案子滑肉,更是在濱河造成了極大的恐慌,老刑警劉巖摘仅,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件靶庙,死亡現(xiàn)場離奇詭異,居然都是意外死亡实檀,警方通過查閱死者的電腦和手機惶洲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來膳犹,“玉大人恬吕,你說我怎么就攤上這事⌒氪玻” “怎么了铐料?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長豺旬。 經(jīng)常有香客問我钠惩,道長,這世上最難降的妖魔是什么族阅? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任篓跛,我火速辦了婚禮,結(jié)果婚禮上坦刀,老公的妹妹穿的比我還像新娘愧沟。我一直安慰自己,他們只是感情好鲤遥,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布沐寺。 她就那樣靜靜地躺著,像睡著了一般盖奈。 火紅的嫁衣襯著肌膚如雪混坞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天钢坦,我揣著相機與錄音究孕,去河邊找鬼。 笑死爹凹,一個胖子當著我的面吹牛蚊俺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逛万,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼泳猬,長吁一口氣:“原來是場噩夢啊……” “哼批钠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起得封,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤埋心,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后忙上,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拷呆,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年疫粥,在試婚紗的時候發(fā)現(xiàn)自己被綠了茬斧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡梗逮,死狀恐怖项秉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情慷彤,我是刑警寧澤娄蔼,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站底哗,受9級特大地震影響岁诉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜跋选,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一涕癣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧前标,春花似錦坠韩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绽昼。三九已至唯鸭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間硅确,已是汗流浹背目溉。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留菱农,地道東北人缭付。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像循未,于是被迫代替她去往敵國和親陷猫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354