AES加密筆記——Windows&Linux

最近由于業(yè)務(wù)需求郎嫁,需要給Kafka內(nèi)的報(bào)文進(jìn)行加密。Kafka的上游與下游都是我們自己的系統(tǒng)统台,分析過業(yè)務(wù)場(chǎng)景后奄容,決定使用對(duì)稱加密算法冰更。

對(duì)稱加密算法

對(duì)稱加密(也叫私鑰加密)指加密和解密使用相同密鑰的加密算法。在大多數(shù)的對(duì)稱算法中嫩海,加密密鑰和解密密鑰是相同的冬殃,所以也稱這種加密算法為秘密密鑰算法或單密鑰算法。

優(yōu)點(diǎn):對(duì)稱加密算法的特點(diǎn)是算法公開叁怪、計(jì)算量小审葬、加密速度快、加密效率高奕谭。

缺點(diǎn):交易雙方都使用同樣鑰匙涣觉,安全性得不到保證。每對(duì)用戶每次使用對(duì)稱加密算法時(shí)血柳,都需要使用其他人不知道的惟一鑰匙官册,這會(huì)使得發(fā)收信雙方所擁有的鑰匙數(shù)量呈幾何級(jí)數(shù)增長,密鑰管理成為用戶的負(fù)擔(dān)难捌。對(duì)稱加密算法在分布式網(wǎng)絡(luò)系統(tǒng)上使用較為困難膝宁,主要是因?yàn)槊荑€管理困難鸦难,使用成本較高。

非對(duì)稱加密算法

非對(duì)稱加密算法需要兩個(gè)密鑰:公開密鑰(publickey:簡稱公鑰)和私有密鑰(privatekey:簡稱私鑰)员淫。公鑰與私鑰是一對(duì)合蔽,如果用公鑰對(duì)數(shù)據(jù)進(jìn)行加密,只有用對(duì)應(yīng)的私鑰才能解密介返。

優(yōu)點(diǎn):算法強(qiáng)度復(fù)雜拴事、安全性強(qiáng)。相比于對(duì)稱秘鑰只有一個(gè)秘鑰而言圣蝎,非對(duì)稱密鑰體制有兩種密鑰刃宵,其中一個(gè)是公開的,這樣就可以不需要像對(duì)稱密碼那樣傳輸對(duì)方的密鑰了徘公。這樣安全性就大了很多牲证。

缺點(diǎn):但是由于其算法復(fù)雜,而使得加密解密速度沒有對(duì)稱加密解密的速度快步淹。

什么是AES从隆?

AES算是比較基礎(chǔ)的對(duì)稱加密算法诚撵,原理簡單缭裆。

高級(jí)加密標(biāo)準(zhǔn)(AES,Advanced Encryption Standard)為最常見的對(duì)稱加密算法,AES最常見的有3種方案寿烟,分別是AES-128澈驼、AES-192和AES-256,它們的區(qū)別在于密鑰長度不同筛武,AES-128的密鑰長度為16bytes(128bit/8)缝其,后兩者分別為24bytes和32bytes。密鑰越長徘六,安全強(qiáng)度越高内边,但伴隨運(yùn)算輪數(shù)的增加,帶來的運(yùn)算開銷就會(huì)更大待锈。

AES算法在加密過程中分為四步:

  • 字節(jié)代換
  • 行移位
  • 列混合
  • 輪密鑰加

字節(jié)代換

AES的字節(jié)代換其實(shí)就是一個(gè)簡單的查表操作漠其。AES定義了一個(gè)S盒和一個(gè)逆S盒。

行移位

行移位是一個(gè)簡單的左循環(huán)移位操作竿音。當(dāng)密鑰長度為128比特時(shí)和屎,狀態(tài)矩陣的第0行左移0字節(jié),第1行左移1字節(jié)春瞬,第2行左移2字節(jié)柴信,第3行左移3字節(jié)。

列混合

列混合變換是通過矩陣相乘來實(shí)現(xiàn)的宽气,經(jīng)行移位后的狀態(tài)矩陣與固定的矩陣相乘随常,得到混淆后的狀態(tài)矩陣潜沦。

輪密鑰加

輪密鑰加是將128位輪密鑰同狀態(tài)矩陣中的數(shù)據(jù)進(jìn)行逐位異或操作。

AES128具體實(shí)現(xiàn)

Windows上的首次嘗試

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class Encrypt1 {
    private final String password;
    private final KeyGenerator kgen;
    private final SecretKey secretKey;
    private final byte[] enCodeFormat;
    private final SecretKeySpec key;
    private Cipher cipher;

    public Encrypt1(String password) throws NoSuchAlgorithmException, NoSuchPaddingException {
        this.password = password;

        kgen = KeyGenerator.getInstance("AES");

        kgen.init(128, new SecureRandom(password.getBytes()));

        secretKey = kgen.generateKey();

        enCodeFormat = secretKey.getEncoded();

        key = new SecretKeySpec(enCodeFormat, "AES");

        cipher = Cipher.getInstance("AES");

    }
    /**
     * AES加密字符串
     *
     * @param content 加密內(nèi)容
     *
     * @return 密文
     */
    public byte[] encrypt(String content) {
        try {
            byte[] byteContent = content.getBytes("utf-8");

            cipher.init(Cipher.ENCRYPT_MODE, key);

            byte[] result = cipher.doFinal(byteContent);

            return result;

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密AES加密過的字符串
     *
     * @param content 解密密文
     *
     * @return 明文
     */
    public byte[] decrypt(byte[] content) {
        try {
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] result = cipher.doFinal(content);
            return result; 

        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static void main(String[] args) {

        String content = "麻溜地?cái)]個(gè)加密程序";
        String password = "123456";
        Encrypt1 e1, e2;

        try {
            e1 = new Encrypt1(password);
            e2 = new Encrypt1(password);

            System.out.println("加密之前:" + content);

            // 加密
            byte[] encrypt = e1.encrypt(content);
            System.out.println("加密后的內(nèi)容:" + new String(encrypt));

            // 解密
            byte[] decrypt = e2.decrypt(encrypt);
            System.out.println("解密后的內(nèi)容:" + new String(decrypt));

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
    }
}

最初我在Windows上的電腦測(cè)試這段代碼時(shí)還很好用绪氛。但是當(dāng)我將相關(guān)代碼部署到Linux服務(wù)器上時(shí)止潮,解密出現(xiàn)了問題,在解密時(shí)拋出異常钞楼。類似下圖:


解密報(bào)錯(cuò).png

報(bào)錯(cuò)指明是由于錯(cuò)誤的秘鑰導(dǎo)致喇闸,但是經(jīng)過詳細(xì)比較,我在加密和解密時(shí)的秘鑰都是采用同一個(gè)询件,不可能是由于使用秘鑰不同導(dǎo)致燃乍。由于業(yè)務(wù)流程上是Windows系統(tǒng)上的程序充當(dāng)Producer對(duì)報(bào)文進(jìn)行加密然后插入Kafka消息隊(duì)列,Linux上的程序作為Consumer進(jìn)行消費(fèi)并對(duì)之前的密文解密宛琅。第一直覺誤認(rèn)為在進(jìn)行插入過程中byte數(shù)組產(chǎn)生了問題刻蟹,于是Producer改進(jìn)為轉(zhuǎn)為16進(jìn)制進(jìn)行插入,在Consumer進(jìn)行消費(fèi)時(shí)進(jìn)行檢查嘿辟。非常奇妙的是舆瘪,消費(fèi)者拿到的加密報(bào)文與生產(chǎn)者產(chǎn)生的報(bào)文完完全全相同,而且將消費(fèi)者拿到的報(bào)文復(fù)制到最初測(cè)試的程序中红伦,可以正常解密英古。于是可以大致斷定為是環(huán)境導(dǎo)致的解密失敗。為了確認(rèn)我用相同字符串在Windows和Linux環(huán)境下用相同秘鑰進(jìn)行了加密昙读,對(duì)比加密后的字符串召调。根據(jù)AES加密算法的原理,如果使用相同秘鑰蛮浑,同一個(gè)字符串加密后的密文應(yīng)該是相同的唠叛。但是在上述不同操作系統(tǒng)之間,加密后的內(nèi)容是不同的沮稚。

錯(cuò)誤原因分析:

SecureRandom 實(shí)現(xiàn)隨操作系統(tǒng)本身的內(nèi)部狀態(tài)不同而不同艺沼,除非調(diào)用方在調(diào)用 getInstance 方法之后又調(diào)用了 setSeed 方法;該實(shí)現(xiàn)在 windows 上每次生成的 key 都相同蕴掏,但是在 solaris 或部分 linux 系統(tǒng)上則不同障般。
真相大白后我們進(jìn)行Linux版本修正。

Linux版本的AES128實(shí)現(xiàn)

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class Encrypt2 {
    private final String password;
    private final KeyGenerator kgen;
    private final SecretKey secretKey;
    private final byte[] enCodeFormat;
    private final SecretKeySpec key;
    private final Cipher cipher;
    private final SecureRandom secureRandom;


    public Encrypt2(String password) throws NoSuchAlgorithmException, NoSuchPaddingException {
        this.password = password;

        kgen = KeyGenerator.getInstance("AES");

        secureRandom = SecureRandom.getInstance("SHA1PRNG");

        secureRandom.setSeed(password.getBytes());

        kgen.init(128, secureRandom);

        secretKey = kgen.generateKey();

        enCodeFormat = secretKey.getEncoded();

        key = new SecretKeySpec(enCodeFormat, "AES");

        cipher = Cipher.getInstance("AES");

    }
    /**
     * AES加密字符串
     *
     * @param content 加密內(nèi)容
     *
     * @return 密文
     */
    public byte[] encrypt(String content) {
        try {
            byte[] byteContent = content.getBytes("utf-8");

            cipher.init(Cipher.ENCRYPT_MODE, key);

            byte[] result = cipher.doFinal(byteContent);

            return result;

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密AES加密過的字符串
     *
     * @param content 解密密文
     *
     * @return 明文
     */
    public byte[] decrypt(byte[] content) {
        try {
            cipher.init(Cipher.DECRYPT_MODE, key);// 初始化為解密模式的密碼器
            byte[] result = cipher.doFinal(content);
            return result; // 明文

        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static void main(String[] args) {

        String content = "麻溜地?cái)]個(gè)加密程序";
        String password = "123456";
        Encrypt2 e1, e2;

        try {
            e1 = new Encrypt2(password);
            e2 = new Encrypt2(password);

            System.out.println("加密之前:" + content);

            // 加密
            byte[] encrypt = e1.encrypt(content);
            System.out.println("加密后的內(nèi)容:" + new String(encrypt));

            // 解密
            byte[] decrypt = e2.decrypt(encrypt);
            System.out.println("解密后的內(nèi)容:" + new String(decrypt));

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
    }
}

經(jīng)過測(cè)試囚似,此加密工具在Windows和Linux系統(tǒng)中均表現(xiàn)良好剩拢。對(duì)于多系統(tǒng)串行加密解密也沒有問題。

多線程進(jìn)行加密解密試驗(yàn)

簡單地對(duì)報(bào)文進(jìn)行加密解密是不能滿足實(shí)際情況的饶唤,該方法是否線程安全是個(gè)還需要確定的事情徐伐。對(duì)多線程進(jìn)行了如下測(cè)試。加密解密方法不變募狂,測(cè)試方法如下:

    public static void main(String[] args) {

        String content1 = "麻溜地?cái)]個(gè)加密程序";
        String content2 = "茍利國家生死以";
        String content3 = "豈因福禍避趨之";
        String password = "123456";
        Encrypt3 e1, e2;

        try {
            e1 = new Encrypt3(password);
            e2 = new Encrypt3(password);
            Thread thread1, thread2, thread3;

            thread1 = new Thread(() -> {
                int i = 0;
                while (true) {
                    System.out.println("線程1加密之前:" + content1 + i);

                    // 加密
                    byte[] encrypt = e1.encrypt(content1 + i++);
                    System.out.println("線程1加密后的內(nèi)容:" + new String(encrypt));

                    // 解密
                    byte[] decrypt = e1.decrypt(encrypt);
                    System.out.println("線程1解密后的內(nèi)容:" + new String(decrypt));
                }
            });

            thread1.start();

            thread2 = new Thread(() -> {
                int i = 0;
                while (true) {
                    System.out.println("線程2加密之前:" + content2 + i);

                    // 加密
                    byte[] encrypt = e1.encrypt(content2 + i++);
                    System.out.println("線程2加密后的內(nèi)容:" + new String(encrypt));

                    // 解密
                    byte[] decrypt = e1.decrypt(encrypt);
                    System.out.println("線程2解密后的內(nèi)容:" + new String(decrypt));
                }
            });

            thread2.start();

            thread3 = new Thread(() -> {
                int i = 0;
                while (true) {
                    System.out.println("線程3加密之前:" + content3 + i);

                    // 加密
                    byte[] encrypt = e1.encrypt(content3 + i++);
                    System.out.println("線程3加密后的內(nèi)容:" + new String(encrypt));

                    // 解密
                    byte[] decrypt = e1.decrypt(encrypt);
                    System.out.println("線程3解密后的內(nèi)容:" + new String(decrypt));
                }
            });

            thread3.start();



        } catch (NoSuchAlgorithmException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }

測(cè)試結(jié)果果然有幺蛾子:


測(cè)試結(jié)果.png

每次啟動(dòng)都會(huì)最終只有一個(gè)線程留下來進(jìn)行加密解密办素。其他兩個(gè)不知道為何就消失了角雷。
經(jīng)過排查,確定是Cipher不是線程安全的性穿。解決方法有兩種勺三,在加密和解密方法中給Cipher加鎖,或者在每次使用Cipher時(shí)新實(shí)例化一個(gè)對(duì)象需曾。我們選擇后一種方式吗坚。如果加密解密不是很頻繁可以使用第一種加鎖方式。但是當(dāng)加密解密密度很高時(shí)呆万,使用第一種方式會(huì)影響性能商源。第二種方式會(huì)增加一定的內(nèi)存使用,但是得益于Java8的gc內(nèi)存回收做的很好谋减,我們不用擔(dān)心由此帶來的內(nèi)存增加問題牡彻。所以我們用空間換時(shí)間。

線程安全加密實(shí)例

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class Encrypt4 {
    private final String password;
    private final KeyGenerator kgen;
    private final SecretKey secretKey;
    private final byte[] enCodeFormat;
    private final SecretKeySpec key;
    private final SecureRandom secureRandom;


    public Encrypt4(String password) throws NoSuchAlgorithmException, NoSuchPaddingException {
        this.password = password;

        kgen = KeyGenerator.getInstance("AES");

        secureRandom = SecureRandom.getInstance("SHA1PRNG");

        secureRandom.setSeed(password.getBytes());

        kgen.init(128, secureRandom);

        secretKey = kgen.generateKey();

        enCodeFormat = secretKey.getEncoded();

        key = new SecretKeySpec(enCodeFormat, "AES");

    }
    /**
     * AES加密字符串
     *
     * @param content 加密內(nèi)容
     *
     * @return 密文
     */
    public byte[] encrypt(String content) {
        try {
            byte[] byteContent = content.getBytes("utf-8");

            Cipher cipher = Cipher.getInstance("AES");

            cipher.init(Cipher.ENCRYPT_MODE, key);

            byte[] result = cipher.doFinal(byteContent);

            return result;

        } catch (UnsupportedEncodingException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        } catch (BadPaddingException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密AES加密過的字符串
     *
     * @param content 解密密文
     *
     * @return 明文
     */
    public byte[] decrypt(byte[] content) {
        try {
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, key);// 初始化為解密模式的密碼器
            byte[] result = cipher.doFinal(content);
            return result; // 明文

        } catch (InvalidKeyException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        } catch (BadPaddingException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static void main(String[] args) {

        String content1 = "麻溜地?cái)]個(gè)加密程序";
        String content2 = "茍利國家生死以";
        String content3 = "豈因福禍避趨之";
        String password = "123456";
        Encrypt4 e1, e2;

        try {
            e1 = new Encrypt4(password);
            e2 = new Encrypt4(password);
            Thread thread1, thread2, thread3;

            thread1 = new Thread(() -> {
                int i = 0;
                while (true) {
                    System.out.println("線程1加密之前:" + content1 + i);

                    // 加密
                    byte[] encrypt = e1.encrypt(content1 + i++);
                    System.out.println("線程1加密后的內(nèi)容:" + new String(encrypt));

                    // 解密
                    byte[] decrypt = e1.decrypt(encrypt);
                    System.out.println("線程1解密后的內(nèi)容:" + new String(decrypt));
                }
            });

            thread1.start();

            thread2 = new Thread(() -> {
                int i = 0;
                while (true) {
                    System.out.println("線程2加密之前:" + content2 + i);

                    // 加密
                    byte[] encrypt = e1.encrypt(content2 + i++);
                    System.out.println("線程2加密后的內(nèi)容:" + new String(encrypt));

                    // 解密
                    byte[] decrypt = e1.decrypt(encrypt);
                    System.out.println("線程2解密后的內(nèi)容:" + new String(decrypt));
                }
            });

            thread2.start();

            thread3 = new Thread(() -> {
                int i = 0;
                while (true) {
                    System.out.println("線程3加密之前:" + content3 + i);

                    // 加密
                    byte[] encrypt = e1.encrypt(content3 + i++);
                    System.out.println("線程3加密后的內(nèi)容:" + new String(encrypt));

                    // 解密
                    byte[] decrypt = e1.decrypt(encrypt);
                    System.out.println("線程3解密后的內(nèi)容:" + new String(decrypt));
                }
            });

            thread3.start();



        } catch (NoSuchAlgorithmException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }
}

寫在最后的話

AES加密算法非常簡單也非常常見出爹,本文只是寫一個(gè)備忘筆記庄吼。特別感謝在我學(xué)習(xí)過程中對(duì)我進(jìn)行無私幫助的耿騰

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末严就,一起剝皮案震驚了整個(gè)濱河市总寻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌盈蛮,老刑警劉巖废菱,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件技矮,死亡現(xiàn)場(chǎng)離奇詭異抖誉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)衰倦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門袒炉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人樊零,你說我怎么就攤上這事我磁。” “怎么了驻襟?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵夺艰,是天一觀的道長。 經(jīng)常有香客問我沉衣,道長郁副,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任豌习,我火速辦了婚禮存谎,結(jié)果婚禮上拔疚,老公的妹妹穿的比我還像新娘。我一直安慰自己既荚,他們只是感情好稚失,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著恰聘,像睡著了一般句各。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上晴叨,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天诫钓,我揣著相機(jī)與錄音,去河邊找鬼篙螟。 笑死菌湃,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的遍略。 我是一名探鬼主播惧所,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼绪杏!你這毒婦竟也來了下愈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤蕾久,失蹤者是張志新(化名)和其女友劉穎势似,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體僧著,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡履因,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了盹愚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片栅迄。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖皆怕,靈堂內(nèi)的尸體忽然破棺而出毅舆,到底是詐尸還是另有隱情,我是刑警寧澤愈腾,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布憋活,位于F島的核電站,受9級(jí)特大地震影響虱黄,放射性物質(zhì)發(fā)生泄漏悦即。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望盐欺。 院中可真熱鬧赁豆,春花似錦、人聲如沸冗美。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽粉洼。三九已至节预,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間属韧,已是汗流浹背安拟。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宵喂,地道東北人糠赦。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像锅棕,于是被迫代替她去往敵國和親拙泽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359