DES暗号化のC++実装(各暗号化の中間結果付き)

70549 ワード

私のgithubからプロジェクト全体をダウンロードすることもできます.https://github.com/archimekai/DESEnciphererNew/
免責声明:This software comes with ABSOLUTELY NO WARRANTY.
main.cpp
#include "DESUtility.h"
#include <iostream>
#include <string>


using namespace std;
using namespace DESUtility;

void main() {
    cout << "Hello world!
"
; Encipherer encipherer = Encipherer(); char key[8] = { 'S', 'E', 'C', 'U', 'R', 'I', 'T', 'Y' }; string text = string("NETWORK INFORMATION SECURITY"); //string text = string("a"); encipherer.setKey((unsigned char *)key); unsigned char * result = encipherer.encipher(text); printf("
Enciphered text:"
); for (int i = 0; i < encipherer.ciphertextSize; ++i) { printf("%02X", result[i]); if ((i + 1) % 2 == 0) printf(" "); } printf("
"
); elemType * decipered = encipherer.decipher(result, encipherer.ciphertextSize); printf("
Plain text:"
); for (int i = 0; i < encipherer.ciphertextSize; ++i) { printf("%c", decipered[i]); } system("pause"); }

DESUtility.h
#pragma once
#define BLOCK_SIZE 64 //        
#define BLOCK_HALF_SIZE (BLOCK_SIZE/2)
#define BLOCK_elemType 8
#define E_SIZE 48 //            
#define ROUND_N 16 //      
#define KEY_LEN 64 //     
#define KEY_LEN_AFTER_P1 56 //              
#define KEY_HALF_LEN_AFTER_P1 (KEY_LEN_AFTER_P1/2)
#define SUB_KEY_LEN 48
#define ELEM_TYPE_BIT_SIZE 8
#define DEBUG //       
//#define DEBUG_ROUND
typedef unsigned char elemType;
//typedef unsigned char textType; //     

#include<string>


using namespace std;

namespace DESUtility {
    class Encipherer {
    public:
        unsigned char * encipher(string text);
        void setKey(unsigned char key[KEY_LEN / 8]);
        int ciphertextSize; //     
        elemType* decipher(elemType* compactBlock, int len); // blocks       
        void encipherBlock(elemType block[BLOCK_SIZE]);
        void decipherBlock(elemType block[BLOCK_SIZE], elemType text[8]);
        Encipherer() { ; }
        Encipherer(unsigned char key[KEY_LEN / 8]) {
            this->setKey(key);
        }
    private:  
        elemType key[KEY_LEN]; //   
        elemType subkeys[KEY_LEN_AFTER_P1 * ROUND_N]; //   
        int char2block(unsigned char* ch, elemType block[BLOCK_SIZE], int len);
        int block2hex(elemType block[BLOCK_SIZE], elemType converted[BLOCK_SIZE / ELEM_TYPE_BIT_SIZE]);
        void printConvertedBlock(elemType converted[BLOCK_SIZE / ELEM_TYPE_BIT_SIZE]);
        void printSparseBlock(elemType block[BLOCK_SIZE]);

        void initialPermutation(elemType* block, elemType* temp64);
        void initialPermutation(elemType block[BLOCK_SIZE]);
        void reversePermutation(elemType* block, elemType* temp64);
        void reversePermutation(elemType block[BLOCK_SIZE]);
        //void encipherBlock(elemType block[BLOCK_SIZE]);

        void genSubKey();

        void round(elemType block[BLOCK_SIZE], int iterCount);
        void extend(elemType block[BLOCK_HALF_SIZE], elemType tempE[E_SIZE]);
        void shiftLeft(elemType* block, int len, int shiftCount);
        void shiftLeftOneBit(elemType* block, int len);
        void replaceSelection2(elemType CD[KEY_LEN_AFTER_P1], elemType target[SUB_KEY_LEN]);
        void xorWithKey(elemType blockE[E_SIZE], int iterCount);
        void xorWithLAndSwapLR(elemType block[BLOCK_SIZE]);
        void selectCompression(elemType blockE[E_SIZE], elemType target[BLOCK_HALF_SIZE]);
        void permutation(elemType input[BLOCK_HALF_SIZE], elemType target[BLOCK_HALF_SIZE]);
        void swapLR(elemType block[BLOCK_SIZE]);

        //void decipherBlock(elemType block[BLOCK_SIZE], elemType text[8]);
        //void num2bits();
    };
}

DESUtility.cpp
#include "DESUtility.h"
#include <iostream>
using namespace std;
namespace DESUtility {
#pragma region constant parameters

    //     IP 
    int IP_Table[64] = { 57,49,41,33,25,17,9,1,
        59,51,43,35,27,19,11,3,
        61,53,45,37,29,21,13,5,
        63,55,47,39,31,23,15,7,
        56,48,40,32,24,16,8,0,
        58,50,42,34,26,18,10,2,
        60,52,44,36,28,20,12,4,
        62,54,46,38,30,22,14,6 };

    //      IP^-1 
    int IP_1_Table[64] = { 39,7,47,15,55,23,63,31,
        38,6,46,14,54,22,62,30,
        37,5,45,13,53,21,61,29,
        36,4,44,12,52,20,60,28,
        35,3,43,11,51,19,59,27,
        34,2,42,10,50,18,58,26,
        33,1,41,9,49,17,57,25,
        32,0,40,8,48,16,56,24 };

    //     E 
    int E_Table[E_SIZE] = { 31, 0, 1, 2, 3, 4,
        3,  4, 5, 6, 7, 8,
        7,  8,9,10,11,12,
        11,12,13,14,15,16,
        15,16,17,18,19,20,
        19,20,21,22,23,24,
        23,24,25,26,27,28,
        27,28,29,30,31, 0 };

    //    P 
    int P_Table[BLOCK_HALF_SIZE] = { 15,6,19,20,28,11,27,16,
        0,14,22,25,4,17,30,9,
        1,7,23,13,31,26,2,8,
        18,12,29,5,21,10,3,24 };

    //S  
    int S[8][4][16] =//S1 
    { { { 14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7 },
    { 0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8 },
    { 4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0 },
    { 15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13 } },
        //S2 
    { { 15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10 },
    { 3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5 },
    { 0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15 },
    { 13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9 } },
        //S3 
    { { 10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8 },
    { 13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1 },
    { 13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7 },
    { 1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12 } },
        //S4 
    { { 7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15 },
    { 13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9 },
    { 10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4 },
    { 3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14 } },
        //S5 
    { { 2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9 },
    { 14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6 },
    { 4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14 },
    { 11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3 } },
        //S6 
    { { 12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11 },
    { 10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8 },
    { 9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6 },
    { 4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13 } },
        //S7 
    { { 4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1 },
    { 13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6 },
    { 1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2 },
    { 6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12 } },
        //S8 
    { { 13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7 },
    { 1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2 },
    { 7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8 },
    { 2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11 } } };
    //    1 
    int PC_1[KEY_LEN_AFTER_P1] = { 56,48,40,32,24,16,8,
        0,57,49,41,33,25,17,
        9,1,58,50,42,34,26,
        18,10,2,59,51,43,35,
        62,54,46,38,30,22,14,
        6,61,53,45,37,29,21,
        13,5,60,52,44,36,28,
        20,12,4,27,19,11,3 };

    //    2 
    int PC_2[SUB_KEY_LEN] = { 13,16,10,23,0,4,2,27,
        14,5,20,9,22,18,11,3,
        25,7,15,6,26,19,12,1,
        40,51,30,36,46,54,29,39,
        50,44,32,46,43,48,38,55,
        33,52,45,41,49,35,28,31 };

    //         
    int MOVE_TIMES[ROUND_N] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 };
#pragma endregion


    unsigned char * Encipherer::encipher(string text) {
        const int len = text.size();
#ifdef DEBUG
        cout << "Text length: " << len <<"
"
; #endif // DEBUG unsigned char temp[8] = { 0 }; elemType block[BLOCK_SIZE] = { 0 }; int size = 0; if (len % 8 == 0) { size = len; } else { size = ((int)(len / 8)) * 8 + 8; } #ifdef DEBUG cout << "Enciphered block size(bytes):" << size << "
"
; #endif // DEBUG unsigned char * resultBlock = (unsigned char *)malloc(sizeof(unsigned char) * size); // memset(resultBlock, 0, sizeof(unsigned char) * size); int i = 0; int blockNo = -1; for (i = 0; i < len; ++i) { temp[i % 8] = text.at(i); if ((i + 1) % 8 == 0) { blockNo = (i + 1) / 8 - 1; #ifdef DEBUG cout << "
====Now encipher block no."
<< blockNo << "====
"
; cout << "Text to be enciphered: "; for (int k = 0; k < 8; ++k) { cout << temp[k]; } cout << "
"
; #endif // DEBUG char2block(temp, block, 8); #ifdef DEBUG cout << "converted text:
"
; printSparseBlock(block); cout << "
"
; #endif // DEBUG encipherBlock(block); block2hex(block, resultBlock + blockNo * 8); #ifdef DEBUG cout << "====Enciphered block no." << blockNo << "====
"
; cout << "====Enciphered text:====
"
; printConvertedBlock(resultBlock + blockNo * 8); cout << "
"
; #endif // DEBUG memset(temp, 0, sizeof(unsigned char) * 8); memset(block, 0, sizeof(elemType) * BLOCK_SIZE); } } if (len % 8 != 0) { ++blockNo; #ifdef DEBUG cout << "
====Now encipher block no."
<< blockNo << "====
"
; cout << "Text to be enciphered: "; for (int k = 0; k < 8; ++k) { printf("%c", temp[k]); } cout << "
"
; #endif // DEBUG // char2block(temp, block, 8); #ifdef DEBUG cout << "converted text:
"
; printSparseBlock(block); cout << "
"
; #endif // DEBUG encipherBlock(block); block2hex(block, resultBlock + blockNo * 8); #ifdef DEBUG cout << "====Enciphered block no." << blockNo << "====
"
; cout << "====Enciphered text:====
"
; printConvertedBlock(resultBlock + blockNo * 8); cout << "
"
; #endif // DEBUG } ciphertextSize = size; return resultBlock; // memory leak } void Encipherer::setKey(unsigned char key[KEY_LEN / 8]) { char2block(key, this->key, KEY_LEN / 8); genSubKey(); } // , // len 8 elemType * Encipherer::decipher(elemType * compactBlock, int len) { int sparseLen = len * ELEM_TYPE_BIT_SIZE; elemType * block = (elemType *)malloc(sizeof(elemType) * sparseLen); for (int i = 0; i < len; ++i) { for (int j = 0; j < ELEM_TYPE_BIT_SIZE; ++j) { block[i * ELEM_TYPE_BIT_SIZE + j] = (compactBlock[i] >> j) % 2; } } elemType * result = (elemType *)malloc(sizeof(elemType) * len); memset(result, 0, sizeof(elemType) * len); // malloc !! for (int i = 0; i < len / 8; ++i) { decipherBlock(block + i * BLOCK_SIZE, (elemType *)(result + 8 * i)); } return result; } // C block, , 8 // len: ch int Encipherer::char2block(unsigned char * ch, elemType block[BLOCK_SIZE], int len) { int ncharsToConvert = BLOCK_SIZE / ELEM_TYPE_BIT_SIZE; int i; for (i = 0; i < ncharsToConvert && i < len; ++i) { for (int j = 0; j < 8; ++j) { // char 8 bit block[i * 8 + j] = (ch[i] >> j) % 2; } } return i; } // converted block int Encipherer::block2hex(elemType block[BLOCK_SIZE], elemType converted[BLOCK_SIZE / ELEM_TYPE_BIT_SIZE]) { for (int i = 0; i < BLOCK_SIZE / ELEM_TYPE_BIT_SIZE; ++i) { for (int j = 0; j < ELEM_TYPE_BIT_SIZE; ++j) { converted[i] += block[i * ELEM_TYPE_BIT_SIZE + j] << j; } } return 0; } void Encipherer::printConvertedBlock(elemType converted[BLOCK_SIZE / ELEM_TYPE_BIT_SIZE]) { for (int i = 0; i < BLOCK_SIZE / ELEM_TYPE_BIT_SIZE; ++i) { printf("%02X", converted[i]); if ((i + 1) % 2 == 0) printf(" "); } } void Encipherer::printSparseBlock(elemType block[BLOCK_SIZE]){ elemType compactBlock[BLOCK_SIZE / ELEM_TYPE_BIT_SIZE] = { 0 }; block2hex(block, compactBlock); printConvertedBlock(compactBlock); } // void Encipherer::initialPermutation(elemType* block, elemType* temp64) { for (int i = 0; i < BLOCK_SIZE; ++i) { temp64[i] = block[IP_Table[i]]; } } void Encipherer::initialPermutation(elemType block[BLOCK_SIZE]) { elemType temp[BLOCK_SIZE] = { 0 }; for (int i = 0; i < BLOCK_SIZE; ++i) { temp[i] = block[IP_Table[i]]; } memcpy(block, temp, sizeof(elemType) * BLOCK_SIZE); } // void Encipherer::reversePermutation(elemType* block, elemType* temp64) { for (int i = 0; i < BLOCK_SIZE; ++i) { temp64[i] = block[IP_1_Table[i]]; } } void Encipherer::reversePermutation(elemType block[BLOCK_SIZE]) { elemType temp[BLOCK_SIZE] = { 0 }; for (int i = 0; i < BLOCK_SIZE; ++i) { temp[i] = block[IP_1_Table[i]]; } memcpy(block, temp, sizeof(elemType) * BLOCK_SIZE); } // void Encipherer::encipherBlock(elemType block[BLOCK_SIZE]) { initialPermutation(block); #ifdef DEBUG cout << "Enciphered block after initialPermutation:
"
; printSparseBlock(block); cout << "
"
; #endif // DEBUG for (int i = 0; i < ROUND_N; ++i) { round(block, i); #ifdef DEBUG cout << "Enciphered block after round " << i <<":
"
; printSparseBlock(block); cout << "
"
; #endif // DEBUG } swapLR(block); #ifdef DEBUG cout << "Enciphered block after left-right-swap:
"
; printSparseBlock(block); cout << "
"
; #endif // DEBUG reversePermutation(block); #ifdef DEBUG cout << "Enciphered block after reversePermutation:
"
; printSparseBlock(block); cout << "
"
; #endif // DEBUG } // 16 。 void Encipherer::genSubKey() { elemType temp[KEY_LEN_AFTER_P1] = { 0 }; // 1 for (int i = 0; i < KEY_LEN_AFTER_P1; ++i) { temp[i] = key[PC_1[i]]; // TODO key } for (int i = 0; i < ROUND_N; ++i) { // C shiftLeft(temp, KEY_HALF_LEN_AFTER_P1, MOVE_TIMES[i]); // D shiftLeft(temp + KEY_HALF_LEN_AFTER_P1, KEY_HALF_LEN_AFTER_P1, MOVE_TIMES[i]); // 2 replaceSelection2(temp, subkeys + i * SUB_KEY_LEN); } } // void Encipherer::round(elemType block[BLOCK_SIZE], int iterCount) { elemType eletemps_R[BLOCK_HALF_SIZE] = { 0 }; memcpy(eletemps_R, block + BLOCK_HALF_SIZE, sizeof(elemType) * BLOCK_HALF_SIZE); // 32 elemType extended[E_SIZE] = { 0 }; extend(block + BLOCK_HALF_SIZE, extended); #ifdef DEBUG_ROUND printSparseBlock(block); cout << "
"
; #endif //DEBUG_ROUND xorWithKey(extended, iterCount); selectCompression(extended, block + BLOCK_HALF_SIZE); #ifdef DEBUG_ROUND printSparseBlock(block); cout << "
"
; #endif //DEBUG_ROUND elemType permutated[BLOCK_HALF_SIZE]; permutation(block + BLOCK_HALF_SIZE, permutated); #ifdef DEBUG_ROUND printSparseBlock(block); cout << "
"
; #endif //DEBUG_ROUND memcpy(block + BLOCK_HALF_SIZE, permutated, sizeof(elemType) * BLOCK_HALF_SIZE); #ifdef DEBUG_ROUND printSparseBlock(block); cout << "
"
; #endif //DEBUG_ROUND xorWithLAndSwapLR(block); memcpy(block, eletemps_R, sizeof(elemType) * BLOCK_HALF_SIZE); #ifdef DEBUG_ROUND printSparseBlock(block); cout << "
"
; #endif //DEBUG_ROUND } // // blockE:48 elemType void Encipherer::extend(elemType blockE[BLOCK_HALF_SIZE], elemType tempE[E_SIZE]) { // [48] for (int i = 0; i < E_SIZE; ++i) { tempE[i] = blockE[E_Table[i]]; } } // // shiftcount void Encipherer::shiftLeft(elemType* block, int len, int shiftCount) { for (int i = 0; i < shiftCount; ++i) { shiftLeftOneBit(block, len); } } // void Encipherer::shiftLeftOneBit(elemType* block, int len) { if (len <= 1) return; elemType temp = block[len - 1]; block[len - 1] = block[0]; for (int i = 1; i <= len - 2; ++i) { block[i - 1] = block[i]; } block[len - 2] = temp; } // 2 void Encipherer::replaceSelection2(elemType CD[KEY_LEN_AFTER_P1], elemType target[SUB_KEY_LEN]) { for (int i = 0; i < SUB_KEY_LEN; ++i) { target[i] = CD[PC_2[i]]; } } // , block // iterCount 1 void Encipherer::xorWithKey(elemType blockE[E_SIZE], int iterCount) { for (int i = 0; i < E_SIZE; ++i) { blockE[i] = blockE[i] ^ subkeys[(iterCount - 1) * SUB_KEY_LEN + i]; } } // void Encipherer::selectCompression(elemType blockE[E_SIZE], elemType target[BLOCK_HALF_SIZE]) { for (int i = 0; i < 6; ++i) { //for (int j = 0; j < 8; ++j) { int row = blockE[i * 6] * 2 + blockE[i * 6 + 5]; int col = blockE[i * 6 + 1] * 8 + blockE[i * 6 + 2] * 4 + blockE[i * 6 + 3] * 2 + blockE[i * 6 + 4]; int out = S[i][row][col]; for (int k = 0; k < 4; ++k) { target[i * 4 + k] = (elemType)((out >> (3 - k)) % 2); } //} } } // void Encipherer::permutation(elemType input[BLOCK_HALF_SIZE], elemType target[BLOCK_HALF_SIZE]) { for (int i = 0; i < BLOCK_HALF_SIZE; ++i) { target[i] = input[P_Table[i]]; } } void Encipherer::swapLR(elemType block[BLOCK_SIZE]) { elemType temp; for (int i = 0; i < BLOCK_HALF_SIZE; ++i) { temp = block[i]; block[i] = block[i + BLOCK_HALF_SIZE]; block[i + BLOCK_HALF_SIZE] = temp; } } void Encipherer::decipherBlock(elemType block[BLOCK_SIZE], elemType text[8]) { #ifdef DEBUG cout << "In decipherBlock:
"
; printSparseBlock(block); cout << "
"
; #endif // DEBUG // initialPermutation(block); #ifdef DEBUG cout << "Deciphered block after initialPermutation:
"
; printSparseBlock(block); cout << "
"
; #endif // DEBUG // 16 for (int i = ROUND_N - 1; i >= 0; --i) { round(block, i); #ifdef DEBUG cout << "Deciphered block after round " << i << ":
"
; printSparseBlock(block); cout << "
"
; #endif // DEBUG } swapLR(block); #ifdef DEBUG cout << "Deciphered block after left-right-swap:
"
; printSparseBlock(block); cout << "
"
; #endif // DEBUG reversePermutation(block); #ifdef DEBUG cout << "Dnciphered block after reversePermutation:
"
; printSparseBlock(block); cout << "
"
; #endif // DEBUG block2hex(block, text); } void Encipherer::xorWithLAndSwapLR(elemType block[BLOCK_SIZE]) { for (int i = 0; i < BLOCK_HALF_SIZE; ++i) { block[BLOCK_HALF_SIZE + i] = block[BLOCK_HALF_SIZE + i] ^ block[i]; } //for (int i = 0; i < BLOCK_HALF_SIZE; ++i) { // elemType temp = block[i]; // block[i] = block[BLOCK_HALF_SIZE + i]; // block[BLOCK_HALF_SIZE + i] = temp; //} } }