美文网首页
p7签名实现

p7签名实现

作者: 柳岸花开 | 来源:发表于2017-11-29 15:36 被阅读769次

    两种p7签名

    1、bc

    我认为你需要以下2castle罐产生PKCS7数字签名: bcprov-jdk15on-147.jar(对JDK 1.5-JDK 1.7) bcmail-jdk15on-147.jar(对JDK 1.5-JDK 1.7) 你可以从这里下载的castle罐子。 你需要设置你的密钥库与公共和私有密钥对。 你只需要私钥生成的数字签名和公钥来验证它。 这里是你如何PKCS7标志内容(异常处理不再赘述): import java.io.FileInputStream;
    import java.io.InputStream;
    import java.security.KeyStore;
    import java.security.PrivateKey;
    import java.security.Security;
    import java.security.cert.Certificate;
    import java.security.cert.X509Certificate;
    import java.util.ArrayList;
    import java.util.List;
    import org.bouncycastle.cert.jcajce.JcaCertStore;
    import org.bouncycastle.cms.CMSProcessableByteArray;
    import org.bouncycastle.cms.CMSSignedData;
    import org.bouncycastle.cms.CMSSignedDataGenerator;
    import org.bouncycastle.cms.CMSTypedData;
    import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import org.bouncycastle.operator.ContentSigner;
    import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
    import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
    import org.bouncycastle.util.Store;
    import org.bouncycastle.util.encoders.Base64;
    public final class PKCS7Signer {
    private static final String PATH_TO_KEYSTORE = "/path/to/keyStore";
    private static final String KEY_ALIAS_IN_KEYSTORE = "My_Private_Key";
    private static final String KEYSTORE_PASSWORD = "MyPassword";
    private static final String SIGNATUREALGO = "SHA1withRSA";
    public PKCS7Signer() {
    }
    KeyStore loadKeyStore() throws Exception {
    KeyStore keystore = KeyStore.getInstance("JKS");
    InputStream is = new FileInputStream(PATH_TO_KEYSTORE);
    keystore.load(is, KEYSTORE_PASSWORD.toCharArray());
    return keystore;
    }
    CMSSignedDataGenerator setUpProvider(final KeyStore keystore) throws Exception {
    Security.addProvider(new BouncyCastleProvider());
    Certificate[] certchain = (Certificate[]) keystore.getCertificateChain(KEY_ALIAS_IN_KEYSTORE);
    final List<Certificate> certlist = new ArrayList<Certificate>();
    for (int i = 0, length = certchain == null ? 0 : certchain.length; i < length; i++) {
    certlist.add(certchain[i]);
    }
    Store certstore = new JcaCertStore(certlist);
    Certificate cert = keystore.getCertificate(KEY_ALIAS_IN_KEYSTORE);
    ContentSigner signer = new JcaContentSignerBuilder(SIGNATUREALGO).setProvider("BC").
    build((PrivateKey) (keystore.getKey(KEY_ALIAS_IN_KEYSTORE, KEYSTORE_PASSWORD.toCharArray())));
    CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
    generator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").
    build()).build(signer, (X509Certificate) cert));
    generator.addCertificates(certstore);
    return generator;
    }
    byte[] signPkcs7(final byte[] content, final CMSSignedDataGenerator generator) throws Exception {
    CMSTypedData cmsdata = new CMSProcessableByteArray(content);
    CMSSignedData signeddata = generator.generate(cmsdata, true);
    return signeddata.getEncoded();
    }
    public static void main(String[] args) throws Exception {
    PKCS7Signer signer = new PKCS7Signer();
    KeyStore keyStore = signer.loadKeyStore();
    CMSSignedDataGenerator signatureGenerator = signer.setUpProvider(keyStore);
    String content = "some bytes to be signed";
    byte[] signedBytes = signer.signPkcs7(content.getBytes("UTF-8"), signatureGenerator);
    System.out.println("Signed Encoded Bytes: " + new String(Base64.encode(signedBytes)));
    }
    }

    PKCS#7被称为现在的CMS(密码消息语法),你将需要castlePKIX库来创建一个。它拥有充足的和一个完善的邮件列表。 我将不提供代码片段,它是对规则。试着自己先。

    2、java jce

    /**

    • PKCS7Tool.java pkcs7格式签名工具

    • @version 1.0
      */
      public class PKCS7Tool {

      /** 签名 /
      private static final int SIGNER = 1;
      /
      * 验证 /
      private static final int VERIFIER = 2;
      /
      * 用途 /
      private int mode = 0;
      /
      * 摘要算法 /
      private String digestAlgorithm = "SHA1";
      /
      * 签名算法 /
      private String signingAlgorithm = "SHA1withRSA";
      /
      * 签名证书链 /
      private X509Certificate[] certificates = null;
      /
      * 签名私钥 /
      private PrivateKey privateKey = null;
      /
      * 根证书 /
      private Certificate rootCertificate = null;
      /
      * JVM 提供商 */
      private static char jvm = 0;
      private static Class algorithmId = null;
      private static Class derValue = null;
      private static Class objectIdentifier = null;
      private static Class x500Name = null;
      private static boolean debug = false;

      /**

      • 私有构造方法
        */
        private PKCS7Tool(int mode) {
        this.mode = mode;
        }

      /**

      • 取得签名工具 加载证书库, 取得签名证书链和私钥
      • @param keyStorePath
      •        证书库路径
        
      • @param keyStorePassword
      •        证书库口令
        
      • @throws GeneralSecurityException
      • @throws IOException
        */
        public static PKCS7Tool getSigner(String keyStorePath,
        String keyStorePassword, String keyPassword)
        throws GeneralSecurityException, IOException {
        init();
        // 加载证书库
        KeyStore keyStore = null;
        if (keyStorePath.toLowerCase().endsWith(".pfx"))
        keyStore = KeyStore.getInstance("PKCS12");
        else
        keyStore = KeyStore.getInstance("JKS");
        FileInputStream fis = null;
        try {
        fis = new FileInputStream(keyStorePath);
        keyStore.load(fis, keyStorePassword.toCharArray());
        } finally {
        if (fis != null)
        fis.close();
        }
        // 在证书库中找到签名私钥
        Enumeration aliases = keyStore.aliases();
        String keyAlias = null;
        if (aliases != null) {
        while (aliases.hasMoreElements()) {
        keyAlias = (String) aliases.nextElement();
        Certificate[] certs = keyStore.getCertificateChain(keyAlias);
        if (certs == null || certs.length == 0)
        continue;
        X509Certificate cert = (X509Certificate) certs[0];
        if (matchUsage(cert.getKeyUsage(), 1)) {
        try {
        cert.checkValidity();
        } catch (CertificateException e) {
        continue;
        }
        break;
        }
        }
        }
        // 没有找到可用签名私钥
        if (keyAlias == null)
        throw new GeneralSecurityException(
        "None certificate for sign in this keystore");
        if (debug)
        System.out.println(keyAlias);
        X509Certificate[] certificates = null;
        if (keyStore.isKeyEntry(keyAlias)) {
        // 检查证书链
        Certificate[] certs = keyStore.getCertificateChain(keyAlias);
        for (int i = 0; i < certs.length; i++) {
        if (!(certs[i] instanceof X509Certificate))
        throw new GeneralSecurityException("Certificate[" + i
        + "] in chain '" + keyAlias
        + "' is not a X509Certificate.");
        }
        // 转换证书链
        certificates = new X509Certificate[certs.length];
        for (int i = 0; i < certs.length; i++)
        certificates[i] = (X509Certificate) certs[i];
        } else if (keyStore.isCertificateEntry(keyAlias)) {
        // 只有单张证书
        Certificate cert = keyStore.getCertificate(keyAlias);
        if (cert instanceof X509Certificate) {
        certificates = new X509Certificate[] { (X509Certificate) cert };
        }
        } else {
        throw new GeneralSecurityException(keyAlias
        + " is unknown to this keystore");
        }
        PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias,
        keyPassword.toCharArray());
        // 没有私钥抛异常
        if (privateKey == null) {
        throw new GeneralSecurityException(keyAlias
        + " could not be accessed");
        }
        PKCS7Tool tool = new PKCS7Tool(SIGNER);
        tool.certificates = certificates;
        tool.privateKey = privateKey;
        return tool;
        }

      /**

      • 取得验签名工具 加载信任根证书
      • @param rootCertificatePath
      •        根证书路径
        
      • @throws GeneralSecurityException
      • @throws IOException
        */
        public static PKCS7Tool getVerifier(String rootCertificatePath)
        throws GeneralSecurityException, IOException {
        init();
        // 加载根证书
        FileInputStream fis = null;
        Certificate rootCertificate = null;
        try {
        fis = new FileInputStream(rootCertificatePath);
        CertificateFactory certificatefactory = CertificateFactory
        .getInstance("X.509");
        try {
        rootCertificate = certificatefactory.generateCertificate(fis);
        } catch (Exception exception) {
        InputStream is = new ByteArrayInputStream(
        new BASE64Decoder().decodeBuffer(fis));
        rootCertificate = certificatefactory.generateCertificate(is);
        }
        } finally {
        if (fis != null)
        fis.close();
        }
        PKCS7Tool tool = new PKCS7Tool(VERIFIER);
        tool.rootCertificate = rootCertificate;
        return tool;
        }

      /**

      • 签名
      • @param data
      •        数据
        
      • @return signature 签名结果
      • @throws GeneralSecurityException
      • @throws IOException
      • @throws IllegalArgumentException
        */
        public String sign(byte[] data) throws Exception {
        if (mode != SIGNER)
        throw new IllegalStateException(
        "call a PKCS7Tool instance not for signature.");
        Signature signer = Signature.getInstance(signingAlgorithm);
        signer.initSign(privateKey);
        signer.update(data, 0, data.length);
        byte[] signedAttributes = signer.sign();
        ContentInfo contentInfo = null;
        Field data_oidField = ContentInfo.class.getField("DATA_OID");
        Object data_oid = data_oidField.get(null);
        Constructor contentInfoConstructor = ContentInfo.class
        .getConstructor(new Class[] { data_oid.getClass(), derValue });
        contentInfo = (ContentInfo) contentInfoConstructor
        .newInstance(new Object[] { data_oid, null });
        // 根证书
        X509Certificate x509 = certificates[0];
        java.math.BigInteger serial = x509.getSerialNumber();
        // X500Name
        Constructor x500NameConstructor = x500Name
        .getConstructor(new Class[] { String.class });
        Object x500NameObject = x500NameConstructor
        .newInstance(new Object[] { x509.getIssuerDN().getName() });
        // AlgorithmId
        Method algorithmIdGet = algorithmId.getMethod("get",
        new Class[] { String.class });
        Object digestAlgorithmId = algorithmIdGet.invoke(null,
        new Object[] { digestAlgorithm });
        Field algorithmIdfield = algorithmId.getField("RSAEncryption_oid");
        Object rsaOid = algorithmIdfield.get(null);
        Constructor algorithmConstructor = algorithmId
        .getConstructor(new Class[] { objectIdentifier });
        Object algorithmRsaOid = algorithmConstructor
        .newInstance(new Object[] { rsaOid });
        // SignerInfo
        Constructor signerInfoConstructor = SignerInfo.class
        .getConstructor(new Class[] { x500Name, BigInteger.class,
        algorithmId, PKCS9Attributes.class, algorithmId,
        byte[].class, PKCS9Attributes.class });
        // 签名信息
        SignerInfo si = (SignerInfo) signerInfoConstructor
        .newInstance(new Object[] { x500NameObject,// X500Name,
        // issuerName,
        serial, // x509.getSerialNumber(), BigInteger serial,
        digestAlgorithmId, // AlgorithmId, digestAlgorithmId,
        null, // PKCS9Attributes, authenticatedAttributes,
        algorithmRsaOid, // AlgorithmId,
        // digestEncryptionAlgorithmId,
        signedAttributes, // byte[] encryptedDigest,
        null // PKCS9Attributes unauthenticatedAttributes)
        });
        SignerInfo[] signerInfos = { si };
        // 构造PKCS7数据
        Object digestAlgorithmIds = Array.newInstance(algorithmId, 1);
        Array.set(digestAlgorithmIds, 0, digestAlgorithmId);
        // PKCS7
        Constructor pkcs7Constructor = PKCS7.class.getConstructor(new Class[] {
        digestAlgorithmIds.getClass(), ContentInfo.class,
        X509Certificate[].class, signerInfos.getClass() });
        PKCS7 p7 = (PKCS7) pkcs7Constructor.newInstance(new Object[] {
        digestAlgorithmIds, contentInfo, certificates, signerInfos });
        // PKCS7 p7 = new PKCS7(digestAlgorithmIds, contentInfo, certificates,
        // signerInfos);
        // public PKCS7(com.ibm.security.x509.AlgorithmId[] arg0,
        // sun.security.pkcs.ContentInfo arg1,
        // java.security.cert.X509Certificate[] arg2,
        // sun.security.pkcs.SignerInfo[] arg3);
        // public PKCS7(sun.security.x509.AlgorithmId[] arg0,
        // sun.security.pkcs.ContentInfo arg1,
        // java.security.cert.X509Certificate[] arg2,
        // sun.security.pkcs.SignerInfo[] arg3);
        ByteArrayOutputStream baout = new ByteArrayOutputStream();
        p7.encodeSignedData(baout);
        // Base64编码
        return (new BASE64Encoder()).encode(baout.toByteArray());
        }

      /**

      • 验证签名(无CRL)
      • @param signature
      •        签名签名结果
        
      • @param data
      •        被签名数据
        
      • @param dn
      •        签名证书dn, 如果为空则不做匹配验证
        
      • @throws IOException
      • @throws NoSuchAlgorithmException
      • @throws SignatureException
      • @throws InvalidKeyException
      • @throws CertificateException
      • @throws NoSuchProviderException
        */
        public void verify(String signature, byte[] data, String dn)
        throws IOException, NoSuchAlgorithmException, SignatureException,
        InvalidKeyException, CertificateException, NoSuchProviderException {
        if (mode != VERIFIER)
        throw new IllegalStateException("call a PKCS7Tool instance not for verify.");
        byte[] sign = new BASE64Decoder().decodeBuffer(signature);
        PKCS7 p7 = new PKCS7(sign);
        X509Certificate[] certs = p7.getCertificates();
        if (debug)
        for (int i = 0; i < certs.length; i++) {
        X509Certificate cert = certs[i];
        System.out.println("SIGNER " + i + "=\n" + cert);
        System.out.println("SIGNER " + i + "=\n"
        + new BASE64Encoder().encode(cert.getEncoded()));
        }
        // 验证签名本身、证书用法、证书扩展
        SignerInfo[] sis = p7.verify(data);
        // check the results of the verification
        if (sis == null)
        throw new SignatureException(
        "Signature failed verification, data has been tampered");
        for (int i = 0; i < sis.length; i++) {
        SignerInfo si = sis[i];
        X509Certificate cert = si.getCertificate(p7);
        // 证书是否过期验证,如果不用系统日期可用cert.checkValidity(date);
        cert.checkValidity();
        if (!cert.equals(rootCertificate)) {
        // 验证证书签名
        cert.verify(rootCertificate.getPublicKey());
        }
        // 验证dn
        if (i == 0 && dn != null) {
        X500Principal name = cert.getSubjectX500Principal();
        if (!dn.equals(name.getName(X500Principal.RFC1779))
        && !new X500Principal(dn).equals(name))
        throw new SignatureException("Signer dn '"
        + name.getName(X500Principal.RFC1779)
        + "' does not matchs '" + dn + "'");
        }
        }
        }

      /**

      • 匹配私钥用法
      • @param keyUsage
      • @param usage
      • @return
        */
        private static boolean matchUsage(boolean[] keyUsage, int usage) {
        if (usage == 0 || keyUsage == null)
        return true;
        for (int i = 0; i < Math.min(keyUsage.length, 32); i++) {
        if ((usage & (1 << i)) != 0 && !keyUsage[i])
        return false;
        }
        return true;
        }

      private static void init() {
      if (jvm != 0)
      return;
      String vendor = System.getProperty("java.vm.vendor");
      if (vendor == null)
      vendor = "";
      String vendorUC = vendor.toUpperCase();
      try {
      // if (vendorUC.indexOf("SUN") >= 0) {
      jvm = 'S';
      algorithmId = Class.forName("sun.security.x509.AlgorithmId");
      derValue = Class.forName("sun.security.util.DerValue");
      objectIdentifier = Class.forName("sun.security.util.ObjectIdentifier");
      x500Name = Class.forName("sun.security.x509.X500Name");
      // } else if (vendorUC.indexOf("IBM") >= 0) {
      // jvm = 'I';
      // algorithmId = Class
      // .forName("com.ibm.security.x509.AlgorithmId");
      // derValue = Class.forName("com.ibm.security.util.DerValue");
      // objectIdentifier = Class
      // .forName("com.ibm.security.util.ObjectIdentifier");
      // x500Name = Class.forName("com.ibm.security.x509.X500Name");
      // } else {
      // System.out.println("Not support JRE: " + vendor);
      //// System.exit(-1);
      // }
      } catch (ClassNotFoundException e) {
      e.printStackTrace();
      System.exit(-1);
      }
      }

      /**

      • @return 返回 digestAlgorithm。
        */
        public final String getDigestAlgorithm() {
        return digestAlgorithm;
        }

      /**

      • @param digestAlgorithm
      •        要设置的 digestAlgorithm。
        

      */
      public final void setDigestAlgorithm(String digestAlgorithm) {
      this.digestAlgorithm = digestAlgorithm;
      }

      /**

      • @return 返回 signingAlgorithm。
        */
        public final String getSigningAlgorithm() {
        return signingAlgorithm;
        }

      /**

      • @param signingAlgorithm
      •        要设置的 signingAlgorithm。
        

      */
      public final void setSigningAlgorithm(String signingAlgorithm) {
      this.signingAlgorithm = signingAlgorithm;
      }

      public static void setDebug(boolean debug) {
      PKCS7Tool.debug = debug;
      }
      }

       @Test
      

      public void testSign() {
      String keyStorePath = getClass().getClassLoader().getResource("").getPath() + "测试证书1.pfx";
      keyStorePath = keyStorePath.replace("%20%e9%a1%b9%e7%9b%ae", " 项目");
      System.out.println(keyStorePath);
      try {
      String test = "hello world";
      String ret = PKCS7Tool.getSigner(keyStorePath, "12345678", "12345678").sign(test.getBytes("utf-8"));
      System.out.println(ret);
      } catch (GeneralSecurityException | IOException e) {
      e.printStackTrace();
      System.out.println("操作失败");
      }
      }

    相关文章

      网友评论

          本文标题:p7签名实现

          本文链接:https://www.haomeiwen.com/subject/llhubxtx.html