p7签名实现

两种p7签名

1、java jce

package encrypt;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import javax.security.auth.x500.X500Principal;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.PKCS9Attributes;
import sun.security.pkcs.SignerInfo;


/**
 * PKCS7Tool.java pkcs7格式签名工具
 * 
 * @version 1.0
 * @author SUNY Written Date: 2008-9-23 Modified Date 2010-6-12 update for IBM
 *         JDK
 */
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[certificates.length - 1];
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;
}
}


2、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)));
 }
}

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

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值