Runtime: المستوى الأولي العام للأصفار (AES-GCM هو الأول)

تم إنشاؤها على ٢٩ أغسطس ٢٠١٧  ·  143تعليقات  ·  مصدر: dotnet/runtime

المنطق

هناك حاجة عامة لعدد من الأصفار للتشفير. أصبح مزيج اليوم من الواجهات والفئات مفككة بعض الشيء. كما لا يوجد دعم لأصفار نمط AEAD لأنها تحتاج إلى القدرة على توفير معلومات مصادقة إضافية. التصميمات الحالية عرضة أيضًا للتخصيص ومن الصعب تجنبها بسبب المصفوفات المرتجعة.

API المقترحة

فئة أساسية مجردة للأغراض العامة سيتم تنفيذها بواسطة فئات محددة. سيسمح هذا بالتوسع وأيضًا من خلال وجود فئة بدلاً من الأساليب الثابتة ، لدينا القدرة على إنشاء طرق تمديد بالإضافة إلى حالة الانتظار بين المكالمات. يجب أن تسمح واجهة برمجة التطبيقات (API) بإعادة تدوير الفئة للسماح بتخصيصات أقل (لا تحتاج إلى مثيل جديد في كل مرة ، وللتقاط المفاتيح غير المُدارة على سبيل المثال). نظرًا للطبيعة غير المُدارة غالبًا للموارد التي يتم تعقبها ، يجب أن تقوم الفئة بتطبيق IDisposable

public abstract class Cipher : IDisposable
{
    public virtual int TagSize { get; }
    public virtual int IVSize { get; }
    public virtual int BlockSize { get; }
    public virtual bool SupportsAssociatedData { get; }

    public abstract void Init(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv);
    public abstract void Init(ReadOnlySpan<byte> iv);
    public abstract int Update(ReadOnlySpan<byte> input, Span<byte> output);
    public abstract int Finish(ReadOnlySpan<byte> input, Span<byte> output);
    public abstract void AddAssociatedData(ReadOnlySpan<byte> associatedData);
    public abstract int GetTag(Span<byte> span);
    public abstract void SetTag(ReadOnlySpan<byte> tagSpan);
}

مثال على الاستخدام

(مصدر الإدخال / الإخراج عبارة عن دفق أسطوري قائم على الامتداد مثل مصدر الإدخال / الإخراج)

using (var cipher = new AesGcmCipher(bitsize: 256))
{
    cipher.Init(myKey, nonce);
    while (!inputSource.EOF)
    {
        var inputSpan = inputSource.ReadSpan(cipher.BlockSize);
        cipher.Update(inputSpan);
        outputSource.Write(inputSpan);
    }
    cipher.AddAssociatedData(extraInformation);
    cipher.Finish(finalBlockData);
    cipher.GetTag(tagData);
}

سلوك API

  1. إذا تم استدعاء علامة get قبل الانتهاء ، فيجب إلقاء [نوع الاستثناء؟] ويجب تعيين الحالة الداخلية على "غير صالحة"
  2. إذا كانت العلامة غير صالحة عند الانتهاء لفك التشفير ، فيجب أن تكون استثناءً تم طرحه
  3. بمجرد الانتهاء ، سيتم استدعاء أي شيء آخر غير إحدى طرق التهيئة
  4. بمجرد استدعاء Init ، ستصدر مكالمة ثانية بدون "إنهاء"
  5. إذا كان النوع يتوقع مفتاحًا تم توفيره (مثيل "new'd" المستقيم لأعلى) إذا كان استدعاء "التهيئة" الأولي يحتوي على مفتاح IV فقط ، فسيتم طرحه
  6. إذا تم إنشاء النوع ، قل من مفتاح مستند إلى المتجر وحاولت تغيير المفتاح عبر التهيئة وليس فقط IV ، فسيتم طرحه
  7. إذا لم يتم استدعاء get tag قبل التخلص أو Init هل يجب طرح استثناء؟ لمنع المستخدم من عدم جمع البطاقة عن طريق الصدفة؟

المرجع dotnet / corefx # 7023

التحديثات

  1. تغيرت nonce إلى الرابع.
  2. قسم السلوك المضاف
  3. تمت إزالة حالات امتداد الإدخال / الإخراج الفردية من الإنهاء والتحديث ، يمكن أن تكون مجرد طرق امتداد
  4. تم تغيير عدد من الامتدادات إلى readonlyspan كما اقترحه bartonjs
  5. تمت إزالة إعادة التعيين ، يجب استخدام البادئة مع IV بدلاً من ذلك
api-suggestion area-System.Security

التعليق الأكثر فائدة

bartonjs أنت تتجاهل حرفياً جميع التحليلات الفنية والمنطقية وتستخدم بدلاً من ذلك تواريخ مشروعي Go و libsodium كبديل ضعيف للتحليل الحقيقي؟

لا ، أنا أستخدم نصيحة مصممي التشفير المحترفين الذين يقولون إنه خطير للغاية ويجب علينا تجنب بث AEAD. ثم أستخدم المعلومات من فريق CNG المكون من "العديد من الأشخاص يقولون إنهم يريدون ذلك من الناحية النظرية ، ولكن من الناحية العملية لا أحد يفعل ذلك تقريبًا" (لا أعرف مقدار القياس عن بُعد مقابل القصص من تقديم طلبات المساعدة). إن حقيقة أن المكتبات الأخرى قد سلكت طريق الطلقة الواحدة _يعزز _ القرار.

لماذا الطلب الذي تم إظهاره حتى الآن على GitHub غير كافٍ؟

تم ذكر عدد قليل من السيناريوهات. من المحتمل أن تتم معالجة المخازن المؤقتة المجزأة بقبول ReadOnlySequence ، إذا بدا أن هناك سيناريو كافٍ لتبرير تعقيد واجهة برمجة التطبيقات بدلاً من جعل المتصل يقوم بإعادة تجميع البيانات.

تمثل الملفات الكبيرة مشكلة ، لكن الملفات الكبيرة تمثل مشكلة بالفعل نظرًا لأن GCM بها حد خجول يبلغ 64 جيجابايت فقط ، وهو "ليس بهذا الحجم" (حسنًا ، إنه كبير جدًا ، ولكنه ليس "قف ، هذا كبير" هكذا كان الحال). تسمح الملفات المعينة للذاكرة باستخدام Spans (تصل إلى 2 ^ 31-1) دون الحاجة إلى ذاكرة وصول عشوائي (RAM) بسعة 2 جيجابايت. لذلك قمنا بحلق بضع بتات من الحد الأقصى ... من المحتمل أن يحدث ذلك بمرور الوقت على أي حال.

أنت تدرك أن اتخاذ قرار بشأن واجهة غير متدفقة لـ AEAD يمنع كل هذه التطبيقات على الطريق ، أليس كذلك؟

أنا مقتنع أكثر فأكثر بأن GrabYourPitchforks كان على حق (https://github.com/dotnet/corefx/issues/23629#issuecomment-334638891) أنه ربما لا توجد واجهة موحدة معقولة. GCM _requiring_ a nonce / IV and SIV _forbidding_ فهذا يعني أن تهيئة وضع / خوارزمية AEAD تتطلب بالفعل معرفة ما سيحدث ... لا يوجد حقًا فكرة "مجردة" لـ AEAD. تملي SIV أين تذهب "العلامة". GCM / CCM لا تفعل ذلك. SIV هو العلامة أولاً ، حسب المواصفات.

لا يمكن لـ SIV البدء في التشفير حتى تحتوي على جميع البيانات. لذا فإن تشفير التدفق الخاص به إما سيرمي (مما يعني أنه يجب عليك معرفة عدم تسميته) أو المخزن المؤقت (والذي قد ينتج عنه وقت تشغيل n ^ 2). لا يمكن أن يبدأ CCM حتى يعرف الطول ؛ لكن CNG لا تسمح بإعطاء تلميح مشفر مسبقًا بالطول ، لذا فهو موجود في نفس القارب.

لا يجب أن نصمم مكونًا جديدًا يكون من الأسهل فيه فعل الشيء الخطأ بدلاً من فعل الشيء الصحيح افتراضيًا. يجعل فك تشفير البث من السهل جدًا والمغري توصيل فئة Stream (على غرار اقتراحك للقيام بذلك باستخدام CryptoStream) مما يجعل من السهل جدًا الحصول على خطأ في التحقق من صحة البيانات قبل التحقق من العلامة ، مما يلغي تقريبًا فائدة AE . ( IGcmDecryptor => CryptoStream => StreamReader => XmlReader => "انتظر ، هذا ليس XML قانونيًا ..." => أوراكل النص المشفر التكيفي) .

إنها تصل إلى النقطة ... طلب ​​الزبون.

كما سمعت ، للأسف ، مرات عديدة في حياتي: أنا آسف ، لكنك لست العميل الذي نفكر فيه. سأعترف بأنه ربما تعرف كيفية القيام بـ GCM بأمان. أنت تعلم أن تقوم بالدفق فقط إلى ملف متغير / مخزن مؤقت / إلخ إلا بعد التحقق من العلامة. أنت تعرف ما تعنيه إدارة nonce ، وتعرف مخاطر فهمها بشكل خاطئ. أنت تعلم أنه يجب الانتباه إلى أحجام التدفق وتقطيعه إلى مقطع GCM جديد بعد 2 ^ 36-64 بايت. أنت تعلم أنه بعد كل ما قيل وفعلت ، فهذا هو الخطأ إذا فهمت هذه الأشياء بشكل خاطئ.

من ناحية أخرى ، فإن العميل الذي أفكر فيه هو شخص يعرف "يجب علي تشفير هذا" لأن رئيسه قال له ذلك. وهم يعلمون أنه عند البحث عن كيفية عمل التشفير ، قال بعض البرامج التعليمية "استخدم دائمًا AE" ويذكر GCM. ثم وجدوا البرنامج التعليمي "التشفير في .NET" الذي يستخدم CryptoStream. ثم يقومون بعد ذلك بتوصيل خط الأنابيب ، دون أن يكون لديهم أي فكرة بأنهم قاموا للتو بنفس الشيء مثل اختيار SSLv2 ... قاموا بفحص المربع من الناحية النظرية ، ولكن ليس في الواقع العملي. وعندما يفعلون ذلك ، فإن هذا الخطأ ينتمي إلى كل من عرف أفضل ، لكن اجعل الشيء الخطأ سهل التنفيذ.

ال 143 كومينتر

تقييم سريع للحكم على واجهة برمجة التطبيقات المقترحة (محاولة أن تكون مفيدة):

  • Span<T> ليس في NetStandard2 .
  • "Nonce" هو تطبيق محدد للغاية - أي. روائح GCM. ومع ذلك ، حتى مستندات GCM (مثل NIST SP800-38D) تشير إليها على أنها "IV" ، والتي - في حالة GCM - تصادف أنها nonce. ومع ذلك ، في حالة تطبيقات AEAD الأخرى ، لا يجب أن يكون IV رقمًا واحدًا (على سبيل المثال ، تكرار IV تحت CBC + HMAC ليس كارثيًا).
  • يجب أن يعمل البث المباشر AEAD إما بسلاسة مع CryptoStream ، أو أن يوفر "AEADCryptoStream" الخاص به والذي يسهل تدفقه إلى الداخل / الخارج مثل CryptoStream.
  • يجب السماح لعمليات محاكاة AEAD API بالقيام باشتقاق مفتاح داخلي بناءً على AAD (البيانات المرتبطة). يعد استخدام AAD فقط لحساب / التحقق من العلامات مقيدًا للغاية ويمنع نموذج AEAD أقوى.
  • يجب أن ترجع طرق "Get *" شيئًا ما (GetTag). إذا كانت باطلة ، فيجب أن تكون قد وضعت شيئًا ما / تغير الحالة.
  • ربما تكون محاولة الحصول على بطاقة قبل "الانتهاء" فكرة سيئة ، لذلك قد تكون "IsFinished" مفيدة.
  • فكر الأشخاص الذين صمموا ICryptoTransform في إعادة الاستخدام ، ودعم الكتل المتعددة ، وأحجام كتل الإدخال / الإخراج ذات الأحجام المختلفة. لم يتم التقاط هذه المخاوف.

كدليل على سلامة AEAD API ، لا ينبغي أن يكون أول تطبيق لواجهة برمجة التطبيقات المقترحة هو AES-GCM ، ولكن يجب أن يكون AES-CBC الكلاسيكي / الافتراضي بعلامة HMAC. والسبب البسيط لذلك هو أنه يمكن لأي شخص إنشاء تطبيق AES-CBC + HMAC AEAD اليوم ، باستخدام فئات .NET بسيطة وحالية ومعروفة. دعنا نحصل على [AES-CBC + HMAC] قديم ممل يعمل على واجهات برمجة تطبيقات AEAD الجديدة أولاً ، لأنه من السهل على الجميع MVP واختبار القيادة.

كانت مشكلة التسمية nonce / IV شيئًا لم أقرر بشأنه ، وأنا سعيد بالتغيير إلى IV لذلك سوف يتغير.

أما بالنسبة لطرق Get تعيد شيئًا ما ، فهذا يتجنب أي تخصيصات. يمكن أن يكون هناك حمل زائد Get () يعيد شيئًا ما. ربما يتطلب الأمر تغيير التسمية ، لكنني متزوج جدًا من فكرة أن واجهة برمجة التطبيقات بأكملها يجب أن تكون خالية من التخصيص بشكل أساسي.

بالنسبة إلى التدفقات وما إلى ذلك ، فأنا لست منزعجًا جدًا من ذلك نظرًا لأنها واجهة برمجة تطبيقات ذات مستوى أعلى يمكن إنشاؤها بسهولة من العناصر الأولية ذات المستوى الأدنى.

لا يجب السماح بالحصول على علامة قبل الانتهاء ، ولكن يجب أن تعرف متى اتصلت بإنهاء ، لذلك لست متأكدًا من أنه يجب أن يكون في واجهة برمجة التطبيقات ، ومع ذلك يجب أن يكون سلوكًا محددًا ، لذا فقد قمت بتحديث تصميم واجهة برمجة التطبيقات لتضمينه قسم السلوك حتى نتمكن من التقاط أي شيء آخر يتم التفكير فيه.

بالنسبة إلى أي تشفير ، لا أعتقد أن أي تشفير محدد يجب أن يكون الهدف الوحيد ، لإثبات وجود واجهة برمجة تطبيقات جديدة للأغراض العامة يجب أن تتناسب مع رقم. يجب تغطية كل من AES GCM و CBC.

(دائمًا ما تكون التعليقات الجيدة أو السيئة حول الموضوع مفيدة!)

  • فئة أم واجهة؟
  • كيف ، على كل حال ، هل تتفاعل فئات SymmetricAlgorithm الحالية مع هذا؟
  • كيف يمكن استخدام هذا للمفاتيح المستمرة ، مثل TripleDESCng و AesCng يمكن أن تفعل؟
  • يبدو أن العديد من هذه الامتدادات يمكن أن تكون ReadOnlySpan.

Drawaes شكرًا لك على تشغيل واجهة برمجة التطبيقات هذه. بعض الأفكار:

  1. يعد إنشاء العلامات والتحقق منها جزءًا مهمًا جدًا من واجهة برمجة التطبيقات هذه نظرًا لأن إساءة استخدام العلامات يمكن أن تلغي الغرض بأكمله. إذا كان ذلك ممكنًا ، أرغب في رؤية العلامات المضمنة في عمليات التهيئة والإنهاء للتأكد من عدم تجاهلها عن طريق الخطأ. من المحتمل أن يعني ذلك أن التشفير وفك التشفير لا ينبغي أن يستخدموا نفس طرق التهيئة والإنهاء.
  2. لدي مشاعر مختلطة حول إخراج الكتل أثناء فك التشفير قبل الوصول إلى النهاية لأن البيانات ليست جديرة بالثقة حتى يتم التحقق من العلامة (وهو ما لا يمكن القيام به حتى تتم معالجة جميع البيانات). سنحتاج إلى تقييم هذه المقايضة بعناية شديدة.
  3. هل إعادة التعيين ضرورية؟ هل يجب إنهاء إعادة التعيين فقط؟ نقوم بذلك على تجزئات إضافية (لكنهم لا يحتاجون إلى IVs جديدة)

تضمين التغريدة

  1. Class ، كما رأينا غالبًا في BCL بواجهة لا يمكنك توسيعها لاحقًا دون كسر كل شيء. الواجهة تشبه جروًا مدى الحياة ... ما لم يتم اعتبار طرق الواجهة الافتراضية كحل لهذه المشكلة.
    كما أن الفصل المختوم من نوع مجردة هو في الواقع أسرع (حتى الآن) لأن jitt يمكن أن يبتعد عن الأساليب الآن ... لذلك فهو مجاني في الأساس. إرسال الواجهة ليس جيدًا (لا يزال جيدًا ولكن ليس جيدًا)
  2. لا أعرف كيف تريد أن يعمل هذا؟ لدي القليل من الاهتمام بالأشياء الحالية لأنه أمر محير للغاية وسأقوم بتصحيح كل الطحالب الحديثة المعقولة مباشرة (اترك 3DES في الفصول الأخرى :) ولكن ليس لدي جميع الإجابات ، فهل لديك أي أفكار أخرى حول هذا؟
  3. يجب أن تكون المفاتيح المستمرة سهلة. قم بعمل طريقة تمديد على الطريقة الرئيسية أو مخزن الثبات.
MyKeyStore.GetCipher();

لم تتم تهيئته. يمكن التخلص منها ، لذا يمكن إسقاط أي مرجع بنمط عادي يمكن التخلص منه. إذا حاولوا تعيين المفتاح ، فقم بإلقاء استثناء غير صالح للعملية.

نعم بالنسبة إلى فترات القراءة فقط التي سأقوم بتعديلها عندما لا أكون على الأنبوب في هاتفي.

@ morganbr لا مشكلة ... أنا فقط أريد أن أراه يحدث أكثر من أي شيء آخر ؛)

  1. هل يمكنك إعطاء مقتطف رمز حول كيفية رؤيتك لهذا العمل؟ لست متأكدًا من ذلك ، لكن الكود دائمًا يجلب الوضوح
  2. إنه أمر مؤسف ولكن عليك حقًا أن تبصق الكتل مبكرًا. باستخدام hmac والتجزئة ، لا يمكنك ذلك ولكن ليس لديك بيانات مؤقتة عن الحالة فقط. لذلك في هذه الحالة سيكون عليك تخزين كمية غير معروفة من البيانات مؤقتًا. دعنا نلقي نظرة على مثال خطوط الأنابيب و TLS. يمكننا كتابة 16 كيلو من نص عادي ولكن المخازن المؤقتة لخط الأنابيب اليوم بحجم صفحة 4k. لذلك نود في أحسن الأحوال تشفير / فك تشفير 4 * 4k. من أنت لا تعطيني الإجابة حتى النهاية تحتاج إلى تخصيص ذاكرة داخلية لتخزين كل ذلك ثم أفترض التخلص منها عندما أحصل على النتيجة؟ أو سوف تمسحها. ماذا لو قمت بفك تشفير 10 ميغا بايت واحتفظت بهذه الذاكرة بعد أن أصبح عليّ الآن القلق بشأن استخدام الذاكرة الكامنة.
  3. ليس 100٪ في الأمر الأولي / إعادة الضبط (وليس أفكارك ، شكل واجهة برمجة التطبيقات الحالي الخاص بي) لا يناسبني جيدًا ، لذا فأنا منفتح على اقتراح جديد!

لدي القليل من الاهتمام بالأشياء الحالية لأنه أمر محير للغاية وسأقوم فقط بتصحيح كل الطحالب الحديثة المعقولة مباشرة (اترك 3DES في الفصول الأخرى :)

قد تكون المشكلة أن تنسيقات الحاويات مثل EnvelopedCms (أو EncryptedXml) قد تحتاج إلى العمل مع 3DES-CBC و AES-CBC وما إلى ذلك. شخص ما يريد فك تشفير شيء مشفر باستخدام ECIES / AES-256-CBC-PKCS7 / HMAC-SHA-2 -256 ربما لن يشعروا أنهم يقومون بأشياء قديمة ومشوهة.

إذا كان من المفترض أن يكون فقط من أجل AE ، فيجب أن ينعكس ذلك في مكان ما في الاسم. في الوقت الحالي ، إنه "تشفير" عام (كنت أو أنا ، في مرحلة ما ، سأجلس مع قاموس / مسرد مصطلحات وأكتشف ما إذا كانت هناك كلمة لـ "خوارزمية تشفير في وضع التشغيل" ، لأنني أعتقد ذلك "تشفير" == "خوارزمية" ، لذلك "Aes").

:) كنت فقط أشير إلى أن هذا ليس مجال موضوعي أو يهمني كثيرًا ، لذا فأنا على استعداد لإخضاعك أنت والمجتمع بشأن هذا الموضوع لم أفكر في الآثار المترتبة على ذلك.


بعد المسح السريع لهذه ، أحد الخيارات هو السماح لهم بأخذ نسخة من "التشفير" أو أيًا كان ما يسمى بالفئة. قد لا يتم ذلك في الموجة الأولى ، ولكن يمكن أن يتبعها بسرعة. إذا كانت واجهة برمجة التطبيقات ذات كفاءة فائقة ، فلا أرى أي سبب يدعوهم للقيام بأشياء خاصة بهم داخليًا وهي بالضبط حالة الاستخدام لواجهة برمجة التطبيقات هذه.

كشريط جانبي في التسمية ... يجب أن أعترف أنه صعب ولكن
Openssl = تشفير
روبي = شفرات
Go = حزمة التشفير مع واجهات ducktyped لـ AEAD وما إلى ذلك
جافا = تشفير

الآن أنا مختلف ولكن ... هناك اتجاه. إذا كان هناك شيء أفضل ممكن فهذا رائع.

ربما "BlockModeCipher" ...؟

لقد أجريت بعض التغييرات ، وسأغير التسمية إذا تم تحديد اسم أفضل.

عندما بدأت في محاولة الإجابة عن الأسئلة ، أدركت أن واجهة برمجة التطبيقات تفتقد بالفعل تمايز التشفير / فك التشفير ، لذلك في مثالك ، لا تعرف ما إذا كانت تريد تشفير البيانات أو فك تشفيرها. الحصول على ذلك قد يضيف بعض الوضوح.

يمكنني أن أتخيل طريقتين يمكن لواجهة برمجة التطبيقات (API) من خلالها فرض استخدام العلامة المناسب (بناءً على افتراض أن هذه واجهة برمجة تطبيقات AEAD ، وليست مجرد تشفير متماثل نظرًا لأن لدينا بالفعل SymmetricAlgorithm / ICryptoTransform / CryptoStream). لا تأخذ هذه على أنها توجيهية ، فقط كمثال لفرض العلامات.
عن طريق الطريقة:

class Cipher
{
   void InitializeEncryption(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv);
   // Ensures decryptors get a tag
   void InitializeDecryption(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv, ReadOnlySpan<byte> tag);
   // Ensure encryptors produce a tag
    void FinishEncryption(ReadOnlySpan<byte> input, Span<byte> output, Span<byte> tag);
   // Throws if tag didn't verify
   void FinishDecryption(ReadOnlySpan<byte> input, Span<byte> output);
   // Update and properties are unchanged, but GetTag and SetTag are gone
}

حسب الفصل:

class Cipher
{
    // Has properties and update, but Initialize and Finish aren't present
}
class Encryptor : Cipher
{
    void Initialize(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv);
    void Finish(ReadOnlySpan<byte> input, Span<byte> output, Span<byte> tag);
}
class Decryptor : Cipher
{
   void Initialize(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv, ReadOnlySpan<byte> tag);
   // Throws if tag didn't verify
   void Finish(ReadOnlySpan<byte> input, Span<byte> output);
}
class AesGCMEncryptor : Encryptor {}
class AesGCMDecryptor : Decryptor {}
}

ومع ذلك ، إذا لم يتم تخزينها مؤقتًا عند فك التشفير ، فهل من العملي التأكد من انتهاء فك التشفير بالفعل والتحقق من العلامة؟ هل يمكن أن يكتشف التحديث بطريقة ما أن الوقت قد حان للتحقق؟ هل هذا شيء يجب أن تفعله شركة التخلص؟ (يعد التخلص خطيرًا بعض الشيء لأنك ربما تكون قد وثقت بالفعل في البيانات بحلول الوقت الذي تخلصت فيه من الكائن)

فيما يتعلق بالتسمية ، فإن سابقة لدينا هي SymmetricAlgorithm و AsymmetricAlgorithm. إذا كان هذا مخصصًا لـ AEAD ، فقد تكون بعض الأفكار خوارزمية AuthenticatedSymmetricAlgorithm أو AuthenticatedEncryptionAlgorithm.

بعض الأفكار وأفكار API:

public interface IAEADConfig
{
    // size of the input block (plaintext)
    int BlockSize { get; }

    // size of the output per input-block;
    // typically a multiple of BlockSize or equal to BlockSize.
    int FeedbackSize { get; }

    // IV size; CAESAR completition uses a fixed-length IV
    int IVSize { get; }

    // CAESAR competition uses a fixed-length key
    int KeySize { get; }

    // CAESAR competition states that typical AEAD ciphers have a constant gap between plaintext length
    // and ciphertext length, but the requirement is to have a constant *limit* on the gap.
    int MaxTagSize { get; }

    // allows for AE-only algorithms
    bool IsAdditionalDataSupported { get; }
}

public interface ICryptoAEADTransform : ICryptoTransform
{
    // new AEAD-specific ICryptoTransform interface will allow CryptoStream implementation
    // to distinguish AEAD transforms.
    // AEAD decryptor transforms should throw on auth failure, but current CryptoStream
    // logic swallows exceptions.
    // Alternatively, we can create a new AEAD_Auth_Failed exception class, and
    // CryptoTransform is modified to catch that specific exception.
}

public interface IAEADAlgorithm : IDisposable, IAEADConfig
{
    // separates object creation from initialization/keying; allows for unkeyed factories
    void Initialize(ArraySegment<byte> key);

    void Encrypt(
        ArraySegment<byte> iv, // readonly; covered by authentication
        ArraySegment<byte> plaintext, // readonly; covered by authentication
        ref ArraySegment<byte> ciphertext, // must be of at least [plaintext_length + MaxTagSize] length. iv is not part of ciphertext.
        ArraySegment<byte> additionalData = default(ArraySegment<byte>) // readonly; optional; covered by authentication
        ); // no failures expected under normal operation - abnormal failures will throw

    bool Decrypt(
        ArraySegment<byte> iv, // readonly
        ArraySegment<byte> ciphertext, // readonly
        ref ArraySegment<byte> plaintext, // must be of at least [ciphertext_length - MaxTagSize] length.
        ArraySegment<byte> additionalData = default(ArraySegment<byte>), // readonly; optional
        bool isAuthenticateOnly = false // supports Authentication-only mode
        );// auth failures expected under normal operation - return false on auth failure; throw on abnormal failure; true on success

    /*  Notes:
        * Array.LongLength should be used instead of Array.Length to accomodate byte arrays longer than 2^32.
        * Ciphertext/Plaintext produced by Encrypt()/Decrypt() must be determined *only* by method inputs (combined with a key).
          - (ie. if randomness or other hidden inputs are needed, they must be a part of iv)
        * Encrypt()/Decrypt() are allowed to write to ciphertext/plaintext segments under all conditions (failure/success/abnormal)
          - some implementations might be more stringent than others, and ex. not leak decrypted plaintext on auth failures
    */

    ICryptoAEADTransform CreateEncryptor(
        ArraySegment<byte> key,
        ArraySegment<byte> iv,
        ArraySegment<byte> additionalData = default(ArraySegment<byte>)
        );

    ICryptoAEADTransform CreateDecryptor(
        ArraySegment<byte> key,
        ArraySegment<byte> iv,
        ArraySegment<byte> additionalData = default(ArraySegment<byte>)
        );

    // Streaming AEAD can be done with good-old CryptoStream
    // (possibly modified to be AEAD-aware).
}

sdrapkin ، شكرًا على المساهمة بالأفكار. أين يجب أن توضع العلامات في واجهة برمجة التطبيقات الخاصة بك؟ هل هم ضمنيا جزء من النص المشفر؟ إذا كان الأمر كذلك ، فهذا يعني بروتوكولًا لا تمتلكه بعض الخوارزميات في الواقع. أود أن أفهم ما هي البروتوكولات التي قد يهتم بها الأشخاص لمعرفة ما إذا كان وضع العلامات الضمنية مقبولاً أو ما إذا كان يجب نقله بشكل منفصل.

morganbr لقد لاحظت مشكلة التشفير / فك التشفير أيضًا ولكن لم يكن لدي وقت الليلة لإصلاح ذلك سعيد جدًا بتصميمك. أنا أفضل الطرق على الفصل لأنها تسمح بإعادة التدوير الأكثر قوة (يمكن أن تضيف المخازن المؤقتة للمفاتيح والمفاتيح IV).

أما الشيك قبل التصرف. لسوء الحظ ، لا يمكن معرفة نهاية العملية.

واجهات sdrapkin أود أن أقول إنها محظورة بسبب مشكلة الإصدار المذكورة سابقًا. ما لم نعتمد على الغرس الافتراضي في المستقبل. كما أن إرسال الواجهة يكون أبطأ .. كما أن مقاطع المصفوفة هي أيضًا لدينا لأن النطاق هو الأكثر تنوعًا بدائيًا أقل. ومع ذلك ، يمكن إضافة طرق الامتداد لتمتد المصفوفة إذا كان هناك طلب في وقت لاحق.

بعض ممتلكاتك ذات أهمية لذلك سيتم تحديثها عندما أكون على جهاز كمبيوتر بدلاً من هاتفي.

ردود فعل جيدة من جميع النواحي!

تعد علامات morganbr جزءًا من النص المشفر. تم تصميم هذا على غرار CAESAR API (الذي يتضمن AES-GCM).

Drawaes لقد استخدمت واجهات لتوضيح الأفكار فقط - أنا موافق تمامًا مع الأساليب / الفئات الثابتة. امتدادغير موجود. لا يهمني ما قد يأتي أو لا يأتي - ليس في NetStandard2 ، وليس في .NET العادي الذي تستخدمه المشاريع الجادة بالفعل (نعم ، نعم ، أعلم أنه في Core ، لكن Core هي لعبة الى الان). يسعدني أن أفكر شخصيًا في Spanعندما أراه - حتى ذلك الحين ArraySegmentهي أقرب واجهة برمجة تطبيقات NetStandard يتم شحنها بالفعل.

سألقي نظرة أعمق على واجهة برمجة تطبيقات CAESAR المفيدة.

بالنسبة إلى Span ، يتم الشحن حول الإطار الزمني 2.1 الذي أعتقد أنه هو نفس الوقت الذي سيتم فيه شحن التطبيق الأول لواجهة برمجة التطبيقات (أو على الأقل في أقرب وقت ممكن).

إذا ألقيت نظرة على حزمة nuget التجريبية الحالية ، فإنها تدعم وصولاً إلى .net القياسي 1.0 ولا توجد خطط لتغيير ذلك عند الإصدار.

ربما يستطيع stephentoub تأكيد ذلك أثناء قيامه بعمل لإضافة واجهة برمجة تطبيقات تستند إلى Span عبر إطار العمل أثناء حديثنا.

(Nuget for Span) [https://www.nuget.org/packages/System.Memory/4.4.0-preview2-25405-01]

لذلك أود أن أقول إنه الخيار الحقيقي الوحيد لواجهة برمجة تطبيقات جديدة تمامًا. ثم يمكن إضافة طرق الامتداد وما إلى ذلك لأخذ ArraySegment إذا اخترت ذلك وإذا كان مفيدًا بدرجة كافية ، فيمكن إضافته إلى إطار العمل ولكن من السهل تحويل ArraySegment إلى Span ، ولكن الطريقة الأخرى تتطلب نسخ البيانات.

المشكلة التي أراها مع واجهة برمجة التطبيقات أعلاه هي أنها ستكون كارثة للأداء على أي بيانات "مقسمة". لنفترض على سبيل المثال حركة مرور الشبكة ، إذا تم تقسيم كتلة مصادقة واحدة على عدة قراءات من دفق موجود ، فأنا بحاجة إلى تخزينها جميعًا مؤقتًا في [إدراج بنية بيانات] واحدة وتشفير / فك تشفير الكل مرة واحدة. يهزم كل المحاولات للقيام بأي نوع من النسخ الصفرية على تلك البيانات.

تمكنت أطر عمل الشبكات مثل تلك التي توفرها Pipelines من تجنب جميع النسخ تقريبًا ، ولكن بعد ذلك إذا وصلت إلى أي نوع من التشفير في واجهة برمجة التطبيقات هذه ، فكل ذلك قد انتهى.

تم بالفعل إشراك كائن التكوين المنفصل (أو الحقيبة) في مناقشة حديثة حول واجهة برمجة تطبيقات أخرى كنت أواجهها. أنا لا أعارض ذلك من حيث المبدأ كما لو أنه ينمو في المستقبل ، فقد يصبح وجود عدد كبير من الخصائص على الكائن الرئيسي أمرًا فوضويًا.

لقد حدث لي شيئان.

  • يدعو الاقتراح الحالي TagSize إلى قيمة خارجية (حسنًا ، خاصية get-only-property). ولكن بالنسبة إلى كل من GCM و CCM ، يعد هذا إدخالًا للتشفير (ويمكن اشتقاقه من فك التشفير نظرًا لأنك قدمت العلامة الفعلية).
  • يفترض الاقتراح أن المدخلات والمخرجات يمكن أن تحدث في نفس الوقت ، وبشكل جزئي.

    • لا يمكن لـ IIRC CCM القيام بتشفير التدفق (طول النص العادي هو إدخال في الخطوة الأولى من الخوارزمية).

    • تتأخر الأوضاع المبطنة في فك التشفير بواسطة كتلة (واحدة على الأقل) ، لأنه حتى يتم استدعاء Final ، لا يعرفون ما إذا كانت هناك المزيد من البيانات قادمة / إذا كانت الكتلة الحالية تحتاج إلى إزالة الحشو

  • قد تعتبر بعض الخوارزميات أن عنصر AD مطلوب في بداية العملية ، مما يجعلها أشبه بمعامل Init / ctor أكثر من ارتباط متأخر.

لا أعرف ما إذا كانت تنسيقات الحاويات (EnvelopedCms ، EncryptedXml) ستحتاج إلى استخراج المفتاح ، أو ما إذا كان الأمر متروكًا لهم لإنشائه وتذكره (طالما أنهم بحاجة إلى كتابته).

(من الواضح أنني لم أضغط على زر "تعليق" أمس ، لذا لن يتم الإقرار بأي شيء بعد "أجريت بعض التغييرات" عند 1910Z)

يجب أن يكون حجم العلامة الحقيقي متغيرًا. متفق.

إذا نظرنا فقط إلى التشفير في الوقت الحالي ، لتبسيط حالة الاستخدام. أنت محق في أن بعض الأصفار لن تعيد شيئًا ، أقل أو أكثر. هناك سؤال عام حول ما سيحدث إذا لم تقم بتوفير مخزن مؤقت كبير بما يكفي.

على واجهات TextEncoding الجديدة التي تستخدم span ، كان هناك اقتراح حول وجود نوع الإرجاع تعداد لتحديد ما إذا كان هناك مساحة كافية للإخراج أم لا ، والحجم المكتوب بالفعل في معلمة "out" بدلاً من ذلك. هذا احتمال.

في حالة CCM ، أود فقط أن أقول إنه لا يُرجع شيئًا وسيتعين عليه التخزين المؤقت داخليًا حتى تقوم باستدعاء إنهاء عند النقطة التي قد ترغب في تفريغ الكمية بأكملها. لا شيء يمنعك من مجرد إنهاء المكالمة كأول مكالمتك إذا كان لديك جميع البيانات في كتلة واحدة (في هذه الحالة قد يكون هناك اسم أفضل). أو من الممكن رميها إذا حاولت تحديث هذه الأصفار. تقوم CNG بإرجاع خطأ حجم غير صالح إذا حاولت إجراء متابعة على CCM على سبيل المثال.

عندما يتم تعيين العلامة على فك التشفير ، غالبًا ما لا تعرفها حتى تقرأ الحزمة بأكملها ، إذا أخذنا TLS كمثال ، فقد نضطر إلى قراءة حزم شبكة 8 * 2k للوصول إلى العلامة في النهاية من كتلة 16 كيلو. لذلك يتعين علينا الآن تخزين 16 كيلو بايت مؤقتًا قبل أن نبدأ في فك التشفير ولا توجد فرصة للتداخل (لا أقول إن هذا سيستخدم لـ TLS فقط لأن عملية ربط الإدخال والإخراج شائعة لهذه الأنواع من الأصفار ، سواء كانت قرصًا أو شبكة الاتصال).

تضمين التغريدة التدفقات المتقطعة وحدود التخزين المؤقت:
عليك أن تختار المعارك الخاصة بك. لن تكون قادرًا على إنشاء واجهة برمجة تطبيقات موحدة تتماشى مع كل هدف جميل في عالم AE - وهناك العديد من هذه الأهداف. السابق. هناك تدفق AEAD لائق مقسم في Inferno ، لكنه ليس معيارًا بأي شكل من الأشكال ، ومثل هذا المعيار غير موجود. على مستوى أعلى ، الهدف هو "قنوات آمنة" (انظر هذا ، هذا ، وهذا ).

ومع ذلك ، نحن بحاجة إلى التفكير بشكل أصغر في الوقت الحالي. التقسيم / الحد من المخزن المؤقت غير موجود حتى على الرادار لجهود التقييس (قسم " AEADs ذات النصوص الصريحة الكبيرة ") ..

تتعلق عمليات التشفير / فك التشفير أساسًا بالتحولات. تتطلب هذه التحويلات مخازن مؤقتة وليست في مكانها (يجب أن تكون المخازن المؤقتة للإخراج أكبر من مخازن الإدخال المؤقتة - على الأقل من أجل تحويل التشفير).

قد يكون RFC 5116 مهمًا أيضًا.

Drawaes ، من المثير للاهتمام طرح TLS. أود أن أزعم أن SSLStream (إذا كان يستخدم واجهة برمجة التطبيقات) يجب ألا يعيد أي نتائج غير مصدق عليها إلى تطبيق ما لأن التطبيق لن يكون لديه أي طريقة للدفاع عن نفسه.

بالتأكيد ، ولكن هذه مشكلة SSLStreams. لقد قمت بنمذجة هذا الشيء الدقيق (TLS المُدار على مستوى البروتوكول الذي ينادي CNG و OpenSSL لبتات التشفير) فوق خطوط الأنابيب. كان المنطق بسيطًا جدًا ، حيث يتم إدخال البيانات المشفرة ، وفك تشفير المخزن المؤقت في مكانه ، وإرفاقه بالحد الخارجي والتكرار حتى تصل إلى العلامة. انتهى استدعاء العلامة ...

إذا رمى إغلاق خط الأنابيب. إذا لم يتم رميها ، فقم بالتدفق للسماح للمرحلة التالية بالذهاب إلى العمل إما على نفس الخيط أو عن طريق الإرسال.

لم يكن إثبات المفهوم الخاص بي جاهزًا لفترة الذروة ولكن باستخدام هذا وتجنب الكثير من النسخ وما إلى ذلك ، أظهر زيادة في الأداء جيدة جدًا ؛)

تكمن المشكلة في أي شبكة في المكان الذي تبدأ فيه الأشياء قيد الإعداد في تخصيص المخازن المؤقتة الخاصة بها وعدم استخدام أكبر قدر ممكن من المخازن المؤقتة التي تتحرك عبر النظام بالفعل.

تشفير OpenSsl و CNG لهما نفس طريقة التحديث ، التحديث ، الإنهاء. يمكن إنهاء إخراج العلامة كما تمت مناقشته. يجب أن تكون التحديثات بحجم الكتلة (لـ CNG) وبالنسبة لـ OpenSsl ، فإنها تقوم بأدنى حد من التخزين المؤقت للوصول إلى حجم الكتلة.

نظرًا لأنهم بدائيون ، فأنا لست متأكدًا من أننا نتوقع وظائف ذات مستوى أعلى منهم. إذا كنا نصمم واجهة برمجة تطبيقات على مستوى "المستخدم" بدلاً من الأساسيات لإنشاء تلك العناصر ، فسأجادل بعد ذلك أنه يجب تنفيذ إنشاء المفتاح والبناء الرابع والأجزاء المصادق عليها بالكامل ، لذا أعتقد أنه يعتمد على المستوى المستهدف لواجهة برمجة التطبيقات هذه حقًا.

الزر الخطأ

blowdart ، الذي كان لديه بعض الأفكار الشيقة حول إدارة nonce.

لذا فإن إدارة nonce هي في الأساس مشكلة للمستخدم وهي خاصة بإعدادها.

لذا ... اجعله مطلبًا. يجب أن تقوم بتوصيل إدارة nonce ... ولا تقدم تطبيقًا افتراضيًا ، أو أي تطبيقات على الإطلاق. هذا ، وليس بسيط

cipher.Init(myKey, nonce);

يجبر المستخدمين على القيام بإيماءة محددة لفهم المخاطر.

قد تساعد فكرة blowdart في حل مشاكل الإدارة غير الرسمية والاختلافات بين الخوارزميات. أوافق على أنه من المهم على الأرجح عدم وجود تطبيق مدمج للتأكد من أن المستخدمين يفهمون أن إدارة nonce هي مشكلة يحتاجون إلى حلها. كيف يبدو شيء مثل هذا؟

interface INonceProvider
{
    public void GetNextNonce(Span<byte> writeNonceHere);
}

class AesGcmCipher : Cipher
{
    public AesGcmCipher(ReadOnlySpan<byte> key, INonceProvider nonceProvider);
}

// Enables platform-specific hardware keys
class AesGcmCng : Cipher
{
    public AesGcmCng(CngKey key, INonceProvider nonceProvider);
}

// Example of AEAD that might not need a nonce
class AesCBCHmac : Cipher
{
    public AesCBC(ReadOnlySpan<byte> key)
}

class Cipher
{
    // As above, but doesn't take keys, IVs, or nonces
}

ولكن ما هو الهدف من INonceProvider؟ إنه مجرد نوع / inteface إضافي ، إذا لم يأخذ التهيئة الأولية شيئًا وكان من الضروري استدعاؤه قبل بدء أي كتلة ، أليس هذا هو الشيء نفسه بدون واجهة / واجهة إضافية؟

كما أنني لست خبيرًا في التشفير ولكن لا تتطلب AES إجراء IV (وهو ليس رقمًا عاديًا ولكن يحتاج إلى توفيره من قبل المستخدم؟)

إنه مجرد نوع إضافي / نوع إضافي

هذا نوع من النقطة. تقول بشكل أساسي أن "عدم الإدارة" يمثل مشكلة ، وليس مجرد المرور في مصفوفة بايت صفرية أو حتى عشوائية. قد يساعد أيضًا في منع إعادة الاستخدام غير المقصود إذا فسّر الأشخاص GetNextNonce على أنه يعني "إرجاع شيئًا مختلفًا عما فعلته في المرة السابقة".

من المفيد أيضًا عدم الحاجة إليها للخوارزميات التي لا تحتوي على مشاكل إدارة غير رسمية (مثل AES SIV أو ربما AES + CBC + HMAC).

تختلف متطلبات IV / nonce وفقًا للوضع. فمثلا:

  • لا يتطلب AES ECB شهادة nonce أو IV
  • يتطلب AES GCM 96 بت nonce لا يجب إعادة استخدامه أبدًا أو أمان فواصل المفاتيح. يعتبر الانتروبيا المنخفضة أمرًا جيدًا طالما لم يتم إعادة استخدام العيوب.
  • يتطلب AES CBC وجود 128 بت IV يجب أن يكون عشوائيًا. إذا تكرر الرابع ، فإنه يكشف فقط ما إذا كان قد تم إرسال نفس الرسالة من قبل.
  • لا يحتاج AES SIV إلى IV صريحًا لأنه يشتق من مدخلات أخرى.

AES CBC يحتاج IV أليس كذلك؟ هل سيكون لديك InitializationVectorProvider؟ انها ليست نونسي ولكن
أدى nonce like وإعادة استخدام الكتلة الأخيرة إلى هجوم tls لأنه يمكن توقع IV. لا يمكنك صراحة استخدام قول رقم غير متسلسل لـ CBC.

نعم ، لكن IV ليس رقمًا غير متوافر ، لذا لا يمكنك الحصول على مصطلح مزود nomce

لم أقصد أن أشير إلى أن AES CBC لا يحتاج إلى IV - إنه كذلك. قصدت فقط التكهن ببعض المخططات التي تستمد IV من بيانات أخرى.

بالتأكيد أعتقد أن وجهة نظري هي أنني أحبه بشكل عام ... يمكنني تجميع الموفر ؛) ولكن إما أن أطلق عليه مزود IV أو أن يكون لديك واجهتان لتوضيح النية

morganbr INonceProvider المصانع التي تم تمريرها إلى صانعي التشفير هي تصميم سيء. إنه يغفل تمامًا حقيقة أن _nonce_ لا يوجد بمفرده: القيد "_... المستخدم مرة واحدة_" يحتوي على _context_. في حالات CTR و GCM (التي تستخدم نسبة النقر إلى الظهور) ، يكون _context_ في _nonce_ هو _key_. بمعنى آخر. _ nonce Provider_ يجب أن يُرجع nonce الذي يتم استخدامه مرة واحدة فقط في سياق _key_ محدد.

نظرًا لأن INonceProvider في واجهة برمجة التطبيقات المقترحة الخاص بك لا يدرك المفتاح ، فإنه لا يمكنه إنشاء أرقام غير صحيحة (بخلاف العشوائية ، وهي ليست ما هو nonce ، حتى لو كانت مساحة البت كبيرة بما يكفي لعمل العشوائية الإحصائية بأمان).

لست متأكدًا تمامًا مما يهدف موضوع المناقشة هذا إلى تحقيقه. تمت مناقشة العديد من أفكار تصميم التشفير المصدق ... حسنًا. ماذا عن واجهات التشفير المصدق المضمنة بالفعل في .NET Core - تحديدًا في ASP.NET API؟ يوجد IAuthenticatedEncryptor ، إلخ. تم تنفيذ جميع هذه الإمكانات بالفعل وقابلة للتوسيع وشحن كجزء من .NET Core اليوم. أنا لا أقول إن تشفير DataProtection مثالي ، لكن هل الخطة لتجاهلها؟ تغييرها؟ استيعاب أو إعادة البناء؟

تم إنشاء تشفير DataProtection بواسطة GrabYourPitchforks (Levi Broderick). إنه يعرف الموضوع ، وسيكون رأيه / مدخلاته / ملاحظاته أكثر قيمة لهذا المجتمع. أنا أستمتع بالترفيه ذي الطابع المشفر مثل أي شخص آخر ، ولكن إذا أراد شخص ما أن يصبح جادًا بشأن تصميم واجهة برمجة تطبيقات التشفير ، فيجب إشراك الخبراء الفعليين الموجودين بالفعل في فريق MS.

sdrapkin ، مقدمو nonce الذين يحتاجون إلى أن يكونوا على دراية رئيسية هي نقطة جيدة. أتساءل عما إذا كانت هناك طريقة معقولة لتعديل واجهات برمجة التطبيقات هذه لفرض ذلك.

DataProtection عبارة عن واجهة برمجة تطبيقات جيدة ، لكنها بنية ذات مستوى أعلى. وهي تلخص إنشاء المفتاح وإدارته ، و IVs وبروتوكول الإخراج. إذا احتاج شخص ما إلى (على سبيل المثال) استخدام GCM في تنفيذ بروتوكول مختلف ، فإن DataProtection لا تجعل ذلك ممكنًا.

يضم فريق التشفير .NETbartonjs و blowdart وأنا. بالطبع ، إذا أراد GrabYourPitchforks المشاركة ، فهو موضع ترحيب كبير.

أتفق مع @ morganbr في أنه من المفترض أن يكون هذا المستوى بدائيًا منخفض المستوى (في الواقع يقول ذلك في العنوان). بينما تم تصميم حماية البيانات وما إلى ذلك لاستخدامها مباشرة في رمز المستخدم وتقليل القدرة على إطلاق النار على نفسك ، فإن الطريقة التي أرى بها هذا الأمر البدائي هي السماح للإطار والمكتبات ببناء بنيات ذات مستوى أعلى على قاعدة مشتركة.

مع وضع هذا الفكر في الاعتبار ، يكون الموفر على ما يرام إذا كان يجب توفيره في أي وقت يتم فيه توفير مفتاح. إنه يجعل الأمر فوضويًا بعض الشيء ، دعني أشرح استخدام TLS (إنه استخدام معروف جيدًا لأوضاع كتلة AES لحركة مرور الشبكة هو كل شيء).

أحصل على "إطار" (ربما يزيد عن 2 + TU مع MTU ~ 1500 للإنترنت). يحتوي على nonce (أو جزء من nonce مع 4 بايت متبقي "مخفي") ثم يتعين علي تعيين هذه القيمة على "مزود" shell ثم استدعاء فك التشفير والانتقال خلال دورة فك تشفير المخازن المؤقتة للحصول على نص عادي واحد .

إذا كنت سعيدًا بذلك ، يمكنني التعايش معه. أنا حريص على المضي قدمًا في هذا الأمر ، لذا حريصًا على تحديث التصميم أعلاه لشيء يمكننا الاتفاق عليه.

نشكرك على إجراء المناقشة ، والحصول على بعض وقت الفراغ للقفز إلى هذا الموضوع. Drawaes ، هل يمكنك تأكيد / تحديث المنشور الأعلى كمعيار ذهبي / هدف لهذه المحادثة المتطورة؟ إذا لم يكن كذلك ، هل يمكنك تحديثه؟

أرى أن الاقتراح الحالي به مشكلة قاتلة ثم مشكلات أخرى تتعلق بكونك ثرثارًا للغاية.

// current proposed usage
using (var cipher = new AesGcmCipher(bitsize: 256))
{
    cipher.Init(myKey, nonce);
    while (!inputSource.EOF)
    {
        var inputSpan = inputSource.ReadSpan(cipher.BlockSize);
        cipher.Update(inputSpan);
        outputSource.Write(inputSpan);
    }
    cipher.AddAssociatedData(extraInformation); // <= fatal, one can't just do this
    cipher.Finish(finalBlockData);
    cipher.GetTag(tagData);
}

إذا نظرت إلى بدائية AEAD حقيقية ، فإن بيانات الخصوصية والبيانات المصادق عليها هي خطوة قفل مختلطة. راجع هذا للحصول على بيانات Auth 1 و CipherText1. هذا بالطبع يستمر لعدة كتل ، وليس فقط 1.highlighted

منذ كل العالم ميمي ، لا يمكن أن تقاوم ، آسف :)
Can't resist

أيضًا ، تبدو واجهة برمجة التطبيقات (API) ثرثرة مع new ، init ، update إلخ. أنا أقترح نموذج هذا المبرمج

// proposed, see detailed comments below
using (var cipher = new AesGcmCipher(myKey, iv, aad)) // 1
{
    // 2
    while (!inputSource.EOF) 
    {
        var inputSpan = inputSource.ReadSpan(16411); // 3
        var outSpan = cipher.Encrypt(inputSpan); // 4
        outputSource.Write(outSpan); 
    }    
    var tag = cipher.Finish(finalBlockData); // 5
}
  1. عادةً ما يكون AAD << نصًا عاديًا ، لذلك رأيت cipher.Init(mykey, nonce, aad); حيث يتم تمرير AAD بالكامل كمخزن مؤقت ، ثم يتم ضغط التشفير على بقية تدفق الجيجابايت + المحتمل. (على سبيل المثال معلمة CipherModeInfo الخاصة بـ BCryptEncrypts ). أيضًا ، يؤسس حجم myKey بالفعل AES128 ، 192 ، 256 ، لا حاجة لمعلمة أخرى.
  2. يصبح Init واجهة برمجة تطبيقات اختيارية في حالة رغبة المتصل في إعادة استخدام الفئة الحالية وثوابت AES الحالية وتخطي إنشاء المفتاح الفرعي AES إذا كان مفتاح AES هو نفسه
  3. يجب أن تحمي واجهة برمجة تطبيقات التشفير المتصل من الأجزاء الداخلية لإدارة حجم الكتلة مثل معظم واجهات برمجة تطبيقات التشفير الأخرى أو حتى واجهات برمجة تطبيقات .NET الموجودة. المتصل معني بحجم المخزن المؤقت الأمثل لحالة استخدامهم ، على سبيل المثال شبكة IO عبر مخازن 16K +). عرض توضيحي برقم أولي أكبر من 16 ألفًا لاختبار افتراضات التنفيذ
  4. inputSpan للقراءة فقط. والمدخلات. لذلك تحتاج إلى outSpan
  5. تحديث () هل تشفير أو فك تشفير؟ فقط لديك واجهات تشفير وفك تشفير لتتناسب مع النموذج العقلي للمطور. tag هو أيضًا أهم البيانات المطلوبة في هذه اللحظة ، أعد ذلك.

في الواقع نخطو خطوة إلى الأمام ، لماذا لا تفعل ذلك فقط

using (var cipher = new AesGcmCipher(myKey, iv, aad))
{
    var tag = cipher.EncryptFinal(inputSpan, outputSpan);
}

أيضا ، يرجى الابتعاد عن INonceProvider وأنواعها. لا تحتاج أساسيات التشفير إلى هذا ، ما عليك سوى التمسك بـ byte[] iv (المفضل لدي للبيانات الصغيرة) أو Span (الشيء الجديد المفترض ولكن الكثير من التجريد IMHO). يعمل مزود Nonce في طبقة أعلاه ويمكن أن تكون النتيجة هي iv الموضحة هنا.

مشكلة جعل الأوليات بدائية للغاية هي أن الناس سيستخدمونها ببساطة بشكل غير صحيح. مع مزود يمكننا على الأقل فرض بعض التفكير في استخدامها.

نحن نتحدث عن AEAD بشكل عام التي GCM محددة. لذلك أولاً ، يجب أن تقود الحالة العامة ( iv ) التصميم ، وليس الحالة المحددة ( nonce ).

ثانيًا ، كيف يمكن لمجرد التحول من byte[] iv إلى GetNextNonce(Span<byte> writeNonceHere) حل المشكلة nonce بالفعل؟ لقد قمت فقط بتغيير الاسم / التسمية الخاصة بالمشكلة مع جعلها في نفس الوقت أكثر تعقيدًا مما ينبغي أن تكون.

ثالثًا ، نظرًا لأننا ندخل في سياسات تتعلق بحماية iv ، فهل يجب علينا أيضًا الدخول في سياسات الحماية الرئيسية؟ ماذا عن سياسات التوزيع الرئيسية؟ من الواضح أن تلك هي مخاوف على مستوى أعلى.

أخيرًا ، يعد nonce موقفيًا للغاية عند الاستخدام في الطبقات العليا. أنت لا تريد أن يكون لديك بنية هشة حيث يتم الجمع بين الاهتمامات عبر الطبقات معًا.

بصراحة ، إذا تمكنا من إخفاء الأوليات إلا إذا قام أحدهم بإيماءة ليقول إنني أعرف ما أفعله ، فسوف أضغط من أجل ذلك. لكننا لا نستطيع. هناك عدد كبير جدًا من تطبيقات التشفير السيئة لأن الناس على الرغم من "أوه هذا متاح ، سأستخدمه". انظر إلى AES نفسها ، سأستخدم ذلك فقط بدون HMAC.

أريد أن أرى واجهات برمجة التطبيقات آمنة بشكل افتراضي ، وإذا كان ذلك يعني مزيدًا من الألم ، فأنا بصراحة أؤيد ذلك. 99٪ من المطورين لا يعرفون ما الذي يفعلونه عندما يتعلق الأمر بالعملات المشفرة وجعل الأمر سهلاً بالنسبة لـ 1٪ الذين يفعلون ذلك يجب أن يكون لهم أولوية أقل.

سبان غير موجود. لا يهمني ما قد يأتي أو لا يأتي - فهو ليس في NetStandard2

sdrapkin كما يشير Drawaes إلى أن Span<T> هو .NET Standard 1.0 لذا يمكن استخدامه في أي إطار عمل. إنه أيضًا أكثر أمانًا من ArraySegment<T> لأنه يتيح لك فقط الوصول إلى النافذة الفعلية المشار إليها ؛ بدلاً من المجموعة بأكملها.

يمنع أيضًا ReadOnlySpan<T> تعديل هذه النافذة ؛ مرة أخرى على عكس مقطع المصفوفة حيث يمكن تعديل أي شيء و / أو الاحتفاظ بمرجع إلى المصفوفة التي تم تمريرها.

يجب أن يكون Span هو الانتقال العام إلى Sync apis (حقيقة أن API الذي يستخدم Span يمكنه أيضًا التعامل مع stackalloc'd والذاكرة الأصلية بالإضافة إلى المصفوفات ؛ هو الجليد)

بمعنى آخر
باستخدام ArraySegment ، يُقترح للقراءة فقط عبر المستندات ؛ ولا يتم منع قراءة / تعديلات خارج الحدود

void Encrypt(
    ArraySegment<byte> iv, // readonly; covered by authentication
    ArraySegment<byte> plaintext, // readonly; covered by authentication
    ref ArraySegment<byte> ciphertext, // must be of at least [plaintext_length + MaxTagSize] length. iv is not part of ciphertext.
    ArraySegment<byte> additionalData = default(ArraySegment<byte>) // readonly; optional; covered by authentication
    );

ولكن مع Span ، يتم فرض readonly بواسطة api ؛ بالإضافة إلى قراءة خارج الحدود للمصفوفات التي تم منعها

void Encrypt(
    ReadOnlySpan<byte> iv, // covered by authentication
    ReadOnlySpan<byte> plaintext, // covered by authentication
    Span<byte> ciphertext, // must be of at least [plaintext_length + MaxTagSize] length. iv is not part of ciphertext.
    ReadOnlySpan<byte> additionalData = ReadOnlySpan<byte>.Empty) // optional; covered by authentication
    );

إنه ينقل النية بالمعلمات بشكل أفضل ؛ وهو أقل عرضة للخطأ فيما يتعلق بالقراءات / الكتابة خارج الحدود.

benaadamsDrawaes لم يقل أبدًا أن Span<T> كان في NetStandard ( أي NetStandard يتم شحنه ). ما قاله هو (1) الموافقة على أن Span<T> ليس موجودًا في NetStandard المشحونة ؛ (2) أن Span<T> سيكون _ "شحنًا قريبًا من الإطار الزمني 2.1" _.

بالنسبة لمسألة Github هذه ، على الرغم من ذلك ، (للقراءة فقط) Span<T> المناقشة هي bikeshedding في الوقت الحالي - لا يوجد وضوح بشأن نطاق أو الغرض من واجهة برمجة التطبيقات التي سيتم تصميمها.

إما أن نذهب مع واجهة برمجة تطبيقات AEAD الأولية منخفضة المستوى الأولية (مثل CAESAR):

  • الايجابيات: مناسب تمامًا لـ AES-GCM / CCM ، ناقلات الاختبار الحالية من مصادر جيدة (NIST ، RFC). sidshetye سيكون سعيدا. سوف يتأمل blowdart أكثر من _ "جعل الأوليات بدائية جدًا" _ ، لكنه سيرى في النهاية يين ويانغ لأن الأوائل بدائيون ولا توجد وسيلة لحماية الأطفال.
  • السلبيات: سيستخدم المستخدمون الخبراء (المثل 1٪) واجهات برمجة التطبيقات منخفضة المستوى بمسؤولية ، بينما يسيء المستخدمون الآخرون غير الخبراء (99٪) استخدامها لكتابة برامج .NET معطلة ستكون مسؤولة عن الغالبية العظمى من .NET CVEs ، والتي ستساهم بشكل كبير في تصور أن .NET منصة غير آمنة.

أو نذهب مع واجهة برمجة تطبيقات AEAD عالية المستوى - مستحيلة أو مقاومة لإساءة الاستخدام:

  • الإيجابيات: 99٪ من المستخدمين غير الخبراء سيستمرون في ارتكاب الأخطاء ، ولكن على الأقل ليس في كود AEAD. blowdart 's _ "أريد أن أرى واجهات برمجة التطبيقات آمنة بشكل افتراضي" _ يتردد صداها بعمق في النظام البيئي ، ويصيب الجميع الأمان والازدهار والكارما الجيدة. تتوفر بالفعل العديد من التصميمات والتطبيقات الجيدة لواجهة برمجة التطبيقات.
  • السلبيات: لا توجد معايير. لا توجد ناقلات اختبار. لا يوجد إجماع حول ما إذا كان AEAD هو الهدف الصحيح لاستهداف واجهة برمجة تطبيقات متدفقة عالية المستوى عبر الإنترنت (المفسد: إنه ليس كذلك - راجع مقالة Rogaway ).

أو نقوم بالأمرين معًا. أو ندخل في شلل التحليل وقد نغلق هذه المشكلة الآن.

أشعر بقوة أنه لكونه جزءًا من اللغة الأساسية ، فإن التشفير يحتاج إلى واجهة برمجة تطبيقات أساسية صلبة ومنخفضة المستوى. بمجرد الحصول على ذلك ، يمكن إنشاء واجهات برمجة تطبيقات عالية المستوى أو واجهات برمجة تطبيقات "عجلات تدريب" بسرعة من خلال النواة أو المجتمع. لكني أتحدى أي شخص أن يفعل العكس بأناقة. بالإضافة إلى أن الموضوع هو " المستوى الأساسي العام للأصفار "!

Drawaes هل هناك جدول زمني للتقارب وحل هذه المشكلة؟ هل توجد أي خطط لإشراك أشخاص غير تابعين لشركة Microsoft بخلاف تنبيهات GitHub؟ مثل 30 دقيقة مكالمة جماعية؟ أحاول أن أبقى بعيدًا عن مأزق الأرانب ولكننا نراهن على أن تشفير NET core سيكون بمستوى معين من النضج والاستقرار .. لذا يمكن فرز مثل هذه المناقشات.

ما زلنا نولي اهتمامًا ونعمل على ذلك. لقد التقينا بمجلس تشفير Microsoft (مجموعة الباحثين والخبراء الآخرين الذين ينصحون باستخدام Microsoft للتشفير) وسيكون لدى bartonjs المزيد من المعلومات لمشاركتها قريبًا.

استنادًا إلى القليل من عبث تدفق البيانات ونصائح مجلس التشفير ، توصلنا إلى ما يلي. كان نموذجنا هو GCM و CCM و SIV و CBC + HMAC (لاحظ أننا لا نتحدث عن إجراء SIV أو CBC + HMAC في الوقت الحالي ، فقط أردنا إثبات الشكل).

ج #
الواجهة العامة INonceProvider
{
ReadOnlySpanGetNextNonce (int nonceSize) ،
}

فئة الملخص العامة AuthenticatedEncryptor: IDisposable
{
NonceOrIVSizeInBits العامة int العامة {get؛ }
عامة int TagSizeInBits {get؛ }
منطقي عام SupportsAssociatedData {get؛ }
ReadOnlySpan العامLastNonceOrIV {get؛ }
ReadOnlySpan العامLastTag {get؛ }

protected AuthenticatedEncryptor(
    int tagSizeInBits,
    bool supportsAssociatedData,
    int nonceOrIVSizeInBits) => throw null;

protected abstract bool TryEncrypt(
    ReadOnlySpan<byte> data,
    ReadOnlySpan<byte> associatedData,
    Span<byte> encryptedData,
    out int bytesWritten,
    Span<byte> tag,
    Span<byte> nonceOrIVUsed);

public abstract void GetEncryptedSizeRange(
    int dataLength,
    out int minEncryptedLength,
    out int maxEncryptedLength);

public bool TryEncrypt(
    ReadOnlySpan<byte> data,
    ReadOnlySpan<byte> associatedData,
    Span<byte> encryptedData,
    out int bytesWritten) => throw null;

public byte[] Encrypt(
    ReadOnlySpan<byte> data,
    ReadOnlySpan<byte> associatedData) => throw null;

// some variant of the Dispose pattern here.

}

فئة مختومة عامة AesGcmEncryptor: AuthenticatedEncryptor
{
AesGcmEncryptor العامة (ReadOnlySpankeySize ، INonceProvider nonceProvider)
: base (128، true، 96)
{
}
}

فئة مختومة عامة AesCcmEncryptor: AuthenticatedEncryptor
{
AesCcmEncryptor العامة (
ReadOnlySpanمفتاح،
int nonceSizeInBits ،
INonceProvider nonceProvider ،
علامة intSizeInBits)
: base (tagSizeInBits، true، nonceSizeInBits)
{
التحقق من صحة nonceSize و tagSize مقابل مواصفات الخوارزمية ؛
}
}

فئة الملخص العامة AuthenticatedDecryptor: IDisposable
{
منطقية الملخص العام TryDecrypt (
ReadOnlySpanبطاقة شعار،
ReadOnlySpannonceOrIV ،
ReadOnlySpanالبيانات المشفرة
ReadOnlySpanالبيانات المرتبطة ،
امتدادالبيانات،
خارج int بايت مكتوبة) ؛

public abstract void GetEncryptedSizeRange(
    int encryptedDataLength,
    out int minDecryptedLength,
    out int maxDecryptedLength);

public byte[] Decrypt(
    ReadOnlySpan<byte> tag,
    ReadOnlySpan<byte> nonceOrIV,
    ReadOnlySpan<byte> encryptedData,
    ReadOnlySpan<byte> associatedData) => throw null;

// some variant of the Dispose pattern here.

}

فئة مختومة عامة AesGcmDecryptor: AuthenticatedDecryptor
{
AesGcmDecryptor العامة (ReadOnlySpanمفتاح) => رمي فارغ ؛
}

فئة مختومة عامة AesCcmDecryptor: AuthenticatedDecryptor
{
AesCcmDecryptor العامة (ReadOnlySpanمفتاح) => رمي فارغ ؛
}
""

هذا الاقتراح يلغي تدفق البيانات. ليس لدينا الكثير من المرونة بشأن هذه النقطة. الحاجة في العالم الحقيقي (منخفضة) مقترنة بالمخاطر المرتبطة (مرتفعة للغاية بالنسبة لـ GCM) أو استحالة ذلك (CCM) تعني أنه قد انتهى للتو.

يستخدم هذا الاقتراح مصدرًا خارجيًا لـ nonce للتشفير. لن يكون لدينا أي تطبيقات عامة لهذه الواجهة. يجب أن يقوم كل تطبيق / بروتوكول بربط المفتاح بالسياق الخاص به حتى يتمكن من تغذية الأشياء بشكل مناسب. في حين أن كل مكالمة إلى TryEncrypt ستجري مكالمة واحدة فقط إلى GetNextNonce ، فليس هناك ما يضمن نجاح برنامج TryEncrypt المحدد ، لذلك لا يزال الأمر متروكًا للتطبيق لفهم ما إذا كان هذا يعني أنه يجب إعادة المحاولة مرة أخرى. بالنسبة إلى CBC + HMAC ، سننشئ واجهة جديدة ، IIVProvider ، لتجنب تشويش المصطلحات. بالنسبة إلى SIV ، يتم إنشاء IV ، لذلك لا يوجد متغير مقبول ؛ واستنادًا إلى المواصفات ، يبدو أن nonce (عند استخدامه) يعتبر جزءًا من البيانات المرتبطة. لذا ، يقترح SIV ، على الأقل ، أن وجود nonceOrIV كمعامل في TryEncrypt لا ينطبق بشكل عام.

من المؤكد أن TryDecrypt يرمي على علامة غير صالحة. يتم إرجاع خطأ فقط إذا كانت الوجهة صغيرة جدًا (وفقًا لقواعد طرق المحاولة)

الأشياء التي هي بالتأكيد مفتوحة للتعليق:

  • يجب أن تكون الأحجام بالبتات (مثل الأجزاء المهمة من المواصفات) أو البايت (نظرًا لأن قيم٪ 8 فقط تعتبر قانونية على أي حال ، وسنقوم دائمًا بالتقسيم ، وتتحدث بعض أجزاء المواصفات عن أشياء مثل الحجم nonce بالبايت )؟
  • أسماء المعلمات وترتيبها.
  • خصائص LastTag / LastNonceOrIV. (جعلها (قابلة للكتابة) الامتدادات على TryEncrypt العام يعني فقط أن هناك ثلاثة مخازن مؤقتة يمكن أن تكون صغيرة جدًا ، من خلال جعلها تجلس على الجانب يكون "Try" أكثر وضوحًا ؛ يمكن للفئة الأساسية أن تقدم الوعد بأنها سوف لا تقدم أبدًا مخزنًا مؤقتًا قصير جدًا.).
  • تقديم خوارزمية AE التي لا يعمل هذا من أجلها.
  • هل يجب نقل associatedData إلى النهاية باستخدام الإعداد الافتراضي ReadOnlySpan<byte>.Empty ؟

    • أو جعل الأحمال الزائدة التي تحذف ذلك؟

  • هل يريد أي شخص تأكيد الحب أو الكراهية لأساليب العودة byte[] ؟ (يمكن تحقيق التخصيص المنخفض باستخدام طريقة Span ، وهذا فقط للراحة)
  • طرق نطاقات الحجم كانت نوعًا ما مثبتة في النهاية.

    • الغرض منها هو أن

    • إذا كان مدى الوجهة أقل من min ، فقم بإرجاع القيمة false على الفور.

    • ستخصص طرق الإرجاع byte[] مخزنًا مؤقتًا بحد أقصى ، ثم Array ، قم بتغيير حجمه حسب الحاجة.

    • نعم ، بالنسبة لـ GCM و CCM min=max=input.Length ، لكن هذا ليس صحيحًا بالنسبة لـ CBC + HMAC أو SIV

    • هل هناك خوارزمية يجب أن تأخذ في الاعتبار طول البيانات المرتبطة؟

بالتأكيد بايت - وليس بت.
يعد مقدم الخدمة nonce الذي ليس على دراية بالمفتاح خطأً فادحًا.

يعد مقدم الخدمة nonce الذي ليس على دراية بالمفتاح خطأً فادحًا.

يمكنك كتابة مزود nonce الخاص بك كيفما تشاء. نحن لا نقدم أي.

ماذا عن التنظيف الحتمي / IDisposable ؟

ماذا عن التنظيف الحتمي / القابل للتصرف؟

دعوة جيدة. تمت إضافته إلى AuthenticatedEncryptor / AuthenticatedDecryptor. لا أعتقد أنه ينبغي عليهم التحقق من إمكانية التخلص من المزود غير الرسمي ، يمكن للمتصل فقط تكديس عبارات الاستخدام.

INonceProvider المفهوم / الغرض لا معنى له بالنسبة لي (مرددًا صدى الآخرين). دع الأوليات تكون بدائية - قم بالمرور في nonce بنفس الطريقة التي تمرر بها المفتاح (على سبيل المثال ، مثل بايت - مهما تم الإعلان عنها). لا توجد مواصفات AE / AEAD تفرض خوارزمية لكيفية إنشاء / اشتقاق nonces - هذه مسؤولية طبقة أعلى (على الأقل في نموذج let-primitives-be-primitive).

لا يتدفقون؟ هل حقا؟ ما هو مبرر الإزالة القسرية للدفق من تيار مشفر مثل AES-GCM على المستوى التأسيسي الأساسي؟

على سبيل المثال ، ما الذي يوصي به مجلس التشفير الخاص بك بهذين السيناريوهين الأخيرين اللذين قمنا بمراجعتهما؟

  1. العميل لديه ملفات رعاية صحية كبيرة بين 10-30 جيجابايت. لا يرى النواة سوى تدفق بيانات بين جهازيْن ، لذلك يكون دفقًا واحدًا. من الواضح أنه يتم إصدار مفتاح جديد لكل ملف بحجم 10 غيغابايت ولكنك جعلت كل سير عمل من هذا القبيل عديم الفائدة. تريد منا الآن أ) تخزين البيانات (الذاكرة ، بدون خطوط الأنابيب) ب) إجراء التشفير (جميع الأجهزة الموجودة في خط الأنابيب خاملة الآن!) ج) كتابة البيانات (البايت الأول المكتوب بعد أ و ب هو 100٪ فعله) ؟ من فضلك قل لي أنك تمزح. أنتم يا رفاق تعيدون عن قصد "التشفير عبء" إلى اللعبة.

  2. تحتوي وحدة الأمان المادي على عدة تدفقات 4K والتي يتم تشفيرها أيضًا لسيناريوهات الراحة. إصدار مفتاح جديد يحدث عند حدود 15 جيجابايت. تقترح تخزين المقطع بالكامل مؤقتًا؟

لا أرى أي مدخلات من المجتمع ، من الأشخاص الذين يقومون بالفعل ببناء برامج في العالم الحقيقي ، ويطلبون إزالة دعم البث. ولكن بعد ذلك ، يختفي الفريق من حوار المجتمع ، ويتجمع داخليًا ثم يعود بشيء لم يطلبه أحد ، وهو شيء يقتل التطبيقات الحقيقية ويعيد فرض أن "التشفير بطيء ومكلف ، هل تريد تخطيه؟"

يمكنك تقديم Encrypt و EncryptFinal والتي ستدعم كلا الخيارين بدلاً من فرض قرارك على النظام البيئي بأكمله.

يزيل التصميم الأنيق التعقيد وليس التحكم.

ما هو مبرر الإزالة القسرية للدفق من تيار مشفر مثل AES-GCM على المستوى التأسيسي الأساسي؟

أعتقد أنه كان شيئًا مثل

هذا الاقتراح يلغي تدفق البيانات. ليس لدينا الكثير من المرونة بشأن هذه النقطة. الحاجة في العالم الحقيقي (منخفضة) مقترنة بالمخاطر المرتبطة (مرتفعة للغاية بالنسبة لـ GCM) أو استحالة ذلك (CCM) تعني أنه قد انتهى للتو.

يحتوي GCM على الكثير من لحظات الخطأ حيث يسمح باسترداد المفتاح. إذا تمكن المهاجم من عمل نص مشفر مختار ومشاهدة إخراج البث من قبل التحقق من العلامة ، فيمكنه استرداد المفتاح. (أو هكذا أخبرني أحد محللي الشفرات). بشكل فعال ، إذا كانت أي بيانات تمت معالجتها بواسطة GCM يمكن ملاحظتها في أي وقت قبل التحقق من العلامة ، فسيتم اختراق المفتاح.

أنا متأكد تمامًا من أن Crypto Board سيوصي بعدم استخدام GCM للسيناريو الأول ، بل CBC + HMAC.

إذا كان السيناريو الثاني الخاص بك هو إطار 4K ، وكنت تقوم بتشفير كل إطار 4K ، فهذا يعمل مع هذا النموذج. يتم فك تشفير كل إطار علامة 4k + nonce + والتحقق منه قبل استعادة وحدات البايت ، لذلك لا تتسرب مطلقًا من تدفق المفاتيح / المفتاح.

للمقارنة: أقوم حاليًا بتطوير واجهة برمجة تطبيقات التشفير هذه "دع الأساسيات تكون بدائية". هنا صفي للتشفير المصدق.

بالنسبة لي ، اتضح أنه من المفيد أن أكون قادرًا على التحدث عن تشفير بدائي بشكل مستقل عن المفتاح. على سبيل المثال ، غالبًا ما أرغب في توصيل بدائية معينة بطريقة تعمل مع أي خوارزمية AEAD وترك توليد المفاتيح وما إلى ذلك لتلك الطريقة. لذلك هناك فئة AeadAlgorithm وفئة Key منفصلة.

هناك شيء آخر مفيد للغاية منع بالفعل العديد من الأخطاء وهو استخدام أنواع مميزة لتمثيل بيانات من أشكال مختلفة ، على سبيل المثال ، مفتاح و Nonce ، بدلاً من استخدام byte[] أو Span<byte> لكل شيء.


AeadAlgorithm API (انقر للتوسيع)

public abstract class AeadAlgorithm : Algorithm
{
    public int KeySize { get; }

    public int NonceSize { get; }

    public int TagSize { get; }

    public byte[] Decrypt(
        Key key,
        Nonce nonce,
        ReadOnlySpan<byte> associatedData,
        ReadOnlySpan<byte> ciphertext)

    public void Decrypt(
        Key key,
        Nonce nonce,
        ReadOnlySpan<byte> associatedData,
        ReadOnlySpan<byte> ciphertext,
        Span<byte> plaintext)

    public byte[] Encrypt(
        Key key,
        Nonce nonce,
        ReadOnlySpan<byte> associatedData,
        ReadOnlySpan<byte> plaintext)

    public void Encrypt(
        Key key,
        Nonce nonce,
        ReadOnlySpan<byte> associatedData,
        ReadOnlySpan<byte> plaintext,
        Span<byte> ciphertext)

    public bool TryDecrypt(
        Key key,
        Nonce nonce,
        ReadOnlySpan<byte> associatedData,
        ReadOnlySpan<byte> ciphertext,
        out byte[] plaintext)

    public bool TryDecrypt(
        Key key,
        Nonce nonce,
        ReadOnlySpan<byte> associatedData,
        ReadOnlySpan<byte> ciphertext,
        Span<byte> plaintext)
}

bartonjs هو / هي على صواب ، فأنت بحاجة إلى الاعتماد على البرنامج الذي لا يخرج حتى المصادقة. لذلك على سبيل المثال ، إذا لم تكن تقوم بالمصادقة (أو لم تقم بذلك بعد) ، فيمكنك التحكم في إدخال كتلة وبالتالي معرفة الإخراج والعمل عكسيًا من هناك ...

على سبيل المثال ، يمكن لرجل في الهجوم الأوسط حقن كتل معروفة في تيار cbc وتنفيذ هجوم تقليب تقليدي.

لست متأكدًا من كيفية حل الأجزاء الكبيرة من مشكلة البيانات حقًا أخرى بفضل تقسيمها بأرقام متسلسلة أو ما شابه ذلك ... علاء TLS.

حسنًا ، دعني أعيد صياغة ما أفعله ولكن فقط في حالة الأحجام الصغيرة للشبكة والتي لا تكفي للأغراض العامة.

بروح الانفتاح ، هل من الممكن الكشف عن الأعضاء في مجلس مراجعة التشفير لـ Microsoft (ومن الأفضل أن تكشف عن تعليقات / آراء أعضاء محددين قاموا بمراجعة هذا الموضوع)؟ براين لاماكيا ومن غيره؟

_باستخدام علم النفس العكسي _

أنا سعيد لأن بث AEAD قد انتهى. هذا يعني أن Inferno لا يزال هو التدفق العملي الوحيد AEAD القائم على CryptoStream لمتوسط ​​Joe. شكرا لك MS Crypto Review Board!

بناءً على تعليق ektrah ، فإن نهجه (الخاص بها؟) مدفوع بـ RFC 5116 ، الذي أشرت إليه سابقًا. هناك العديد من الاقتباسات البارزة في RFC 5116:

3.1 متطلبات إنشاء الجينات
من الضروري للأمان أن يتم إنشاء nonces بطريقة تحترم متطلبات أن تكون كل قيمة nonce مميزة لكل استدعاء لعملية التشفير المصادق عليها ، لأي قيمة ثابتة للمفتاح.
...

  1. متطلبات مواصفات خوارزمية AEAD
    يجب أن تقبل كل خوارزمية AEAD أي خوارزمية nonce بطول يتراوح بين N_MIN و N_MAX ثماني بتات ، بما في ذلك ، حيث تكون قيم N_MIN و N_MAX خاصة بتلك الخوارزمية. قد تكون قيم N_MAX و N_MIN متساوية. يجب أن تقبل كل خوارزمية قيمة nonce بطول اثنتي عشرة (12) ثماني بتات. قد تحتوي الخوارزميات العشوائية أو ذات الحالة ، الموضحة أدناه ، على قيمة N_MAX صفر.
    ...
    قد تتضمن خوارزمية التشفير المصدق مصدرًا عشوائيًا أو تستخدمه ، على سبيل المثال ، لإنشاء متجه تهيئة داخلي مدمج في إخراج النص المشفر. تسمى خوارزمية AEAD من هذا النوع العشوائية ؛ على الرغم من ملاحظة أن التشفير فقط هو عشوائي ، وأن فك التشفير دائمًا حتمي. قد تحتوي الخوارزمية العشوائية على قيمة N_MAX تساوي صفرًا.

قد تتضمن خوارزمية التشفير المصدق معلومات الحالة الداخلية التي يتم الاحتفاظ بها بين استدعاءات عملية التشفير ، على سبيل المثال ، للسماح ببناء قيم مميزة يتم استخدامها كخوارزمية داخلية بواسطة الخوارزمية. تسمى خوارزمية AEAD من هذا النوع ذات الحالة. يمكن استخدام هذه الطريقة بواسطة خوارزمية لتوفير أمان جيد حتى عندما يقوم التطبيق بإدخال أرقام غير محدودة الطول الصفري. قد تحتوي الخوارزمية ذات الحالة على قيمة N_MAX تساوي صفرًا.

إحدى الأفكار التي يحتمل أن تستحق الاستكشاف هي تمرير Nonce ذات الطول الصفري / الفارغ ، والتي قد تكون حتى الافتراضي. سيؤدي تمرير قيمة Nonce "الخاصة" هذه إلى إجراء عشوائي لقيمة Nonce الفعلية ، والتي ستكون متاحة كمخرجات Encrypt.

إذا بقي INonceProvider بسبب "أسباب" ، هناك فكرة أخرى تتمثل في إضافة مكالمة Reset() ، والتي سيتم تشغيلها في كل مرة يتم فيها إعادة طلب AuthenticatedEncryptor . من ناحية أخرى ، إذا كانت الخطة هي عدم إعادة إنشاء مثيل AuthenticatedEncryptor ، فسيؤدي ذلك إلى حذف GC إذا أردنا إنشاء واجهة برمجة تطبيقات تشفير متدفقة (على سبيل المثال chunk = حزمة شبكة) ، ويجب أن تكون كل قطعة مشفر بمفتاح مختلف (مثل بروتوكول Netflix MSL و Inferno وغيرها). خاصة بالنسبة لعمليات enc / dec المتوازية حيث نرغب في الحفاظ على مجموعة من محركات AEAD ، واستعارة مثيلات من هذا التجمع لإجراء enc / dec. دعونا نعطي GC بعض الحب :)

من وجهة نظري ، فإن الغرض الوحيد من أساسيات التشفير هو تنفيذ بروتوكولات أمان عالية المستوى جيدة التصميم. كل بروتوكول من هذا القبيل يصر على إنشاء الرموز غير الرسمية بطريقتهم الخاصة. فمثلا:

  • يتبع TLS 1.2 توصيات RFC 5116 وسلسلة 4 بايت IV مع عداد 8 بايت ،
  • TLS 1.3 xor عداد 8 بايت مبطن بـ 12 بايت مع 12 بايت IV ،
  • يستخدم Noise عداد 8 بايت مبطن حتى 12 بايت بترتيب بايت كبير الحجم لـ AES-GCM وعداد 8 بايت مبطن إلى 12 بايت بترتيب بايت صغير الحجم لـ ChaCha / Poly.

GCM هش للغاية بالنسبة للأرقام غير المخصصة العشوائية بأحجام nonce نموذجية (96 بت). ولست على علم بأي بروتوكول أمان يدعم فعليًا الأرقام العشوائية.

لا يوجد طلب كبير على المزيد من واجهات برمجة التطبيقات التي توفر أساسيات التشفير. يحتاج 99.9٪ من المطورين إلى وصفات عالية المستوى للسيناريوهات المتعلقة بالأمان: تخزين كلمة مرور في قاعدة بيانات ، وتشفير ملف في حالة السكون ، ونقل تحديث البرنامج بأمان ، وما إلى ذلك.

ومع ذلك ، فإن واجهات برمجة التطبيقات لمثل هذه الوصفات عالية المستوى نادرة. غالبًا ما تكون واجهات برمجة التطبيقات (API) الوحيدة المتاحة هي HTTPS والأساسيات المشفرة فقط ، مما يجبر المطورين على تشغيل بروتوكولات الأمان الخاصة بهم. لا يتمثل الحل في IMO في بذل الكثير من الجهد في تصميم واجهات برمجة التطبيقات للعمل مع الأوليات. إنها واجهات برمجة تطبيقات للوصفات عالية المستوى.

شكرا لردود الفعل ، الجميع! بعض الأسئلة:

  1. بينما يمكن أن يفشل دفق التشفير بشكل كارثي ، يمكن أن يكون تشفير البث ممكنًا. هل تشفير البث (مع خيار عدم البث) ولكن فقط فك التشفير غير المتدفق يبدو أكثر فائدة؟ إذا كانت الإجابة بنعم ، فهناك مشكلتان يجب حلهما:
    أ. بعض الخوارزميات (CCM ، SIV) لا تدعم البث فعليًا. هل يجب أن نضع تشفير التدفق على الفئة الأساسية والمدخلات المتدفقة في المخزن المؤقت أم نرمي من الفئات المشتقة؟
    ب. من المحتمل ألا يكون دفق AAD ممكنًا بسبب قيود التنفيذ ، ولكن تحتاجه الخوارزميات المختلفة في أوقات مختلفة (يحتاجه البعض في البداية ، والبعض الآخر لا يحتاجه حتى النهاية). هل يجب أن نطلبها مقدمًا أم أن لدينا طريقة لإضافتها تعمل عندما تسمح الخوارزميات الفردية؟
  1. نحن منفتحون على إدخال تحسينات على INonceProvider طالما أن الهدف هو أن المستخدمين بحاجة إلى كتابة رمز لإنشاء رمز nonce جديد. هل لدى أي شخص شكل آخر مقترح لها؟

1. أ = أعتقد أنه قد يكون عدم تحذير المستخدم مبكرًا مشكلة. تخيل السيناريو من شخص فوق ، ملف 10 جيجابايت. يعتقدون أنهم يتدفقون ، ثم في وقت لاحق قام مطور آخر بتغيير الشفرة والشيء التالي هو تخزين الكود 10 جيجابايت مؤقتًا (أو المحاولة) قبل إرجاع قيمة.

  1. b = مرة أخرى مع فكرة "الدفق" أو الشبكة ، على سبيل المثال AES GCM وما إلى ذلك ، لن تحصل على معلومات AAD حتى نهاية فك التشفير. بالنسبة للتشفير ، ما زلت أرى حالة لا تملك فيها البيانات مقدمًا. لذلك أود أن أقول على الأقل بالنسبة للتشفير يجب أن تطلبه في البداية ، فك التشفير أكثر تعقيدًا.
  1. أعتقد أنها ليست مشكلة حقًا ، توفير "بايت" لـ nonce من خلال واجهة أو فقط بشكل مباشر ليس هنا ولا هناك. يمكنك تحقيق الشيء نفسه في كلا الاتجاهين ، أجده أقبح بالنسبة لشخص بدائي ولكني لا أعارض بشدة إذا كان ذلك يجعل الناس ينامون بشكل أفضل في الليل. أود فقط أن أشطب هذا باعتباره صفقة منتهية ، وأمضي قدمًا في القضايا الأخرى.

فيما يتعلق بعملية المداولات

bartonjs : يمكننا الجدال طوال اليوم إذا كانت قرارات الباب المغلق الخالية من مشاركة المجتمع تبريرًا فعالًا ولكننا سنخرج عن الموضوع ، لذلك سأترك ذلك. بالإضافة إلى أنه بدون اتصالات أكثر ثراءً وجهاً لوجه أو اتصالات في الوقت الفعلي ، لا أريد أن أزعج أي شخص هناك.

بخصوص الجري

1. لا يعني الدفق عدم وجود حجة أمان AES-GCM

على وجه التحديد ، البخار => إعادة البيانات المشفرة إلى المتصل قبل التحقق من العلامة => لا يوجد أمان. هذا ليس سليمًا. تدعي bartonjs 'ciphertext المختار => مشاهدة الإخراج => استرداد المفتاح' بينما يدعي drawaes 'إدخال التحكم للكتلة => لذا تعرف الإخراج => "العمل من هناك"

حسنًا ، في AES-GCM ، الشيء الوحيد الذي تفعله العلامة هو التحقق من السلامة (الحماية من العبث). ليس لها تأثير على الخصوصية. في الواقع ، إذا قمت بإزالة معالجة علامة GCM / GHASH من AES-GCM ، فستحصل ببساطة على وضع AES-CTR. هذا البناء هو الذي يتعامل مع جانب الخصوصية. ونسبة النقر إلى الظهور (CTR) قابلة للطرق ولكن لا يتم "كسرها" بأي طريقة من الطرق التي تؤكد بها (استرداد مفتاح أو نص عادي) لأن ذلك قد يعني أن أساسيات AES الأساسية قد تم اختراقها. إذا كان محلل الشفرات الخاص بك (من هو؟) يعرف شيئًا لا يعرفه بقيتنا ، فيجب عليه / عليها نشره. الشيء الوحيد الممكن هو أنه يمكن للهجوم أن يقلب الجزء N ويعرف أن الجزء N من النص العادي قد تم قلبه - لكنهم لا يعرفون أبدًا ما هو النص العادي الفعلي.

لذا

1) يتم دائمًا فرض خصوصية النص العادي
2) يتم ببساطة تأجيل التحقق من السلامة (حتى نهاية الدفق) و
3) لم يتم اختراق أي مفتاح.

بالنسبة للمنتجات والأنظمة التي يكون البث فيها أساسيًا ، يمكنك الآن على الأقل هندسة مقايضة حيث يتراجع المرء للحظات من AEAD إلى تشفير AES العادي - ثم الرجوع إلى AEAD عند التحقق من العلامة. يفتح ذلك العديد من المفاهيم المبتكرة لتبني الأمان بدلاً من الذهاب "تريد تخزين كل ذلك - هل أنت مجنون؟ لا يمكننا عمل التشفير!".

كل ذلك لأنك تريد تنفيذ EncryptFinal فقط بدلاً من كل من Encrypt و EncryptFinal (أو ما يعادلها).

2. غير خاص بـ GCM!

الآن AES-GCM ليس وحشًا سحريًا يتمتع بـ "لحظات عفوية" وافرة. إنه ببساطة AES-CTR + GHASH (نوع من التجزئة إذا جاز لي ذلك). يتم توريث الاعتبارات غير الأساسية المتعلقة بالخصوصية من وضع نسبة النقر إلى الظهور (CTR) وتأتي اعتبارات العلامات المتعلقة بالتكامل من أحجام العلامات المتغيرة المسموح بها في المواصفات. ومع ذلك ، فإن AES-CTR + GHASH تشبه إلى حد بعيد شيئًا مثل AES-CBC + HMAC-SHA256 من حيث أن الخوارزمية الأولى تتعامل مع الخصوصية بينما تتعامل الخوارزمية الثانية مع النزاهة. في AES-CBC + HMAC-SHA256 ، ستؤدي تقلبات البت في النص المشفر إلى إتلاف الكتلة المقابلة في النص غير المشفر (على عكس CTR) وأيضًا قلب البتات بشكل حاسم في كتلة النص العادي التالية التي تم فك تشفيرها (مثل CTR). مرة أخرى ، لن يعرف المهاجم ما هو النص العادي الناتج - فقط تم قلب البتات (مثل نسبة النقر إلى الظهور). أخيرًا ، سيؤدي فحص النزاهة (HMAC-SHA256) إلى اكتشافه. لكن معالجة البايت الأخير فقط (مثل GHASH).

لذا ، إذا كانت حجتك المتمثلة في كبح جميع البيانات التي تم فك تشفيرها حتى تصبح النزاهة جيدة حقًا - فيجب تطبيقها باستمرار. لذلك يجب أيضًا تخزين جميع البيانات الصادرة من مسار AES-CBC (داخليًا بواسطة المكتبة) حتى مرور HMAC-SHA256. هذا يعني أساسًا أنه على .NET ، لا يمكن أن تستفيد أي بيانات متدفقة من تقدم AEAD. .NET يفرض تدفق البيانات إلى إصدار أقدم. للاختيار بين عدم وجود تشفير أو تشفير عادي. لا AEAD. عندما يكون التخزين المؤقت غير عملي من الناحية الفنية ، يجب أن يكون لدى المهندسين المعماريين على الأقل خيار تحذير المستخدمين النهائيين من أن "لقطات الطائرات بدون طيار قد تكون فاسدة" بدلاً من "عدم النظر إليك".

3. إنه أفضل ما لدينا

البيانات تزداد حجمًا ويجب أن يكون الأمان أقوى. يعد البث أيضًا حقيقة يجب على المصممين احتضانها. حتى يقوم العالم بصياغة خوارزمية AEAD متكاملة حقًا يمكنها اكتشاف الفساد أثناء التلاعب في منتصف التدفق ، فإننا عالقون مع التشفير + المصادقة كأصدقاء مثبتين. يتم البحث عن بدائية AEAD الحقيقية ولكن لدينا للتو تشفير + مصادقة في الوقت الحالي.

لا أهتم كثيرًا بـ "AES-GCM" بقدر ما أهتم بخوارزمية AEAD السريعة والشائعة التي يمكنها دعم تدفق أعباء العمل - منتشر بشكل كبير في عالم غني بالبيانات ومتصل بشكل كبير.

4. استخدم AES-CBC-HMAC ، استخدم (أدخل الحل)

يوصي مجلس التشفير بعدم استخدام GCM للسيناريو الأول ، بل باستخدام CBC + HMAC.

بغض النظر عن كل ما هو مذكور أعلاه أو حتى تفاصيل السيناريو - مما يشير إلى أن AES-CBC-HMAC ليس مجانيًا. إنه أبطأ بثلاث مرات تقريبًا من AES-GCM نظرًا لأن تشفير AES-CBC غير قابل للتوازي وبما أنه يمكن تسريع GHASH عبر تعليمات PCLMULQDQ. لذا ، إذا كنت في 1 جيجابايت / ثانية باستخدام AES-GCM ، فستصل الآن إلى 300 ميجابايت / ثانية باستخدام AES-CBC-HMAC. يؤدي هذا مرة أخرى إلى ارتكاب عقلية "Crypto تبطئ من سرعتك ، وتخطيها" - وهي عقلية يحاول أفراد الأمن مكافحتها بشدة.

تشفير كل إطار 4K

يجب أن تفعل برامج ترميز الفيديو التشفير فجأة؟ أو يجب أن تفهم طبقة التشفير الآن برامج ترميز الفيديو؟ إنه مجرد دفق بت في طبقة أمان البيانات. لا ينبغي أن تكون حقيقة أنها فيديو / بيانات جينومية / صور / تنسيقات مملوكة وما إلى ذلك مصدر قلق لطبقة الأمان. الحل الشامل لا ينبغي أن يختلط المسؤوليات الأساسية.

نونس

يسمح NIST لـ IVs العشوائية بطول يتجاوز 96 بت. انظر القسم 8.2.2 في NIST 800-38D . لا جديد هنا ، متطلبات nonce تأتي من وضع نسبة النقر إلى الظهور. وهو أيضًا قياسي إلى حد ما عبر معظم أصفار الدفق . لا أفهم الخوف المفاجئ تجاه الأشخاص غير المتفرغين - فقد كان دائمًا number used once . ومع ذلك ، في حين أن المناظرة INonce تجعل واجهة المستخدم عالية الجودة ، إلا أنها على الأقل لا تلغي الابتكار مثل فرض عدم البث. سأتنازل عن INonce في أي يوم إذا تمكنا من الحصول على AEAD Security + ابتكارات عبء العمل المتدفقة. أكره تسمية شيء أساسي مثل بث ابتكار - ولكن هذا هو المكان الذي أخشى أن نتراجع فيه.

أحب أن أكون مخطئًا

أنا مجرد رجل بعد يوم طويل في العمل ، تخلى عن ليلة الفيلم مع أطفالي لكتابة هذا. أنا متعب ويمكن أن أكون مخطئا. ولكن على الأقل لديك حوار مجتمعي مفتوح قائم على الحقائق بدلاً من الحكايات أو "أسباب اللجنة" أو بعض الفودو الأخرى. أنا أعمل على تعزيز ابتكارات .NET و Azure الآمنة. أعتقد أن لدينا أهدافًا متسقة.

الحديث عن الحوار المجتمعي ...

هل يمكن أن يكون لدينا مكالمة Skype مجتمعية؟ إن التعبير عن موضوع معقد مثل هذا ينفجر في جدار ضخم من النص. جميلة من فضلك؟

من فضلك لا تجري مكالمة Skype - هذا هو تعريف "الاجتماع المغلق" ، مع عدم وجود سجلات متاحة للمجتمع. تعد مشكلات Github هي الأداة المناسبة لجميع الأطراف للحصول على خطاب مدني موثق (تجاهل سوابق إزالة التعليقات MS).

من المحتمل أن يكون مجلس مراجعة MS Crypto قد أجرى مكالمة Skype أيضًا. إنه ليس خطأ أعضاء MS المشاركين في هذا الموضوع - فمن المحتمل أن يكون لديهم وصول محدود للغاية إلى الأبراج العاجية من MS Crypto Review Board (أيا كان / أيا كان).

بخصوص تدفق AEAD:

دفق حجم البايت _encryption_ ممكن لأنماط MAC-last مثل GCM و CTR + HMAC ، ولكن غير ممكن لأنماط MAC-first مثل CCM. يعد التدفق بحجم البايت _decryption_ في الأساس تسريبًا وبالتالي لا يتم اعتباره من قبل أي شخص. يمكن أيضًا البث بحجم الكتلة _encryption_ لـ CBC + HMAC ، لكن هذا لا يغير شيئًا. بمعنى آخر. نهج حجم البايت أو حجم الكتلة لدفق AEAD معيب.

يعمل البث بحجم الكتلة _encryption_ و _decryption_ بشكل رائع ، لكن لهما قيدان:

  • تتطلب تخزينًا مؤقتًا (يتجاوز حجم الكتلة). يمكن القيام بذلك عن طريق المكتبة / API إذا تم التحكم في التخزين المؤقت / تغطيته (على سبيل المثال ، Inferno) ، أو تركه للطبقة العليا (الطبقة المستدعاة) للتعامل معها. يعمل في كلتا الحالتين.

  • إن التدفق المتقطع AEAD غير موحد. السابق. nacl-Stream ، Inferno، MS-own DataProtection ، اصنع بنفسك.

هذا مجرد ملخص لما يعرفه الجميع في هذه المناقشة بالفعل.

sdrapkin ، للتأكد من فهمي بشكل صحيح ، هل أنت موافق على واجهة برمجة التطبيقات هذه التي توفر تشفير البث ، ولكن لا يوجد فك تشفير للبث؟

sdrapkin حسنًا ، العصف الذهني للبشر في الوقت الفعلي مفيد بالتأكيد ، ويمكن حل مشكلات حفظ السجلات من خلال محضر الاجتماع. بالعودة إلى الجانب التقني ، بينما يعمل التقسيم من أجل فك تشفير البث ، فإن هذا ليس مستوى أمانًا أوليًا منخفضًا. إنه بروتوكول مخصص. وأخرى غير قياسية كما لاحظت.

تضمين التغريدة

_ هل أنت موافق على واجهة برمجة التطبيقات هذه التي توفر تشفير البث ، ولكن لا يوجد فك تشفير للبث؟ _

لا أنا لست كذلك. إذا كانت واجهة برمجة التطبيقات هذه متاحة ، فسيكون من السهل إنشاء نص مشفر مشفر بشكل متدفق بحجم لا يمكن لفك تشفير المخزن المؤقت فك تشفيره (نفاد الذاكرة).

^^ ^^ كلاهما من "مرحبًا كانت طرق فك تشفير الدفق التي اعتقدت أنني سأعتمد عليها نظرًا لوجود طرق تشفير" ، وبسبب تعليقات sdrapkin أعلاه.

Drawaes متفق عليه. إن واجهة برمجة تطبيقات enc / dec غير المتماثلة ستكون مريعة.

أي تحديثات الناس؟

يبدو أنني خلطت بين بعض الهجمات.

تسمح نقاط الضعف المتأصلة في أصفار الدفق (التي تعتبر AES-CTR و AES-GCM) بهجمات النص المشفر المختارة للسماح باستعادة النص العادي التعسفي. الدفاع ضد هجمات النص المشفر المختار هو المصادقة ؛ لذا فإن AES-GCM محصن ... إلا إذا كنت تقوم بفك تشفير البث ويمكنك التعرف من خلال ملاحظات القناة الجانبية على ما كان يمكن أن يكون عليه النص العادي. على سبيل المثال ، إذا تمت معالجة البيانات التي تم فك تشفيرها بتنسيق XML ، فسوف تفشل بسرعة كبيرة إذا كانت الأحرف غير المسافة البيضاء أو <في بداية البيانات التي تم فك تشفيرها. لذلك فإن "فك التشفير المتدفق يعيد تقديم الاهتمامات المتعلقة بتصميم تشفير الدفق" (والذي ربما لاحظت أن .NET ليس لديه أي من ذلك).

أثناء البحث عن مصدر استرداد المفتاح ، توجد أوراق مثل المصادقةنقاط الضعف في GCM (Ferguson / Microsoft) ، ولكن هذا الشخص يستعيد مفتاح المصادقة بناءً على أحجام العلامات القصيرة (وهو جزء من سبب سماح تطبيق Windows بعلامات 96 بت فقط). ربما تم إخطاري بموجهات استرداد مفتاح المصادقة الأخرى حول سبب خطورة تدفق GCM.

في تعليق سابق ، أشار sdrapkin إلى أن "فك تشفير تدفق حجم البايت هو في الأساس تسريب وبالتالي لا يعتبره أي شخص. ... نهج حجم البايت أو حجم الكتلة لدفق AEAD معيب.". هذا ، جنبًا إلى جنب مع CCM (و SIV) غير قادرين على القيام بتشفير البث والتعليق عليه سيكون من الغريب أن يكون هناك بث واحد وليس الآخر ، مما يشير إلى أننا عدنا إلى اقتراح الحصول على تشفير طلقة واحدة و فك.

لذلك يبدو أننا عدنا إلى آخر اقتراح لواجهة برمجة التطبيقات (https://github.com/dotnet/corefx/issues/23629#issuecomment-329202845). ما لم تكن هناك مشكلات معلقة أخرى تمكنت من نسيانها أثناء إجازة بعض الوقت.

أهلا بكم من جديد @ bartonjs

سوف أنام لوقت قصير ولكن لفترة وجيزة:

  1. لقد خلطنا بين تصميم البروتوكول والتصميم البدائي من قبل في هذا الموضوع. سأقول فقط أن هجمات النص المشفر المختارة هي مصدر قلق لتصميم البروتوكول ، وليست مصدر قلق بدائي.

  2. يتيح لك فك تشفير AEAD المتدفق على الأقل التمتع بالخصوصية ثم الترقية على الفور إلى الخصوصية + الأصالة في آخر بايت. بدون دعم البث على AEAD (أي الخصوصية التقليدية فقط) ، فأنت تقيد الأشخاص بشكل دائم بضمان أقل للخصوصية فقط.

إذا كانت المزايا التقنية غير كافية أو كنت (بحق) متشككًا في مصداقية حججي ، فسأحاول مسار السلطة الخارجية. يجب أن تعلم أن التنفيذ الأساسي الفعلي يدعم AEAD (بما في ذلك AES GCM) في وضع البث. يتيح نظام تشغيل Windows الأساسي ( bcrypt ) دفق GCM عبر وظائف BCryptEncrypt أو BCryptDecrypt . انظر dwFlags هناك. أو مثال على رمز المستخدم . أو برنامج تضمين CLR مؤلف من Microsoft. أو أن التطبيق قد حصل على شهادة NIST FIP-140-2 مؤخرًا في وقت سابق من هذا العام. أو أن كلاً من Microsoft و NIST قد أنفقا موارد كبيرة حول تطبيق AES واعتمادهما هنا وهنا . وعلى الرغم من كل هذا ، لم يلوم أحد الأعداء. ليس من المنطقي على الإطلاق أن يأتي .NET Core فجأة ويفرض أطروحته الخاصة بالشفرات لتقليل التنفيذ الأساسي القوي. خاصة عندما يمكن دعم كل من البث المباشر ولقطة واحدة في وقت واحد ، بشكل تافه للغاية.

أكثر؟ حسنًا ، ما ورد أعلاه ينطبق على OpenSSL ، حتى مع واجهات برمجة تطبيقات evp "الأحدث".

وهذا صحيح بالنسبة إلى BouncyCastle.

وهذا صحيح مع Java Cryptography Architecture.

في صحتك!
سيد

sidshetye ++ 10 إذا كانت لوحة التشفير قلقة للغاية فلماذا تسمح لـ windows CNG بالقيام بذلك؟

إذا قمت بفحص التحقق من صحة Microsoft NIST FIPS-140-2 AES (على سبيل المثال # 4064 ) ، فستلاحظ ما يلي:

AES-GCM:

  • أطوال النص العادي: 0 ، 8 ، 1016 ، 1024
  • أطوال AAD: 0، 8، 1016، 1024

AES-CCM:

  • طول النص العادي: 0-32
  • طول AAD: 0-65536

لا يوجد التحقق من صحة للبث. لست متأكدًا حتى مما إذا كان NIST يتحقق من ذلك السابق. لا ينبغي السماح لتطبيق AES-GCM بتشفير أكثر من 64 جيجا بايت نص عادي (قيد آخر مثير للسخرية لـ GCM).

أنا لست ملتزمًا بشكل كبير بالبث لأن استخدامي لا يجب أن يتجاوز 16 كيلو بايت ، لكن المخازن المؤقتة المجزأة ستكون لطيفة ويجب ألا تشكل أي خطر على الإطلاق (أظن في الواقع أن cng جعلت واجهتها بالطريقة التي هي عليها لهذا الغرض بالضبط) ... على سبيل المثال ، أريد أن أكون قادرًا على تمرير عدد من الامتدادات أو ما شابه (قائمة مرتبطة على سبيل المثال) وفك تشفيرها دفعة واحدة. إذا تم فك تشفيره إلى مخزن مؤقت قريب فلا بأس بذلك.

لذلك أعتقد أن نقل لوحة التشفير الغامضة على واجهة برمجة التطبيقات "نمط البث" أمر غير مقبول في الوقت الحالي ، لذا دعنا نتحرك إلى الأمام في إنشاء واجهة برمجة تطبيقات ذات طلقة واحدة. هناك دائمًا مجال لتوسيع API إذا أظهر عدد كافٍ من الأشخاص الحاجة لاحقًا

sdrapkin النقطة هي أنها واجهة برمجة التطبيقات المتدفقة التي خضعت لمراجعة شاملة من قبل NIST Labs و MSFT. تتراوح تكلفة كل بناء يتم التحقق منه ما بين 80،000 دولار - 50،000 دولار ، وقد استثمرت MSFT (و OpenSSL و Oracle وغيرها من الشركات المشفرة ذات الوزن الثقيل) HEAVILY في الحصول على واجهة برمجة التطبيقات هذه والتطبيقات التي تم التحقق من صحتها لأكثر من 10 سنوات. دعنا لا نتشتت انتباهك بأحجام النص العادي المحددة لخطة الاختبار لأنني واثق من أن .NET ستدعم أحجامًا بخلاف 0 و 8 و 1016 و 1024 بغض النظر عن البث أو اللقطة الواحدة. النقطة المهمة هي أن كل واجهات برمجة التطبيقات (API) التي تم اختبارها في المعركة (حرفيًا ؛ على أنظمة دعم الأسلحة) ، تدعم جميع هذه المنصات تدفق AEAD على مستوى واجهة برمجة تطبيقات التشفير البدائية. لسوء الحظ ، كانت كل حجة حتى الآن ضدها عبارة عن قلق على مستوى التطبيق أو البروتوكول تم الاستشهاد به على أنه قلق زائف على المستوى البدائي للعملات المشفرة.

أنا جميعًا مع "دع أفضل فكرة تفوز" ولكن ما لم يكن لدى فريق التشفير الأساسي. وهم على حق.

ملاحظة: أعلم أننا في خلاف هنا ولكننا جميعًا نريد الأفضل للمنصة وعملائها.

Drawaes ما لم تكن واجهة AEAD (وليس بالضرورة التنفيذ) التي تم تحديدها اليوم تدعم سطح واجهة برمجة التطبيقات المتدفقة ، لا أرى كيف يمكن للأشخاص توسيعها دون وجود واجهتين أو واجهات مخصصة. . قد يكون ذلك كارثة آمل أن تؤدي هذه المناقشة إلى واجهة تكون برهانًا مستقبليًا (أو على الأقل تعكس واجهات AEAD الأخرى التي كانت موجودة منذ سنوات عديدة!).

أنا أميل إلى الاتفاق. لكن هذه المشكلة لا تسير في أي مكان بسرعة وعندما يحدث ذلك ، فمن المحتمل أن نصل إلى نقطة حرجة إما أنها لن تصل إلى 2.1 أو سيتعين عليك التغلب عليها دون ترك الوقت لحل المشكلات. سأكون صريحًا ، لقد عدت إلى أغلفة الأغلفة القديمة الخاصة بي وأنا فقط أقوم بتجديدها من أجل 2.0 ؛)

لدينا عدد قليل من واجهات برمجة التطبيقات المرجعية لـ Java أو OpenSSL أو C # Bouncy Castle أو CLR Security . بصراحة ، فإن أيًا منهم سيفعل ذلك وعلى المدى الطويل ، أتمنى أن يكون لدى C # شيء مثل Java Cryptography Architecture حيث تكون جميع تطبيقات التشفير مقابل واجهة راسخة تسمح للمرء بتبديل مكتبات التشفير دون التأثير على رمز المستخدم.

بالعودة إلى هنا ، أعتقد أنه من الأفضل توسيع واجهة .NET Core's ICryptoTransform كـ

public interface IAuthenticatedCryptoTransform : ICryptoTransform 
{
    bool CanChainBlocks { get; }
    byte[] GetTag();
    void SetExpectedTag(byte[] tag);
}

إذا كنا Span إذا كنا نتعامل مع كل byte[] s ، فيجب أن يتخلل ذلك واجهة برمجة التطبيقات بالكامل في مساحة الاسم System.Security.Cryptography أجل التناسق الكلي.

تحرير: روابط JCA الثابتة

إذا كنا نمتد جميع البايتات ، فيجب أن يتخلل ذلك واجهة برمجة التطبيقات بالكامل في مساحة الاسم System.Security.Cryptography من أجل الاتساق الكلي.

لقد فعلنا ذلك بالفعل. كل شيء ما عدا ICryptoTransform ، لأننا لا نستطيع تغيير الواجهات.

أعتقد أنه من الأفضل أن نوسع تحويل ICryptoTransform الخاص بـ .NET Core ...

المشكلة في هذا هو أن نمط الاستدعاء محرج للغاية مع إخراج العلامة في النهاية (خاصة إذا كان CryptoStream متضمنًا). لقد كتبت هذا في الأصل ، وكان قبيحًا. هناك أيضًا مشكلة في كيفية الحصول على أحد هذه ، نظرًا لأن معلمات GCM تختلف عن معلمات CBC / ECB.

حتى هنا هي أفكاري.

  • يعد تدفق فك التشفير أمرًا خطيرًا على AE.
  • بشكل عام ، أنا معجب بـ "أعطني العنصر البدائي ، ودعني أدير مخاطري"
  • أنا أيضًا معجب بـ "يجب ألا يسمح .NET (بسهولة) بأشياء غير آمنة تمامًا ، لأن هذا بعضًا من قيمته المقترحة"
  • إذا كانت مخاطر القيام بفك تشفير GCM بشكل سيئ ، كما أساء فهمها في الأصل ، هي استرداد مفتاح الإدخال ، فسأظل في "هذا غير آمن للغاية". (قد يكون الاختلاف بين .NET وكل شيء آخر هو "أنه استغرق وقتًا أطول للقيام بذلك ، وتعلم العالم أكثر")
  • ولكن ، نظرًا لأن الأمر ليس كذلك ، إذا كنت تريد حقًا أن تنطلق عجلات التدريب ، فأعتقد أنني سأستمتع بهذه الفكرة.

أفكاري الخام إلى حد ما لتحقيق هذه الغاية (إضافة إلى الاقتراحات الحالية ، لذلك تظل اللقطة الواحدة ، على الرغم من أنني أعتقد أنها ضمنية افتراضية افتراضية بدلاً من الملخص):

ج #
فئة جزئية AuthenticatedEncryptor
{
// رميات إذا كانت العملية قيد التقدم بالفعل
تهيئة الفراغ الملخص العام (ReadOnlySpanالبيانات المرتبطة) ؛
// صحيح عند النجاح ، خطأ في "الوجهة صغيرة جدًا" ، استثناء في أي شيء آخر.
منطقية الملخص العام TryEncrypt (ReadOnlySpanالبيانات ، سبانencryptedData ، خارج int bytesRead ، out int bytesWritten) ؛
// false إذا كانت قيمة المتبقية المتبقية
// يمكن نقل NonceOrIvUsed إلى Initialize ، ولكن بعد ذلك قد يتم تفسيره على أنه إدخال.
منطقية الملخص العام TryFinish (ReadOnlySpanالمتبقية البيانات ، سبانبقيت تشفير البيانات ، خارج بايت عدد صحيح مكتوب ، سبانعلامة ، سبانnonceOrIvUsed) ؛
}

فئة جزئية AuthenticatedDecryptor
{
// رميات إذا كانت العملية قيد التقدم بالفعل
تهيئة الفراغ الملخص العام (ReadOnlySpanعلامة ، ReadOnlySpannonceOrIv و ReadOnlySpanالبيانات المرتبطة) ؛
// صحيح عند النجاح ، خطأ في "الوجهة صغيرة جدًا" ، استثناء في أي شيء آخر.
منطقية الملخص العام TryDecrypt (ReadOnlySpanالبيانات ، سبانdecryptedData، out int bytesRead، out int bytesWritten) ؛
// يلقي بعلامة سيئة ، لكنه قد يؤدي إلى تسريب البيانات على أي حال.
// (
منطقية الملخص العام TryFinish (ReadOnlySpanالمتبقية البيانات ، سبانتبقىDecryptedData ، خارج int bytesWritten) ؛
}
""

تأتي AssociatedData عند Initialize ، لأن الخوارزميات التي تحتاجها في النهاية يمكنها التمسك بها ، ولا يمكن للخوارزميات التي تحتاجها أولاً أن تحصل عليها بأي طريقة أخرى.

بمجرد تحديد الشكل الذي سيبدو عليه البث (وما إذا كان الناس يعتقدون أن CCM يجب أن تقوم بالتخزين المؤقت داخليًا ، أو يجب أن ترمي ، عندما تكون في وضع تشفير البث) ، فسأعود إلى اللوحة.

bartonjs أعلم ما تقصده بشأن نتف العلامة وبرمجتها من نهاية الدفق من أجل التناظر عبر التشفير / فك التشفير. إنه أمر صعب ولكنه أسوأ إذا تُرك حله لكل مستخدم. لدي تطبيق يمكنني مشاركته تحت MIT ؛ سأحتاج إلى البحث داخليًا مع فريقي (ليس على مكتبي / هاتفي المحمول)

يمكن أن يكون الحل الوسطي مثل OpenSSL أو NT's bcrypt حيث تحتاج إلى توصيل العلامة مباشرة قبل استدعاء فك التشفير النهائي حيث يحدث ذلك عندما تحدث مقارنات العلامات. مثال: SetExpectedTag (قبل فك التشفير النهائي) و GetTag (بعد التشفير النهائي) ستعمل لكن تفريغ إدارة العلامات للمستخدم. سيقوم معظمهم ببساطة بإلحاق العلامة بمجرى التشفير نظرًا لأنه الترتيب الزمني الطبيعي.

أعتقد أن توقع العلامة في Initialize نفسها (في فك التشفير) يكسر التماثل في الفضاء (تدفق البايت) والوقت (التحقق من العلامة في النهاية ، وليس البداية) مما يحد من فائدتها. لكن واجهات برمجة التطبيقات الوسم المذكورة أعلاه تحل ذلك.

أيضًا للتشفير ، يحتاج Initialize إلى IV قبل أي تحويلات تشفير.

أخيرًا ، للتشفير وفك التشفير ، يحتاج Initialize إلى مفاتيح تشفير AES قبل أي تحويلات. (أفتقد شيئًا واضحًا أو نسيت كتابة هذا الجزء؟)

أعتقد أن توقع العلامة في Initialize نفسها (في فك التشفير) يكسر التناظر

في CBC + HMAC ، التوصية المعتادة هي التحقق من HMAC قبل البدء في أي فك تشفير ، لذلك فهي خوارزمية فك تشفير العلامة أولاً. وبالمثل ، يمكن أن تكون هناك خوارزمية "AE خالصة" تقوم بعمليات مدمرة على العلامة أثناء العمليات الحسابية وتتحقق فقط من أن الإجابة النهائية كانت 0. لذلك ، مثل قيمة البيانات المرتبطة ، حيث يمكن أن تكون هناك خوارزميات تحتاجها أولاً ، لتأتي أولاً في واجهة برمجة التطبيقات المعممة بالكامل.

يؤدي تحريكهم إلى SetAssociatedData و SetTag إلى مشكلة أنه بينما كانت الفئة الأساسية مستقلة عن الخوارزمية ، يصبح الاستخدام معتمدًا على الخوارزمية. سيؤدي تغيير AesGcm إلى AesCbcHmacSha256 أو SomeTagDesctructiveAlgorithm الآن إلى طرح TryDecrypt لأن العلامة لم يتم توفيرها بعد. بالنسبة لي ، هذا أسوأ من عدم تعدد الأشكال على الإطلاق ، لذا فإن السماح بالمرونة يقترح تقسيم النموذج بعيدًا عن بعضها البعض بشكل كامل لكل خوارزمية. (نعم ، يمكن التحكم فيه من خلال المزيد من الخصائص المميزة لتعريف الخوارزمية مثل NeedsTagFirst ، لكن هذا يؤدي حقًا إلى صعوبة استخدامه)

أيضًا للتشفير ، يحتاج التهيئة إلى IV قبل أي تحويلات تشفير.

أخيرًا ، للتشفير وفك التشفير ، يحتاج التهيئة إلى مفاتيح تشفير AES قبل أي تحويلات.

كان المفتاح عبارة عن معلمة فئة ctor. يأتي IV / nonce من مزود IV / nonce في معامل ctor.

يحل نموذج الموفر SIV ، حيث لا يتم إعطاء IV أثناء التشفير ، يتم إنشاء واحد نيابة عن البيانات. بخلاف ذلك ، يحتوي SIV على المعلمة ويتطلب تقديم قيمة فارغة.

أو نسيت أن تكتب هذا الشيء؟

تمت إضافة طرق التدفق إلى اقتراحي الحالي ، والذي كان يحتوي بالفعل على المفتاح الرئيسي وموفر IV / nonce كمعلمات ctor.

bartonjs : نقطة جيدة أن بعض الطوائف قد ترغب في وضع علامة أولاً بينما البعض الآخر في النهاية وشكرًا للتذكير بأنه إضافة إلى المواصفات الأصلية. لقد اكتشفت أن التفكير في حالة استخدام يسهل الأمر ، لذا إليك مثال على السحابة أولاً:

سنقوم بإجراء تحليلات على واحد أو أكثر من الملفات المشفرة AES-GCM بسعة 10 جيجابايت (أي العلامات بعد النص المشفر) المحفوظة في التخزين. يقوم عامل التحليلات في نفس الوقت بفك تشفير العديد من التدفقات الواردة إلى جهاز / مجموعات منفصلة وبعد عمليات التحقق من البايت + العلامة الأخيرة ، يبدأ كل عبء عمل تحليل. جميع أجهزة التخزين والعامل والتحليلات الافتراضية موجودة في Azure US-West.

هنا ، لا توجد طريقة لجلب العلامة في نهاية كل دفق وتقديمها إلى طريقة AuthenticatedDecryptor Initialize . لذلك حتى إذا تطوع المستخدم لتعديل الكود لاستخدام GCM ، فلا يمكنهم حتى البدء في استخدام API.

إذا فكرت في الأمر ، فإن الطريقة الوحيدة التي يمكننا من خلالها الحصول على واجهة برمجة تطبيقات تستوعب العديد من AEAD ولا توجد تغييرات في كود المستخدم ، هي إذا كان موفرو التشفير لخوارزميات AEAD المختلفة يتعاملون تلقائيًا مع العلامات. تقوم Java بذلك عن طريق وضع العلامات في نهاية النص المشفر لـ GCM وإخراجها أثناء فك التشفير دون تدخل المستخدم. بخلاف ذلك ، في أي وقت يغير فيه شخص ما الخوارزمية بشكل كبير (على سبيل المثال CBC-HMAC => GCM) ، سيتعين عليه تعديل الكود الخاص به بسبب الطبيعة الحصرية المتبادلة للمعالجة الأولى والعلامة الأخيرة.

IMHO ، يجب أن نقرر أولاً ما إذا كان

الخيار 1) يتعامل موفرو الخوارزمية داخليًا مع إدارة العلامات (مثل Java)

أو

الخيار 2) كشف ما يكفي عن واجهة برمجة التطبيقات للمستخدمين للقيام بذلك بأنفسهم (مثل WinNT bcrypt أو opensl)

الخيار 1 من شأنه أن يبسط التجربة الكلية لمستهلكي المكتبات لأن إدارة المخزن المؤقت يمكن أن تصبح معقدة. قم بحلها جيدًا في المكتبة ولن يضطر كل مستخدم إلى حلها في كل مرة الآن. بالإضافة إلى أن جميع AEADs تحصل على نفس الواجهة (علامة أولاً ، علامة أخيرة ، علامة أقل) كما أن تبديل الخوارزميات أسهل أيضًا.

سيكون تصويتي للخيار 1.

أخيرًا ، تمكنا من البحث عن تطبيقنا الذي سمح لعمليات الدفق ICryptoTransform عبر GCM بإخراج العلامة في مصدر البث تلقائيًا. كان هذا تحديثًا مهمًا للغلاف الخاص بـ CLR Security ، وعلى الرغم من نسخ المخزن المؤقت الإضافية ، فإنه لا يزال سريعًا حقًا (حوالي 4 جيجابايت / ثانية في اختبار macbook pro الخاص بنا في Windows 10 bootcamp). لقد لفنا بشكل أساسي حول CLR Security لإنشاء الخيار 1 لأنفسنا حتى لا نحتاج إلى القيام بذلك في أي مكان آخر. يساعد هذا المرئي حقًا في شرح ما يحدث داخل واجهة TransformBlock و TransformFinalBlock من الواجهة ICryptoTransform .

sidshetye لست متأكدًا من سبب حظر مثال السحابة الأول الخاص بك. إذا كنت تقرأ من وحدة التخزين ، فيمكنك تنزيل آخر عدد من وحدات بايت الوسم أولاً وتقديمها إلى برنامج فك التشفير. إذا كنت تستخدم واجهات برمجة تطبيقات تخزين Azure ، فسيتم تحقيق ذلك عبر CloudBlockBlob.DownloadRangeXxx .

GrabYourPitchforks لا تنحرف كثيرًا في هذا المثال ولكن هذه قدرة محددة لتخزين Azure Blob. بشكل عام ، عادةً ما تحصل أحمال التخزين المستندة إلى VM (IaaS) أو التخزين غير Azure Storage على دفق شبكة لا يمكن البحث عنه.

أنا شخصيًا متحمس جدًا لرؤية GrabYourPitchforks - رائع!

سنقوم بإجراء تحليلات على واحد أو أكثر من الملفات المشفرة AES-GCM بسعة 10 جيجابايت (أي العلامات بعد النص المشفر) المحفوظة في التخزين. يقوم عامل التحليلات في نفس الوقت بفك تشفير العديد من التدفقات الواردة إلى جهاز / مجموعات منفصلة وبعد عمليات التحقق من البايت + العلامة الأخيرة ، يبدأ كل عبء عمل تحليل. جميع أجهزة التخزين والعامل والتحليلات الافتراضية موجودة في Azure US-West.

sidshetye ، لقد كنت شديد الإصرار على الفصل بين الأوليات الغبية والخطيرة والبروتوكولات الذكية القابلة للاحتضان! كان لدي حلم - وقد صدقته. ثم ترمي هذا علينا. هذا بروتوكول - تصميم نظام. كل من صمم هذا البروتوكول الذي وصفته - أفسد. لا جدوى من البكاء على عدم القدرة على وضع وتد مربع في حفرة مستديرة الآن.

مهما كانت ملفات 10 جيجا بايت المشفرة بواسطة GCM لا تعيش فقط بشكل خطير بالقرب من الحافة البدائية (GCM ليس جيدًا بعد 64 جيجا بايت) ، ولكن كان هناك أيضًا تأكيد ضمني على أن النص المشفر بأكمله يجب تخزينه مؤقتًا.

كل من يقوم بتشفير ملفات 10 جيجا بايت بواسطة GCM يرتكب خطأ بروتوكول باحتمالية هائلة. الحل: التشفير المقسم. يحتوي TLS على تقطيع متغير الطول 16 كيلو بايت ، وهناك نكهات أخرى أبسط خالية من PKI. إن الجاذبية الجنسية "السحابية أولاً" لهذا المثال الافتراضي لا تقلل من أخطاء التصميم.

(لدي الكثير من اللحاق بالركب في هذا الموضوع.)

أثارsdrapkin نقطة حول إعادة استخدام واجهة IAuthenticatedEncryptor من طبقة حماية البيانات. لأكون صريحًا ، لا أعتقد أن هذا هو التجريد الصحيح للبدائية ، لأن طبقة حماية البيانات لها رأي كبير في كيفية أدائها للتشفير. على سبيل المثال ، يحظر الاختيار الذاتي لـ IV أو nonce ، ويفرض أن يفهم التنفيذ المطابق مفهوم AAD ، وينتج نتيجة مملوكة إلى حد ما. في حالة AES-GCM ، فإن القيمة المعادة من IAuthenticatedEncryptor.Encrypt هي عبارة عن تسلسل لشيء غريب تقريبًا يستخدم لاشتقاق المفتاح الفرعي ، وهو النص المشفر الناتج عن تشغيل AES-GCM على النص الصريح المقدم (ولكن ليس AAD!) وعلامة AES-GCM. لذا ، في حين أن كل خطوة يتم تضمينها في إنشاء الحمولة المحمية تكون آمنة ، فإن الحمولة نفسها لا تتبع أي نوع من الاصطلاحات المقبولة ، ولن تجد أي شخص بخلاف مكتبة حماية البيانات يمكنه فك تشفير النص المشفر الناتج بنجاح. وهذا يجعلها مرشحًا جيدًا لمكتبة تواجه مطوري التطبيقات ، ولكنها مرشح مروع للواجهة التي يتم تنفيذها بواسطة الأساسيات.

يجب أن أقول أيضًا أنني لا أرى قيمة كبيرة في وجود واجهة واحدة حقيقية (tm) IAuthenticatedEncryptionAlgorithm التي من المفترض أن تنفذها جميع خوارزميات التشفير المصادق عليها. تعتبر هذه العناصر الأولية "معقدة" ، على عكس العناصر الأولية للتشفير البسيط أو عناصر التجزئة الأولية. هناك ببساطة الكثير من المتغيرات في هذه البدائل المعقدة. هل AE البدائي فقط ، أم هو AEAD؟ هل تقبل الخوارزمية IV / nonce على الإطلاق؟ (لقد رأيت البعض لا.) هل هناك أي مخاوف بشأن كيفية هيكلة المدخلات IV / nonce أو البيانات؟ يجب أن تكون العناصر الأولية المعقدة IMO ببساطة عبارة عن واجهات برمجة تطبيقات مستقلة ، والمكتبات عالية المستوى ستعمل على دعم الأساسيات المعقدة المحددة التي تهتم بها. ثم تعرض المكتبة عالية المستوى أي واجهة برمجة تطبيقات موحدة تعتقد أنها مناسبة لسيناريوهاتها.

sdrapkin سنخرج عن الموضوع مرة أخرى. سأقول فقط أن النظام مبني باستخدام الأوليات. بدائل التشفير هنا عارية وقوية. بينما عالجت طبقة النظام / البروتوكول التخزين المؤقت ؛ هذا أيضًا على مستوى الكتلة ، وبالتأكيد ليس في ذاكرة النظام الرئيسية التي ستفرضها الطلقات الأولية. حدود "التقسيم" هي X (X = 10 غيغابايت هنا) لأن <64 غيغابايت ، لأن سعة التخزين المؤقت للمجموعة كانت بلا حدود تقريبًا ولن يبدأ أي شيء حتى يتم تحميل البايت الأخير في المجموعة. هذا هو بالضبط الفصل بين الاهتمامات ، وتحسين كل طبقة لنقاط القوة التي كنت أتحدث عنها. ويمكن أن يحدث هذا فقط إذا لم تعيق الأساسيات الأساسية تصميمات / قيود الطبقة العليا (لاحظ أن المزيد من تطبيقات العالم الحقيقي تأتي مع عوائقها القديمة).

ينص NIST 800-38d sec9.1 على ما يلي:

من أجل منع طرف غير مصرح له من السيطرة أو التأثير على توليد IVs ،
يتم تنفيذ GCM فقط داخل وحدة تشفير تفي بمتطلبات
حانة FIPS. 140-2. على وجه الخصوص ، يجب أن تحتوي حدود التشفير للوحدة النمطية على ملف
"وحدة التوليد" التي تنتج IVs وفقًا لإحدى الإنشاءات في الثانية. 8.2 أعلاه.
يجب توثيق الوحدة للتحقق من صحتها مقابل متطلبات FIPS 140-2
صف كيف تتوافق الوحدة مع متطلبات التفرد في IV.

هذا يعني لي أن GCM IVs يجب أن يتم إنشاؤها تلقائيًا داخليًا (ولا يتم تمريرها خارجيًا).

sdrapkin نقطة جيدة ولكن إذا قرأت عن قرب ، سترى أنه بالنسبة لأطوال IV البالغة 96 بت وما فوق ، يسمح القسم 8.2.2 بتوليد IV بمولد بت عشوائي (RBG) حيث تكون 96 بت على الأقل عشوائية (أنت يمكن فقط 0 بتات أخرى). لقد ذكرت هذا الشهر الماضي في هذا الموضوع نفسه ( هنا تحت عنوان nonce).

LT ؛ DR: INonce هو فخ يؤدي إلى عدم الامتثال لإرشادات NIST و FIPS.

يقول القسم 9.1 ببساطة ، بالنسبة إلى FIPS 140-2 ، يجب أن تقع وحدة التوليد IV (عشوائية بالكامل ، أي القسم 8.2.2 أو التنفيذ الحتمي ، أي القسم 8.2.1) ضمن حدود الوحدة التي تخضع للتحقق من FIPS. حيث ...

  1. RBGs تم التحقق من صحتها بالفعل FIPS
  2. يوصى باستخدام عدسة IV> = 96
  3. تصميم وحدة الجيل الرابع التي تستمر في إعادة التشغيل ، من الصعب فقدان الطاقة إلى أجل غير مسمى في طبقة تشفير بدائية
  4. الحصول على 3 أعلاه يتم تنفيذه داخل مكتبة التشفير والحصول على الشهادة أمر صعب ومكلف (50 ألف دولار لأي شيء ينتج عنه صورة بنية غير دقيقة بت)
  5. لن يقوم أي رمز مستخدم مطلقًا بتنفيذ 3 والحصول على شهادة بسبب 4 أعلاه. (دعنا نترك جانبا بعض المنشآت العسكرية / الحكومية الغريبة).

... تستخدم معظم مكتبات التشفير (راجع Oracle's Java و WinNT's bcryptprimitives و OpenSSL وما إلى ذلك) التي تخضع لشهادة FIPS مسار RBG لـ IV وتستغرق ببساطة مجموعة بايت للإدخال. لاحظ أن وجود واجهة INonce هو في الواقع اعتراض من منظور NIST و FIPS لأنه يشير ضمنيًا إلى أنه يجب على المستخدم تمرير تنفيذ تلك الواجهة إلى وظيفة التشفير. لكن أي تطبيق مستخدم لـ INonce يكاد يكون مضمونًا أنه لم يخضع لعملية شهادة 9 أشهر + و 50 ألف دولار + NIST. ومع ذلك ، إذا أرسلوا للتو مصفوفة بايت باستخدام بنية RGB (موجودة بالفعل في مكتبة التشفير) ، فستكون متوافقة تمامًا مع الإرشادات.

لقد قلت من قبل - طورت مكتبات التشفير الحالية سطح API الخاص بها وتم اختبارها عبر سيناريوهات متعددة. أكثر مما تطرقنا إليه في هذا الموضوع الطويل. تصويتي مرة أخرى هو الاستفادة من تلك المعرفة والخبرة عبر جميع تلك المكتبات ، وكل تلك المصادقة وكل تلك التركيبات بدلاً من محاولة إعادة اختراع العجلة. لا تعيد اختراع العجلة. استخدمه لاختراع الصاروخ :)

مرحبا يا رفاق،

أي تحديثات على هذا؟ لم أر أي تحديثات في خارطة طريق التشفير karelz أو على مؤشر ترابط AES GCM .

شكرا
سيد

لذا فإن آخر عرض ملموس هو من https://github.com/dotnet/corefx/issues/23629#issuecomment -334328439:

partial class AuthenticatedEncryptor
{
    // throws if an operation is already in progress
    public abstract void Initialize(ReadOnlySpan<byte> associatedData);
    // true on success, false on “destination too small”, exception on anything else.
    public abstract bool TryEncrypt(ReadOnlySpan<byte> data, Span<byte> encryptedData, out int bytesRead, out int bytesWritten);
    // false if remainingEncryptedData is too small, throws if other inputs are too small, see NonceOrIVSizeInBits and TagSizeInBits properties.
    // NonceOrIvUsed could move to Initialize, but then it might be interpreted as an input.
    public abstract bool TryFinish(ReadOnlySpan<byte> remainingData, Span<byte> remainingEncryptedData, out int bytesWritten, Span<byte> tag, Span<byte> nonceOrIvUsed);
}

partial class AuthenticatedDecryptor 
{
    // throws if an operation is already in progress
    public abstract void Initialize(ReadOnlySpan<byte> tag, ReadOnlySpan<byte> nonceOrIv, ReadOnlySpan<byte> associatedData);
    // true on success, false on “destination too small”, exception on anything else.
    public abstract bool TryDecrypt(ReadOnlySpan<byte> data, Span<byte> decryptedData, out int bytesRead, out int bytesWritten);
    // throws on bad tag, but might leak the data anyways.
    // (remainingDecryptedData is required for CBC+HMAC, and so may as well add remainingData, I guess?)
    public abstract bool TryFinish(ReadOnlySpan<byte> remainingData, Span<byte> remainingDecryptedData, out int bytesWritten);
}

تم طرح عدد قليل فقط من القضايا المحتملة منذ ذلك الحين:

  • العلامة مطلوبة مقدمًا ، مما يعيق بعض السيناريوهات. إما أن تصبح واجهة برمجة التطبيقات أكثر تعقيدًا بشكل ملحوظ للسماح بمزيد من المرونة ، أو يجب اعتبار هذه المشكلة مشكلة بروتوكول (أي عالية المستوى).
  • قد يكون INonceProvider معقدًا بلا داع و / أو يؤدي إلى عدم الامتثال لإرشادات NIST و FIPS.
  • قد يكون التجريد المقصود من بدائل التشفير المصدق بمثابة حلم بعيد المنال ، حيث قد تكون الاختلافات كبيرة جدًا. لم يكن هناك أي مناقشة أخرى لهذا الاقتراح.

أود أن أقترح ما يلي:

  1. يبدو التعقيد الإضافي المتمثل في عدم طلب العلامة مقدمًا شديدًا ، ويبدو سيناريو المشكلة المقابل غير شائع ، ويبدو أن المشكلة تشبه إلى حد كبير مسألة بروتوكول. يمكن أن يستوعب التصميم الجيد الكثير ، ولكن ليس كل شيء. أنا شخصياً أشعر بالراحة عند ترك هذا الأمر للبروتوكول. (ترحب الأمثلة المضادة القوية.)
  2. انتقلت المناقشة باستمرار نحو تنفيذ مرن ومنخفض المستوى لا يحمي من سوء الاستخدام ، باستثناء الجيل الرابع . لنكن متسقين. يبدو أن الإجماع العام هو أن واجهة برمجة التطبيقات عالية المستوى هي خطوة تالية مهمة وحيوية للاستخدام السليم من قبل غالبية المطورين - هذه هي الطريقة التي نفلت بها من عدم الحماية من سوء الاستخدام في واجهة برمجة التطبيقات منخفضة المستوى . ولكن يبدو أن جرعة إضافية من الخوف قد أدت إلى استمرار فكرة منع إساءة الاستخدام في مجال الجيل الرابع. في سياق واجهة برمجة التطبيقات منخفضة المستوى ، ولكي أكون متسقًا ، أميل إلى ما يعادل byte[] . لكن تبديل التنفيذ يكون أكثر سلاسة مع حقنة INonceProvider . هل تعليق sidshetye غير قابل للدحض ، أم أن التضمين INonceProvider البسيط الذي يستدعي RNG فقط لا يزال يعتبر متوافقًا؟
  3. تبدو الأفكار المجردة مفيدة ، وقد تم بذل الكثير من الجهد لتصميمها ، وأنا مقتنع الآن أنها ستفيد أكثر من الضرر. إلى جانب ذلك ، لا يزال بإمكان واجهات برمجة التطبيقات عالية المستوى اختيار تنفيذ واجهات برمجة التطبيقات منخفضة المستوى التي لا تتوافق مع التجريدات منخفضة المستوى.
  4. IV هو المصطلح العام ، و nonce هو نوع محدد من IV ، أليس كذلك؟ هذا يتطلب إعادة تسمية من INonceProvider إلى IIVProvider ، ومن nonceOrIv* إلى iv* . بعد كل شيء ، نحن نتعامل دائمًا مع IV ، ولكن ليس بالضرورة مع nonce.

العلامة المقدمة ليست بداية للسيناريو الخاص بي ، لذا من المحتمل أن أحتفظ بالتنفيذ الخاص بي. وهو أمر جيد ، لست متأكدًا من أن كل شخص لديه كوب شاي لكتابة كود أداء عالٍ في هذا المجال.

المشكلة هي أنه سيؤدي إلى زمن انتقال غير ضروري. يجب عليك تخزين رسالة بأكملها مؤقتًا مسبقًا للحصول على العلامة في النهاية لبدء فك تشفير الإطار. هذا يعني أنه لا يمكنك في الأساس تداخل الإدخال / الإخراج وفك التشفير.

لست متأكدًا من سبب صعوبة السماح بذلك في النهاية. لكنني لن أخرج من طريق مسدود لواجهة برمجة التطبيقات هذه ، فلن يكون هناك أي اهتمام في السيناريو الخاص بي.

IV هو المصطلح العام ، و nonce هو نوع محدد من IV ، أليس كذلك؟

لا ، رقم A nonce هو رقم تم استخدامه مرة واحدة . تشير الخوارزمية التي تحدد nonce إلى أن إعادة الاستخدام تنتهك ضمانات الخوارزمية. في حالة GCM ، يمكن أن يؤدي استخدام نفس المفتاح مع نفس المفتاح ورسالة مختلفة إلى اختراق مفتاح GHASH ، مما يقلل من GCM إلى نسبة النقر إلى الظهور.

من http://nvlpubs.nist.gov/nistpubs/ir/2013/NIST.IR.7298r2.pdf :

Nonce: قيمة مستخدمة في بروتوكولات الأمان لا تتكرر أبدًا مع نفس المفتاح. على سبيل المثال ، لا يجب تكرار nonces المستخدمة كتحديات في بروتوكولات مصادقة استجابة التحدي بشكل عام حتى يتم تغيير مفاتيح المصادقة. خلاف ذلك ، هناك احتمال حدوث هجوم إعادة. يعد استخدام nonce كتحدي متطلبًا مختلفًا عن التحدي العشوائي ، لأن الرقم nonce ليس بالضرورة غير متوقع.

لا يحتوي "الرابع" على نفس المتطلبات الصارمة. على سبيل المثال ، يؤدي تكرار IV مع CBC فقط إلى تسريب ما إذا كانت الرسالة المشفرة هي نفسها أو مختلفة عن الرسالة السابقة مع نفس IV. لا يضعف الخوارزمية.

nonce هو رقم يستخدم مرة واحدة.
لا يحتوي "الرابع" على نفس المتطلبات الصارمة.

bartonjs نعم. أعتقد أنه نظرًا لاستخدام nonce لتهيئة التشفير البدائي ، فهو ناقل التهيئة الخاص به. إنه يلتزم تمامًا بأي تعريف لـ IV يمكنني العثور عليه. لديها متطلبات أكثر صرامة ، نعم ، تمامًا كما أن البقرة تتطلب متطلبات أكثر صرامة من كونها حيوانًا. يبدو أن الصياغة الحالية تطلب معلمة "cowOrAnimal". حقيقة أن الأنماط المختلفة لها متطلبات مختلفة من IV لا يغير حقيقة أنهم جميعًا يطلبون شكلاً من أشكال IV. إذا كان هناك شيء مفقود ، احتفظ بكل الوسائل بالصياغة الحالية ، ولكن بقدر ما أستطيع أن أقول ، فقط "iv" أو "IIVProvider" كلاهما بسيط وصحيح.

لتنغمس في حفل زفاف دراجات nonceOrIv :

يتم تعريف 96bit GCM IV أحيانًا على أنها 4 بايت salt و 8 بايت nonce (مثل RFC 5288). يعرّف RFC 4106 GCM nonce على أنه 4 بايت salt و 8 بايت iv . يقول RFC 5084 (GCM in CMS) أن CCM يأخذ nonce ، GCM يأخذ iv ، لكن _ "... للحصول على مجموعة مشتركة من المصطلحات لـ AES-CCM و AES-GCM ، يشار إلى AES-GCM IV على أنه nonce في بقية هذا المستند. "_ RFC 5647 (GCM لـ SSH) يقول _" ملاحظة: في [RFC5116] ، يسمى IV بـ nonce. _ RFC 4543 ( GCM في IPSec) يقول _ "نشير إلى إدخال AES-GMAC IV على أنه nonce ، من أجل تمييزه عن الحقول IV في الحزم." _ RFC 7714 (GCM for SRTP) يتحدث عن 12 بايت IV ويحافظ تقريبًا على تناسقه ، ولكنه يقول بعد ذلك "_ الحد الأدنى والأقصى للطول nonce (IV): يجب أن يكون 12 ثماني بتات." _

نظرًا للنقص الكامل في الاتساق في معظم مواصفات GCM ، فإن nonceOrIv كيندا أمر منطقي. 0.02 دولار

العلامة مقدمًا ليست بداية

مثل العملاء الآخرين الذين يعبرون عن أنفسهم هنا ، فإن طلب العلامة مقدمًا ليس بداية بالنسبة لنا أيضًا. لا توجد طريقة يمكن لـ .NET بعد ذلك معالجة التدفقات المتزامنة مع هذا القيد المقدم بشكل مصطنع. يقتل قابلية التوسع تمامًا.

هل يمكنك دعم التأكيد على أنه يضيف تعقيدًا؟ لأنه يجب أن يكون تافهًا في الواقع. بالإضافة إلى عدم وجود هذا القيد في تطبيقات التشفير الخاصة بالنظام الأساسي (التي ستقوم بتغليفها). على وجه التحديد ، السبب هو أن علامة الإدخال يجب أن تكون مجرد وقت ثابت مقارنة بالعلامة المحسوبة. والعلامة المحسوبة متاحة فقط بعد فك تشفير الكتلة النهائية خلال TryFinish . لذلك بشكل أساسي ، عند بدء التنفيذ ، ستجد أنك تقوم فقط بتخزين tag داخل المثيل الخاص بك حتى TryFinish . يمكنك الحصول عليه كمدخل اختياري

public abstract bool TryFinish(ReadOnlySpan<byte> remainingData, 
                             Span<byte> remainingDecryptedData, 
                             out int bytesWritten, 
                             ReadOnlySpan<byte> tag = null); // <==

أعتقد أيضًا أننا نحاول جاهدين التطبيع مع واجهة واحدة تغطي جميع سيناريوهات التشفير. أنا أيضًا أفضل الواجهات المعممة ، ولكن ليس على حساب الوظيفة أو قابلية التوسع - خاصةً في مثل هذه الطبقة التأسيسية مثل مكتبة cryto القياسية للغة نفسها. IMHO ، إذا وجد المرء نفسه يفعل ذلك ، فهذا يعني عادة أن التجريد معيب.

إذا كانت هناك حاجة إلى واجهة بسيطة متسقة ، فأنا أفضل نهج Java - الذي تم طرحه سابقًا هنا كخيار 1 . كما أنه يتجنب المشكلة المذكورة أعلاه الخاصة بالعلامة الأولى / العلامة الأخيرة عن طريق إبقائها ضمن تطبيقات الخوارزمية (IMHO ، كما أعتقد أنه ينبغي). لا يقوم فريقي بتنفيذ هذا ، لذا فهذا ليس قرارنا ولكن إذا كان علينا اتخاذ قرار والبدء في التنفيذ - فسنمضي في هذا الطريق بالتأكيد.

يرجى تجنب واجهة INonce # $ 4 $ # $ ، يجب أن يكفي byte[] أو span<> لواجهة منخفضة المستوى متوافقة.

IV مقابل Nonce - الحالة المعممة هي بالفعل IV. بالنسبة إلى GCM ، يجب أن يكون IV من Nonce (مثل Car vs RedOrCar). ولأنني ألصق هذا ، لاحظت للتو استخدام timovzl مثالًا مشابهًا جدًا :)

sidshetye هل يمكنك تقديم اقتراح دقيق بأن كلا (1) يدعم الخوارزميات التي تحتاج إلى العلامة مقدمًا ، و (2) يحتاج فقط إلى العلامة في وقت متأخر مثل TryFinish في جميع المواقف الأخرى؟

أفترض أنك تفكر في شيء في الاتجاه التالي؟

  • يُسمح بأن تكون العلامة الموجودة في Initialize خالية. فقط تلك الخوارزميات التي تحتاجها مقدمًا سترمي بلا قيمة.
  • العلامة الموجودة في TryFinish مطلوبة ، أو (بدلاً من ذلك) يُسمح لها بأن تكون فارغة لتلك الخوارزميات التي تطلبتها مسبقًا.

أفترض أن ما ورد أعلاه يضيف فقط التعقيد في شكل التوثيق والمعرفة. بالنسبة لواجهة برمجة التطبيقات منخفضة المستوى ، يمكن اعتبار ذلك تضحية صغيرة ، نظرًا لأن الوثائق والدراية الكافية مطلوبة على أي حال.

لقد بدأت في الاقتناع بأن هذا يجب أن يكون ممكنًا ، من أجل التوافق مع التطبيقات الأخرى ، والبث.

timovzl بالتأكيد ، آمل أن أخصص بعض الوقت غدًا لهذا الغرض.

Timovzl ، انتهى بي الأمر بقضاء الوقت اليوم فقط واتضح أن هذا هو حفرة الأرانب! هذا طويل ولكني أعتقد أنه يلتقط معظم حالات الاستخدام ، ويلتقط نقاط قوة تشفير .NET ( ICryptoTransform ) أثناء تبني اتجاه .NET Core / Standard ( Span<> ). لقد أعدت القراءة ولكن آمل ألا تكون هناك أخطاء مطبعية أدناه. أعتقد أيضًا أن بعض الاتصالات في الوقت الفعلي (الدردشة ، الاتصال الخاطئ ، إلخ) أمر حيوي لعصف ذهني سريع ؛ آمل أن تتمكن من التفكير في ذلك.

نموذج البرمجة

سأتحدث أولاً عن نموذج البرمجة الناتج لمستخدمي واجهة برمجة التطبيقات.

تشفير الجري

var aesGcm = new AesGcm();
using (var encryptor = aesGcm.CreateAuthenticatedEncryptor(Key, IV, AAD))
{
  using (var cryptoOutStream = new CryptoStream(cipherOutStream, encryptor, CryptoStreamMode.Write))
  {
    clearInStream.CopyTo(cryptoOutStream);
  }
}

الجري فك التشفير

var aesGcm = new AesGcm();
using (var decryptor = aesGcm.CreateAuthenticatedDecryptor(Key, IV, AAD))
{
  using (var decryptStream = new CryptoStream(cipherInStream, encryptor, CryptoStreamMode.Write))
  {
    decryptStream.CopyTo(clearOutStream);
  }
}

غير متدفق

نظرًا لأن عدم البث يمثل حالة خاصة من البث ، يمكننا التفاف رمز المستخدم أعلاه في طرق مساعدة على AuthenticatedSymmetricAlgorithm (الموضح أدناه) لفضح واجهة برمجة تطبيقات أبسط. بمعنى آخر

public class AesGcm : AuthenticatedSymmetricAlgorithm
{
  ...
  // These return only after consuming entire input buffer

  // Code like Streaming Encrypt from above within here
​  public abstract bool TryEncrypt(ReadOnlySpan<byte> clearData, Span<byte> encryptedData);

  // Code like Streaming Decrypt from above within here
  public abstract bool TryDecrypt(ReadOnlySpan<byte> encryptedData, Span<byte> clearData); 
  ...
}

يمكن أن يتضاعف هذا لتقديم واجهة برمجة تطبيقات أبسط مثل

تشفير غير متدفق

var aesGcm = new AesGcm(Key, IV, AAD);
aesGcm.TryEncrypt(clearData, encryptedData);
var tag = aesGcm.Tag;

فك التشفير غير المتدفقة

var aesGcm = new AesGcm(Key, IV, AAD);
aesGcm.Tag = tag;
aesGcm.TryDecrypt(encryptedData, clearData);

تحت الغطاء

بالنظر إلى مصدر corefx ، ستجد Span <> في كل مكان. يتضمن ذلك System.Security.Cryptography. * - باستثناء الأصفار المتماثلة ، لذلك دعنا نصلح ذلك التشفير الأول وطبقة التشفير المصدق في الأعلى.

1. أنشئ ICipherTransform لمدخل / إخراج Span

هذا يشبه إصدار Span المدرك لـ ICryptoTransform . سأقوم فقط بتغيير الواجهة نفسها كجزء من ترقية إطار العمل ولكن نظرًا لأن الأشخاص يمكن أن يتأثروا بهذا الأمر ، فإنني أسميها ICipherTransform .

public partial interface ICipherTransform : System.IDisposable
{
  bool CanReuseTransform { get; }
  bool CanTransformMultipleBlocks { get; } // multiple blocks in single call?
  bool CanChainBlocks { get; }             // multiple blocks across Transform/TransformFinal
  int InputBlockSize { get; }
  int OutputBlockSize { get; }
  int TransformBlock(ReadOnlySpan<byte> inputBuffer, int inputOffset, int inputCount, Span<byte> outputBuffer, int outputOffset);
  Span<byte> TransformFinalBlock(ReadOnlySpan<byte> inputBuffer, int inputOffset, int inputCount);
}

ضع علامة أيضًا ICryptoTransform على أنه [Obsolete]

أن تكون مهذبًا مع الأشخاص الذين لديهم معرفة سابقة بتشفير .NET

[Obsolete("See ICipherTransform")]
public partial interface ICryptoTransform : System.IDisposable { ... }

2. قم بتوسيع فئة SymmetricAlgorithm الحالية لـ Span I / O

public abstract class SymmetricAlgorithm : IDisposable
{
  ...
  public abstract ICipherTransform CreateDecryptor(ReadOnlySpan<byte> Key, ReadOnlySpan<byte> IV);
  public abstract ICipherTransform CreateEncryptor(ReadOnlySpan<byte> Key, ReadOnlySpan<byte> IV);
  public virtual ReadOnlySpan<byte> KeySpan {...}
  public virtual ReadOnlySpan<byte> IVSpan {...}
  public virtual ReadOnlySpan<byte> KeySpan {...}
  ...
}

3. قم بتوسيع CryptoStream الحالي لمدخل / إخراج Span

هذا تمامًا مثل Stream في System.Runtime. بالإضافة إلى أننا سنضيف c'tor لحالة AEAD لدينا لمتابعة.

هام: سيحتاج CryptoStream إلى ترقية إلزامية في FlushFinalBlock لإضافة العلامة إلى نهاية الدفق أثناء التشفير واستخراج العلامة تلقائيًا (TagSize bytes) أثناء فك التشفير . هذا مشابه لواجهات برمجة التطبيقات الأخرى التي تم اختبارها في المعركة مثل Java's Cryptographic Architecture أو C # BouncyCastle. هذا أمر لا مفر منه ولكن أفضل مكان للقيام بذلك لأنه في دفق يتم إنتاج العلامة في النهاية ولكن ليست هناك حاجة حتى يتم تحويل الكتلة النهائية أثناء فك التشفير. الاتجاه الصعودي هو أنه يبسط إلى حد كبير نموذج البرمجة.

ملاحظة: 1) باستخدام CBC-HMAC ، يمكنك اختيار التحقق من العلامة أولاً. إنه الخيار الأكثر أمانًا ، ولكن إذا كان الأمر كذلك ، فإنه يجعله في الواقع خوارزمية ثنائية المسار. المرور الأول يحسب علامة HMAC ثم الممر الثاني يقوم بالفعل بفك التشفير. لذلك يجب دائمًا تخزين دفق الذاكرة أو دفق الشبكة في الذاكرة لتقليله إلى نموذج اللقطة الواحدة ؛ لا يتدفقون. يمكن لخوارزميات AEAD الحقيقية مثل GCM أو CCM البث بكفاءة.

public class CryptoStream : Stream, IDisposable
{
  ...
  public CryptoStream(Stream stream, IAuthenticatedCipherTransform transform, CryptoStreamMode mode);
  public override int Read(Span<byte> buffer, int offset, int count);
  public override Task<int> ReadAsync(Span<byte> buffer, int offset, int count, CancellationToken cancellationToken);
  public override void Write(ReadOnlySpan<byte> buffer, int offset, int count);
  public override Task WriteAsync(ReadOnlySpan<byte> buffer, int offset, int count, CancellationToken cancellationToken);

  public void FlushFinalBlock()
  {
    ...
    // If IAuthenticatedCipherTransform
    //    If encrypting, `TransformFinalBlock` -> `GetTag` -> append to out stream
    //    If decryption, extract last `TagSize` bytes -> `SetExpectedTag` -> `TransformFinalBlock`
    ...
  }

  ...
}

طبقة في التشفير المصدق

مع ما سبق ، يمكننا إضافة البتات المفقودة للسماح بالتشفير المصدق مع البيانات المرتبطة (AEAD)

تمديد ICipherTransform الجديد لـ AEAD

هذا يتيح لـ CryptoStream القيام بعمله بشكل صحيح. يمكننا أيضًا استخدام واجهة IAuthenticatedCipherTransform لتنفيذ فئة / استخدام البث المخصص الخاص بنا ولكن العمل مع CryptoStream يجعل من واجهة برمجة تطبيقات تشفير صافي فائقة التماسك ومتسقة.

  public interface IAuthenticatedCipherTransform : ICipherTransform
  {
    Span<byte> GetTag();
    void SetExpectedTag(Span<byte> tag);
  }

فئة أساسية للتشفير المصدق

ببساطة يوسع SymmetricAlgorithm

public abstract class AuthenticatedSymmetricAlgorithm : SymmetricAlgorithm
{
  ...
  // Program Key/IV/AAD via class properties OR CreateAuthenticatedEn/Decryptor() params
  public abstract IAuthenticatedCipherTransform CreateAuthenticatedDecryptor(ReadOnlySpan<byte> Key = default, ReadOnlySpan<byte> IV = default, ReadOnlySpan<byte> AuthenticatedData = default);
  public abstract IAuthenticatedCipherTransform CreateAuthenticatedEncryptor(ReadOnlySpan<byte> Key = default, ReadOnlySpan<byte> IV = default, ReadOnlySpan<byte> AuthenticatedData = default);
  public virtual Span<byte> AuthenticatedData {...}
  public virtual Span<byte> Tag {...}
  public virtual int TagSize {...}
  ...
}

فئة AES GCM

public class AesGcm : AuthenticatedSymmetricAlgorithm
{
  public AesGcm(ReadOnlySpan<byte> Key = default, ReadOnlySpan<byte> IV = default, ReadOnlySpan<byte> AuthenticatedData = default)

  /* other stuff like valid key sizes etc similar to `System.Security.Cryptography.Aes` */
}

sidshetye أنا أحيي هذا الجهد.

يمكن إجراء البث المباشر عبر GCM. الجري-فك التشفير عبر GCM هو

  • غير مسموح به في NIST 800-38d. القسم 5.2.2 "وظيفة فك التشفير المصدق" واضح تمامًا أن إرجاع النص العادي الذي تم فك تشفيره P يجب أن يتضمن المصادقة الصحيحة عبر العلامة T.
  • غير آمن. هناك مفهوم أمان للخوارزميات التي تكون آمنة في إعداد "إصدار نص عادي لم يتم التحقق منه" (RUP). تم إضفاء الطابع الرسمي على أمن RUP في ورقة 2014 بواسطة Andreeva-et-al. GCM ليس آمنًا في إعداد RUP. تسرد مسابقة CAESAR حيث تتم مقارنة كل إدخال مقابل GCM أمان RUP كخاصية مرغوبة. النص العادي الذي لم يتم التحقق منه والذي تم إصداره من GCM عرضة بشكل تافه لهجمات تقليب البت.

في وقت سابق من هذا الموضوع ، تم طرح إمكانية التشفير غير المتماثل / فك تشفير واجهات برمجة التطبيقات (من الناحية المفاهيمية) ، وأعتقد أن الإجماع كان على أنها ستكون فكرة سيئة للغاية.

باختصار ، لا يمكن أن يكون لديك واجهة برمجة تطبيقات دفق عالية المستوى لحبيبات البايت لفك تشفير GCM. لقد قلتها عدة مرات من قبل ، وأكررها مرة أخرى. الطريقة الوحيدة للحصول على دفق API هو التشفير المقسم. سأوفر على الجميع فرصة اللعب على التشفير المقسم ..

مهما قررت MS القيام به لواجهة برمجة تطبيقات GCM ، لا يمكن السماح لـ RUP.

تمت مناقشة sdrapkin RUP هنا بالتفصيل وقد عبرنا هذا الجسر بالفعل. باختصار ، يشير RUP إلى أن البيانات التي تم فك تشفيرها لا تحتاج إلى استخدامها حتى يتم التحقق من العلامة ، ولكن مثل Java JCE و WinNT bcrypt و OpenSSL وما إلى ذلك ، لا يلزم فرضها على حدود الطريقة. كما هو الحال مع معظم أساسيات التشفير ، ولا سيما العناصر منخفضة المستوى ، استخدمها بحذر.

^ ^ ^ هذا كثير. أوافق على المستوى الأعلى لواجهات برمجة التطبيقات (API) وما إلى ذلك ثم فرضها بشكل جيد. ولكن عندما أرغب في استخدام مستوى بدائي منخفض ، فأنا بحاجة إلى أن أكون قادرًا على استخدام أشياء مثل تقسيم المخازن المؤقتة وما إلى ذلك ، والأمر متروك لي لضمان عدم استخدام البيانات. قم بطرح استثناء في حساب العلامة / نقطة التحقق ولكن لا تعيق العناصر الأولية ذات المستوى المنخفض.

الأمر متروك لي للتأكد من عدم استخدام البيانات

خاطئ. انها ليست متروك لكم. AES-GCM له تعريف _ خاص_ للغاية ، وهذا التعريف يضمن أن الأمر ليس متروكًا لك. ما تريده هو بدائية AES-CTR منفصلة ، وبدائية منفصلة من نوع GHASH ، والتي يمكنك بعد ذلك دمجها وتطبيقها على النحو الذي تراه مناسبًا. لكننا لا نناقش بدائل AES-CTR و GHASH منفصلة ، أليس كذلك؟ نحن نناقش AES-GCM. ويتطلب AES-GCM عدم السماح باستخدام RUP.

أقترح أيضًا مراجعة إجابة Ilmari Karonen من crypto.stackexchange .

sdrapkin أنت تقدم نقطة جيدة. سيكون من المرغوب ، مع ذلك ، أن يكون لديك خوارزمية آمنة بموجب RUP ، وأن تكون هذه الخوارزمية مناسبة لواجهة برمجة التطبيقات التي يتم تحديدها هنا. لذلك علينا أن نختار:

  1. لا تدعم واجهة برمجة التطبيقات البث. بسيط ، لكنه يفتقر إلى واجهة برمجة تطبيقات منخفضة المستوى. قد نأسف لهذا يومًا ما.
  2. يمنع تنفيذ AES-GCM التدفق ، والالتزام بالمواصفات دون تقييد واجهة برمجة التطبيقات.

هل يمكننا اكتشاف سيناريو البث وطرح استثناء يشرح سبب عدم صحة هذا الاستخدام؟ أم أننا بحاجة إلى اللجوء إلى جعل تطبيقه المتدفق يستهلك المخزن المؤقت بأكمله؟ سيكون هذا الأخير مؤسفًا: قد تعتقد أنك تقوم بالبث ، لكنك لست كذلك.

يمكننا إضافة طريقة SupportsStreaming(out string whyNot) يتم فحصها من خلال تنفيذ البث.

هل لدينا حجة قوية ضد البث المباشر / tag-at-the-end بشكل عام ؟ إذا لم يكن الأمر كذلك ، فأعتقد أنه يجب ألا نهدف إلى استبعاده باستخدام واجهة برمجة التطبيقات.

sdrapkin : لنلقي نظرة أوسع على RUP لأن هذه مكتبة وليست تطبيقًا. لذا فهذه مشكلة تتعلق بالتخزين المؤقت وتصميم الطبقة أكثر من الإصدار الفعلي / الاستخدام الفعلي لبيانات لم يتم التحقق منها. بالنظر إلى منشور NIST الخاص 800-38D لـ AES GCM ، نرى ذلك

  1. تحدد مواصفات GCM الحد الأقصى لطول النص العادي ليكون 2 ^ 39-256 بت ~ 64 جيجابايت. التخزين المؤقت في أي مكان قريب من ذاكرة النظام أمر غير معقول.

  2. حددت مواصفات GCM الإخراج كـ FAIL إذا فشلت العلامة. لكنها ليست إلزامية حول أي طبقة في التنفيذ يجب تخزينها مؤقتًا حتى التحقق من العلامة. لنلقِ نظرة على مكدس المكالمات مثل:

A => AESGCM_Decrypt_App(key, iv, ciphertext, aad, tag)
B =>  +- AESGCM_Decrypt_DotNet(key, iv, ciphertext, aad, tag)
C =>    +- AESGCM_Decrypt_OpenSSL(key, iv, ciphertext, aad, tag)

أين
A هو AES GCM في طبقة التطبيق
B هو AES-GCM في طبقة اللغة
C هي AES-GCM في طبقة المنصة

يتم تحرير النص العادي في (A) إذا تم سحب العلامة ولكن FAIL عاد إذا كان الأمر مختلفًا. ومع ذلك ، لا يشير أي مكان في المواصفات إلى أن الذاكرة الرئيسية هي المكان الوحيد لتخزين نص عادي قيد التقدم ، ولا يجب أن يحدث التخزين المؤقت في (B) أو (C) أو في أي مكان آخر. في الواقع OpenSSL و Windows NT Bcrypt على سبيل المثال (C) حيث يسمح التدفق بالتخزين المؤقت في الطبقة العليا. و Java JCA و Microsoft's CLR Security واقتراحي أعلاه هي أمثلة على (B) حيث يسمح البث بالتخزين المؤقت في طبقة التطبيق. من الغري افتراض أن مصممي A ليس لديهم قدرات تخزين مؤقت أفضل قبل إصدار نص عادي. يمكن أن يكون هذا المخزن المؤقت نظريًا وعمليًا ذاكرة أو محركات أقراص صلبة أو مجموعة تخزين عبر الشبكة. أو بطاقات مثقبة ؛)!

حتى لو تركنا التخزين المؤقت جانباً ، تناقش الورقة مخاوف عملية أخرى (انظر القسم 9.1 ، اعتبارات التصميم و 9.2 ، الاعتبارات التشغيلية) مثل حداثة المفاتيح أو عدم التكرار الرابع عبر حالات فشل الطاقة غير المحددة. من الواضح أننا لن نخبز هذا في الطبقة ب ، أي هنا.

timovzl ، يعالج الاقتراح الأخير أعلاه كلا السيناريوهين - طلقة واحدة (المهندس المعماري لا يهتم بالتخزين المؤقت) بالإضافة إلى البث (يتمتع المهندس المعماري بقدرات تخزين مؤقت أفضل). طالما أن وثائق واجهة برمجة التطبيقات المتدفقة منخفضة المستوى واضحة أن المستهلك مسؤول الآن عن التخزين المؤقت لها ، فلا يوجد أي انخفاض في إثبات الأمان ولا يوجد أي انحراف عن المواصفات.

تحرير: القواعد النحوية والأخطاء المطبعية ومحاولة الحصول على تخفيض السعر

Bingo .. مرة أخرى ، يعود قرار مصممي الطبقات إلى مكان حدوث التحقق من العلامة. أنا لا أدعو بأي حال من الأحوال إلى إصدار بيانات لم يتم التحقق منها إلى طبقة التطبيق.

تعود المناقشة حول مستوى واجهة برمجة التطبيقات (API) الخاصة بمستوى "المستهلك" أم أنها عناصر أولية حقيقية. إذا كانت عناصر أولية حقيقية ، فيجب عليهم الكشف عن الوظيفة بحيث يمكن إنشاء واجهات برمجة تطبيقات ذات مستوى أعلى "أكثر أمانًا" في الأعلى. لقد تقرر بالفعل أعلاه مع مناقشة Nonce أن هذه يجب أن تكون بدائية حقيقية مما يعني أنه يمكنك إطلاق النار على نفسك ، وأعتقد أن الأمر نفسه ينطبق على فك تشفير النص المشفر المتدفق / الجزئي.

بقول ذلك ، سيكون من الضروري توفير مستوى "أعلى" وأكثر أمانًا لواجهة برمجة التطبيقات بسرعة لمنع الأشخاص من "تدحرج" أنفسهم فوق هذه.

ينبع اهتمامي من الشبكات / خطوط الأنابيب وإذا كنت لا تستطيع عمل مخازن مؤقتة جزئية وعليك القيام بـ "طلقة واحدة" فلن تكون هناك فائدة من الجانب السلبي لواجهة برمجة التطبيقات هذه ، لذا سأستمر في الذهاب إلى BCrypt / OpenSsl وما إلى ذلك مباشرةً.

ينبع اهتمامي من الشبكات / خطوط الأنابيب وإذا كنت لا تستطيع عمل مخازن مؤقتة جزئية وعليك القيام بـ "طلقة واحدة" فلن تكون هناك فائدة من الجانب السلبي لواجهة برمجة التطبيقات هذه ، لذا سأستمر في الذهاب إلى BCrypt / OpenSsl وما إلى ذلك مباشرةً.

بالضبط. لن تختفي الحاجة ، لذلك سيستخدم الناس تطبيقات أخرى أو يطرحون تطبيقاتهم الخاصة. هذه ليست بالضرورة نتيجة أكثر أمانًا من السماح بالبث مع وثائق تحذير جيدة.

Timovzl ، أعتقد أننا استخلصنا الكثير من التعليقات الفنية ومتطلبات التصميم حول الاقتراح الأخير . أفكار حول التنفيذ والإفراج؟

قدم Sidshetye عرضًا تفصيليًا أعتقد أنه يلبي جميع المتطلبات. تم التعامل مع الانتقاد الفردي المتعلق بال RUP دون مزيد من المعارضة. (على وجه التحديد ، قد يتم منع RUP في واحدة من عدة طبقات ، ويجب ألا تملي واجهة برمجة التطبيقات ذات المستوى المنخفض أيًا منها ؛ ومن المتوقع أن يكون لتقديم _لا_ تدفق تأثيرات أسوأ.)

من أجل إحراز تقدم ، أود أن أدعو أي شخص لديه مخاوف أخرى بشأن الاقتراح الأخير للتحدث - وبالطبع ، تقديم بدائل.

أنا متحمس بشأن هذا الاقتراح وبشأن واجهة برمجة التطبيقات (API) التي تتشكل.

Sidshetye ، لدي بعض الأسئلة والاقتراحات:

  1. هل من المستحسن أن ترث من SymmetricAlgorithm الموجود؟ هل هناك أي مكونات حالية نريد التكامل معها؟ ما لم أفقد بعض المزايا لهذا الأسلوب ، أفضل أن أرى AuthenticatedEncryptionAlgorithm بدون فئة أساسية. إذا لم يكن هناك شيء آخر ، فإنه يتجنب كشف طرق غير مرغوب فيها CreateEncryptor / CreateDecryptor (غير مصادقة!).
  2. لا يوجد أي من المكونات المعنية قابلة للاستخدام مع التشفير غير المتماثل ، أليس كذلك؟ تحذف جميع المكونات تقريبًا كلمة "متماثل" من أسمائها ، وهو أمر أتفق معه. ما لم نستمر في وراثة SymmetricAlgorithm ، يمكن إعادة تسمية AuthenticatedSymmetricAlgorithm إلى AuthenticatedEncryptionAlgorithm ، مع الالتزام بالمصطلح التقليدي "التشفير المصدق".
  3. قم بتغيير TryEncrypt / TryDecrypt للكتابة إلى / استلام العلامة ، بدلاً من امتلاك خاصية Tag قابلة للتعيين في الخوارزمية.
  4. ما هو الغرض من تعيين key و iv و authenticatedAdditionalData عبر المستوطنين العامين؟ أود الابتعاد عن الأساليب المتعددة الصالحة ، والخصائص القابلة للتغيير قدر الإمكان. هل يمكنك إنشاء اقتراح محدث بدونهم؟
  5. هل نريد أي ولاية في AesGcm على الإطلاق؟ غريزتي هي بالتأكيد الاحتفاظ بـ iv و authenticatedAdditionalData ، لأنهما لكل رسالة. قد يستحق key وجوده كحالة ، لأننا نريد عمومًا القيام بعمليات متعددة بمفتاح واحد. ومع ذلك ، من الممكن أن تأخذ المفتاح على أساس كل مكالمة أيضًا. نفس الأسئلة تذهب إلى CreateAuthenticatorEncryptor . على أي حال ، يجب أن نستقر على طريقة واحدة لتمرير المعلمات. أنا حريص على مناقشة الإيجابيات والسلبيات. أميل إلى الحالة الرئيسية في AesGcm ، والباقي بـ CreateAuthenticatedEncryptor أو TryEncrypt على التوالي. إذا كنا بالفعل متفقين ، يرجى إطلاعنا على اقتراح محدث. :-)
  6. من المحتمل أن يكون ICipherTransform فئة مجردة ، CipherTransform ، بحيث يمكن إضافة هذه الأساليب دون كسر عمليات التنفيذ الحالية.
  7. يجب أن تستخدم جميع معلمات الوظيفة حالة الجمل ، أي ابدأ بأحرف صغيرة. أيضًا ، هل يجب أن نقول authenticatedData أم authenticatedAdditionalData ؟ بالإضافة إلى ذلك ، أعتقد أنه يجب علينا اختيار أسماء المعلمات plaintext و ciphertext .
  8. أينما يتم تمرير IV ، أود أن أراه كمعامل اختياري ، مما يسهل الحصول على IV (Cryptorandom) IV الذي تم إنشاؤه بشكل صحيح بدلاً من تقديمه الخاص بنا. يجعل إساءة استخدام واجهة برمجة التطبيقات ذات المستوى المنخفض أكثر صعوبة ، على الأقل ، ونحصل عليها مجانًا.
  9. ما زلت أحاول معرفة كيف يمكن لكود عميل TryEncrypt معرفة طول الامتداد المطلوب لتوفير ciphertext ! نفس الشيء لـ TryDecrypt وطول plaintext . بالتأكيد ليس من المفترض أن نجربهم في حلقة حتى النجاح ، مضاعفة الطول بعد كل تكرار فاشل؟

أخيرًا ، فكر في المستقبل ، كيف يمكن أن تبدو واجهة برمجة التطبيقات عالية المستوى المبنية على رأس هذا؟ بالنظر فقط إلى استخدام واجهة برمجة التطبيقات ، يبدو أن هناك مجالًا ضئيلًا للتحسين ، نظرًا لأن كلا من واجهات برمجة التطبيقات المتدفقة وغير المتدفقة واضحة جدًا بالفعل! الاختلافات الرئيسية التي أتخيلها هي IV تلقائيًا ، وأحجام إخراج تلقائية ، وربما حدًا لكمية البيانات المشفرة.

يسمح Windows بالبث. OpenSSL يفعل ذلك أيضًا. كل من هؤلاء في الغالب صنفوه في المفاهيم الحالية (على الرغم من أنهم ألقوا مفتاح ربط مع "وهناك هذا الشيء على الجانب الذي يجب عليك التعامل معه أو سأخطئ").

لا يذهب ، و libsodium لا.

يبدو أن الموجة الأولى سمحت بذلك ، ولكن الموجة اللاحقة لم تسمح بذلك. نظرًا لأننا بلا جدال في موجة لاحقة ، أعتقد أننا سنلتزم بعدم السماح بذلك. إذا كان هناك طلب متزايد على البث بعد تقديم نموذج أحادي الطلقة (للتشفير / فك التشفير ، يمكن الاحتفاظ بالمفتاح عبر المكالمات) ، فيمكننا إعادة التقييم. لذا فإن اقتراح واجهة برمجة التطبيقات الذي يلتزم بهذا النمط يبدو مفيدًا. على الرغم من عدم دعم SIV و CCM لتشفير البث ، إلا أن واجهة برمجة التطبيقات المتدفقة بالنسبة لهم من المحتمل أن تكون مخزنة بشكل كبير. إبقاء الأمور واضحة يبدو أفضل.

يجب ألا تُدرج المقترحات العلامة في الحمولة (يطلق عليها GCM و CCM كمرجع منفصل) ، ما لم تدمجها الخوارزمية نفسها (SIV) في إخراج التشفير. ( E(...) => (c, t) مقابل E(...) => c || t أو E(...) => t || c ). يمكن لمستخدمي واجهة برمجة التطبيقات (API) بالتأكيد استخدامها كسلسلة (فقط افتح Spans بشكل مناسب).

لا تسمح مواصفات GCM بالإفراج عن أي شيء بخلاف FAIL عند عدم تطابق العلامة. NIST واضح تمامًا بشأن ذلك. تقول ورقة GCM الأصلية من McGrew & Viega أيضًا:

ستعيد عملية فك التشفير FAIL بدلاً من النص العادي ، وسيتوقف فك الكبسولة وسيتم تجاهل النص العادي بدلاً من إعادة توجيهه أو معالجته مرة أخرى.

لم تتناول أي من التعليقات السابقة RUP - لقد قاموا فقط بلوحها يدويًا بعيدًا ("الطبقة العليا ستعتني بها" - نعم ، صحيح).

الأمر بسيط: يمكن لتشفير GCM البث. لا يمكن بث فك تشفير GCM. أي شيء آخر لم يعد GCM.

يبدو أن الموجة الأولى سمحت بذلك ، ولكن الموجة اللاحقة لم تسمح بذلك. نظرًا لأننا بلا جدال في موجة لاحقة ، أعتقد أننا سنلتزم بعدم السماح بذلك.

bartonjs أنت تتجاهل حرفيًا جميع التحليلات الفنية والمنطقية وتستخدم بدلاً من ذلك تواريخ مشروعي Go و libsodium كبديل ضعيف للتحليل الحقيقي؟ تخيل لو قدمت حجة مماثلة بناءً على أسماء المشاريع. بالإضافة إلى أننا نقرر الواجهة والتطبيقات. أنت تدرك أن اتخاذ قرار بشأن واجهة غير متدفقة لـ AEAD يمنع كل هذه التطبيقات على الطريق ، أليس كذلك؟

إذا كان هناك طلب متزايد على البث بعد تقديم نموذج أحادي الطلقة (للتشفير / فك التشفير ، يمكن الاحتفاظ بالمفتاح عبر المكالمات) ، فيمكننا إعادة التقييم.

لماذا الطلب الذي تم إظهاره حتى الآن على GitHub غير كافٍ؟ لقد وصل الأمر إلى النقطة التي يبدو فيها أنه من الغريب تمامًا دعم الاضطرار إلى القيام بعمل أقل من أي مزايا فنية أو طلب العميل.

bartonjs أنت تتجاهل حرفياً جميع التحليلات الفنية والمنطقية وتستخدم بدلاً من ذلك تواريخ مشروعي Go و libsodium كبديل ضعيف للتحليل الحقيقي؟

لا ، أنا أستخدم نصيحة مصممي التشفير المحترفين الذين يقولون إنه خطير للغاية ويجب علينا تجنب بث AEAD. ثم أستخدم المعلومات من فريق CNG المكون من "العديد من الأشخاص يقولون إنهم يريدون ذلك من الناحية النظرية ، ولكن من الناحية العملية لا أحد يفعل ذلك تقريبًا" (لا أعرف مقدار القياس عن بُعد مقابل القصص من تقديم طلبات المساعدة). إن حقيقة أن المكتبات الأخرى قد سلكت طريق الطلقة الواحدة _يعزز _ القرار.

لماذا الطلب الذي تم إظهاره حتى الآن على GitHub غير كافٍ؟

تم ذكر عدد قليل من السيناريوهات. من المحتمل أن تتم معالجة المخازن المؤقتة المجزأة بقبول ReadOnlySequence ، إذا بدا أن هناك سيناريو كافٍ لتبرير تعقيد واجهة برمجة التطبيقات بدلاً من جعل المتصل يقوم بإعادة تجميع البيانات.

تمثل الملفات الكبيرة مشكلة ، لكن الملفات الكبيرة تمثل مشكلة بالفعل نظرًا لأن GCM بها حد خجول يبلغ 64 جيجابايت فقط ، وهو "ليس بهذا الحجم" (حسنًا ، إنه كبير جدًا ، ولكنه ليس "قف ، هذا كبير" هكذا كان الحال). تسمح الملفات المعينة للذاكرة باستخدام Spans (تصل إلى 2 ^ 31-1) دون الحاجة إلى ذاكرة وصول عشوائي (RAM) بسعة 2 جيجابايت. لذلك قمنا بحلق بضع بتات من الحد الأقصى ... من المحتمل أن يحدث ذلك بمرور الوقت على أي حال.

أنت تدرك أن اتخاذ قرار بشأن واجهة غير متدفقة لـ AEAD يمنع كل هذه التطبيقات على الطريق ، أليس كذلك؟

أنا مقتنع أكثر فأكثر بأن GrabYourPitchforks كان على حق (https://github.com/dotnet/corefx/issues/23629#issuecomment-334638891) أنه ربما لا توجد واجهة موحدة معقولة. GCM _requiring_ a nonce / IV and SIV _forbidding_ فهذا يعني أن تهيئة وضع / خوارزمية AEAD تتطلب بالفعل معرفة ما سيحدث ... لا يوجد حقًا فكرة "مجردة" لـ AEAD. تملي SIV أين تذهب "العلامة". GCM / CCM لا تفعل ذلك. SIV هو العلامة أولاً ، حسب المواصفات.

لا يمكن لـ SIV البدء في التشفير حتى تحتوي على جميع البيانات. لذا فإن تشفير التدفق الخاص به إما سيرمي (مما يعني أنه يجب عليك معرفة عدم تسميته) أو المخزن المؤقت (والذي قد ينتج عنه وقت تشغيل n ^ 2). لا يمكن أن يبدأ CCM حتى يعرف الطول ؛ لكن CNG لا تسمح بإعطاء تلميح مشفر مسبقًا بالطول ، لذا فهو موجود في نفس القارب.

لا يجب أن نصمم مكونًا جديدًا يكون من الأسهل فيه فعل الشيء الخطأ بدلاً من فعل الشيء الصحيح افتراضيًا. يجعل فك تشفير البث من السهل جدًا والمغري توصيل فئة Stream (على غرار اقتراحك للقيام بذلك باستخدام CryptoStream) مما يجعل من السهل جدًا الحصول على خطأ في التحقق من صحة البيانات قبل التحقق من العلامة ، مما يلغي تقريبًا فائدة AE . ( IGcmDecryptor => CryptoStream => StreamReader => XmlReader => "انتظر ، هذا ليس XML قانونيًا ..." => أوراكل النص المشفر التكيفي) .

إنها تصل إلى النقطة ... طلب ​​الزبون.

كما سمعت ، للأسف ، مرات عديدة في حياتي: أنا آسف ، لكنك لست العميل الذي نفكر فيه. سأعترف بأنه ربما تعرف كيفية القيام بـ GCM بأمان. أنت تعلم أن تقوم بالدفق فقط إلى ملف متغير / مخزن مؤقت / إلخ إلا بعد التحقق من العلامة. أنت تعرف ما تعنيه إدارة nonce ، وتعرف مخاطر فهمها بشكل خاطئ. أنت تعلم أنه يجب الانتباه إلى أحجام التدفق وتقطيعه إلى مقطع GCM جديد بعد 2 ^ 36-64 بايت. أنت تعلم أنه بعد كل ما قيل وفعلت ، فهذا هو الخطأ إذا فهمت هذه الأشياء بشكل خاطئ.

من ناحية أخرى ، فإن العميل الذي أفكر فيه هو شخص يعرف "يجب علي تشفير هذا" لأن رئيسه قال له ذلك. وهم يعلمون أنه عند البحث عن كيفية عمل التشفير ، قال بعض البرامج التعليمية "استخدم دائمًا AE" ويذكر GCM. ثم وجدوا البرنامج التعليمي "التشفير في .NET" الذي يستخدم CryptoStream. ثم يقومون بعد ذلك بتوصيل خط الأنابيب ، دون أن يكون لديهم أي فكرة بأنهم قاموا للتو بنفس الشيء مثل اختيار SSLv2 ... قاموا بفحص المربع من الناحية النظرية ، ولكن ليس في الواقع العملي. وعندما يفعلون ذلك ، فإن هذا الخطأ ينتمي إلى كل من عرف أفضل ، لكن اجعل الشيء الخطأ سهل التنفيذ.

أنت لست العميل الذي نفكر فيه [...] العميل الذي أفكر فيه ، من ناحية أخرى ، هو شخص يعرف "لا بد لي من تشفير هذا" لأن رئيسهم طلب منهم [...]

منذ أشهر bartonjs ، قررنا بالفعل أن الهدف هو استهداف ملفي تعريف للعملاء من خلال وجود واجهة برمجة تطبيقات منخفضة المستوى (قوية ولكنها غير آمنة في ظل ظروف معينة) وواجهة برمجة تطبيقات عالية المستوى (مضمونة). إنه حتى في العنوان. إنها بالتأكيد دولة حرة ولكن من المخادع الآن تحريك المرمى من خلال الادعاء بخلاف ذلك.

من ناحية أخرى ، فإن العميل الذي أفكر فيه هو شخص يعرف "يجب علي تشفير هذا" لأن رئيسه قال له ذلك. وهم يعلمون أنه عند البحث عن كيفية عمل التشفير ، قال بعض البرامج التعليمية "استخدم دائمًا AE" ويذكر GCM. ثم وجدوا البرنامج التعليمي "التشفير في .NET" الذي يستخدم CryptoStream. ثم يقومون بعد ذلك بتوصيل خط الأنابيب ، دون أن يكون لديهم أي فكرة بأنهم قاموا للتو بنفس الشيء مثل اختيار SSLv2 ... قاموا بفحص المربع من الناحية النظرية ، ولكن ليس في الواقع العملي. وعندما يفعلون ذلك ، فإن هذا الخطأ ينتمي إلى كل من يعرف أفضل ، لكن دع الشيء الخطأ يكون من السهل جدًا القيام به.

bartonjs انتظر ، ماذا حدث للبدائية منخفضة المستوى؟ اعتقدت أن الهدف من هذه المشكلة بالذات هو المرونة في مجالسة الأطفال. أخبرنا بالتأكيد إذا كانت الخطة قد تغيرت ، حتى نتحدث جميعًا عن نفس الشيء.

أيضًا ، هل لا تزال طرق كل كتلة قيد الدراسة ، أم مجرد طرق أحادية الطور؟

أنا مقتنع أكثر فأكثر بأن GrabYourPitchforks كان محقًا (# 23629 (تعليق)) أنه ربما لا توجد واجهة موحدة معقولة.

عند رؤية جميع الأمثلة ، يبدو أن هذا يبدو أكثر فأكثر غير مجدي - خاصة بالنسبة لواجهة برمجة التطبيقات منخفضة المستوى حيث يكون للتطبيقات قيود مختلفة. ربما يجب علينا فقط أن نضع مثالًا قويًا مع AES-GCM ، بدلاً من واجهة موحدة. كملاحظة جانبية ، قد لا يزال هذا الأخير مثيرًا للاهتمام لواجهة برمجة تطبيقات عالية المستوى في المستقبل. من المحتمل أن تجعل خصائصه المتمثلة في كونها أكثر تقييدًا واجهة موحدة أسهل بكثير هناك.

هل الأساليب لكل كتلة لا تزال قيد الدراسة ، أم مجرد طرق أحادية الطور؟

كما هو مذكور في https://github.com/dotnet/corefx/issues/23629#issuecomment -378605071 ، نشعر أن المخاطر مقابل المكافأة مقابل حالات الاستخدام المعبر عنها تقول أننا يجب أن نسمح فقط بإصدارات من لقطة واحدة من AE.

لم أقرأ المناقشة بأكملها ، فقط أجزاء عشوائية. لا أعرف في أي اتجاه أنت ذاهب. آسف إذا كان ما أكتبه لا معنى له في هذا السياق. بلدي 2 ¢:

  • تيارات مهمة. إذا لم تتمكن من دعمهم بشكل مباشر لأن ذلك قد يعني ثغرة أمنية ، فقم إذا أمكن بتوفير غلاف عالي المستوى مبني على واجهة API منخفضة المستوى الخاصة بك والتي من شأنها أن تكشف التدفقات (بطريقة غير فعالة ولكنها آمنة).
  • إذا لم يكن بإمكان AES-GCM مطلقًا استخدام التدفقات في أي سيناريو ، فقم بتوفير تنفيذ شرعي لـ AES-CBC-HMAC المستند إلى التدفقات. أو بعض خوارزمية AE الأخرى.
  • كلما ارتفع المستوى كان ذلك أفضل. كلما قل عدد المناطق التي يرتكب فيها المستخدم خطأً كلما كان ذلك أفضل. المعنى - كشف واجهة برمجة التطبيقات التي من شأنها إخفاء أكبر قدر ممكن من الأشياء (على سبيل المثال علامة المصادقة هذه). بالطبع ، يمكن (ينبغي) أن يكون هناك حمولات زائدة أكثر تحديدًا أيضًا.
  • لا تهتم IMHO بتوحيد الواجهات مع خدمات التشفير الأخرى إذا كانت ببساطة غير مناسبة. هذا ما فعلته openssl مع CLI وكانت النتيجة رديئة (على سبيل المثال ، لا توجد إمكانية لتوفير علامة المصادقة).

نحن (فريق أمان .NET) الذي عقدناه فيما بيننا ومع فريق التشفير الأوسع داخل Microsoft. ناقشنا العديد من القضايا والاهتمامات المذكورة في هذا الموضوع. في النهاية ، لم تكن هذه المخاوف مقنعة بما يكفي لضمان تقديم GCM API المتدفقة باعتبارها لبنة أساسية في إطار العمل.

يمكن إعادة النظر في هذا القرار في المستقبل إذا دعت الحاجة. وفي غضون ذلك ، لم نجعل الأمور أسوأ مما هي عليه اليوم: يمكن للمطورين الذين يستخدمون حاليًا مكتبة تشفير تابعة لجهة خارجية لبث دعم GCM الاستمرار في القيام بذلك ، ولن يتم كسرهم من خلال تقديمنا المقصود لـ واجهة برمجة تطبيقات GCM غير المتدفقة.

كيف يتم التعامل مع تشفير البيانات التي لا تتناسب مع الذاكرة؟

pgolebiowski أنت تستخدم مكتبات تشفير عالية المستوى من .NET مصممة خصيصًا لتقديم تشفير آمن للبث.

sdrapkin قول هذا أسهل من فعله. "الآمن" كثير لنطلبه. ما الذي تم إثباته ويمكن الوثوق به بالفعل؟ تقول لنفسك:

مكتبة Bouncy Castle c # (توصية StackOverflow نموذجية). Bouncy Castle c # عبارة عن كتالوج متحف ضخم (145k LOC) ضعيف الأداء من العملات المشفرة (بعضها قديم) ، مع تطبيقات Java القديمة التي تم نقلها إلى .NET القديمة (2.0؟).

طيب ما هي الخيارات؟ ربما مكتبتك الخاصة؟ ليس حقا . هم ... ربما libsodium-net؟ ليس حقا .

عندما تبحث بالفعل عن مكتبة مدققة تأتي من مصدر موثوق إلى حد ما (مثل Microsoft أو يستخدمه المجتمع على نطاق واسع) ، لا أعتقد أن مثل هذه المكتبة موجودة في عالم .NET Core.


  • العميل: تشفير مصدق للبيانات لا يتناسب مع الذاكرة؟
  • Microsoft: أنا آسف ، لكنك لست العميل الذي نضعه في الاعتبار. استخدم مكتبة لم يتم تدقيقها وسلامتها موضع شك ، وليست مشكلتنا إذا كنت تتعرض لهجوم من قناة جانبية.
  • عميل:

pgolebiowski الخيارات هي استخدام إطار عمل .NET ثابت - أي. الشيء نفسه الذي تم إثباته ويمكن الوثوق به كما تريد. تنتظر المكتبات الأخرى (بما في ذلك المكتبات الخاصة بي) حتى تقوم Microsoft بإضافة أساسيات التشفير المفقودة مثل ECDH إلى NetStandard.

يمكنك أيضًا إلقاء نظرة على شوكات Inferno. هناك ما لا يقل عن 2 مفترقات حيث حققت بعض التغييرات البسيطة NetStandard20.

تم تدقيق مكتبتك منذ عامين في غضون يومين بواسطة شخص واحد . أنا لا أثق في ذلك ، آسف. في Microsoft ، سيكون هناك فريق مخصص لذلك - من الأشخاص الذين لدي ثقة أعلى من أولئك من Cure53.

بجدية ، يمكننا التحدث عن دعم الجهات الخارجية للعديد من الأشياء. ولكن يجب توفير جميع الأشياء المتعلقة بالأمان من قبل المكتبة القياسية.

pgolebiowski حاشا مني أن أقنع أي شخص بالثقة في أي شيء ، لكن بيانك ليس دقيقًا. تم تدقيق Inferno من قبل 2 متخصصين من منظمة "Cure53". استغرق التدقيق يومين ، وكانت المكتبة بأكملها حوالي 1000 سطر من التعليمات البرمجية. هذا ~ 250 سطرًا من التعليمات البرمجية لكل مدقق / يوم - يمكن التحكم فيه تمامًا.

في الواقع ، تعد إمكانية التدقيق السهلة من بين الميزات الرئيسية لـ Inferno ، على وجه التحديد لأولئك الذين لا يريدون الوثوق.

الهدف من هذا الموضوع هو إضافة دعم لـ AES-GCM. مكتبتك لا تدعم حتى AES-GCM. إذا كنت تريد أن يستخدم الأشخاص الكود الخاص بك ، قم بإرساله كاقتراح لـ corefx. في موضوع مناسب.

شيء آخر ، حتى لو دعمت هذه الخوارزمية - لم تتم مراجعتها من قبل لوحة تشفير الشبكة وليست جزءًا من corefx. إنه ليس حتى مرشحًا لمثل هذه المراجعة. هذا يعني نهاية هذا النقاش والإعلان غير المجدي.

pgolebiowski لم أعلن عن أي شيء - فقط أجبت على سؤالك واقترح بدائل لحالة استخدامك وصححت الادعاءات غير الدقيقة. لا يناسب AES-GCM تشفير البث ، وهذا شيء تمت مراجعته والاتفاق عليه من قبل فريق أمان .NET ، لذا يمكنك الوثوق بذلك .

هل أنا أدافع عن بث AES-GCM في أي مكان؟ لا استطيع التذكر. ولكن يمكن أن تتذكر قوله:

  • تيارات مهمة. إذا لم تتمكن من دعمهم بشكل مباشر لأن ذلك قد يعني ثغرة أمنية ، فقم إذا أمكن بتوفير غلاف عالي المستوى مبني على واجهة API منخفضة المستوى الخاصة بك والتي من شأنها أن تكشف التدفقات (بطريقة غير فعالة ولكنها آمنة).
  • إذا لم يكن بإمكان AES-GCM مطلقًا استخدام التدفقات في أي سيناريو ، فقم بتوفير تنفيذ شرعي لـ AES-CBC-HMAC المستند إلى التدفقات. أو بعض خوارزمية AE الأخرى.

أو ذكر مشكلة مفتوحة لـ corefx:

كيف يتم التعامل مع تشفير البيانات التي لا تتناسب مع الذاكرة؟


علاوة:

يمكنك أيضًا إلقاء نظرة على شوكات Inferno. هناك ما لا يقل عن 2 مفترقات حيث حققت بعض التغييرات البسيطة NetStandard20. [...] تم تدقيق Inferno بواسطة مهنيين اثنين من منظمة "Cure53" [...] سهولة التدقيق هي من بين السمات الرئيسية لـ Inferno ، على وجه التحديد لأولئك الذين لا يريدون الوثوق.

أنا لم أعلن أي شيء

تمامًا كما لو كنت جانبًا ، لم أرغب مطلقًا في "البث" بالمعنى الذي يفكر فيه معظم الناس. أردت فقط معالجة "الكتلة" لأسباب تتعلق بالأداء واستخدام الذاكرة. لا أريد في الواقع "بث" النتائج. هذا ما يبدو أنه من العار أن يفقد دعم cng ذلك ويجعل "البدائيين" عديم الفائدة في أي سيناريو يمكنني التفكير فيه.

Drawaes إذا فكرت في الأمر ، فقد تكون عملية الحظر أكثر أمانًا من استخدام التدفقات. قد يلمس الشخص العادي التدفقات ، لكنه يفضل استخدام واجهة برمجة التطبيقات ذات اللقطة الواحدة بدلاً من عملية الحظر. علاوة على ذلك ، لا يمكن دمج عملية الحظر _ مباشرة إلى الأمام_ مع ، على سبيل المثال ، XmlReader . لذلك في الواقع ، تنطبق العديد من المخاطر التي تمت مناقشتها على تدفق الكائنات ، ولكن ليس على عرقلة العملية.

للعمل مع عملية الكتلة عندما تتوفر أيضًا واجهة برمجة تطبيقات ذات طلقة واحدة ، يشير ذلك إلى أننا نعرف ما نقوم به ، وأننا نطلب على وجه التحديد تعديلًا منخفض المستوى. يمكننا حماية الشخص العادي _ و_ المرونة.

فيما يتعلق بتجنب RUP ، ما زلت أفكر في مقدار عملية كتلة الميزات حقًا لـ GCM. يجني التشفير الفوائد الكاملة ، بينما يستفيد فك التشفير إلى حد ما فقط. يمكننا تجنب تخزين النص المشفر بالكامل ، ولكن لا يزال يتعين علينا تخزين النص العادي الكامل مؤقتًا. اختيار فك التشفير لتخزين النص العادي الوسيط على القرص. لكن في المقابل ، قدمنا ​​مجالًا أكبر للخطأ. هل لدينا حجة مقنعة لعدم حل هذه المشكلة على مستوى أعلى (على سبيل المثال قطعة هناك ، أو استخدام خوارزمية دفق حقيقية)؟

TLS وخطوط الأنابيب. حاليًا (وللمستقبل المنظور) تستخدم خطوط الأنابيب 4k كتل ولكن رسالة tls يمكن أن تكون 16 كيلو من نص التشفير. مع طلقة واحدة ، ستحتاج إلى نسخ 16 كيلو بايت إلى مخزن مؤقت طارئ واحد قبل أن تتمكن من فك التشفير. مع الكتل قد تقول 4 أو 5 وقد تحتاج إلى تخزين مؤقت يصل إلى 16 بايت لضمان كتل المنافسة.

Drawaes 16k لا يزال ثابتًا وليس ضخمًا. هل يحدث فرق كبير في هذا السياق؟

نعم ، هذا يعني نسخة أخرى قيد الإعداد. هذا له تأثير كبير وقابل للقياس على الأداء.

ما هو المطلوب لتحقيق ذلك؟ ما هي الخطوات التالية؟ تضمين التغريدة

بالنسبة إلى AES-GCM ، أعتقد أن تسليمها ضعيف بسبب إغلاق المشكلة المقابلة: https://github.com/dotnet/corefx/issues/7023. blowdart ، هل يمكنك فتح؟ من الصعب حقًا إحراز تقدم عندما لا يستطيع الناس المناقشة. أو ، إذا لم يكن هذا خيارًا ، فربما تقترح حلاً بديلاً يسمح بإحضار هذه الميزة إلى الجمهور.

لا ، أنا لا أقوم بإلغاء قفل ذلك. تم اتخاذ القرار ، تم الانتهاء من الموضوع.

blowdart شكرا على الرد. أفهم أنه ربما لم يكن هذا واضحًا بما يكفي:

أو ، إذا لم يكن هذا خيارًا ، فربما تقترح حلاً بديلاً يسمح بإحضار هذه الميزة إلى الجمهور.

أقدر أن هناك قرارًا لدعم AES-GCM. هذا رائع ، أنا بالتأكيد أريد تلك الخوارزمية. وبالتالي ، سيكون من الرائع الآن أن يتم دعمها بالفعل. هل ترغب في إجراء مناقشة حول تصميم وتنفيذ AES-GCM هنا أم في إصدار جديد؟

أيضًا ، إذا تم الانتهاء من هذا الموضوع ، فلماذا لا يتم إغلاقه؟ واجعلها أكثر وضوحًا من خلال تغيير عنوان هذه المشكلة ، حيث تشير الآن إلى أن المناقشة حول التنفيذ ستعقد هنا: https://github.com/dotnet/corefx/issues/7023. ربما شيء مثل تحديد خوارزمية AEAD التي يجب دعمها أولاً .

بمعنى آخر: أقدم ملاحظاتي بأنه في الوضع الحالي ليس من الواضح ما هو المطلوب لدفع AES-GCM إلى الأمام.

تضمين التغريدة

pgolebiowski هناك بالفعل علاقات عامة خارج. من المحتمل أن يكون متاحًا في الماجستير الأربعاء الأسبوع المقبل.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

omajid picture omajid  ·  3تعليقات

aggieben picture aggieben  ·  3تعليقات

yahorsi picture yahorsi  ·  3تعليقات

jzabroski picture jzabroski  ·  3تعليقات

EgorBo picture EgorBo  ·  3تعليقات