2012-02-14 34 views
23

मैं एक सी प्रोग्राम लिखने की कोशिश कर रहा हूं जो साबित करता है कि SHA1 लगभग टकराव मुक्त है, लेकिन मैं यह नहीं समझ सकता कि वास्तव में मेरे इनपुट मानों के लिए हैश कैसे बनाया जाए। मुझे बस हैश बनाने की जरूरत है, और हेक्स मान को सरणी में स्टोर करें। कुछ Google खोजों के बाद, मैं OpenSSL प्रलेखन इस का उपयोग करने के लिए मुझे निर्देशन मिल गया है:सी प्रोग्रामिंग में SHA1 हैशिंग का उपयोग कैसे करें

#include <openssl/sha.h> 

unsigned char *SHA1(const unsigned char *d, unsigned long n, 
        unsigned char *md); 

int SHA1_Init(SHA_CTX *c); 
int SHA1_Update(SHA_CTX *c, const void *data, 
        unsigned long len); 
int SHA1_Final(unsigned char *md, SHA_CTX *c); 

मेरा मानना ​​है कि मैं या तो अहस्ताक्षरित चार * SHA1 या SHA1_Init का उपयोग कर होना चाहिए, लेकिन मुझे यकीन है कि तर्क होगा क्या नहीं कर रहा हूँ, यह देखते हुए एक्स मेरा इनपुट हैश करने के लिए है। क्या कोई इसे मेरे लिए साफ़ कर देगा? धन्यवाद।

+0

आपके इनपुट मान क्या हैं: मेमोरी स्ट्रिंग्स, या फ़ाइल सामग्री? –

+0

मैं जन्मदिन का हमला लिख ​​रहा हूं जो एक नया हैश बनाना चाहिए और जब भी मैं सरणी के माध्यम से साफ़ करता हूं तो इसे अंत में जोड़ता हूं। मैं बस इसे सरल रखने जा रहा था और हैश का मूल्य I। त्वरित उत्तर, स्मृति तारों में। – spassen

+1

'साबित करना कि SHA1 लगभग टकराव मुक्त है' के साथ आपका क्या मतलब है? SHA1 160-बिट हैश है, इसलिए 2^160 संभावित मान हैं, लेकिन 2^160 संभव स्ट्रिंग्स (1 एमबी से कम कहें) से कहीं अधिक हैं, इसलिए कई टकराव हैं। यदि आप सिर्फ यह जांचना चाहते हैं कि आपको कई यादृच्छिक रूप से जेनरेट किए गए तारों से टकराव मिलते हैं, तो आधा रास्ते विश्वसनीय उत्तर के लिए आवश्यक तारों की संख्या असुरक्षित रूप से उच्च है (जब तक कि आप जल्दी टकराव नहीं पाते हैं, लेकिन SHA1 को असाइन करने के लिए पर्याप्त रूप से परीक्षण किया जाता है एक लापरवाही छोटी संभावना)। –

उत्तर

39

आप अपने डेटा के सभी एक ही बार है, तो सिर्फ SHA1 समारोह का उपयोग करें:

// The data to be hashed 
char data[] = "Hello, world!"; 
size_t length = sizeof(data); 

unsigned char hash[SHA_DIGEST_LENGTH]; 
SHA1(data, length, hash); 
// hash now contains the 20-byte SHA-1 hash 

हैं, तो दूसरी ओर, यदि आप केवल अपने डेटा एक समय में एक टुकड़ा मिलता है और आप की गणना करना चाहते हैं आप प्राप्त के रूप में है कि डेटा है, तो अन्य कार्यों हैश का उपयोग करें:

// Error checking omitted for expository purposes 

// Object to hold the current state of the hash 
SHA_CTX ctx; 
SHA1_Init(&ctx); 

// Hash each piece of data as it comes in: 
SHA1_Update(&ctx, "Hello, ", 7); 
... 
SHA1_Update(&ctx, "world!", 6); 
// etc. 
... 
// When you're done with the data, finalize it: 
unsigned char hash[SHA_DIGEST_LENGTH]; 
SHA1_Final(hash, &ctx); 
+0

मैंने sha1 फ़ंक्शन का उपयोग करने का प्रयास किया, लेकिन जब मैं टर्मिनल में संकलित करता हूं तो यह SHA1 के अनिर्धारित संदर्भ को कहता है। मुझे किसी और चीज के बारे में कोई शिकायत नहीं मिली है। कोई विचार क्या मैं याद कर रहा हूँ? – spassen

+7

आपको ओपनएसएसएल रनटाइम लाइब्रेरी से लिंक करने की आवश्यकता है। मान लीजिए कि आप जीसीसी का उपयोग कर रहे हैं, अपने लिंकर कमांड लाइन में '-lcrypto' जोड़ें। –

+0

कोई कैसे hmacsha1 उत्पन्न करेगा? – Cmag

11

वे एक ही चीज़ को प्राप्त करने के दो अलग-अलग तरीके हैं।

विशेष रूप से, आप या तो उपयोग SHA_Init, तो SHA_Update के रूप में कई के रूप में आवश्यक बार अपने डेटा के माध्यम से SHA_Final डाइजेस्ट, या आप SHA1 प्राप्त करने के लिए पारित करने के लिए और उसके बाद।

दो तरीकों का कारण यह है कि जब बड़ी फाइलें हैं तो फाइलों को टुकड़ों में पढ़ने के लिए आम है, क्योंकि विकल्प बहुत मेमोरी का उपयोग करेगा। इसलिए, SHA_CTX - एसएचए संदर्भ का ट्रैक रखते हुए - जैसे ही आप जाते हैं, आप इसे पाने के लिए अनुमति देते हैं। एल्गोरिदम आंतरिक रूप से इस मॉडल को भी फिट करता है - यानी, एक समय में डेटा ब्लॉक में पारित किया जाता है।

SHA विधि काफी सरल होना चाहिए। इस तरह अन्य कार्यों:

unsigned char md[SHA_DIGEST_LENGTH]; 
SHA_CTX context; 
int SHA1_Init(&context); 

for (i = 0; i < numblocks; i++) 
{ 
    int SHA1_Update(&context, pointer_to_data, data_length); 
} 
int SHA1_Final(md, &context); 

महत्वपूर्ण बात अंत md पर द्विआधारी डाइजेस्ट, नहीं हेक्साडेसिमल प्रतिनिधित्व शामिल होंगे - यह एक स्ट्रिंग नहीं है और एक के रूप में नहीं किया जाना चाहिए।

+0

कैसे एक hmacsha1 उत्पन्न करेगा? – Cmag

+0

@Clustermagnet hmacsha1 हैश के रूप में SHA1 का उपयोग करके एक एचएमएसी एल्गोरिदम है। मेरे उत्तर में यह वही विचार है (देखें [यहां] (http://www.openssl.org/docs/crypto/hmac.html)) लेकिन एचएमएसी के लिए विशिष्ट 'EVP_MD' तर्क के लिए आप' EVP_sha1() निर्दिष्ट करते हैं '। –

+0

@Cmag - देखें [ईवीपी हस्ताक्षर और सत्यापन | एचएमएसी] (http://wiki.openssl.org/index.php/EVP_Signing_and_Verifying#HMAC) ओपनएसएसएल विकी पर। यह भी देखें [ओपनएसएसएल में एचएमएसी बनाम ईवीपी कार्यों का उपयोग] (http://stackoverflow.com/a/20322002/608639) स्टैक ओवरफ़्लो पर। – jww

3

पहले समारोह (SHA1()) उच्च स्तर से एक है, यह शायद एक आप चाहते हैं। दस्तावेज़ उपयोग पर बहुत स्पष्ट है - d इनपुट है, n इसका आकार है और md है जहां परिणाम रखा गया है (आप इसे आवंटित करते हैं)।

अन्य 3 कार्यों के लिए - ये निम्न स्तर हैं और मुझे पूरा यकीन है कि इन्हें आंतरिक रूप से पहले उपयोग किया जाता है। वे बड़े इनपुट के लिए बेहतर अनुकूल हैं जिन्हें ब्लॉक-दर-ब्लॉक तरीके से संसाधित करने की आवश्यकता होती है।

2

मेरा मानना ​​है कि मैं, 1.0.2 और 1.1.0 की तरह, इस परियोजना EVP इंटरफ़ेस का उपयोग कर की सिफारिश या तो unsigned char *SHA1 या SHA1_Init ...

OpenSSL पुस्तकालय के बाद के संस्करणों के लिए उपयोग करना चाहिए।अन्यथा हैश अशक्त टर्मिनेटर सहित गणना की जाएगी

#define handleErrors abort 

EVP_MD_CTX *ctx; 

if((ctx = EVP_MD_CTX_create()) == NULL) 
    handleErrors(); 

if(1 != EVP_DigestInit_ex(ctx, EVP_sha256(), NULL)) 
    handleErrors(); 

unsigned char message[] = "abcd .... wxyz"; 
unsinged int message_len = sizeof(message); 

if(1 != EVP_DigestUpdate(ctx, message, message_len)) 
    handleErrors(); 

unsigned char digest[EVP_MAX_MD_SIZE]; 
unsigned int digest_len = sizeof(digest); 

if(1 != EVP_DigestFinal_ex(ctx, digest, &digest_len)) 
    handleErrors(); 

EVP_MD_CTX_destroy(ctx); 
0

एडम Rosenfield का जवाब ठीक है, लेकिन बल्कि sizeof से strlen का उपयोग करें: SHA256 साथ EVP Message Digests का उपयोग करने का एक उदाहरण OpenSSL विकि पर उपलब्ध है। जो इस मामले में शायद ठीक है, लेकिन यदि आपको अपने हैश की तुलना किसी अन्य टूल द्वारा जेनरेट करने की आवश्यकता नहीं है।

// The data to be hashed 
char data[] = "Hello, world!"; 
size_t length = strlen(data); 

unsigned char hash[SHA_DIGEST_LENGTH]; 
SHA1(data, length, hash); 
// hash now contains the 20-byte SHA-1 hash 
संबंधित मुद्दे