对称密码

来源:互联网 发布:慈溪行知职高地址全称 编辑:程序博客网 时间:2024/05/20 11:47

概念介绍

对称密码就是加密和解密使用同一个key
对称密码算法有很多,但是现在只有AES (Advanced Encryption Standard) 是最常用的,其它像 DES, 3DES 等都已淘汰

AES是一种块密码算法,块密码算法只能对固定长度的数据进行加密,例如:AES的块长度是128位,即16字节。AES算法将一个明文块加密生成一个密文块,密文快的长度跟明文块相等,都为16字节。
如果要加密的数据比16字节长,就要进行分块加密,然后将密文块组合成完整的密文。
分块加密并组合有多种方法,称为mode。主要模式有ecb, cbc, cfb, ofb, ctr 等,但是最常用的只有两种:即 cbc 和 ctr,其它都已淘汰

代码

为方便使用,下面对苹果平台提供的对称密码库做个封装

头文件:Aes.h

#ifndef Aes_h#define Aes_h#include <stdint.h>#include <vector>class Aes final {public:    enum struct Mode {        Cbc,        Ctr,    };    enum struct Operation {        Encrypt,        Decrypt,    };    enum {        KeySize128 = 16,        KeySize192 = 24,        KeySize256 = 32,    };public:    typedef std::vector<uint8_t> Data;public:    static Data encrypt_cbc_128(const Data &data, const uint8_t (&key)[KeySize128], const uint8_t (&iv)[16]);    static Data decrypt_cbc_128(const Data &data, const uint8_t (&key)[KeySize128], const uint8_t (&iv)[16]);public:    ~Aes();    Aes(Operation op, Mode mode, const uint8_t (&key)[KeySize128], const uint8_t (&iv)[16]);    Aes(Operation op, Mode mode, const uint8_t (&key)[KeySize192], const uint8_t (&iv)[16]);    Aes(Operation op, Mode mode, const uint8_t (&key)[KeySize256], const uint8_t (&iv)[16]);    Aes(Aes &&aes) noexcept;    Aes &operator=(Aes &&aes) noexcept;    Data update(const Data &data);    Data final();    void reset();private:    struct AesImpl *_impl = nullptr;};#endif /* Aes_h */

实现文件:Aes.cpp

#include "Aes.h"#include <CommonCrypto/CommonCryptor.h>#include <assert.h>struct AesImpl final {public:    ~AesImpl()    {        CCCryptorRelease(_cryptor);    }    AesImpl(Aes::Operation op, Aes::Mode mode, const void *key, size_t keyLength, const void *iv)    {        CCCryptorCreateWithMode(_operation(op), _mode(mode), kCCAlgorithmAES, ccPKCS7Padding, iv, key, keyLength, nullptr, 0, 0, 0, &_cryptor);    }    Aes::Data update(const Aes::Data &data)    {        size_t len = CCCryptorGetOutputLength(_cryptor, data.size(), false);        Aes::Data buf(len);        size_t size = 0;        CCCryptorUpdate(_cryptor, data.data(), data.size(), buf.data(), buf.size(), &size);        return buf;    }    Aes::Data final()    {        Aes::Data buf(kCCBlockSizeAES128);        size_t size = 0;        CCCryptorFinal(_cryptor, buf.data(), buf.size(), &size);        buf.resize(size);        return buf;    }    void reset()    {        CCCryptorReset(_cryptor, nullptr);    }private:    constexpr CCOperation _operation(Aes::Operation op) const    {        switch (op) {        case Aes::Operation::Encrypt:            return kCCEncrypt;        case Aes::Operation::Decrypt:            return kCCDecrypt;        }    }    constexpr CCMode _mode(Aes::Mode mode) const    {        switch (mode) {        case Aes::Mode::Cbc:            return kCCModeCBC;        case Aes::Mode::Ctr:            return kCCModeCTR;        }    }private:    CCCryptorRef _cryptor = nullptr;};#pragma mark -Aes::~Aes(){    delete _impl;}Aes::Aes(Operation op, Mode mode, const uint8_t (&key)[KeySize128], const uint8_t (&iv)[16])    : _impl(new AesImpl(op, mode, key, KeySize128, iv)){}Aes::Aes(Operation op, Mode mode, const uint8_t (&key)[KeySize192], const uint8_t (&iv)[16])    : _impl(new AesImpl(op, mode, key, KeySize192, iv)){}Aes::Aes(Operation op, Mode mode, const uint8_t (&key)[KeySize256], const uint8_t (&iv)[16])    : _impl(new AesImpl(op, mode, key, KeySize256, iv)){}Aes::Aes(Aes &&aes) noexcept : _impl(aes._impl){    aes._impl = nullptr;}Aes &Aes::operator=(Aes &&aes) noexcept{    assert(&aes != this);    delete _impl;    _impl = aes._impl;    aes._impl = nullptr;    return *this;}Aes::Data Aes::update(const Data &data){    return _impl->update(data);}Aes::Data Aes::final(){    return _impl->final();}void Aes::reset(){    return _impl->reset();}Aes::Data Aes::encrypt_cbc_128(const Data &data, const uint8_t (&key)[KeySize128], const uint8_t (&iv)[16]){    Data buf;    Aes aes(Operation::Encrypt, Mode::Cbc, key, iv);    auto u = aes.update(data);;    buf.insert(buf.end(), u.cbegin(), u.cend());    auto f = aes.final();    buf.insert(buf.end(), f.cbegin(), f.cend());    return buf;}Aes::Data Aes::decrypt_cbc_128(const Data &data, const uint8_t (&key)[KeySize128], const uint8_t (&iv)[16]){    Data buf;    Aes aes(Operation::Decrypt, Mode::Cbc, key, iv);    auto u = aes.update(data);;    buf.insert(buf.end(), u.cbegin(), u.cend());    auto f = aes.final();    buf.insert(buf.end(), f.cbegin(), f.cend());    return buf;}

示例:main.cpp

#include <iostream>#include <stdio.h>#include <stdarg.h>#include <string>#include <vector>#include <algorithm>#include <numeric>#include "Aes.h"std::string format(const char *fmt, ...){    va_list ap;    va_start(ap, fmt);    int size = vsnprintf(nullptr, 0, fmt, ap) + 1;    va_end(ap);    char *buf = new char[size];    va_start(ap, fmt);    vsnprintf(buf, size, fmt, ap);    va_end(ap);    std::string fs(buf, size-1);    delete[] buf;    return fs;}std::string toHexString(const Aes::Data &data){    std::vector<std::string> svec;    std::transform(data.cbegin(), data.cend(), std::back_inserter(svec), [](auto byte) { return format("%02X", byte); });    return std::accumulate(svec.cbegin(), svec.cend(), std::string());}int main(){    const uint8_t key[16] = { 0xa5, 0xc0, 0xda, 0xb7, 0x87, 0x45, 0xc7, 0x37, 0x95, 0x07, 0x2C, 0x96, 0x67, 0xae, 0x28, 0xf1 };    const uint8_t iv[16] = { 0xdb, 0x32, 0x9a, 0x66, 0x09, 0x8b, 0x67, 0xf7, 0xb5, 0xa7, 0x9f, 0x38, 0x57, 0xb9, 0x25, 0x41 };    std::string msg = "hello, world";    Aes::Data data(msg.cbegin(), msg.cend());    auto enc = Aes::encrypt_cbc_128(data, key, iv);    std::cout << toHexString(enc) << std::endl;    auto dec = Aes::decrypt_cbc_128(enc, key, iv);    std::cout << std::string(dec.cbegin(), dec.cend()) << std::endl;}

运行输出:

$ ./a.outBC0B8E8AF2458A300E08A350B48EE793hello, world
原创粉丝点击