Java开发网 |
注册 |
登录 |
帮助 |
搜索 |
排行榜 |
发帖统计
|
您没有登录 |
» Java开发网 » Java Security
» 精华区
打印话题 寄给朋友 订阅主题 |
作者 | 关于ibm-jdk下的证书加密解密问题 |
zijingshanke
发贴: 2 积分: 1 |
于 2009-12-03 13:05
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; 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.security.pkcs.ContentInfo; import sun.security.pkcs.PKCS7; import sun.security.pkcs.SignerInfo; import sun.security.x509.AlgorithmId; import sun.security.x509.X500Name; import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; /** * PKCS7Tool.java pkcs7格式签名工具 */ 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; /** * 私有构造方法 */ private _PKCS7Tool(int mode) { this.mode = mode; } /** * 取得签名工具 加载证书库, 取得签名证书链和私钥 * @param keyStorePath * 证书库路径 * @param keyStorePassword * 证书库口令 */ public static _PKCS7Tool getSigner(String keyStorePath, String keyStorePassword, String keyPassword) throws GeneralSecurityException, IOException { // 加载证书库 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"); 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 data * 数据 * @return signature 签名结果 * @throws GeneralSecurityException * @throws IOException * @throws IllegalArgumentException */ public String sign(byte[] data) throws GeneralSecurityException, IOException { 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; contentInfo = new ContentInfo(ContentInfo.DATA_OID, null); // 根证书 X509Certificate x509 = certificates[certificates.length - 1]; // 如果jdk1.5则用以下语句 java.math.BigInteger serial = x509.getSerialNumber(); // 签名信息 SignerInfo si = new SignerInfo(new X500Name(x509.getIssuerDN() .getName()), // X500Name, issuerName, serial, // x509.getSerialNumber(), BigInteger serial, AlgorithmId.get(digestAlgorithm), // AlgorithmId, // digestAlgorithmId, null, // PKCS9Attributes, authenticatedAttributes, new AlgorithmId(AlgorithmId.RSAEncryption_oid), // AlgorithmId, // digestEncryptionAlgorithmId, signedAttributes, // byte[] encryptedDigest, null); // PKCS9Attributes unauthenticatedAttributes) { SignerInfo[] signerInfos = { si }; // 构造PKCS7数据 AlgorithmId[] digestAlgorithmIds = { AlgorithmId.get(digestAlgorithm) }; PKCS7 p7 = new PKCS7(digestAlgorithmIds, contentInfo, certificates, signerInfos); ByteArrayOutputStream baout = new ByteArrayOutputStream(); p7.encodeSignedData(baout); // Base64编码 return Base64.encode(baout.toByteArray()); } /** * 匹配私钥用法 * * @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; } public static void main(String[] args) { String keyStorePath = "D:\\淘宝网.pfx"; String keyStorePassword = "11111111"; String keyPassword = "11111111"; _PKCS7Tool tool = null; try { tool = getSigner(keyStorePath, keyStorePassword, keyPassword); } catch (GeneralSecurityException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } String plaintext = "123456"; try { System.out.println(tool.sign(plaintext.getBytes())); } catch (Exception e) { e.printStackTrace(); } } 得到的签名密文为, 现在根据项目的需要,使用Ibm-jdk,并且使用Ibm提供的安全开发包ibmjceprovider.jar、ibmjgssprovider.jar、ibmjsseprovider2.jar、ibmpkcs.jar等,不用sun的jsse.jar。查询了相关资料,将签名方法进行修改,加载签名工具即取得证书和私钥的方法基本不变。 Java code import com.ibm.misc.BASE64Decoder; import com.ibm.security.pkcs7.Data; import com.ibm.security.pkcsutil.PKCSAttributes; import com.ibm.security.pkcs7.ContentInfo; import com.ibm.security.pkcs7.SignedData; /** * 签名 * * @param data * 数据 * @return signature 签名结果 * @throws GeneralSecurityException * @throws IOException * @throws IllegalArgumentException */ public String sign(byte[] data) throws GeneralSecurityException, IOException { byte[] byteArray = null; // Data ibmData = new Data(); ibmData.setData(data); ContentInfo contentInfo = new ContentInfo(ibmData); // Certificate[] signingCert = new Certificate[1]; signingCert[0] = certificates[certificates.length - 1]; //-------- CRL[] crls = null; PKCSAttributes signedAttributes = null; PKCSAttributes unsignedAttributes = null; PrivateKey[] privateKeys = new PrivateKey[1]; privateKeys[0] = privateKey; boolean signatureOnly = false; String AlgName = signingAlgorithm;// // 签名信息 SignedData signData = new SignedData(signingCert, crls, contentInfo, AlgName, privateKeys, signedAttributes, unsignedAttributes, signatureOnly); ContentInfo contentInfo2 = new ContentInfo(signData); byte[] encodedSignedData = contentInfo2.encode(); return Base64.encode(encodedSignedData); } 这时出现一个奇怪的现象,每次执行签名方法得到的签名密文都不一样,请大家指教。
zijingshanke edited on 2009-12-03 13:09
优化jQuery开发的网页代码性能 |
作者 | Re:关于ibm-jdk下的证书加密解密问题 [Re:zijingshanke] |
cckoan
Smoking CJSDN高级会员 发贴: 253 积分: 130 |
于 2009-12-04 14:32
Bouncy Castle Provider 对抗暴力拆迁,光有力量和勇气是不够滴,关键你的胯下还得有只大鸟--阿凡达观后 太多只会SSH的白痴了.....国内培养出那么多代码民工何用?! |
已读帖子 新的帖子 被删除的帖子 |
Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1 客服电话 18559299278 客服信箱 714923@qq.com 客服QQ 714923 |