go包:crypto-aes 對(duì)稱加密

1.介紹

高級(jí)加密標(biāo)準(zhǔn)英語:Advanced Encryption Standard茧泪,縮寫:AES),又稱Rijndael加密法(荷蘭語發(fā)音:[?r?inda?l],音似英文的“Rhine doll”),是美國(guó)聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)训桶。這個(gè)標(biāo)準(zhǔn)用來替代原先的DES躏精,已經(jīng)被多方分析且廣為全世界所使用。經(jīng)過五年的甄選流程苦锨,高級(jí)加密標(biāo)準(zhǔn)由美國(guó)國(guó)家標(biāo)準(zhǔn)與技術(shù)研究院(NIST)于2001年11月26日發(fā)布于FIPS PUB 197,并在2002年5月26日成為有效的標(biāo)準(zhǔn)∨棵冢現(xiàn)在舟舒,高級(jí)加密標(biāo)準(zhǔn)已然成為對(duì)稱密鑰加密中最流行的[算法之一。

該算法為比利時(shí)密碼學(xué)家Joan Daemen和Vincent Rijmen所設(shè)計(jì)嗜憔,結(jié)合兩位作者的名字秃励,以Rijndael為名投稿高級(jí)加密標(biāo)準(zhǔn)的甄選流程。

2. 電碼本模式(ECB)

2.1 加密

a.代碼
// 加密
func AesEncryptByECB(data, key string) string {
    // 判斷key長(zhǎng)度
    keyLenMap := map[int]struct{}{16: {}, 24: {}, 32: {}}
    if _,ok := keyLenMap[len(key)]; !ok {
        panic("key長(zhǎng)度必須是 16吉捶、24夺鲜、32 其中一個(gè)")
    }
    // 密鑰和待加密數(shù)據(jù)轉(zhuǎn)成[]byte
    originByte := []byte(data)
    keyByte := []byte(key)
    // 創(chuàng)建密碼組,長(zhǎng)度只能是16呐舔、24币励、32字節(jié)
    block, _ := aes.NewCipher(keyByte)
    // 獲取密鑰長(zhǎng)度
    blockSize := block.BlockSize()
    // 補(bǔ)碼
    originByte = PKCS7Padding(originByte, blockSize)
    // 創(chuàng)建保存加密變量
    encryptResult := make([]byte, len(originByte))
    // CEB是把整個(gè)明文分成若干段相同的小段,然后對(duì)每一小段進(jìn)行加密
    for bs, be := 0, blockSize; bs < len(originByte); bs, be = bs+blockSize, be+blockSize {
        block.Encrypt(encryptResult[bs:be], originByte[bs:be])
    }
    return base64.StdEncoding.EncodeToString(encryptResult)
}
// 補(bǔ)碼
func PKCS7Padding(originByte []byte, blockSize int) []byte {
    // 計(jì)算補(bǔ)碼長(zhǎng)度
    padding := blockSize - len(originByte)%blockSize
    // 生成補(bǔ)碼
    padText := bytes.Repeat([]byte{byte(padding)}, padding)
    // 追加補(bǔ)碼
    return append(originByte, padText...)
}
b.測(cè)試
package crypto
import (
    "52lu/go-study-example/package/crypto"
    "fmt"
    "strings"
    "testing"
)
// 加密
func TestECBEncrypt(t *testing.T) {
    key := strings.Repeat("a", 16)
    data := "hello word"
    s := crypto.AesEncryptByECB(data, key)
    fmt.Printf("加密密鑰: %v \n", key)
    fmt.Printf("加密數(shù)據(jù): %v \n", data)
    fmt.Printf("加密結(jié)果: %v \n", s)
}
/** 輸出
=== RUN   TestECBEncrypt
加密密鑰: aaaaaaaaaaaaaaaa 
加密數(shù)據(jù): hello word 
加密結(jié)果: mMAsLF/fPBfUrP0mPqZm1w== 
--- PASS: TestECBEncrypt (0.00s)
PASS
*/

2.2 解密

a.代碼
// 解密
func AesDecryptByECB(data, key string) string {
    // 判斷key長(zhǎng)度
    keyLenMap := map[int]struct{}{16: {}, 24: {}, 32: {}}
    if _,ok := keyLenMap[len(key)]; !ok {
        panic("key長(zhǎng)度必須是 16珊拼、24食呻、32 其中一個(gè)")
    }
    // 反解密碼base64
    originByte, _ := base64.StdEncoding.DecodeString(data)
    // 密鑰和待加密數(shù)據(jù)轉(zhuǎn)成[]byte
    keyByte := []byte(key)
    // 創(chuàng)建密碼組,長(zhǎng)度只能是16、24仅胞、32字節(jié)
    block, _ := aes.NewCipher(keyByte)
    // 獲取密鑰長(zhǎng)度
    blockSize := block.BlockSize()
    // 創(chuàng)建保存解密變量
    decrypted := make([]byte, len(originByte))
    for bs, be := 0, blockSize; bs < len(originByte); bs, be = bs+blockSize, be+blockSize {
        block.Decrypt(decrypted[bs:be], originByte[bs:be])
    }
    // 解碼
    return string(PKCS7UNPadding(decrypted))
}
// 解碼
func PKCS7UNPadding(originDataByte []byte) []byte {
    length := len(originDataByte)
    unpadding := int(originDataByte[length-1])
    return originDataByte[:(length-unpadding)]
}
b.測(cè)試
// 解密
func TestECBDecrypt(t *testing.T) {
    key := strings.Repeat("a", 16)
    data := "mMAsLF/fPBfUrP0mPqZm1w=="
    s := crypto.AesDecryptByECB(data, key)
    fmt.Printf("解密密鑰: %v \n", key)
    fmt.Printf("解密數(shù)據(jù): %v \n", data)
    fmt.Printf("解密結(jié)果: %v \n", s)
}
/** 輸出
=== RUN   TestECBDecrypt
解密密鑰: aaaaaaaaaaaaaaaa 
解密數(shù)據(jù): mMAsLF/fPBfUrP0mPqZm1w== 
解密結(jié)果: hello word 
--- PASS: TestECBDecrypt (0.00s)
PASS
*/

3. 密碼分組鏈模式(CBC)

3.1 加密

a.代碼
// AES加密
func AesEncryptByCBC(str, key string) string {
    // 判斷key長(zhǎng)度
    keyLenMap := map[int]struct{}{16: {}, 24: {}, 32: {}}
    if _,ok := keyLenMap[len(key)]; !ok {
        panic("key長(zhǎng)度必須是 16每辟、24、32 其中一個(gè)")
    }
    // 待加密字符串轉(zhuǎn)成byte
    originDataByte := []byte(str)
    // 秘鑰轉(zhuǎn)成[]byte
    keyByte := []byte(key)
    // 創(chuàng)建一個(gè)cipher.Block接口干旧。參數(shù)key為密鑰渠欺,長(zhǎng)度只能是16、24莱革、32字節(jié)
    block, _ := aes.NewCipher(keyByte)
    // 獲取秘鑰長(zhǎng)度
    blockSize := block.BlockSize()
    // 補(bǔ)碼填充
    originDataByte = PKCS7Padding(originDataByte, blockSize)
    // 選用加密模式
    blockMode := cipher.NewCBCEncrypter(block, keyByte[:blockSize])
    // 創(chuàng)建數(shù)組峻堰,存儲(chǔ)加密結(jié)果
    encrypted := make([]byte, len(originDataByte))
    // 加密
    blockMode.CryptBlocks(encrypted, originDataByte)
    // []byte轉(zhuǎn)成base64
    return base64.StdEncoding.EncodeToString(encrypted)
}
// 補(bǔ)碼
func PKCS7Padding(originByte []byte, blockSize int) []byte {
    // 計(jì)算補(bǔ)碼長(zhǎng)度
    padding := blockSize - len(originByte)%blockSize
    // 生成補(bǔ)碼
    padText := bytes.Repeat([]byte{byte(padding)}, padding)
    // 追加補(bǔ)碼
    return append(originByte, padText...)
}
b.測(cè)試
package crypto
import (
    "52lu/go-study-example/package/crypto"
    "fmt"
    "strings"
    "testing"
)
// AES加密
func TestAesEncryptByCBC(t *testing.T) {
    key := strings.Repeat("a", 16)
    fmt.Printf("key: %v 長(zhǎng)度: %d \n", key, len(key))
    text := "abc"
    fmt.Printf("帶加密文案: %v \n", text)
    encrypt := crypto.AesEncryptByCBC(text, key)
    fmt.Printf("加密結(jié)果: %v \n", encrypt)
}
/** 輸出
=== RUN   TestAesEncryptByCBC
key: aaaaaaaaaaaaaaaa 長(zhǎng)度: 16 
帶加密文案: abc 
加密結(jié)果: rMX6r9x+PnTOhfgDH4jjXg== 
--- PASS: TestAesEncryptByCBC (0.00s)
PASS
*/

3.2 解密

a.代碼
// 解密
func AesDecryptByCBC(encrypted,key string) string  {
    // 判斷key長(zhǎng)度
    keyLenMap := map[int]struct{}{16: {}, 24: {}, 32: {}}
    if _,ok := keyLenMap[len(key)]; !ok {
        panic("key長(zhǎng)度必須是 16、24盅视、32 其中一個(gè)")
    }
    // encrypted密文反解base64
    decodeString, _ := base64.StdEncoding.DecodeString(encrypted)
    // key 轉(zhuǎn)[]byte
    keyByte := []byte(key)
    // 創(chuàng)建一個(gè)cipher.Block接口捐名。參數(shù)key為密鑰,長(zhǎng)度只能是16闹击、24镶蹋、32字節(jié)
    block, _ := aes.NewCipher(keyByte)
    // 獲取秘鑰塊的長(zhǎng)度
    blockSize := block.BlockSize()
    // 選擇加密模式
    blockMode := cipher.NewCBCDecrypter(block, keyByte[:blockSize])
    // 創(chuàng)建數(shù)組,存儲(chǔ)解密結(jié)果
    decodeResult := make([]byte, blockSize)
    // 解密
    blockMode.CryptBlocks(decodeResult,decodeString)
    // 解碼
    padding := PKCS7UNPadding(decodeResult)
    return string(padding)
}
// 解碼
func PKCS7UNPadding(originDataByte []byte) []byte {
    length := len(originDataByte)
    unpadding := int(originDataByte[length-1])
    return originDataByte[:(length-unpadding)]
}
b.測(cè)試
package crypto
import (
    "52lu/go-study-example/package/crypto"
    "fmt"
    "strings"
    "testing"
)
// AES解密
func TestAesDecryptByCBC(t *testing.T) {
    key := strings.Repeat("a", 16)
    fmt.Printf("key: %v 長(zhǎng)度: %d \n", key, len(key))
    text := "rMX6r9x+PnTOhfgDH4jjXg=="
    fmt.Printf("待解密文案: %v \n", text)
    decrypt := crypto.AesDecryptByCBC(text, key)
    fmt.Printf("解密結(jié)果: %v \n", decrypt)
}

/** 輸出
=== RUN   TestAesDecryptByCBC
key: aaaaaaaaaaaaaaaa 長(zhǎng)度: 16 
待解密文案: rMX6r9x+PnTOhfgDH4jjXg== 
解密結(jié)果: abc 
--- PASS: TestAesDecryptByCBC (0.00s)
PASS
*/

4. 計(jì)算器模式(CTR)

4.1 加密

a.代碼
// 加密,分別返回 hex格式和base64 結(jié)果
func AesEncryptByCTR(data, key string) (string,string) {
    // 判斷key長(zhǎng)度
    keyLenMap := map[int]struct{}{16: {}, 24: {}, 32: {}}
    if _,ok := keyLenMap[len(key)]; !ok {
        panic("key長(zhǎng)度必須是 16赏半、24贺归、32 其中一個(gè)")
    }
    // 轉(zhuǎn)成byte
    dataByte := []byte(data)
    keyByte := []byte(key)
    // 創(chuàng)建block
    block, err := aes.NewCipher(keyByte)
    if err != nil {
        panic(fmt.Sprintf("NewCipher error:%s",err))
    }
    blockSize := block.BlockSize()
    // 創(chuàng)建偏移量iv,取秘鑰前16個(gè)字符
    iv := []byte(key[:blockSize])
    // 補(bǔ)碼
    padding := PKCS7Padding(dataByte, blockSize)
    // 加密模式
    stream := cipher.NewCTR(block, iv)
    // 定義保存結(jié)果變量
    out := make([]byte,len(padding))
    stream.XORKeyStream(out,padding)
    // 處理加密結(jié)果
    hexRes := fmt.Sprintf("%x",out)
    base64Res := base64.StdEncoding.EncodeToString(out)
    return hexRes,base64Res
}
// 補(bǔ)碼
func PKCS7Padding(originByte []byte, blockSize int) []byte {
    // 計(jì)算補(bǔ)碼長(zhǎng)度
    padding := blockSize - len(originByte)%blockSize
    // 生成補(bǔ)碼
    padText := bytes.Repeat([]byte{byte(padding)}, padding)
    // 追加補(bǔ)碼
    return append(originByte, padText...)
}
b.測(cè)試
package crypto
import (
    "52lu/go-study-example/package/crypto"
    "fmt"
    "strings"
    "testing"
)
// 測(cè)試AES-CTR加密
func TestAesEncryptByCTR(t *testing.T) {
    key := strings.Repeat("a", 16)
    data := "hello word"
    hex, base64 := crypto.AesEncryptByCTR(data, key)
    fmt.Printf("加密key: %v \n", key)
    fmt.Printf("加密key長(zhǎng)度: %v \n", len(key))
    fmt.Printf("加密數(shù)據(jù): %v \n", data)
    fmt.Printf("加密結(jié)果(hex): %v \n", hex)
    fmt.Printf("加密結(jié)果(base64): %v \n", base64)
}
/** 輸出
=== RUN   TestAesEncryptByCTR
加密key: aaaaaaaaaaaaaaaa 
加密key長(zhǎng)度: 16 
加密數(shù)據(jù): hello word 
加密結(jié)果(hex): 39edaa2b2402fbd2a026ef1458b81b55 
加密結(jié)果(base64): Oe2qKyQC+9KgJu8UWLgbVQ== 
--- PASS: TestAesEncryptByCTR (0.00s)
PASS
*/

4.2 解密

a.代碼
// 解密
func AesDecryptByCTR(dataBase64,key string)  string {
    // 判斷key長(zhǎng)度
    keyLenMap := map[int]struct{}{16: {}, 24: {}, 32: {}}
    if _,ok := keyLenMap[len(key)]; !ok {
        panic("key長(zhǎng)度必須是 16、24断箫、32 其中一個(gè)")
    }
    // dataBase64轉(zhuǎn)成[]byte
    decodeStringByte, err := base64.StdEncoding.DecodeString(dataBase64)
    if err != nil {
        panic(fmt.Sprintf("base64 DecodeString error: %s",err))
    }
    // 創(chuàng)建block
    block, err := aes.NewCipher([]byte(key))
    if err != nil {
        panic(fmt.Sprintf("NewCipher error: %s",err))
    }
    blockSize := block.BlockSize()
    // 創(chuàng)建偏移量iv,取秘鑰前16個(gè)字符
    iv := []byte(key[:blockSize])
    // 創(chuàng)建Stream
    stream := cipher.NewCTR(block, iv)
    // 聲明變量
    out := make([]byte,len(decodeStringByte))
    // 解密
    stream.XORKeyStream(out,decodeStringByte)
    // 解密加密結(jié)果并返回
    return string(PKCS7UNPadding(out))
}
b.測(cè)試
package crypto
import (
    "52lu/go-study-example/package/crypto"
    "fmt"
    "strings"
    "testing"
)
// 測(cè)試AES-CTR解密
func TestAesDecryptByCTR(t *testing.T) {
    key := strings.Repeat("a", 16)
    data := "Oe2qKyQC+9KgJu8UWLgbVQ=="
    res := crypto.AesDecryptByCTR(data, key)
    fmt.Printf("解密key: %v \n", key)
    fmt.Printf("解密數(shù)據(jù): %v \n", data)
    fmt.Printf("解密結(jié)果: %v \n", res)
}
/** 輸出
=== RUN   TestAesDecryptByCTR
解密key: aaaaaaaaaaaaaaaa 
解密數(shù)據(jù): Oe2qKyQC+9KgJu8UWLgbVQ== 
解密結(jié)果: hello word 
--- PASS: TestAesDecryptByCTR (0.00s)
PASS
*/

5. CFB拂酣、OFB

CTR模式一樣,只需要修改加密模式即可,查看具體源碼 https://github.com/52lu/go-study-example

// CFB
...
stream := cipher.NewCFBDecrypter(block, iv)
...
// OFB
...
stream := cipher.NewOFB(block, iv)
...

不理解的點(diǎn): 在學(xué)習(xí)使用中,發(fā)現(xiàn)CFB/OFB/CTR 在加密很短的字符串時(shí)仲义,發(fā)現(xiàn)加密結(jié)果一致婶熬。

func TestAesEncryptByOFB(t *testing.T) {
    key := strings.Repeat("a", 16)
    data := "123"
    _, base64 := crypto.AesEncryptByOFB(data, key)
    _, base642 := crypto.AesEncryptByCTR(data, key)
    _, base643 := crypto.AesEncryptByCFB(data, key)
    fmt.Printf("加密key: %v \n", key)
    fmt.Printf("加密key長(zhǎng)度: %v \n", len(key))
    fmt.Printf("加密數(shù)據(jù): %v \n", data)
    fmt.Printf("加密結(jié)果(OFB): %v \n", base64)
    fmt.Printf("加密結(jié)果(CTR): %v \n", base642)
    fmt.Printf("加密結(jié)果(CFB): %v \n", base643)
}
/** 輸出
=== RUN   TestAesEncrypt
加密key: aaaaaaaaaaaaaaaa 
加密key長(zhǎng)度: 16 
加密數(shù)據(jù): 123 
加密結(jié)果(OFB): YLr1SkYvgbDfT+QfU7MQXg== 
加密結(jié)果(CTR): YLr1SkYvgbDfT+QfU7MQXg== 
加密結(jié)果(CFB): YLr1SkYvgbDfT+QfU7MQXg== 
--- PASS: TestAesEncrypt (0.00s)
PASS

6.AES-GCM

GCM 全稱為Galois/Counter Mode,可以看出 G 是指 GMAC埃撵,C 是指 CTR赵颅。它在 CTR 加密的基礎(chǔ)上增加 GMAC 的特性,解決了 CTR 不能對(duì)加密消息進(jìn)行完整性校驗(yàn)的問題暂刘。

6.1 加密

// 加密(GCM 不需要補(bǔ)碼)
func AesEncryptByGCM(data, key string) string {
    block, err := aes.NewCipher([]byte(key))
    if err != nil {
        panic(fmt.Sprintf("NewCipher error:%s", err))
    }
    gcm, err := cipher.NewGCM(block)
    if err != nil {
        panic(fmt.Sprintf("NewGCM error:%s", err))
    }
    // 生成隨機(jī)因子(這里固定取密鑰指定位數(shù))
    //nonce := make([]byte, gcm.NonceSize())
    //if _,err := io.ReadFull(rand.Reader,nonce); err != nil {
    //    panic(fmt.Sprintf("make rand nonce error:%s", err))
    //}
    nonceStr := key[:gcm.NonceSize()]
    nonce := []byte(nonceStr)
    fmt.Printf("nonceStr = %v \n", nonceStr)
    seal := gcm.Seal(nonce, nonce, []byte(data), nil)
    return base64.StdEncoding.EncodeToString(seal)
}

6.2 解密

// 解密(GCM 不需要解碼)
func AesDecryptByGCM(data, key string) string {
    // 反解base64
    dataByte,err := base64.StdEncoding.DecodeString(data)
    if err != nil {
        panic(fmt.Sprintf("base64 DecodeString error:%s", err))
    }
    block, err := aes.NewCipher([]byte(key))
    if err != nil {
        panic(fmt.Sprintf("NewCipher error:%s", err))
    }
    gcm, err := cipher.NewGCM(block)
    if err != nil {
        panic(fmt.Sprintf("NewGCM error:%s", err))
    }
    nonceSize := gcm.NonceSize()
    if len(dataByte) < nonceSize {
        panic("dataByte to short")
    }
    nonce, ciphertext := dataByte[:nonceSize], dataByte[nonceSize:]
    open, err := gcm.Open(nil, nonce, ciphertext, nil)
    if err != nil {
        panic(fmt.Sprintf("gcm Open error:%s", err))
    }
    return string(open)
}

6.3 測(cè)試

package crypto
import (
    "52lu/go-study-example/package/crypto"
    "fmt"
    "strings"
    "testing"
)
func TestAesGCM(t *testing.T) {
    key := strings.Repeat("a",16)
    data := "hello word!"
    // 加密
    gcm := crypto.AesEncryptByGCM(data, key)
    fmt.Printf("密鑰key: %s \n",key)
    fmt.Printf("加密數(shù)據(jù): %s \n",data)
    fmt.Printf("加密結(jié)果: %s \n",gcm)
    // 解密
    byGCM := crypto.AesDecryptByGCM(gcm, key)
    fmt.Printf("解密結(jié)果: %s \n",byGCM)
}
/** 輸出
=== RUN   TestAesGCM
nonceStr = aaaaaaaaaaaa 
密鑰key: aaaaaaaaaaaaaaaa 
加密數(shù)據(jù): hello word! 
加密結(jié)果: YWFhYWFhYWFhYWFhhi5dsHDfOdUFfno08BMWWI4iESBd0CF6zE9C 
解密結(jié)果: hello word! 
--- PASS: TestAesGCM (0.00s)
PASS
*/
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末饺谬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子谣拣,更是在濱河造成了極大的恐慌募寨,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件森缠,死亡現(xiàn)場(chǎng)離奇詭異绪商,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)辅鲸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腹殿,“玉大人独悴,你說我怎么就攤上這事例书。” “怎么了刻炒?”我有些...
    開封第一講書人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵决采,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我坟奥,道長(zhǎng)树瞭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任爱谁,我火速辦了婚禮晒喷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘访敌。我一直安慰自己凉敲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開白布寺旺。 她就那樣靜靜地躺著爷抓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪阻塑。 梳的紋絲不亂的頭發(fā)上蓝撇,一...
    開封第一講書人閱讀 49,792評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音陈莽,去河邊找鬼渤昌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛传透,可吹牛的內(nèi)容都是我干的耘沼。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼朱盐,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼群嗤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起兵琳,我...
    開封第一講書人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤狂秘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后躯肌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體者春,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年清女,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了钱烟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拴袭,靈堂內(nèi)的尸體忽然破棺而出读第,到底是詐尸還是另有隱情,我是刑警寧澤拥刻,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布怜瞒,位于F島的核電站,受9級(jí)特大地震影響般哼,放射性物質(zhì)發(fā)生泄漏吴汪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一蒸眠、第九天 我趴在偏房一處隱蔽的房頂上張望漾橙。 院中可真熱鬧,春花似錦黔宛、人聲如沸近刘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽觉渴。三九已至,卻和暖如春徽惋,著一層夾襖步出監(jiān)牢的瞬間案淋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工险绘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留踢京,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓宦棺,卻偏偏與公主長(zhǎng)得像瓣距,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子代咸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

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