2013-10-10 65 views
4

我想在我的C++項目中實現OAuth 1.0協議。爲了創建OAuth簽名,我需要實現HMAC-SHA1算法,其中keytext將根據OAuth規範創建一些字符串。如何在HMAC-SHA1 Crypto ++實現中使用自定義密鑰

我想使用Crypto ++庫來實現HMAC-SHA1。我發現項目的維基這個HMAC-SHA1例如:

AutoSeededRandomPool prng; 

SecByteBlock key(16); 
prng.GenerateBlock(key, key.size()); 

string plain = "HMAC Test"; 
string mac, encoded; 

/*********************************\ 
\*********************************/ 

// Pretty print key 
encoded.clear(); 
StringSource(key, key.size(), true, 
    new HexEncoder(
     new StringSink(encoded) 
    ) // HexEncoder 
); // StringSource 

cout << "key: " << encoded << endl; 
cout << "plain text: " << plain << endl; 

/*********************************\ 
\*********************************/ 

try 
{ 
    HMAC<SHA256> hmac(key, key.size()); 

    StringSource(plain, true, 
     new HashFilter(hmac, 
      new StringSink(mac) 
     ) // HashFilter  
    ); // StringSource 
} 
catch(const CryptoPP::Exception& e) 
{ 
    cerr << e.what() << endl; 
    exit(1); 
} 

/*********************************\ 
\*********************************/ 

// Pretty print 
encoded.clear(); 
StringSource(mac, true, 
    new HexEncoder(
     new StringSink(encoded) 
    ) // HexEncoder 
); // StringSource 

cout << "hmac: " << encoded << endl; 

但我不知道如何隨機生成的字符串,而不是我的創造key使用。我嘗試過創建:

string key=...; //string generated by OAuth specification; 

但隨後出現編譯錯誤。但是當我寫:

string plain=...; //string generated by OAuth specification; 

然後沒有錯誤。

我需要指定什麼密鑰長度?因爲我將有不同長度的鍵(有48個,也許有96個符號)。

回答

4

看起來有幾件事需要熟悉。 (對不起,我不能幫助,因爲我從來沒有這樣做)。

首先是安全架構。你可以在Beginner's Guide to OAuth – Part III : Security Architecture找到一些閱讀。

其次是HMAC-SHA1簽名和格式。你可以在OAuth Core HMAC-SHA1找到總覽。

第三,您需要了解OAuth的編碼和表示格式。你可以在OAuth Core Parameter Encoding找到一些閱讀。


爲了回答大家的一些問題:

你需要解析和解碼參數拿到鑰匙,簽名的數據和簽名。所以你需要解析和解碼三個值:oauth_key,oauth_dataoauth_signature

然後,您將如下設置您的Crypto ++ HMAC key

SecByteBlock key(SHA1::BLOCKSIZE); 
memcpy(key.data(), key.size(), oauth_key); 

之後,你會驗證與如下:

byte oauth_key[] = ...; // Your parsed and decoded key 
string oauth_data = ...; // Your parsed and decoded data 
string oauth_signature = ...; // // Your parsed and decoded signature 

try 
{ 
    SecByteBlock key(SHA1::BLOCKSIZE); 
    memcpy(key.data(), key.size(), oauth_key); 

    HMAC<SHA1> hmac(key, key.size()); 
    const int flags = HashVerificationFilter::THROW_EXCEPTION | HashVerificationFilter::HASH_AT_END; 

    StringSource ss(oauth_data + oauth_signature + mac, true, 
     new HashVerificationFilter(hmac, NULL, flags) 
    ); // StringSource 

    cout << "Verified message" << endl; 
} 
catch(const CryptoPP::Exception& e) 
{ 
    // Handle failure 
    cerr << e.what() << endl;   
} 

另一件事加密+或許能夠幫助是Base64編碼解碼。下面是從HexDecoder wiki page,但它適用於Base64Decoder,因爲編碼器和解碼器使用相同的接口。

string encoded = ...; 
string decoded; 

StringSource ss(encoded, 
    new HexDecoder(
     new StringSink(decoded) 
    ) // HexDecoder 
); // StringSource 

所以您的代碼將是:

string encoded = ...; 
string decoded; 

StringSource ss(encoded, 
    new Base64Decoder(
     new StringSink(decoded) 
    ) // Base64Decoder 
); // StringSource 

上述用途的Crypto ++的pipline接口,其中,數據從源到宿流動。你也可以做一個更「C」之類的Base64Decoder對象上使用PutGet方式:

string encoded = ...; 
string decoded; 

Base64Decoder decoder; 

decoder.Put((byte*)encoded.data(), encoded.size()); 
decoder.MessageEnd(); 

word64 size = decoder.MaxRetrievable(); 
if(size && size <= SIZE_MAX) 
{ 
    decoded.resize(size);  
    decoder.Get((byte*)decoded.data(), decoded.size()); 
} 
0

我用非常類似的任務負責。在C++中使用雙腿OAuth 1.0a。雙腿,因爲沒有用戶參與過程,只有客戶端和服務器。正如描述的:http://oauth.googlecode.com/svn/spec/ext/consumer_request/1.0/drafts/2/spec.html

概念的完整的證明包括分析和參數進行解碼,可以發現:https://gist.github.com/duedal/a197fc9f6dc1ad59f08c

應該很容易在此建來完成它。主要需要驗證時間戳+隨機數,當然也會綁定到您的項目中。

相關問題