En Habré hay un magnífico artículo "
Escape from Crypto Pro. Versión del director, edición SMEV ", pero llegó el año 2019 y todas las AC comenzaron a emitir firmas digitales de acuerdo con GOST 34.10-2012 en lugar de GOST 34.10-2001.
Debajo del corte, una historia sobre cómo puede modificar su software en Bouncy Castle para apoyar el trabajo con claves para nuevos invitados.

Descargo de responsabilidad
No sé nada sobre las complejidades legales de firmar documentos a través de Bouncy Castle y otros sistemas de protección de información criptográfica y no estoy listo para comunicarme. Antes de usar el código en producción, consulte con un abogado.
¿Por qué es esto necesario? Artículo original bien escrito. No me repetiré
Obteniendo una llave del Token

Todas las CA que conozco emiten claves con certificados en tokens similares. El contenedor cryptoPro con la clave privada y el certificado está escrito en el token. Al exportar una clave a través de CryptoPro CSP, se exporta a un "CryptoPro pfx" especial que no es compatible con nada.
Las solicitudes para emitir una clave en un pfx estándar o cualquier otro contenedor CA típico se ignoran.
Si alguien conoce la CA que emite firmas en contenedores estándar, comparta las coordenadas en los comentarios. Las buenas personas no se avergüenzan de promover.Para convertir el contenedor CryptoPro a pfx estándar, nosotros, como en el artículo original, usaremos P12FromGostCSP. Las versiones pirateadas antiguas no funcionan con claves para 2012 Gost. Vamos al
sitio web de los autores y compramos uno nuevo.
Entonces obtuvimos el pfx estándar con la clave y el certificado.
Actualización del castillo hinchableActualizamos Bouncy Castle a 1.60. Las versiones anteriores pueden no ser compatibles con los algoritmos 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>
Inicializando el castillo hinchable static { BouncyCastleProvider bcProvider = new BouncyCastleProvider(); String name = bcProvider.getName(); Security.removeProvider(name);
Análisis de 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); } }
Los alias deben ser cambiados. La utilidad P12FromGostCSP siempre establece el mismo alias "csp_exported" y habrá problemas al procesar la segunda clave.
Para mayor comodidad, la clave de pfx debe cargarse en el Java KeyStore estándar y luego trabajar solo con ella.
Descargar KeyStore FileInputStream is = new FileInputStream(keystorePath); keystore = KeyStore.getInstance(KeyStore.getDefaultType()); char[] passwd = keystorePassword.toCharArray(); keystore.load(is, passwd);
Guardar una clave con un certificado en 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(); } }
Descargue claves y certificados de 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);
Firma de archivo 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();
Hay una opción JcaContentSignerBuilder ("GOST3411WITHECGOST3410-2012-512") para claves de 512 bits. Mis CA emiten 256 bits sin hacer nada e ignoran las preguntas aclaratorias.
Verificación de firma byte[] data = ...;
La verificación de firma es completamente similar a la verificación GOST de 2001. No puedes cambiar nada.
Resumen
Como resultado de todas las acciones anteriores, obtuvimos una forma relativamente fácil de deshacernos de la gran carga de Crypto Pro en 2019.