هذه مكتبة لتبسيط إرسال رسائل الدفع المشفرة من طرف إلى طرف (E2E) من خوادم التطبيق المستندة إلى Java إلى عملاء Android. يرجى التحقق من التعليمات أدناه والتوضيح لمزيد من التفاصيل.
لإضافة تبعية باستخدام Maven:
لخادم قائم على جافا:
< dependency >
< groupId >com.google.capillary</ groupId >
< artifactId >lib</ artifactId >
< version >1.0.0</ version >
</ dependency >
لنظام Android:
< dependency >
< groupId >com.google.capillary</ groupId >
< artifactId >lib-android</ artifactId >
< version >1.0.0</ version >
</ dependency >
لإضافة تبعية باستخدام Gradle:
dependencies {
compile 'com.google.capillary:lib:1.0.0'
}
dependencies {
compile 'com.google.capillary:lib-android:1.0.0'
}
لاستخدام خدمات المراسلة الدفع لإرسال الرسائل إلى الأجهزة المتصلة ، يجب على المطورين إرسالها من خلال خدمة مراسلة من طرف ثالث ، مثل Firebase Cloud Messaging (FCM). من السهل تشفير محتويات الرسائل بين المطور وخدمة المراسلة باستخدام HTTPS. تعمل خدمات المراسلة الرئيسية ، بما في ذلك FCM ، على تشفير الرسائل بين خوادمها وأجهزة العملاء.
ومع ذلك ، لا يتم تشفير الرسائل بين خادم المطورين وأجهزة المستخدم من طرف إلى طرف (E2E):
يمكن تحقيق تشفير E2E من خلال إنشاء زوج مفتاح تشفير غير متماثل على العميل ، وتسجيل المفتاح العام مع خدمة المراسلة المطورين ، وتشفير الرسائل الصادرة مع المفتاح العام ، وفك تشفير الرسائل على العميل باستخدام المفتاح الخاص:
تعامل الشعيرات الدموية هذه العمليات لخدمات الرسائل التي تستخدمها تطبيقات Android. ويشمل:
وظائف التشفير والإدارة الرئيسية عبر جميع إصدارات Android إلى KitKat (API Level 19).
توليد المفاتيح وتسجيل سير العمل.
تشفير الرسائل (على الخادم) وفك التشفير (على العميل).
حماية النزاهة لمنع تعديل الرسائل.
حركات الحافة ، مثل المستخدمين إضافة/إعادة ضبط قفل الجهاز بعد تثبيت التطبيق ، إعادة تعيين المستخدمين تخزين التطبيق ، إلخ.
كمكافأة ، فإنه يتيح أيضًا للمطورين مطالبة أن يتم فتح الأجهزة قبل أن يتم فك تشفير الرسائل المحددة. يتضمن ذلك رسائل على الأجهزة التي تستخدم التشفير المستندة إلى الملف (FBE): يتم تخزين الرسائل المشفرة في مخزنة في مفاتيح التخزين المشفرة (DE) ومفاتيح فك تشفير الرسائل في Android Keystore التي تتطلب مصادقة المستخدم. يتيح ذلك للمطورين تحديد الرسائل ذات المحتوى الحساس للبقاء مشفرة في شكل مخبأة حتى يقوم المستخدم بإلغاء تأمين أجهزتهم وفك تشفيرها.
دفع الويب
PRO: يتبع IETF RFC 8291 ، وبالتالي يتيح للمطورين مشاركة الكود والبنية التحتية للتخزين الرئيسية مع تطبيقات الدفع على الويب الحالية. يعتمد بروتوكول دفع الويب على خوارزمية التبادل المفتاحية للتبادل الإهليلجي (ECDH) ، والتي تعتبر فعالة للغاية للأجهزة المقيدة بالأداء. لاحظ أن التطبيقات (على عكس المتصفحات) لا يمكن أن تتلقى رسائل الدفع الخام من خلال FCM ، ولكن يمكن بسهولة لف رسائل دفع الويب في FCM JSON المناسبة من خلال تطبيق وكيل ، مما يتيح لك استخدام نفس البنية التحتية مع تعديلات بسيطة.
CON: Android Keystore لا يدعم عمليات ECDH الرئيسية. المفاتيح محفوظة الهجينة مع مفتاح RSA المخزّن في Keystore مما يعني أن النص Plainte-ex المتوفر في ذاكرة المستخدم أثناء عمليات التشفير.
RSA-ECDSA
PRO: incrypts hybrid a رسالة مع مفتاح RSA العمومي الذي تم إنشاؤه بواسطة العميل (من أجل السرية) ويوقع على النص المشفر مع مفتاح Public ECDSA الذي تم إنشاؤه بواسطة المطور (من أجل النزاهة). يتم دعم عمليات RSA Crypto (Encrypt ، decrypt) بواسطة Android Keystore من إصدارات SDK 18 (Jelly Bean) وما فوق ، مما يعني أن المواد الرئيسية غير متوفرة خارج بيئة التنفيذ الموثوق بها. هذا يعني أنه لا يمكن للمهاجم المتطور الذي يمكنه الوصول إلى ذاكرة الجهاز الوصول إلى المواد الرئيسية الخاصة (على سبيل المثال ، لفك تشفير الرسائل المستقبلية التي تصل في وضع التمهيد المباشر).
CON: أقل كفاءة من ECDH والمفاتيح غير متوافقة مع معيار مراسلة دفع الويب.
يضمن المستخدمون مفاتيح Auth Bound أنه لا يمكن قراءة الرسائل من قبل المستخدمين عند قفل أجهزتهم ، مما يعني أن المحتوى الحساس لن يتم قراءته بواسطة أجهزة الكتف أو إذا فقد الجهاز أو سرقته.
يوفر Capillary وظائف التشفير الأساسية المطلوبة للإرسال (من خادم التطبيق) واستلام رسائل الدفع المشفرة في تطبيقات Android. هذا يغطي:
توليد وتخزين المفاتيح على العميل.
تشفير وتوقيع الرسائل على الخادم.
فك تشفير الرسائل المشفرة والتحقق منها على العميل.
تحديد الرسائل المشفرة التي يجب تخزينها لاحقًا إذا تم استلامها أثناء قفل الجهاز.
نظرًا لأن البنية من جانب الخادم ودفعات استخدام الرسائل كثيرة ومتنوعة ، فليس من العملي توفير واجهة برمجة تطبيقات من جانب الخادم للتعامل مع جميع تطبيقات رسائل الدفع الممكنة. لذلك ، قمنا بفصل وظيفة التشفير أعلاه من نقل الرسائل ووظائف تخزين/استرجاع مفتاح الخادم. ومع ذلك ، فقد قدمنا تطبيقًا كاملًا يستخدم الشعيرات الدموية لإرسال رسائل دفع e2E من الخادم المستند إلى Java إلى عملاء Android في التطبيق التجريبي. باختصار ، ستحتاج إلى تنفيذ الجوانب التالية من الحل بنفسك (باستخدام التطبيق التجريبي والتعليمات أدناه للحصول على التوجيه عند الاقتضاء):
يرجى اتباع الخطوات التالية للاندماج مع مكتبة الشعيرات الدموية.
قبل استخدام مكتبة الشعيرات الدموية ، يجب تهيئتها في وقت التشغيل على النحو التالي:
import com . google . capillary . Config ;
Config . initialize ();
إذا كنت تستخدم خوارزمية RSA-ECDSA ، فأنت بحاجة إلى إنشاء زوج مفتاح عام/خاص ECDSA وجعل المفتاح العام متاحًا لتطبيق Android الخاص بك (على سبيل المثال ، كمورد خام) ومفتاح خاص متاح لخادم التطبيق الخاص بك. استخدم برنامج الأداة المساعدة التي قدمناها لإنشاء أزواج مفتاح ECDSA هذه:
$ ./gradlew tools:installDist
$ ./tools/build/install/tools/bin/ecdsa-key-pair-generator
> --ecdsa_public_key_path= < path to new public key >
> --ecdsa_private_key_path= < path to new private key >
تستخدم مكتبة الشعيرات الدموية أساليب واجهة CapillaryHandler
لتوفير ردود ، مثل المفاتيح العامة ، وملفات فك التشفير ، وما إلى ذلك ، إلى تطبيق Android. لذلك ، فإن الخطوة الأولى في دمج تطبيق Android مع مكتبة الشعيرات الدموية هي تنفيذ واجهة CapillaryHandler
مع منطق التطبيق الخاص بك للتعامل مع الاستجابات المذكورة أعلاه. يمكنك أن ترى كيف يبرز تطبيق Android التجريبي التابع لمكتبة الشعرية واجهة CapillaryHandler
في فئة DemoCapillaryHandler
.
يتم تحديد كل زوج مفتاح شعري بواسطة معرف زوج المفاتيح (ويعرف أيضًا باسم معرف سلسلة المفاتيح) ، وهو سلسلة تعسفية متروك لك لتقريره. لإنشاء زوج مفتاح:
import android . content . Context ;
import com . google . capillary . android . RsaEcdsaKeyManager ;
import com . google . capillary . android . WebPushKeyManager ;
import java . io . InputStream ;
Context context = ... // The current app context.
String keychainId = ... // Some identifier for the key pair.
boolean isAuth = ... // Whether the private key usage should be guarded by the device lock.
// To generate an RSA-ECDSA key pair.
InputStream senderVerificationKey = ... // The ECDSA public key of the server.
RsaEcdsaKeyManager . getInstance ( context , keychainId , senderVerificationKey ). generateKeyPair ( isAuth );
// To generate a Web Push key pair.
WebPushKeyManager . getInstance ( context , keychainId ). generateKeyPair ( isAuth );
هناك أيضًا طريقة commeratekeypairs لإنشاء مفاتيح Auth و Noauth في مكالمة طريقة واحدة.
بعد إنشاء زوج مفتاح شعري ، يمكنك استرداد المفتاح العام الذي تم إنشاؤه في صفيف البايت على النحو التالي:
import android . content . Context ;
import com . google . capillary . android . CapillaryHandler ;
import com . google . capillary . android . RsaEcdsaKeyManager ;
import com . google . capillary . android . WebPushKeyManager ;
import java . io . InputStream ;
Context context = ... // The current app context.
String keychainId = ... // The identifier for the key pair.
boolean isAuth = ... // Whether the private key usage is guarded by the device lock.
CapillaryHandler handler = ... // An implementation of CapillaryHandler interface.
Object extra = ... // Any extra information to be passed back to the handler.
// To obtain an RSA-ECDSA public key.
InputStream senderVerificationKey = ... // The ECDSA public key of the server.
RsaEcdsaKeyManager . getInstance ( context , keychainId , senderVerificationKey )
. getPublicKey ( isAuth , handler , extra );
// To obtain a Web Push public key.
WebPushKeyManager . getInstance ( context , keychainId ). getPublicKey ( isAuth , handler , extra );
// The Capillary library returns a byte array representing the Capillary public key via the
// handlePublicKey method of the CapillaryHandler instance.
بعد تلقي نص مشفر تم إنشاؤه باستخدام مفتاح شعري عام ، يمكنك فك تشفيره على النحو التالي:
import android . content . Context ;
import com . google . capillary . android . CapillaryHandler ;
import com . google . capillary . android . RsaEcdsaKeyManager ;
import com . google . capillary . android . WebPushKeyManager ;
import java . io . InputStream ;
byte [] ciphertext = ... // The ciphertext received through FCM.
Context context = ... // The current app context.
String keychainId = ... // The identifier for the key pair.
CapillaryHandler handler = ... // An implementation of CapillaryHandler interface.
Object extra = ... // Any extra information to be passed back to the handler.
// To decrypt a ciphertext and pass the plaintext to the CapillaryHandler instance,
// (e.g. for display to the user):
// For RSA-ECDSA:
InputStream senderVerificationKey = ... // The ECDSA public key of the server.
RsaEcdsaKeyManager . getInstance ( context , keychainId , senderVerificationKey )
. getDecrypterManager (). decrypt ( ciphertext , handler , extra );
// For Web Push:
WebPushKeyManager . getInstance ( context , keychainId )
. getDecrypterManager (). decrypt ( ciphertext , handler , extra );
// The Capillary library returns a byte array representing the plaintext via the handleData
// method of the CapillaryHandler instance.
ضع في اعتبارك أنه أثناء فك التشفير ، قد تعيد مكتبة الشعيرات الدموية تلقائيًا تلقائيًا أزواج المفاتيح الشعرية الأساسية إذا كانت هذه الأزواج الرئيسية تالفة بشكل لا يمكن الاسترداد ، والتي يمكن أن تحدث ، على سبيل المثال ، عندما يضيف المستخدم/يعيد تعيين قفل الجهاز ، وإعادة تعيين تخزين التطبيق ، إلخ CapillaryHandler
إذا تم إنشاء النص المشفر باستخدام مفتاح AUTH ولكن جهاز Android في سياق غير مصحيح ، فإن مكتبة الشعيرات الدموية تنقذ داخليًا النص المشفر ليتم فك تشفيرها لاحقًا وإبلاغ تطبيق Android عبر طريقة AuthCipherTextSavedforlater. يتيح ذلك لتطبيق Android التعامل مع الشفرات المخزنة مؤقتًا ، على سبيل المثال ، عن طريق إخبار رسائل المستخدم تتوفر عند إلغاء القفل. عند فتح المستخدم للجهاز ، يمكنك أن تتفكك مكتبة الشعيرات الدموية أي تشفير محفوظ على النحو التالي:
import android . content . Context ;
import com . google . capillary . android . CapillaryHandler ;
import com . google . capillary . android . RsaEcdsaKeyManager ;
import com . google . capillary . android . WebPushKeyManager ;
import java . io . InputStream ;
Context context = ... // The current app context.
String keychainId = ... // The identifier for the key pair.
CapillaryHandler handler = ... // An implementation of CapillaryHandler interface.
Object extra = ... // Any extra information to be passed back to the handler.
// To decrypt saved ciphertexts and pass the plaintexts to the CapillaryHandler instance,
// (e.g. for display to the user):
// For RSA-ECDSA:
InputStream senderVerificationKey = ... // The ECDSA public key of the server.
RsaEcdsaKeyManager . getInstance ( context , keychainId , senderVerificationKey )
. getDecrypterManager (). decryptSaved ( handler , extra );
// For Web Push:
WebPushKeyManager . getInstance ( context , keychainId )
. getDecrypterManager (). decryptSaved ( handler , extra );
// For each decrypted ciphertext, the Capillary library returns a byte array representing the
// plaintext via the handleData method of the CapillaryHandler instance.
هناك عدة طرق لتشغيل معالج النص المشفر المخبأة عند فتح الجهاز. إن النهج الذي يستخدمه تطبيق Android التجريبي التابع لمكتبة الشعيرات الدموية هو الاستماع إلى نية البث Action_user_present. انظر DeviceUnlockedBroadcastReceiver
لمزيد من التفاصيل.
لحذف زوج مفتاح شعري:
import android . content . Context ;
import com . google . capillary . android . RsaEcdsaKeyManager ;
import com . google . capillary . android . WebPushKeyManager ;
import java . io . InputStream ;
Context context = ... // The current app context.
String keychainId = ... // The identifier for the key pair.
boolean isAuth = ... // Whether the private key usage is guarded by the device lock.
// To delete an RSA-ECDSA key pair.
InputStream senderVerificationKey = ... // The ECDSA public key of the server.
RsaEcdsaKeyManager . getInstance ( context , keychainId , senderVerificationKey ). deleteKeyPair ( isAuth );
// To delete a Web Push key pair.
WebPushKeyManager . getInstance ( context , keychainId ). deleteKeyPair ( isAuth );
توفر مكتبة الشعيرات الدموية الوظائف لتشفير الرسائل على خوادم التطبيق المستندة إلى Java.
لتشفير رسالة باستخدام مفتاح شعري عام:
import com . google . capillary . EncrypterManager ;
import com . google . capillary . RsaEcdsaEncrypterManager ;
import com . google . capillary . WebPushEncrypterManager ;
import java . io . InputStream ;
byte [] recipientPublicKey = ... // The Capillary public key of the client.
byte [] message = ... // The message to be sent to the client.
// To create an RSA-ECDSA ciphertext.
InputStream senderSigningKey = ... // The ECDSA private key of the server.
EncrypterManager rsaEcdsaEncrypterManager = new RsaEcdsaEncrypterManager ( senderSigningKey );
rsaEcdsaEncrypterManager . loadPublicKey ( recipientPublicKey );
byte [] ciphertext = rsaEcdsaEncrypterManager . encrypt ( message );
// This step is not strictly necessary, but it ensures that the EncrypterManager releases the
// stored public key for garbage collection.
rsaEcdsaEncrypterManager . clearPublicKey ();
// To create a Web Push ciphertext.
EncrypterManager webPushEncrypterManager = new WebPushEncrypterManager ();
webPushEncrypterManager . loadPublicKey ( recipientPublicKey );
byte [] ciphertext = webPushEncrypterManager . encrypt ( message );
webPushEncrypterManager . clearPublicKey ();
يتم الحفاظ على مكتبة الشعيرات الدموية من قبل googlers التالية: