Auf Habré gibt es einen großartigen Artikel "
Escape from Crypto Pro. Director's Version, SMEV-Edition ", aber das Jahr 2019 kam und alle Zertifizierungsstellen begannen, digitale Signaturen gemäß GOST 34.10-2012 anstelle von GOST 34.10-2001 herauszugeben.
Unter dem Schnitt eine Geschichte darüber, wie Sie Ihre Software auf Bouncy Castle ändern können, um die Arbeit mit Schlüsseln für neue Gäste zu unterstützen.

Haftungsausschluss
Ich weiß nichts über die rechtlichen Schwierigkeiten beim Signieren von Dokumenten über Bouncy Castle und andere kryptografische Informationsschutzsysteme und bin nicht bereit zu kommunizieren. Bevor Sie den Code in der Produktion verwenden, wenden Sie sich an einen Anwalt.
Warum ist das überhaupt notwendig? gut geschriebener Originalartikel. Ich werde mich nicht wiederholen.
Einen Schlüssel vom Token erhalten

Alle mir bekannten Zertifizierungsstellen stellen Schlüssel mit Zertifikaten für ähnliche Token aus. Der cryptoPro-Container mit dem privaten Schlüssel und dem Zertifikat wird auf das Token geschrieben. Beim Exportieren eines Schlüssels über CryptoPro CSP wird er in einen speziellen „CryptoPro pfx“ exportiert, der mit nichts kompatibel ist.
Anforderungen zur Ausgabe eines Schlüssels in einem Standard-Pfx oder einem anderen typischen CA-Container werden ignoriert.
Wenn jemand weiß, dass die Zertifizierungsstelle Signaturen in Standardcontainern ausgibt, teilen Sie die Koordinaten in den Kommentaren mit. Gute Leute schämen sich nicht zu fördern.Um den CryptoPro-Container in Standard-pfx zu konvertieren, verwenden wir wie im Originalartikel P12FromGostCSP. Alte gehackte Versionen funktionieren nicht mit Schlüsseln für 2012 Gost. Wir gehen zur
Website des Autors und kaufen eine neue.
Also haben wir den Standard-Pfx mit dem Schlüssel und dem Zertifikat bekommen.
Hüpfburg UpdateWir aktualisieren Bouncy Castle auf 1.60. Ältere Versionen unterstützen möglicherweise keine GOST 2012-Algorithmen.
<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>
Hüpfburg initialisieren static { BouncyCastleProvider bcProvider = new BouncyCastleProvider(); String name = bcProvider.getName(); Security.removeProvider(name);
Pfx-Analyse 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); } }
Aliase müssen geändert werden. Das Dienstprogramm P12FromGostCSP setzt immer den gleichen Alias "csp_exported", und es treten Probleme bei der Verarbeitung des zweiten Schlüssels auf.
Der Einfachheit halber muss der Schlüssel von pfx in den Standard-Java-KeyStore geladen werden und dann nur damit funktionieren.
Laden Sie den KeyStore herunter FileInputStream is = new FileInputStream(keystorePath); keystore = KeyStore.getInstance(KeyStore.getDefaultType()); char[] passwd = keystorePassword.toCharArray(); keystore.load(is, passwd);
Speichern eines Schlüssels mit einem Zertifikat im 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(); } }
Laden Sie Schlüssel und Zertifikate aus dem KeyStore herunter 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);
Dateisignatur 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();
Es gibt eine JcaContentSignerBuilder-Option ("GOST3411WITHECGOST3410-2012-512") für 512-Bit-Schlüssel. Meine Zertifizierungsstellen geben 256-Bit-Dateien aus, ohne etwas zu fragen, und ignorieren klärende Fragen.
Überprüfung der Unterschrift byte[] data = ...;
Die Signaturüberprüfung ähnelt vollständig der GOST-Überprüfung von 2001. Sie können nichts ändern.
Zusammenfassung
Als Ergebnis all der oben genannten Maßnahmen haben wir eine relativ einfache Möglichkeit gefunden, die schwere Last von Crypto Pro im Jahr 2019 loszuwerden.