2010-09-01 14 views
8

मैं यहां कुछ पोस्ट और वेब के लेख पढ़ रहा हूं लेकिन मैं अपने आवेदन के लिए एक धारावाहिक कुंजी आधारित प्रणाली नहीं चित्रित कर सकता हूं।सीरियल कुंजी: क्या करना है?

http://www.brandonstaggs.com/2007/07/26/implementing-a-partial-serial-number-verification-system-in-delphi/

मैं इस एक पढ़ा लेकिन मैं जावा में कोड चालू नहीं कर सकता और मैं या तो मामले से परिचित नहीं हूँ।

आप मुझे इस पर क्या अंतर्दृष्टि दे सकते हैं? आदर्श रूप से मेरा आवेदन बिक्री के लिए होगा, लेकिन मुझे उम्मीद नहीं है कि यह बहुत लोकप्रिय होगा, अगर मुझे ऐसे उत्पाद हैं जो उत्पाद की सराहना करते हैं और इसे खरीदते हैं, तो मुझे बहुत बुरा नहीं लगता है, लेकिन मैं आसानी से इसे टालना चाहता हूं फटा। कृपया जितना हो सके उतना विशिष्ट हो, मैं जावा के लिए कुछ नया हूं।

अग्रिम धन्यवाद।

उत्तर

6

यह कठिन नहीं है, अगर आप अपनी आवश्यकताओं में कुछ हद तक लचीले हैं - शायद नीचे दी गई योजना आपके लिए काम करेगी।

आप केवल के = [एसएन, एच ([एक्स, एसएन, वाई]) का उत्पादन कर सकते हैं] जो एक हैश के साथ बढ़ते क्रम संख्या का संयोग है, जहां हैश एक संगतता का एक सुरक्षित हैश फ़ंक्शन है अद्वितीय स्थिरांक एक्स और वाई के बीच सीरियल नंबर जो "salt" you use to prevent the use of rainbow tables गुप्त हैं।

एक प्रसिद्ध सुरक्षित हैश एल्गोरिथ्म का उपयोग करें (उदाहरण के लिए, SHA-1 या SHA-2, MD5 शायद भी पर्याप्त है, के बाद से MD5 के लिए जाना जाता कमजोरियों टक्कर हमलों रहे हैं, और नहींpreimage attacks) और आप पूरी तरह से तैयार किया जाना चाहिए , कम से कम जहां तक ​​धारावाहिक कुंजी भाग जाता है (आप शायद दो लोगों को एक ही कुंजी का उपयोग करने से रोकना चाहते हैं)।

अन्य चीज जो आप कर सकते हैं उपयोगी है K = [SN, T, H ([X, SN, T, Y])] का उपयोग करें - सीरियल नंबर और टाइमस्टैम्प दोनों का उपयोग करें। इसका उपयोग धारावाहिक कुंजी के लिए केवल एक संकीर्ण उपयोग विंडो की अनुमति देने के लिए किया जा सकता है: यह टाइमस्टैम्प के एन सेकंड के भीतर मान्य है, इसलिए यह उस विंडो के बाहर की कुंजी का पुन: उपयोग रोक देगा।

फिर किसी प्रतिनिधित्व के लिए के को एन्कोड/डीकोड करें जिसका उपयोग उपयोगकर्ताओं को कुंजी (उदा। बेस 64) में प्रवेश करने की अनुमति देने के लिए किया जा सकता है।

एक सरल और पारदर्शी समग्र एल्गोरिदम होना सर्वोत्तम है - अगर कोई आपकी योजना को रिवर्स-इंजीनियर करता है तो obfuscation आपकी सहायता नहीं करेगा।

+0

धन्यवाद जेसन। मैं इस पर काम करना शुरू कर दूंगा! – Qosmo

4

सामान्य रूप से एप्लिकेशन सुरक्षित करना एक साधारण काम नहीं है। कई कंपनियां नए सुरक्षित एल्गोरिदम खोजने के लिए बहुत सारा पैसा निवेश कर रही हैं, जो सभी को बहुत तेजी से क्रैक किया जाता है।

जावा अनुप्रयोगों को सुरक्षित करना थोड़ा और कठिन है। आपके आवेदन के भीतर एम्बेडेड कोई भी सीरियल सत्यापन एल्गोरिदम डीकंपिल्ड किया जा सकता है, इसलिए एक धारावाहिक कुंजी जेनरेटर निर्माण करना बहुत आसान होगा।

एक अच्छा प्रारंभिक बिंदु आपके द्वारा दिया गया लेख है। यह आपको बताता है कि एक महत्वपूर्ण सत्यापन प्रणाली कैसे बनाएं, और अपने (वैध) उपयोगकर्ताओं के लिए कुंजी कैसे उत्पन्न करें।

ऐसे एल्गोरिदम को लागू करने के बाद, मैं आपको स्रोत कोड को थोड़ा सुरक्षित करने का सुझाव दूंगा, इसलिए अपघटन थोड़ा और "मुश्किल" बन जाएगा। अपने सत्यापन एल्गोरिदम कार्यान्वयन को छिपाने के लिए कोड obfuscation तकनीकों का उपयोग करें। यह बाइट कोड को संशोधित करके आपके आवेदन को क्रैक करने की कोशिश करने वाले लोगों के लिए कार्य को कठिन बना देगा।

एक अच्छी तकनीक रिमोट सर्वर पर आपके कुंजी सत्यापन एल्गोरिदम को निर्यात करने के लिए हो सकती है। क्लाइंट सर्वर को कुंजी भेजता है, जो आपके एप्लिकेशन को यह बताने के लिए 'सत्यापन कोड' के साथ जवाब देता है कि आपकी कुंजी मान्य है। लेकिन यह उपयोगकर्ताओं को किसी भी कुंजी सत्यापन प्रक्रिया को हटाने के लिए आपके आवेदन को संशोधित करने से रोकता नहीं है। और यह वैध उपयोगकर्ताओं के लिए बहुत परेशान हो सकता है जिनके पास 24 घंटे का इंटरनेट कनेक्शन नहीं है। मैं स्टीम के बारे में सोच रहा हूं, जो इंटरनेट पर हर लॉन्च पर महत्वपूर्ण वैधता को सत्यापित करता है, और जो बहुत से उपयोगकर्ताओं को परेशान करता है।

अच्छी सुरक्षा तकनीक खोजने के लिए, अपने आस-पास देखें और यह निर्धारित करने का प्रयास करें कि अन्य लोग कैसे करते हैं, कौन सी तकनीकें काम कर रही हैं, जो नहीं हैं। वे बहुत उदाहरण हैं (विशेष रूप से वीडियो गेम उद्योग)। लेकिन ध्यान रखें कि यहां तक ​​कि सबसे अच्छी कंपनियां भी अपने अनुप्रयोगों को सही तरीके से सुरक्षित नहीं कर पाती हैं। कोई तकनीक अटूट नहीं है।

+0

मेरी इच्छा है कि मैं दोनों को जवाब के रूप में चिह्नित कर सकूं लेकिन जेसन के जवाब ने मुझे काम करना शुरू करने के लिए कुछ दिया, इसलिए मैं अपने प्रश्न के प्रयोजनों के लिए अपना उत्तर चिन्हित करूंगा। धन्यवाद! – Qosmo

12

मुझे उस लेख में काफी रुचि थी, इसलिए मैंने जावा में कोड लागू किया।

import java.util.Locale; 
import java.util.Set; 
import java.util.TreeSet; 

public class KeyValidator { 
    private static final byte[][] params = new byte[][] { { 24, 4, 127 }, { 10, 0, 56 }, { 1, 2, 91 }, { 7, 1, 100 } }; 
    private static final Set<String> blacklist = new TreeSet<String>(); 

    static { 
     blacklist.add("11111111"); 
    } 

    private static byte PKV_GetKeyByte(final int seed, final byte a, final byte b, final byte c) { 
     final int a1 = a % 25; 
     final int b1 = b % 3; 
     if (a1 % 2 == 0) { 
      return (byte) (((seed >> a1) & 0x000000FF)^((seed >> b1) | c)); 
     } else { 
      return (byte) (((seed >> a1) & 0x000000FF)^((seed >> b1) & c)); 
     } 
    } 

    private static String PKV_GetChecksum(final String s) { 
     int left = 0x0056; 
     int right = 0x00AF; 
     for (byte b : s.getBytes()) { 
      right += b; 
      if (right > 0x00FF) { 
       right -= 0x00FF; 
      } 
      left += right; 
      if (left > 0x00FF) { 
       left -= 0x00FF; 
      } 
     } 
     int sum = (left << 8) + right; 
     return intToHex(sum, 4); 
    } 

    public static String PKV_MakeKey(final int seed) { 
     // Fill KeyBytes with values derived from Seed. 
     // The parameters used here must be exactly the same 
     // as the ones used in the PKV_CheckKey function. 
     // A real key system should use more than four bytes. 
     final byte[] keyBytes = new byte[4]; 
     keyBytes[0] = PKV_GetKeyByte(seed, params[0][0], params[0][1], params[0][2]); 
     keyBytes[1] = PKV_GetKeyByte(seed, params[1][0], params[1][1], params[1][2]); 
     keyBytes[2] = PKV_GetKeyByte(seed, params[2][0], params[2][1], params[2][2]); 
     keyBytes[3] = PKV_GetKeyByte(seed, params[3][0], params[3][1], params[3][2]); 

     // the key string begins with a hexadecimal string of the seed 
     final StringBuilder result = new StringBuilder(intToHex(seed, 8)); 

     // then is followed by hexadecimal strings of each byte in the key 
     for (byte b : keyBytes) { 
      result.append(intToHex(b, 2)); 
     } 

     // add checksum to key string 
     result.append(PKV_GetChecksum(result.toString())); 

     final String key = result.toString(); 
     return key.substring(0, 4) + "-" + key.substring(4, 8) + "-" + key.substring(8, 12) + "-" + key.substring(12, 16) + "-" + key.substring(16, 20); 
    } 

    private static boolean PKV_CheckKeyChecksum(final String key) { 
     // remove cosmetic hyphens and normalise case 
     final String comp = key.replaceAll("-", "").toLowerCase(Locale.UK); 
     if (comp.length() != 20) { 
      return false; // Our keys are always 20 characters long 
     } 

     // last four characters are the checksum 
     final String checksum = comp.substring(16); 
     return checksum.equals(PKV_GetChecksum(comp.substring(0, 16))); 
    } 

    public static Status PKV_CheckKey(final String key) { 
     if (!PKV_CheckKeyChecksum(key)) { 
      return Status.KEY_INVALID; // bad checksum or wrong number of 
      // characters 
     } 

     // remove cosmetic hyphens and normalise case 
     final String comp = key.replaceAll("-", "").toLowerCase(Locale.UK); 

     // test against blacklist 
     for (String bl : blacklist) { 
      if (comp.startsWith(bl)) { 
       return Status.KEY_BLACKLISTED; 
      } 
     } 

     // At this point, the key is either valid or forged, 
     // because a forged key can have a valid checksum. 
     // We now test the "bytes" of the key to determine if it is 
     // actually valid. 

     // When building your release application, use conditional defines 
     // or comment out most of the byte checks! This is the heart 
     // of the partial key verification system. By not compiling in 
     // each check, there is no way for someone to build a keygen that 
     // will produce valid keys. If an invalid keygen is released, you 
     // simply change which byte checks are compiled in, and any serial 
     // number built with the fake keygen no longer works. 

     // Note that the parameters used for PKV_GetKeyByte calls MUST 
     // MATCH the values that PKV_MakeKey uses to make the key in the 
     // first place! 

     // extract the Seed from the supplied key string 
     final int seed; 
     try { 
      seed = Integer.valueOf(comp.substring(0, 8), 16); 
     } catch (NumberFormatException e) { 
      return Status.KEY_PHONY; 
     } 

     // test key 0 
     final String kb0 = comp.substring(8, 10); 
     final byte b0 = PKV_GetKeyByte(seed, params[0][0], params[0][1], params[0][2]); 
     if (!kb0.equals(intToHex(b0, 2))) { 
      return Status.KEY_PHONY; 
     } 

     // test key1 
     final String kb1 = comp.substring(10, 12); 
     final byte b1 = PKV_GetKeyByte(seed, params[1][0], params[1][1], params[1][2]); 
     if (!kb1.equals(intToHex(b1, 2))) { 
      return Status.KEY_PHONY; 
     } 

     // test key2 
     final String kb2 = comp.substring(12, 14); 
     final byte b2 = PKV_GetKeyByte(seed, params[2][0], params[2][1], params[2][2]); 
     if (!kb2.equals(intToHex(b2, 2))) { 
      return Status.KEY_PHONY; 
     } 

     // test key3 
     final String kb3 = comp.substring(14, 16); 
     final byte b3 = PKV_GetKeyByte(seed, params[3][0], params[3][1], params[3][2]); 
     if (!kb3.equals(intToHex(b3, 2))) { 
      return Status.KEY_PHONY; 
     } 

     // If we get this far, then it means the key is either good, or was made 
     // with a keygen derived from "this" release. 
     return Status.KEY_GOOD; 
    } 

    protected static String intToHex(final Number n, final int chars) { 
     return String.format("%0" + chars + "x", n); 
    } 

    public enum Status { 
     KEY_GOOD, KEY_INVALID, KEY_BLACKLISTED, KEY_PHONY 
    } 
} 
+0

यदि आप दिखाते हैं कि इसे कैसे कार्यान्वित किया जाए तो मुझे खुशी होगी। –

संबंधित मुद्दे