2015-08-03 10 views
6

पर हस्ताक्षर करना मुझे विभिन्न प्लेटफ़ॉर्म और सेवा के कार्यान्वयन के बीच JSON ऑब्जेक्ट्स का आदान-प्रदान करना है और डिजिटल हस्ताक्षर के माध्यम से इसकी अखंडता सत्यापित करना है। तो एक मंच ए ऐसी वस्तु पैदा करेगा और डिजिटल हस्ताक्षर बनाएगा। कहा गया है कि हस्ताक्षर को ऑब्जेक्ट में शामिल किया गया है और प्लेटफॉर्म बी को भेजा गया है। JSON ऑब्जेक्ट्स में मनमाना विशेषताएँ और डेटा हो सकता है।JSON ऑब्जेक्ट्स

उदा। PHP में:

function signObject($jsonObjectToSign, $privateKey) { 
    $jsonObjectToSign->signature = ""; 
    $msgToSign = json_encode($jsonObjectToSign); 

    openssl_sign($msgToSign, $jsonObjectToSign->signature, $privateKey, OPENSSL_SLGO_SHA1); 

    return $jsonObjectToSign; 
} 

समस्या यह है कि उदा। जावा में, यह बताने का कोई तरीका नहीं है कि JSON ऑब्जेक्ट के गुण उसी क्रम में होंगे जो आपने उन्हें जोड़ा था (JSONObject.put() के माध्यम से)। तो, अगर मैं PHP में एक

$json = json_encode('{"a":1, "b":2}'); 

करते हैं, इस वस्तु के रूप में ऊपर कहा गया है पर हस्ताक्षर, एक जावा आधारित सर्वर पर स्थानांतरित करते हैं, json वस्तु को डिकोड और उसके बाद हस्ताक्षर सत्यापित करने का प्रयास करें, मैं शायद एक अलग मिलता था वस्तु के गुणों का क्रम।

तो मुझे जो चाहिए वह एक भाषा या मंच से स्वतंत्र, JSONObject से स्ट्रिंग बनाने का एक विश्वसनीय तरीका है।

उपरोक्त उदाहरण वस्तु को हमेशा {"a":1, "b":2} आउटपुट और {"b":2, "a":1} आउटपुट की आवश्यकता होती है। दुर्भाग्यवश, यह सामान्य मामला है उदा। जावा में

क्या JSON ऑब्जेक्ट्स को सुरक्षित तरीके से साइन करने के लिए कोई "सर्वोत्तम अभ्यास" है?

लेकिन मुझे किसी अन्य तरीके से समस्या का वर्णन करते हैं:

मान लीजिए कि मैं जावा में ऐसा करना चाहते हैं (या किसी भी अन्य भाषा) करते हैं:

JSONObject j = new JSONObject(); 
j.put("a", 1); 
j.put("b", 2); 

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

+0

सुनिश्चित नहीं हैं कि अगर [इस] (http://stackoverflow.com/questions/4670494/how-to-cryptographically-hash-a-json-object) एक डुप्लिकेट है, लेकिन यह निश्चित रूप से पढ़ने लायक है। जेएसओएन को पुनरुत्पादित हैश की गारंटी देने के लिए कुछ विचारों का प्रस्ताव दिया गया है। –

उत्तर

0

इस तरह मैंने इसे हल किया है। हेडर को छोड़कर, यह किसी भी तरह जोसे करता है। लेकिन जॉय बहुत अधिक ओवरहेड (और फीचर्स) लाने की ज़रूरत है, मुझे इसकी आवश्यकता नहीं है। तो मैं निम्नलिखित के साथ जाने का फैसला किया:

class Signature 
{ 
    private static $algorithm = OPENSSL_ALGO_SHA512; 
    private static $signaturePrefix = '-----BEGIN SIGNATURE-----'; 
    private static $signaturePostfix = '-----END SIGNATURE-----'; 

    public static function createSignature($message, $privateKey) 
    { 
     $signature = null; 

     openssl_sign($message, $signature, $privateKey, self::$algorithm); 

     return self::$signaturePrefix . base64_encode($signature) . self::$signaturePostfix; 
    } 

    public static function verifySignature($message, $publicKey, $signature) 
    { 
     $signature = str_replace(self::$signaturePrefix, '', $signature); 
     $signature = str_replace(self::$signaturePostfix, '', $signature); 

     return openssl_verify($message, base64_decode($signature), $publicKey, self::$algorithm); 
    } 

    public static function signJSON($jsonToSign, $privateKey) 
    { 
     if(gettype($jsonToSign) != 'string') 
      $jsonToSign = json_encode($jsonToSign); 

     $signedJSON = json_decode('{}'); 
     $sigedJSON->signature = self::createSignature($message, $privateKey); 
     $signedJSON->object = $jsonToSign; 

     return $signedJSON; 
    } 

    public static function verifyJSONSignature($jsonObject, $publicKey) 
    { 
     if(gettype($jsonObject->object) == 'string') 
      throw new Exception('Value $jsonObject->object must be a String, is a ' . gettype($jsonObject->object)); 

     return self::verifySignature($jsonObject->object, $publicKey, $jsonObject->signature); 
    } 
} 
+0

आपने अन्य प्लेटफ़ॉर्म और भाषाओं में JSON के तत्वों के आदेश को कैसे सत्यापित किया? –

+0

'jsonToSign' को एक स्ट्रिंग के रूप में क्रमबद्ध किया गया है और फिर हस्ताक्षरित किया गया है। यह किसी भी JSON कार्यान्वयन को हस्ताक्षर सत्यापित करने की अनुमति देता है, लेकिन वास्तविक डेटा प्राप्त करने के लिए अतिरिक्त एन्कोडिंग/डिकोडिंग चरण की आवश्यकता होती है। –

2

जैसा कि AFAIK JSON पर अभी तक कोई आधिकारिक (न तो अनौपचारिक) मानक है, मैं शायद एक कस्टम कार्यान्वयन करता हूं। मैं एक नया JSON ऑब्जेक्ट परिभाषित करता हूं, उदा।

{ 
    "original": "..." // original JSON as a Base64 encoded string 
    "signature": "..." // the signature 
} 

और मेरे सिस्टम के दोनों तरफ एक हस्ताक्षर/हस्ताक्षर सत्यापन परत लागू करें।

+0

यह थोडा है जो मैं अभी कर रहा हूं।किसी भी तरह, ऑब्जेक्ट का उपयोग करते समय और फिर बेस 64 प्रस्तुति के निर्माण के दौरान, मुझे शायद विभिन्न प्रणालियों पर एक अलग बेस 64 प्रतिनिधित्व मिलेगा। इसलिए, हस्ताक्षर की जांच शायद असफल हो जाएगी। – Xenonite

+1

नहीं, बेस 64 समान होना चाहिए (आईएमएचओ)। या आपका मतलब है, उदाहरण के लिए मूल JSON स्ट्रिंग में फ़ील्ड का क्रम भिन्न हो सकता है, और इस प्रकार बेस 64 स्ट्रिंग अलग-अलग हो जाएगी? लेकिन यह कोई समस्या नहीं होनी चाहिए, आप बेस 64 स्ट्रिंग पर हस्ताक्षर करेंगे, मूल नहीं। और आपको फ़ील्ड ऑर्डर की परवाह नहीं है, लक्ष्य प्रणाली के रूप में आप पहले बेस 64 स्ट्रिंग ** के हस्ताक्षर ** को मान्य करते हैं, फिर मूल प्राप्त करने के लिए इसे डीकोड करें, और अंततः इसे लोड करें। लेकिन डीकोडिंग और लोड करके आप हस्ताक्षर की परवाह नहीं करते हैं। –

+0

हां, यही समस्या है जिसके बारे में मैं बात कर रहा हूं। दुर्भाग्य से, मुझे अपने फ्रेमवर्क में इस स्ट्रिंग प्रस्तुति को "प्राप्त नहीं" मिलता है, मुझे बस JSON ऑब्जेक्ट मिलता है। तो मुझे हमेशा एक ही बेस 64 प्रतिनिधित्व बनाने के लिए एक तरीका चाहिए। – Xenonite

3

हस्ताक्षर और JSON वस्तुओं की एन्क्रिप्शन विनिर्देशों के जोस सूट जहां जोस जावास्क्रिप्ट वस्तु हस्ताक्षर और एन्क्रिप्शन के लिए खड़ा है में निर्दिष्ट किया जाता, http://jose.readthedocs.org/en/latest/ देख जोस JSON ऑब्जेक्ट की एक base64url एनकोड प्रतिनिधित्व पर गणना की एक अलग हस्ताक्षर का उपयोग करता है। हस्ताक्षर JSON ऑब्जेक्ट का हिस्सा नहीं है, इसलिए इसे सत्यापित करने के लिए कोई पुन: क्रमिक आवश्यकता नहीं है।

+0

जोस अभी तक अंतिम नहीं है, है ना? –

+0

वे हैं, देखें: http://self-issued.info/?p=1387 –

+0

धन्यवाद, आपने यह नहीं देखा है। –

-1
JsonObject js = new JsonObject(); 
js.addProperty("c", "123"); 
js.addProperty("t", "yyyy-MM-dd'T'HH:mm:ss.SSSZ"); 
System.out.println("Json object == " + js); 
GenerateSignature util = new GenerateSignature(); 
String ecodedToken = util.signJSONObject(js); 
+0

स्टैक ओवरफ़्लो में आपका स्वागत है :-) कृपया [उत्तर] देखें। आपको कुछ जानकारी प्रदान करनी चाहिए क्यों आपका कोड समस्या हल करता है। कोड-केवल उत्तर समुदाय के लिए उपयोगी नहीं हैं। – JimHawkins

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