2012-04-03 24 views
5

पास करने के लिए एचएमएसी-एसएचए 256 नहीं मिल सकता है, मुझे "HMAC-SHA256 in Delphi" पर पिछले प्रश्न की तरह अमेज़ॅन आरईएसटी सेवाओं तक पहुंचने की ज़रूरत है। चूंकि यह मैं नवीनतम libeay32.dll उपयोग करने के लिए आरएफसी 4231 में परीक्षण वेक्टर पारित करने के लिए कोशिश कर रहा हूँ D2010 में हो गया है:डेल्फी - आरएफसी 4231 टेस्ट वेक्टर

http://tools.ietf.org/html/rfc4231

किसी को भी एक तरीका है कि डेल्फी में इन परीक्षणों इस लाइब्रेरी का उपयोग कर गुजरता है क्या ? पोस्ट में शंटी द्वारा पोस्ट किया गया कोड जिसे मैंने पहले दो टेस्ट वैक्टरों के साथ-साथ पांचवां पास किया है, लेकिन यह तीसरे और चौथे स्थान पर विफल रहता है। वे वैक्टर 64 बाइट्स से अधिक हैं और चूंकि अमेज़ॅन के लिए साइन इन करने की ज़रूरत वाले सभी यूआरएल 64 बाइट्स से अधिक हैं, यह एक समस्या है। अगर मैं कुछ गलत कर रहा हूं तो मैं यह समझने में सक्षम नहीं हूं। ओपनएसएसएल परीक्षण hmactest.c में है, लेकिन यह केवल EVP_md5 की जांच करता है और परीक्षण वैक्टर आरएफसी में समान नहीं हैं। मुझे SHA256 के साथ काम करने की आवश्यकता है ताकि मैं आरएफसी में परीक्षण वैक्टरों के खिलाफ सत्यापित कर सकूं। मैं परीक्षण के लिए निम्नलिखित स्थिरांक उपयोग कर रहा हूँ (स्थिरांक अब भविष्य दर्शकों के लिए अद्यतन मेरी कॉपी और पेस्ट त्रुटियों नीचे टिप्पणी में उल्लेख किया है ठीक करने के लिए):

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 द्वारा इस कोड को दिखेगा पता नहीं कैसे चिपकाया क्योंकि यह यहां भयानक लग रहा है (मैं एक स्टैक ओवरफ्लो नौसिखिया हूँ)। मैं नहीं बल्कि RAND_load_file से की तरह उसने किया RAND_seed इस्तेमाल किया, लेकिन अन्यथा यह एक ही है:

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 ऐप बनाने के हूँ ...

उत्तर

6

आप, जिसका अर्थ है कि UnicodeString साथ काम कर रहे (TEncoding के आपके उपयोग से स्पष्ट रूप में) D2009 + का उपयोग कर रहे हैं, लेकिन आप आपके तर्क में यूनिकोड को ध्यान में नहीं ले रहे हैं। आरएफसी पात्रों पर काम नहीं करता है, यह बाइट्स पर काम करता है। आपके टेस्ट डेटा में हेक्स-एन्कोडेड स्ट्रिंग्स हैं। जब आप उन्हें (Unicode)String मानों में डीकोड करते हैं, तो परिणामी वर्णों में से कई वर्णों की ASCII रेंज के बाहर होते हैं, जिसका अर्थ है कि उन्हें Ansi codepages द्वारा व्याख्या किया जाना चाहिए इससे पहले कि आप उन्हें यूटीएफ -8 में सही रूप से परिवर्तित कर सकें (जिसे आप में उपयोग नहीं करना चाहिए वैसे भी इस स्थिति)।

आप सीधे TBytes करने के लिए अपने हेक्स तार को डिकोड करने के अपने कार्यान्वयन को बदलने की जरूरत के बजाय (आप उस के लिए Classes.HexToBin() उपयोग कर सकते हैं) तो सही बाइट मूल्यों संरक्षित कर रहे हैं और HMAC को पारित कर दिया, और पूरी तरह से TEncoding.UTF8.GetBytes() से छुटकारा पाने:

function TForm1.GetHMAC(const AKey, AData: TBytes): TBytes; 
var 
    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); 
    md_len := EVP_MAX_MD_SIZE; 
    SetLength(Result, md_len); 
    res := HMAC(EVP_sha256, Pointer(AKey), Length(AKey), Pointer(AData), Length(AData), @Result[0], md_len); 
    if (res <> nil) then 
     SetLength(Result, md_len); 
    finally 
    FreeMem(buf); 
    end; 
end; 

function HexToBytes(const S: String): TBytes; 
begin 
    SetLength(Result, Length(S) div 2); 
    SetLength(Result, HexToBin(PChar(S), Pointer(Result), Length(Result))); 
en; 

procedure TForm1.btnTestCase3Click(Sender: TObject); 
var 
    LBytesDigest: TBytes; 
    LHashString: string; 
    LHexDigest: string; 
begin 
    LBytesDigest := GetHMAC(HexToBytes(TEST3_KEY), HexToBytes(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; 
+0

मेरी रक्षा में, यूटीएफ 8.गेटबाइट्स का उपयोग किया गया था क्योंकि यही वह विशेष ऐप था जो हम आवश्यकतानुसार काम कर रहे थे - हम कभी भी ऐप के बाहर कुछ भी नहीं कर रहे थे। और पोस्ट के निचले हिस्से में एक अस्वीकरण है जिसमें कहा गया है कि मैंने संदर्भ डेटा के खिलाफ इसका उपयोग नहीं किया था। और हमने पिछले दो वर्षों में सुधार किया है :-) – shunty

+0

दिलचस्प। एक बिंदु पर मेरे पास एक अधिभारित गेटएचएमएसी था जिसने टीबीइट्स को पैरामीटर के रूप में लिया। यकीन नहीं है कि अगर मैं उस समय आरएफसी से हेक्स एन्कोडेड परीक्षण का उपयोग कर रहा था, हालांकि। यह शायद कुछ यूनिकोड मुद्दों के कारण काम नहीं करता है। मुझे इससे पहले कभी इस तरह से निपटना नहीं था। अमेज़ॅन के लिए आपको एक यूआरआई लेना है, इसे एचएमएसी SHA1 या SHA256 के साथ परिवर्तित करना है, फिर उसे बेस 64 में परिवर्तित करें, फिर यूआरएल एन्कोड करें, फिर मूल यूआरआई में हस्ताक्षर जोड़ें। डेल्फी में यह एक शार्क टैंक से दूसरे में और दूसरे में फिर से चलने जैसा है। कोड अमेज़ॅन की .NET लाइब्रेरी का उपयोग तुलना करके इतना आसान है। –

+0

@ शुनटी - मूल पोस्ट के लिए धन्यवाद।मेरी टिप्पणी की तरह लगता है कि आपने कहा था कि संपादन में किसी बिंदु पर किसी भी संदर्भ डेटा को छोड़कर आपने इसका परीक्षण नहीं किया था। यह ठीक था क्योंकि आपका अस्वीकरण मुझे आरएफसी खोजने के लिए प्रेरित करता है और अपने हेक्स एन्कोडेड परीक्षणों को काम करने की कोशिश करता है। –