這將是一個長期的問題,但我有一個非常奇怪的錯誤。我在C++中使用OpenSSL來計算HMAC,並將它們與使用javax.crypto.Mac的相似實現進行比較。對於某些密鑰,HMAC計算是正確的,對於其他密鑰,HMAC存在差異。我相信當鑰匙變大時會出現問題。這裏是細節。Java Mac HMAC vs C++ OpenSSL hmac
這裏是C++中最重要的代碼:
void computeHMAC(std::string message, std::string key){
unsigned int digestLength = 20;
HMAC_CTX hmac_ctx_;
BIGNUM* key_ = BN_new();;
BN_hex2bn(&key_, key);
unsigned char convertedKey[BN_num_bytes(key_)];
BIGNUM* bn = BN_new();
HMAC_CTX_init(&hmac_ctx_);
BN_bn2bin(bn, convertedKey);
int length = BN_bn2bin(key_, convertedKey);
HMAC_Init_ex(&hmac_ctx_, convertedKey, length, EVP_sha1(), NULL);
/*Calc HMAC */
std::transform(message.begin(), message.end(), message.begin(), ::tolower);
unsigned char digest[digestLength];
HMAC_Update(&hmac_ctx_, reinterpret_cast<const unsigned char*>(message.c_str()),
message.length());
HMAC_Final(&hmac_ctx_, digest, &digestLength);
char mdString[40];
for(unsigned int i = 0; i < 20; ++i){
sprintf(&mdString[i*2], "%02x", (unsigned int)digest[i]);
}
std::cout << "\n\nMSG:\n" << message << "\nKEY:\n" + std::string(BN_bn2hex(key_)) + "\nHMAC\n" + std::string(mdString) + "\n\n";
}
的Java測試看起來是這樣的:
public String calculateKey(String msg, String key) throws Exception{
HMAC = Mac.getInstance("HmacSHA1");
BigInteger k = new BigInteger(key, 16);
HMAC.init(new SecretKeySpec(k.toByteArray(), "HmacSHA1"));
msg = msg.toLowerCase();
HMAC.update(msg.getBytes());
byte[] digest = HMAC.doFinal();
System.out.println("Key:\n" + k.toString(16) + "\n");
System.out.println("HMAC:\n" + DatatypeConverter.printHexBinary(digest).toLowerCase() + "\n");
return DatatypeConverter.printHexBinary(digest).toLowerCase();
}
一些試驗使用不同的密鑰運行(所有的字符串被解釋爲十六進制):
密鑰1: 736A66B29072C49AB6DC93BB2BA41A53E169D14621872B0345F01EBB F117FCE48EEEA2409CFC1BD92B0428BA0A34092E3117BEB4A8A14F03391C661994863DAC1A75ED437C1394DA0741B16740D018CA243A800DA25311FDFB9CA4361743E8511E220B79C2A3483FCC29C7A54F1EB804481B2DC87E54A3A7D8A94253A60AC77FA4584A525EDC42BF82AE2A1FD6E3746F626E0AFB211F6984367B34C954B0E08E3F612590EFB8396ECD9AE77F15D5222A6DB106E8325C3ABEA54BB59E060F9EA0
消息: 測試
HMAC的OpenSSL: b37f79df52afdbbc4282d3146f9fe7a254dd23b3
HMAC的Java的Mac: b37f79df52afdbbc4282d3146f9fe7a254dd23b3
鍵2:636A66B29072C49AB6DC93BB2BA41A53E169D14621872B0345F01EBBF117FCE48EEEA2409CFC1BD92B0428BA0A34092E3117BEB4A8A14F03391C661994863DAC1A75ED437C1394DA0741B16740D018CA243A800DA25311FDFB9CA4361743E8511E220B79C2A3483FCC29C7A54F1EB804481B2DC87E54A3A7D8A94253A60AC77FA4584A525EDC42BF82AE2A1FD6E3746F626E0AFB211F6984367B34C954B0E08E3F612590EFB8396ECD9AE77F15D5222A6DB106E8325C3ABEA54BB59E060F9EA0
消息: 測試
HMAC的OpenSSL: bac64a905fa6ae3f7bf5131be06ca037b3b498d7
HMAC的Java的Mac: bac64a905fa6ae3f7bf5131be06ca037b3b498d7
重點3:836A66B29072C49AB6DC93BB2BA41A53E169D14621872B0345F01EBBF117FCE48EEEA2409CFC1BD92B0428BA0A34092E3117BEB4A8A14F03391C661994863DAC1A75ED437C1394DA0741B16740D018CA243A800DA25311FDFB9CA4361743E8511E220B79C2A3483FCC29C7A54F1EB804481B2DC87E54A3A7D8A94253A60AC77FA4584A525EDC42BF82AE2A1FD6E3746F626E0AFB211F6984367B34C954B0E08E3F612590EFB8396ECD9AE77F15D5222A6DB106E8325C3ABEA54BB59E060F9EA0
消息: 測試
HMAC運算enSSL: c189c637317b67cee04361e78c3ef576c3530aa7
HMAC的Java的Mac: 472d734762c264bea19b043094ad0416d1b2cd9c
如數據所示,當鑰匙獲取到大,發生錯誤。如果不知道哪個實現有問題。我也嘗試了更大的按鍵和更小的按鍵。我還沒有確定確切的門檻。任何人都可以發現問題嗎?有沒有人能夠通過使用不同的軟件進行仿真來告訴我哪種HMAC在最後一種情況下是不正確的,或者任何人都可以告訴我可以使用哪種第三種實現來檢查我的?
親切的問候,
羅埃爾風暴
我認爲問題不在關鍵的長度,而是在其符號。你可以嘗試用一個「FF」替換一個短鍵的起始字節,看看你在C++和Java之間得到不同的結果嗎? – RealSkeptic
那麼用FF代替83例如? – Silver
這樣做仍然會導致不同的HMAC。 Openssl:53e8fab89762b945f08d245f963aab72dfd47533 Java:15996db38398cb114f73f81645d7bbb87b24c2e4 – Silver