一個RSA的C++封裝

使用RSA的難點:

  1. 公鑰和私鑰的保存與加載录别。
    在很多的場合下,密鑰是以文件的形式分開保存的德谅,對程序員使用者來說爹橱,需要解決公鑰和私鑰的生成、保存窄做、加載問題。
  2. 加解密過程中的分組問題慰技。
    RSA加解密的開銷很大椭盏,比DES和AES高2個數(shù)量級,一般情況下不適合用來對較長的數(shù)據(jù)進行加解密吻商。但是掏颊,RSA本身也是一種分組加密算法,即使再短的數(shù)據(jù)加密需求,從程序的健狀性考慮乌叶,我們也必須搞清楚和實現(xiàn)分組的加解密支持盆偿。

下面的C++可復用代碼,解決了上面的這兩個問題准浴,有需要的朋友可以借鑒事扭。代碼如下:

頭文件RSA.h:

#ifndef __DAKUANG_RSA_H__
#define __DAKUANG_RSA_H__

#include <string>

namespace dakuang
{

    class CRSA
    {
    public:

        // 生成密鑰對,輸出為PEM文件
        static bool genKeyFiles(const std::string& strPrivateKeyPEMFile, const std::string& strPublicKeyPEMFile);

        // 生成密鑰對乐横,輸出為PEM字符串
        static bool genKeyStrings(std::string& strPrivateKeyPEMString, std::string& strPublicKeyPEMString);


        // 使用PEM私鑰文件加密
        static bool encryptByPrivatePEMFile(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMFile);

        // 使用PEM私鑰文件解密
        static bool decryptByPrivatePEMFile(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMFile);

        // 使用PEM公鑰文件加密
        static bool encryptByPublicPEMFile(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMFile);

        // 使用PEM公鑰文件解密
        static bool decryptByPublicPEMFile(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMFile);


        // 使用PEM私鑰字符串加密
        static bool encryptByPrivatePEMString(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMString);

        // 使用PEM私鑰字符串解密
        static bool decryptByPrivatePEMString(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMString);

        // 使用PEM公鑰字符串加密
        static bool encryptByPublicPEMString(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMString);

        // 使用PEM公鑰字符串解密
        static bool decryptByPublicPEMString(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMString);

    private:

        // 生成RSA密鑰結構
        static void* __genKey(int nBits);

        // 使用RSA執(zhí)行加密或解密
        static bool __encryptOrDecrypt(const std::string& strIn, std::string& strOut, const void* pRSA, const void* pFunc, bool bEncrypt);
    };

}

#endif

實現(xiàn)文件RSA.cpp:

#include "RSA.h"

#include <openssl/rsa.h>
#include <openssl/pem.h>

using namespace dakuang;

// 加解密函數(shù)簽名
typedef int (*RSA_encryptOrDecrypt)(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);

// 生成密鑰對求橄,輸出為PEM文件
bool CRSA::genKeyFiles(const std::string& strPrivateKeyPEMFile, const std::string& strPublicKeyPEMFile)
{
    // 生成RSA
    RSA* rsa = (RSA*)__genKey(1024);
    if (rsa == NULL)
        return false;

    // 輸出私鑰
    {
        BIO* bio = BIO_new_file(strPrivateKeyPEMFile.data(), "w");
        int ret = PEM_write_bio_RSAPrivateKey(bio, rsa, NULL, NULL, 0, NULL, NULL);
        if (ret != 1)
        {
            BIO_free(bio);
            RSA_free(rsa);
            return false;
        }

        BIO_free(bio);
    }

    // 輸出公鑰
    {
        BIO* bio = BIO_new_file(strPublicKeyPEMFile.data(), "w");
        int ret = PEM_write_bio_RSAPublicKey(bio, rsa);
        if (ret != 1)
        {
            BIO_free(bio);
            RSA_free(rsa);
            return false;
        }

        BIO_free(bio);
    }

    RSA_free(rsa);
    return true;
}

// 生成密鑰對,輸出為PEM字符串
bool CRSA::genKeyStrings(std::string& strPrivateKeyPEMString, std::string& strPublicKeyPEMString)
{
    // 生成RSA
    RSA* rsa = (RSA*)__genKey(1024);
    if (rsa == NULL)
        return false;

    // 輸出私鑰
    {
        BIO* bio = BIO_new(BIO_s_mem());
        int ret = PEM_write_bio_RSAPrivateKey(bio, rsa, NULL, NULL, 0, NULL, NULL);
        if (ret != 1)
        {
            BIO_free(bio);
            RSA_free(rsa);
            return false;
        }

        char sBuf[1024] = {0};
        int bytes = BIO_read(bio, sBuf, 1024);
        if (bytes <= 0)
        {
            BIO_free(bio);
            RSA_free(rsa);
            return false;
        }

        BIO_free(bio);
        strPrivateKeyPEMString.assign(sBuf, bytes);
    }

    // 輸出公鑰
    {
        BIO* bio = BIO_new(BIO_s_mem());
        int ret = PEM_write_bio_RSAPublicKey(bio, rsa);
        if (ret != 1)
        {
            BIO_free(bio);
            RSA_free(rsa);
            return false;
        }

        char sBuf[1024] = {0};
        int bytes = BIO_read(bio, sBuf, 1024);
        if (bytes <= 0)
        {
            BIO_free(bio);
            RSA_free(rsa);
            return false;
        }

        BIO_free(bio);
        strPublicKeyPEMString.assign(sBuf, bytes);
    }

    RSA_free(rsa);
    return true;
}


// 使用PEM私鑰文件加密
bool CRSA::encryptByPrivatePEMFile(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMFile)
{
    // 加載私鑰
    BIO* bio = BIO_new_file(strKeyPEMFile.data(), "r");
    RSA* rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
    BIO_free(bio);

    if (rsa == NULL)
        return false;

    // 使用私鑰加密
    bool b = __encryptOrDecrypt(strIn, strOut, rsa, (const void*)RSA_private_encrypt, true);
    RSA_free(rsa);
    return b;
}

// 使用PEM私鑰文件解密
bool CRSA::decryptByPrivatePEMFile(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMFile)
{
    // 加載私鑰
    BIO* bio = BIO_new_file(strKeyPEMFile.data(), "r");
    RSA* rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
    BIO_free(bio);

    if (rsa == NULL)
        return false;

    // 檢查密文大小是否為分組的整數(shù)倍
    int keySize = RSA_size(rsa);
    int blockSize = keySize;
    if ( (strIn.size() % blockSize) != 0 )
        return false;

    // 使用私鑰解密
    bool b = __encryptOrDecrypt(strIn, strOut, rsa, (const void*)RSA_private_decrypt, false);
    RSA_free(rsa);
    return b;
}

// 使用PEM公鑰文件加密
bool CRSA::encryptByPublicPEMFile(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMFile)
{
    // 加載公鑰
    BIO* bio = BIO_new_file(strKeyPEMFile.data(), "r");
    RSA* rsa = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL);
    BIO_free(bio);

    if (rsa == NULL)
        return false;

    // 使用公鑰加密
    bool b = __encryptOrDecrypt(strIn, strOut, rsa, (const void*)RSA_public_encrypt, true);
    RSA_free(rsa);
    return b;
}

// 使用PEM公鑰文件解密
bool CRSA::decryptByPublicPEMFile(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMFile)
{
    // 加載公鑰
    BIO* bio = BIO_new_file(strKeyPEMFile.data(), "r");
    RSA* rsa = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL);
    BIO_free(bio);

    if (rsa == NULL)
        return false;

    // 檢查密文大小是否為分組的整數(shù)倍
    int keySize = RSA_size(rsa);
    int blockSize = keySize;
    if ( (strIn.size() % blockSize) != 0 )
        return false;

    // 使用公鑰解密
    bool b = __encryptOrDecrypt(strIn, strOut, rsa, (const void*)RSA_public_decrypt, false);
    RSA_free(rsa);
    return b;
}


// 使用PEM私鑰字符串加密
bool CRSA::encryptByPrivatePEMString(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMString)
{
    // 加載私鑰
    BIO* bio = BIO_new_mem_buf((const void*)strKeyPEMString.data(), strKeyPEMString.size());
    RSA* rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
    BIO_free(bio);

    if (rsa == NULL)
        return false;

    // 使用私鑰加密
    bool b = __encryptOrDecrypt(strIn, strOut, rsa, (const void*)RSA_private_encrypt, true);
    RSA_free(rsa);
    return b;
}

// 使用PEM私鑰字符串解密
bool CRSA::decryptByPrivatePEMString(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMString)
{
    // 加載私鑰
    BIO* bio = BIO_new_mem_buf((const void*)strKeyPEMString.data(), strKeyPEMString.size());
    RSA* rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
    BIO_free(bio);

    if (rsa == NULL)
        return false;

    // 檢查密文大小是否為分組的整數(shù)倍
    int keySize = RSA_size(rsa);
    int blockSize = keySize;
    if ( (strIn.size() % blockSize) != 0 )
        return false;

    // 使用私鑰解密
    bool b = __encryptOrDecrypt(strIn, strOut, rsa, (const void*)RSA_private_decrypt, false);
    RSA_free(rsa);
    return b;
}

// 使用PEM公鑰字符串加密
bool CRSA::encryptByPublicPEMString(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMString)
{
    // 加載公鑰
    BIO* bio = BIO_new_mem_buf((const void*)strKeyPEMString.data(), strKeyPEMString.size());
    RSA* rsa = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL);
    BIO_free(bio);

    if (rsa == NULL)
        return false;

    // 使用公鑰加密
    bool b = __encryptOrDecrypt(strIn, strOut, rsa, (const void*)RSA_public_encrypt, true);
    RSA_free(rsa);
    return b;
}

// 使用PEM公鑰字符串解密
bool CRSA::decryptByPublicPEMString(const std::string& strIn, std::string& strOut, const std::string& strKeyPEMString)
{
    // 加載公鑰
    BIO* bio = BIO_new_mem_buf((const void*)strKeyPEMString.data(), strKeyPEMString.size());
    RSA* rsa = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL);
    BIO_free(bio);

    if (rsa == NULL)
        return false;

    // 檢查密文大小是否為分組的整數(shù)倍
    int keySize = RSA_size(rsa);
    int blockSize = keySize;
    if ( (strIn.size() % blockSize) != 0 )
        return false;

    // 使用公鑰解密
    bool b = __encryptOrDecrypt(strIn, strOut, rsa, (const void*)RSA_public_decrypt, false);
    RSA_free(rsa);
    return b;
}

// 生成RSA密鑰結構
void* CRSA::__genKey(int nBits)
{
    RSA* rsa = RSA_new();

    BIGNUM* bne = BN_new();
    BN_set_word(bne, RSA_F4);

    int ret = RSA_generate_key_ex(rsa, nBits, bne, NULL);

    BN_free(bne);

    if (ret != 1)
    {
        RSA_free(rsa);
        return NULL;
    }

    return (void*)rsa;
}

// 使用RSA執(zhí)行加密或解密
bool CRSA::__encryptOrDecrypt(const std::string& strIn, std::string& strOut, const void* pRSA, const void* pFunc, bool bEncrypt)
{
    const RSA_encryptOrDecrypt encryptOrDecrypt = (const RSA_encryptOrDecrypt)pFunc;

    // 計算加密塊大小
    int nKeySize = RSA_size((RSA*)pRSA);
    int nBlockSize = bEncrypt ? (nKeySize - RSA_PKCS1_PADDING_SIZE) : nKeySize;

    const unsigned char* pIn = (const unsigned char*)strIn.data();
    int nInSize = strIn.size();

    unsigned char* pBuf = new unsigned char[nKeySize];

    // 分組迭代加密
    for (int i = 0; i < nInSize; )
    {
        int nBlockLen = (nInSize - i > nBlockSize ? nBlockSize : nInSize - i);

        int ret = encryptOrDecrypt(nBlockLen, pIn + i, pBuf, (RSA*)pRSA, RSA_PKCS1_PADDING);
        if (ret <= 0)
        {
            delete[] pBuf;
            return false;
        }

        strOut.append((char*)pBuf, ret);
        i += nBlockLen;
    }

    delete[] pBuf;
    return true;
}

使用舉例:

下面的代碼完整地演示了RSA封裝的所有功能葡公,包括PEM文件的生成與加載罐农、字符串密鑰的生成與加載,以及兩種密鑰方法的加解密催什。

#include <stdio.h>
#include <stdlib.h>

#include "RSA.h"

int main(int argc, char* argv[])
{
    using namespace dakuang;

    std::string strText = "abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567
890abcdefghijklmnopqrstuvwxyz1234567890";

    {
        bool b = CRSA::genKeyFiles("test.key", "test.pub");
        printf("CRSA::genKeyFiles() ret:[%d] \n", b);

        std::string strCipher = "";
        b = CRSA::encryptByPrivatePEMFile(strText, strCipher, "test.key");
        printf("CRSA::encryptByPrivatePEMFile() ret:[%d] cipher len:[%d] \n", b, strCipher.size());

        std::string strText2 = "";
        b = CRSA::decryptByPublicPEMFile(strCipher, strText2, "test.pub");
        printf("CRSA::decryptByPublicPEMFile() ret:[%d] text len:[%d] body:[%s] \n", b, strText2.size(), strText2.data());

        strCipher = "";
        b = CRSA::encryptByPublicPEMFile(strText, strCipher, "test.pub");
        printf("CRSA::encryptByPublicPEMFile() ret:[%d] cipher len:[%d] \n", b, strCipher.size());

        strText2 = "";
        b = CRSA::decryptByPrivatePEMFile(strCipher, strText2, "test.key");
        printf("CRSA::decryptByPrivatePEMFile() ret:[%d] text len:[%d] body:[%s] \n", b, strText2.size(), strText2.data());
    }

    {
        std::string strPrivateKey = "", strPublicKey = "";
        bool b = CRSA::genKeyStrings(strPrivateKey, strPublicKey);
        printf("CRSA::genKeyStrings() ret:[%d] \n", b);

        std::string strCipher = "";
        b = CRSA::encryptByPrivatePEMString(strText, strCipher, strPrivateKey);
        printf("CRSA::encryptByPrivatePEMString() ret:[%d] cipher len:[%d] \n", b, strCipher.size());

        std::string strText2 = "";
        b = CRSA::decryptByPublicPEMString(strCipher, strText2, strPublicKey);
        printf("CRSA::decryptByPublicPEMString() ret:[%d] text len:[%d] body:[%s] \n", b, strText2.size(), strText2.data());

        strCipher = "";
        b = CRSA::encryptByPublicPEMString(strText, strCipher, strPublicKey);
        printf("CRSA::encryptByPublicPEMString() ret:[%d] cipher len:[%d] \n", b, strCipher.size());

        strText2 = "";
        b = CRSA::decryptByPrivatePEMString(strCipher, strText2, strPrivateKey);
        printf("CRSA::decryptByPrivatePEMString() ret:[%d] text len:[%d] body:[%s] \n", b, strText2.size(), strText2.data());
    }

    return 0;
}

生成私鑰內(nèi)容如下:
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDqpNkFqAdedWhOc+lukwCKFNamFr0HMSGgjONUE7dYL5wxk2Pe
5QsLIjqgA7dE14AFCQgF5WOyyUdP94xRGZdstH7CCWz2KhG7nX6ZupKwc5mMO+d3
8tpSp98TTx+CWLL/ntpZNB0cwU/Cx9TbkW+Ysto3LyPkjmlh4othcRMbJwIDAQAB
AoGAUV+qA9Qp+hAthEeehMJmRXzElAT+uSfIya0SiW3s/6BDQs4irIIyOkI8opGn
VTCHLTfcmG7dDHvRR2JKPzXo1RgQW7CgBK3/G5u7CCjF43XtdBd7F4f04yE+bOnY
3oGiXyv2N8okL3MtjSbQwsMX//v+M+fcQtVOO1iUtZPcnQECQQD8t1Dl1isvkaET
ZA+kdnzcF50Y0UQ3lIeTZKNhBH27jzs9tg172s/opS0Ef5c99gFx72Wt9QJfZKLu
4ZDHhJzxAkEA7bFpvS7tbCzqNYGrp3pocWGP7R7dGjKnxzy7tXOucPnyiLqlSL/N
48iWb0jneGN6u+/GiHrnwLaGGzh6gvcZlwJAJS4rPsVVsTfxxNKR4pZ0JEVtHXuc
V7kIgUzrJJjujquyAZBJR5GXyRiUGPdUnw8Ug1i/UuqbIMHDnvWcwV3nYQJAe1lo
QC8MMukUGfRS+jTB4qT4pdswbpn/C5vu5XlE+4gaXu5NO/WdiSndN58j0Av/82u5
IbZ2ckHGUnX6zeAhvQJBAJQs5GMT2MCQ8n5cFP/1eT0fiGPeP6qLO0UZ1BTFfGIq
mXz1ITOTo+PbE93uHDf3u299I70zF8v5R3ifFsGmAus=
-----END RSA PRIVATE KEY-----

生成公鑰內(nèi)容如下:
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAOqk2QWoB151aE5z6W6TAIoU1qYWvQcxIaCM41QTt1gvnDGTY97lCwsi
OqADt0TXgAUJCAXlY7LJR0/3jFEZl2y0fsIJbPYqEbudfpm6krBzmYw753fy2lKn
3xNPH4JYsv+e2lk0HRzBT8LH1NuRb5iy2jcvI+SOaWHii2FxExsnAgMBAAE=
-----END RSA PUBLIC KEY-----

輸出:
CRSA::genKeyFiles() ret:[1]
CRSA::encryptByPrivatePEMFile() ret:[1] cipher len:[256]
CRSA::decryptByPublicPEMFile() ret:[1] text len:[144] body:[abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890]
CRSA::encryptByPublicPEMFile() ret:[1] cipher len:[256]
CRSA::decryptByPrivatePEMFile() ret:[1] text len:[144] body:[abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890]
CRSA::genKeyStrings() ret:[1]
CRSA::encryptByPrivatePEMString() ret:[1] cipher len:[256]
CRSA::decryptByPublicPEMString() ret:[1] text len:[144] body:[abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890]
CRSA::encryptByPublicPEMString() ret:[1] cipher len:[256]
CRSA::decryptByPrivatePEMString() ret:[1] text len:[144] body:[abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890]

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涵亏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蒲凶,更是在濱河造成了極大的恐慌气筋,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件豹爹,死亡現(xiàn)場離奇詭異裆悄,居然都是意外死亡,警方通過查閱死者的電腦和手機臂聋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門光稼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人孩等,你說我怎么就攤上這事艾君。” “怎么了肄方?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵冰垄,是天一觀的道長。 經(jīng)常有香客問我权她,道長虹茶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任隅要,我火速辦了婚禮蝴罪,結果婚禮上,老公的妹妹穿的比我還像新娘步清。我一直安慰自己要门,他們只是感情好虏肾,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著欢搜,像睡著了一般封豪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上炒瘟,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天吹埠,我揣著相機與錄音,去河邊找鬼唧领。 笑死藻雌,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的斩个。 我是一名探鬼主播胯杭,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼受啥!你這毒婦竟也來了做个?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤滚局,失蹤者是張志新(化名)和其女友劉穎居暖,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體藤肢,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡太闺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了嘁圈。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片省骂。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖最住,靈堂內(nèi)的尸體忽然破棺而出钞澳,到底是詐尸還是另有隱情,我是刑警寧澤涨缚,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布轧粟,位于F島的核電站,受9級特大地震影響脓魏,放射性物質(zhì)發(fā)生泄漏兰吟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一茂翔、第九天 我趴在偏房一處隱蔽的房頂上張望揽祥。 院中可真熱鬧,春花似錦檩电、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽料按。三九已至,卻和暖如春卓箫,著一層夾襖步出監(jiān)牢的瞬間载矿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工烹卒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留闷盔,地道東北人。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓旅急,卻偏偏與公主長得像逢勾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子藐吮,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

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