এই নথিটি আনুষ্ঠানিকভাবে AES-CTR HMAC স্ট্রিমিং কী দ্বারা উপস্থাপিত গাণিতিক ফাংশনকে সংজ্ঞায়িত করে (প্রোটো ফর্ম্যাটে type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey
হিসাবে এনকোড করা হয়েছে)।
এই এনক্রিপশনটি ঢিলেঢালাভাবে [HRRV15] 1 এর উপর ভিত্তি করে। নিরাপত্তা বিশ্লেষণের জন্য আমরা [HS20] 2 উল্লেখ করি। এছাড়াও নোট করুন যে Tink ক্রস ল্যাঙ্গুয়েজ টেস্টে একটি পরীক্ষা আছে aes_ctr_hmac_streaming_key_test.py যাতে test_manually_created_test_vector
থাকে এবং কিভাবে একটি সাইফারটেক্সট পেতে হয় তার সম্পূর্ণ ওয়াকথ্রু সহ।
কী এবং পরামিতি
কীগুলি নিম্নলিখিত অংশগুলি দ্বারা বর্ণনা করা হয়েছে (এই নথিতে সমস্ত আকার বাইটে রয়েছে):
- \(\mathrm{InitialKeyMaterial}\), একটি বাইট স্ট্রিং: প্রাথমিক কী উপাদান।
- \(\mathrm{CiphertextSegmentSize} \in \{1, 2, \ldots, 2^{31}-1\}\).
- \(\mathrm{DerivedKeySize} \in \{16, 32\}\).
- \(\mathrm{HkdfHashType} \in \{\mathrm{SHA1}, \mathrm{SHA256}, \mathrm{SHA512}\}\).
- \(\mathrm{HmacHashType} \in \{\mathrm{SHA1}, \mathrm{SHA256}, \mathrm{SHA512}\}\).
- \(\mathrm{HmacTagSize} \in \mathbb{N}\).
বৈধ কীগুলি অতিরিক্তভাবে নিম্নলিখিত বৈশিষ্ট্যগুলিকে সন্তুষ্ট করে:
- \(\mathrm{len}(\mathrm{InitialKeyMaterial}) \geq \mathrm{DerivedKeySize}\).
- যদি \(\mathrm{HmacHashType} = \mathrm{SHA1}\) তারপর \(\mathrm{HmacTagSize} \in \{10, \ldots, 20\}\).
- যদি \(\mathrm{HmacHashType} = \mathrm{SHA256}\) তারপর \(\mathrm{HmacTagSize} \in \{10, \ldots, 32\}\).
- যদি \(\mathrm{HmacHashType} = \mathrm{SHA512}\) তারপর \(\mathrm{HmacTagSize} \in \{10, \ldots, 64\}\).
- \(\mathrm{CiphertextSegmentSize} > \mathrm{DerivedKeySize} + \mathrm{HmacTagSize} + 8\) (এটি সমান\(\mathrm{len}(\mathrm{Header}) + \mathrm{HmacTagSize}\) যেমনটি পরে ব্যাখ্যা করা হয়েছে)।
যে কীগুলি এই বৈশিষ্ট্যগুলির কোনওটিই সন্তুষ্ট করে না সেগুলি টিঙ্ক দ্বারা প্রত্যাখ্যান করা হয় (হয় যখন কীটি পার্স করা হয় বা যখন সংশ্লিষ্ট আদিম তৈরি করা হয়)৷
এনক্রিপশন ফাংশন
একটি বার্তা এনক্রিপ্ট করতে \(\mathrm{Msg}\) সংশ্লিষ্ট ডেটা সহ\(\mathrm{AssociatedData}\), আমরা একটি হেডার তৈরি করি, বার্তাটিকে সেগমেন্টে বিভক্ত করি, প্রতিটি সেগমেন্ট এনক্রিপ্ট করি এবং সেগমেন্টগুলিকে সংযুক্ত করি। আমরা নিম্নলিখিত এই পদক্ষেপগুলি ব্যাখ্যা করি।
হেডার তৈরি করা হচ্ছে
হেডার তৈরি করতে, আমরা প্রথমে একটি অভিন্ন র্যান্ডম স্ট্রিং বাছাই করি \(\mathrm{Salt}\)দৈর্ঘ্যের \(\mathrm{DerivedKeySize}\). আমরা পরবর্তীতে একটি অভিন্ন র্যান্ডম স্ট্রিং বাছাই করি\(\mathrm{NoncePrefix}\) দৈর্ঘ্য 7.
আমরা তারপর সেট\(\mathrm{Header} := \mathrm{len}(\mathrm{Header}) \| \mathrm{Salt} \| \mathrm{NoncePrefix}\), যেখানে হেডারের দৈর্ঘ্য একক বাইট হিসাবে এনকোড করা হয়। আমরা যে নোট\(\mathrm{len}(\mathrm{Header}) \in \{24, 40\}\).
এর পরে, আমরা হ্যাশ-ফাংশন সহ HKDF 3 ব্যবহার করি \(\mathrm{HkdfHashType}\)দৈর্ঘ্যের মূল উপাদান গণনা করতে\(\mathrm{DerivedKeySize} + 32\) এই বার্তার জন্য:\(k := \mathrm{HKDF}(\mathrm{InitialKeyMaterial}, \mathrm{Salt}, \mathrm{AssociatedData})\). ইনপুট এর সংশ্লিষ্ট নিজ নিজ ইনপুট ব্যবহার করা হয়\(\mathrm{HKDF}\): \(\mathrm{InitialKeyMaterial}\) হয় \(\mathrm{ikm}\),\(\mathrm{Salt}\) লবণ হয়, এবং\(\mathrm{AssociatedData}\) হিসাবে ব্যবহৃত হয় \(\mathrm{info}\).
স্ট্রিং \(k\) তারপর দুই ভাগে বিভক্ত করা হয় \(k_1 \| k_2 := k\), যেমন যে\(\mathrm{len}(k_1) = \mathrm{DerivedKeySize}\) এবং \(\mathrm{len}(k_2) = 32\).
বার্তা বিভক্ত করা
বার্তাটি \(M\) পরবর্তী অংশে বিভক্ত: \(M = M_0 \| M_1 \| \cdots \| M_{n-1}\).
তাদের দৈর্ঘ্য বেছে নেওয়া হয়েছে যাতে তারা সন্তুষ্ট হয়:
- \(\mathrm{len}(M_0) \in \{0,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{len}(\mathrm{Header}) - \mathrm{HmacTagSize}\}\).
- যদি \(n > 1\), তারপর \(\mathrm{len}(M_1), \ldots, \mathrm{len}(M_{n-1}) \in \{1,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{HmacTagSize}\}\).
- যদি \(n > 1\), তারপর \(M_{0}, \ldots, M_{n-2}\) সীমাবদ্ধতা উপরোক্ত অনুযায়ী সর্বোচ্চ দৈর্ঘ্য থাকতে হবে.
এই বিভাজনে, \(n\) সর্বাধিক হতে পারে \(2^{32}\). অন্যথায়, এনক্রিপশন ব্যর্থ হয়।
ব্লক এনক্রিপ্ট করা হচ্ছে
সেগমেন্ট এনক্রিপ্ট করতে \(M_i\), আমরা প্রথমে গণনা করি\(\mathrm{IV}_i := \mathrm{NoncePrefix} \| \mathrm{i} \| b \| 0x00000000\), যেখানে আমরা এনকোড করি \(\mathrm{i}\) বিগ-এন্ডিয়ান এনকোডিং ব্যবহার করে 4 বাইটে, এবং $i < n-1$ এবং অন্যথায় 0x01
হলে বাইট $b$ 0x00
সেট করুন।
তারপর আমরা এনক্রিপ্ট করি \(M_i\) AES CTR কী ব্যবহার করে \(k_1\), এবং আরম্ভ ভেক্টর\(\mathrm{IV}_i\). অন্য কথায়, AES এর আহ্বানের ইনপুটগুলি হল\(\mathrm{IV}_i, \mathrm{IV}_i + 1, \mathrm{IV}_i + 2, \ldots\)যেখানে \(\mathrm{IV}_i\) বড়-এন্ডিয়ান পূর্ণসংখ্যা হিসাবে ব্যাখ্যা করা হয়। এই ফলন \(C'_i\).
আমরা হ্যাশ ফাংশন দিয়ে HMAC ব্যবহার করে ট্যাগ গণনা করি \(\mathrm{HmacHashType}\) এবং চাবি দিয়ে \(k_2\) সংযোগের উপর\(\mathrm{IV}_i \| C'_i\).
তারপরে আমরা ট্যাগটি পেতে সাইফারটেক্সটকে সংযুক্ত করি \(C_i\).
বিভাগগুলিকে সংযুক্ত করুন
পরিশেষে, সমস্ত বিভাগ হিসাবে একত্রিত হয়\(\mathrm{Header} \| C_0 \| \cdots \| C_{n-1}\), যা চূড়ান্ত সাইফারটেক্সট।
ডিক্রিপশন ফাংশন
ডিক্রিপশন সহজভাবে এনক্রিপশনকে উল্টে দেয়। আমরা নন্স পেতে হেডার ব্যবহার করি এবং সাইফারটেক্সটের প্রতিটি সেগমেন্টকে পৃথকভাবে ডিক্রিপ্ট করি।
APIs (এবং সাধারণত করে) র্যান্ডম অ্যাক্সেস, বা ফাইলের শেষ পরিদর্শন ছাড়াই একটি ফাইলের শুরুতে অ্যাক্সেসের অনুমতি দিতে পারে। এটি ইচ্ছাকৃত, যেহেতু এটি ডিক্রিপ্ট করা সম্ভব \(M_i\) থেকে \(C_i\), সমস্ত পূর্ববর্তী এবং অবশিষ্ট সাইফারটেক্সট ব্লকগুলি ডিক্রিপ্ট না করে।
যাইহোক, API-এর সতর্কতা অবলম্বন করা উচিত যাতে ব্যবহারকারীরা ফাইলের শেষ এবং ডিক্রিপশন ত্রুটিগুলিকে বিভ্রান্ত করতে না পারে: উভয় ক্ষেত্রেই API-কে সম্ভবত একটি ত্রুটি ফেরত দিতে হবে এবং পার্থক্য উপেক্ষা করার ফলে একটি প্রতিপক্ষকে কার্যকরভাবে ফাইল ছেঁটে ফেলতে সক্ষম হতে পারে।
ক্রমিককরণ এবং কীগুলির পার্সিং
"Tink Proto" ফরম্যাটে একটি কীকে সিরিয়ালাইজ করতে, আমরা প্রথমে aes_ctr_hmac_streaming.proto এ প্রদত্ত প্রোটোতে স্পষ্টভাবে প্যারামিটারগুলি ম্যাপ করি। ক্ষেত্র version
0 তে সেট করা দরকার। তারপরে আমরা এটিকে সাধারণ প্রোটো সিরিয়ালাইজেশন ব্যবহার করে সিরিয়ালাইজ করি এবং ফলাফল স্ট্রিংটিকে একটি কীডেটা প্রোটোর ক্ষেত্রের মানটিতে এম্বেড করি। আমরা type_url
ক্ষেত্রটিকে type.googleapis.com/google.crypto.tink.AesCtrHmacStreamingKey
এ সেট করেছি। আমরা তখন key_material_type
SYMMETRIC
এ সেট করি এবং এটিকে একটি কীসেটে এম্বেড করি। আমরা সাধারণত output_prefix_type
RAW
এ সেট করি। ব্যতিক্রম হল যদি output_prefix_type
এর জন্য একটি ভিন্ন মান সেট করে কী পার্স করা হয়, Tink হয় RAW
বা পূর্ববর্তী মান লিখতে পারে।
একটি কী পার্স করতে, আমরা উপরের প্রক্রিয়াটিকে বিপরীত করি (প্রোটো পার্স করার সময় স্বাভাবিক উপায়ে)। ক্ষেত্র key_material_type
উপেক্ষা করা হয়। output_prefix_type
এর মান হয় উপেক্ষা করা যেতে পারে, অথবা RAW
থেকে আলাদা output_prefix_type
আছে এমন কীগুলি প্রত্যাখ্যান করা যেতে পারে। 0 থেকে ভিন্ন version
আছে এমন কীগুলি প্রত্যাখ্যান করা হবে।
তথ্যসূত্র
[HRRV15] Hoang, Reyhanitabar, Rogaway, Vizar. অনলাইন প্রমাণীকৃত-এনক্রিপশন এবং এর অ-পুনঃব্যবহার অপব্যবহার-প্রতিরোধ। CRYPTO 2015। https://eprint.iacr.org/2015/189 ↩
[HS20] গুগলের টিঙ্ক লাইব্রেরিতে স্ট্রিমিং এনক্রিপশনের নিরাপত্তা। হোয়াং, শেন, 2020। https://eprint.iacr.org/2020/1019 ↩
[HKDF] HMAC-ভিত্তিক Extract-and-Expand Key Derivation Function (HKDF), RFC 5869. https://www.rfc-editor.org/rfc/rfc5869 ↩