• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

            路漫漫,長修遠,我們不能沒有錢
            隨筆 - 173, 文章 - 0, 評論 - 257, 引用 - 0
            數(shù)據(jù)加載中……

            ChaCha20 加密 算法 c++11實現(xiàn)


            ChaCha20 加密/解密算法, 支持單輪多輪加密
              1 #ifndef CHACHA20_H
              2 #define CHACHA20_H
              3 
              4 #include <array>
              5 #include <vector>
              6 #include <algorithm>
              7 #include <sstream>
              8 #include <iostream>
              9 #include <iomanip>
             10 #include <string>
             11 
             12 //#include<QDebug>
             13 
             14 
             15 /**
             16  * @brief ChaCha20 加密/解密算法, 支持單輪多輪加密
             17  */
             18 class ChaCha20
             19 {
             20 public:
             21     /**
             22      * @brief ChaCha20 chacha20加密算法構(gòu)造器 單輪
             23      * @param key 32字節(jié)的key
             24      * @param nonce 8字節(jié)隨機數(shù)
             25      */
             26     ChaCha20(std::array<unsigned char32> key, std::array<unsigned char8> nonce) :
             27         matrix{}
             28     {
             29         // 16byte常量字符串"apxe3 dnyb-2k et"
             30         this->matrix[ 0= 0x61707865;
             31         this->matrix[ 1= 0x3320646e;
             32         this->matrix[ 2= 0x79622d32;
             33         this->matrix[ 3= 0x6b206574;
             34 
             35         this->matrix[ 4= littleEndianToInt(key, 0);
             36         this->matrix[ 5= littleEndianToInt(key, 4);
             37         this->matrix[ 6= littleEndianToInt(key, 8);
             38         this->matrix[ 7= littleEndianToInt(key, 12);
             39 
             40         this->matrix[ 8= littleEndianToInt(key, 16);
             41         this->matrix[ 9= littleEndianToInt(key, 20);
             42         this->matrix[10= littleEndianToInt(key, 24);
             43         this->matrix[11= littleEndianToInt(key, 28);
             44 
             45         this->matrix[12= 0;
             46         this->matrix[13= 0;
             47         this->matrix[14= littleEndianToInt(nonce, 0);
             48         this->matrix[15= littleEndianToInt(nonce, 4);
             49     }
             50 
             51     /**
             52      * @brief ChaCha20 ChaCha20 chacha20加密算法構(gòu)造器, 多輪
             53      * @param key 32字節(jié)key
             54      * @param nonce 12字節(jié)隨機數(shù)
             55      * @param counter 輪轉(zhuǎn)次數(shù)
             56      */
             57     ChaCha20(std::array<unsigned char32> key, std::array<unsigned char12> nonce, const int counter) :
             58         matrix{}
             59     {
             60 
             61         // 16byte常量字符串"apxe3 dnyb-2k et"
             62         this->matrix[ 0= 0x61707865;
             63         this->matrix[ 1= 0x3320646e;
             64         this->matrix[ 2= 0x79622d32;
             65         this->matrix[ 3= 0x6b206574;
             66 
             67         this->matrix[ 4= littleEndianToInt(key, 0);
             68         this->matrix[ 5= littleEndianToInt(key, 4);
             69         this->matrix[ 6= littleEndianToInt(key, 8);
             70         this->matrix[ 7= littleEndianToInt(key, 12);
             71         this->matrix[ 8= littleEndianToInt(key, 16);
             72         this->matrix[ 9= littleEndianToInt(key, 20);
             73         this->matrix[10= littleEndianToInt(key, 24);
             74         this->matrix[11= littleEndianToInt(key, 28);
             75 
             76 
             77         this->matrix[12= counter;
             78         this->matrix[13= littleEndianToInt(nonce, 0);
             79         this->matrix[14= littleEndianToInt(nonce, 4);
             80         this->matrix[15= littleEndianToInt(nonce, 8);
             81     }
             82 
             83 
             84     /**
             85      * @brief encrypt 加密
             86      * @param plain 原文
             87      * @param dst 密文
             88      * @param len 原文長度
             89      */
             90     void encrypt( std::vector<unsigned char>& plain, std::vector<unsigned char>& ciphertext) {
             91         std::array<int16> x{};
             92         std::array<unsigned char64> output{};
             93         int i, dpos = 0, spos = 0, len = plain.size();
             94 //        qDebug() << "len:" << len;
             95         while (len > 0) {
             96 //            for (i = 16; i-- > 0; ) x[i] = this->matrix[i];
             97             std::copy_n(matrix.begin(), matrix.size(), x.begin());
             98             for (i = 20; i > 0; i -= 2) {
             99                 quarterRound(x, 04,  812);
            100                 quarterRound(x, 15,  913);
            101                 quarterRound(x, 261014);
            102                 quarterRound(x, 371115);
            103                 quarterRound(x, 051015);
            104                 quarterRound(x, 161112);
            105                 quarterRound(x, 27,  813);
            106                 quarterRound(x, 34,  914);
            107 
            108 //                qDebug() << "[" << intToHex(x[0]).c_str() << ", " << intToHex(x[1]).c_str() << ", " << intToHex(x[2]).c_str() << ", " << intToHex(x[3]).c_str()
            109 //                         << ", " << intToHex(x[4]).c_str() << ", " << intToHex(x[5]).c_str() << ", " << intToHex(x[6]).c_str() << ", " << intToHex(x[7]).c_str()
            110 //                         << ", " << intToHex(x[8]).c_str() << ", " << intToHex(x[9]).c_str() << ", " << intToHex(x[10]).c_str() << ", " << intToHex(x[11]).c_str()
            111 //                         << ", " << intToHex(x[12]).c_str() << ", " << intToHex(x[13]).c_str() << ", " << intToHex(x[14]).c_str() << ", " << intToHex(x[15]).c_str()  << "]";
            112             }
            113             for (i = 16; i-- > 0; ) x[i] += this->matrix[i];
            114             for (i = 16; i-- > 0; ) intToLittleEndian(x[i], output, 4 * i);
            115 
            116             // TODO: (1) check block count 32-bit vs 64-bit; (2) java int is signed!
            117             this->matrix[12+= 1;
            118             if (this->matrix[12== 0) {
            119                 this->matrix[13+= 1;
            120             }
            121             if (len <= 64) {
            122                 for (i = len; i-- > 0; ) {
            123 //                    qDebug() << "dist["  << (i + dpos) << "] = " << ((unsigned char) (plain[i + spos] ^ output[i]));
            124                     ciphertext[i + dpos] = (unsigned char) (plain[i + spos] ^ output[i]);
            125                 }
            126                 return;
            127             }
            128             for (i = 64; i-- > 0; ) {
            129 //                qDebug() << "dist[" << (i + dpos) << "] = " << ((unsigned char) (plain[i + spos] ^ output[i]));
            130                 ciphertext[i + dpos] = (unsigned char) (plain[i + spos] ^ output[i]);
            131             }
            132             len -= 64;
            133             spos += 64;
            134             dpos += 64;
            135         }
            136     }
            137 
            138 
            139 
            140     /**
            141      * @brief decrypt 解密
            142      * @param src 原文
            143      * @param plain 密文
            144      * @param len
            145      */
            146     void decrypt(std::vector<unsigned char>& ciphertext, std::vector<unsigned char>& plain) {
            147         encrypt(ciphertext, plain);
            148     }
            149 
            150 
            151 //    void test(){
            152 //        int v = 0xaaaa, c=0x8888;
            153 //        rotate(v, c);
            154 //    }
            155 
            156 
            157 protected:
            158     template< typename T >
            159     std::string intToHex( const T& i )
            160     {
            161       std::stringstream stream;
            162       stream //<< "0x"
            163              << std::setfill ('0'<< std::setw(sizeof(T)*2)
            164              << std::hex << i;
            165       return stream.str();
            166     }
            167 
            168 private:
            169     /**
            170      * N支持8或12
            171      */
            172     template<size_t N >
            173     /**
            174      * @brief littleEndianToInt 小端內(nèi)存塊轉(zhuǎn)整數(shù)
            175      * @param bs  小端內(nèi)存塊
            176      * @param offset 需要轉(zhuǎn)換成int的位置offset
            177      * @return 返回轉(zhuǎn)換后的整數(shù)
            178      */
            179     inline int littleEndianToInt(std::array<unsigned char, N>& bs, const int& offset){
            180         return (bs[offset]) | (bs[offset + 1<< 8| (bs[offset + 2<< 16| (bs[offset + 3<< 24);
            181     }
            182 
            183 
            184     /**
            185      * @brief intToLittleEndian
            186      * @param n 整數(shù)
            187      * @param bs 小端內(nèi)存塊, 出參
            188      * @param offset 存放在內(nèi)存塊中的偏移位
            189      */
            190     inline void intToLittleEndian(const int& n, std::array<unsigned char64>& bs, int offset){
            191         bs[  offset] = (unsigned char)(n      );
            192         bs[++offset] = (unsigned char)((unsigned)n >>  8);
            193         bs[++offset] = (unsigned char)((unsigned)n >> 16);
            194         bs[++offset] = (unsigned char)((unsigned)n >> 24);
            195     }
            196 
            197 
            198     int rotate(const int& v, const int& c){
            199 //        qDebug() << intToHex((v << c) | (v >> (32 - c))).c_str();
            200         return (v << c) | ((unsigned)v >> (32 - c));
            201     }
            202 
            203     void quarterRound(std::array<int16>& x, const int& a, const int& b, const int& c, const int& d) {
            204 //        qDebug() << "begin " << intToHex(x[a]).c_str() << ", "<< intToHex(x[b]).c_str() << ", "<< intToHex(x[c]).c_str() << ", "<< intToHex(x[d]).c_str();
            205         x[a] += x[b];
            206 //        qDebug() << "1 " << intToHex(x[a]).c_str() << ", "<< intToHex(x[b]).c_str() << ", "<< intToHex(x[c]).c_str() << ", "<< intToHex(x[d]).c_str();
            207 
            208 //        qDebug() << "1 " << intToHex(x[d]).c_str() << ",  " << intToHex(x[d] ^ x[a]).c_str();
            209         x[d] = rotate(x[d] ^ x[a], 16);
            210 //        qDebug() << "1 " << intToHex(x[d]).c_str() << ",  " << intToHex(x[d] ^ x[a]).c_str();
            211         x[c] += x[d];
            212 //        qDebug() << "2 " << intToHex(x[a]).c_str() << ", "<< intToHex(x[b]).c_str() << ", "<< intToHex(x[c]).c_str() << ", "<< intToHex(x[d]).c_str();
            213 
            214         x[b] = rotate(x[b] ^ x[c], 12);
            215 //        qDebug() << "2 " << intToHex(x[b]).c_str() ;
            216         x[a] += x[b];
            217         x[d] = rotate(x[d] ^ x[a], 8);
            218         x[c] += x[d];
            219         x[b] = rotate(x[b] ^ x[c], 7);
            220 //        qDebug() << "end " << intToHex(x[a]).c_str() << ", "<< intToHex(x[b]).c_str() << ", "<< intToHex(x[c]).c_str() << ", "<< intToHex(x[d]).c_str();
            221     }
            222 
            223 
            224 private:
            225     std::array<int16> matrix;
            226 
            227 };
            228 
            229 
            230 
            231 
            232 #endif // CHACHA20_H
            233 






            調(diào)用方式:

            1  加密:

             1         volatile bool flag = false;
             2         //加密
             3         QByteArray qKeyBytes = qKey.toUtf8();
             4         std::array<unsigned char32> keyBytes;
             5         std::copy_n(qKeyBytes.begin(), keyBytes.size(), keyBytes.begin());
             6 
             7         QByteArray qSourceBytes = qSource.toUtf8();
             8         std::vector<unsigned char> sourceBytes(qSourceBytes.size());
             9         std::copy_n(qSourceBytes.begin(), qSourceBytes.size(), sourceBytes.begin());
            10 
            11         std::vector<unsigned char> destinaBytes(sourceBytes.size());
            12         if(qNonce.length() == 8){
            13             QByteArray qNonceBytes = qNonce.toUtf8();
            14             std::array<unsigned char8> nonceBytes;
            15             std::copy_n(qNonceBytes.begin(), qNonceBytes.size(), nonceBytes.begin());
            16             ChaCha20 chacha20(keyBytes, nonceBytes);
            17             //            chacha20.test();
            18             chacha20.encrypt(sourceBytes, destinaBytes);
            19             flag = true;
            20         } else if(qNonce.length() == 12){
            21             QByteArray qNonceBytes = qNonce.toUtf8();
            22             std::array<unsigned char12> nonceBytes;
            23             std::copy_n(qNonceBytes.begin(), qNonceBytes.size(), nonceBytes.begin());
            24             ChaCha20 chacha20(keyBytes, nonceBytes, qCounter.toUInt());
            25             //            chacha20.test();
            26             chacha20.encrypt(sourceBytes, destinaBytes);
            27             flag = true;
            28         } else {
            29             qDebug() << TIMESTAMP << "encrypt nonce長度不合法";
            30         }
            31 
            32         if(flag){
            33             QByteArray qDestBytes(destinaBytes.size(), 0);
            34             std::copy_n(destinaBytes.begin(), destinaBytes.size(), qDestBytes.begin());
            35 
            36             qDebug() << TIMESTAMP << "encrypt data:" << qDestBytes.toHex();
            37 
            38             QString qDestStr = qDestBytes.toBase64(QByteArray::Base64UrlEncoding);
            39             qDebug() << TIMESTAMP << "encrypt base64 data:" << qDestStr;
            40 
            41             ui->leDestina->setText(qDestStr);
            42         }



            2: 解密
                        volatile bool flag = false;
                        //解密
                        QByteArray qKeyBytes = qKey.toUtf8();
                        std::array<unsigned char, 32> keyBytes;
                        std::copy_n(qKeyBytes.begin(), keyBytes.size(), keyBytes.begin());

                        QByteArray qDestinaBytes;
                        qDestinaBytes = qDestinaBytes.fromBase64(qDestina.toUtf8());
                //        qDebug() << TIMESTAMP << "ciphertext data:" << qDestinaBytes.toHex();

                        std::vector<unsigned char> destinaBytes(qDestinaBytes.size());
                        std::copy_n(qDestinaBytes.begin(), qDestinaBytes.size(), destinaBytes.begin());

                        std::vector<unsigned char> sourceBytes(destinaBytes.size());
                        if(qNonce.length() == 8){
                            QByteArray qNonceBytes = qNonce.toUtf8();
                            std::array<unsigned char, 8> nonceBytes;
                            std::copy_n(qNonceBytes.begin(), qNonceBytes.size(), nonceBytes.begin());
                            ChaCha20 chacha20(keyBytes, nonceBytes);
                            chacha20.decrypt(destinaBytes, sourceBytes);
                            flag = true;
                        } else if(qNonce.length() == 12){
                            QByteArray qNonceBytes = qNonce.toUtf8();
                            std::array<unsigned char, 12> nonceBytes;
                            std::copy_n(qNonceBytes.begin(), qNonceBytes.size(), nonceBytes.begin());
                            ChaCha20 chacha20(keyBytes, nonceBytes, qCounter.toUInt());
                            chacha20.decrypt(destinaBytes, sourceBytes);
                            flag = true;
                        } else {
                            qDebug() << TIMESTAMP << "decrypt nonce長度不合法";
                        }

                        if(flag){
                            QByteArray qSourceBytes(sourceBytes.size(), 0);
                            std::copy_n(sourceBytes.begin(), sourceBytes.size(), qSourceBytes.begin());

                            qDebug() << TIMESTAMP << "decrypt ascii data:" << qSourceBytes.toHex();

                            QString qSourceStr = qSourceBytes;
                            qDebug() << TIMESTAMP << "decrypt data:" << qSourceStr;

                            ui->leSource->setText(qSourceStr);
                        }


                        //解密
                        qDebug() << TIMESTAMP << "key:" << qKey << ", nonce:" << qNonce << ", counter:" << qCounter
                                 << ", destina:" << qDestina;



            后記 :
            1. nonce長度只允許8字節(jié)或12字節(jié), 如果nonce長度為8字節(jié), 則counter被無視, 如果為12字節(jié), counter才有效
            2. key長度恒定為32字節(jié), 如果不足, 自己補齊32字節(jié)
            3. 解密就是將加密的結(jié)果在xor一次





















            posted on 2021-06-03 17:38 Khan 閱讀(2781) 評論(0)  編輯 收藏 引用

            亚洲伊人久久大香线蕉综合图片 | 欧美一级久久久久久久大| 亚洲香蕉网久久综合影视| 欧美一级久久久久久久大片| 亚洲综合婷婷久久| 久久婷婷久久一区二区三区| 久久精品亚洲日本波多野结衣| 久久伊人五月丁香狠狠色| 综合久久一区二区三区 | 久久精品国产亚洲AV忘忧草18| 亚洲?V乱码久久精品蜜桃 | 国产成人综合久久精品红| 久久无码一区二区三区少妇 | 久久天天躁狠狠躁夜夜2020| 久久青青草原精品国产软件| 久久久久久av无码免费看大片| 精品99久久aaa一级毛片| 久久精品国产亚洲一区二区三区| 久久精品成人免费国产片小草| 久久久久国产一区二区| 欧美一级久久久久久久大| 波多野结衣久久一区二区| 久久久女人与动物群交毛片| 国产三级久久久精品麻豆三级| 伊人久久大香线焦综合四虎| 91精品国产高清91久久久久久| 国产精品久久久久天天影视| 亚洲综合精品香蕉久久网97| 久久精品中文字幕第23页| 九九精品久久久久久噜噜| 久久亚洲中文字幕精品一区| 亚洲国产精品无码成人片久久| 久久99精品久久久久婷婷| 嫩草影院久久99| 伊人伊成久久人综合网777| 久久久久人妻精品一区| 国产日韩久久久精品影院首页| 久久久国产99久久国产一| 99999久久久久久亚洲| 色综合久久88色综合天天 | 久久精品国产亚洲AV麻豆网站|