0

ですから、私には少し変わった状況があります。テンプレートとチュートリアルでの私の経験はカバーしていないようです。

能力がないがAPIが制限されている別のプログラムのメッセージに自動的に署名するプログラムを書いています。メッセージに署名するために使用するハッシュをプログラムに指示する文字列を含む構成ファイルがあります。この文字列は、ダイジェスト、ダイジェストのサイズ、およびダイジェストのエンコードに関するいくつかのオプションを格納するsignatureAlgorithmオブジェクトに格納されます。ハッシュ関数にCrypto++ライブラリを使用しています。現在、以下に示すように、文字列がアルゴリズムの内容に応じて、if / elseifステートメントと3つのコマンドの大規模なセットがあります。

void signatureAlgorithm::createDigest(string input)
{
bool digestFail = false;

if (_algorithm == "md5")
{
    //byte digest[ CryptoPP::MD5::DIGESTSIZE ];
    _digestSize = (CryptoPP::MD5::DIGESTSIZE);
    _digest = new byte[ _digestSize ];
    CryptoPP::MD5().CalculateDigest( _digest, (byte*) input.c_str(), input.length() );
}

.....

else if (_algorithm == "sha256")
{
    _digestSize = (CryptoPP::SHA256::DIGESTSIZE);
    _digest = new byte[ _digestSize ];
    CryptoPP::SHA256().CalculateDigest( _digest, (byte*) input.c_str(), input.length() );
}
else if (_algorithm == "sha512")
{
    _digestSize = (CryptoPP::SHA512::DIGESTSIZE);
    _digest = new byte[ _digestSize ];
    CryptoPP::SHA512().CalculateDigest( _digest, (byte*) input.c_str(), input.length() );
}
else
    digestFail = true;

if (!digestFail)
    _ready = true;
else
    _ready = false;
}

_digestSizeは、ダイジェストのバイトに対して_digestが行うように、オブジェクトにダイジェストサイズを格納します(バイトはtypedef const unsigned char *)。 、または代わりにプログラムにエラーを返します。

最終的には、より効率的で整理されたものにするためにマップに切り替える予定ですが、その前に、_digestSizeの設定とCreateDigest()の呼び出しをより一般的にする方法を見つける必要があります。最終リリースでコンパイルされた形式でCrypto++のFIPSステータスを維持したいので、ライブラリの変更を避けようとしていますが、今のところ、違いが生じるかどうかをソースを使用してテストしています。

各ifステートメントの内側のセクションで値を設定するだけのテンプレートについて考えましたが、そのような方法で使用されているテンプレートの例を見つけることができません。他の関数があるクラスを作成するためにそれらを見つけますが、この場合、ここで考えているのであれば、単に別のクラスを指すジェネリッククラスを作成できる必要があります。

私がやろうとしていることの擬似コード:

class tempClass {};

if (_algorithm == "md5")
{
  tempClass = CryptoPP::MD5
}
......
else
  digestFail = true;

_digestSize = (tempClass::DIGESTSIZE);
_digest = new byte[_digestSize];
tempClass().CalculateDigest( _digest, (byte*) input.c_str(), input.length() );

-ジミー

編集:コメントの中で、クラスツリーの分岐のために継承は機能しないと述べましたが、私が使用しているドキュメントは最新バージョンのものであることがわかりました。私がテストに使用しているバージョンとFIPSバージョンは、MD5などの機能が別の「弱い」構造に分割される前から古いものです。

編集2:しかし、クラスがフォークされ、同じ場所からCalculateDigestを継承していなくても、これを回避する方法があるかどうかについてはまだ興味があります。

編集3:ジョン・バンデラが質問に答えましたが、私は彼が私にくれたものを少し変更する必要がありました。回答のコメントに変更があります。皆さんありがとう!

4

2 に答える 2

0

コードを次のようなテンプレート関数に分割します

//_digestと_digestsizeがクラスメンバーであると仮定します。

template<class Digest>
byte* doDigest(string input, int& digestSize){
        int digestSize = (Digest::DIGESTSIZE);
        byte* digest = new byte[ digestSize ];
        Digest().CalculateDigest( digest, (byte*) input.c_str(), input.length() );
        return digest;
 }

次に、createDigest関数でこれを行います

if (_algorithm == "md5")
{
    _digest = doDigest<CryptoPP::MD5>(input,_digestSize);
}

else if (_algorithm == "sha256")
{
    _digest = doDigest<CryptoPP::SHA256>(input,_digestSize);
}
...

トピックから外れていますが、バイトの代わりにベクトルの使用を検討することをお勧めします*

于 2012-11-28T20:01:18.550 に答える
0

これを行う別の方法ですが、より多くのテンプレートメタプログラミングを使用します

完全に実行可能な例については、を参照してください。

https://gist.github.com/4164700

template<class Digest, class... T>
struct DigestMatcher{
    template<class U, class ... V>
    static byte* doDigest(std::string input, int& digestSize,std::string algorithm,U firstalgorithm, U nextalgorithm, V... algorithms){
    if(algorithm==firstalgorithm){
        return doDigest(input,digestSize);
    }
    else{
        return DigestMatcher<T...>::doDigest(input,digestSize,algorithm,nextalgorithm,algorithms...);

    }
}

template<class U>
static byte* doDigest(std::string input, int& digestSize,std::string algorithm, U firstalgorithm){
    if(algorithm==firstalgorithm){
        return doDigest(input,digestSize);
    }
    else{
        std::cout << algorithm << " invalid" << std::endl;
        return 0;
    }
}

static byte* doDigest(std::string input, int& digestSize){

        // Cout for debug purposes
        std::cout << "using " << typeid(Digest).name() << std::endl;
        digestSize = Digest::DIGESTSIZE;
        byte* digest = new byte[ digestSize ];
        Digest().CalculateDigest( digest, (byte*) input.c_str(), input.length() );
        return digest;
}

};

次に、あなたの呼び出しコードのために

void signatureAlgorithm::createDigest(std::string input)
{
    _digest = DigestMatcher<MD5,SHA256,SHA512>::doDigest(input,_digestSize,_algorithm,"md5","sha256","sha512");
    if(_digest)
        _ready = true;
    else
    _ready = false;
}
于 2012-11-28T21:35:04.537 に答える