سؤال

لدي تطبيق C/C++ وأحتاج إلى إنشاء شهادة X509 pem تحتوي على مفتاح عام وخاص.يمكن أن تكون الشهادة موقعة ذاتيًا، أو غير موقعة، لا يهم.

أريد أن أفعل ذلك داخل التطبيق، وليس من سطر الأوامر.

ما هي وظائف OpenSSL التي ستفعل ذلك من أجلي؟أي رمز عينة هو مكافأة!

هل كانت مفيدة؟

المحلول

وأنت بحاجة للتعرف على نفسك مع المصطلحات وآليات أولا.

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

في أي حال، سوف تحتاج إلى استدعاء 20+ وظائف مختلفة من API بينسل لإنشاء مفتاح وشهادة موقعة ذاتيا. مثال على ذلك هو في مصدر بينسل نفسها، في <وأ href = "http://www.opensource.apple.com/source/OpenSSL/OpenSSL-22/openssl/demos/x509/mkcert.c" يختلط = "noreferrer" > العروض / X509 / mkcert.c

لإجابة أكثر تفصيلا، يرجى الاطلاع على الشرح href="https://stackoverflow.com/a/15082282/2387465"> أدناه.

نصائح أخرى

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

وهو استعار الكثير من ما سوف تقرأ أقل من <لأ href = "http://www.opensource.apple.com/source/OpenSSL/OpenSSL-22/openssl/demos/x509/mkcert.c" يختلط = "noreferrer"> هذا العرض و مستندات بينسل. ينطبق رمز أدناه إلى كل من C و C ++.


وقبل أن نتمكن فعلا إنشاء شهادة، نحن بحاجة إلى إنشاء مفتاح خاص. يوفر بينسل هيكل EVP_PKEY لتخزين على مفتاح خاص مستقلة الخوارزمية في الذاكرة. وأعلن هذا الهيكل في openssl/evp.h لكن يتم تضمين بواسطة openssl/x509.h (التي سنحتاج لاحقا) حتى لا تحتاج لتشمل صراحة رأس حقا.

في أجل تخصيص بنية EVP_PKEY، ونحن نستخدم EVP_PKEY_new :

EVP_PKEY * pkey;
pkey = EVP_PKEY_new();

وهناك أيضا وظيفة المقابلة لتحرير هيكل - EVP_PKEY_free - التي تقبل حجة واحدة: هيكل EVP_PKEY تهيئة أعلى

والآن نحن بحاجة لإنشاء مفتاح. على سبيل المثال، فإننا سوف إنشاء مفتاح RSA. ويتم ذلك مع وظيفة RSA_generate_key الذي أعلن في openssl/rsa.h. هذه الدالة تقوم بإرجاع مؤشر إلى بنية RSA.

وهناك احتجاج بسيط من وظيفة قد تبدو هذه:

RSA * rsa;
rsa = RSA_generate_key(
    2048,   /* number of bits for the key - 2048 is a sensible value */
    RSA_F4, /* exponent - RSA_F4 is defined as 0x10001L */
    NULL,   /* callback - can be NULL if we aren't displaying progress */
    NULL    /* callback argument - not needed in this case */
);

وإذا كانت قيمة الإرجاع من RSA_generate_key هي NULL، ثم ذهب شيئا خاطئا. إذا لم يكن كذلك، ثم لدينا الآن مفتاح RSA، ويمكننا إسناد ذلك إلى بنية EVP_PKEY لدينا في وقت سابق من:

EVP_PKEY_assign_RSA(pkey, rsa);

وسيتم الافراج عن هيكل RSA تلقائيا عندما يتم تحرير بنية EVP_PKEY.


والآن للحصول على شهادة في حد ذاته.

وبينسل يستخدم هيكل X509 لتمثيل شهادة X509 في الذاكرة. تعريف لهذه البنية في openssl/x509.h. الوظيفة الأولى نحن نذهب إلى تحتاجه هو X509_new . استخدامه هو بسيط نسبيا:

X509 * x509;
x509 = X509_new();

وكما كان الحال مع EVP_PKEY، هناك وظيفة المقابلة لتحرير هيكل - X509_free

والآن نحن بحاجة إلى تحديد بعض خصائص الشهادة باستخدام بعض الوظائف X509_*:

ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);

وهذا يضع الرقم التسلسلي للشهادة لدينا إلى '1'. بعض ملقمات HTTP مفتوحة المصدر ترفض قبول شهادة مع الرقم التسلسلي لل'0'، الذي هو الافتراضي. الخطوة التالية هي تحديد فترة زمنية خلالها الشهادة صالحة فعلا. ونحن نفعل ذلك مع المكالمتين وظيفة التالية:

X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);

والسطر الأول يحدد الملكية notBefore الشهادة إلى الوقت الحالي. (وظيفة X509_gmtime_adj يضيف عدد محدد من الثواني إلى الوقت الحالي - في هذه الحالة لا شيء.) السطر الثاني يحدد الملكية notAfter الشهادة إلى 365 يوما من الآن (60 ثانية * 60 دقيقة * 24 ساعة * 365 يوما)

والآن نحن بحاجة إلى تعيين المفتاح العمومي للشهادة لدينا باستخدام مفتاح ولدت لنا في وقت سابق:

X509_set_pubkey(x509, pkey);

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

X509_NAME * name;
name = X509_get_subject_name(x509);

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

X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
                           (unsigned char *)"CA", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_ASC,
                           (unsigned char *)"MyCompany Inc.", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
                           (unsigned char *)"localhost", -1, -1, 0);

و(أنا باستخدام قيمة 'CA 'هنا لأنني الكندية وهذا هو رمز البلد لدينا. لاحظ أيضا أن المعلمة # 4 احتياجات أن يلقي صراحة إلى unsigned char *).

والآن يمكننا فعلا تعيين اسم المصدر:

X509_set_issuer_name(x509, name);

وأخيرا نحن على استعداد لتنفيذ عملية التوقيع. ونحن ندعو X509_sign مع مفتاح ولدت لنا في وقت سابق. رمز في ذلك بسيط مؤلم:

X509_sign(x509, pkey, EVP_sha1());

لاحظ أننا تستخدم SHA-1 تجزئة خوارزمية التوقيع على المفتاح. وهذا يختلف عن التجريبي mkcert.c ذكرتها في بداية هذه الإجابة، والذي يستخدم MD5.


ونحن الآن لدينا شهادة موقعة ذاتيا! لكننا لم تفعل حتى الآن - ونحن بحاجة لكتابة هذه الملفات إلى القرص. الحمد لله بينسل تمت تغطيها لنا هناك أيضا مع وظائف PEM_* التي تم تعريفها في openssl/pem.h. وPEM_write_PrivateKey أول واحد سوف نحتاج لحفظ المفتاح الخاص لدينا.

FILE * f;
f = fopen("key.pem", "wb");
PEM_write_PrivateKey(
    f,                  /* write the key to the file we've opened */
    pkey,               /* our key from earlier */
    EVP_des_ede3_cbc(), /* default cipher for encrypting the key on disk */
    "replace_me",       /* passphrase required for decrypting the key on disk */
    10,                 /* length of the passphrase string */
    NULL,               /* callback for requesting a password */
    NULL                /* data to pass to the callback */
);

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

يا للعجب! نحن الآن وصولا الى وظيفة واحدة - ونحن بحاجة لكتابة شهادة إلى القرص. وظيفة نحتاج لذلك هو PEM_write_X509:

FILE * f;
f = fopen("cert.pem", "wb");
PEM_write_X509(
    f,   /* write the certificate to the file we've opened */
    x509 /* our certificate */
);

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

للراغبين في رؤية كل ما من قانون تبدو فوق كما هو الحال في تطبيق حقيقي، لقد القيت معا جست (مكتوب في C ++) التي يمكنك عرض على هنا .

أي فرصة للقيام بذلك عبر أ system الاتصال من داخل التطبيق الخاص بك؟عدة أسباب وجيهة للقيام بذلك:

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

  • توثيق:يأتي OpenSSL مع هائل وثائق سطر الأوامر التي تبسط إلى حد كبير أداة يحتمل أن تكون معقدة.

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

إذا اخترت استخدام واجهة برمجة التطبيقات (API)، فتحقق من openssl-dev قائمة المطورين على www.openssl.org.

حظ سعيد!

وتعليمي بسيط جدا لخلق الشهادات الرقمية <لأ href = "http://publib.boulder.ibm.com/infocenter/rsthelp/v8r0m0/index.jsp؟topic=/com.ibm.rational.test.lt. وثيقة / المواضيع / tcreatecertopenssl.html "يختلط =" نوفولو "> http://publib.boulder.ibm.com/infocenter/rsthelp/v8r0m0/index.jsp؟topic=/com.ibm.rational.test.lt.doc /topics/tcreatecertopenssl.html

وعن تنفيذ هذه الأوامر من التعليمات البرمجية لست متأكدا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top