DES-CBC加密和解密模式

问题

加密       

    输入:<plaintext> <key> <iv>

    输出:<ciphertext>

    例如

    输入:<i love you, sunsiqi> <0123456789ABCDEF> <FEDCBA0123456789>

    输出:<4e152ec964f73950dfc7a3d833bdaeffd6f0b8a727c13c29>

      输入:<ciphertext> <key> <iv>

      输出:<plaintext>

      例如

      输入:<4e152ec964f73950dfc7a3d833bdaeffd6f0b8a727c13c29> <0123456789ABCDEF> <FEDCBA0123456789>

      输出:<i love you, sunsiqi>

要求

  • 中英文混合内容处理
  • 正确处理任意长度的明文输入

  • 自动进行PKCS#7填充

  • 验证所有输入参数的合法性

  • 提供清晰的错误信息

  • 保证加密过程的安全性

  • 正确处理边界情况(如空输入、最大长度输入等)

  • 跨平台编码支持

WIN平台支持

#include <>
...
...
#ifdef _WIN32
#include <windows.h>
#endif

在主函数中设置控制台编码格式为UTF-8

int main(){
// 设置控制台编码为UTF-8
    #ifdef _WIN32
    SetConsoleOutputCP(CP_UTF8);
    #endif
    ...
    ...
}

代码

头文件

#include <iostream>
#include <string>
#include <cctype> // <cctype>包含字符处理库,用于字符类型判断等操作,在 isValidHex 函数中使用 std::isxdigit 来判断字符是否为十六进制字符
#include <cryptopp/des.h>
#include <cryptopp/modes.h>
#include <cryptopp/filters.h>// <cryptopp/filters.h>包含 Crypto++ 库中数据过滤器的头文件,用于处理加密解密过程中的数据转换和流操作
#include <cryptopp/hex.h>
#include <cryptopp/pwdbased.h>
#include <stdexcept>

加密

// 命名空间,用于组织相关功能
namespace SymCryptoUtilities {

    /**
     * @brief 验证十六进制字符串的有效性
     * 
     * 该函数遍历输入的字符串,检查每个字符是否为有效的十六进制字符(0-9, A-F, a-f)。
     * 
     * @param hexStr 待验证的十六进制字符串
     * @return 如果字符串中的所有字符都是有效的十六进制字符,则返回 true;否则返回 false
     */
    bool isValidHex(const std::string& hexStr) {
        for (char c : hexStr) {
            if (!std::isxdigit(c)) return false;
        }
        return true;
    }

     /**
     * @brief 将十六进制字符串解码为字节数组
     * 
     * 该函数首先检查输入的十六进制字符串长度是否为偶数,因为每个字节由两个十六进制字符表示。
     * 然后使用 Crypto++ 库的 HexDecoder 进行解码操作。
     * 
     * @param hexStr 待解码的十六进制字符串
     * @return 解码后的字节数组,以 std::string 形式表示
     * @throws std::invalid_argument 如果输入的十六进制字符串长度不是偶数
     */
    std::string hexDecode(const std::string& hexStr) {
        if (hexStr.length() % 2 != 0) {
            throw std::invalid_argument("Hex string must have even length");
        }

        std::string decoded;
        CryptoPP::StringSource ss(
            hexStr, 
            true, 
            new CryptoPP::HexDecoder(new CryptoPP::StringSink(decoded))
        );
        return decoded;
    }

    /**
     * @brief 将字节数组编码为十六进制字符串
     * 
     * 该函数使用 Crypto++ 库的 HexEncoder 对输入的字节数组进行编码操作,不添加换行符。
     * 
     * @param data 待编码的字节数组,以 std::string 形式表示
     * @return 编码后的十六进制字符串
     */
    std::string hexEncode(const std::string& data) {
        std::string encoded;
        CryptoPP::StringSource ss(
            data, 
            true, 
            new CryptoPP::HexEncoder(new CryptoPP::StringSink(encoded),false)// 不添加换行符
        );
        return encoded;
    }

    /**
     * @brief 执行 DES-CBC 加密操作
     * 
     * 该函数使用 DES(Data Encryption Standard)算法的 CBC(Cipher Block Chaining)模式对明文进行加密。
     * 明文长度标准为 64bit,少于则进行填充,多于则进行截断。
     * 分组长度为 64bit,密文长度为 64bit,密钥长度为 64bit(包含 8bit 奇偶校验,不参与加解密过程)。
     * 
     * @param plaintext 待加密的明文,以 std::string 形式表示
     * @param key 加密使用的密钥,以字节数组形式表示,长度必须为 8 字节
     * @param iv 初始化向量(IV),以字节数组形式表示,长度必须为 8 字节
     * @return 加密后的密文,以十六进制字符串形式表示
     * @throws std::invalid_argument 如果密钥或 IV 的长度不符合要求
     * @throws std::runtime_error 如果 Crypto++ 库在加密过程中抛出异常
     */
    std::string desCBCEncrypt(const std::string& plaintext, const std::string& key, const std::string& iv) {
        try {
            // 参数验证,检查参数的合法性
            if (key.size() != CryptoPP::DES::DEFAULT_KEYLENGTH) {
                throw std::invalid_argument("Invalid key size. Expected 8 bytes");
            }
            if (iv.size() != CryptoPP::DES::BLOCKSIZE) {
                throw std::invalid_argument("Invalid IV size. Expected 8 bytes");
            }

            // 设置加密参数,创建CBC模式加密对象encryptor
            // CryptoPP::CBC_Mode<>时一个模板类,需要传入具体的算法类型,如<CryptoPP::DES>
            CryptoPP::CBC_Mode<CryptoPP::DES>::Encryption encryptor;
            /*
                CryptoPP::CBC_Mode<CryptoPP::DES>::Encryption::SetKeyWithIV用于设置加密所需的密钥和初始化向量
            */
            encryptor.SetKeyWithIV(
                // CryptoPP::byte是库中定义的字节类型,通常等同于unsigned char
                // 将密钥字符串转换为 Crypto++ 的字节指针
                reinterpret_cast<const CryptoPP::byte*>(key.data()), key.size(),
                reinterpret_cast<const CryptoPP::byte*>(iv.data()), iv.size()
            );

            // 用于存储密文的字符串
            std::string ciphertext;

            // 执行加密操作
            // CryptoPP::StringSource是库中的一个数据源类,用于从std::string对象中读取数据
            /*构造函数参数分别是:
                std:string类型的数据源;
                bool value:
                    true:自动删除过滤器链中的对象
                    false:不自动删除过滤器链中的对象,需要手动调用delete释放CryptoPP::StreamTransformationFilter 对象的内存
                指向过滤器对象的指针
            */
            CryptoPP::StringSource ss(
                plaintext, true,
        
                /* 
                    使用 StreamTransformationFilter 进行流转换过滤,将明文加密为密文
                    CryptoPP::StreamTransformationFilter是一个过滤器类,用于对数据流进行加密和解密操作。
                    构造函数参数:
                        指向加密或解密对象的指针
                        指向数据接收器对象的指针
                        可选参数:填充方案
                    返回值:
                        返回指向CryptoPP::StreamTransformationFilter类对象的指针
                        类的对象可以作为指针类型传递给其他对象
                */
                new CryptoPP::StreamTransformationFilter(
                    encryptor,
                    // CryptoPP::StringSink是一个数据接收器类,用于将处理后的数据存储到std:string对象中
                    // 将加密后的密文存储到 ciphertext 字符串中
                    new CryptoPP::StringSink(ciphertext),
                    // 使用 PKCS#7 填充方案,确保明文长度是块大小的整数倍
                    CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING
                )
            );

            // 将加密后的密文编码为十六进制字符串并返回
            return hexEncode(ciphertext);

        } catch (const CryptoPP::Exception& e) { // 处理crypto++库相关异常
            std::throw_with_nested(std::runtime_error("Crypto++ error: " + std::string(e.what())));
        } catch (const std::exception& e) {
            std::cerr << "Standard Exception: " << e.what() << std::endl;
            throw;
        }
    }
}

解密

namespace SymCryptoUtilities {

    bool isValidHex(const std::string& hexStr) {
        if (hexStr.empty()) return false;
        for (char c : hexStr) {
            if (!std::isxdigit(c)) return false;
        }
        return true;
    }

    std::string hexDecode(const std::string& hexStr) {
        if (hexStr.length() % 2 != 0) {
            throw std::invalid_argument("Hex string must have even length");
        }

        std::string decoded;
        CryptoPP::StringSource ss(
            hexStr, true,
            new CryptoPP::HexDecoder(
                new CryptoPP::StringSink(decoded)
            )
        );
        return decoded;
    }

    std::string hexEncode(const std::string& data) {
        std::string encoded;
        CryptoPP::StringSource ss(
            data, true,
            new CryptoPP::HexEncoder(
                new CryptoPP::StringSink(encoded),
                false
            )
        );
        return encoded;
    }

    // DES-CBC解密核心实现
    std::string desCBCDecrypt(const std::string& ciphertextHex, 
                             const std::string& key, 
                             const std::string& iv) {
        try {
            // 参数验证
            if (key.size() != CryptoPP::DES::DEFAULT_KEYLENGTH) {
                throw std::invalid_argument("Invalid key size. Expected 8 bytes");
            }
            if (iv.size() != CryptoPP::DES::BLOCKSIZE) {
                throw std::invalid_argument("Invalid IV size. Expected 8 bytes");
            }
            if (!isValidHex(ciphertextHex)) {
                throw std::invalid_argument("Invalid hexadecimal ciphertext");
            }

            // 解码十六进制密文
            const std::string ciphertext = hexDecode(ciphertextHex);

            // 检查密文长度有效性
            if (ciphertext.empty() || (ciphertext.size() % CryptoPP::DES::BLOCKSIZE != 0)) {
                throw std::invalid_argument("Invalid ciphertext length");
            }

            // 设置解密参数
            CryptoPP::CBC_Mode<CryptoPP::DES>::Decryption decryptor;
            decryptor.SetKeyWithIV(
                reinterpret_cast<const CryptoPP::byte*>(key.data()), key.size(),
                reinterpret_cast<const CryptoPP::byte*>(iv.data()), iv.size()
            );

            // 解密流程
            std::string decrypted;
            CryptoPP::StringSource ss(
                ciphertext, true,
                new CryptoPP::StreamTransformationFilter(
                    decryptor,
                    new CryptoPP::StringSink(decrypted),
                    CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING
                )
            );

            return decrypted;

        } catch (const CryptoPP::Exception& e) {
            std::throw_with_nested(std::runtime_error("Crypto++ error: " + std::string(e.what())));
        } catch (const std::exception&) {
            throw;
        }
    }
}

 主函数

int main(int argc, char* argv[]) {
    if (argc != 4) {
        std::cerr << "Usage: " << argv[0] << " <ciphertext_hex> <hex_key> <hex_iv>\n"
                  << "Example: " << argv[0] << " A1B2C3D4E5F6 0123456789ABCDEF FEDCBA9876543210\n"
                  << "Note:\n"
                  << "  - Key and IV must be 16-character hexadecimal strings (8 bytes)\n"
                  << "  - Ciphertext must be hexadecimal format"
                  << std::endl;
        return 1;
    }

    const std::string ciphertextHex = argv[1];
    const std::string keyHex        = argv[2];
    const std::string ivHex         = argv[3];

    try {
        // 输入验证
        if (keyHex.length() != 16 || !SymCryptoUtilities::isValidHex(keyHex)) {
            throw std::invalid_argument("Key must be 16-character hex string (8 bytes)");
        }
        if (ivHex.length() != 16 || !SymCryptoUtilities::isValidHex(ivHex)) {
            throw std::invalid_argument("IV must be 16-character hex string (8 bytes)");
        }
        if (ciphertextHex.empty()) {
            throw std::invalid_argument("Ciphertext cannot be empty");
        }

        // 十六进制解码
        const std::string key = SymCryptoUtilities::hexDecode(keyHex);
        const std::string iv  = SymCryptoUtilities::hexDecode(ivHex);

        // 执行解密
        const std::string plaintext = SymCryptoUtilities::desCBCDecrypt(ciphertextHex, key, iv);
        
        std::cout << "Decrypted plaintext: " << plaintext << std::endl;
} catch (const std::exception& e) {
        std::cerr << "Error: ";
        try {
            std::rethrow_if_nested(e);
        } catch (const std::exception& nested) {
            std::cerr << nested.what() << std::endl;
            return 2;
        }
        std::cerr << e.what() << std::endl;
        return 1;
    }

    return 0;
}

WIN平台主函数

int main(int argc, char* argv[]) {
    // 设置控制台编码为UTF-8
    #ifdef _WIN32
    SetConsoleOutputCP(CP_UTF8);
    #endif

    if (argc != 4) {
    ...
    ...
    ...
}

运行

g++ DES64-CBC-encrypt.cpp -o encrypt -lcryptopp 

g++ DES64-CBC-decrypt.cpp -o decrypt -lcryptopp

测试 

最近做一个接口,与JAVA的关于DES/CBC/PKCS5Padding 互相解密。在网上找了很多资料,摸索了3天才摸索出来。同样的明文,用JAVA加密的密文死活都跟用DELPHI加密的不相等,有时候少于8个字符的就正常,多了8个字符的就有问题,原来是有个7把7改成8就可以了。害人啊,, function EncryDes(const str:string;const keystr:string;const ivstr:string):string ; var key:tkey64; Context:TDESContext; Block,iv:TDESBlock; i,j,len,posnum:smallint; poschar,xx:char; xuhuan:integer; begin for i:=0 to 7 do begin if i > (length(keystr)-1) then key[i] :=0 else key[i] := byte(keystr[i+1]); end; for i:=0 to 7 do begin if i > (length(ivstr)-1) then iv[i]:=0 else iv[i] := byte(ivstr[i+1]); end; InitEncryptDES(Key, Context, true); len := length(AnsiString(str)); xx:= char( 8- (len mod 8)); if len<=8 then xuhuan:=0 else xuhuan:=round(len/8); for i:=0 to xuhuan do begin for j:=0 to 7 do begin if ((i*8+j+1)<=len) then //关键这一步,网上好多参考资料都是((i*7+j+1)<=len),而不是((i*8+j+1)<=len) 害人啊,害得我摸索了3天,,哎 begin poschar:=str[i*8+j+1]; block[j]:=byte(poschar); end else block[j]:=byte(xx); end; EncryptDESCBC(Context, IV, Block); for j:= 0 to 7 do begin posnum:=block[j]; result := result + inttohex(posnum,2); end; iv:=block; end; end; //完整代码如下 unit dmdes; {*********************************************************} {* DELPHI、PHP、C#通用DES编码解码单元 *} {* 由TurboPower LockBox部分代码改写 *} {* 滕州市东鸣软件工作室制作 ZWF 2011-12-27 *} {*********************************************************} {EncryDes为编码函数,DecryDes为解码函数,keystr为密码,ivstr为偏移量, 一般设置keystr,ivstr相同,内容为八位字节长度的字符串,编码结果为十六进制字串} interface uses Windows,SysUtils; type PKey64 = ^TKey64; TKey64 = array [0..7] of Byte; type TDESBlock = array[0..7] of Byte; TDESContext = packed record TransformedKey : array [0..31] of LongInt; Encrypt : Boolean; end; function EncryDes(const str:string;const keystr:string;const ivstr:string):string ; function DecryDes(const str:string;const keystr:string;const ivstr:string):string ; function DecryDessec(const str:string;const keystr:string;const ivstr:string):string ; implementation procedure XorMemPrim(var Mem1; const Mem2; Count : Cardinal); register; asm push esi push edi mov esi, eax //esi = Mem1 mov edi, edx //edi = Mem2 push ecx //save byte count shr ecx, 2 //convert to dwords jz @Continue cld @Loop1: //xor dwords at a time mov eax, [edi] xor [esi], eax add esi, 4 add edi, 4 dec ecx jnz @Loop1 @Continue: //handle remaining bytes (3 or less) pop ecx and ecx, 3 jz @Done @Loop2: //xor remaining bytes mov al, [edi] xor [esi], al inc esi inc edi dec ecx jnz @Loop2 @Done: pop edi pop esi end; { -------------------------------------------------------------------------- } procedure XorMem(var Mem1; const Mem2; Count : Cardinal); begin XorMemPrim(Mem1, Mem2, Count); end; { -------------------------------------------------------------------------- } procedure EncryptDES(const Context : TDESContext; var Block : TDESBlock); const SPBox : array [0..7, 0..63] of DWord = (($01010400, $00000000, $00010000, $01010404, $01010004, $00010404, $00000004, $00010000, $00000400, $01010400, $01010404, $00000400, $01000404, $01010004, $01000000, $00000004, $00000404, $01000400, $01000400, $00010400, $00010400, $01010000, $01010000, $01000404, $00010004, $01000004, $01000004, $00010004, $00000000, $00000404, $00010404, $01000000, $00010000, $01010404, $00000004, $01010000, $01010400, $01000000, $01000000, $00000400, $01010004, $00010000, $00010400, $01000004, $00000400, $00000004, $01000404, $00010404, $01010404, $00010004, $01010000, $01000404, $01000004, $00000404, $00010404, $01010400, $00000404, $01000400, $01000400, $00000000, $00010004, $00010400, $00000000, $01010004), ($80108020, $80008000, $00008000, $00108020, $00100000, $00000020, $80100020, $80008020, $80000020, $80108020, $80108000, $80000000, $80008000, $00100000, $00000020, $80100020, $00108000, $00100020, $80008020, $00000000, $80000000, $00008000, $00108020, $80100000, $00100020, $80000020, $00000000, $00108000, $00008020, $80108000, $80100000, $00008020, $00000000, $00108020, $80100020, $00100000, $80008020, $80100000, $80108000, $00008000, $80100000, $80008000, $00000020, $80108020, $00108020, $00000020, $00008000, $80000000, $00008020, $80108000, $00100000, $80000020, $00100020, $80008020, $80000020, $00100020, $00108000, $00000000, $80008000, $00008020, $80000000, $80100020, $80108020, $00108000), ($00000208, $08020200, $00000000, $08020008, $08000200, $00000000, $00020208, $08000200, $00020008, $08000008, $08000008, $00020000, $08020208, $00020008, $08020000, $00000208, $08000000, $00000008, $08020200, $00000200, $00020200, $08020000, $08020008, $00020208, $08000208, $00020200, $00020000, $08000208, $00000008, $08020208, $00000200, $08000000, $08020200, $08000000, $00020008, $00000208, $00020000, $08020200, $08000200, $00000000, $00000200, $00020008, $08020208, $08000200, $08000008, $00000200, $00000000, $08020008, $08000208, $00020000, $08000000, $08020208, $00000008, $00020208, $00020200, $08000008, $08020000, $08000208, $00000208, $08020000, $00020208, $00000008, $08020008, $00020200), ($00802001, $00002081, $00002081, $00000080, $00802080, $00800081, $00800001, $00002001, $00000000, $00802000, $00802000, $00802081, $00000081, $00000000, $00800080, $00800001, $00000001, $00002000, $00800000, $00802001, $00000080, $00800000, $00002001, $00002080, $00800081, $00000001, $00002080, $00800080, $00002000, $00802080, $00802081, $00000081, $00800080, $00800001, $00802000, $00802081, $00000081, $00000000, $00000000, $00802000, $00002080, $00800080, $00800081, $00000001, $00802001, $00002081, $00002081, $00000080, $00802081, $00000081, $00000001, $00002000, $00800001, $00002001, $00802080, $00800081, $00002001, $00002080, $00800000, $00802001, $00000080, $00800000, $00002000, $00802080), ($00000100, $02080100, $02080000, $42000100, $00080000, $00000100, $40000000, $02080000, $40080100, $00080000, $02000100, $40080100, $42000100, $42080000, $00080100, $40000000, $02000000, $40080000, $40080000, $00000000, $40000100, $42080100, $42080100, $02000100, $42080000, $40000100, $00000000, $42000000, $02080100, $02000000, $42000000, $00080100, $00080000, $42000100, $00000100, $02000000, $40000000, $02080000, $42000100, $40080100, $02000100, $40000000, $42080000, $02080100, $40080100, $00000100, $02000000, $42080000, $42080100, $00080100, $42000000, $42080100, $02080000, $00000000, $40080000, $42000000, $00080100, $02000100, $40000100, $00080000, $00000000, $40080000, $02080100, $40000100), ($20000010, $20400000, $00004000, $20404010, $20400000, $00000010, $20404010, $00400000, $20004000, $00404010, $00400000, $20000010, $00400010, $20004000, $20000000, $00004010, $00000000, $00400010, $20004010, $00004000, $00404000, $20004010, $00000010, $20400010, $20400010, $00000000, $00404010, $20404000, $00004010, $00404000, $20404000, $20000000, $20004000, $00000010, $20400010, $00404000, $20404010, $00400000, $00004010, $20000010, $00400000, $20004000, $20000000, $00004010, $20000010, $20404010, $00404000, $20400000, $00404010, $20404000, $00000000, $20400010, $00000010, $00004000, $20400000, $00404010, $00004000, $00400010, $20004010, $00000000, $20404000, $20000000, $00400010, $20004010), ($00200000, $04200002, $04000802, $00000000, $00000800, $04000802, $00200802, $04200800, $04200802, $00200000, $00000000, $04000002, $00000002, $04000000, $04200002, $00000802, $04000800, $00200802, $00200002, $04000800, $04000002, $04200000, $04200800, $00200002, $04200000, $00000800, $00000802, $04200802, $00200800, $00000002, $04000000, $00200800, $04000000, $00200800, $00200000, $04000802, $04000802, $04200002, $04200002, $00000002, $00200002, $04000000, $04000800, $00200000, $04200800, $00000802, $00200802, $04200800, $00000802, $04000002, $04200802, $04200000, $00200800, $00000000, $00000002, $04200802, $00000000, $00200802, $04200000, $00000800, $04000002, $04000800, $00000800, $00200002), ($10001040, $00001000, $00040000, $10041040, $10000000, $10001040, $00000040, $10000000, $00040040, $10040000, $10041040, $00041000, $10041000, $00041040, $00001000, $00000040, $10040000, $10000040, $10001000, $00001040, $00041000, $00040040, $10040040, $10041000, $00001040, $00000000, $00000000, $10040040, $10000040, $10001000, $00041040, $00040000, $00041040, $00040000, $10041000, $00001000, $00000040, $10040040, $00001000, $00041040, $10001000, $00000040, $10000040, $10040000, $10040040, $10000000, $00040000, $10001040, $00000000, $10041040, $00040040, $10000040, $10040000, $10001000, $10001040, $00000000, $10041040, $00041000, $00041000, $00001040, $00001040, $00040040, $10000000, $10041000)); var I, L, R, Work : DWord; CPtr : PDWord; procedure SplitBlock(const Block : TDESBlock; var L, R : DWord); register; asm push ebx push eax mov eax, [eax] mov bh, al mov bl, ah rol ebx, 16 shr eax, 16 mov bh, al mov bl, ah mov [edx], ebx pop eax mov eax, [eax+4] mov bh, al mov bl, ah rol ebx, 16 shr eax, 16 mov bh, al mov bl, ah mov [ecx], ebx pop ebx end; procedure JoinBlock(const L, R : LongInt; var Block : TDESBlock); register; asm push ebx mov bh, al mov bl, ah rol ebx, 16 shr eax, 16 mov bh, al mov bl, ah mov [ecx+4], ebx mov bh, dl mov bl, dh rol ebx, 16 shr edx, 16 mov bh, dl mov bl, dh mov [ecx], ebx pop ebx end; procedure IPerm(var L, R : DWord); var Work : DWord; begin Work := ((L shr 4) xor R) and $0F0F0F0F; R := R xor Work; L := L xor Work shl 4; Work := ((L shr 16) xor R) and $0000FFFF; R := R xor Work; L := L xor Work shl 16; Work := ((R shr 2) xor L) and $33333333; L := L xor Work; R := R xor Work shl 2; Work := ((R shr 8) xor L) and $00FF00FF; L := L xor Work; R := R xor Work shl 8; R := (R shl 1) or (R shr 31); Work := (L xor R) and $AAAAAAAA; L := L xor Work; R := R xor Work; L := (L shl 1) or (L shr 31); end; procedure FPerm(var L, R : DWord); var Work : DWord; begin L := L; R := (R shl 31) or (R shr 1); Work := (L xor R) and $AAAAAAAA; L := L xor Work; R := R xor Work; L := (L shr 1) or (L shl 31); Work := ((L shr 8) xor R) and $00FF00FF; R := R xor Work; L := L xor Work shl 8; Work := ((L shr 2) xor R) and $33333333; R := R xor Work; L := L xor Work shl 2; Work := ((R shr 16) xor L) and $0000FFFF; L := L xor Work; R := R xor Work shl 16; Work := ((R shr 4) xor L) and $0F0F0F0F; L := L xor Work; R := R xor Work shl 4; end; begin SplitBlock(Block, L, R); IPerm(L, R); CPtr := @Context; for I := 0 to 7 do begin Work := (((R shr 4) or (R shl 28)) xor CPtr^); Inc(CPtr); L := L xor SPBox[6, Work and $3F]; L := L xor SPBox[4, Work shr 8 and $3F]; L := L xor SPBox[2, Work shr 16 and $3F]; L := L xor SPBox[0, Work shr 24 and $3F]; Work := (R xor CPtr^); Inc(CPtr); L := L xor SPBox[7, Work and $3F]; L := L xor SPBox[5, Work shr 8 and $3F]; L := L xor SPBox[3, Work shr 16 and $3F]; L := L xor SPBox[1, Work shr 24 and $3F]; Work := (((L shr 4) or (L shl 28)) xor CPtr^); Inc(CPtr); R := R xor SPBox[6, Work and $3F]; R := R xor SPBox[4, Work shr 8 and $3F]; R := R xor SPBox[2, Work shr 16 and $3F]; R := R xor SPBox[0, Work shr 24 and $3F]; Work := (L xor CPtr^); Inc(CPtr); R := R xor SPBox[7, Work and $3F]; R := R xor SPBox[5, Work shr 8 and $3F]; R := R xor SPBox[3, Work shr 16 and $3F]; R := R xor SPBox[1, Work shr 24 and $3F]; end; FPerm(L, R); JoinBlock(L, R, Block); end; procedure InitEncryptDES(const Key : TKey64; var Context : TDESContext; Encrypt : Boolean); const PC1 : array [0..55] of Byte = (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); PC2 : array [0..47] of Byte = (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, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31); CTotRot : array [0..15] of Byte = (1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28); CBitMask : array [0..7] of Byte = (128, 64, 32, 16, 8, 4, 2, 1); var PC1M : array [0..55] of Byte; PC1R : array [0..55] of Byte; KS : array [0..7] of Byte; I, J, L, M : LongInt; begin {convert PC1 to bits of key} for J := 0 to 55 do begin L := PC1[J]; M := L mod 8; PC1M[J] := Ord((Key[L div 8] and CBitMask[M]) 0); end; {key chunk for each iteration} for I := 0 to 15 do begin {rotate PC1 the right amount} for J := 0 to 27 do begin L := J + CTotRot[I]; if (L (length(keystr)-1) then key[i] :=0 else key[i] := byte(keystr[i+1]); end; for i:=0 to 7 do begin if i > (length(ivstr)-1) then iv[i]:=0 else iv[i] := byte(ivstr[i+1]); end; InitEncryptDES(Key, Context, true); len := length(AnsiString(str)); xx:= char( 8- (len mod 8)); if len<=8 then xuhuan:=0 else xuhuan:=round(len/8); for i:=0 to xuhuan do begin for j:=0 to 7 do begin if ((i*8+j+1) (length(temp)-1) then key[i] :=0 else key[i] := byte(temp[i+1]); end; temp := ivstr; for i:=0 to 7 do begin if i > (length(temp)-1) then iv[i] := 0 else iv[i] := byte(temp[i+1]); end; InitEncryptDES(Key, Context, False); temp := str; posnum := 0; for i:=0 to length(temp)-1 do begin Block[posnum] := byte(temp[i+1]); posnum := posnum+1; if posnum = 8 then begin bak := block; EncryptDESCBC(Context, IV, Block); for j:= 0 to 7 do begin // temp := temp+inttostr(byte(block[i]))+' '; res := res + char(block[j]); end; iv := bak; posnum := 0; end; end; if posnum 0 then begin // end else begin temp:=''; for i:= 1 to length(res) do begin temp := temp+char(res[i]); end; Result:= trim(temp); end; end; function DecryDes(const str:string;const keystr:string;const ivstr:string):string ; var key:tkey64; Context:TDESContext; bak,Block,iv:TDESBlock; i,j,len,posnum:smallint; poschar,xx:char; res,lss:string; begin for i:=0 to 7 do begin if i > (length(keystr)-1) then key[i] :=0 else key[i] := byte(keystr[i+1]); end; for i:=0 to 15 do begin if i > (length(ivstr)-1) then iv[i]:=0 else iv[i] := byte(ivstr[i+1]); end; InitEncryptDES(Key, Context, false); res:=''; for j:= 0 to (length(str) div 2)-1 do begin lss:=copy(str,j*2+1,2); res:=res+ char(StrToInt('$'+lss)) ; end; len := length(AnsiString(res)); for i:=0 to round(len/8)-1 do begin for j:=0 to 7 do begin if ((i*7+j+1)<=len) then begin poschar:=res[i*8+j+1]; block[j]:=byte(poschar); end else begin block[j]:=byte(xx); end; end; bak:=block; EncryptDESCBC(Context, IV, Block); for j:= 0 to 7 do begin result := result + char(block[j]); end; iv:=bak; end; end; end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值