Вопрос о том, какой шаблон дизайна использовать - PullRequest
2 голосов
/ 23 июня 2010

Дано два класса:

Первый класс выполняет шифрование / дешифрование AES и возвращает зашифрованные / дешифрованные данные с определенным ключом и цепочкой.

Второй класс собирает данные для шифрования и затем передает их в класс шифрования / дешифрования.

Правильно ли спроектировать непосредственный вызов класса шифрования из класса, который собирает данные, или между двумя классами должен существовать объект, который далее абстрагирует процесс? Должен ли я иметь один экземпляр абстрактного класса и один экземпляр шифрования для обработки всех этих типов запросов в течение времени жизни программы?

Ответы [ 2 ]

3 голосов
/ 23 июня 2010

Лично я бы создал некоторый абстрактный интерфейс, представляющий алгоритм шифрования, с заводской функцией, берущей ключ и производящей конкретный экземпляр алгоритма шифрования с установленным ключом. Таким образом, «второй класс» здесь будет обращаться напрямую к «первому классу», но будет «третий класс», отвечающий за создание экземпляра класса. Что-то вроде:

/* Core encryption framework definitions */
class CipherInstance {
  // ...
  public:
    virtual void encrypt(void *, size_t) = 0;
    virtual void decrypt(void *, size_t) = 0;
    virtual size_t blocksize() const = 0;
// ...
    virtual ~CipherInstance() { }
};

class Cipher {
  public:
    virtual CipherInstance *instantiate(const void *key, size_t keylen) = 0;
    virtual size_t minkeysize() const = 0;
    virtual size_t maxkeysize() const = 0;
};

/* AES implementation */
class privateAESImpl : public Cipher { /* ... */ };
// This is the only public definition in the AES implementation. The privateAESImpl
// class is a stateless singleton, and this is the only instance. Doing this instead
// of static functions allows AES to be passed to a function taking a Cipher * 
extern privateAESImpl AES;

// Much later:
  CipherInstance *aes = AES.instantiate(key, keylen);
  aes->encrypt(data, datalen);
// or, to be more general:
void frob(Cipher *cipher, void *key, size_t keylen, void *data, size_t datalen) {
    CipherInstance *inst = cipher->instantiate(key, keylen);
    inst->encrypt(data, datalen);
}
Библиотеки

C # System.Security.Cryptography используют аналогичный подход - см., Например, System.Security.Cryptography.SymmetricAlgorithm. Однако обратите внимание, что, поскольку C # поддерживает самоанализ, нет необходимости в фабричном классе - вместо этого есть просто статический метод, принимающий имя. В C ++ необходим полный фабричный класс.

1 голос
/ 23 июня 2010

Я бы назвал объект шифрования напрямую, но через интерфейс.Фактический объект шифрования, который нужно вызвать, будет предоставлен во время выполнения любым классом, управляющим программой.

Вы должны извинить меня, мой C ++ ржавый ...

// Interface for encryption.
class Encryptor
{
    public:
        virtual byte* encrypt(byte* data) = 0;
}

// Gathering class
class Gatherer
{
    private:
        Encryptor* encryptor;
    public:
        Gatherer(Encryptor* encryptor)
        {
            this->encryptor = encryptor;
        }

        void doStuff()
        {
            // Do stuff

            // Call encryption on gathered data
            byte* encryptedData = encryptor->encrypt(data);

            // Do more stuff with encrypted data.
        }
}

main()
{
    Encryptor* encryptor = new AESEncryptor(ENCRYPTION_KEY);
    Gatherer gatherer = new Gatherer(encryptor);
    gatherer->doStuff();
}
}
...