يوجد على
Habré مقال رائع بعنوان "
Escape from Crypto Pro. إصدار المخرج ، SMEV-edition " ، لكن عام 2019 جاء وبدأت جميع CAs في إصدار التواقيع الرقمية وفقًا لـ GOST 34.10-2012 بدلاً من GOST 34.10-2001.
تحت القص ، قصة حول كيف يمكنك تعديل برنامجك على Bouncy Castle لدعم العمل مع مفاتيح للضيوف الجدد.

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

جميع المراجع المصدقة المعروفة لي تصدر مفاتيح بشهادات على رموز مشابهة. الحاوية cryptoPro مع المفتاح الخاص والشهادة مكتوبة على الرمز المميز. عند تصدير مفتاح من خلال CryptoPro CSP ، يتم تصديره إلى "CryptoPro pfx" خاص لا يتوافق مع أي شيء.
يتم تجاهل طلبات إصدار مفتاح في pfx قياسي أو أي حاوية CA نموذجية أخرى.
إذا كان أي شخص يعرف إصدار المرجع المصدق (CA) في حاويات قياسية ، شارك الإحداثيات في التعليقات. الناس الطيبين لا يخجلون من الترويج.لتحويل حاوية CryptoPro إلى pfx قياسي ، سنستخدم P12FromGostCSP ، كما في المقالة الأصلية. لا تعمل الإصدارات القديمة المخترقة مع مفاتيح لعام 2012 Gost. نذهب إلى
موقع المؤلفين وشراء واحدة جديدة.
لذلك حصلنا على pfx القياسية مع المفتاح والشهادة.
نطاط القلعة التحديثنقوم بتحديث Bouncy Castle إلى 1.60 قد لا تدعم الإصدارات الأقدم خوارزميات GOST 2012.
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.60</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.60</version> </dependency>
تهيئة نطاط القلعة static { BouncyCastleProvider bcProvider = new BouncyCastleProvider(); String name = bcProvider.getName(); Security.removeProvider(name);
Pfx تحليل KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC"); ByteArrayInputStream baos = new ByteArrayInputStream(pfxFileContent); keyStore.load(baos, password.toCharArray()); Enumeration<String> aliases = keyStore.aliases(); while (aliases.hasMoreElements()) { String alias = aliases.nextElement(); if (keyStore.isKeyEntry(alias )) { Key key = keyStore.getKey(alias , keyPassword.toCharArray()); java.security.cert.Certificate certificate = keyStore.getCertificate(alias ); addKeyAndCertificateToStore((PrivateKey)key, (X509Certificate)certificate); } }
يجب تغيير الأسماء المستعارة. تقوم الأداة المساعدة P12FromGostCSP دائمًا بتعيين الاسم المستعار نفسه "csp_exported" وستكون هناك مشكلات في معالجة المفتاح الثاني.
للراحة ، يجب تحميل المفتاح من pfx في Java KeyStore القياسي ومن ثم العمل معه فقط.
تحميل KeyStore FileInputStream is = new FileInputStream(keystorePath); keystore = KeyStore.getInstance(KeyStore.getDefaultType()); char[] passwd = keystorePassword.toCharArray(); keystore.load(is, passwd);
حفظ مفتاح مع شهادة في KeyStore public void addKeyAndCertificateToStore(PrivateKey key, X509Certificate certificate) { synchronized (this) { keystore.setKeyEntry(alias.toLowerCase(), key, keyPassword.toCharArray(), new X509Certificate[] {certificate}); FileOutputStream out = new FileOutputStream(keystorePath); keystore.store(out, keystorePassword.toCharArray()); out.close(); } }
قم بتنزيل المفاتيح والشهادات من KeyStore Enumeration<String> aliases = keystore.aliases(); while (aliases.hasMoreElements()) { String alias = aliases.nextElement(); if (keystore.isKeyEntry(alias)) { Key key = keystore.getKey(alias, keyPassword.toCharArray()); keys.put(alias.toLowerCase(), key);
توقيع الملف CMSProcessableByteArray msg = new CMSProcessableByteArray(dataToSign); List certList = new ArrayList(); certList.add(cert); Store certs = new JcaCertStore(certList); CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); ContentSigner signer = new org.bouncycastle.operator.jcajce.JcaContentSignerBuilder("GOST3411WITHECGOST3410-2012-256").setProvider("BC").build(privateKey); gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()).build(signer, certificate)); gen.addCertificates(certs); CMSSignedData sigData = gen.generate(msg, false); byte[] sign = sigData.getEncoded();
يوجد خيار JcaContentSignerBuilder ("GOST3411WITHECGOST3410-2012-512") لمفاتيح 512 بت. تصدر شهادات الاعتماد الخاصة بي 256 بت دون طرح أي شيء وتجاهل الأسئلة التوضيحية.
التحقق من التوقيع byte[] data = ...;
يشبه التحقق من التوقيع تمامًا التحقق من GOST لعام 2001. لا يمكنك تغيير أي شيء.
ملخص
نتيجة لجميع الإجراءات المذكورة أعلاه ، حصلنا على طريقة سهلة نسبيًا للتخلص من الحمل الثقيل لـ Crypto Pro في عام 2019.