/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * Copyright (c) 2013, MPL CodeInside http://codeinside.ru */ package ru.codeinside.gws.crypto.cryptopro; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import ru.codeinside.gws.api.Signature; import sun.security.pkcs.ContentInfo; import sun.security.pkcs.PKCS7; import sun.security.pkcs.ParsingException; import sun.security.pkcs.SignerInfo; import sun.security.util.DerOutputStream; import sun.security.util.ObjectIdentifier; import sun.security.x509.AlgorithmId; import sun.security.x509.X500Name; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.cert.X509Certificate; final public class SunPkcs7 { final static ObjectIdentifier GOST3410; final static ObjectIdentifier GOST3411; static { try { GOST3410 = new ObjectIdentifier("1.2.643.2.2.19"); GOST3411 = new ObjectIdentifier("1.2.643.2.2.9"); } catch (IOException e) { throw new IllegalStateException(e); } } final private static Log log = LogFactory.getLog(CryptoProvider.class); public static byte[] toPkcs7(final Signature signature) { final X509Certificate certificate = signature.certificate; final byte[] sign = signature.sign; X500Name issuer = X500Name.asX500Name(certificate.getIssuerX500Principal()); final AlgorithmId digestAlgorithmId = new AlgorithmId(GOST3411); final AlgorithmId signAlgorithmId = new AlgorithmId(GOST3410); SignerInfo sInfo = new SignerInfo(issuer, certificate.getSerialNumber(), digestAlgorithmId, signAlgorithmId, sign); ContentInfo cInfo = new ContentInfo(ContentInfo.DATA_OID, null); PKCS7 pkcs7 = new PKCS7( new AlgorithmId[]{digestAlgorithmId}, cInfo, new X509Certificate[]{certificate}, new SignerInfo[]{sInfo}); final ByteArrayOutputStream bOut = new DerOutputStream(); try { pkcs7.encodeSignedData(bOut); } catch (IOException e) { throw new RuntimeException(e); } return bOut.toByteArray(); } public static Signature fromPkcs7(final byte[] bytes) { final PKCS7 pkcs7; try { pkcs7 = new PKCS7(bytes); } catch (ParsingException e) { log.info("fail parse pkcs7: ", e); return new Signature(null, null, null, false); } final AlgorithmId digestAlgorithmId = new AlgorithmId(GOST3411); final AlgorithmId signAlgorithmId = new AlgorithmId(GOST3410); final AlgorithmId[] digestAlgorithmIds = pkcs7.getDigestAlgorithmIds(); if (digestAlgorithmIds == null || digestAlgorithmIds.length == 0) { log.info("no digestAlgorithm in pkcs7"); } else if (!digestAlgorithmIds[0].equals(digestAlgorithmId)) { log.info("no GOST3411 in pkcs7"); } else { final X509Certificate[] certificates = pkcs7.getCertificates(); if (certificates == null || certificates.length == 0) { log.info("no certificate in pkcs7"); } else { final X509Certificate certificate = certificates[0]; final SignerInfo[] signerInfos = pkcs7.getSignerInfos(); if (signerInfos == null || signerInfos.length == 0) { log.info("no signerInfos in pkcs7"); } else { final SignerInfo signerInfo = signerInfos[0]; if (!signerInfo.getIssuerName().equals(X500Name.asX500Name(certificate.getIssuerX500Principal()))) { log.info("invalid issuerX500Principal in pkcs7"); } else if (!signerInfo.getDigestAlgorithmId().equals(digestAlgorithmId)) { log.info("no GOST3411 in pkcs7"); } else if (!signerInfo.getDigestEncryptionAlgorithmId().equals(signAlgorithmId)) { log.info("no GOST3410 in pkcs7"); } else if (!signerInfo.getCertificateSerialNumber().equals(certificate.getSerialNumber())) { log.info("invalid certificate serial number in pkcs7"); } else { return new Signature(certificate, null, signerInfo.getEncryptedDigest(), true); } } } } return new Signature(null, null, null, false); } }