"HMAC-SHA256 in Delphi"で前の質問のようにAmazon RESTサービスにアクセスする必要があります。これはD2010にしておく必要がありますので、私は、RFC 4231でテストベクタを渡すために、最新のlibeay32.dllを使用しようとしている:Delphi - HMAC-SHA256にRFC 4231テストベクトルを渡すことができません
http://tools.ietf.org/html/rfc4231
誰もがこのライブラリを使用して、Delphiで、これらのテストに合格する方法を持っています?私が参照した記事でshuntyが投稿したコードは、最初の2つのテストベクタと5番目のテストベクタを渡しますが、3番目と4番目のテストベクタは失敗します。これらのベクトルは64バイト以上で、私がAmazonに署名する必要があるすべてのURLは64バイトを超えているので、これは問題です。私は何か間違っているかどうかわからない。 OpenSSLテストはhmactest.cにありますが、EVP_md5のみをチェックし、テストベクタはRFCと全く同じではありません。私はSHA256で動作するためにこれを必要とするので、RFCのテストベクタと照合することができます。私は(下記のコメントで述べた私のコピー&ペーストのエラーを修正するために、今、将来の視聴者のために更新された定数)テストのために次の定数を使用しています:
const
LIBEAY_DLL_NAME = 'libeay32.dll';
EVP_MAX_MD_SIZE = 64;
//RFC 4231 Test case 1
TEST1_KEY: string = '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b';
TEST1_DATA: string = '4869205468657265';
TEST1_DIGEST: string = 'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7';
//RFC 4231 Test case 2
TEST2_KEY = '4a656665';
TEST2_DATA = '7768617420646f2079612077616e7420666f72206e6f7468696e673f';
TEST2_DIGEST = '5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843';
//RFC 4231 Test case 3
TEST3_KEY = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
TEST3_DATA = 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd';
TEST3_DIGEST = '773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe';
//RFC 4231 Test case 4
TEST4_KEY = '0102030405060708090a0b0c0d0e0f10111213141516171819';
TEST4_DATA = 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd';
TEST4_DIGEST = '82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b';
//RFC 4231 Test case 5
TEST5_KEY = '0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c';
TEST5_DATA = '546573742057697468205472756e636174696f6e';
TEST5_DIGEST = 'a3b6167473100ee06e0c796c2955552b';
私はshuntyによって、このコードがどのように見えるか分かりませんここでひどいように見えます(私はstackoverflowの初心者です)。彼がやったように私はRAND_seedではなくRAND_load_fileを使用しますが、それ以外の場合は同じです:
function TForm1.GetHMAC(const AKey, AData: string): TBytes;
var
key, data: TBytes;
md_len: integer;
res: PByte;
buf: PInteger;
rand_val: Integer;
begin
OpenSSL_add_all_algorithms;
Randomize;
rand_val := Random(100);
GetMem(buf, rand_val);
try
RAND_seed(buf, rand_val);
key := TEncoding.UTF8.GetBytes(AKey);
data := TEncoding.UTF8.GetBytes(AData);
md_len := EVP_MAX_MD_SIZE;
SetLength(Result, md_len);
res := HMAC(EVP_sha256, @key[0], Length(key), @data[0], Length(data), @result[0], md_len);
if (res <> nil) then
SetLength(Result, md_len);
finally
FreeMem(buf);
end;
end;
私がテストに使用したコードは次のようになります。この特定の方法は、失敗したテスト3のためのものです。結果はbb861233f283aef2ef7aea09785245c9f3c62720c9d04e0c232789f27a586e44ですが、それはTEST3_DIGEST一定進値に等しくなければなりません:
procedure TForm1.btnTestCase3Click(Sender: TObject);
var
LBytesDigest: TBytes;
LHashString: string;
LHexDigest: string;
begin
LBytesDigest := GetHMAC(HexToStr(TEST3_KEY), HexToStr(TEST3_DATA));
LHexDigest := LowerCase(BytesToHex(LBytesDigest));
if LHexDigest = TEST3_DIGEST then begin
Memo1.Lines.Add('SUCCESS: Matches test case');
Memo1.Lines.Add(LHexDigest);
end else begin
Memo1.Lines.Add('ERROR: Does not match test case');
Memo1.Lines.Add('Result: ' + LHexDigest);
Memo1.Lines.Add('Test Case: ' + TEST3_DIGEST);
end;
end;
任意のアイデア?私はあきらめてちょうど彼らが提供するライブラリを使用した.NETアプリケーションを作成しようよ...
私の防衛では、UTF8.GetBytesが使用されました。なぜなら、それは私たちが取り組んでいた特定のアプリケーションの内部が必要だったからです。私たちは決してアプリケーションの外のものと対話していませんでした。私は参照データに対して使用していなかったという旨のポストの一番下に免責があります。私たちはここ2年間で改善しました:-) – shunty
興味深い。ある時点で、私はパラメータとしてTBytesを取ったオーバーロードされたGetHMACを持っていました。私がRFCの当時の16進数でエンコードされたテストを使用していたかどうかはわかりませんが、いくつかのUnicodeの問題のためにおそらく動作しませんでした。私は前にこのように直接対処する必要はなかった。 Amazonの場合は、URIを取得してHMAC SHA1またはSHA256で変換し、Base64に変換してからURLエンコードし、元のURIに署名を追加する必要があります。デルファイでは、あるシャークタンクから別のシャークタンクに歩き回り、再び別のシャークタンクに移動するのが好きです。 Amazonの.NETライブラリが使用するコードは、比較すると非常に簡単です。 –
@shunty - 元の投稿をありがとう。私のコメントのように、編集中のある時点で参照データが破棄されたことをテストしていないと言っていたようです。あなたの免責事項が私にRFCを見つけさせ、16進数でエンコードされたテストを動作させようとしているからです。 –