p7签名实现

两种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 certlist = new ArrayList();
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签名实现)