Melarikan diri dari Crypto Pro. Edisi GOST 34.10-2012

Di Habré ada artikel yang luar biasa " Escape from Crypto Pro. Versi sutradara, SMEV-edisi ", tetapi tahun 2019 datang dan semua CA mulai mengeluarkan tanda tangan digital sesuai dengan GOST 34.10-2012 alih-alih GOST 34.10-2001.

Di bawah potongan, sebuah cerita tentang bagaimana Anda dapat memodifikasi perangkat lunak Anda di Bouncy Castle untuk mendukung bekerja dengan kunci untuk tamu baru.

gambar

Penafian


Saya tidak tahu apa-apa tentang seluk-beluk hukum penandatanganan dokumen melalui Bouncy Castle dan sistem perlindungan informasi kriptografis lainnya dan saya tidak siap untuk berkomunikasi. Sebelum menggunakan kode dalam produksi, berkonsultasilah dengan pengacara.

Mengapa ini perlu? artikel asli yang ditulis dengan baik. Saya tidak akan mengulangi lagi.

Mendapatkan kunci dari Token


gambar

Semua CA yang saya kenal mengeluarkan kunci dengan sertifikat pada token yang serupa. Kontainer cryptoPro dengan kunci pribadi dan sertifikat tertulis di token. Ketika mengekspor kunci melalui CryptoPro CSP, itu diekspor ke "CryptoPro pfx" khusus yang tidak kompatibel dengan apa pun.

Permintaan untuk mengeluarkan kunci dalam pfx standar atau wadah CA lainnya diabaikan.
Jika ada yang tahu CA mengeluarkan tanda tangan dalam wadah standar, bagikan koordinat dalam komentar. Orang baik tidak malu untuk berpromosi.

Untuk mengonversi wadah CryptoPro ke pfx standar, kami, seperti pada artikel asli, akan menggunakan P12FromGostCSP. Versi yang diretas lama tidak berfungsi dengan kunci untuk 2012 Gost. Kami pergi ke situs web penulis dan membeli yang baru.

Jadi kami mendapat pfx standar dengan kunci dan sertifikat.

Pembaruan Istana Goyang

Kami memperbarui Bouncy Castle ke 1.60 Versi yang lebih lama mungkin tidak mendukung algoritma 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> 

Menginisialisasi Bouncy Castle

  static { BouncyCastleProvider bcProvider = new BouncyCastleProvider(); String name = bcProvider.getName(); Security.removeProvider(name); // remove old instance Security.addProvider(bcProvider); } 

Penguraian 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); } } 

Alias ​​harus diubah. Utilitas P12FromGostCSP selalu menetapkan alias yang sama "csp_exported" dan akan ada masalah saat memproses kunci kedua.

Untuk kenyamanan, kunci dari pfx harus dimuat ke dalam Java KeyStore standar dan kemudian hanya bekerja dengannya.

Unduh KeyStore

 FileInputStream is = new FileInputStream(keystorePath); keystore = KeyStore.getInstance(KeyStore.getDefaultType()); char[] passwd = keystorePassword.toCharArray(); keystore.load(is, passwd); 

Menyimpan kunci dengan sertifikat di 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(); } } 

Unduh kunci dan sertifikat dari 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); //any key,value collection Certificate certificate = keystore.getCertificate(alias); if (certificate instanceof X509Certificate) certificates.put(alias.toLowerCase(), (X509Certificate) certificate); //any key,value collection } } 

Arsip tanda tangan

 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(); //result here 

Ada opsi JcaContentSignerBuilder ("GOST3411WITHECGOST3410-2012-512") untuk kunci 512 bit. CA saya mengeluarkan 256 bit tanpa meminta apa pun dan mengabaikan pertanyaan klarifikasi.

Verifikasi Tanda Tangan

 byte[] data = ...; //signed file data byte[] signature = ...;//signature boolean checkResult = false; CMSProcessable signedContent = new CMSProcessableByteArray(data); CMSSignedData signedData; try { signedData = new CMSSignedData(signedContent, signature); } catch (CMSException e) { return SIGNATURE_STATUS.ERROR; } SignerInformation signer; try { Store<X509CertificateHolder> certStoreInSing = signedData.getCertificates(); signer = signedData.getSignerInfos().getSigners().iterator().next(); Collection certCollection = certStoreInSing.getMatches(signer.getSID()); Iterator certIt = certCollection.iterator(); X509CertificateHolder certHolder = (X509CertificateHolder) certIt.next(); X509Certificate certificate = new JcaX509CertificateConverter().getCertificate(certHolder); checkResult = signer.verify(new JcaSimpleSignerInfoVerifierBuilder().build(certificate)); } catch (Exception ex) { return SIGNATURE_STATUS.ERROR; } 

Verifikasi tanda tangan sangat mirip dengan verifikasi GOST 2001. Anda tidak dapat mengubah apa pun.

Ringkasan


Sebagai hasil dari semua tindakan di atas, kami mendapat cara yang relatif mudah untuk menyingkirkan beban berat Crypto Pro pada tahun 2019.

Source: https://habr.com/ru/post/id440882/


All Articles