Em Habré, há um artigo magnífico "
Escape from Crypto Pro. Versão do diretor, edição SMEV ", mas chegou o ano de 2019 e todas as CAs começaram a emitir assinaturas digitais de acordo com GOST 34.10-2012, em vez de GOST 34.10-2001.
Abaixo, uma história sobre como você pode modificar seu software no Bouncy Castle para dar suporte ao trabalho com chaves para novos convidados.

Isenção de responsabilidade
Não sei nada sobre os meandros legais da assinatura de documentos por meio do Bouncy Castle e outros sistemas de proteção de informações criptográficas e não estou pronto para me comunicar. Antes de usar o código na produção, consulte um advogado.
Por que isso é necessário? artigo original bem escrito. Eu não vou me repetir.
Obtendo uma chave do token

Todas as CAs conhecidas por mim emitem chaves com certificados em tokens semelhantes. O contêiner cryptoPro com a chave privada e o certificado está gravado no token. Ao exportar uma chave pelo CryptoPro CSP, ela é exportada para um "CryptoPro pfx" especial que não é compatível com nada.
Solicitações para emitir uma chave em um pfx padrão ou em qualquer outro contêiner de CA típico são ignoradas.
Se alguém souber que a CA está emitindo assinaturas em contêineres padrão, compartilhe as coordenadas nos comentários. Boas pessoas não têm vergonha de promover.Para converter o contêiner CryptoPro em pfx padrão, nós, como no artigo original, usaremos P12FromGostCSP. As versões hackeadas antigas não funcionam com chaves para o Gost de 2012. Vamos ao
site dos autores e compramos um novo.
Portanto, obtivemos o PFX padrão com a chave e o certificado.
Atualização do castelo insuflávelAtualizamos o Bouncy Castle para 1,60. As versões mais antigas podem não suportar os 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 o Castelo Saltitante static { BouncyCastleProvider bcProvider = new BouncyCastleProvider(); String name = bcProvider.getName(); Security.removeProvider(name);
Análise 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); } }
Os aliases devem ser alterados. O utilitário P12FromGostCSP sempre define o mesmo alias "csp_exported" e haverá problemas ao processar a segunda chave.
Por conveniência, a chave do pfx deve ser carregada no Java KeyStore padrão e, em seguida, trabalhar apenas com ela.
Baixar KeyStore FileInputStream is = new FileInputStream(keystorePath); keystore = KeyStore.getInstance(KeyStore.getDefaultType()); char[] passwd = keystorePassword.toCharArray(); keystore.load(is, passwd);
Salvando uma chave com um certificado no 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(); } }
Baixe chaves e certificados do 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);
Assinatura de arquivo 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();
Existe uma opção JcaContentSignerBuilder ("GOST3411WITHECGOST3410-2012-512") para chaves de 512 bits. Minhas CAs emitem as de 256 bits sem fazer nada e ignoram as perguntas de esclarecimento.
Verificação de Assinatura byte[] data = ...;
A verificação de assinatura é completamente semelhante à verificação GOST de 2001. Você não pode mudar nada.
Sumário
Como resultado de todas as ações acima, temos uma maneira relativamente fácil de se livrar da carga pesada do Crypto Pro em 2019.