हमारा सुझाव है कि जब निजी पासकोड ऐसी जगह पर हो जहां मैसेज नहीं भेजा जा सकता, तब ML_DSA_44 कुंजी के साथ Prehash और SignPrehash प्रिमिटिव का इस्तेमाल करें.
कभी-कभी, साइनिंग पासकोड रखने वाली पार्टी को मैसेज नहीं मिल पाता या उसे मैसेज नहीं मिलना चाहिए: पासकोड, एचएसएम या केएमएस में मौजूद होता है या मैसेज, हस्ताक्षर करने वाले के अनुरोध के साइज़ की सीमा से बड़ा होता है.
Prehash और SignPrehash प्रिमिटिव, हस्ताक्षर करने की प्रोसेस को दो चरणों में बांटकर इस समस्या को हल करते हैं. सिर्फ़ सार्वजनिक पासकोड का इस्तेमाल करके, मैसेज की छोटी प्रीहैश वैल्यू का हिसाब लगाया जाता है. इसके बाद, इसे हस्ताक्षर करने वाले व्यक्ति को भेजा जाता है. हस्ताक्षर करने वाला व्यक्ति, मैसेज को देखे बिना निजी कुंजी का इस्तेमाल करके, उसे हस्ताक्षर में बदल देता है. External Mu मोड में एमएल-डीएसए के साथ, प्रीहैश वैल्यू 69 बाइट होती है. भले ही, मैसेज का साइज़ कुछ भी हो. इस मोड में, Tink एल्गोरिदम काम करता है.
आपको जो हस्ताक्षर मिलता है वह ओरिजनल मैसेज पर किया गया सामान्य हस्ताक्षर होता है: पुष्टि करने वाले लोग, सामान्य डिजिटल सिग्नेचर प्रिमिटिव का इस्तेमाल करते हैं. उन्हें यह जानने की ज़रूरत नहीं होती कि इसमें दो चरण शामिल थे.
शुरू करने से पहले
एक ऐसा एमएल-डीएसए कीसेट बनाएं जिसके कुंजियों के लिए आईडी की ज़रूरत हो. इसके लिए, TINK वैरिएंट का इस्तेमाल करें. अगर आपको नतीजे के तौर पर मिले हस्ताक्षर पर आउटपुट प्रीफ़िक्स नहीं चाहिए, तो NO_PREFIX_WITH_PREHASH_ID का इस्तेमाल करें. हस्ताक्षर करने वाले को निजी पासकोड का सेट और प्रीहैशिंग करने वाले को उससे जुड़ा सार्वजनिक पासकोड का सेट दें. हस्ताक्षर करने वाले के पास, हर उस कुंजी आईडी के लिए चालू की गई कुंजी होनी चाहिए जिसे प्रीहैशिंग करने वाला पक्ष जनरेट कर सकता है. कीसेट देखें.
पहला चरण: प्रीहैश वैल्यू का हिसाब लगाना
इसे वहां चलाएं जहां मैसेज मौजूद है. इसके लिए, सिर्फ़ सार्वजनिक पासकोड की ज़रूरत होती है.
C++
#include "tink/keyset_handle.h" #include "tink/signature/config_2026.h" #include "tink/signature/prehash.h" absl::StatusOr<std::unique_ptr<crypto::tink::Prehash>> prehasher = public_handle.GetPrimitive<crypto::tink::Prehash>( crypto::tink::ConfigSignature2026()); if (!prehasher.ok()) return prehasher.status(); absl::StatusOr<std::string> prehash = (*prehasher)->Compute(message); if (!prehash.ok()) return prehash.status();
ऐप पर जाएं
import "github.com/tink-crypto/tink-go/v2/signprehash" prehasher, err := signprehash.NewPrehash(publicHandle) if err != nil { return err } prehash, err := prehasher.ComputePrehash(message) if err != nil { return err }
Python
from tink import signature # Due to the internal structure of Tink Python, Prehash and SignPrehash # are an exception where calling signature.register() is not necessary. # Do not expect the same for other primitives (such as PublicKeyVerify in # Step 4). prehasher = public_handle.primitive(signature.Prehash) prehash = prehasher.compute(message)
दूसरा चरण: हस्ताक्षर करने वाले व्यक्ति को प्रीहैश वैल्यू भेजें
प्रीहैश की गई वैल्यू को उस सिस्टम को भेजें जिसके पास निजी पासकोड है. यह कोई सीक्रेट नहीं है. हालांकि, आपको ट्रांज़िट के दौरान इसकी इंटीग्रिटी को सुरक्षित रखना होगा: हमलावर, फ़्लाइट के दौरान इसमें बदलाव कर सकता है. इससे यह तय होता है कि किस चीज़ पर हस्ताक्षर किए जाएंगे.
तीसरा चरण: प्रीहैश वैल्यू पर हस्ताक्षर करना
इसे उस जगह पर चलाएं जहां निजी पासकोड मौजूद है.
C++
#include "tink/keyset_handle.h" #include "tink/signature/config_2026.h" #include "tink/signature/sign_prehash.h" absl::StatusOr<std::unique_ptr<crypto::tink::SignPrehash>> signer = private_handle.GetPrimitive<crypto::tink::SignPrehash>( crypto::tink::ConfigSignature2026()); if (!signer.ok()) return signer.status(); absl::StatusOr<std::string> signature = (*signer)->Sign(prehash); if (!signature.ok()) return signature.status();
ऐप पर जाएं
import "github.com/tink-crypto/tink-go/v2/signprehash" signer, err := signprehash.NewPrehashSigner(privateHandle) if err != nil { return err } sig, err := signer.SignPrehash(prehash) if err != nil { return err }
Python
from tink import signature # Due to the internal structure of Tink Python, Prehash and SignPrehash # are an exception where calling signature.register() is not necessary. # Do not expect the same for other primitives (such as PublicKeyVerify in # Step 4). signer = private_handle.primitive(signature.SignPrehash) sig = signer.sign(prehash)
चौथा चरण: हस्ताक्षर की पुष्टि करना
पुष्टि, ओरिजनल मैसेज पर डिजिटल हस्ताक्षर की सामान्य प्रोसेस है. यह प्रीहैश वैल्यू पर नहीं होती.
C++
absl::StatusOr<std::unique_ptr<crypto::tink::PublicKeyVerify>> verifier = public_handle.GetPrimitive<crypto::tink::PublicKeyVerify>( crypto::tink::ConfigSignature2026()); if (!verifier.ok()) return verifier.status(); absl::Status verified = (*verifier)->Verify(signature, message);
ऐप पर जाएं
import "github.com/tink-crypto/tink-go/v2/signature" verifier, err := signature.NewVerifier(publicHandle) if err != nil { return err } if err := verifier.Verify(sig, message); err != nil { return err }
Python
from tink import signature signature.register() verifier = public_handle.primitive(signature.PublicKeyVerify) verifier.verify(sig, message)
Prehash और SignPrehash
Prehash और SignPrehash प्रिमिटिव, डिजिटल हस्ताक्षर की गणना को दो चरणों में बांटते हैं:
- प्रीहैश के लिए सिर्फ़ सार्वजनिक कुंजी की ज़रूरत होती है. यह किसी भी लंबाई के मैसेज को, तय साइज़ वाली छोटी प्रीहैश वैल्यू में बदलता है.
- SignPrehash के लिए, private कुंजी की ज़रूरत होती है. यह प्रीहैश वैल्यू को सिग्नेचर में बदलता है.
इस तरह से जनरेट किया गया हस्ताक्षर, ओरिजनल मैसेज पर किया गया सामान्य हस्ताक्षर होता है. इसकी पुष्टि, सामान्य डिजिटल सिग्नेचर PublicKeyVerify प्रिमिटिव से की जाती है. साथ ही, पुष्टि करने वालों को यह जानने की ज़रूरत नहीं होती कि हस्ताक्षर दो चरणों में बनाया गया था.
प्रीहैश वैल्यू को ओपेक बाइट के तौर पर इस्तेमाल करें. इसका साइज़ तय होता है. इसमें उस कुंजी का आईडी होता है जिसके लिए इसे कंप्यूट किया गया था. हालांकि, इसका लेआउट Tink के वायर फ़ॉर्मैट का हिस्सा होता है. इसलिए, आपको इसे खुद से पार्स या कंस्ट्रक्ट नहीं करना चाहिए. अगर आपको Tink को पोर्ट करना है या बाइट-लेवल की जानकारी चाहिए, तो Tink वायर फ़ॉर्मैट देखें.
इन प्रिमिटिव का इस्तेमाल तब करें, जब:
- हस्ताक्षर करने वाली कुंजी किसी दूसरी जगह पर मौजूद है. उदाहरण के लिए, एचएसएम, केएमएस या आरपीसी बाउंड्री के पीछे. साथ ही, आपको पूरा मैसेज उस बाउंड्री के पार नहीं भेजना है.
- मैसेज का साइज़ बहुत बड़ा है. साथ ही, रिमोट हस्ताक्षर करने वाला व्यक्ति अनुरोध के साइज़ की सीमा लागू करता है.
अगर इनमें से कोई भी विकल्प लागू नहीं होता है, तो इसके बजाय सामान्य डिजिटल सिग्नेचर प्रिमिटिव का इस्तेमाल करें: यह ज़्यादा आसान है और इसका गलत इस्तेमाल करना मुश्किल है.
कीसेट
दोनों प्रिमिटिव, कुंजियों को अलग-अलग तरीके से चुनती हैं. ठीक उसी तरह जैसे साइनिंग और पुष्टि करने की सुविधा, डिजिटल सिग्नेचर प्रिमिटिव के लिए करती है:
Prehash.Computeहमेशा सार्वजनिक पासकोड सेट की प्राइमरी कुंजी का इस्तेमाल करता है. साथ ही, उस कुंजी के आईडी को प्रीहैश वैल्यू में रिकॉर्ड करता है. यह वह पक्ष है जो यह चुनता है कि हस्ताक्षर किस कुंजी से किया जाएगा.SignPrehash.Sign, प्रीहैश वैल्यू से मुख्य आईडी को पढ़ता है और निजी पासकोड के सेट की मैच होने वाली चालू की गई कुंजी से साइन करता है. यह वह पक्ष है जो किसी दूसरे व्यक्ति के पहले से किए गए फ़ैसले को फ़ॉलो करता है. अगर कीसेट में चालू की गई किसी भी कुंजी में वह आईडी नहीं है, तो कॉल नहीं किया जा सकेगा.
SignPrehash के कीसेट में मौजूद हर कुंजी के लिए, आईडी की ज़रूरत होती है. ऐसा न होने पर, प्रिमिटिव नहीं बन पाता.
सुरक्षा से जुड़ी कम से कम गारंटी
- इस सिग्नेचर की प्रॉपर्टी, Digital Signature प्रिमिटिव से जनरेट किए गए सिग्नेचर की प्रॉपर्टी जैसी ही होती हैं. हालांकि, दोनों के लिए एक ही तरह की कुंजी इस्तेमाल की जाती है.
- Tink, प्रीहैश वैल्यू में 5 बाइट का प्रीफ़िक्स जोड़ता है. इसमें खास रिज़र्व वैल्यू और उस कुंजी का आईडी होता है जिसके लिए इसे कंप्यूट किया गया था.
SignPrehashसिर्फ़ उस कुंजी की मदद से वैल्यू पर हस्ताक्षर करता है. वैल्यू, उस कुंजी से क्रिप्टोग्राफ़िक तौर पर जुड़ी है या नहीं, यह एल्गोरिदम पर निर्भर करता है. External Mu ML-DSA के लिए, यह जुड़ी होती है. इसके बारे में जानने के लिए, Tink वायर फ़ॉर्मैट देखें. - मैसेज की लंबाई कितनी भी हो सकती है.
इन बातों का ध्यान रखें
- हस्ताक्षर करने वाला व्यक्ति, उस कॉन्टेंट की जांच नहीं कर सकता जिस पर उसे हस्ताक्षर करना है.
SignPrehashको कॉल करने वाला कोई भी व्यक्ति, किसी भी मैसेज पर हस्ताक्षर कर सकता है. हस्ताक्षर करने वाले के पास, मैसेज के कॉन्टेंट पर नीति लागू करने का कोई तरीका नहीं होता.SignPrehashके ऐक्सेस को ठीक उसी तरह सुरक्षित रखें जिस तरहPublicKeySignके ऐक्सेस को सुरक्षित रखा जाता है. - ट्रांज़िट में प्रीहैश वैल्यू को सुरक्षित रखें. यह कोई सीक्रेट नहीं है. हालांकि, हमलावर इसे बदल सकता है. इसलिए, हमलावर यह तय करता है कि किस चीज़ पर हस्ताक्षर किए जाएंगे.
कुंजी का टाइप चुनें
External Mu मोड में एमएल-डीएसए, RFC 9881 में बताए गए तरीके के मुताबिक, प्रीहैश और साइनप्रीहैश के लिए Tink का इस्तेमाल किया जाने वाला एकमात्र एल्गोरिदम है. आपको इन प्रिमिटिव के साथ स्टैंडर्ड एमएल-डीएसए पासकोड का इस्तेमाल करना चाहिए.
हम ज़्यादातर मामलों में ML_DSA_44 का इस्तेमाल करने का सुझाव देते हैं.
कुंजी के लिए आईडी की ज़रूरत होती है, क्योंकि हर प्रीहैश वैल्यू ऐसे प्रीफ़िक्स से शुरू होती है जिसमें उस कुंजी का आईडी होता है जिसके लिए उसे कंप्यूट किया गया था. इन वैरिएंट को स्वीकार किया जाता है:
TINK-- इससे मिलने वाला सिग्नेचर, Tink के सामान्य 5-बाइट आउटपुट प्रीफ़िक्स से शुरू होता है.NO_PREFIX_WITH_PREHASH_ID-- इस हस्ताक्षर में कोई आउटपुट प्रीफ़िक्स नहीं होता है. हालांकि, कुंजी में अब भी वह आईडी होता है जिसकी ज़रूरत प्रीहैश वैल्यू को होती है.
NO_PREFIX (रॉ) वैरिएंट का इस्तेमाल करने वाली कुंजियों के साथ काम नहीं करता, क्योंकि उनके पास कोई कुंजी आईडी नहीं होता.