DES-CFB加密和解密模式

问题

加密

    输入:<plaintext> <key> <iv>
 
    输出:<ciphertext>
 
    例如
 
    输入:<i love you, sunsiqi> <0123456789ABCDEF> <FEDCBA0123456789>
 
    输出:<4e152ec964f73950dfc7a3d833bdaeffd6f0b8a727c13c29>

解密

      输入:<ciphertext> <key> <iv>
 
      输出:<plaintext>
 
      例如
 
      输入:<4e152ec964f73950dfc7a3d833bdaeffd6f0b8a727c13c29> <0123456789ABCDEF> <FEDCBA0123456789>
 
      输出:<i love you, sunsiqi>

特性

  • CFB模式不需要进行明文填充处理 
  • 明文与密文长度保持1:1对应

特性CBC模式CFB模式
是否需要填充需要PKCS#7填充无需填充
数据长度关系密文长度是块大小的倍数密文长度=明文长度
错误传播影响整个块只影响单个字节
典型应用场景文件加密实时通信
初始化向量要求必须唯一且不可预测必须唯一且不可预测

代码

头文件

#include <iostream>
#include <string>
#include <cctype>
#include <cryptopp/des.h>
#include <cryptopp/modes.h>
#include <cryptopp/filters.h>
#include <cryptopp/hex.h>
#include <stdexcept>

加密

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-CFB加密函数
    std::string desCFBEncrypt(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");
            }

            // 设置加密器
            CryptoPP::CFB_Mode<CryptoPP::DES>::Encryption encryptor;
            encryptor.SetKeyWithIV(
                reinterpret_cast<const CryptoPP::byte*>(key.data()), key.size(),
                reinterpret_cast<const CryptoPP::byte*>(iv.data()), iv.size()
            );

            // 执行加密
            std::string ciphertext;
            CryptoPP::StringSource ss(
                plaintext, true,
                //流模式无需填充
                new CryptoPP::StreamTransformationFilter(
                    encryptor,
                    new CryptoPP::StringSink(ciphertext)) //无填充参数
            );

            return hexEncode(ciphertext);

        } catch (const CryptoPP::Exception& e) {
            std::throw_with_nested(std::runtime_error("Crypto++错误: " + 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-CFB解密函数
    std::string desCFBDecrypt(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);

            // 设置解密器
            CryptoPP::CFB_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)
                )
            );

            return decrypted;

        } catch (const CryptoPP::Exception& e) {
            std::throw_with_nested(std::runtime_error("Crypto++错误: " + std::string(e.what())));
        }catch (const std::exception& e) {
            std::cerr << "Standard Exception: " << e.what() << std::endl;
            throw;
        }
    }
}

主函数

int main(int argc, char* argv[]) {
    if (argc != 4) {
        if (argc != 4) {
        std::cerr << "Usage: " << argv[0] << " <plaintext> <hex_key> <hex_iv>\n"
                  << "Example: " << argv[0] << " \"SecretData\" 0123456789ABCDEF FEDCBA9876543210\n"
                  << "Note: Key and IV must be 16-character hexadecimal strings (8 bytes)\n"
                  << "Note: support arbitrary binary data such as Chinese characters\n"
                  << "Note: no padding is required when using the CFB mode."
                  << std::endl;
        return 1;
        }
    }

    const std::string plaintext = 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)");
        }

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

        // 执行加密
        const std::string ciphertext = SymCryptoUtilities::desCFBEncrypt(plaintext, key, iv);
        
        std::cout << "Ciphertext (hex): " << ciphertext << 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;
}

运行

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

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

测试

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值