読者です 読者をやめる 読者になる 読者になる

C++ による RC4(Arcfour) 暗号化

暗号化 C++

ARCFOUR Algorithm」を C++ に移植したので紹介します.
以下に実装する関数 encrypt_rc4/decrypt_rc4 を用いればバイト列(std::vector)を暗号化/復号化できます.
RC4 については「RC4」をご覧下さい.
それでは以下に私の実装を示します.

rc4.hpp

#ifndef RC4_HPP_20100912_
#define RC4_HPP_20100912_

#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif


#include <vector>


namespace algorithm {
    void encrypt_rc4(const std::vector<unsigned char>& src, const std::vector<unsigned char>& key, std::vector<unsigned char>& dst);
    void decrypt_rc4(const std::vector<unsigned char>& src, const std::vector<unsigned char>& key, std::vector<unsigned char>& dst);
}


#endif

rc4.cpp

#include <algorithm>
#include <numeric>
#include "rc4.hpp"


namespace {
    class arcfour_context {
    public:
        explicit arcfour_context(const std::vector<unsigned char>& key) : x_(0), y_(0) {
            unsigned int state_index = 0;
            unsigned int key_index   = 0;

            std::iota(&state_[0], &state_[256], 0);

            for (int counter = 0; counter < 256; ++counter) {
                state_index = (state_index + key[key_index] + state_[counter]) & 0xFF;
                (std::swap)(state_[state_index], state_[counter]);
                if (++key_index >= key.size()) {
                    key_index = 0;
                }
            }
        }

        unsigned char operator()() {
            unsigned int x  = (x_ + 1        ) & 0xFF;
            unsigned int y  = (y_ + state_[x]) & 0xFF;

            x_ = x;
            y_ = y;
            (std::swap)(state_[x], state_[y]);

            return state_[(state_[x] + state_[y]) & 0xFF];
        }

    private:
        unsigned int  x_;
        unsigned int  y_;
        unsigned char state_[256];
    };
}


void algorithm::encrypt_rc4(const std::vector<unsigned char>& src, const std::vector<unsigned char>& key, std::vector<unsigned char>& dst)
{
    arcfour_context            context(key);
    std::vector<unsigned char> cdst;

    for (std::size_t i = 0; i < src.size(); ++i) {
        cdst.push_back(src[i] ^ context());
    }

    dst = std::move(cdst);
}


void algorithm::decrypt_rc4(const std::vector<unsigned char>& src, const std::vector<unsigned char>& key, std::vector<unsigned char>& dst)
{ encrypt_rc4(src, key, dst); }

rc4.cpp に RC4 暗号化/復号化をする関数 encrypt_rc4/decrypt_rc4 を実装しました.rc4.cpp をプロジェクトに加え(他のソースコードと一緒にコンパイル),rc4.hpp を include することにより encrypt_rc4/decrypt_rc4 が使用可能になります.
以下のテストコードで encrypt_rc4/decrypt_rc4 の動作を確認できます.

test.cpp

#include <cassert>
#include "rc4.hpp"


int main()
{
    std::vector<unsigned char> key;

    key.push_back(0x61);
    key.push_back(0x8a);
    key.push_back(0x63);
    key.push_back(0xd2);
    key.push_back(0xfb);

    std::vector<unsigned char> plain;

    plain.push_back(0xdc);
    plain.push_back(0xee);
    plain.push_back(0x4c);
    plain.push_back(0xf9);
    plain.push_back(0x2c);

    std::vector<unsigned char> cipher, dst;

    algorithm::encrypt_rc4(plain, key, cipher); // plain を key で暗号化
    algorithm::decrypt_rc4(cipher, key, dst); // 暗号化した cipher を key で復号化

    assert(plain.size() == dst.size());
    for (std::size_t i = 0; i < plain.size(); ++i) {
        assert(plain[i] == dst[i]);
    }

    return 0;
}

以上です.
非常に単純な記事ですが,少しでもお役に立てると幸いです.